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

diff -urN linux-2.5.70-bk16/Documentation/Changes linux-2.5.70-bk17/Documentation/Changes
--- linux-2.5.70-bk16/Documentation/Changes	2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk17/Documentation/Changes	2003-06-12 04:49:55.000000000 -0700
@@ -61,7 +61,7 @@
 o  PPP                    2.4.0                   # pppd --version
 o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
 o  procps                 2.0.9                   # ps --version
-o  oprofile               0.5                     # oprofiled --version
+o  oprofile               0.5.3                   # oprofiled --version
 o  nfs-utils              1.0.3                   # showmount --version
 
 Kernel compilation
@@ -367,7 +367,7 @@
 
 OProfile
 --------
-o  <http://oprofile.sf.net/download.php3>
+o  <http://oprofile.sf.net/download/>
  
 Suggestions and corrections
 ===========================
diff -urN linux-2.5.70-bk16/MAINTAINERS linux-2.5.70-bk17/MAINTAINERS
--- linux-2.5.70-bk16/MAINTAINERS	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/MAINTAINERS	2003-06-12 04:49:55.000000000 -0700
@@ -207,6 +207,7 @@
 AGPGART DRIVER
 P:	Dave Jones
 M:	davej@codemonkey.org.uk
+W:	http://www.codemonkey.org.uk/agp/
 S:	Maintained
 
 AHA152X SCSI DRIVER
@@ -771,24 +772,24 @@
 L:	linux-hippi@sunsite.dk
 S:	Maintained
 
-COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
+HEWLETT-PACKARD FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
 P:	Chase Maupin
 M:	Chase Maupin (support@compaq.com)
-L:	compaqandlinux@cpqlin.van-dijk.net
-S:	Supported
-
-COMPAQ SMART2 RAID DRIVER
+ L:	compaqandlinux@cpqlin.van-dijk.net
+ S:	Supported
+ 
+HEWLETT-PACKARD SMART2 RAID DRIVER
 P:	Francis Wiran
 M:	Francis Wiran <support@compaq.com>
-L:	compaqandlinux@cpqlin.van-dijk.net
-S:	Supported	
-
-COMPAQ SMART CISS RAID DRIVER 
+ L:	compaqandlinux@cpqlin.van-dijk.net
+ S:	Supported	
+ 
+HEWLETT-PACKARD SMART CISS RAID DRIVER 
 P:	Mike Miller, Michael Ni
 M:	Mike Miller, Michael Ni <support@compaq.com>
-L:	compaqandlinux@cpqlin.van-dijk.net
-S:	Supported 
-  
+ L:	compaqandlinux@cpqlin.van-dijk.net
+ S:	Supported 
+ 
 HP100:	Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
 P:	Jaroslav Kysela
 M:	perex@suse.cz
diff -urN linux-2.5.70-bk16/Makefile linux-2.5.70-bk17/Makefile
--- linux-2.5.70-bk16/Makefile	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/Makefile	2003-06-12 04:49:55.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 70
-EXTRAVERSION = -bk16
+EXTRAVERSION = -bk17
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.70-bk16/arch/alpha/Kconfig linux-2.5.70-bk17/arch/alpha/Kconfig
--- linux-2.5.70-bk16/arch/alpha/Kconfig	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/alpha/Kconfig	2003-06-12 04:49:55.000000000 -0700
@@ -297,7 +297,7 @@
 
 config PCI_DOMAINS
 	bool
-	default PCI
+	default y
 
 config ALPHA_CORE_AGP
 	bool
diff -urN linux-2.5.70-bk16/arch/alpha/kernel/srmcons.c linux-2.5.70-bk17/arch/alpha/kernel/srmcons.c
--- linux-2.5.70-bk16/arch/alpha/kernel/srmcons.c	2003-05-26 18:00:57.000000000 -0700
+++ linux-2.5.70-bk17/arch/alpha/kernel/srmcons.c	2003-06-12 04:49:55.000000000 -0700
@@ -30,11 +30,6 @@
  */
 #define MAX_SRM_CONSOLE_DEVICES 1	/* only support 1 console device */
 
-static int srmcons_refcount;
-static struct tty_struct *srmcons_table[MAX_SRM_CONSOLE_DEVICES];
-static struct termios *srmcons_termios[MAX_SRM_CONSOLE_DEVICES];
-static struct termios *srmcons_termios_locked[MAX_SRM_CONSOLE_DEVICES];
-
 struct srmcons_private {
 	struct tty_struct *tty;
 	struct timer_list timer;
@@ -269,21 +264,9 @@
 }
 
 
-static struct tty_driver srmcons_driver = {
-	.driver_name	= "srm",
-	.name		= "srm",
-	.magic		= TTY_DRIVER_MAGIC,
-	.major		= 0, 	/* dynamic */
-	.minor_start	= 0,
-	.num		= MAX_SRM_CONSOLE_DEVICES,
-	.type		= TTY_DRIVER_TYPE_SYSTEM,
-	.subtype	= SYSTEM_TYPE_SYSCONS,
-
-	.table		= srmcons_table,
-	.termios	= srmcons_termios,
-	.termios_locked	= srmcons_termios_locked,
-	.refcount	= &srmcons_refcount,
+static struct tty_driver *srmcons_driver;
 
+static struct tty_operations srmcons_ops = {
 	.open		= srmcons_open,
 	.close		= srmcons_close,
 	.write		= srmcons_write,
@@ -295,8 +278,25 @@
 srmcons_init(void)
 {
 	if (srm_is_registered_console) {
-		srmcons_driver.init_termios = tty_std_termios;
-		return tty_register_driver(&srmcons_driver);
+		struct tty_driver *driver;
+		int err;
+
+		driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES);
+		if (!driver)
+			return -ENOMEM;
+		driver->driver_name = "srm";
+		driver->name = "srm";
+		driver->major = 0; 	/* dynamic */
+		driver->minor_start = 0;
+		driver->type = TTY_DRIVER_TYPE_SYSTEM;
+		driver->subtype = SYSTEM_TYPE_SYSCONS;
+		driver->init_termios = tty_std_termios;
+		err = tty_register_driver(driver);
+		if (err) {
+			put_tty_driver(driver);
+			return err;
+		}
+		srmcons_driver = driver;
 	}
 
 	return -ENODEV;
@@ -322,7 +322,7 @@
 srm_console_device(struct console *co, int *index)
 {
 	*index = co->index;
-	return &srmcons_driver;
+	return srmcons_driver;
 }
 
 static int __init
diff -urN linux-2.5.70-bk16/arch/arm/Kconfig linux-2.5.70-bk17/arch/arm/Kconfig
--- linux-2.5.70-bk16/arch/arm/Kconfig	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/arch/arm/Kconfig	2003-06-12 04:49:55.000000000 -0700
@@ -377,6 +377,15 @@
 
 	  If you don't know what this all is, saying Y is a safe choice.
 
+config CPU_BIG_ENDIAN
+	bool "Build big-endian kernel"
+	depends on ARCH_SUPPORTS_BIG_ENDIAN
+	help
+	  Say Y if you plan on running a kernel in big-endian mode.
+	  Note that your board must be properly built and your board
+	  port must properly enable and big-endian related features
+	  of your chipset/board/processor.
+
 config CPU_ICACHE_DISABLE
 	bool "Disable I-Cache"
 	depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020
diff -urN linux-2.5.70-bk16/arch/arm/Makefile linux-2.5.70-bk17/arch/arm/Makefile
--- linux-2.5.70-bk16/arch/arm/Makefile	2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk17/arch/arm/Makefile	2003-06-12 04:49:55.000000000 -0700
@@ -24,6 +24,12 @@
 CFLAGS		+=-g
 endif
 
+ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+CFLAGS		+= -mbig-endian
+AS		+= -EB
+LD		+= -EB
+endif
+
 # Select CPU dependent flags.  Note that order of declaration is important;
 # the options further down the list override previous items.
 #
@@ -34,10 +40,7 @@
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
 # testing for a specific architecture or later rather impossible.
-#
-# Note - GCC does accept -march=armv5te, but someone messed up the assembler or the
-# gcc specs file - this needs fixing properly - ie in gcc and/or binutils.
-arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 -march=armv5t
+arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 -march=armv5te
 arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
 arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
 
@@ -50,13 +53,13 @@
 tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
-tune-$(CONFIG_CPU_XSCALE)	:=-mtune=strongarm -Wa,-mxscale #-mtune=xscale
+tune-$(CONFIG_CPU_XSCALE)	:=-mtune=xscale
 
 # Force -mno-fpu to be passed to the assembler.  Some versions of gcc don't
 # do this with -msoft-float
 CFLAGS_BOOT	:=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm
 CFLAGS		+=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm
-AFLAGS		+=$(apcs-y) $(arch-y) $(tune-y) -mno-fpu -msoft-float -Wa,-mno-fpu
+AFLAGS		+=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu
 
 #Default value
 DATAADDR	:= .
@@ -76,7 +79,11 @@
 ifeq ($(CONFIG_CPU_32),y)
 PROCESSOR	:= armv
 head-y		:= arch/arm/kernel/head.o arch/arm/kernel/init_task.o
-LDFLAGS_BLOB	+= --oformat elf32-littlearm
+  ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+    LDFLAGS_BLOB	+= --oformat elf32-bigarm
+  else
+    LDFLAGS_BLOB	+= --oformat elf32-littlearm
+  endif
 textaddr-y	:= 0xC0008000
 endif
 
diff -urN linux-2.5.70-bk16/arch/arm/lib/div64.S linux-2.5.70-bk17/arch/arm/lib/div64.S
--- linux-2.5.70-bk16/arch/arm/lib/div64.S	2003-05-26 18:01:00.000000000 -0700
+++ linux-2.5.70-bk17/arch/arm/lib/div64.S	2003-06-12 04:49:55.000000000 -0700
@@ -1,27 +1,42 @@
 #include <linux/linkage.h>
 
+#ifndef __ARMEB__
 ql	.req	r0			@ quotient low
 qh	.req	r1			@ quotient high
-dl	.req	r3			@ divisor low
-dh	.req	r2			@ divisor high
+onl	.req	r0			@ original dividend low
+onh	.req	r1			@ original dividend high
 nl	.req	r4			@ dividend low
 nh	.req	r5			@ dividend high
+res	.req	r4			@ result
+#else
+ql	.req	r1
+qh	.req	r0
+onl	.req	r1
+onh	.req	r0
+nl	.req	r5
+nh	.req	r4
+res	.req	r5
+#endif
+
+dl	.req	r3			@ divisor low
+dh	.req	r2			@ divsor high
+
 
 ENTRY(do_div64)
 	stmfd	sp!, {r4, r5, lr}
-	mov	nl, r0
-	movs	nh, r1			@ if high bits are zero
+	mov	nl, onl
+	movs	nh, onh			@ if high bits are zero
 	movne	lr, #33
 	moveq	lr, #1			@ only divide low bits
-	moveq	nh, r0
+	moveq	nh, onl
 
 1:	cmp	nh, dh
 	bls	2f
 	add	lr, lr, #1
-	movs	dh, dh, lsl #1		@ left justify divisor
+	movs	dh, dh, lsl #1		@ left justify disor
 	bpl	1b
 
-2:	movs	nh, r1
+2:	movs	nh, onh
 	moveq	dl, dh
 	moveq	dh, #0
 	movne	dl, #0
@@ -38,5 +53,5 @@
 	subs	lr, lr, #1
 	bne	3b
 
-	mov	r2, nl
+	mov	r2, res
 	ldmfd	sp!, {r4, r5, pc}
diff -urN linux-2.5.70-bk16/arch/arm/mach-sa1100/irq.c linux-2.5.70-bk17/arch/arm/mach-sa1100/irq.c
--- linux-2.5.70-bk16/arch/arm/mach-sa1100/irq.c	2003-05-26 18:00:59.000000000 -0700
+++ linux-2.5.70-bk17/arch/arm/mach-sa1100/irq.c	2003-06-12 04:49:55.000000000 -0700
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/ptrace.h>
-#include <linux/device.h>
+#include <linux/sysdev.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -211,94 +211,73 @@
 	.end	= 0x9005ffff,
 };
 
-struct sa1100irq_state {
+static struct {
 	unsigned int	saved;
 	unsigned int	icmr;
 	unsigned int	iclr;
 	unsigned int	iccr;
-};
+} sa1100irq_state;
 
 static int sa1100irq_suspend(struct device *dev, u32 state, u32 level)
 {
-	struct sa1100irq_state *st;
+	struct sa1100irq_state *st = &sa1100irq_state;
 
-	if (!dev->saved_state && level == SUSPEND_NOTIFY)
-		dev->saved_state = kmalloc(sizeof(struct sa1100irq_state),
-					   GFP_KERNEL);
-	if (!dev->saved_state)
-		return -ENOMEM;
-
-	if (level == SUSPEND_POWER_DOWN) {
-		st = (struct sa1100irq_state *)dev->saved_state;
-
-		st->saved = 1;
-		st->icmr = ICMR;
-		st->iclr = ICLR;
-		st->iccr = ICCR;
+	st->saved = 1;
+	st->icmr = ICMR;
+	st->iclr = ICLR;
+	st->iccr = ICCR;
 
-		/*
-		 * Disable all GPIO-based interrupts.
-		 */
-		ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
-			  IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
-			  IC_GPIO1|IC_GPIO0);
+	/*
+	 * Disable all GPIO-based interrupts.
+	 */
+	ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
+		  IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
+		  IC_GPIO1|IC_GPIO0);
 
-		/*
-		 * Set the appropriate edges for wakeup.
-		 */
-		GRER = PWER & GPIO_IRQ_rising_edge;
-		GFER = PWER & GPIO_IRQ_falling_edge;
+	/*
+	 * Set the appropriate edges for wakeup.
+	 */
+	GRER = PWER & GPIO_IRQ_rising_edge;
+	GFER = PWER & GPIO_IRQ_falling_edge;
+	
+	/*
+	 * Clear any pending GPIO interrupts.
+	 */
+	GEDR = GEDR;
 
-		/*
-		 * Clear any pending GPIO interrupts.
-		 */
-		GEDR = GEDR;
-	}
 	return 0;
 }
 
-static int sa1100irq_resume(struct device *dev, u32 level)
+static int sa1100irq_resume(struct sys_device *dev)
 {
-	struct sa1100irq_state *st;
-
-	if (level == RESUME_POWER_ON) {
-		st = (struct sa1100irq_state *)dev->saved_state;
-		dev->saved_state = NULL;
-
-		if (st->saved) {
-			ICCR = st->iccr;
-			ICLR = st->iclr;
+	struct sa1100irq_state *st = &sa1100irq_state;
 
-			GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-			GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+	if (st->saved) {
+		ICCR = st->iccr;
+		ICLR = st->iclr;
 
-			ICMR = st->icmr;
-		}
+		GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+		GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
 
-		kfree(st);
+		ICMR = st->icmr;
 	}
 	return 0;
 }
 
-static struct device_driver sa1100irq_driver = {
-	.name		= "sa11x0-irq",
-	.bus		= &system_bus_type,
+static struct sysdev_class sa1100irq_sysclass = {
+	set_kset_name("sa11x0-irq"),
 	.suspend	= sa1100irq_suspend,
 	.resume		= sa1100irq_resume,
 };
 
 static struct sys_device sa1100irq_device = {
-	.name		= "irq",
 	.id		= 0,
-	.dev = {
-		.name	= "Intel SA11x0 [Interrupt Controller]",
-		.driver	= &sa1100irq_driver,
-	},
+	.cls		= &sa1100irq_sysclass,
 };
 
 static int __init sa1100irq_init_devicefs(void)
 {
-	driver_register(&sa1100irq_driver);
+	sysdev_class_register(&sa1100irq_sysclass);
 	return sys_device_register(&sa1100irq_device);
 }
 
diff -urN linux-2.5.70-bk16/arch/cris/drivers/serial.c linux-2.5.70-bk17/arch/cris/drivers/serial.c
--- linux-2.5.70-bk16/arch/cris/drivers/serial.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/cris/drivers/serial.c	2003-06-12 04:49:55.000000000 -0700
@@ -335,8 +335,7 @@
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
-struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 
 /* serial subtype definitions */
 #ifndef SERIAL_TYPE_NORMAL
@@ -488,10 +487,6 @@
 
 
 #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
-  
-static struct tty_struct *serial_table[NR_PORTS]; 
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
 
 #ifdef CONFIG_ETRAX_SERIAL_PROC_ENTRY
 #define PROCSTAT(x) x
@@ -3011,12 +3006,6 @@
 	}
 	info->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -3324,11 +3313,6 @@
 		return retval;
 	}
 
-	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		change_speed(info);
-	}
-
 #ifdef SERIAL_DEBUG_OPEN
 	printk("rs_open ttyS%d successful...\n", info->line);
 #endif
@@ -3434,12 +3418,37 @@
 }
 
 /* rs_init inits the driver at boot (using the module_init chain) */
+  
+static struct tty_operations rs_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.break_ctl = rs_break,
+	.send_xchar = rs_send_xchar,
+	.wait_until_sent = rs_wait_until_sent,
+	.read_proc = rs_read_proc,
+};
 
 static int __init
 rs_init(void)
 {
 	int i;
 	struct e100_serial *info;
+	struct tty_driver *driver = alloc_tty_driver(NR_PORTS);
+
+	if (!driver)
+		return -ENOMEM;
 
 	show_serial_version();
         
@@ -3455,52 +3464,20 @@
 
 	/* Initialize the tty_driver structure */
   
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-#if (LINUX_VERSION_CODE > 0x20100)
-	serial_driver.driver_name = "serial";
-#endif
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NR_PORTS;       /* etrax100 has 4 serial ports */
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
+	driver->driver_name = "serial";
+	driver->name = "ttyS";
+	driver->major = TTY_MAJOR;
+	driver->minor_start = 64;
+	driver->type = TTY_DRIVER_TYPE_SERIAL;
+	driver->subtype = SERIAL_TYPE_NORMAL;
+	driver->init_termios = tty_std_termios;
+	driver->init_termios.c_cflag =
 		B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
-	serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-  
-	serial_driver.open = rs_open;
-	serial_driver.close = rs_close;
-	serial_driver.write = rs_write;
-	/* should we have an rs_put_char as well here ? */
-	serial_driver.flush_chars = rs_flush_chars;
-	serial_driver.write_room = rs_write_room;
-	serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	serial_driver.flush_buffer = rs_flush_buffer;
-	serial_driver.ioctl = rs_ioctl;
-	serial_driver.throttle = rs_throttle;
-	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.set_termios = rs_set_termios;
-	serial_driver.stop = rs_stop;
-	serial_driver.start = rs_start;
-	serial_driver.hangup = rs_hangup;
-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
-	serial_driver.break_ctl = rs_break;
-#endif
-#if (LINUX_VERSION_CODE >= 131343)
-	serial_driver.send_xchar = rs_send_xchar;
-	serial_driver.wait_until_sent = rs_wait_until_sent;
-	serial_driver.read_proc = rs_read_proc;
-#endif
-	  
-	if (tty_register_driver(&serial_driver))
+	driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	tty_set_operations(driver, &rs_ops);
+	if (tty_register_driver(driver))
 		panic("Couldn't register serial driver\n");
+	serial_driver = driver;
   
 	/* do some initializing for the separate ports */
   
@@ -3520,7 +3497,6 @@
 		info->blocked_open = 0;
 		info->tqueue.routine = do_softint;
 		info->tqueue.data = info;
-		info->normal_termios = serial_driver.init_termios;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 		info->xmit.buf = NULL;
@@ -3541,7 +3517,7 @@
 
 		if (info->enabled) {
 			printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
-			       serial_driver.name, info->line, (unsigned int)info->port);
+			       serial_driver->name, info->line, (unsigned int)info->port);
 		}
 	}
 
diff -urN linux-2.5.70-bk16/arch/cris/drivers/serial.h linux-2.5.70-bk17/arch/cris/drivers/serial.h
--- linux-2.5.70-bk16/arch/cris/drivers/serial.h	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/cris/drivers/serial.h	2003-06-12 04:49:55.000000000 -0700
@@ -84,7 +84,6 @@
 
 	struct tq_struct	tqueue;
 	struct async_icount	icount;   /* error-statistics etc.*/
-	struct termios		normal_termios;
 #ifdef DECLARE_WAITQUEUE
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
diff -urN linux-2.5.70-bk16/arch/i386/kernel/cpu/cpufreq/powernow-k7.c linux-2.5.70-bk17/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
--- linux-2.5.70-bk16/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	2003-06-12 04:49:55.000000000 -0700
@@ -10,6 +10,7 @@
  *
  * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt.
  * - We cli/sti on stepping A0 CPUs around the FID/VID transition.
+ * (ADDENDUM: This seems to be needed on more systems, so we do it unconditionally now).
  * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect.
  * - We disable half multipliers if ACPI is used on A0 stepping CPUs.
  */
@@ -259,8 +260,7 @@
 
 	/* Now do the magic poking into the MSRs.  */
 
-	if (have_a0 == 1)	/* A0 errata 5 */
-		__asm__("\tcli\n");
+	__asm__("\tcli\n");
 
 	if (freqs.old > freqs.new) {
 		/* Going down, so change FID first */
@@ -272,9 +272,7 @@
 		change_FID(vid);
 	}
 	
-
-	if (have_a0 == 1)
-		__asm__("\tsti\n");
+	__asm__("\tsti\n");
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 }
diff -urN linux-2.5.70-bk16/arch/ia64/hp/sim/hpsim_console.c linux-2.5.70-bk17/arch/ia64/hp/sim/hpsim_console.c
--- linux-2.5.70-bk16/arch/ia64/hp/sim/hpsim_console.c	2003-05-26 18:00:47.000000000 -0700
+++ linux-2.5.70-bk17/arch/ia64/hp/sim/hpsim_console.c	2003-06-12 04:49:55.000000000 -0700
@@ -59,7 +59,7 @@
 
 static struct tty_driver *simcons_console_device (struct console *c, int *index)
 {
-	extern struct tty_driver hp_simserial_driver;
+	extern struct tty_driver *hp_simserial_driver;
 	*index = c->index;
-	return &hp_simserial_driver;
+	return hp_simserial_driver;
 }
diff -urN linux-2.5.70-bk16/arch/ia64/hp/sim/simserial.c linux-2.5.70-bk17/arch/ia64/hp/sim/simserial.c
--- linux-2.5.70-bk16/arch/ia64/hp/sim/simserial.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/ia64/hp/sim/simserial.c	2003-06-12 04:49:55.000000000 -0700
@@ -103,13 +103,9 @@
 	{ 0, 0}
 };
 
-struct tty_driver hp_simserial_driver;
-static int serial_refcount;
+struct tty_driver *hp_simserial_driver;
 
 static struct async_struct *IRQ_ports[NR_IRQS];
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
 
 static struct console *console;
 
@@ -934,11 +930,6 @@
 		return retval;
 	}
 
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->state->normal_termios;
-	}
-
 	/*
 	 * figure out which console to use (should be one already)
 	 */
@@ -1009,6 +1000,28 @@
 	printk(KERN_INFO " no serial options enabled\n");
 }
 
+static struct tty_operations hp_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.put_char = rs_put_char,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.send_xchar = rs_send_xchar,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.break_ctl = rs_break,
+	.wait_until_sent = rs_wait_until_sent,
+	.read_proc = rs_read_proc,
+};
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -1018,47 +1031,25 @@
 	int			i;
 	struct serial_state	*state;
 
+	hp_simserial_driver = alloc_tty_driver(1);
+	if (!hp_simserial_driver)
+		return -ENOMEM;
+
 	show_serial_version();
 
 	/* Initialize the tty_driver structure */
 
-	memset(&hp_simserial_driver, 0, sizeof(struct tty_driver));
-	hp_simserial_driver.magic = TTY_DRIVER_MAGIC;
-	hp_simserial_driver.driver_name = "simserial";
-	hp_simserial_driver.name = "ttyS";
-	hp_simserial_driver.major = TTY_MAJOR;
-	hp_simserial_driver.minor_start = 64;
-	hp_simserial_driver.num = 1;
-	hp_simserial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	hp_simserial_driver.subtype = SERIAL_TYPE_NORMAL;
-	hp_simserial_driver.init_termios = tty_std_termios;
-	hp_simserial_driver.init_termios.c_cflag =
+	hp_simserial_driver->driver_name = "simserial";
+	hp_simserial_driver->name = "ttyS";
+	hp_simserial_driver->major = TTY_MAJOR;
+	hp_simserial_driver->minor_start = 64;
+	hp_simserial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	hp_simserial_driver->subtype = SERIAL_TYPE_NORMAL;
+	hp_simserial_driver->init_termios = tty_std_termios;
+	hp_simserial_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	hp_simserial_driver.flags = TTY_DRIVER_REAL_RAW;
-	hp_simserial_driver.refcount = &serial_refcount;
-	hp_simserial_driver.table = serial_table;
-	hp_simserial_driver.termios = serial_termios;
-	hp_simserial_driver.termios_locked = serial_termios_locked;
-
-	hp_simserial_driver.open = rs_open;
-	hp_simserial_driver.close = rs_close;
-	hp_simserial_driver.write = rs_write;
-	hp_simserial_driver.put_char = rs_put_char;
-	hp_simserial_driver.flush_chars = rs_flush_chars;
-	hp_simserial_driver.write_room = rs_write_room;
-	hp_simserial_driver.chars_in_buffer = rs_chars_in_buffer;
-	hp_simserial_driver.flush_buffer = rs_flush_buffer;
-	hp_simserial_driver.ioctl = rs_ioctl;
-	hp_simserial_driver.throttle = rs_throttle;
-	hp_simserial_driver.unthrottle = rs_unthrottle;
-	hp_simserial_driver.send_xchar = rs_send_xchar;
-	hp_simserial_driver.set_termios = rs_set_termios;
-	hp_simserial_driver.stop = rs_stop;
-	hp_simserial_driver.start = rs_start;
-	hp_simserial_driver.hangup = rs_hangup;
-	hp_simserial_driver.break_ctl = rs_break;
-	hp_simserial_driver.wait_until_sent = rs_wait_until_sent;
-	hp_simserial_driver.read_proc = rs_read_proc;
+	hp_simserial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(hp_simserial_driver, &hp_ops);
 
 	/*
 	 * Let's have a little bit of fun !
@@ -1078,7 +1069,7 @@
 		       uart_config[state->type].name);
 	}
 
-	if (tty_register_driver(&hp_simserial_driver))
+	if (tty_register_driver(hp_simserial_driver))
 		panic("Couldn't register simserial driver\n");
 
 	return 0;
diff -urN linux-2.5.70-bk16/arch/mips/au1000/common/serial.c linux-2.5.70-bk17/arch/mips/au1000/common/serial.c
--- linux-2.5.70-bk16/arch/mips/au1000/common/serial.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/mips/au1000/common/serial.c	2003-06-12 04:49:56.000000000 -0700
@@ -126,8 +126,7 @@
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 
 static struct timer_list serial_timer;
 
@@ -187,14 +186,9 @@
 
 #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
 
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
-
 #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
-#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- tty->name, (info->flags), serial_refcount,info->count,tty->count,s)
+#define DBG_CNT(s) printk("(%s): [%x], refc=%d, serc=%d, ttyc=%d -> %s\n", \
+ tty->name, (info->flags), serial_driver->refcount, info->count,tty->count,s)
 #else
 #define DBG_CNT(s)
 #endif
@@ -1928,12 +1922,6 @@
 	info->flags |= ASYNC_CLOSING;
 	restore_flags(flags);
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->state->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -2300,11 +2288,6 @@
 		return retval;
 	}
 
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->state->normal_termios;
-		change_speed(info, 0);
-	}
 #ifdef CONFIG_AU1000_SERIAL_CONSOLE
 	if (sercons.cflag && sercons.index == line) {
 		tty->termios->c_cflag = sercons.cflag;
@@ -2512,6 +2495,28 @@
 EXPORT_SYMBOL(register_serial);
 EXPORT_SYMBOL(unregister_serial);
 
+static struct tty_operations serial_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.put_char = rs_put_char,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.break_ctl = rs_break,
+	.send_xchar = rs_send_xchar,
+	.wait_until_sent = rs_wait_until_sent,
+	.read_proc = rs_read_proc,
+};
+
 
 /*
  * The serial driver boot-time initialization code!
@@ -2521,6 +2526,10 @@
 	int i;
 	struct serial_state * state;
 
+	serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!serial_driver)
+		return -ENOMEM;
+
 	init_bh(SERIAL_BH, do_serial_bh);
 	init_timer(&serial_timer);
 	serial_timer.function = rs_timer;
@@ -2546,46 +2555,20 @@
 
 	/* Initialize the tty_driver structure */
 	
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.driver_name = "serial";
-	serial_driver.devfs_name = "tts/";
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET;
-	serial_driver.num = NR_PORTS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
+	serial_driver->driver_name = "serial";
+	serial_driver->devfs_name = "tts/";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64 + SERIAL_DEV_OFFSET;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_open;
-	serial_driver.close = rs_close;
-	serial_driver.write = rs_write;
-	serial_driver.put_char = rs_put_char;
-	serial_driver.flush_chars = rs_flush_chars;
-	serial_driver.write_room = rs_write_room;
-	serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	serial_driver.flush_buffer = rs_flush_buffer;
-	serial_driver.ioctl = rs_ioctl;
-	serial_driver.throttle = rs_throttle;
-	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.set_termios = rs_set_termios;
-	serial_driver.stop = rs_stop;
-	serial_driver.start = rs_start;
-	serial_driver.hangup = rs_hangup;
-	serial_driver.break_ctl = rs_break;
-	serial_driver.send_xchar = rs_send_xchar;
-	serial_driver.wait_until_sent = rs_wait_until_sent;
-	serial_driver.read_proc = rs_read_proc;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	tty_set_operations(serial_driver, &serial_ops);
 	
-	if (tty_register_driver(&serial_driver))
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 
 	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
@@ -2596,7 +2579,6 @@
 		state->custom_divisor = 0;
 		state->close_delay = 5*HZ/10;
 		state->closing_wait = 30*HZ;
-		state->normal_termios = serial_driver.init_termios;
 		state->icount.cts = state->icount.dsr = 
 			state->icount.rng = state->icount.dcd = 0;
 		state->icount.rx = state->icount.tx = 0;
@@ -2622,7 +2604,7 @@
 		       (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
 		       state->port, state->irq,
 		       uart_config[state->type].name);
-		tty_register_device(&serial_driver, state->line, NULL);
+		tty_register_device(serial_driver, state->line, NULL);
 	}
 	return 0;
 }
@@ -2709,7 +2691,7 @@
 	      state->iomem_base ? "iomem" : "port",
 	      state->iomem_base ? (unsigned long)state->iomem_base :
 	      state->port, state->irq, uart_config[state->type].name);
-	tty_register_device(&serial_driver, state->line, NULL); 
+	tty_register_device(serial_driver, state->line, NULL); 
 	return state->line + SERIAL_DEV_OFFSET;
 }
 
@@ -2735,8 +2717,7 @@
 	/* These will be hidden, because they are devices that will no longer
 	 * be available to the system. (ie, PCMCIA modems, once ejected)
 	 */
-	tty_unregister_device(&serial_driver, state->line);
-	tty_unregister_device(&callout_driver, state->line);
+	tty_unregister_device(serial_driver, state->line);
 	restore_flags(flags);
 }
 
@@ -2751,10 +2732,11 @@
 	del_timer_sync(&serial_timer);
 	save_flags(flags); cli();
         remove_bh(SERIAL_BH);
-	if ((e1 = tty_unregister_driver(&serial_driver)))
+	if ((e1 = tty_unregister_driver(serial_driver)))
 		printk("serial: failed to unregister serial driver (%d)\n",
 		       e1);
 	restore_flags(flags);
+	put_tty_driver(serial_driver);
 
 	for (i = 0; i < NR_PORTS; i++) {
 		if ((info = rs_table[i].info)) {
@@ -2854,7 +2836,7 @@
 static struct tty_driver *serial_console_device(struct console *c, int *index)
 {
 	*index = c->index - SERIAL_DEV_OFFSET;
-	return &serial_driver;
+	return serial_driver;
 }
 
 /*
diff -urN linux-2.5.70-bk16/arch/mips/baget/vacserial.c linux-2.5.70-bk17/arch/mips/baget/vacserial.c
--- linux-2.5.70-bk16/arch/mips/baget/vacserial.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/mips/baget/vacserial.c	2003-06-12 04:49:56.000000000 -0700
@@ -29,7 +29,7 @@
   
 #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
 #define DBG_CNT(s) baget_printk("(%s):[%x] refc=%d, serc=%d, ttyc=%d-> %s\n", \
-  tty->name,(info->flags),serial_refcount,info->count,tty->count,s)
+  tty->name,(info->flags),serial_driver->refcount,info->count,tty->count,s)
 #else
 #define DBG_CNT(s)
 #endif
@@ -95,8 +95,7 @@
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
@@ -143,10 +142,6 @@
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
 
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
@@ -1685,12 +1680,6 @@
 	}
 	info->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->state->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -2038,11 +2027,6 @@
 		 return retval;
 	}
 
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->state->normal_termios;
-		change_speed(info);
-	}
 #ifdef CONFIG_SERIAL_CONSOLE
 	if (sercons.cflag && sercons.index == line) {
 		tty->termios->c_cflag = sercons.cflag;
@@ -2267,6 +2251,28 @@
                 mod_timer(&vacs_timer, jiffies + IRQ_timeout[0] - 2);
         }
 }
+
+static struct tty_operations rs_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.put_char = rs_put_char,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.send_xchar = rs_send_xchar,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.break_ctl = rs_break,
+	.wait_until_sent = rs_wait_until_sent,
+	.read_proc = rs_read_proc,
+};
  
 /*
  * The serial driver boot-time initialization code!
@@ -2316,49 +2322,27 @@
 #endif
 
 #endif
+	serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!serial_driver)
+		return -ENOMEM;
+
 	show_serial_version();
 
 	/* Initialize the tty_driver structure */
 	
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.driver_name = "serial";
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NR_PORTS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
+	serial_driver->driver_name = "serial";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_open;
-	serial_driver.close = rs_close;
-	serial_driver.write = rs_write;
-	serial_driver.put_char = rs_put_char;
-	serial_driver.flush_chars = rs_flush_chars;
-	serial_driver.write_room = rs_write_room;
-	serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	serial_driver.flush_buffer = rs_flush_buffer;
-	serial_driver.ioctl = rs_ioctl;
-	serial_driver.throttle = rs_throttle;
-	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.send_xchar = rs_send_xchar;
-	serial_driver.set_termios = rs_set_termios;
-	serial_driver.stop = rs_stop;
-	serial_driver.start = rs_start;
-	serial_driver.hangup = rs_hangup;
-	serial_driver.break_ctl = rs_break;
-	serial_driver.wait_until_sent = rs_wait_until_sent;
-	serial_driver.read_proc = rs_read_proc;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &rs_ops);
 	
-	if (tty_register_driver(&serial_driver))
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 	
 	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
@@ -2368,7 +2352,6 @@
 		state->custom_divisor = 0;
 		state->close_delay = 5*HZ/10;
 		state->closing_wait = 30*HZ;
-		state->normal_termios = serial_driver.init_termios;
 		state->icount.cts = state->icount.dsr = 
 			state->icount.rng = state->icount.dcd = 0;
 		state->icount.rx = state->icount.tx = 0;
@@ -2481,10 +2464,11 @@
 	del_timer_sync(&vacs_timer);
         remove_bh(SERIAL_BH);
 
-	if ((e1 = tty_unregister_driver(&serial_driver)))
+	if ((e1 = tty_unregister_driver(serial_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       e1);
 	restore_flags(flags);
+	put_tty_driver(serial_driver);
 
 	for (i = 0; i < NR_PORTS; i++) {
 		if (rs_table[i].type != PORT_UNKNOWN)
@@ -2572,7 +2556,7 @@
 static struct tty_driver *serial_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 /*
diff -urN linux-2.5.70-bk16/arch/ppc/4xx_io/serial_sicc.c linux-2.5.70-bk17/arch/ppc/4xx_io/serial_sicc.c
--- linux-2.5.70-bk16/arch/ppc/4xx_io/serial_sicc.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/ppc/4xx_io/serial_sicc.c	2003-06-12 04:49:56.000000000 -0700
@@ -197,11 +197,7 @@
 /*
  * Things needed by tty driver
  */
-static struct tty_driver siccnormal_driver;
-static int siccuart_refcount;
-static struct tty_struct *siccuart_table[SERIAL_SICC_NR];
-static struct termios *siccuart_termios[SERIAL_SICC_NR];
-static struct termios *siccuart_termios_locked[SERIAL_SICC_NR];
+static struct tty_driver *siccnormal_driver;
 
 #if defined(CONFIG_SERIAL_SICC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -269,7 +265,6 @@
     unsigned int        closing_wait;
     unsigned int        custom_divisor;
     unsigned int        flags;
-    struct termios      normal_termios;
     int         count;
     struct SICC_info    *info;
 };
@@ -1473,12 +1468,6 @@
     info->flags |= ASYNC_CLOSING;
     restore_flags(flags);
     /*
-     * Save the termios structure, since this port may have
-     * separate termios for callout and dialin.
-     */
-    if (info->flags & ASYNC_NORMAL_ACTIVE)
-        info->state->normal_termios = *tty->termios;
-    /*
      * Now we wait for the transmit buffer to clear; and we notify
      * the line discipline to only process XON/XOFF characters.
      */
@@ -1761,10 +1750,6 @@
         return retval;
     }
 
-    if ((info->state->count == 1) &&
-        (info->flags & ASYNC_SPLIT_TERMIOS)) {
-	*tty->termios = info->state->normal_termios;
-    }
 #ifdef CONFIG_SERIAL_SICC_CONSOLE
     if (siccuart_cons.cflag && siccuart_cons.index == line) {
         tty->termios->c_cflag = siccuart_cons.cflag;
@@ -1775,47 +1760,46 @@
     return 0;
 }
 
+static struct tty_operations sicc_ops = {
+	.open = siccuart_open,
+	.close = siccuart_close,
+	.write = siccuart_write,
+	.put_char = siccuart_put_char,
+	.flush_chars = siccuart_flush_chars,
+	.write_room = siccuart_write_room,
+	.chars_in_buffer = siccuart_chars_in_buffer,
+	.flush_buffer  = siccuart_flush_buffer,
+	.ioctl = siccuart_ioctl,
+	.throttle = siccuart_throttle,
+	.unthrottle = siccuart_unthrottle,
+	.send_xchar = siccuart_send_xchar,
+	.set_termios = siccuart_set_termios,
+	.stop = siccuart_stop,
+	.start = siccuart_start,
+	.hangup = siccuart_hangup,
+	.break_ctl = siccuart_break_ctl,
+	.wait_until_sent = siccuart_wait_until_sent,
+};
+
 int __init siccuart_init(void)
 {
     int i;
+    siccnormal_driver = alloc_tty_driver(SERIAL_SICC_NR);
+    if (!siccnormal_driver)
+	return -ENOMEM;
     printk("IBM Vesta SICC serial port driver V 0.1 by Yudong Yang and Yi Ge / IBM CRL .\n");
-    siccnormal_driver.magic = TTY_DRIVER_MAGIC;
-    siccnormal_driver.driver_name = "serial_sicc";
-    siccnormal_driver.name = SERIAL_SICC_NAME;
-    siccnormal_driver.major = SERIAL_SICC_MAJOR;
-    siccnormal_driver.minor_start = SERIAL_SICC_MINOR;
-    siccnormal_driver.num = SERIAL_SICC_NR;
-    siccnormal_driver.type = TTY_DRIVER_TYPE_SERIAL;
-    siccnormal_driver.subtype = SERIAL_TYPE_NORMAL;
-    siccnormal_driver.init_termios = tty_std_termios;
-    siccnormal_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-    siccnormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-    siccnormal_driver.refcount = &siccuart_refcount;
-    siccnormal_driver.table = siccuart_table;
-    siccnormal_driver.termios = siccuart_termios;
-    siccnormal_driver.termios_locked = siccuart_termios_locked;
-
-    siccnormal_driver.open = siccuart_open;
-    siccnormal_driver.close = siccuart_close;
-    siccnormal_driver.write = siccuart_write;
-    siccnormal_driver.put_char = siccuart_put_char;
-    siccnormal_driver.flush_chars = siccuart_flush_chars;
-    siccnormal_driver.write_room = siccuart_write_room;
-    siccnormal_driver.chars_in_buffer = siccuart_chars_in_buffer;
-    siccnormal_driver.flush_buffer  = siccuart_flush_buffer;
-    siccnormal_driver.ioctl = siccuart_ioctl;
-    siccnormal_driver.throttle = siccuart_throttle;
-    siccnormal_driver.unthrottle = siccuart_unthrottle;
-    siccnormal_driver.send_xchar = siccuart_send_xchar;
-    siccnormal_driver.set_termios = siccuart_set_termios;
-    siccnormal_driver.stop = siccuart_stop;
-    siccnormal_driver.start = siccuart_start;
-    siccnormal_driver.hangup = siccuart_hangup;
-    siccnormal_driver.break_ctl = siccuart_break_ctl;
-    siccnormal_driver.wait_until_sent = siccuart_wait_until_sent;
-    siccnormal_driver.read_proc = NULL;
+    siccnormal_driver->driver_name = "serial_sicc";
+    siccnormal_driver->name = SERIAL_SICC_NAME;
+    siccnormal_driver->major = SERIAL_SICC_MAJOR;
+    siccnormal_driver->minor_start = SERIAL_SICC_MINOR;
+    siccnormal_driver->type = TTY_DRIVER_TYPE_SERIAL;
+    siccnormal_driver->subtype = SERIAL_TYPE_NORMAL;
+    siccnormal_driver->init_termios = tty_std_termios;
+    siccnormal_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+    siccnormal_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+    tty_set_operations(siccnormal_driver, &sicc_ops);
 
-    if (tty_register_driver(&siccnormal_driver))
+    if (tty_register_driver(siccnormal_driver))
         panic("Couldn't register SICC serial driver\n");
 
     for (i = 0; i < SERIAL_SICC_NR; i++) {
@@ -1823,7 +1807,6 @@
         state->line     = i;
         state->close_delay  = 5 * HZ / 10;
         state->closing_wait = 30 * HZ;
-        state->normal_termios   = siccnormal_driver.init_termios;
     }
 
 
@@ -1922,7 +1905,7 @@
 static struct tty_driver *siccuart_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &siccnormal_driver;
+	return siccnormal_driver;
 }
 
 static int __init siccuart_console_setup(struct console *co, char *options)
diff -urN linux-2.5.70-bk16/arch/ppc/8260_io/uart.c linux-2.5.70-bk17/arch/ppc/8260_io/uart.c
--- linux-2.5.70-bk16/arch/ppc/8260_io/uart.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/ppc/8260_io/uart.c	2003-06-12 04:49:56.000000000 -0700
@@ -74,8 +74,7 @@
 static char *serial_name = "CPM UART driver";
 static char *serial_version = "0.02";
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 static int serial_console_setup(struct console *co, char *options);
 
 /*
@@ -170,10 +169,6 @@
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
 
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
 /* The number of buffer descriptors and their sizes.
 */
 #define RX_NUM_FIFO	4
@@ -1659,12 +1654,6 @@
 	}
 	info->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->state->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -1974,12 +1963,6 @@
 		return retval;
 	}
 
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->state->normal_termios;
-		change_speed(info);
-	}
-
 #ifdef SERIAL_DEBUG_OPEN
 	printk("rs_open %s successful...", line);
 #endif
@@ -2411,7 +2394,7 @@
 static kdev_t serial_console_device(struct console *c)
 {
 	*index = c->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 
@@ -2440,6 +2423,26 @@
  */
 static	int	baud_idx;
 
+static struct tty_operations rs_8xx_ops = {
+	.open = rs_8xx_open,
+	.close = rs_8xx_close,
+	.write = rs_8xx_write,
+	.put_char = rs_8xx_put_char,
+	.write_room = rs_8xx_write_room,
+	.chars_in_buffer = rs_8xx_chars_in_buffer,
+	.flush_buffer = rs_8xx_flush_buffer,
+	.ioctl = rs_8xx_ioctl,
+	.throttle = rs_8xx_throttle,
+	.unthrottle = rs_8xx_unthrottle,
+	.send_xchar = rs_8xx_send_xchar,
+	.set_termios = rs_8xx_set_termios,
+	.stop = rs_8xx_stop,
+	.start = rs_8xx_start,
+	.hangup = rs_8xx_hangup,
+	.wait_until_sent = rs_8xx_wait_until_sent,
+	.read_proc = rs_8xx_read_proc,
+};
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -2459,49 +2462,27 @@
 	volatile	immap_t		*immap;
 	volatile	iop8260_t	*io;
 	
+	serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!serial_driver)
+		return -ENOMEM;
+
 	show_serial_version();
 
 	/* Initialize the tty_driver structure */
 	
-	/*memset(&serial_driver, 0, sizeof(struct tty_driver));*/
-	__clear_user(&serial_driver,sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.driver_name = "serial";
-	serial_driver.devfs_name = "tts/";
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NR_PORTS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
+	serial_driver->driver_name = "serial";
+	serial_driver->devfs_name = "tts/";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_8xx_open;
-	serial_driver.close = rs_8xx_close;
-	serial_driver.write = rs_8xx_write;
-	serial_driver.put_char = rs_8xx_put_char;
-	serial_driver.write_room = rs_8xx_write_room;
-	serial_driver.chars_in_buffer = rs_8xx_chars_in_buffer;
-	serial_driver.flush_buffer = rs_8xx_flush_buffer;
-	serial_driver.ioctl = rs_8xx_ioctl;
-	serial_driver.throttle = rs_8xx_throttle;
-	serial_driver.unthrottle = rs_8xx_unthrottle;
-	serial_driver.send_xchar = rs_8xx_send_xchar;
-	serial_driver.set_termios = rs_8xx_set_termios;
-	serial_driver.stop = rs_8xx_stop;
-	serial_driver.start = rs_8xx_start;
-	serial_driver.hangup = rs_8xx_hangup;
-	serial_driver.wait_until_sent = rs_8xx_wait_until_sent;
-	serial_driver.read_proc = rs_8xx_read_proc;
-	
-	if (tty_register_driver(&serial_driver))
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &rs_8xx_ops);
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 
 	immap = immr;
@@ -2584,7 +2565,6 @@
 		state->custom_divisor = 0;
 		state->close_delay = 5*HZ/10;
 		state->closing_wait = 30*HZ;
-		state->normal_termios = serial_driver.init_termios;
 		state->icount.cts = state->icount.dsr = 
 			state->icount.rng = state->icount.dcd = 0;
 		state->icount.rx = state->icount.tx = 0;
diff -urN linux-2.5.70-bk16/arch/ppc/8xx_io/uart.c linux-2.5.70-bk17/arch/ppc/8xx_io/uart.c
--- linux-2.5.70-bk16/arch/ppc/8xx_io/uart.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/arch/ppc/8xx_io/uart.c	2003-06-12 04:49:56.000000000 -0700
@@ -85,8 +85,7 @@
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 static int serial_console_setup(struct console *co, char *options);
 
 static void serial_console_write(struct console *c, const char *s,
@@ -169,10 +168,6 @@
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
 
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
 /* The number of buffer descriptors and their sizes.
 */
 #define RX_NUM_FIFO	4
@@ -1706,12 +1701,6 @@
 	}
 	info->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->state->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -2034,12 +2023,6 @@
 		return retval;
 	}
 
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->state->normal_termios;
-		change_speed(info);
-	}
-
 #ifdef SERIAL_DEBUG_OPEN
 	printk("rs_open %s successful...", tty->name);
 #endif
@@ -2476,7 +2459,7 @@
 static struct tty_driver *serial_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 /*
@@ -2493,6 +2476,26 @@
 */
 static	int	baud_idx;
 
+static struct tty_operations rs_8xx_ops = {
+	.open = rs_8xx_open,
+	.close = rs_8xx_close,
+	.write = rs_8xx_write,
+	.put_char = rs_8xx_put_char,
+	.write_room = rs_8xx_write_room,
+	.chars_in_buffer = rs_8xx_chars_in_buffer,
+	.flush_buffer = rs_8xx_flush_buffer,
+	.ioctl = rs_8xx_ioctl,
+	.throttle = rs_8xx_throttle,
+	.unthrottle = rs_8xx_unthrottle,
+	.send_xchar = rs_8xx_send_xchar,
+	.set_termios = rs_8xx_set_termios,
+	.stop = rs_8xx_stop,
+	.start = rs_8xx_start,
+	.hangup = rs_8xx_hangup,
+	.wait_until_sent = rs_8xx_wait_until_sent,
+	.read_proc = rs_8xx_read_proc,
+};
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -2510,6 +2513,10 @@
 	volatile	scc_t		*scp;
 	volatile	scc_uart_t	*sup;
 	volatile	immap_t		*immap;
+
+	serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!serial_driver)
+		return -ENOMEM;
 	
 	init_bh(SERIAL_BH, do_serial_bh);
 
@@ -2517,44 +2524,20 @@
 
 	/* Initialize the tty_driver structure */
 	
-	__clear_user(&serial_driver,sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.driver_name = "serial";
-	serial_driver.devfs_name = "tts/";
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NR_PORTS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
+	serial_driver->driver_name = "serial";
+	serial_driver->devfs_name = "tts/";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_8xx_open;
-	serial_driver.close = rs_8xx_close;
-	serial_driver.write = rs_8xx_write;
-	serial_driver.put_char = rs_8xx_put_char;
-	serial_driver.write_room = rs_8xx_write_room;
-	serial_driver.chars_in_buffer = rs_8xx_chars_in_buffer;
-	serial_driver.flush_buffer = rs_8xx_flush_buffer;
-	serial_driver.ioctl = rs_8xx_ioctl;
-	serial_driver.throttle = rs_8xx_throttle;
-	serial_driver.unthrottle = rs_8xx_unthrottle;
-	serial_driver.send_xchar = rs_8xx_send_xchar;
-	serial_driver.set_termios = rs_8xx_set_termios;
-	serial_driver.stop = rs_8xx_stop;
-	serial_driver.start = rs_8xx_start;
-	serial_driver.hangup = rs_8xx_hangup;
-	serial_driver.wait_until_sent = rs_8xx_wait_until_sent;
-	serial_driver.read_proc = rs_8xx_read_proc;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &rs_8xx_ops);
 	
-	if (tty_register_driver(&serial_driver))
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 	
 	cp = cpmp;	/* Get pointer to Communication Processor */
@@ -2615,7 +2598,6 @@
 		state->custom_divisor = 0;
 		state->close_delay = 5*HZ/10;
 		state->closing_wait = 30*HZ;
-		state->normal_termios = serial_driver.init_termios;
 		state->icount.cts = state->icount.dsr = 
 			state->icount.rng = state->icount.dcd = 0;
 		state->icount.rx = state->icount.tx = 0;
diff -urN linux-2.5.70-bk16/arch/um/drivers/line.c linux-2.5.70-bk17/arch/um/drivers/line.c
--- linux-2.5.70-bk16/arch/um/drivers/line.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk17/arch/um/drivers/line.c	2003-06-12 04:49:56.000000000 -0700
@@ -399,12 +399,17 @@
 	return(line_setup(lines, num, config, 0));
 }
 
-void line_register_devfs(struct lines *set, struct line_driver *line_driver, 
-			 struct tty_driver *driver, struct line *lines,
+struct tty_driver *line_register_devfs(struct lines *set,
+			 struct line_driver *line_driver, 
+			 struct tty_operations *ops, struct line *lines,
 			 int nlines)
 {
-	int err, i, n;
+	int err, i;
 	char *from, *to;
+	struct tty_driver *driver = alloc_tty_driver(nlines);
+
+	if (!driver)
+		return NULL;
 
 	driver->driver_name = line_driver->name;
 	driver->name = line_driver->devfs_name;
@@ -412,26 +417,9 @@
 	driver->minor_start = line_driver->minor_start;
 	driver->type = line_driver->type;
 	driver->subtype = line_driver->subtype;
-	driver->magic = TTY_DRIVER_MAGIC;
 	driver->flags = TTY_DRIVER_REAL_RAW;
-
-	n = set->num;
-	driver->num = n;
-	driver->table = kmalloc(n * sizeof(driver->table[0]), GFP_KERNEL);
-	driver->termios = kmalloc(n * sizeof(driver->termios[0]), GFP_KERNEL);
-	driver->termios_locked = kmalloc(n * sizeof(driver->termios_locked[0]),
-					 GFP_KERNEL);
-	if((driver->table == NULL) || (driver->termios == NULL) ||
-	   (driver->termios_locked == NULL))
-		panic("Failed to allocate driver table");
-
-	memset(driver->table, 0, n * sizeof(driver->table[0]));
-	memset(driver->termios, 0, n * sizeof(driver->termios[0]));
-	memset(driver->termios_locked, 0, 
-	       n * sizeof(driver->termios_locked[0]));
-
-	driver->write_room = line_write_room;
 	driver->init_termios = tty_std_termios;
+	tty_set_operations(driver, ops);
 
 	if (tty_register_driver(driver))
 		panic("line_register_devfs : Couldn't register driver\n");
@@ -448,6 +436,7 @@
 	}
 
 	mconsole_register_dev(&line_driver->mc);
+	return driver;
 }
 
 void lines_init(struct line *lines, int nlines)
diff -urN linux-2.5.70-bk16/arch/um/drivers/ssl.c linux-2.5.70-bk17/arch/um/drivers/ssl.c
--- linux-2.5.70-bk16/arch/um/drivers/ssl.c	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/arch/um/drivers/ssl.c	2003-06-12 04:49:56.000000000 -0700
@@ -28,9 +28,8 @@
 /* Referenced only by tty_driver below - presumably it's locked correctly
  * by the tty driver.
  */
-static int ssl_refcount = 0;
 
-static struct tty_driver ssl_driver;
+static struct tty_driver *ssl_driver;
 
 #define NR_PORTS 64
 
@@ -190,8 +189,7 @@
 {
 }
 
-static struct tty_driver ssl_driver = {
-	.refcount 		= &ssl_refcount,
+static struct tty_operations ssl_ops = {
 	.open 	 		= ssl_open,
 	.close 	 		= ssl_close,
 	.write 	 		= ssl_write,
@@ -205,7 +203,8 @@
 	.set_termios 		= ssl_set_termios,
 	.stop 	 		= ssl_stop,
 	.start 	 		= ssl_start,
-	.hangup 	 	= ssl_hangup
+	.hangup 	 	= ssl_hangup,
+	.write_room		= line_write_room,
 };
 
 /* Changed by ssl_init and referenced by ssl_exit, which are both serialized
@@ -220,8 +219,8 @@
 	printk(KERN_INFO "Initializing software serial port version %d\n", 
 	       ssl_version);
 
-	line_register_devfs(&lines, &driver, &ssl_driver, serial_lines, 
-			    sizeof(serial_lines)/sizeof(serial_lines[0]));
+	ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops,
+		serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]));
 
 	lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]));
 
diff -urN linux-2.5.70-bk16/arch/um/drivers/stdio_console.c linux-2.5.70-bk17/arch/um/drivers/stdio_console.c
--- linux-2.5.70-bk16/arch/um/drivers/stdio_console.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/arch/um/drivers/stdio_console.c	2003-06-12 04:49:56.000000000 -0700
@@ -36,9 +36,7 @@
  * by the tty driver.
  */
 
-static struct tty_driver console_driver;
-
-static int console_refcount = 0;
+static struct tty_driver *console_driver;
 
 static struct chan_ops init_console_ops = {
 	.type		= "you shouldn't see this",
@@ -167,8 +165,8 @@
 
 	printk(KERN_INFO "Initializing stdio console driver\n");
 
-	line_register_devfs(&console_lines, &driver, &console_driver, vts, 
-			    sizeof(vts)/sizeof(vts[0]));
+	console_driver = line_register_devfs(&console_lines, &driver,
+				&console_ops, vts, sizeof(vts)/sizeof(vts[0]));
 
 	lines_init(vts, sizeof(vts)/sizeof(vts[0]));
 
@@ -190,19 +188,19 @@
 	if(con_init_done) up(&vts[console->index].sem);
 }
 
-static struct tty_driver console_driver = {
-	.refcount 		= &console_refcount,
+static struct tty_operations console_ops = {
 	.open 	 		= con_open,
 	.close 	 		= con_close,
 	.write 	 		= con_write,
 	.chars_in_buffer 	= chars_in_buffer,
-	.set_termios 		= set_termios
+	.set_termios 		= set_termios,
+	.write_room		= line_write_room,
 };
 
 static struct tty_driver *console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &console_driver;
+	return console_driver;
 }
 
 static int console_setup(struct console *co, char *options)
diff -urN linux-2.5.70-bk16/arch/um/include/line.h linux-2.5.70-bk17/arch/um/include/line.h
--- linux-2.5.70-bk16/arch/um/include/line.h	2003-05-26 18:00:45.000000000 -0700
+++ linux-2.5.70-bk17/arch/um/include/line.h	2003-06-12 04:49:56.000000000 -0700
@@ -81,9 +81,10 @@
 extern int line_setup_irq(int fd, int input, int output, void *data);
 extern void line_close_chan(struct line *line);
 extern void line_disable(struct line *line, int current_irq);
-extern void line_register_devfs(struct lines *set, 
+extern struct tty_driver * line_register_devfs(struct lines *set, 
 				struct line_driver *line_driver, 
-				struct tty_driver *driver, struct line *lines,
+				struct tty_operations *driver,
+				struct line *lines,
 				int nlines);
 extern void lines_init(struct line *lines, int nlines);
 extern void close_lines(struct line *lines, int nlines);
diff -urN linux-2.5.70-bk16/arch/v850/kernel/memcons.c linux-2.5.70-bk17/arch/v850/kernel/memcons.c
--- linux-2.5.70-bk16/arch/v850/kernel/memcons.c	2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk17/arch/v850/kernel/memcons.c	2003-06-12 04:49:56.000000000 -0700
@@ -58,11 +58,12 @@
 		len -= write (buf, len);
 }
 
-extern struct tty_driver tty_driver;
+static struct tty_driver *tty_driver;
+
 static struct tty_driver *memcons_device (struct console *co, int *index)
 {
 	*index = co->index;
-	return &tty_driver;
+	return tty_driver;
 }
 
 static struct console memcons =
@@ -82,12 +83,6 @@
 
 /* Higher level TTY interface.  */
 
-static struct tty_struct *tty_table[1] = { 0 };
-static struct termios *tty_termios[1] = { 0 };
-static struct termios *tty_termios_locked[1] = { 0 };
-static struct tty_driver tty_driver = { 0 };
-static int tty_ref_count = 0;
-
 int memcons_tty_open (struct tty_struct *tty, struct file *filp)
 {
 	return 0;
@@ -110,27 +105,32 @@
 	return 0;
 }
 
+static struct tty_operations ops = {
+	.open = memcons_tty_open,
+	.write = memcons_tty_write,
+	.write_room = memcons_tty_write_room,
+	.chars_in_buffer = memcons_tty_chars_in_buffer,
+};
+
 int __init memcons_tty_init (void)
 {
-	tty_driver.name = "memcons";
-	tty_driver.major = TTY_MAJOR;
-	tty_driver.minor_start = 64;
-	tty_driver.num = 1;
-	tty_driver.type = TTY_DRIVER_TYPE_SYSCONS;
-
-	tty_driver.refcount = &tty_ref_count;
-
-	tty_driver.table = tty_table;
-	tty_driver.termios = tty_termios;
-	tty_driver.termios_locked = tty_termios_locked;
-
-	tty_driver.init_termios = tty_std_termios;
-
-	tty_driver.open = memcons_tty_open;
-	tty_driver.write = memcons_tty_write;
-	tty_driver.write_room = memcons_tty_write_room;
-	tty_driver.chars_in_buffer = memcons_tty_chars_in_buffer;
-
-	tty_register_driver (&tty_driver);
+	int err;
+	struct tty_driver *driver = alloc_tty_driver(1);
+	if (!driver)
+		return -ENOMEM;
+
+	driver->name = "memcons";
+	driver->major = TTY_MAJOR;
+	driver->minor_start = 64;
+	driver->type = TTY_DRIVER_TYPE_SYSCONS;
+	driver->init_termios = tty_std_termios;
+	tty_set_operations(driver, &ops);
+	err = tty_register_driver(driver);
+	if (err) {
+		put_tty_driver(driver);
+		return err;
+	}
+	tty_driver = driver;
+	return 0;
 }
 __initcall (memcons_tty_init);
diff -urN linux-2.5.70-bk16/arch/v850/kernel/simcons.c linux-2.5.70-bk17/arch/v850/kernel/simcons.c
--- linux-2.5.70-bk16/arch/v850/kernel/simcons.c	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk17/arch/v850/kernel/simcons.c	2003-06-12 04:49:56.000000000 -0700
@@ -35,11 +35,11 @@
 	return V850_SIM_SYSCALL (read, 0, buf, len);
 }
 
-extern struct tty_driver tty_driver;
+static struct tty_driver *tty_driver;
 static struct tty_driver *simcons_device (struct console *c, int *index)
 {
 	*index = c->index;
-	return &tty_driver;
+	return tty_driver;
 }
 
 static struct console simcons =
@@ -54,12 +54,6 @@
 
 /* Higher level TTY interface.  */
 
-static struct tty_struct *tty_table[1] = { 0 };
-static struct termios *tty_termios[1] = { 0 };
-static struct termios *tty_termios_locked[1] = { 0 };
-static struct tty_driver tty_driver = { 0 };
-static int tty_refcount = 0;
-
 int simcons_tty_open (struct tty_struct *tty, struct file *filp)
 {
 	return 0;
@@ -83,28 +77,32 @@
 	return 0;
 }
 
+static struct tty_operations ops = {
+	.open = simcons_tty_open,
+	.write = simcons_tty_write,
+	.write_room = simcons_tty_write_room,
+	.chars_in_buffer = simcons_tty_chars_in_buffer,
+};
+
 int __init simcons_tty_init (void)
 {
-	tty_driver.name = "simcons";
-	tty_driver.major = TTY_MAJOR;
-	tty_driver.minor_start = 64;
-	tty_driver.num = 1;
-	tty_driver.type = TTY_DRIVER_TYPE_SYSCONS;
-
-	tty_driver.refcount = &tty_refcount;
-
-	tty_driver.table = tty_table;
-	tty_driver.termios = tty_termios;
-	tty_driver.termios_locked = tty_termios_locked;
-
-	tty_driver.init_termios = tty_std_termios;
-
-	tty_driver.open = simcons_tty_open;
-	tty_driver.write = simcons_tty_write;
-	tty_driver.write_room = simcons_tty_write_room;
-	tty_driver.chars_in_buffer = simcons_tty_chars_in_buffer;
-
-	tty_register_driver (&tty_driver);
+	struct tty_driver *driver = alloc_tty_driver(1);
+	int err;
+	if (!driver)
+		return -ENOMEM;
+	driver->name = "simcons";
+	driver->major = TTY_MAJOR;
+	driver->minor_start = 64;
+	driver->type = TTY_DRIVER_TYPE_SYSCONS;
+	driver->init_termios = tty_std_termios;
+	tty_set_operations(driver, &ops);
+	err = tty_register_driver(driver);
+	if (err) {
+		put_tty_driver(driver);
+		return err;
+	}
+	tty_driver = driver;
+	return 0;
 }
 __initcall (simcons_tty_init);
 
@@ -149,8 +147,8 @@
 
 void simcons_poll_ttys (void)
 {
-	if (tty_table[0])
-		simcons_poll_tty (tty_table[0]);
+	if (tty_driver && tty_driver->ttys[0])
+		simcons_poll_tty (tty_driver->ttys[0]);
 }
 
 void simcons_setup (void)
diff -urN linux-2.5.70-bk16/drivers/acpi/acpi_ksyms.c linux-2.5.70-bk17/drivers/acpi/acpi_ksyms.c
--- linux-2.5.70-bk16/drivers/acpi/acpi_ksyms.c	2003-05-26 18:00:37.000000000 -0700
+++ linux-2.5.70-bk17/drivers/acpi/acpi_ksyms.c	2003-06-12 04:49:56.000000000 -0700
@@ -144,8 +144,8 @@
 #include <linux/pci.h>
 extern int acpi_pci_irq_enable(struct pci_dev *dev);
 EXPORT_SYMBOL(acpi_pci_irq_enable);
-extern int acpi_pci_irq_lookup (int segment, int bus, int device, int pin);
-EXPORT_SYMBOL(acpi_pci_irq_lookup);
+EXPORT_SYMBOL(acpi_pci_register_driver);
+EXPORT_SYMBOL(acpi_pci_unregister_driver);
 #endif /*CONFIG_ACPI_PCI */
 
 #ifdef CONFIG_ACPI_EC
diff -urN linux-2.5.70-bk16/drivers/acpi/osl.c linux-2.5.70-bk17/drivers/acpi/osl.c
--- linux-2.5.70-bk16/drivers/acpi/osl.c	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk17/drivers/acpi/osl.c	2003-06-12 04:49:56.000000000 -0700
@@ -38,6 +38,7 @@
 #include <acpi/acpi.h>
 #include <asm/io.h>
 #include <acpi/acpi_bus.h>
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_ACPI_EFI
 #include <linux/efi.h>
@@ -948,19 +949,22 @@
 	return 0;
 }
 
-/*
- * We just have to assume we're dealing with valid memory
- */
-
+/* Assumes no unreadable holes inbetween */
 BOOLEAN
 acpi_os_readable(void *ptr, u32 len)
 {
+#if defined(__i386__) || defined(__x86_64__) 
+	char tmp;
+	return !__get_user(tmp, (char *)ptr) && !__get_user(tmp, (char *)ptr + len - 1);
+#endif
 	return 1;
 }
 
 BOOLEAN
 acpi_os_writable(void *ptr, u32 len)
 {
+	/* could do dummy write (racy) or a kernel page table lookup.
+	   The later may be difficult at early boot when kmap doesn't work yet. */
 	return 1;
 }
 
diff -urN linux-2.5.70-bk16/drivers/acpi/pci_irq.c linux-2.5.70-bk17/drivers/acpi/pci_irq.c
--- linux-2.5.70-bk16/drivers/acpi/pci_irq.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/acpi/pci_irq.c	2003-06-12 04:49:56.000000000 -0700
@@ -229,22 +229,20 @@
                           PCI Interrupt Routing Support
    -------------------------------------------------------------------------- */
 
-int
-acpi_pci_irq_lookup (
-	int			segment,
-	int			bus,
-	int			device,
-	int			pin)
+static int
+acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin)
 {
 	struct acpi_prt_entry	*entry = NULL;
+	int segment = pci_domain_nr(bus);
+	int bus_nr = bus->number;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup");
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
 		"Searching for PRT entry for %02x:%02x:%02x[%c]\n", 
-		segment, bus, device, ('A' + pin)));
+		segment, bus_nr, device, ('A' + pin)));
 
-	entry = acpi_pci_irq_find_prt_entry(segment, bus, device, pin); 
+	entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin); 
 	if (!entry) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
 		return_VALUE(0);
@@ -288,7 +286,8 @@
 	while (!irq && bridge->bus->self) {
 		pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
 		bridge = bridge->bus->self;
-		irq = acpi_pci_irq_lookup(0, bridge->bus->number, PCI_SLOT(bridge->devfn), pin);
+		irq = acpi_pci_irq_lookup(bridge->bus,
+				PCI_SLOT(bridge->devfn), pin);
 	}
 
 	if (!irq) {
@@ -331,7 +330,7 @@
 	 * First we check the PCI IRQ routing table (PRT) for an IRQ.  PRT
 	 * values override any BIOS-assigned IRQs set during boot.
 	 */
- 	irq = acpi_pci_irq_lookup(0, dev->bus->number, PCI_SLOT(dev->devfn), pin);
+ 	irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin);
  
 	/*
 	 * If no PRT entry was found, we'll try to derive an IRQ from the
diff -urN linux-2.5.70-bk16/drivers/acpi/pci_root.c linux-2.5.70-bk17/drivers/acpi/pci_root.c
--- linux-2.5.70-bk16/drivers/acpi/pci_root.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/drivers/acpi/pci_root.c	2003-06-12 04:49:56.000000000 -0700
@@ -59,17 +59,63 @@
 			},
 };
 
- struct acpi_pci_root {
+struct acpi_pci_root {
 	struct list_head	node;
- 	acpi_handle		handle;
- 	struct acpi_pci_id	id;
- 	struct pci_bus		*bus;
+	acpi_handle		handle;
+	struct acpi_pci_id	id;
+	struct pci_bus		*bus;
 	u64			mem_tra;
 	u64			io_tra;
- };
+};
 
 struct list_head		acpi_pci_roots;
 
+static struct acpi_pci_driver *sub_driver;
+
+int acpi_pci_register_driver(struct acpi_pci_driver *driver)
+{
+	int n = 0;
+	struct list_head *entry;
+
+	struct acpi_pci_driver **pptr = &sub_driver;
+	while (*pptr)
+		pptr = &(*pptr)->next;
+	*pptr = driver;
+
+	if (!driver->add)
+		return 0;
+
+	list_for_each(entry, &acpi_pci_roots) {
+		struct acpi_pci_root *root;
+		root = list_entry(entry, struct acpi_pci_root, node);
+		driver->add(root->handle);
+		n++;
+	}
+
+	return n;
+}
+
+void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
+{
+	struct list_head *entry;
+
+	struct acpi_pci_driver **pptr = &sub_driver;
+	while (*pptr) {
+		if (*pptr != driver)
+			continue;
+		*pptr = (*pptr)->next;
+		break;
+	}
+
+	if (!driver->remove)
+		return;
+
+	list_for_each(entry, &acpi_pci_roots) {
+		struct acpi_pci_root *root;
+		root = list_entry(entry, struct acpi_pci_root, node);
+		driver->remove(root->handle);
+	}
+}
 
 void
 acpi_pci_get_translations (
diff -urN linux-2.5.70-bk16/drivers/acpi/sleep/main.c linux-2.5.70-bk17/drivers/acpi/sleep/main.c
--- linux-2.5.70-bk16/drivers/acpi/sleep/main.c	2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk17/drivers/acpi/sleep/main.c	2003-06-12 04:49:56.000000000 -0700
@@ -214,6 +214,10 @@
 {
 	acpi_status status;
 
+	/* Suspend is hard to get right on SMP. */
+	if (num_online_cpus() != 1)
+		return AE_ERROR;
+
 	/* get out if state is invalid */
 	if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5)
 		return AE_ERROR;
@@ -226,7 +230,10 @@
 	 * TBD: S1 can be done without device_suspend.  Make a CONFIG_XX
 	 * to handle however when S1 failed without device_suspend.
 	 */
-	freeze_processes();		/* device_suspend needs processes to be stopped */
+	if (freeze_processes()) {
+		thaw_processes();
+		return AE_ERROR;		/* device_suspend needs processes to be stopped */
+	}
 
 	/* do we have a wakeup address for S2 and S3? */
 	/* Here, we support only S4BIOS, those we set the wakeup address */
diff -urN linux-2.5.70-bk16/drivers/acpi/tables.c linux-2.5.70-bk17/drivers/acpi/tables.c
--- linux-2.5.70-bk16/drivers/acpi/tables.c	2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk17/drivers/acpi/tables.c	2003-06-12 04:49:56.000000000 -0700
@@ -56,7 +56,7 @@
 	[ACPI_SRAT]		= "SRAT",
 	[ACPI_SSDT]		= "SSDT",
 	[ACPI_SPMI]		= "SPMI",
-	[ACPI_HPET]		= "HPET"
+	[ACPI_HPET]		= "HPET",
 };
 
 /* System Description Table (RSDT/XSDT) */
diff -urN linux-2.5.70-bk16/drivers/acpi/thermal.c linux-2.5.70-bk17/drivers/acpi/thermal.c
--- linux-2.5.70-bk16/drivers/acpi/thermal.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk17/drivers/acpi/thermal.c	2003-06-12 04:49:56.000000000 -0700
@@ -430,7 +430,7 @@
 	ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
 
 	if (!path)
-		return_VALUE(-EINVAL);;
+		return_VALUE(-EINVAL);
 
 	argv[0] = path;
 
diff -urN linux-2.5.70-bk16/drivers/base/class.c linux-2.5.70-bk17/drivers/base/class.c
--- linux-2.5.70-bk16/drivers/base/class.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/base/class.c	2003-06-12 04:49:56.000000000 -0700
@@ -264,8 +264,6 @@
 		return -EINVAL;
 
 	parent = class_get(class_dev->class);
-	if (class_dev->dev)
-		get_device(class_dev->dev);
 
 	pr_debug("CLASS: registering class device: ID = '%s'\n",
 		 class_dev->class_id);
diff -urN linux-2.5.70-bk16/drivers/base/memblk.c linux-2.5.70-bk17/drivers/base/memblk.c
--- linux-2.5.70-bk16/drivers/base/memblk.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/base/memblk.c	2003-06-12 04:49:56.000000000 -0700
@@ -13,13 +13,6 @@
 	set_kset_name("memblk"),
 };
 
-
-static struct device_driver memblk_driver = {
-	.name		= "memblk",
-	.bus		= &system_bus_type,
-};
-
-
 /*
  * register_memblk - Setup a driverfs device for a MemBlk
  * @num - MemBlk number to use when creating the device.
@@ -37,7 +30,7 @@
 	error = sys_device_register(&memblk->sysdev);
 	if (!error) 
 		error = sysfs_create_link(&root->sysdev.kobj,
-					  &memblk->sysdev,kobj,
+					  &memblk->sysdev.kobj,
 					  memblk->sysdev.kobj.name);
 	return error;
 }
diff -urN linux-2.5.70-bk16/drivers/base/node.c linux-2.5.70-bk17/drivers/base/node.c
--- linux-2.5.70-bk16/drivers/base/node.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/base/node.c	2003-06-12 04:49:56.000000000 -0700
@@ -2,7 +2,7 @@
  * drivers/base/node.c - basic Node class support
  */
 
-#include <linux/device.h>
+#include <linux/sysdev.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/mm.h>
@@ -14,18 +14,17 @@
 };
 
 
-static ssize_t node_read_cpumap(struct device * dev, char * buf)
+static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
 {
-	struct node *node_dev = to_node(to_root(dev));
+	struct node *node_dev = to_node(dev);
         return sprintf(buf,"%lx\n",node_dev->cpumap);
 }
 static SYSDEV_ATTR(cpumap,S_IRUGO,node_read_cpumap,NULL);
 
 #define K(x) ((x) << (PAGE_SHIFT - 10))
-static ssize_t node_read_meminfo(struct device * dev, char * buf)
+static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
 {
-	struct sys_root *node = to_root(dev);
-	int nid = node->id;
+	int nid = dev->id;
 	struct sysinfo i;
 	si_meminfo_node(&i, nid);
 	return sprintf(buf, "\n"
@@ -64,8 +63,8 @@
 	error = sys_device_register(&node->sysdev);
 
 	if (!error){
-		sys_device_create_file(&node->sysroot.dev, &attr_cpumap);
-		sys_device_create_file(&node->sysroot.dev, &attr_meminfo);
+		sysdev_create_file(&node->sysdev, &attr_cpumap);
+		sysdev_create_file(&node->sysdev, &attr_meminfo);
 	}
 	return error;
 }
diff -urN linux-2.5.70-bk16/drivers/base/power.c linux-2.5.70-bk17/drivers/base/power.c
--- linux-2.5.70-bk16/drivers/base/power.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/base/power.c	2003-06-12 04:49:56.000000000 -0700
@@ -10,7 +10,7 @@
  *
  */
 
-#define DEBUG
+#undef DEBUG
 
 #include <linux/device.h>
 #include <linux/module.h>
@@ -49,19 +49,19 @@
  */
 int device_suspend(u32 state, u32 level)
 {
-	struct list_head * node;
+	struct device * dev;
 	int error = 0;
 
 	printk(KERN_EMERG "Suspending devices\n");
 
 	down_write(&devices_subsys.rwsem);
-	list_for_each(node,&devices_subsys.kset.list) {
-		struct device * dev = to_dev(node);
+	list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) {
 		if (dev->driver && dev->driver->suspend) {
 			pr_debug("suspending device %s\n",dev->name);
 			error = dev->driver->suspend(dev,state,level);
 			if (error)
-				printk(KERN_ERR "%s: suspend returned %d\n",dev->name,error);
+				printk(KERN_ERR "%s: suspend returned %d\n",
+				       dev->name,error);
 		}
 	}
 	up_write(&devices_subsys.rwsem);
@@ -93,7 +93,7 @@
  */
 void device_resume(u32 level)
 {
-	struct list_head * node;
+	struct device * dev;
 
 	switch (level) {
 	case RESUME_POWER_ON:
@@ -107,8 +107,7 @@
 	}
 
 	down_write(&devices_subsys.rwsem);
-	list_for_each_prev(node,&devices_subsys.kset.list) {
-		struct device * dev = to_dev(node);
+	list_for_each_entry(dev,&devices_subsys.kset.list,kobj.entry) {
 		if (dev->driver && dev->driver->resume) {
 			pr_debug("resuming device %s\n",dev->name);
 			dev->driver->resume(dev,level);
@@ -124,13 +123,12 @@
  */
 void device_shutdown(void)
 {
-	struct list_head * entry;
+	struct device * dev;
 	
 	printk(KERN_EMERG "Shutting down devices\n");
 
 	down_write(&devices_subsys.rwsem);
-	list_for_each(entry,&devices_subsys.kset.list) {
-		struct device * dev = to_dev(entry);
+	list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) {
 		pr_debug("shutting down %s: ",dev->name);
 		if (dev->driver && dev->driver->shutdown) {
 			pr_debug("Ok\n");
diff -urN linux-2.5.70-bk16/drivers/base/sys.c linux-2.5.70-bk17/drivers/base/sys.c
--- linux-2.5.70-bk16/drivers/base/sys.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/base/sys.c	2003-06-12 04:49:56.000000000 -0700
@@ -12,7 +12,7 @@
  * add themselves as children of the system bus.
  */
 
-#define DEBUG
+#undef DEBUG
 
 #include <linux/sysdev.h>
 #include <linux/err.h>
@@ -62,6 +62,19 @@
 	.sysfs_ops	= &sysfs_ops,
 };
 
+
+int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a)
+{
+	return sysfs_create_file(&s->kobj,&a->attr);
+}
+
+
+void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a)
+{
+	sysfs_remove_file(&s->kobj,&a->attr);
+}
+
+
 /* 
  * declare system_subsys 
  */
@@ -104,9 +117,16 @@
 			   struct sysdev_driver * drv)
 {
 	down_write(&system_subsys.rwsem);
-	if (cls && kset_get(&cls->kset))
+	if (cls && kset_get(&cls->kset)) {
 		list_add_tail(&drv->entry,&cls->drivers);
-	else
+
+		/* If devices of this class already exist, tell the driver */
+		if (drv->add) {
+			struct sys_device *dev;
+			list_for_each_entry(dev, &cls->kset.list, kobj.entry)
+				drv->add(dev);
+		}
+	} else
 		list_add_tail(&drv->entry,&global_drivers);
 	up_write(&system_subsys.rwsem);
 	return 0;
@@ -123,8 +143,14 @@
 {
 	down_write(&system_subsys.rwsem);
 	list_del_init(&drv->entry);
-	if (cls)
+	if (cls) {
+		if (drv->remove) {
+			struct sys_device *dev;
+			list_for_each_entry(dev, &cls->kset.list, kobj.entry)
+				drv->remove(dev);
+		}
 		kset_put(&cls->kset);
+	}
 	up_write(&system_subsys.rwsem);
 }
 
@@ -157,7 +183,7 @@
 	if (!error) {
 		struct sysdev_driver * drv;
 
-		down_read(&system_subsys.rwsem);
+		down_write(&system_subsys.rwsem);
 		/* Generic notification is implicit, because it's that 
 		 * code that should have called us. 
 		 */
@@ -173,7 +199,7 @@
 			if (drv->add)
 				drv->add(sysdev);
 		}
-		up_read(&system_subsys.rwsem);
+		up_write(&system_subsys.rwsem);
 	}
 	return error;
 }
@@ -182,7 +208,7 @@
 {
 	struct sysdev_driver * drv;
 
-	down_read(&system_subsys.rwsem);
+	down_write(&system_subsys.rwsem);
 	list_for_each_entry(drv,&global_drivers,entry) {
 		if (drv->remove)
 			drv->remove(sysdev);
@@ -192,7 +218,10 @@
 		if (drv->remove)
 			drv->remove(sysdev);
 	}
-	up_read(&system_subsys.rwsem);
+
+	list_del_init(&sysdev->entry);
+
+	up_write(&system_subsys.rwsem);
 
 	kobject_unregister(&sysdev->kobj);
 }
diff -urN linux-2.5.70-bk16/drivers/block/loop.c linux-2.5.70-bk17/drivers/block/loop.c
--- linux-2.5.70-bk16/drivers/block/loop.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/block/loop.c	2003-06-12 04:49:56.000000000 -0700
@@ -120,12 +120,6 @@
 	return 0;
 }
 
-static int none_status(struct loop_device *lo, const struct loop_info64 *info)
-{
-	lo->lo_flags |= LO_FLAGS_BH_REMAP;
-	return 0;
-}
-
 static int xor_status(struct loop_device *lo, const struct loop_info64 *info)
 {
 	if (info->lo_encrypt_key_size <= 0)
@@ -136,7 +130,6 @@
 struct loop_func_table none_funcs = { 
 	.number = LO_CRYPT_NONE,
 	.transfer = transfer_none,
-	.init = none_status,
 }; 	
 
 struct loop_func_table xor_funcs = { 
@@ -439,18 +432,47 @@
 	return 0;
 }
 
-static struct bio *loop_get_buffer(struct loop_device *lo, struct bio *rbh)
+static struct bio *loop_copy_bio(struct bio *rbh)
 {
 	struct bio *bio;
+	struct bio_vec *bv;
+	int i;
+
+	bio = bio_alloc(__GFP_NOWARN, rbh->bi_vcnt);
+	if (!bio)
+		return NULL;
 
 	/*
-	 * for xfer_funcs that can operate on the same bh, do that
+	 * iterate iovec list and alloc pages
 	 */
-	if (lo->lo_flags & LO_FLAGS_BH_REMAP) {
-		bio = rbh;
-		goto out_bh;
+	__bio_for_each_segment(bv, rbh, i, 0) {
+		struct bio_vec *bbv = &bio->bi_io_vec[i];
+
+		bbv->bv_page = alloc_page(__GFP_NOWARN|__GFP_HIGHMEM);
+		if (bbv->bv_page == NULL)
+			goto oom;
+
+		bbv->bv_len = bv->bv_len;
+		bbv->bv_offset = bv->bv_offset;
 	}
 
+	bio->bi_vcnt = rbh->bi_vcnt;
+	bio->bi_size = rbh->bi_size;
+
+	return bio;
+
+oom:
+	while (--i >= 0)
+		__free_page(bio->bi_io_vec[i].bv_page);
+
+	bio_put(bio);
+	return NULL;
+}
+
+static struct bio *loop_get_buffer(struct loop_device *lo, struct bio *rbh)
+{
+	struct bio *bio;
+
 	/*
 	 * When called on the page reclaim -> writepage path, this code can
 	 * trivially consume all memory.  So we drop PF_MEMALLOC to avoid
@@ -461,17 +483,16 @@
 		int flags = current->flags;
 
 		current->flags &= ~PF_MEMALLOC;
-		bio = bio_copy(rbh, (GFP_ATOMIC & ~__GFP_HIGH) | __GFP_NOWARN,
-					rbh->bi_rw & WRITE);
-		current->flags = flags;
+		bio = loop_copy_bio(rbh);
+		if (flags & PF_MEMALLOC)
+			current->flags |= PF_MEMALLOC;
+
 		if (bio == NULL)
 			blk_congestion_wait(WRITE, HZ/10);
 	} while (bio == NULL);
 
 	bio->bi_end_io = loop_end_io_transfer;
 	bio->bi_private = rbh;
-
-out_bh:
 	bio->bi_sector = rbh->bi_sector + (lo->lo_offset >> 9);
 	bio->bi_rw = rbh->bi_rw;
 	bio->bi_bdev = lo->lo_device;
@@ -479,9 +500,8 @@
 	return bio;
 }
 
-static int
-bio_transfer(struct loop_device *lo, struct bio *to_bio,
-			      struct bio *from_bio)
+static int loop_transfer_bio(struct loop_device *lo,
+			     struct bio *to_bio, struct bio *from_bio)
 {
 	unsigned long IV = loop_get_iv(lo, from_bio->bi_sector);
 	struct bio_vec *from_bvec, *to_bvec;
@@ -508,7 +528,6 @@
 {
 	struct bio *new_bio = NULL;
 	struct loop_device *lo = q->queuedata;
-	unsigned long IV;
 	int rw = bio_rw(old_bio);
 
 	if (!lo)
@@ -530,8 +549,6 @@
 		goto err;
 	}
 
-	blk_queue_bounce(q, &old_bio);
-
 	/*
 	 * file backed, queue for loop_thread to handle
 	 */
@@ -544,9 +561,8 @@
 	 * piggy old buffer on original, and submit for I/O
 	 */
 	new_bio = loop_get_buffer(lo, old_bio);
-	IV = loop_get_iv(lo, old_bio->bi_sector);
 	if (rw == WRITE) {
-		if (bio_transfer(lo, new_bio, old_bio))
+		if (loop_transfer_bio(lo, new_bio, old_bio))
 			goto err;
 	}
 
@@ -578,7 +594,7 @@
 	} else {
 		struct bio *rbh = bio->bi_private;
 
-		ret = bio_transfer(lo, bio, rbh);
+		ret = loop_transfer_bio(lo, bio, rbh);
 
 		bio_endio(rbh, rbh->bi_size, ret);
 		loop_put_buffer(bio);
@@ -714,7 +730,7 @@
 		goto out_putf;
 	}
 	lo->old_gfp_mask = inode->i_mapping->gfp_mask;
-	inode->i_mapping->gfp_mask = GFP_NOIO;
+	inode->i_mapping->gfp_mask &= ~(__GFP_IO|__GFP_FS);
 
 	set_blocksize(bdev, lo_blocksize);
 
@@ -725,7 +741,6 @@
 	 * device
 	 */
 	blk_queue_make_request(&lo->lo_queue, loop_make_request);
-	blk_queue_bounce_limit(&lo->lo_queue, BLK_BOUNCE_HIGH);
 	lo->lo_queue.queuedata = lo;
 
 	/*
diff -urN linux-2.5.70-bk16/drivers/char/agp/amd-k8-agp.c linux-2.5.70-bk17/drivers/char/agp/amd-k8-agp.c
--- linux-2.5.70-bk16/drivers/char/agp/amd-k8-agp.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/agp/amd-k8-agp.c	2003-06-12 04:49:56.000000000 -0700
@@ -278,12 +278,13 @@
 		default:	revstring="??";
 				break;
 		}
-		printk ("Detected AMD 8151 AGP Bridge rev %s", revstring);
+		printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring);
 		/*
 		 * Work around errata.
 		 * Chips before B2 stepping incorrectly reporting v3.5
 		 */
 		if (rev_id < 0x13) {
+			printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n");
 			bridge->major_version = 3;
 			bridge->minor_version = 0;
 		}
diff -urN linux-2.5.70-bk16/drivers/char/agp/frontend.c linux-2.5.70-bk17/drivers/char/agp/frontend.c
--- linux-2.5.70-bk16/drivers/char/agp/frontend.c	2003-05-26 18:00:24.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/agp/frontend.c	2003-06-12 04:49:56.000000000 -0700
@@ -300,7 +300,6 @@
 	struct agp_memory *memory;
 
 	memory = agp_allocate_memory(pg_count, type);
-   	printk(KERN_DEBUG "agp_allocate_memory: %p\n", memory);
 	if (memory == NULL)
 		return NULL;
 
diff -urN linux-2.5.70-bk16/drivers/char/agp/intel-agp.c linux-2.5.70-bk17/drivers/char/agp/intel-agp.c
--- linux-2.5.70-bk16/drivers/char/agp/intel-agp.c	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/agp/intel-agp.c	2003-06-12 04:49:56.000000000 -0700
@@ -447,7 +447,7 @@
 		printk (KERN_DEBUG "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
 				pg_start,intel_i830_private.gtt_entries);
 
-		printk ("Trying to insert into local/stolen memory\n");
+		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
 		return (-EINVAL);
 	}
 
@@ -483,7 +483,7 @@
 	global_cache_flush();
 
 	if (pg_start < intel_i830_private.gtt_entries) {
-		printk ("Trying to disable local/stolen memory\n");
+		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
 		return (-EINVAL);
 	}
 
@@ -645,7 +645,7 @@
 	/* the Intel 815 chipset spec. says that bits 29-31 in the
 	* ATTBASE register are reserved -> try not to write them */
 	if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
-		printk (KERN_EMERG "gatt bus addr too high");
+		printk (KERN_EMERG PFX "gatt bus addr too high");
 		return -EINVAL;
 	}
 
diff -urN linux-2.5.70-bk16/drivers/char/agp/sworks-agp.c linux-2.5.70-bk17/drivers/char/agp/sworks-agp.c
--- linux-2.5.70-bk16/drivers/char/agp/sworks-agp.c	2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/agp/sworks-agp.c	2003-06-12 04:49:56.000000000 -0700
@@ -240,7 +240,7 @@
 	while(INREG8(serverworks_private.registers, 
 		     SVWRKS_POSTFLUSH) == 0x01) {
 		if((signed)(end - jiffies) <= 0) {
-			printk(KERN_ERR "Posted write buffer flush took more"
+			printk(KERN_ERR PFX "Posted write buffer flush took more"
 			       "then 3 seconds\n");
 		}
 	}
@@ -249,7 +249,7 @@
 	while(INREG32(serverworks_private.registers, 
 		     SVWRKS_DIRFLUSH) == 0x00000001) {
 		if((signed)(end - jiffies) <= 0) {
-			printk(KERN_ERR "TLB flush took more"
+			printk(KERN_ERR PFX "TLB flush took more"
 			       "then 3 seconds\n");
 		}
 	}
@@ -447,8 +447,7 @@
 			PCI_DEVFN(0, 1));
 	if (!bridge_dev) {
 		printk(KERN_INFO PFX "agpgart: Detected a Serverworks "
-		       "Chipset, but could not find the secondary "
-		       "device.\n");
+		       "Chipset, but could not find the secondary device.\n");
 		return -ENODEV;
 	}
 
@@ -470,8 +469,8 @@
 	if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
 		pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2);
 		if (temp2 != 0) {
-			printk("Detected 64 bit aperture address, but top "
-			       "bits are not zero.  Disabling agp\n");
+			printk(KERN_INFO PFX "Detected 64 bit aperture address, "
+			       "but top bits are not zero.  Disabling agp\n");
 			return -ENODEV;
 		}
 		serverworks_private.mm_addr_ofs = 0x18;
@@ -483,8 +482,8 @@
 		pci_read_config_dword(pdev,
 				serverworks_private.mm_addr_ofs + 4, &temp2);
 		if (temp2 != 0) {
-			printk("Detected 64 bit MMIO address, but top "
-			       "bits are not zero.  Disabling agp\n");
+			printk(KERN_INFO PFX "Detected 64 bit MMIO address, "
+			       "but top bits are not zero.  Disabling agp\n");
 			return -ENODEV;
 		}
 	}
diff -urN linux-2.5.70-bk16/drivers/char/amiserial.c linux-2.5.70-bk17/drivers/char/amiserial.c
--- linux-2.5.70-bk16/drivers/char/amiserial.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/amiserial.c	2003-06-12 04:49:56.000000000 -0700
@@ -50,7 +50,7 @@
   
 #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
 #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- tty->name, (info->flags), serial_refcount,info->count,tty->count,s)
+ tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s)
 #else
 #define DBG_CNT(s)
 #endif
@@ -102,13 +102,7 @@
 
 static char *serial_name = "Amiga-builtin serial driver";
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
-
-/* serial subtype definitions */
-#ifndef SERIAL_TYPE_NORMAL
-#define SERIAL_TYPE_NORMAL	1
-#endif
+static struct tty_driver *serial_driver;
 
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
@@ -125,11 +119,6 @@
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
 
-
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
@@ -1560,12 +1549,6 @@
 	}
 	info->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->state->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -1922,12 +1905,6 @@
 		return retval;
 	}
 
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->state->normal_termios;
-		change_speed(info, 0);
-	}
-
 #ifdef SERIAL_DEBUG_OPEN
 	printk("rs_open %s successful...", tty->name);
 #endif
@@ -2049,6 +2026,28 @@
 void unregister_serial(int line);
 
 
+static struct tty_operations serial_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.put_char = rs_put_char,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.break_ctl = rs_break,
+	.send_xchar = rs_send_xchar,
+	.wait_until_sent = rs_wait_until_sent,
+	.read_proc = rs_read_proc,
+};
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -2060,6 +2059,10 @@
 	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL))
 		return -ENODEV;
 
+	serial_driver = alloc_tty_driver(1);
+	if (!serial_driver)
+		return -ENOMEM;
+
 	/*
 	 *  We request SERDAT and SERPER only, because the serial registers are
 	 *  too spreaded over the custom register space
@@ -2073,46 +2076,20 @@
 
 	/* Initialize the tty_driver structure */
 
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.owner = THIS_MODULE;
-	serial_driver.driver_name = "amiserial";
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = 1;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = "amiserial";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_open;
-	serial_driver.close = rs_close;
-	serial_driver.write = rs_write;
-	serial_driver.put_char = rs_put_char;
-	serial_driver.flush_chars = rs_flush_chars;
-	serial_driver.write_room = rs_write_room;
-	serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	serial_driver.flush_buffer = rs_flush_buffer;
-	serial_driver.ioctl = rs_ioctl;
-	serial_driver.throttle = rs_throttle;
-	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.set_termios = rs_set_termios;
-	serial_driver.stop = rs_stop;
-	serial_driver.start = rs_start;
-	serial_driver.hangup = rs_hangup;
-	serial_driver.break_ctl = rs_break;
-	serial_driver.send_xchar = rs_send_xchar;
-	serial_driver.wait_until_sent = rs_wait_until_sent;
-	serial_driver.read_proc = rs_read_proc;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &serial_ops);
 
-	if (tty_register_driver(&serial_driver))
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 
 	state = rs_table;
@@ -2122,7 +2099,6 @@
 	state->custom_divisor = 0;
 	state->close_delay = 5*HZ/10;
 	state->closing_wait = 30*HZ;
-	state->normal_termios = serial_driver.init_termios;
 	state->icount.cts = state->icount.dsr = 
 	  state->icount.rng = state->icount.dcd = 0;
 	state->icount.rx = state->icount.tx = 0;
@@ -2174,9 +2150,10 @@
 
 	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
 	tasklet_kill(&info->tlet);
-	if ((e1 = tty_unregister_driver(&serial_driver)))
+	if ((e1 = tty_unregister_driver(serial_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       e1);
+	put_tty_driver(serial_driver);
 
 	if (info) {
 	  rs_table[0].info = NULL;
@@ -2234,7 +2211,7 @@
 static struct tty_driver *serial_console_device(struct console *c, int *index)
 {
 	*index = 0;
-	return &serial_driver;
+	return serial_driver;
 }
 
 static struct console sercons = {
diff -urN linux-2.5.70-bk16/drivers/char/cyclades.c linux-2.5.70-bk17/drivers/char/cyclades.c
--- linux-2.5.70-bk16/drivers/char/cyclades.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/cyclades.c	2003-06-12 04:49:56.000000000 -0700
@@ -712,8 +712,7 @@
 
 #define	JIFFIES_DIFF(n, j)	((j) - (n))
 
-static struct tty_driver cy_serial_driver;
-static int serial_refcount;
+static struct tty_driver *cy_serial_driver;
 
 #ifdef CONFIG_ISA
 /* This is the address lookup table. The driver will probe for
@@ -760,10 +759,6 @@
 
 static int cy_next_channel; /* next minor available */
 
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -2645,10 +2640,6 @@
         return retval;
     }
 
-    if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-	*tty->termios = info->normal_termios;
-    }
-
 #ifdef CY_DEBUG_OPEN
     printk(" cyc:cy_open done\n");/**/
 #endif
@@ -2793,12 +2784,6 @@
         return;
     }
     info->flags |= ASYNC_CLOSING;
-    /*
-     * Save the termios structure, since this port may have
-     * separate termios for callout and dialin.
-     */
-    if (info->flags & ASYNC_NORMAL_ACTIVE)
-        info->normal_termios = *tty->termios;
 
     /*
     * Now we wait for the transmit buffer to clear; and we notify
@@ -5427,6 +5412,27 @@
     extra ports are ignored.
  */
 
+static struct tty_operations cy_ops = {
+    .open = cy_open,
+    .close = cy_close,
+    .write = cy_write,
+    .put_char = cy_put_char,
+    .flush_chars = cy_flush_chars,
+    .write_room = cy_write_room,
+    .chars_in_buffer = cy_chars_in_buffer,
+    .flush_buffer = cy_flush_buffer,
+    .ioctl = cy_ioctl,
+    .throttle = cy_throttle,
+    .unthrottle = cy_unthrottle,
+    .set_termios = cy_set_termios,
+    .stop = cy_stop,
+    .start = cy_start,
+    .hangup = cy_hangup,
+    .break_ctl = cy_break,
+    .wait_until_sent = cy_wait_until_sent,
+    .read_proc = cyclades_get_proc_info,
+};
+
 int __init
 cy_init(void)
 {
@@ -5438,49 +5444,27 @@
   unsigned short chip_number;
   int nports;
 
+    cy_serial_driver = alloc_tty_driver(NR_PORTS);
+    if (!cy_serial_driver)
+	return -ENOMEM;
     show_version();
 
     /* Initialize the tty_driver structure */
     
-    memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
-    cy_serial_driver.magic = TTY_DRIVER_MAGIC;
-    cy_serial_driver.owner = THIS_MODULE;
-    cy_serial_driver.driver_name = "cyclades";
-    cy_serial_driver.name = "ttyC";
-    cy_serial_driver.major = CYCLADES_MAJOR;
-    cy_serial_driver.minor_start = 0;
-    cy_serial_driver.num = NR_PORTS;
-    cy_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-    cy_serial_driver.subtype = SERIAL_TYPE_NORMAL;
-    cy_serial_driver.init_termios = tty_std_termios;
-    cy_serial_driver.init_termios.c_cflag =
+    cy_serial_driver->owner = THIS_MODULE;
+    cy_serial_driver->driver_name = "cyclades";
+    cy_serial_driver->name = "ttyC";
+    cy_serial_driver->major = CYCLADES_MAJOR;
+    cy_serial_driver->minor_start = 0;
+    cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+    cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
+    cy_serial_driver->init_termios = tty_std_termios;
+    cy_serial_driver->init_termios.c_cflag =
             B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-    cy_serial_driver.flags = TTY_DRIVER_REAL_RAW;
-    cy_serial_driver.refcount = &serial_refcount;
-    cy_serial_driver.table = serial_table;
-    cy_serial_driver.termios = serial_termios;
-    cy_serial_driver.termios_locked = serial_termios_locked;
-
-    cy_serial_driver.open = cy_open;
-    cy_serial_driver.close = cy_close;
-    cy_serial_driver.write = cy_write;
-    cy_serial_driver.put_char = cy_put_char;
-    cy_serial_driver.flush_chars = cy_flush_chars;
-    cy_serial_driver.write_room = cy_write_room;
-    cy_serial_driver.chars_in_buffer = cy_chars_in_buffer;
-    cy_serial_driver.flush_buffer = cy_flush_buffer;
-    cy_serial_driver.ioctl = cy_ioctl;
-    cy_serial_driver.throttle = cy_throttle;
-    cy_serial_driver.unthrottle = cy_unthrottle;
-    cy_serial_driver.set_termios = cy_set_termios;
-    cy_serial_driver.stop = cy_stop;
-    cy_serial_driver.start = cy_start;
-    cy_serial_driver.hangup = cy_hangup;
-    cy_serial_driver.break_ctl = cy_break;
-    cy_serial_driver.wait_until_sent = cy_wait_until_sent;
-    cy_serial_driver.read_proc = cyclades_get_proc_info;
+    cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
+    tty_set_operations(cy_serial_driver, &cy_ops);
 
-    if (tty_register_driver(&cy_serial_driver))
+    if (tty_register_driver(cy_serial_driver))
             panic("Couldn't register Cyclades serial driver\n");
 
     for (i = 0; i < NR_CARDS; i++) {
@@ -5572,8 +5556,6 @@
                     info->default_threshold = 0;
                     info->default_timeout = 0;
 		    INIT_WORK(&info->tqueue, do_softint, info);
-                    info->normal_termios =
-		                cy_serial_driver.init_termios;
 		    init_waitqueue_head(&info->open_wait);
 		    init_waitqueue_head(&info->close_wait);
 		    init_waitqueue_head(&info->shutdown_wait);
@@ -5649,8 +5631,6 @@
                     info->default_threshold = 0;
                     info->default_timeout = 0;
 		    INIT_WORK(&info->tqueue, do_softint, info);
-                    info->normal_termios =
-		               cy_serial_driver.init_termios;
 		    init_waitqueue_head(&info->open_wait);
 		    init_waitqueue_head(&info->close_wait);
 		    init_waitqueue_head(&info->shutdown_wait);
@@ -5697,11 +5677,12 @@
 
     save_flags(flags); cli();
 
-    if ((e1 = tty_unregister_driver(&cy_serial_driver)))
+    if ((e1 = tty_unregister_driver(cy_serial_driver)))
             printk("cyc: failed to unregister Cyclades serial driver(%d)\n",
 		e1);
 
     restore_flags(flags);
+    put_tty_driver(cy_serial_driver);
 
     for (i = 0; i < NR_CARDS; i++) {
         if (cy_card[i].base_addr != 0) {
diff -urN linux-2.5.70-bk16/drivers/char/dz.c linux-2.5.70-bk17/drivers/char/dz.c
--- linux-2.5.70-bk16/drivers/char/dz.c	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/dz.c	2003-06-12 04:49:56.000000000 -0700
@@ -1090,12 +1090,6 @@
 	}
 	info->flags |= DZ_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & DZ_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify the line
 	 * discipline to only process XON/XOFF characters.
 	 */
@@ -1268,11 +1262,6 @@
 	if (retval)
 		return retval;
 
-	if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		change_speed(info);
-	}
-
 	return 0;
 }
 
@@ -1281,54 +1270,54 @@
 	printk("%s%s\n", dz_name, dz_version);
 }
 
+static struct tty_driver *serial_driver;
+
+static struct tty_operations serial_ops = {
+	.open = dz_open,
+	.close = dz_close,
+	.write = dz_write,
+	.flush_chars = dz_flush_chars,
+	.write_room = dz_write_room,
+	.chars_in_buffer = dz_chars_in_buffer,
+	.flush_buffer = dz_flush_buffer,
+	.ioctl = dz_ioctl,
+	.throttle = dz_throttle,
+	.unthrottle = dz_unthrottle,
+	.send_xchar = dz_send_xchar,
+	.set_termios = dz_set_termios,
+	.stop = dz_stop,
+	.start = dz_start,
+	.hangup = dz_hangup,
+};
 
 int __init dz_init(void)
 {
 	int i, flags;
 	struct dz_serial *info;
 
+	serial_driver = alloc_tty_driver(DZ_NB_PORT);
+	if (!serial_driver)
+		return -ENOMEM;
+
 	/* Setup base handler, and timer table. */
 	init_bh(SERIAL_BH, do_serial_bh);
 
 	show_serial_version();
 
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.owner = THIS_MODULE;
-	serial_driver.devfs_name = "tts/";
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = DZ_NB_PORT;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-
-	serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->devfs_name = "tts/";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
 	                                     CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = dz_open;
-	serial_driver.close = dz_close;
-	serial_driver.write = dz_write;
-	serial_driver.flush_chars = dz_flush_chars;
-	serial_driver.write_room = dz_write_room;
-	serial_driver.chars_in_buffer = dz_chars_in_buffer;
-	serial_driver.flush_buffer = dz_flush_buffer;
-	serial_driver.ioctl = dz_ioctl;
-	serial_driver.throttle = dz_throttle;
-	serial_driver.unthrottle = dz_unthrottle;
-	serial_driver.send_xchar = dz_send_xchar;
-	serial_driver.set_termios = dz_set_termios;
-	serial_driver.stop = dz_stop;
-	serial_driver.start = dz_start;
-	serial_driver.hangup = dz_hangup;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	tty_set_operations(serial_driver, &serial_ops);
 
-	if (tty_register_driver (&serial_driver))
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 
 	save_flags(flags); cli();
@@ -1355,7 +1344,6 @@
 		info->tqueue.data = info;
 		info->tqueue_hangup.routine = do_serial_hangup;
 		info->tqueue_hangup.data = info;
-		info->normal_termios = serial_driver.init_termios;
 		init_waitqueue_head(&info->open_wait); 
 		init_waitqueue_head(&info->close_wait); 
 
@@ -1369,7 +1357,7 @@
 		printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line,
 		       info->port, SERIAL);
 
-		tty_register_device(&serial_driver, info->line, NULL);
+		tty_register_device(serial_driver, info->line, NULL);
 	}
 
 	/* Reset the chip */
@@ -1448,7 +1436,7 @@
 static struct tty_driver *dz_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 static int __init dz_console_setup(struct console *co, char *options)
diff -urN linux-2.5.70-bk16/drivers/char/dz.h linux-2.5.70-bk17/drivers/char/dz.h
--- linux-2.5.70-bk16/drivers/char/dz.h	2003-06-12 04:49:49.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/dz.h	2003-06-12 04:49:56.000000000 -0700
@@ -156,7 +156,6 @@
   struct tty_struct       *tty;                /* tty associated */
   struct tq_struct        tqueue;              /* Queue for BH */
   struct tq_struct        tqueue_hangup;
-  struct termios          normal_termios;
   wait_queue_head_t       open_wait;
   wait_queue_head_t       close_wait;
 
@@ -166,13 +165,6 @@
 
 static struct dz_serial multi[DZ_NB_PORT];    /* Four serial lines in the DZ chip */
 static struct dz_serial *dz_console;
-static struct tty_driver serial_driver, callout_driver;
-
-static struct tty_struct *serial_table[DZ_NB_PORT];
-static struct termios *serial_termios[DZ_NB_PORT];
-static struct termios *serial_termios_locked[DZ_NB_PORT];
-
-static int serial_refcount;
 
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
diff -urN linux-2.5.70-bk16/drivers/char/epca.c linux-2.5.70-bk17/drivers/char/epca.c
--- linux-2.5.70-bk16/drivers/char/epca.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/epca.c	2003-06-12 04:49:56.000000000 -0700
@@ -82,7 +82,7 @@
 /* ----------------- Begin global definitions ------------------- */
 
 static char mesg[100];
-static int pc_refcount, nbdevs, num_cards, liloconfig;
+static int nbdevs, num_cards, liloconfig;
 static int digi_poller_inhibited = 1 ;
 
 static int setup_error_code;
@@ -97,19 +97,8 @@
 
 /* ------------- Begin structures used for driver registeration ---------- */
 
-struct tty_driver pc_driver;
-struct tty_driver pc_info;
-
-/* The below structures are used to initialize the tty_driver structures. */
-
-/*	-------------------------------------------------------------------------
-	Note : MAX_ALLOC is currently limited to 0x100.  This restriction is 
-	placed on us by Linux not Digi.
-----------------------------------------------------------------------------*/
-static struct tty_struct *pc_table[MAX_ALLOC];
-static struct termios *pc_termios[MAX_ALLOC];
-static struct termios *pc_termios_locked[MAX_ALLOC];
-
+static struct tty_driver *pc_driver;
+static struct tty_driver *pc_info;
 
 /* ------------------ Begin Digi specific structures -------------------- */
 
@@ -215,6 +204,8 @@
 static void receive_data(struct channel *);
 static int pc_ioctl(struct tty_struct *, struct file *,
                     unsigned int, unsigned long);
+static int info_ioctl(struct tty_struct *, struct file *,
+                    unsigned int, unsigned long);
 static void pc_set_termios(struct tty_struct *, struct termios *);
 static void do_softint(void *);
 static void pc_stop(struct tty_struct *);
@@ -502,12 +493,6 @@
 	struct channel *ch;
 	unsigned long flags;
 
-	if (tty->driver->subtype == SERIAL_TYPE_INFO) 
-	{
-		return;
-	}
-
-
 	/* ---------------------------------------------------------
 		verifyChannel returns the channel from the tty struct
 		if it is valid.  This serves as a sanity check.
@@ -553,14 +538,6 @@
 
 		ch->asyncflags |= ASYNC_CLOSING;
 	
-		/* -------------------------------------------------------------
-			Save the termios structure, since this port may have
-			separate termios for callout and dialin.
-		--------------------------------------------------------------- */
-
-		if (ch->asyncflags & ASYNC_NORMAL_ACTIVE)
-			ch->normal_termios = *tty->termios;
-
 		tty->closing = 1;
 
 		if (ch->asyncflags & ASYNC_INITIALIZED) 
@@ -723,13 +700,6 @@
 		brought into the driver.  
 	------------------------------------------------------------------- */
 
-	/* Stop users from hurting themselves on control minor */
-
-	if (tty->driver->subtype == SERIAL_TYPE_INFO) 
-	{
-		return (0) ;
-	}
-
 	/* ---------------------------------------------------------
 		verifyChannel returns the channel from the tty struct
 		if it is valid.  This serves as a sanity check.
@@ -1325,13 +1295,6 @@
 	volatile struct board_chan *bc;
 	volatile unsigned int head;
 
-	/* Nothing "real" happens in open of control device */
-
-	if (tty->driver->subtype == SERIAL_TYPE_INFO) 
-	{
-		return (0) ;
-	}
-
 	line = tty->index;
 	if (line < 0 || line >= nbdevs) 
 	{
@@ -1409,12 +1372,6 @@
 		the tty->termios struct otherwise let pc_close handle it.
 	-------------------------------------------------------------------- */
 
-	/* Should this be here except for SPLIT termios ? */
-	if (ch->count == 1) 
-	{
-		*tty->termios = ch->normal_termios;
-	}
-
 	save_flags(flags);
 	cli();
 
@@ -1510,13 +1467,15 @@
 	save_flags(flags);
 	cli();
 
-	if ((tty_unregister_driver(&pc_driver)) ||  
-	    (tty_unregister_driver(&pc_info)))
+	if ((tty_unregister_driver(pc_driver)) ||  
+	    (tty_unregister_driver(pc_info)))
 	{
 		printk(KERN_WARNING "<Error> - DIGI : cleanup_module failed to un-register tty driver\n");
 		restore_flags(flags);
 		return;
 	}
+	put_tty_driver(pc_driver);
+	put_tty_driver(pc_info);
 
 	for (crd = 0; crd < num_cards; crd++) 
 	{ /* Begin for each card */
@@ -1554,6 +1513,34 @@
 module_exit(epca_module_exit);
 #endif /* MODULE */
 
+static struct tty_operations pc_ops = {
+	.open = pc_open,
+	.close = pc_close,
+	.write = pc_write,
+	.write_room = pc_write_room,
+	.flush_buffer = pc_flush_buffer,
+	.chars_in_buffer = pc_chars_in_buffer,
+	.flush_chars = pc_flush_chars,
+	.put_char = pc_put_char,
+	.ioctl = pc_ioctl,
+	.set_termios = pc_set_termios,
+	.stop = pc_stop,
+	.start = pc_start,
+	.throttle = pc_throttle,
+	.unthrottle = pc_unthrottle,
+	.hangup = pc_hangup,
+};
+
+static int info_open(struct tty_struct *tty, struct file * filp)
+{
+	return 0;
+}
+
+static struct tty_operations info_ops = {
+	.open = info_open,
+	.ioctl = info_ioctl,
+};
+
 /* ------------------ Begin pc_init  ---------------------- */
 
 int __init pc_init(void)
@@ -1578,7 +1565,6 @@
 	int crd;
 	struct board_info *bd;
 	unsigned char board_id = 0;
-	
 
 #ifdef ENABLE_PCI
 	int pci_boards_found, pci_count;
@@ -1586,6 +1572,16 @@
 	pci_count = 0;
 #endif /* ENABLE_PCI */
 
+	pc_driver = alloc_tty_driver(MAX_ALLOC);
+	if (!pc_driver)
+		return -ENOMEM;
+
+	pc_info = alloc_tty_driver(MAX_ALLOC);
+	if (!pc_info) {
+		put_tty_driver(pc_driver);
+		return -ENOMEM;
+	}
+
 	/* -----------------------------------------------------------------------
 		If epca_setup has not been ran by LILO set num_cards to defaults; copy
 		board structure defined by digiConfig into drivers board structure.
@@ -1645,60 +1641,33 @@
 
 #endif /* ENABLE_PCI */
 
-	memset(&pc_driver, 0, sizeof(struct tty_driver));
-	memset(&pc_info, 0, sizeof(struct tty_driver));
-
-	pc_driver.magic = TTY_DRIVER_MAGIC;
-	pc_driver.owner = THIS_MODULE;
-	pc_driver.name = "ttyD"; 
-	pc_driver.major = DIGI_MAJOR; 
-	pc_driver.minor_start = 0;
-	pc_driver.num = MAX_ALLOC;
-	pc_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	pc_driver.subtype = SERIAL_TYPE_NORMAL;
-	pc_driver.init_termios = tty_std_termios;
-	pc_driver.init_termios.c_iflag = 0;
-	pc_driver.init_termios.c_oflag = 0;
-
-	pc_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	pc_driver.init_termios.c_lflag = 0;
-	pc_driver.flags = TTY_DRIVER_REAL_RAW;
-	pc_driver.refcount = &pc_refcount;
-	pc_driver.table = pc_table;
-	
-	/* pc_termios is an array of pointers pointing at termios structs */
-	/* The below should get the first pointer */
-	pc_driver.termios = pc_termios;
-	pc_driver.termios_locked = pc_termios_locked;
-
-	/* ------------------------------------------------------------------
-		Setup entry points for the driver.  These are primarily called by 
-		the kernel in tty_io.c and n_tty.c
-	--------------------------------------------------------------------- */
-
-	pc_driver.open = pc_open;
-	pc_driver.close = pc_close;
-	pc_driver.write = pc_write;
-	pc_driver.write_room = pc_write_room;
-	pc_driver.flush_buffer = pc_flush_buffer;
-	pc_driver.chars_in_buffer = pc_chars_in_buffer;
-	pc_driver.flush_chars = pc_flush_chars;
-	pc_driver.put_char = pc_put_char;
-	pc_driver.ioctl = pc_ioctl;
-	pc_driver.set_termios = pc_set_termios;
-	pc_driver.stop = pc_stop;
-	pc_driver.start = pc_start;
-	pc_driver.throttle = pc_throttle;
-	pc_driver.unthrottle = pc_unthrottle;
-	pc_driver.hangup = pc_hangup;
-
-	pc_info = pc_driver;
-	pc_info.name = "digi_ctl";
-	pc_info.major = DIGIINFOMAJOR;
-	pc_info.minor_start = 0;
-	pc_info.num = 1;
-	pc_info.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
-	pc_info.subtype = SERIAL_TYPE_INFO;
+	pc_driver->owner = THIS_MODULE;
+	pc_driver->name = "ttyD"; 
+	pc_driver->major = DIGI_MAJOR; 
+	pc_driver->minor_start = 0;
+	pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	pc_driver->subtype = SERIAL_TYPE_NORMAL;
+	pc_driver->init_termios = tty_std_termios;
+	pc_driver->init_termios.c_iflag = 0;
+	pc_driver->init_termios.c_oflag = 0;
+	pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+	pc_driver->init_termios.c_lflag = 0;
+	pc_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(pc_driver, &pc_ops);
+
+	pc_info->owner = THIS_MODULE;
+	pc_info->name = "digi_ctl";
+	pc_info->major = DIGIINFOMAJOR;
+	pc_info->minor_start = 0;
+	pc_info->type = TTY_DRIVER_TYPE_SERIAL;
+	pc_info->subtype = SERIAL_TYPE_INFO;
+	pc_info->init_termios = tty_std_termios;
+	pc_info->init_termios.c_iflag = 0;
+	pc_info->init_termios.c_oflag = 0;
+	pc_info->init_termios.c_lflag = 0;
+	pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+	pc_info->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(pc_info, &info_ops);
 
 
 	save_flags(flags);
@@ -1823,10 +1792,10 @@
 
 	} /* End for each card */
 
-	if (tty_register_driver(&pc_driver))
+	if (tty_register_driver(pc_driver))
 		panic("Couldn't register Digi PC/ driver");
 
-	if (tty_register_driver(&pc_info))
+	if (tty_register_driver(pc_info))
 		panic("Couldn't register Digi PC/ info ");
 
 	/* -------------------------------------------------------------------
@@ -2099,7 +2068,6 @@
 		ch->close_delay = 50;
 		ch->count = 0;
 		ch->blocked_open = 0;
-		ch->normal_termios = pc_driver.init_termios;
 		init_waitqueue_head(&ch->open_wait);
 		init_waitqueue_head(&ch->close_wait);
 		ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
@@ -2878,103 +2846,102 @@
 
 } /* End receive_data */
 
-/* --------------------- Begin pc_ioctl  ----------------------- */
-
-static int pc_ioctl(struct tty_struct *tty, struct file * file,
+static int info_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
-{ /* Begin pc_ioctl */
-
-	digiflow_t dflow;
-	int retval, error;
-	unsigned long flags;
-	unsigned int mflag, mstat;
-	unsigned char startc, stopc;
-	volatile struct board_chan *bc;
-	struct channel *ch = (struct channel *) tty->driver_data;
+{
+	int error;
 	
-	/* The control device has it's own set of commands */
-	if (tty->driver->subtype == SERIAL_TYPE_INFO) 
-	{ /* Begin if subtype is the control device */
-
-		switch (cmd) 
-		{ /* Begin switch cmd */
+	switch (cmd) 
+	{ /* Begin switch cmd */
 
-			case DIGI_GETINFO:
-			{ /* Begin case DIGI_GETINFO */
+		case DIGI_GETINFO:
+		{ /* Begin case DIGI_GETINFO */
 
-				struct digi_info di ;
-				int brd;
+			struct digi_info di ;
+			int brd;
 
-				getUser(brd, (unsigned int *)arg);
+			getUser(brd, (unsigned int *)arg);
 
-				if ((error = verify_area(VERIFY_WRITE, (char*)arg, sizeof(di))))
-				{
-					printk(KERN_ERR "DIGI_GETINFO : verify area size 0x%x failed\n",sizeof(di));
-					return(error);
-				}
+			if ((error = verify_area(VERIFY_WRITE, (char*)arg, sizeof(di))))
+			{
+				printk(KERN_ERR "DIGI_GETINFO : verify area size 0x%x failed\n",sizeof(di));
+				return(error);
+			}
 
-				if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
-					return (-ENODEV);
+			if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
+				return (-ENODEV);
 
-				memset(&di, 0, sizeof(di));
+			memset(&di, 0, sizeof(di));
 
-				di.board = brd ; 
-				di.status = boards[brd].status;
-				di.type = boards[brd].type ;
-				di.numports = boards[brd].numports ;
-				di.port = boards[brd].port ;
-				di.membase = boards[brd].membase ;
+			di.board = brd ; 
+			di.status = boards[brd].status;
+			di.type = boards[brd].type ;
+			di.numports = boards[brd].numports ;
+			di.port = boards[brd].port ;
+			di.membase = boards[brd].membase ;
 
-				if (copy_to_user((char *)arg, &di, sizeof (di)))
-					return -EFAULT;
-				break;
+			if (copy_to_user((char *)arg, &di, sizeof (di)))
+				return -EFAULT;
+			break;
 
-			} /* End case DIGI_GETINFO */
+		} /* End case DIGI_GETINFO */
 
-			case DIGI_POLLER:
-			{ /* Begin case DIGI_POLLER */
+		case DIGI_POLLER:
+		{ /* Begin case DIGI_POLLER */
 
-				int brd = arg & 0xff000000 >> 16 ; 
-				unsigned char state = arg & 0xff ; 
+			int brd = arg & 0xff000000 >> 16 ; 
+			unsigned char state = arg & 0xff ; 
 
-				if ((brd < 0) || (brd >= num_cards))
-				{
-					printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
-					return (-ENODEV);
-				}
+			if ((brd < 0) || (brd >= num_cards))
+			{
+				printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
+				return (-ENODEV);
+			}
 
-				digi_poller_inhibited = state ;
-				break ; 
+			digi_poller_inhibited = state ;
+			break ; 
 
-			} /* End case DIGI_POLLER */
+		} /* End case DIGI_POLLER */
 
-			case DIGI_INIT:
-			{ /* Begin case DIGI_INIT */
+		case DIGI_INIT:
+		{ /* Begin case DIGI_INIT */
 
-				/* ------------------------------------------------------------
-					This call is made by the apps to complete the initilization
-					of the board(s).  This routine is responsible for setting
-					the card to its initial state and setting the drivers control
-					fields to the sutianle settings for the card in question.
-				---------------------------------------------------------------- */
-			
-				int crd ; 
-				for (crd = 0; crd < num_cards; crd++) 
-					post_fep_init (crd);
+			/* ------------------------------------------------------------
+				This call is made by the apps to complete the initilization
+				of the board(s).  This routine is responsible for setting
+				the card to its initial state and setting the drivers control
+				fields to the sutianle settings for the card in question.
+			---------------------------------------------------------------- */
+		
+			int crd ; 
+			for (crd = 0; crd < num_cards; crd++) 
+				post_fep_init (crd);
 
-			 	break ; 
+			break ; 
 
-			} /* End case DIGI_INIT */
+		} /* End case DIGI_INIT */
 
 
-			default:
-				return -ENOIOCTLCMD;
+		default:
+			return -ENOIOCTLCMD;
 
-		} /* End switch cmd */
-		return (0) ;
+	} /* End switch cmd */
+	return (0) ;
+}
+/* --------------------- Begin pc_ioctl  ----------------------- */
 
-	} /* End if subtype is the control device */
+static int pc_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{ /* Begin pc_ioctl */
 
+	digiflow_t dflow;
+	int retval, error;
+	unsigned long flags;
+	unsigned int mflag, mstat;
+	unsigned char startc, stopc;
+	volatile struct board_chan *bc;
+	struct channel *ch = (struct channel *) tty->driver_data;
+	
 	if (ch)
 		bc = ch->brdchan;
 	else 
diff -urN linux-2.5.70-bk16/drivers/char/epca.h linux-2.5.70-bk17/drivers/char/epca.h
--- linux-2.5.70-bk16/drivers/char/epca.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/epca.h	2003-06-12 04:49:56.000000000 -0700
@@ -135,7 +135,6 @@
 	volatile struct board_chan  *brdchan;
 	struct digi_struct          digiext;
 	struct tty_struct           *tty;
-	struct termios              normal_termios;
 	wait_queue_head_t           open_wait;
 	wait_queue_head_t           close_wait;
 	struct work_struct            tqueue;
diff -urN linux-2.5.70-bk16/drivers/char/esp.c linux-2.5.70-bk17/drivers/char/esp.c
--- linux-2.5.70-bk16/drivers/char/esp.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/esp.c	2003-06-12 04:49:56.000000000 -0700
@@ -109,8 +109,7 @@
 
 static DECLARE_TASK_QUEUE(tq_esp);
 
-static struct tty_driver esp_driver;
-static int serial_refcount;
+static struct tty_driver *esp_driver;
 
 /* serial subtype definitions */
 #define SERIAL_TYPE_NORMAL	1
@@ -134,7 +133,7 @@
   
 #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
 #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- tty->name, (info->flags), serial_refcount,info->count,tty->count,s)
+ tty->name, (info->flags), serial_driver.refcount,info->count,tty->count,s)
 #else
 #define DBG_CNT(s)
 #endif
@@ -153,10 +152,6 @@
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
@@ -2070,12 +2065,6 @@
 	}
 	info->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -2365,11 +2354,6 @@
 		return retval;
 	}
 
-	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		change_speed(info);
-	}
-
 #ifdef SERIAL_DEBUG_OPEN
 	printk("esp_open %s successful...", tty->name);
 #endif
@@ -2458,6 +2442,26 @@
 	return (port_detected);
 }
 
+static struct tty_operations esp_ops = {
+	.open = esp_open,
+	.close = rs_close,
+	.write = rs_write,
+	.put_char = rs_put_char,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = esp_hangup,
+	.break_ctl = esp_break,
+	.wait_until_sent = rs_wait_until_sent,
+};
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -2468,6 +2472,10 @@
 	struct esp_struct * info;
 	struct esp_struct *last_primary = 0;
 	int esp[] = {0x100,0x140,0x180,0x200,0x240,0x280,0x300,0x380};
+
+	esp_driver = alloc_tty_driver(NR_PORTS);
+	if (!esp_driver)
+		return -ENOMEM;
 	
 	init_bh(ESP_BH, do_serial_bh);
 
@@ -2506,45 +2514,21 @@
 
 	/* Initialize the tty_driver structure */
 	
-	memset(&esp_driver, 0, sizeof(struct tty_driver));
-	esp_driver.magic = TTY_DRIVER_MAGIC;
-	esp_driver.owner = THIS_MODULE;
-	esp_driver.name = "ttyP";
-	esp_driver.major = ESP_IN_MAJOR;
-	esp_driver.minor_start = 0;
-	esp_driver.num = NR_PORTS;
-	esp_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	esp_driver.subtype = SERIAL_TYPE_NORMAL;
-	esp_driver.init_termios = tty_std_termios;
-	esp_driver.init_termios.c_cflag =
+	esp_driver->owner = THIS_MODULE;
+	esp_driver->name = "ttyP";
+	esp_driver->major = ESP_IN_MAJOR;
+	esp_driver->minor_start = 0;
+	esp_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	esp_driver->subtype = SERIAL_TYPE_NORMAL;
+	esp_driver->init_termios = tty_std_termios;
+	esp_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	esp_driver.flags = TTY_DRIVER_REAL_RAW;
-	esp_driver.refcount = &serial_refcount;
-	esp_driver.table = serial_table;
-	esp_driver.termios = serial_termios;
-	esp_driver.termios_locked = serial_termios_locked;
-
-	esp_driver.open = esp_open;
-	esp_driver.close = rs_close;
-	esp_driver.write = rs_write;
-	esp_driver.put_char = rs_put_char;
-	esp_driver.flush_chars = rs_flush_chars;
-	esp_driver.write_room = rs_write_room;
-	esp_driver.chars_in_buffer = rs_chars_in_buffer;
-	esp_driver.flush_buffer = rs_flush_buffer;
-	esp_driver.ioctl = rs_ioctl;
-	esp_driver.throttle = rs_throttle;
-	esp_driver.unthrottle = rs_unthrottle;
-	esp_driver.set_termios = rs_set_termios;
-	esp_driver.stop = rs_stop;
-	esp_driver.start = rs_start;
-	esp_driver.hangup = esp_hangup;
-	esp_driver.break_ctl = esp_break;
-	esp_driver.wait_until_sent = rs_wait_until_sent;
-
-	if (tty_register_driver(&esp_driver))
+	esp_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(esp_driver, &esp_ops);
+	if (tty_register_driver(esp_driver))
 	{
 		printk(KERN_ERR "Couldn't register esp serial driver");
+		put_tty_driver(esp_driver);
 		return 1;
 	}
 
@@ -2553,7 +2537,8 @@
 	if (!info)
 	{
 		printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
-		tty_unregister_driver(&esp_driver);
+		tty_unregister_driver(esp_driver);
+		put_tty_driver(esp_driver);
 		return 1;
 	}
 
@@ -2587,7 +2572,6 @@
 		info->tqueue.data = info;
 		info->tqueue_hangup.routine = do_serial_hangup;
 		info->tqueue_hangup.data = info;
-		info->normal_termios = esp_driver.init_termios;
 		info->config.rx_timeout = rx_timeout;
 		info->config.flow_on = flow_on;
 		info->config.flow_off = flow_off;
@@ -2657,10 +2641,11 @@
 	save_flags(flags);
 	cli();
 	remove_bh(ESP_BH);
-	if ((e1 = tty_unregister_driver(&esp_driver)))
+	if ((e1 = tty_unregister_driver(esp_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       e1);
 	restore_flags(flags);
+	put_tty_driver(esp_driver);
 
 	while (ports) {
 		if (ports->port) {
diff -urN linux-2.5.70-bk16/drivers/char/generic_serial.c linux-2.5.70-bk17/drivers/char/generic_serial.c
--- linux-2.5.70-bk16/drivers/char/generic_serial.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/generic_serial.c	2003-06-12 04:49:56.000000000 -0700
@@ -735,12 +735,6 @@
 	port->flags |= ASYNC_CLOSING;
 
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (port->flags & ASYNC_NORMAL_ACTIVE)
-		port->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
diff -urN linux-2.5.70-bk16/drivers/char/hvc_console.c linux-2.5.70-bk17/drivers/char/hvc_console.c
--- linux-2.5.70-bk16/drivers/char/hvc_console.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/hvc_console.c	2003-06-12 04:49:56.000000000 -0700
@@ -41,11 +41,7 @@
 
 #define TIMEOUT		((HZ + 99) / 100)
 
-struct tty_driver hvc_driver;
-static int hvc_refcount;
-static struct tty_struct *hvc_table[MAX_NR_HVC_CONSOLES];
-static struct termios *hvc_termios[MAX_NR_HVC_CONSOLES];
-static struct termios *hvc_termios_locked[MAX_NR_HVC_CONSOLES];
+static struct tty_driver *hvc_driver;
 static int hvc_offset;
 #ifdef CONFIG_MAGIC_SYSRQ
 static int sysrq_pressed;
@@ -250,46 +246,48 @@
 	}
 }
 
+static struct tty_operations hvc_ops = {
+	.open = hvc_open,
+	.close = hvc_close,
+	.write = hvc_write,
+	.hangup = hvc_hangup,
+	.write_room = hvc_write_room,
+	.chars_in_buffer = hvc_chars_in_buffer,
+};
+
 int __init hvc_init(void)
 {
+	int num = hvc_count(&hvc_offset);
 	int i;
 
-	memset(&hvc_driver, 0, sizeof(struct tty_driver));
+	if (num > MAX_NR_HVC_CONSOLES)
+		num = MAX_NR_HVC_CONSOLES;
 
-	hvc_driver.magic = TTY_DRIVER_MAGIC;
-	hvc_driver.owner = THIS_MODULE;
-	hvc_driver.driver_name = "hvc";
-	hvc_driver.name = "hvc/";
-	hvc_driver.major = HVC_MAJOR;
-	hvc_driver.minor_start = HVC_MINOR;
-	hvc_driver.num = hvc_count(&hvc_offset);
-	if (hvc_driver.num > MAX_NR_HVC_CONSOLES)
-		hvc_driver.num = MAX_NR_HVC_CONSOLES;
-	hvc_driver.type = TTY_DRIVER_TYPE_SYSTEM;
-	hvc_driver.init_termios = tty_std_termios;
-	hvc_driver.flags = TTY_DRIVER_REAL_RAW;
-	hvc_driver.refcount = &hvc_refcount;
-	hvc_driver.table = hvc_table;
-	hvc_driver.termios = hvc_termios;
-	hvc_driver.termios_locked = hvc_termios_locked;
-
-	hvc_driver.open = hvc_open;
-	hvc_driver.close = hvc_close;
-	hvc_driver.write = hvc_write;
-	hvc_driver.hangup = hvc_hangup;
-	hvc_driver.write_room = hvc_write_room;
-	hvc_driver.chars_in_buffer = hvc_chars_in_buffer;
-
-	for (i = 0; i < hvc_driver.num; i++) {
+	hvc_driver = alloc_tty_driver(num);
+	if (!hvc_driver)
+		return -ENOMEM;
+
+	hvc_driver->owner = THIS_MODULE;
+	hvc_driver->driver_name = "hvc";
+	hvc_driver->name = "hvc/";
+	hvc_driver->major = HVC_MAJOR;
+	hvc_driver->minor_start = HVC_MINOR;
+	hvc_driver->type = TTY_DRIVER_TYPE_SYSTEM;
+	hvc_driver->init_termios = tty_std_termios;
+	hvc_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(hvc_driver, &hvc_ops);
+	for (i = 0; i < num; i++) {
 		hvc_struct[i].lock = SPIN_LOCK_UNLOCKED;
 		hvc_struct[i].index = i;
-		tty_register_device(&hvc_driver, i, NULL);
 	}
 
-	if (tty_register_driver(&hvc_driver))
+	if (tty_register_driver(hvc_driver))
 		panic("Couldn't register hvc console driver\n");
 
-	if (hvc_driver.num > 0)
+	for (i = 0; i < num; i++)
+		tty_register_device(hvc_driver, i, NULL);
+
+	if (num > 0)
 		kernel_thread(khvcd, NULL, CLONE_KERNEL);
 
 	return 0;
@@ -333,7 +331,7 @@
 static struct tty_driver *hvc_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &hvc_driver;
+	return hvc_driver;
 }
 
 static int __init hvc_console_setup(struct console *co, char *options)
diff -urN linux-2.5.70-bk16/drivers/char/ip2/i2lib.h linux-2.5.70-bk17/drivers/char/ip2/i2lib.h
--- linux-2.5.70-bk16/drivers/char/ip2/i2lib.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/ip2/i2lib.h	2003-06-12 04:49:56.000000000 -0700
@@ -101,8 +101,6 @@
 	struct timer_list  BookmarkTimer;   // Used by i2DrainOutput
 	wait_queue_head_t pBookmarkWait;   // Used by i2DrainOutput
 
-	struct termios NormalTermios;
-
 	int      BaudBase;
 	int      BaudDivisor;
 
diff -urN linux-2.5.70-bk16/drivers/char/ip2main.c linux-2.5.70-bk17/drivers/char/ip2main.c
--- linux-2.5.70-bk16/drivers/char/ip2main.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/ip2main.c	2003-06-12 04:49:56.000000000 -0700
@@ -295,9 +295,7 @@
 /* Static Data */
 /***************/
 
-static struct tty_driver ip2_tty_driver;
-
-static int ref_count;
+static struct tty_driver *ip2_tty_driver;
 
 /* Here, then is a table of board pointers which the interrupt routine should
  * scan through to determine who it must service.
@@ -310,10 +308,6 @@
 //DevTableMem just used to save addresses for kfree
 static void  *DevTableMem[IP2_MAX_BOARDS];
 
-static struct tty_struct * TtyTable[IP2_MAX_PORTS];
-static struct termios    * Termios[IP2_MAX_PORTS];
-static struct termios    * TermiosLocked[IP2_MAX_PORTS];
-
 /* This is the driver descriptor for the ip2ipl device, which is used to
  * download the loadware to the boards.
  */
@@ -354,7 +348,7 @@
 
 #if defined(MODULE) && defined(IP2DEBUG_OPEN)
 #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
-		    tty->name,(pCh->flags),ref_count, \
+		    tty->name,(pCh->flags),ip2_tty_driver->refcount, \
 		    tty->count,/*GET_USE_COUNT(module)*/0,s)
 #else
 #define DBG_CNT(s)
@@ -508,9 +502,10 @@
 		}
 	}
 	devfs_remove("ip2");
-	if ( ( err = tty_unregister_driver ( &ip2_tty_driver ) ) ) {
+	if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
 		printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
 	}
+	put_tty_driver(ip2_tty_driver);
 	if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) {
 		printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err);
 	}
@@ -537,6 +532,26 @@
 }
 #endif /* MODULE */
 
+static struct tty_operations ip2_ops = {
+	.open            = ip2_open,
+	.close           = ip2_close,
+	.write           = ip2_write,
+	.put_char        = ip2_putchar,
+	.flush_chars     = ip2_flush_chars,
+	.write_room      = ip2_write_room,
+	.chars_in_buffer = ip2_chars_in_buf,
+	.flush_buffer    = ip2_flush_buffer,
+	.ioctl           = ip2_ioctl,
+	.throttle        = ip2_throttle,
+	.unthrottle      = ip2_unthrottle,
+	.set_termios     = ip2_set_termios,
+	.set_ldisc       = ip2_set_line_discipline,
+	.stop            = ip2_stop,
+	.start           = ip2_start,
+	.hangup          = ip2_hangup,
+	.read_proc       = ip2_read_proc,
+};
+
 /******************************************************************************/
 /* Function:   ip2_loadmain()                                                 */
 /* Parameters: irq, io from command line of insmod et. al.                    */
@@ -611,15 +626,16 @@
 	}
 	loaded++;
 
+	ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
+	if (!ip2_tty_driver)
+		return -ENOMEM;
+
 	/* Initialise the iiEllis subsystem. */
 	iiEllisInit();
 
 	/* Initialize arrays. */
 	memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable );
 	memset( DevTable, 0, sizeof DevTable );
-	memset( TtyTable, 0, sizeof TtyTable );
-	memset( Termios, 0, sizeof Termios );
-	memset( TermiosLocked, 0, sizeof TermiosLocked );
 
 	/* Initialise all the boards we can find (up to the maximum). */
 	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
@@ -768,54 +784,26 @@
 
 	ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 );
 
-	/* Zero out the normal tty device structure. */
-	memset ( &ip2_tty_driver, 0, sizeof ip2_tty_driver );
-
-	/* Initialise the relevant fields. */
-	ip2_tty_driver.magic                = TTY_DRIVER_MAGIC;
-	ip2_tty_driver.owner		    = THIS_MODULE;
-	ip2_tty_driver.name                 = "ttyF";
-	ip2_tty_driver.devfs_name	    = "tts/F";
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
-	ip2_tty_driver.driver_name          = pcDriver_name;
-	ip2_tty_driver.read_proc          	= ip2_read_proc;
-#endif
-	ip2_tty_driver.major                = IP2_TTY_MAJOR;
-	ip2_tty_driver.minor_start          = 0;
-	ip2_tty_driver.num                  = IP2_MAX_PORTS;
-	ip2_tty_driver.type                 = TTY_DRIVER_TYPE_SERIAL;
-	ip2_tty_driver.subtype              = SERIAL_TYPE_NORMAL;
-	ip2_tty_driver.init_termios         = tty_std_termios;
-	ip2_tty_driver.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-	ip2_tty_driver.flags                = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-	ip2_tty_driver.refcount             = &ref_count;
-	ip2_tty_driver.table                = TtyTable;
-	ip2_tty_driver.termios              = Termios;
-	ip2_tty_driver.termios_locked       = TermiosLocked;
-
-	/* Setup the pointers to the implemented functions. */
-	ip2_tty_driver.open            = ip2_open;
-	ip2_tty_driver.close           = ip2_close;
-	ip2_tty_driver.write           = ip2_write;
-	ip2_tty_driver.put_char        = ip2_putchar;
-	ip2_tty_driver.flush_chars     = ip2_flush_chars;
-	ip2_tty_driver.write_room      = ip2_write_room;
-	ip2_tty_driver.chars_in_buffer = ip2_chars_in_buf;
-	ip2_tty_driver.flush_buffer    = ip2_flush_buffer;
-	ip2_tty_driver.ioctl           = ip2_ioctl;
-	ip2_tty_driver.throttle        = ip2_throttle;
-	ip2_tty_driver.unthrottle      = ip2_unthrottle;
-	ip2_tty_driver.set_termios     = ip2_set_termios;
-	ip2_tty_driver.set_ldisc       = ip2_set_line_discipline;
-	ip2_tty_driver.stop            = ip2_stop;
-	ip2_tty_driver.start           = ip2_start;
-	ip2_tty_driver.hangup          = ip2_hangup;
+	ip2_tty_driver->owner		    = THIS_MODULE;
+	ip2_tty_driver->name                 = "ttyF";
+	ip2_tty_driver->devfs_name	    = "tts/F";
+	ip2_tty_driver->driver_name          = pcDriver_name;
+	ip2_tty_driver->major                = IP2_TTY_MAJOR;
+	ip2_tty_driver->minor_start          = 0;
+	ip2_tty_driver->type                 = TTY_DRIVER_TYPE_SERIAL;
+	ip2_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
+	ip2_tty_driver->init_termios         = tty_std_termios;
+	ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
+	ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	tty_set_operations(ip2_tty_driver, &ip2_ops);
 
 	ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 );
 
 	/* Register the tty devices. */
-	if ( ( err = tty_register_driver ( &ip2_tty_driver ) ) ) {
+	if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) {
 		printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err);
+		put_tty_driver(ip2_tty_driver);
+		return -EINVAL;
 	} else
 	/* Register the IPL driver. */
 	if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) {
@@ -851,7 +839,7 @@
 			        {
 				    if ( pB->i2eChannelMap[box] & (1 << j) )
 				    {
-				        tty_register_device(&ip2_tty_driver,
+				        tty_register_device(ip2_tty_driver,
 					    j + ABS_BIGGEST_BOX *
 						    (box+i*ABS_MAX_BOXES), NULL);
 			    	    }
@@ -1629,9 +1617,6 @@
 	/* first open - Assign termios structure to port */
 	if ( tty->count == 1 ) {
 		i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-		if ( pCh->flags & ASYNC_SPLIT_TERMIOS ) {
-			*tty->termios = pCh->NormalTermios;
-		}
 		/* Now we must send the termios settings to the loadware */
 		set_params( pCh, NULL );
 	}
@@ -1691,13 +1676,6 @@
 	}
 	pCh->flags |= ASYNC_CLOSING;	// last close actually
 
-	/*
-	 * Save the termios structure, since this port may have separate termios
-	 * for callout and dialin.
-	 */
-	if (pCh->flags & ASYNC_NORMAL_ACTIVE)
-		pCh->NormalTermios = *tty->termios;
-
 	tty->closing = 1;
 
 	if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
@@ -3039,7 +3017,7 @@
 	case 13:
 		switch ( cmd ) {
 		case 64:	/* Driver - ip2stat */
-			PUT_USER(rc, ref_count, pIndex++ );
+			PUT_USER(rc, ip2_tty_driver->refcount, pIndex++ );
 			PUT_USER(rc, irq_counter, pIndex++  );
 			PUT_USER(rc, bh_counter, pIndex++  );
 			break;
diff -urN linux-2.5.70-bk16/drivers/char/isicom.c linux-2.5.70-bk17/drivers/char/isicom.c
--- linux-2.5.70-bk16/drivers/char/isicom.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/isicom.c	2003-06-12 04:49:56.000000000 -0700
@@ -73,13 +73,9 @@
 };
 MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
 
-static int isicom_refcount;
 static int prev_card = 3;	/*	start servicing isi_card[0]	*/
 static struct isi_board * irq_to_board[16];
-static struct tty_driver isicom_normal;
-static struct tty_struct * isicom_table[PORT_COUNT];
-static struct termios * isicom_termios[PORT_COUNT];
-static struct termios * isicom_termios_locked[PORT_COUNT];
+static struct tty_driver *isicom_normal;
 
 static struct isi_board isi_card[BOARD_COUNT];
 static struct isi_port  isi_ports[PORT_COUNT];
@@ -1031,14 +1027,7 @@
 #endif	
 	if ((error = block_til_ready(tty, filp, port))!=0)
 		return error;
-		
-	if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = port->normal_termios;
-		save_flags(flags); cli();
-		isicom_config_port(port);
-		restore_flags(flags);		
-	}	
-	
+
 #ifdef ISICOM_DEBUG	
 	printk(KERN_DEBUG "ISICOM: open end!!!.\n");
 #endif	
@@ -1132,13 +1121,6 @@
 		return;
 	} 	
 	port->flags |= ASYNC_CLOSING;
-	/* 
-	 * save termios struct since callout and dialin termios may be 
-	 * different.
-	 */	
-	if (port->flags & ASYNC_NORMAL_ACTIVE)
-		port->normal_termios = *tty->termios;
-	
 	tty->closing = 1;
 	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		tty_wait_until_sent(tty, port->closing_wait);
@@ -1658,49 +1640,49 @@
 		}
 }
 
+static struct tty_operations isicom_ops = {
+	.open	= isicom_open,
+	.close	= isicom_close,
+	.write	= isicom_write,
+	.put_char	= isicom_put_char,
+	.flush_chars	= isicom_flush_chars,
+	.write_room	= isicom_write_room,
+	.chars_in_buffer	= isicom_chars_in_buffer,
+	.ioctl	= isicom_ioctl,
+	.set_termios	= isicom_set_termios,
+	.throttle	= isicom_throttle,
+	.unthrottle	= isicom_unthrottle,
+	.stop	= isicom_stop,
+	.start	= isicom_start,
+	.hangup	= isicom_hangup,
+	.flush_buffer	= isicom_flush_buffer,
+};
+
 static int register_drivers(void)
 {
 	int error;
 
 	/* tty driver structure initialization */
-	memset(&isicom_normal, 0, sizeof(struct tty_driver));
-	isicom_normal.magic	= TTY_DRIVER_MAGIC;
-	isicom_normal.owner	= THIS_MODULE;
-	isicom_normal.name 	= "ttyM";
-	isicom_normal.major	= ISICOM_NMAJOR;
-	isicom_normal.minor_start	= 0;
-	isicom_normal.num	= PORT_COUNT;
-	isicom_normal.type	= TTY_DRIVER_TYPE_SERIAL;
-	isicom_normal.subtype	= SERIAL_TYPE_NORMAL;
-	isicom_normal.init_termios	= tty_std_termios;
-	isicom_normal.init_termios.c_cflag	= 
+	isicom_normal = alloc_tty_driver(PORT_COUNT);
+	if (!isicom_normal)
+		return -ENOMEM;
+
+	isicom_normal->owner	= THIS_MODULE;
+	isicom_normal->name 	= "ttyM";
+	isicom_normal->major	= ISICOM_NMAJOR;
+	isicom_normal->minor_start	= 0;
+	isicom_normal->type	= TTY_DRIVER_TYPE_SERIAL;
+	isicom_normal->subtype	= SERIAL_TYPE_NORMAL;
+	isicom_normal->init_termios	= tty_std_termios;
+	isicom_normal->init_termios.c_cflag	= 
 				B9600 | CS8 | CREAD | HUPCL |CLOCAL;
-	isicom_normal.flags	= TTY_DRIVER_REAL_RAW;
-	isicom_normal.refcount	= &isicom_refcount;
-	
-	isicom_normal.table	= isicom_table;
-	isicom_normal.termios	= isicom_termios;
-	isicom_normal.termios_locked	= isicom_termios_locked;
-	
-	isicom_normal.open	= isicom_open;
-	isicom_normal.close	= isicom_close;
-	isicom_normal.write	= isicom_write;
-	isicom_normal.put_char	= isicom_put_char;
-	isicom_normal.flush_chars	= isicom_flush_chars;
-	isicom_normal.write_room	= isicom_write_room;
-	isicom_normal.chars_in_buffer	= isicom_chars_in_buffer;
-	isicom_normal.ioctl	= isicom_ioctl;
-	isicom_normal.set_termios	= isicom_set_termios;
-	isicom_normal.throttle	= isicom_throttle;
-	isicom_normal.unthrottle	= isicom_unthrottle;
-	isicom_normal.stop	= isicom_stop;
-	isicom_normal.start	= isicom_start;
-	isicom_normal.hangup	= isicom_hangup;
-	isicom_normal.flush_buffer	= isicom_flush_buffer;
+	isicom_normal->flags	= TTY_DRIVER_REAL_RAW;
+	tty_set_operations(isicom_normal, &isicom_ops);
 	
-	if ((error=tty_register_driver(&isicom_normal))!=0) {
+	if ((error=tty_register_driver(isicom_normal))!=0) {
 		printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
 			error);
+		put_tty_driver(isicom_normal);
 		return error;
 	}
 	return 0;
@@ -1709,8 +1691,9 @@
 static void unregister_drivers(void)
 {
 	int error;
-	if (tty_unregister_driver(&isicom_normal))
+	if (tty_unregister_driver(isicom_normal))
 		printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
+	put_tty_driver(isicom_normal);
 }
 
 static int register_isr(void)
@@ -1836,7 +1819,6 @@
 			port->magic = ISICOM_MAGIC;
 			port->card = &isi_card[card];
 			port->channel = channel;		
-			port->normal_termios = isicom_normal.init_termios;
 		 	port->close_delay = 50 * HZ/100;
 		 	port->closing_wait = 3000 * HZ/100;
 			port->hangup_tq.routine = do_isicom_hangup;
diff -urN linux-2.5.70-bk16/drivers/char/istallion.c linux-2.5.70-bk17/drivers/char/istallion.c
--- linux-2.5.70-bk16/drivers/char/istallion.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/istallion.c	2003-06-12 04:49:56.000000000 -0700
@@ -170,11 +170,7 @@
 static char	*stli_drvversion = "5.6.0";
 static char	*stli_serialname = "ttyE";
 
-static struct tty_driver	stli_serial;
-static struct tty_struct	*stli_ttys[STL_MAXDEVS];
-static struct termios		*stli_termios[STL_MAXDEVS];
-static struct termios		*stli_termioslocked[STL_MAXDEVS];
-static int			stli_refcount;
+static struct tty_driver	*stli_serial;
 
 /*
  *	We will need to allocate a temporary write buffer for chars that
@@ -851,13 +847,14 @@
 		del_timer(&stli_timerlist);
 	}
 
-	i = tty_unregister_driver(&stli_serial);
+	i = tty_unregister_driver(stli_serial);
 	if (i) {
 		printk("STALLION: failed to un-register tty driver, "
 			"errno=%d,%d\n", -i);
 		restore_flags(flags);
 		return;
 	}
+	put_tty_driver(stli_serial);
 	for (i = 0; i < 4; i++)
 		devfs_remove("staliomem/%d", i);
 	devfs_remove("staliomem");
@@ -1113,11 +1110,6 @@
 			return(rc);
 	}
 	portp->flags |= ASYNC_NORMAL_ACTIVE;
-
-	if ((portp->refcount == 1) && (portp->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = portp->normaltermios;
-		stli_setport(portp);
-	}
 	return(0);
 }
 
@@ -1152,9 +1144,6 @@
 
 	portp->flags |= ASYNC_CLOSING;
 
-	if (portp->flags & ASYNC_NORMAL_ACTIVE)
-		portp->normaltermios = *tty->termios;
-
 /*
  *	May want to wait for data to drain before closing. The BUSY flag
  *	keeps track of whether we are still transmitting or not. It is
@@ -3325,7 +3314,6 @@
 		init_waitqueue_head(&portp->open_wait);
 		init_waitqueue_head(&portp->close_wait);
 		init_waitqueue_head(&portp->raw_wait);
-		portp->normaltermios = stli_deftermios;
 		panelport++;
 		if (panelport >= brdp->panels[panelnr]) {
 			panelport = 0;
@@ -5250,6 +5238,28 @@
 	return(rc);
 }
 
+static struct tty_operations stli_ops = {
+	.open = stli_open,
+	.close = stli_close,
+	.write = stli_write,
+	.put_char = stli_putchar,
+	.flush_chars = stli_flushchars,
+	.write_room = stli_writeroom,
+	.chars_in_buffer = stli_charsinbuffer,
+	.ioctl = stli_ioctl,
+	.set_termios = stli_settermios,
+	.throttle = stli_throttle,
+	.unthrottle = stli_unthrottle,
+	.stop = stli_stop,
+	.start = stli_start,
+	.hangup = stli_hangup,
+	.flush_buffer = stli_flushbuffer,
+	.break_ctl = stli_breakctl,
+	.wait_until_sent = stli_waituntilsent,
+	.send_xchar = stli_sendxchar,
+	.read_proc = stli_readproc,
+};
+
 /*****************************************************************************/
 
 int __init stli_init(void)
@@ -5259,6 +5269,10 @@
 
 	stli_initbrds();
 
+	stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+	if (!stli_serial)
+		return -ENOMEM;
+
 /*
  *	Allocate a temporary write buffer.
  */
@@ -5289,45 +5303,22 @@
 /*
  *	Set up the tty driver structure and register us as a driver.
  */
-	memset(&stli_serial, 0, sizeof(struct tty_driver));
-	stli_serial.magic = TTY_DRIVER_MAGIC;
-	stli_serial.owner = THIS_MODULE;
-	stli_serial.driver_name = stli_drvname;
-	stli_serial.name = stli_serialname;
-	stli_serial.major = STL_SERIALMAJOR;
-	stli_serial.minor_start = 0;
-	stli_serial.num = STL_MAXBRDS * STL_MAXPORTS;
-	stli_serial.type = TTY_DRIVER_TYPE_SERIAL;
-	stli_serial.subtype = SERIAL_TYPE_NORMAL;
-	stli_serial.init_termios = stli_deftermios;
-	stli_serial.flags = TTY_DRIVER_REAL_RAW;
-	stli_serial.refcount = &stli_refcount;
-	stli_serial.table = stli_ttys;
-	stli_serial.termios = stli_termios;
-	stli_serial.termios_locked = stli_termioslocked;
-	
-	stli_serial.open = stli_open;
-	stli_serial.close = stli_close;
-	stli_serial.write = stli_write;
-	stli_serial.put_char = stli_putchar;
-	stli_serial.flush_chars = stli_flushchars;
-	stli_serial.write_room = stli_writeroom;
-	stli_serial.chars_in_buffer = stli_charsinbuffer;
-	stli_serial.ioctl = stli_ioctl;
-	stli_serial.set_termios = stli_settermios;
-	stli_serial.throttle = stli_throttle;
-	stli_serial.unthrottle = stli_unthrottle;
-	stli_serial.stop = stli_stop;
-	stli_serial.start = stli_start;
-	stli_serial.hangup = stli_hangup;
-	stli_serial.flush_buffer = stli_flushbuffer;
-	stli_serial.break_ctl = stli_breakctl;
-	stli_serial.wait_until_sent = stli_waituntilsent;
-	stli_serial.send_xchar = stli_sendxchar;
-	stli_serial.read_proc = stli_readproc;
+	stli_serial->owner = THIS_MODULE;
+	stli_serial->driver_name = stli_drvname;
+	stli_serial->name = stli_serialname;
+	stli_serial->major = STL_SERIALMAJOR;
+	stli_serial->minor_start = 0;
+	stli_serial->type = TTY_DRIVER_TYPE_SERIAL;
+	stli_serial->subtype = SERIAL_TYPE_NORMAL;
+	stli_serial->init_termios = stli_deftermios;
+	stli_serial->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(stli_serial, &stli_ops);
 
-	if (tty_register_driver(&stli_serial))
+	if (tty_register_driver(stli_serial)) {
+		put_tty_driver(stli_serial);
 		printk(KERN_ERR "STALLION: failed to register serial driver\n");
+		return -EBUSY;
+	}
 	return(0);
 }
 
diff -urN linux-2.5.70-bk16/drivers/char/moxa.c linux-2.5.70-bk17/drivers/char/moxa.c
--- linux-2.5.70-bk16/drivers/char/moxa.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/moxa.c	2003-06-12 04:49:56.000000000 -0700
@@ -153,7 +153,7 @@
 	int asyncflags;
 	unsigned long statusflags;
 	struct tty_struct *tty;
-	struct termios normal_termios;
+	int cflag;
 	wait_queue_head_t open_wait;
 	wait_queue_head_t close_wait;
 	struct work_struct tqueue;
@@ -206,12 +206,8 @@
 
 #endif				//MODULE
 
-static struct tty_driver moxaDriver;
-static struct tty_struct *moxaTable[MAX_PORTS + 1];
-static struct termios *moxaTermios[MAX_PORTS + 1];
-static struct termios *moxaTermiosLocked[MAX_PORTS + 1];
+static struct tty_driver *moxaDriver;
 static struct moxa_str moxaChannels[MAX_PORTS];
-static int moxaRefcount;
 static unsigned char *moxaXmitBuff;
 static int moxaTimer_on;
 static struct timer_list moxaTimer;
@@ -312,14 +308,33 @@
 		if (moxaEmptyTimer_on[i])
 			del_timer(&moxaEmptyTimer[i]);
 
-	if (tty_unregister_driver(&moxaDriver))
+	if (tty_unregister_driver(moxaDriver))
 		printk("Couldn't unregister MOXA Intellio family serial driver\n");
+	put_tty_driver(moxaDriver);
 	if (verbose)
 		printk("Done\n");
 
 }
 #endif
 
+static struct tty_operations moxa_ops = {
+	.open = moxa_open,
+	.close = moxa_close,
+	.write = moxa_write,
+	.write_room = moxa_write_room,
+	.flush_buffer = moxa_flush_buffer,
+	.chars_in_buffer = moxa_chars_in_buffer,
+	.flush_chars = moxa_flush_chars,
+	.put_char = moxa_put_char,
+	.ioctl = moxa_ioctl,
+	.throttle = moxa_throttle,
+	.unthrottle = moxa_unthrottle,
+	.set_termios = moxa_set_termios,
+	.stop = moxa_stop,
+	.start = moxa_start,
+	.hangup = moxa_hangup,
+};
+
 int moxa_init(void)
 {
 	int i, n, numBoards;
@@ -327,43 +342,24 @@
 	int ret1, ret2;
 
 	printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION);
+	moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
+	if (!moxaDriver)
+		return -ENOMEM;
 
 	init_MUTEX(&moxaBuffSem);
-	memset(&moxaDriver, 0, sizeof(struct tty_driver));
-	moxaDriver.magic = TTY_DRIVER_MAGIC;
-	moxaDriver.owner = THIS_MODULE;
-	moxaDriver.name = "ttya";
-	moxaDriver.major = ttymajor;
-	moxaDriver.minor_start = 0;
-	moxaDriver.num = MAX_PORTS + 1;
-	moxaDriver.type = TTY_DRIVER_TYPE_SERIAL;
-	moxaDriver.subtype = SERIAL_TYPE_NORMAL;
-	moxaDriver.init_termios = tty_std_termios;
-	moxaDriver.init_termios.c_iflag = 0;
-	moxaDriver.init_termios.c_oflag = 0;
-	moxaDriver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	moxaDriver.init_termios.c_lflag = 0;
-	moxaDriver.flags = TTY_DRIVER_REAL_RAW;
-	moxaDriver.refcount = &moxaRefcount;
-	moxaDriver.table = moxaTable;
-	moxaDriver.termios = moxaTermios;
-	moxaDriver.termios_locked = moxaTermiosLocked;
-
-	moxaDriver.open = moxa_open;
-	moxaDriver.close = moxa_close;
-	moxaDriver.write = moxa_write;
-	moxaDriver.write_room = moxa_write_room;
-	moxaDriver.flush_buffer = moxa_flush_buffer;
-	moxaDriver.chars_in_buffer = moxa_chars_in_buffer;
-	moxaDriver.flush_chars = moxa_flush_chars;
-	moxaDriver.put_char = moxa_put_char;
-	moxaDriver.ioctl = moxa_ioctl;
-	moxaDriver.throttle = moxa_throttle;
-	moxaDriver.unthrottle = moxa_unthrottle;
-	moxaDriver.set_termios = moxa_set_termios;
-	moxaDriver.stop = moxa_stop;
-	moxaDriver.start = moxa_start;
-	moxaDriver.hangup = moxa_hangup;
+	moxaDriver->owner = THIS_MODULE;
+	moxaDriver->name = "ttya";
+	moxaDriver->major = ttymajor;
+	moxaDriver->minor_start = 0;
+	moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
+	moxaDriver->subtype = SERIAL_TYPE_NORMAL;
+	moxaDriver->init_termios = tty_std_termios;
+	moxaDriver->init_termios.c_iflag = 0;
+	moxaDriver->init_termios.c_oflag = 0;
+	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+	moxaDriver->init_termios.c_lflag = 0;
+	moxaDriver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(moxaDriver, &moxa_ops);
 
 	moxaXmitBuff = 0;
 
@@ -376,7 +372,7 @@
 		ch->closing_wait = 30 * HZ;
 		ch->count = 0;
 		ch->blocked_open = 0;
-		ch->normal_termios = moxaDriver.init_termios;
+		ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
 		init_waitqueue_head(&ch->open_wait);
 		init_waitqueue_head(&ch->close_wait);
 	}
@@ -392,8 +388,9 @@
 	MoxaDriverInit();
 	printk("Tty devices major number = %d\n", ttymajor);
 
-	if (tty_register_driver(&moxaDriver)) {
+	if (tty_register_driver(moxaDriver)) {
 		printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n");
+		put_tty_driver(moxaDriver);
 		return -1;
 	}
 	for (i = 0; i < MAX_PORTS; i++) {
@@ -559,9 +556,6 @@
 	ch->count++;
 	tty->driver_data = ch;
 	ch->tty = tty;
-	if (ch->count == 1 && (ch->asyncflags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = ch->normal_termios;
-	}
 	if (!(ch->asyncflags & ASYNC_INITIALIZED)) {
 		ch->statusflags = 0;
 		set_tty_param(tty);
@@ -621,12 +615,7 @@
 	}
 	ch->asyncflags |= ASYNC_CLOSING;
 
-	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (ch->asyncflags & ASYNC_NORMAL_ACTIVE)
-		ch->normal_termios = *tty->termios;
+	ch->cflag = *tty->termios->c_cflag;
 	if (ch->asyncflags & ASYNC_INITIALIZED) {
 		setup_empty_event(tty);
 		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */
@@ -1688,7 +1677,7 @@
 			}
 
 			if (!moxaChannels[i].tty || !moxaChannels[i].tty->termios)
-				GMStatus[i].cflag = moxaChannels[i].normal_termios.c_cflag;
+				GMStatus[i].cflag = moxaChannels[i].cflag;
 			else
 				GMStatus[i].cflag = moxaChannels[i].tty->termios->c_cflag;
 		}
diff -urN linux-2.5.70-bk16/drivers/char/mxser.c linux-2.5.70-bk17/drivers/char/mxser.c
--- linux-2.5.70-bk16/drivers/char/mxser.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/mxser.c	2003-06-12 04:49:56.000000000 -0700
@@ -258,7 +258,7 @@
 	int xmit_tail;
 	int xmit_cnt;
 	struct work_struct tqueue;
-	struct termios normal_termios;
+	int cflag;
 	wait_queue_head_t open_wait;
 	wait_queue_head_t close_wait;
 	wait_queue_head_t delta_msr_wait;
@@ -288,12 +288,8 @@
 };
 
 
-static struct tty_driver mxvar_sdriver;
-static int mxvar_refcount;
+static struct tty_driver *mxvar_sdriver;
 static struct mxser_struct mxvar_table[MXSER_PORTS];
-static struct tty_struct *mxvar_tty[MXSER_PORTS + 1];
-static struct termios *mxvar_termios[MXSER_PORTS + 1];
-static struct termios *mxvar_termios_locked[MXSER_PORTS + 1];
 static struct mxser_log mxvar_log;
 static int mxvar_diagflag;
 /*
@@ -368,8 +364,9 @@
 
 	if (verbose)
 		printk("Unloading module mxser ...\n");
-	if ((err |= tty_unregister_driver(&mxvar_sdriver)))
+	if ((err |= tty_unregister_driver(mxvar_sdriver)))
 		printk("Couldn't unregister MOXA Smartio family serial driver\n");
+	put_tty_driver(mxvar_sdriver);
 
 	for (i = 0; i < MXSER_BOARDS; i++) {
 		if (mxsercfg[i].board_type == -1)
@@ -420,7 +417,7 @@
 		info->close_delay = 5 * HZ / 10;
 		info->closing_wait = 30 * HZ;
 		INIT_WORK(&info->tqueue, mxser_do_softint, info);
-		info->normal_termios = mxvar_sdriver.init_termios;
+		info->cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 		init_waitqueue_head(&info->delta_msr_wait);
@@ -479,6 +476,24 @@
 	return (0);
 }
 
+static struct tty_operations mxser_ops = {
+	.open = mxser_open,
+	.close = mxser_close,
+	.write = mxser_write,
+	.put_char = mxser_put_char,
+	.flush_chars = mxser_flush_chars,
+	.write_room = mxser_write_room,
+	.chars_in_buffer = mxser_chars_in_buffer,
+	.flush_buffer = mxser_flush_buffer,
+	.ioctl = mxser_ioctl,
+	.throttle = mxser_throttle,
+	.unthrottle = mxser_unthrottle,
+	.set_termios = mxser_set_termios,
+	.stop = mxser_stop,
+	.start = mxser_start,
+	.hangup = mxser_hangup,
+};
+
 static int __init mxser_module_init(void)
 {
 	int i, m, retval, b;
@@ -486,43 +501,24 @@
 	int ret1, ret2;
 	struct mxser_hwconf hwconf;
 
+	mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
+	if (!mxvar_sdriver)
+		return -ENOMEM;
+
 	printk("MOXA Smartio family driver version %s\n", MXSER_VERSION);
 
 	/* Initialize the tty_driver structure */
 
-	memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));
-	mxvar_sdriver.magic = TTY_DRIVER_MAGIC;
-	mxvar_sdriver.owner = THIS_MODULE;
-	mxvar_sdriver.name = "ttyM";
-	mxvar_sdriver.major = ttymajor;
-	mxvar_sdriver.minor_start = 0;
-	mxvar_sdriver.num = MXSER_PORTS + 1;
-	mxvar_sdriver.type = TTY_DRIVER_TYPE_SERIAL;
-	mxvar_sdriver.subtype = SERIAL_TYPE_NORMAL;
-	mxvar_sdriver.init_termios = tty_std_termios;
-	mxvar_sdriver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	mxvar_sdriver.flags = TTY_DRIVER_REAL_RAW;
-	mxvar_sdriver.refcount = &mxvar_refcount;
-	mxvar_sdriver.table = mxvar_tty;
-	mxvar_sdriver.termios = mxvar_termios;
-	mxvar_sdriver.termios_locked = mxvar_termios_locked;
-
-	mxvar_sdriver.open = mxser_open;
-	mxvar_sdriver.close = mxser_close;
-	mxvar_sdriver.write = mxser_write;
-	mxvar_sdriver.put_char = mxser_put_char;
-	mxvar_sdriver.flush_chars = mxser_flush_chars;
-	mxvar_sdriver.write_room = mxser_write_room;
-	mxvar_sdriver.chars_in_buffer = mxser_chars_in_buffer;
-	mxvar_sdriver.flush_buffer = mxser_flush_buffer;
-	mxvar_sdriver.ioctl = mxser_ioctl;
-	mxvar_sdriver.throttle = mxser_throttle;
-	mxvar_sdriver.unthrottle = mxser_unthrottle;
-	mxvar_sdriver.set_termios = mxser_set_termios;
-	mxvar_sdriver.stop = mxser_stop;
-	mxvar_sdriver.start = mxser_start;
-	mxvar_sdriver.hangup = mxser_hangup;
-
+	mxvar_sdriver->owner = THIS_MODULE;
+	mxvar_sdriver->name = "ttyM";
+	mxvar_sdriver->major = ttymajor;
+	mxvar_sdriver->minor_start = 0;
+	mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
+	mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
+	mxvar_sdriver->init_termios = tty_std_termios;
+	mxvar_sdriver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(mxvar_sdriver, &mxser_ops);
 	printk("Tty devices major number = %d\n", ttymajor);
 
 	mxvar_diagflag = 0;
@@ -648,9 +644,10 @@
 	}
 
 
-	if (!tty_register_driver(&mxvar_sdriver))
+	if (!tty_register_driver(mxvar_sdriver))
 		return 0;
 
+	put_tty_driver(mxvar_sdriver);
 	printk("Couldn't install MOXA Smartio family driver !\n");
 
 	for (i = 0; i < MXSER_BOARDS; i++) {
@@ -722,15 +719,7 @@
 	if (retval)
 		return (retval);
 
-	retval = mxser_block_til_ready(tty, filp, info);
-	if (retval)
-		return (retval);
-
-	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		mxser_change_speed(info, 0);
-	}
-	return (0);
+	return mxser_block_til_ready(tty, filp, info);
 }
 
 /*
@@ -780,12 +769,7 @@
 		return;
 	}
 	info->flags |= ASYNC_CLOSING;
-	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
+	info->cflag = tty->termios->c_cflag;
 	/*
 	 * Now we wait for the transmit buffer to clear; and we notify
 	 * the line discipline to only process XON/XOFF characters.
@@ -1140,7 +1124,7 @@
 				continue;
 			}
 			if (!mxvar_table[i].tty || !mxvar_table[i].tty->termios)
-				GMStatus[i].cflag = mxvar_table[i].normal_termios.c_cflag;
+				GMStatus[i].cflag = mxvar_table[i].cflag;
 			else
 				GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag;
 
diff -urN linux-2.5.70-bk16/drivers/char/pcmcia/synclink_cs.c linux-2.5.70-bk17/drivers/char/pcmcia/synclink_cs.c
--- linux-2.5.70-bk16/drivers/char/pcmcia/synclink_cs.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/pcmcia/synclink_cs.c	2003-06-12 04:49:56.000000000 -0700
@@ -154,8 +154,6 @@
 	
 	struct mgsl_icount	icount;
 	
-	struct termios		normal_termios;
-	
 	struct tty_struct 	*tty;
 	int			timeout;
 	int			x_char;		/* xon/xoff character */
@@ -497,8 +495,7 @@
 static char *driver_name = "SyncLink PC Card driver";
 static char *driver_version = "$Revision: 4.10 $";
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
@@ -506,10 +503,6 @@
 static void mgslpc_change_params(MGSLPC_INFO *info);
 static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
 
-static struct tty_struct *serial_table[MAX_DEVICE_COUNT];
-static struct termios *serial_termios[MAX_DEVICE_COUNT];
-static struct termios *serial_termios_locked[MAX_DEVICE_COUNT];
-
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
@@ -611,12 +604,6 @@
 
     mgslpc_add_device(info);
 
-    memset(serial_table,0,sizeof(struct tty_struct*)*MAX_DEVICE_COUNT);
-    memset(serial_termios,0,sizeof(struct termios*)*MAX_DEVICE_COUNT);
-    memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_DEVICE_COUNT);
-
-    info->normal_termios  = serial_driver.init_termios;
-
     return link;
 }
 
@@ -2580,12 +2567,6 @@
 	
 	info->flags |= ASYNC_CLOSING;
 	
-	/* Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-
 	/* set tty->closing to notify line discipline to 
 	 * only process XON/XOFF characters. Only the N_TTY
 	 * discipline appears to use this (ppp does not).
@@ -2891,12 +2872,6 @@
 		goto cleanup;
 	}
 
-	if ((info->count == 1) &&
-	    info->flags & ASYNC_SPLIT_TERMIOS) {
-		*tty->termios = info->normal_termios;
-		mgslpc_change_params(info);
-	}
-	
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_open(%s) success\n",
 			 __FILE__,__LINE__, info->device_name);
@@ -3140,6 +3115,30 @@
 	.detach		= mgslpc_detach,
 };
 
+static struct tty_operations mgslpc_ops = {
+	.open = mgslpc_open,
+	.close = mgslpc_close,
+	.write = mgslpc_write,
+	.put_char = mgslpc_put_char,
+	.flush_chars = mgslpc_flush_chars,
+	.write_room = mgslpc_write_room,
+	.chars_in_buffer = mgslpc_chars_in_buffer,
+	.flush_buffer = mgslpc_flush_buffer,
+	.ioctl = mgslpc_ioctl,
+	.throttle = mgslpc_throttle,
+	.unthrottle = mgslpc_unthrottle,
+	.send_xchar = mgslpc_send_xchar,
+	.break_ctl = mgslpc_break,
+	.wait_until_sent = mgslpc_wait_until_sent,
+	.read_proc = mgslpc_read_proc,
+	.set_termios = mgslpc_set_termios,
+	.stop = tx_pause,
+	.start = tx_release,
+	.hangup = mgslpc_hangup,
+	.tiocmget = tiocmget,
+	.tiocmset = tiocmset,
+};
+
 static int __init synclink_cs_init(void)
 {
     int error;
@@ -3151,60 +3150,38 @@
 
     printk("%s %s\n", driver_name, driver_version);
 
+    serial_driver = alloc_tty_driver(MAX_DEVICE_COUNT);
+    if (!serial_driver)
+	    return -ENOMEM;
+
     error = pcmcia_register_driver(&mgslpc_driver);
-    if (error)
+    if (error) {
+	    put_tty_driver(serial_driver);
 	    return error;
+    }
 
     /* Initialize the tty_driver structure */
 	
-    memset(&serial_driver, 0, sizeof(struct tty_driver));
-    serial_driver.magic = TTY_DRIVER_MAGIC;
-    serial_driver.owner = THIS_MODULE;
-    serial_driver.driver_name = "synclink_cs";
-    serial_driver.name = "ttySLP";
-    serial_driver.major = ttymajor;
-    serial_driver.minor_start = 64;
-    serial_driver.num = MAX_DEVICE_COUNT;
-    serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-    serial_driver.subtype = SERIAL_TYPE_NORMAL;
-    serial_driver.init_termios = tty_std_termios;
-    serial_driver.init_termios.c_cflag =
+    serial_driver->owner = THIS_MODULE;
+    serial_driver->driver_name = "synclink_cs";
+    serial_driver->name = "ttySLP";
+    serial_driver->major = ttymajor;
+    serial_driver->minor_start = 64;
+    serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+    serial_driver->subtype = SERIAL_TYPE_NORMAL;
+    serial_driver->init_termios = tty_std_termios;
+    serial_driver->init_termios.c_cflag =
 	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-    serial_driver.flags = TTY_DRIVER_REAL_RAW;
-    serial_driver.refcount = &serial_refcount;
-    serial_driver.table = serial_table;
-    serial_driver.termios = serial_termios;
-    serial_driver.termios_locked = serial_termios_locked;
-
-    serial_driver.open = mgslpc_open;
-    serial_driver.close = mgslpc_close;
-    serial_driver.write = mgslpc_write;
-    serial_driver.put_char = mgslpc_put_char;
-    serial_driver.flush_chars = mgslpc_flush_chars;
-    serial_driver.write_room = mgslpc_write_room;
-    serial_driver.chars_in_buffer = mgslpc_chars_in_buffer;
-    serial_driver.flush_buffer = mgslpc_flush_buffer;
-    serial_driver.ioctl = mgslpc_ioctl;
-    serial_driver.throttle = mgslpc_throttle;
-    serial_driver.unthrottle = mgslpc_unthrottle;
-    serial_driver.send_xchar = mgslpc_send_xchar;
-    serial_driver.break_ctl = mgslpc_break;
-    serial_driver.wait_until_sent = mgslpc_wait_until_sent;
-    serial_driver.read_proc = mgslpc_read_proc;
-    serial_driver.set_termios = mgslpc_set_termios;
-    serial_driver.stop = tx_pause;
-    serial_driver.start = tx_release;
-    serial_driver.hangup = mgslpc_hangup;
-    serial_driver.tiocmget = tiocmget;
-    serial_driver.tiocmset = tiocmset;
-	
-    if (tty_register_driver(&serial_driver) < 0)
+    serial_driver->flags = TTY_DRIVER_REAL_RAW;
+    tty_set_operations(serial_driver, &mgslpc_ops);
+
+    if (tty_register_driver(serial_driver) < 0)
 	    printk("%s(%d):Couldn't register serial driver\n",
 		   __FILE__,__LINE__);
 			
     printk("%s %s, tty major#%d\n",
 	   driver_name, driver_version,
-	   serial_driver.major);
+	   serial_driver->major);
 	
     return 0;
 }
@@ -3218,9 +3195,10 @@
 	while(mgslpc_device_list)
 		mgslpc_remove_device(mgslpc_device_list);
 
-	if ((rc = tty_unregister_driver(&serial_driver)))
+	if ((rc = tty_unregister_driver(serial_driver)))
 		printk("%s(%d) failed to unregister tty driver err=%d\n",
 		       __FILE__,__LINE__,rc);
+	put_tty_driver(serial_driver);
 
 	pcmcia_unregister_driver(&mgslpc_driver);
 
diff -urN linux-2.5.70-bk16/drivers/char/pcxx.c linux-2.5.70-bk17/drivers/char/pcxx.c
--- linux-2.5.70-bk16/drivers/char/pcxx.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/pcxx.c	2003-06-12 04:49:56.000000000 -0700
@@ -129,9 +129,6 @@
 static int nbdevs = 0;
  
 static struct channel    *digi_channels;
-static struct tty_struct **pcxe_table;
-static struct termios    **pcxe_termios;
-static struct termios    **pcxe_termios_locked;
  
 int pcxx_ncook=sizeof(pcxx_cook);
 int pcxx_nbios=sizeof(pcxx_bios);
@@ -143,8 +140,7 @@
 #define SERIAL_TYPE_NORMAL	1
 #define PCXE_EVENT_HANGUP   1
 
-struct tty_driver pcxe_driver;
-static int pcxe_refcount;
+static struct tty_driver *pcxe_driver;
 
 static struct timer_list pcxx_timer;
 
@@ -236,14 +232,12 @@
 	del_timer_sync(&pcxx_timer);
 	remove_bh(DIGI_BH);
 
-	if ((e1 = tty_unregister_driver(&pcxe_driver)))
+	if ((e1 = tty_unregister_driver(pcxe_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n", e1);
 
+	put_tty_driver(pcxe_driver);
 	cleanup_board_resources();
 	kfree(digi_channels);
-	kfree(pcxe_termios_locked);
-	kfree(pcxe_termios);
-	kfree(pcxe_table);
 	restore_flags(flags);
 }
 #endif
@@ -478,16 +472,6 @@
 	}
 	ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
  	
-	save_flags(flags);
-	cli();
-	if((ch->count == 1) && (ch->asyncflags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = ch->normal_termios;
-		globalwinon(ch);
-		pcxxparam(tty,ch);
-		memoff(ch);
-	}
-
-	restore_flags(flags);
 	return 0;
 } 
 
@@ -560,12 +544,6 @@
 
 		info->asyncflags |= ASYNC_CLOSING;
 	
-		/*
-		* Save the termios structure, since this port may have
-		* separate termios for callout and dialin.
-		*/
-		if(info->asyncflags & ASYNC_NORMAL_ACTIVE)
-			info->normal_termios = *tty->termios;
 		tty->closing = 1;
 		if(info->asyncflags & ASYNC_INITIALIZED) {
 			setup_empty_event(tty,info);		
@@ -1049,6 +1027,24 @@
 }
 #endif
 
+static struct tty_operations pcxe_ops = {
+	.open = pcxe_open,
+	.close = pcxe_close,
+	.write = pcxe_write,
+	.put_char = pcxe_put_char,
+	.flush_chars = pcxe_flush_chars,
+	.write_room = pcxe_write_room,
+	.chars_in_buffer = pcxe_chars_in_buffer,
+	.flush_buffer = pcxe_flush_buffer,
+	.ioctl = pcxe_ioctl,
+	.throttle = pcxe_throttle,
+	.unthrottle = pcxe_unthrottle,
+	.set_termios = pcxe_set_termios,
+	.stop = pcxe_stop,
+	.start = pcxe_start,
+	.hangup = pcxe_hangup,
+};
+
 /*
  * function to initialize the driver with the given parameters, which are either
  * the default values from this file or the parameters given at boot.
@@ -1142,6 +1138,10 @@
 		return -EIO;
 	}
 
+	pcxe_driver = alloc_tty_driver(nbdevs);
+	if (!pcxe_driver)
+		return -ENOMEM;
+
 	/*
 	 * this turns out to be more memory efficient, as there are no 
 	 * unused spaces.
@@ -1149,71 +1149,26 @@
 	digi_channels = kmalloc(sizeof(struct channel) * nbdevs, GFP_KERNEL);
 	if (!digi_channels) {
 		printk(KERN_ERR "Unable to allocate digi_channel struct\n");
+		put_tty_driver(pcxe_driver);
 		return -ENOMEM;
 	}
 	memset(digi_channels, 0, sizeof(struct channel) * nbdevs);
 
-	pcxe_table =  kmalloc(sizeof(struct tty_struct *) * nbdevs, GFP_KERNEL);
-	if (!pcxe_table) {
-		printk(KERN_ERR "Unable to allocate pcxe_table struct\n");
-		goto cleanup_digi_channels;
-	}
-	memset(pcxe_table, 0, sizeof(struct tty_struct *) * nbdevs);
-
-	pcxe_termios = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
-	if (!pcxe_termios) {
-		printk(KERN_ERR "Unable to allocate pcxe_termios struct\n");
-		goto cleanup_pcxe_table;
-	}
-	memset(pcxe_termios,0,sizeof(struct termios *)*nbdevs);
-
-	pcxe_termios_locked = kmalloc(sizeof(struct termios *) * nbdevs, GFP_KERNEL);
-	if (!pcxe_termios_locked) {
-		printk(KERN_ERR "Unable to allocate pcxe_termios_locked struct\n");
-		goto cleanup_pcxe_termios;
-	}
-	memset(pcxe_termios_locked,0,sizeof(struct termios *)*nbdevs);
-
 	init_bh(DIGI_BH,do_pcxe_bh);
 
 	init_timer(&pcxx_timer);
 	pcxx_timer.function = pcxxpoll;
 
-	memset(&pcxe_driver, 0, sizeof(struct tty_driver));
-	pcxe_driver.magic = TTY_DRIVER_MAGIC;
-	pcxe_driver.owner = THIS_MODULE;
-	pcxe_driver.name = "ttyD";
-	pcxe_driver.major = DIGI_MAJOR; 
-	pcxe_driver.minor_start = 0;
-
-	pcxe_driver.num = nbdevs;
-
-	pcxe_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	pcxe_driver.subtype = SERIAL_TYPE_NORMAL;
-	pcxe_driver.init_termios = tty_std_termios;
-	pcxe_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
-	pcxe_driver.flags = TTY_DRIVER_REAL_RAW;
-	pcxe_driver.refcount = &pcxe_refcount;
-
-	pcxe_driver.table = pcxe_table;
-	pcxe_driver.termios = pcxe_termios;
-	pcxe_driver.termios_locked = pcxe_termios_locked;
-
-	pcxe_driver.open = pcxe_open;
-	pcxe_driver.close = pcxe_close;
-	pcxe_driver.write = pcxe_write;
-	pcxe_driver.put_char = pcxe_put_char;
-	pcxe_driver.flush_chars = pcxe_flush_chars;
-	pcxe_driver.write_room = pcxe_write_room;
-	pcxe_driver.chars_in_buffer = pcxe_chars_in_buffer;
-	pcxe_driver.flush_buffer = pcxe_flush_buffer;
-	pcxe_driver.ioctl = pcxe_ioctl;
-	pcxe_driver.throttle = pcxe_throttle;
-	pcxe_driver.unthrottle = pcxe_unthrottle;
-	pcxe_driver.set_termios = pcxe_set_termios;
-	pcxe_driver.stop = pcxe_stop;
-	pcxe_driver.start = pcxe_start;
-	pcxe_driver.hangup = pcxe_hangup;
+	pcxe_driver->owner = THIS_MODULE;
+	pcxe_driver->name = "ttyD";
+	pcxe_driver->major = DIGI_MAJOR; 
+	pcxe_driver->minor_start = 0;
+	pcxe_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	pcxe_driver->subtype = SERIAL_TYPE_NORMAL;
+	pcxe_driver->init_termios = tty_std_termios;
+	pcxe_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+	pcxe_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(pcxe_driver, &pcxe_ops);
 
 	for(crd=0; crd < numcards; crd++) {
 		bd = &boards[crd];
@@ -1571,7 +1526,6 @@
 			ch->close_delay = 50;
 			ch->count = 0;
 			ch->blocked_open = 0;
-			ch->normal_termios = pcxe_driver.init_termios;
 			init_waitqueue_head(&ch->open_wait);
 			init_waitqueue_head(&ch->close_wait);
 			ch->asyncflags = 0;
@@ -1596,7 +1550,7 @@
 		goto cleanup_boards;
 	}
 
-	ret = tty_register_driver(&pcxe_driver);
+	ret = tty_register_driver(pcxe_driver);
 	if(ret) {
 		printk(KERN_ERR "Couldn't register PC/Xe driver\n");
 		goto cleanup_boards;
@@ -1611,12 +1565,10 @@
 		printk(KERN_NOTICE "PC/Xx: Driver with %d card(s) ready.\n", enabled_cards);
 
 	return 0;
-cleanup_pcxe_driver:	tty_unregister_driver(&pcxe_driver);
-cleanup_boards:		cleanup_board_resources();
-			kfree(pcxe_termios_locked);
-cleanup_pcxe_termios:	kfree(pcxe_termios);
-cleanup_pcxe_table:	kfree(pcxe_table);
-cleanup_digi_channels:	kfree(digi_channels);
+cleanup_boards:
+	cleanup_board_resources();
+	kfree(digi_channels);
+	put_tty_driver(pcxe_driver);
 	return ret;
 }
 
diff -urN linux-2.5.70-bk16/drivers/char/pcxx.h linux-2.5.70-bk17/drivers/char/pcxx.h
--- linux-2.5.70-bk16/drivers/char/pcxx.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/pcxx.h	2003-06-12 04:49:56.000000000 -0700
@@ -123,7 +123,6 @@
 	ulong						c_cflag;
 	ulong						c_lflag;
 	ulong						c_oflag;
-	struct termios				normal_termios;
 	struct digi_struct			digiext;
 	ulong						dummy[8];
 };
diff -urN linux-2.5.70-bk16/drivers/char/pty.c linux-2.5.70-bk17/drivers/char/pty.c
--- linux-2.5.70-bk16/drivers/char/pty.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/pty.c	2003-06-12 04:49:56.000000000 -0700
@@ -31,37 +31,12 @@
 #include <asm/bitops.h>
 #include <linux/devpts_fs.h>
 
-struct pty_struct {
-	int	magic;
-	wait_queue_head_t open_wait;
-};
-
-#define PTY_MAGIC 0x5001
-
-static struct tty_driver pty_driver, pty_slave_driver;
-static int pty_refcount;
-
-/* Note: one set of tables for BSD and one for Unix98 */
-static struct tty_struct *pty_table[NR_PTYS];
-static struct termios *pty_termios[NR_PTYS];
-static struct termios *pty_termios_locked[NR_PTYS];
-static struct tty_struct *ttyp_table[NR_PTYS];
-static struct termios *ttyp_termios[NR_PTYS];
-static struct termios *ttyp_termios_locked[NR_PTYS];
-static struct pty_struct pty_state[NR_PTYS];
+static struct tty_driver *pty_driver, *pty_slave_driver;
 
 #ifdef CONFIG_UNIX98_PTYS
 /* These are global because they are accessed in tty_io.c */
-struct tty_driver ptm_driver;
-struct tty_driver pts_driver;
-
-static struct tty_struct *ptm_table[UNIX98_NR_MAJORS*NR_PTYS];
-static struct termios *ptm_termios[UNIX98_NR_MAJORS*NR_PTYS];
-static struct termios *ptm_termios_locked[UNIX98_NR_MAJORS*NR_PTYS];
-static struct tty_struct *pts_table[UNIX98_NR_MAJORS*NR_PTYS];
-static struct termios *pts_termios[UNIX98_NR_MAJORS*NR_PTYS];
-static struct termios *pts_termios_locked[UNIX98_NR_MAJORS*NR_PTYS];
-static struct pty_struct ptm_state[UNIX98_NR_MAJORS*NR_PTYS];
+struct tty_driver *ptm_driver;
+struct tty_driver *pts_driver;
 #endif
 
 static void pty_close(struct tty_struct * tty, struct file * filp)
@@ -87,7 +62,7 @@
 	if (tty->driver->subtype == PTY_TYPE_MASTER) {
 		set_bit(TTY_OTHER_CLOSED, &tty->flags);
 #ifdef CONFIG_UNIX98_PTYS
-		if (tty->driver == &ptm_driver)
+		if (tty->driver == ptm_driver)
 			devpts_pty_kill(tty->index);
 #endif
 		tty_vhangup(tty->link);
@@ -300,16 +275,10 @@
 
 static int pty_open(struct tty_struct *tty, struct file * filp)
 {
-	int	retval;
-	int	line;
-	struct	pty_struct *pty;
+	int	retval = -ENODEV;
 
-	retval = -ENODEV;
 	if (!tty || !tty->link)
 		goto out;
-	line = tty->index;
-	pty = (struct pty_struct *)(tty->driver->driver_state) + line;
-	tty->driver_data = pty;
 
 	retval = -EIO;
 	if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
@@ -320,7 +289,6 @@
 		goto out;
 
 	clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
-	wake_up_interruptible(&pty->open_wait);
 	set_bit(TTY_THROTTLED, &tty->flags);
 	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	retval = 0;
@@ -334,118 +302,114 @@
         tty->termios->c_cflag |= (CS8 | CREAD);
 }
 
+static struct tty_operations pty_ops = {
+	.open = pty_open,
+	.close = pty_close,
+	.write = pty_write,
+	.write_room = pty_write_room,
+	.flush_buffer = pty_flush_buffer,
+	.chars_in_buffer = pty_chars_in_buffer,
+	.unthrottle = pty_unthrottle,
+	.set_termios = pty_set_termios,
+};
+
 int __init pty_init(void)
 {
-	int i;
-
 	/* Traditional BSD devices */
 
-	memset(&pty_state, 0, sizeof(pty_state));
-	for (i = 0; i < NR_PTYS; i++)
-		init_waitqueue_head(&pty_state[i].open_wait);
-	memset(&pty_driver, 0, sizeof(struct tty_driver));
-	pty_driver.magic = TTY_DRIVER_MAGIC;
-	pty_driver.owner = THIS_MODULE;
-	pty_driver.driver_name = "pty_master";
-	pty_driver.name = "pty";
-	pty_driver.devfs_name = "pty/m";
-	pty_driver.major = PTY_MASTER_MAJOR;
-	pty_driver.minor_start = 0;
-	pty_driver.num = NR_PTYS;
-	pty_driver.type = TTY_DRIVER_TYPE_PTY;
-	pty_driver.subtype = PTY_TYPE_MASTER;
-	pty_driver.init_termios = tty_std_termios;
-	pty_driver.init_termios.c_iflag = 0;
-	pty_driver.init_termios.c_oflag = 0;
-	pty_driver.init_termios.c_cflag = B38400 | CS8 | CREAD;
-	pty_driver.init_termios.c_lflag = 0;
-	pty_driver.flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
-	pty_driver.refcount = &pty_refcount;
-	pty_driver.table = pty_table;
-	pty_driver.termios = pty_termios;
-	pty_driver.termios_locked = pty_termios_locked;
-	pty_driver.driver_state = pty_state;
-	pty_driver.other = &pty_slave_driver;
-
-	pty_driver.open = pty_open;
-	pty_driver.close = pty_close;
-	pty_driver.write = pty_write;
-	pty_driver.write_room = pty_write_room;
-	pty_driver.flush_buffer = pty_flush_buffer;
-	pty_driver.chars_in_buffer = pty_chars_in_buffer;
-	pty_driver.unthrottle = pty_unthrottle;
-	pty_driver.set_termios = pty_set_termios;
-
-	pty_slave_driver = pty_driver;
-	pty_slave_driver.driver_name = "pty_slave";
-	pty_slave_driver.proc_entry = 0;
-	pty_slave_driver.name = "ttyp";
-	pty_slave_driver.devfs_name = "pty/s";
-	pty_slave_driver.subtype = PTY_TYPE_SLAVE;
-	pty_slave_driver.major = PTY_SLAVE_MAJOR;
-	pty_slave_driver.minor_start = 0;
-	pty_slave_driver.init_termios = tty_std_termios;
-	pty_slave_driver.init_termios.c_cflag = B38400 | CS8 | CREAD;
-	/* Slave ptys are registered when their corresponding master pty
-	 * is opened, and unregistered when the pair is closed.
-	 */
-	pty_slave_driver.flags |= TTY_DRIVER_NO_DEVFS;
-	pty_slave_driver.table = ttyp_table;
-	pty_slave_driver.termios = ttyp_termios;
-	pty_slave_driver.termios_locked = ttyp_termios_locked;
-	pty_slave_driver.driver_state = pty_state;
-	pty_slave_driver.other = &pty_driver;
+	pty_driver = alloc_tty_driver(NR_PTYS);
+	if (!pty_driver)
+		panic("Couldn't allocate pty driver");
+
+	pty_slave_driver = alloc_tty_driver(NR_PTYS);
+	if (!pty_slave_driver)
+		panic("Couldn't allocate pty slave driver");
+
+	pty_driver->owner = THIS_MODULE;
+	pty_driver->driver_name = "pty_master";
+	pty_driver->name = "pty";
+	pty_driver->devfs_name = "pty/m";
+	pty_driver->major = PTY_MASTER_MAJOR;
+	pty_driver->minor_start = 0;
+	pty_driver->type = TTY_DRIVER_TYPE_PTY;
+	pty_driver->subtype = PTY_TYPE_MASTER;
+	pty_driver->init_termios = tty_std_termios;
+	pty_driver->init_termios.c_iflag = 0;
+	pty_driver->init_termios.c_oflag = 0;
+	pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+	pty_driver->init_termios.c_lflag = 0;
+	pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
+	pty_driver->other = pty_slave_driver;
+	tty_set_operations(pty_driver, &pty_ops);
+	pty_driver->ioctl = pty_bsd_ioctl;
+
+	pty_slave_driver->owner = THIS_MODULE;
+	pty_slave_driver->driver_name = "pty_slave";
+	pty_slave_driver->name = "ttyp";
+	pty_slave_driver->devfs_name = "pty/s";
+	pty_slave_driver->major = PTY_SLAVE_MAJOR;
+	pty_slave_driver->minor_start = 0;
+	pty_slave_driver->type = TTY_DRIVER_TYPE_PTY;
+	pty_slave_driver->subtype = PTY_TYPE_SLAVE;
+	pty_slave_driver->init_termios = tty_std_termios;
+	pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+	pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
+			TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	pty_slave_driver->other = pty_driver;
+	tty_set_operations(pty_slave_driver, &pty_ops);
 
-	if (tty_register_driver(&pty_driver))
+	if (tty_register_driver(pty_driver))
 		panic("Couldn't register pty driver");
-	if (tty_register_driver(&pty_slave_driver))
+	if (tty_register_driver(pty_slave_driver))
 		panic("Couldn't register pty slave driver");
 
-	/* 
-	 * only the master pty gets this ioctl (which is why we
-	 * assign it here, instead of up with the rest of the
-	 * pty_driver initialization. <cananian@alumni.princeton.edu>
-	 */
-	pty_driver.ioctl = pty_bsd_ioctl;
 
 	/* Unix98 devices */
 #ifdef CONFIG_UNIX98_PTYS
 	devfs_mk_dir("pts");
 	printk("pty: %d Unix98 ptys configured\n", UNIX98_NR_MAJORS*NR_PTYS);
-	ptm_driver = pty_driver;
-	ptm_driver.name = "ptm";
-	ptm_driver.proc_entry = 0;
-	ptm_driver.major = UNIX98_PTY_MASTER_MAJOR;
-	ptm_driver.minor_start = 0;
-	ptm_driver.num = UNIX98_NR_MAJORS * NR_PTYS;
-	ptm_driver.other = &pts_driver;
-	ptm_driver.flags |= TTY_DRIVER_NO_DEVFS;
-	ptm_driver.table = ptm_table;
-	ptm_driver.termios = ptm_termios;
-	ptm_driver.termios_locked = ptm_termios_locked;
-	ptm_driver.driver_state = ptm_state;
-
-	for (i = 0; i < UNIX98_NR_MAJORS*NR_PTYS; i++)
-		init_waitqueue_head(&ptm_state[i].open_wait);
-	
-	pts_driver = pty_slave_driver;
-	pts_driver.name = "pts";
-	pts_driver.proc_entry = 0;
-	pts_driver.major = UNIX98_PTY_SLAVE_MAJOR;
-	pts_driver.minor_start = 0;
-	pts_driver.num = UNIX98_NR_MAJORS * NR_PTYS;
-	pts_driver.other = &ptm_driver;
-	pts_driver.flags |= TTY_DRIVER_NO_DEVFS;
-	pts_driver.table = pts_table;
-	pts_driver.termios = pts_termios;
-	pts_driver.termios_locked = pts_termios_locked;
-	pts_driver.driver_state = ptm_state;
-	
-	ptm_driver.ioctl = pty_unix98_ioctl;
+	ptm_driver = alloc_tty_driver(UNIX98_NR_MAJORS * NR_PTYS);
+	if (!ptm_driver)
+		panic("Couldn't allocate Unix98 ptm driver");
+	pts_driver = alloc_tty_driver(UNIX98_NR_MAJORS * NR_PTYS);
+	if (!pts_driver)
+		panic("Couldn't allocate Unix98 pts driver");
+
+	ptm_driver->owner = THIS_MODULE;
+	ptm_driver->driver_name = "pty_master";
+	ptm_driver->name = "ptm";
+	ptm_driver->major = UNIX98_PTY_MASTER_MAJOR;
+	ptm_driver->minor_start = 0;
+	ptm_driver->type = TTY_DRIVER_TYPE_PTY;
+	ptm_driver->subtype = PTY_TYPE_MASTER;
+	ptm_driver->init_termios = tty_std_termios;
+	ptm_driver->init_termios.c_iflag = 0;
+	ptm_driver->init_termios.c_oflag = 0;
+	ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+	ptm_driver->init_termios.c_lflag = 0;
+	ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
+				TTY_DRIVER_NO_DEVFS;
+	ptm_driver->other = pts_driver;
+	tty_set_operations(ptm_driver, &pty_ops);
+	ptm_driver->ioctl = pty_unix98_ioctl;
+
+	pts_driver->owner = THIS_MODULE;
+	pts_driver->driver_name = "pty_slave";
+	pts_driver->name = "pts";
+	pts_driver->major = UNIX98_PTY_SLAVE_MAJOR;
+	pts_driver->minor_start = 0;
+	pts_driver->type = TTY_DRIVER_TYPE_PTY;
+	pts_driver->subtype = PTY_TYPE_SLAVE;
+	pts_driver->init_termios = tty_std_termios;
+	pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+	pts_driver->flags = TTY_DRIVER_RESET_TERMIOS |
+			TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	pts_driver->other = ptm_driver;
+	tty_set_operations(pts_driver, &pty_ops);
 	
-	if (tty_register_driver(&ptm_driver))
+	if (tty_register_driver(ptm_driver))
 		panic("Couldn't register Unix98 ptm driver");
-	if (tty_register_driver(&pts_driver))
+	if (tty_register_driver(pts_driver))
 		panic("Couldn't register Unix98 pts driver");
 #endif
 	return 0;
diff -urN linux-2.5.70-bk16/drivers/char/rio/rio_linux.c linux-2.5.70-bk17/drivers/char/rio/rio_linux.c
--- linux-2.5.70-bk16/drivers/char/rio/rio_linux.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/rio/rio_linux.c	2003-06-12 04:49:56.000000000 -0700
@@ -201,11 +201,7 @@
 
 void my_hd (void *addr, int len);
 
-static struct tty_driver rio_driver, rio_driver2;
-
-static struct tty_struct * rio_table[RIO_NPORTS];
-static struct termios ** rio_termios;
-static struct termios ** rio_termios_locked;
+static struct tty_driver *rio_driver, *rio_driver2;
 
 /* The name "p" is a bit non-descript. But that's what the rio-lynxos
 sources use all over the place. */
@@ -214,7 +210,6 @@
 /* struct rio_board boards[RIO_HOSTS]; */
 struct rio_port *rio_ports;
 
-int rio_refcount;
 int rio_initialized;
 int rio_nports;
 int rio_debug;
@@ -366,13 +361,13 @@
 
 int rio_minor(struct tty_struct *tty)
 {
-	return tty->index + (tty->driver->termios - rio_termios);
+	return tty->index + (tty->driver == rio_driver) ? 0 : 256;
 }
 
 
 int rio_ismodem(struct tty_struct *tty)
 {
-	return tty->driver == &rio_driver || tty->driver == &rio_driver2;
+	return 1;
 }
 
 
@@ -865,66 +860,77 @@
   return &vpdp;
 }
 
-
+static struct tty_operations rio_ops = {
+	.open  = riotopen,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = rio_ioctl,
+	.throttle = rio_throttle,
+	.unthrottle = rio_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+};
 
 static int rio_init_drivers(void)
 {
-  int error;
-  
-  func_enter();
-
-  memset(&rio_driver, 0, sizeof(rio_driver));
-  rio_driver.magic = TTY_DRIVER_MAGIC;
-  rio_driver.owner = THIS_MODULE;
-  rio_driver.driver_name = "specialix_rio";
-  rio_driver.name = "ttySR";
-  rio_driver.major = RIO_NORMAL_MAJOR0;
-  rio_driver.num = 256;
-  rio_driver.type = TTY_DRIVER_TYPE_SERIAL;
-  rio_driver.subtype = SERIAL_TYPE_NORMAL;
-  rio_driver.init_termios = tty_std_termios;
-  rio_driver.init_termios.c_cflag =
-    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-  rio_driver.flags = TTY_DRIVER_REAL_RAW;
-  rio_driver.refcount = &rio_refcount;
-  rio_driver.table = rio_table;
-  rio_driver.termios = rio_termios;
-  rio_driver.termios_locked = rio_termios_locked;
-
-  rio_driver.open  = riotopen;
-  rio_driver.close = gs_close;
-  rio_driver.write = gs_write;
-  rio_driver.put_char = gs_put_char;
-  rio_driver.flush_chars = gs_flush_chars;
-  rio_driver.write_room = gs_write_room;
-  rio_driver.chars_in_buffer = gs_chars_in_buffer;
-  rio_driver.flush_buffer = gs_flush_buffer;
-  rio_driver.ioctl = rio_ioctl;
-  rio_driver.throttle = rio_throttle;
-  rio_driver.unthrottle = rio_unthrottle;
-  rio_driver.set_termios = gs_set_termios;
-  rio_driver.stop = gs_stop;
-  rio_driver.start = gs_start;
-  rio_driver.hangup = gs_hangup;
-
-  rio_driver2 = rio_driver;
-  rio_driver2.major = RIO_NORMAL_MAJOR1;
-  rio_driver2.termios += 256;
-  rio_driver2.termios_locked += 256;
+	int error = -ENOMEM;
 
-  rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
-
-  if ((error = tty_register_driver(&rio_driver))) goto bad1;
-  if ((error = tty_register_driver(&rio_driver2))) goto bad2;
-
-  func_exit();
-  return 0;
-  /* 
- bad3:tty_unregister_driver (&rio_driver2);
- bad2:tty_unregister_driver (&rio_driver);
- bad1:printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n",
-             error);
-  return 1;
+	rio_driver = alloc_tty_driver(256);
+	if (!rio_driver)
+		goto out;
+	rio_driver2 = alloc_tty_driver(256);
+	if (!rio_driver2)
+		goto out1;
+
+	func_enter();
+
+	rio_driver->owner = THIS_MODULE;
+	rio_driver->driver_name = "specialix_rio";
+	rio_driver->name = "ttySR";
+	rio_driver->major = RIO_NORMAL_MAJOR0;
+	rio_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	rio_driver->subtype = SERIAL_TYPE_NORMAL;
+	rio_driver->init_termios = tty_std_termios;
+	rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	rio_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(rio_driver, &rio_ops);
+
+	rio_driver2->owner = THIS_MODULE;
+	rio_driver2->driver_name = "specialix_rio";
+	rio_driver2->name = "ttySR";
+	rio_driver2->major = RIO_NORMAL_MAJOR1;
+	rio_driver2->type = TTY_DRIVER_TYPE_SERIAL;
+	rio_driver2->subtype = SERIAL_TYPE_NORMAL;
+	rio_driver2->init_termios = tty_std_termios;
+	rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	rio_driver2->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(rio_driver2, &rio_ops);
+
+	rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
+
+	if ((error = tty_register_driver(rio_driver)))
+		goto out2;
+	if ((error = tty_register_driver(rio_driver2)))
+		goto out3;
+	func_exit();
+	return 0;
+out3:
+	tty_unregister_driver(rio_driver);
+out2:
+	put_tty_driver(rio_driver2);
+out1:
+	put_tty_driver(rio_driver);
+out:
+	printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n",
+	     error);
+	return 1;
 }
 
 
@@ -966,16 +972,10 @@
   if (!(p                  = ckmalloc (              RI_SZ))) goto free0;
   if (!(p->RIOHosts        = ckmalloc (RIO_HOSTS * HOST_SZ))) goto free1;
   if (!(p->RIOPortp        = ckmalloc (RIO_PORTS * PORT_SZ))) goto free2;
-  if (!(rio_termios        = ckmalloc (RIO_PORTS * TMIO_SZ))) goto free3;
-  if (!(rio_termios_locked = ckmalloc (RIO_PORTS * TMIO_SZ))) goto free4;
   p->RIOConf = RIOConf;
-  rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p %p %p\n", 
-               p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+  rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p\n", 
+               p, p->RIOHosts, p->RIOPortp);
 
-  /* Adjust the values in the "driver" */
-  rio_driver.termios = rio_termios;
-  rio_driver.termios_locked = rio_termios_locked;
-  
 #if 1
   for (i = 0; i < RIO_PORTS; i++) {
     port = p->RIOPortp[i] = ckmalloc (sizeof (struct Port));
@@ -984,7 +984,6 @@
     }
     rio_dprintk (RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
     port->PortNum = i;
-    port->gs.normal_termios  = tty_std_termios;
     port->gs.magic = RIO_MAGIC;
     port->gs.close_delay = HZ/2;
     port->gs.closing_wait = 30 * HZ;
@@ -1013,13 +1012,12 @@
  free6:for (i--;i>=0;i--)
         kfree (p->RIOPortp[i]);
 /*free5: */
-       kfree (rio_termios_locked); 
- free4:kfree (rio_termios);
+ free4:
  free3:kfree (p->RIOPortp);
  free2:kfree (p->RIOHosts);
  free1:
-  rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p %p %p\n", 
-        	       p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+  rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", 
+        	       p, p->RIOHosts, p->RIOPortp);
   kfree(p);        	      
  free0:
   return -ENOMEM;
@@ -1028,8 +1026,10 @@
 static void  __exit rio_release_drivers(void)
 {
   func_enter();
-  tty_unregister_driver (&rio_driver2);
-  tty_unregister_driver (&rio_driver);
+  tty_unregister_driver(rio_driver2);
+  tty_unregister_driver(rio_driver);
+  put_tty_driver(rio_driver2);
+  put_tty_driver(rio_driver);
   func_exit();
 }
 
@@ -1397,8 +1397,6 @@
   rio_release_drivers ();
 
   /* Release dynamically allocated memory */
-  kfree (rio_termios_locked); 
-  kfree (rio_termios);
   kfree (p->RIOPortp);
   kfree (p->RIOHosts);
   kfree (p);
diff -urN linux-2.5.70-bk16/drivers/char/rio/rioboot.c linux-2.5.70-bk17/drivers/char/rio/rioboot.c
--- linux-2.5.70-bk16/drivers/char/rio/rioboot.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/rio/rioboot.c	2003-06-12 04:49:56.000000000 -0700
@@ -326,6 +326,7 @@
 
 			if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) {
 				rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n");
+				sysfree( DownCode, rbp->Count );
 				p->RIOError.Error = COPYIN_FAILED;
 				func_exit ();
 				return -EFAULT;
diff -urN linux-2.5.70-bk16/drivers/char/riscom8.c linux-2.5.70-bk17/drivers/char/riscom8.c
--- linux-2.5.70-bk16/drivers/char/riscom8.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/riscom8.c	2003-06-12 04:49:56.000000000 -0700
@@ -84,11 +84,7 @@
 static DECLARE_TASK_QUEUE(tq_riscom);
 
 static struct riscom_board * IRQ_to_board[16];
-static struct tty_driver riscom_driver;
-static int    riscom_refcount;
-static struct tty_struct * riscom_table[RC_NBOARD * RC_NPORT];
-static struct termios * riscom_termios[RC_NBOARD * RC_NPORT];
-static struct termios * riscom_termios_locked[RC_NBOARD * RC_NPORT];
+static struct tty_driver *riscom_driver;
 static unsigned char * tmp_buf;
 static DECLARE_MUTEX(tmp_buf_sem);
 
@@ -1075,12 +1071,6 @@
 	if ((error = block_til_ready(tty, filp, port)))
 		return error;
 	
-	if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = port->normal_termios;
-		save_flags(flags); cli();
-		rc_change_speed(bp, port);
-		restore_flags(flags);
-	}
 	return 0;
 }
 
@@ -1115,12 +1105,6 @@
 		goto out;
 	port->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (port->flags & ASYNC_NORMAL_ACTIVE)
-		port->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -1694,53 +1678,53 @@
 	}
 }
 
+static struct tty_operations riscom_ops = {
+	.open  = rc_open,
+	.close = rc_close,
+	.write = rc_write,
+	.put_char = rc_put_char,
+	.flush_chars = rc_flush_chars,
+	.write_room = rc_write_room,
+	.chars_in_buffer = rc_chars_in_buffer,
+	.flush_buffer = rc_flush_buffer,
+	.ioctl = rc_ioctl,
+	.throttle = rc_throttle,
+	.unthrottle = rc_unthrottle,
+	.set_termios = rc_set_termios,
+	.stop = rc_stop,
+	.start = rc_start,
+	.hangup = rc_hangup,
+};
+
 static inline int rc_init_drivers(void)
 {
 	int error;
 	int i;
 
+	riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
+	if (!riscom_driver)	
+		return -ENOMEM;
 	
 	if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
 		printk(KERN_ERR "rc: Couldn't get free page.\n");
+		put_tty_driver(riscom_driver);
 		return 1;
 	}
 	init_bh(RISCOM8_BH, do_riscom_bh);
 	memset(IRQ_to_board, 0, sizeof(IRQ_to_board));
-	memset(&riscom_driver, 0, sizeof(riscom_driver));
-	riscom_driver.magic = TTY_DRIVER_MAGIC;
-	riscom_driver.owner = THIS_MODULE;
-	riscom_driver.name = "ttyL";
-	riscom_driver.major = RISCOM8_NORMAL_MAJOR;
-	riscom_driver.num = RC_NBOARD * RC_NPORT;
-	riscom_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	riscom_driver.subtype = SERIAL_TYPE_NORMAL;
-	riscom_driver.init_termios = tty_std_termios;
-	riscom_driver.init_termios.c_cflag =
+	riscom_driver->owner = THIS_MODULE;
+	riscom_driver->name = "ttyL";
+	riscom_driver->major = RISCOM8_NORMAL_MAJOR;
+	riscom_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	riscom_driver->subtype = SERIAL_TYPE_NORMAL;
+	riscom_driver->init_termios = tty_std_termios;
+	riscom_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	riscom_driver.flags = TTY_DRIVER_REAL_RAW;
-	riscom_driver.refcount = &riscom_refcount;
-	riscom_driver.table = riscom_table;
-	riscom_driver.termios = riscom_termios;
-	riscom_driver.termios_locked = riscom_termios_locked;
-
-	riscom_driver.open  = rc_open;
-	riscom_driver.close = rc_close;
-	riscom_driver.write = rc_write;
-	riscom_driver.put_char = rc_put_char;
-	riscom_driver.flush_chars = rc_flush_chars;
-	riscom_driver.write_room = rc_write_room;
-	riscom_driver.chars_in_buffer = rc_chars_in_buffer;
-	riscom_driver.flush_buffer = rc_flush_buffer;
-	riscom_driver.ioctl = rc_ioctl;
-	riscom_driver.throttle = rc_throttle;
-	riscom_driver.unthrottle = rc_unthrottle;
-	riscom_driver.set_termios = rc_set_termios;
-	riscom_driver.stop = rc_stop;
-	riscom_driver.start = rc_start;
-	riscom_driver.hangup = rc_hangup;
-
-	if ((error = tty_register_driver(&riscom_driver)))  {
+	riscom_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(riscom_driver, &riscom_ops);
+	if ((error = tty_register_driver(riscom_driver)))  {
 		free_page((unsigned long)tmp_buf);
+		put_tty_driver(riscom_driver);
 		printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
 				"error = %d\n",
 		       error);
@@ -1749,7 +1733,6 @@
 
 	memset(rc_port, 0, sizeof(rc_port));
 	for (i = 0; i < RC_NPORT * RC_NBOARD; i++)  {
-		rc_port[i].normal_termios  = riscom_driver.init_termios;
 		rc_port[i].magic = RISCOM8_MAGIC;
 		rc_port[i].tqueue.routine = do_softint;
 		rc_port[i].tqueue.data = &rc_port[i];
@@ -1772,7 +1755,8 @@
 	cli();
 	remove_bh(RISCOM8_BH);
 	free_page((unsigned long)tmp_buf);
-	tty_unregister_driver(&riscom_driver);
+	tty_unregister_driver(riscom_driver);
+	put_tty_driver(riscom_driver);
 	restore_flags(flags);
 }
 
diff -urN linux-2.5.70-bk16/drivers/char/riscom8.h linux-2.5.70-bk17/drivers/char/riscom8.h
--- linux-2.5.70-bk16/drivers/char/riscom8.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/riscom8.h	2003-06-12 04:49:56.000000000 -0700
@@ -79,7 +79,6 @@
 	int			xmit_head;
 	int			xmit_tail;
 	int			xmit_cnt;
-	struct termios          normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 	struct tq_struct	tqueue;
diff -urN linux-2.5.70-bk16/drivers/char/rocket.c linux-2.5.70-bk17/drivers/char/rocket.c
--- linux-2.5.70-bk16/drivers/char/rocket.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/rocket.c	2003-06-12 04:49:56.000000000 -0700
@@ -170,11 +170,7 @@
 
 /****** RocketPort Local Variables ******/
 
-static struct tty_struct *rocket_table[MAX_RP_PORTS];	/*  TTY required variables */
-static struct termios *rocket_termios[MAX_RP_PORTS];
-static struct termios *rocket_termios_locked[MAX_RP_PORTS];
-static struct tty_driver rocket_driver;
-static int rocket_refcount;
+static struct tty_driver *rocket_driver;
 
 static struct rocket_version driver_version = {	
 	ROCKET_VERSION, ROCKET_DATE
@@ -716,7 +712,6 @@
 	info->chan = chan;
 	info->closing_wait = 3000;
 	info->close_delay = 50;
-	info->normal_termios = rocket_driver.init_termios;
 	init_waitqueue_head(&info->open_wait);
 	init_waitqueue_head(&info->close_wait);
 	info->flags &= ~ROCKET_MODE_MASK;
@@ -769,7 +764,7 @@
 	rp_table[line] = info;
 #if LINUX_VERSION_CODE > VERSION_CODE(2,5,0)
 	if (pci_dev)
-		tty_register_device(&rocket_driver, line, &pci_dev->dev);
+		tty_register_device(rocket_driver, line, &pci_dev->dev);
 #endif
 }
 
@@ -1148,11 +1143,6 @@
 #endif
 		return retval;
 	}
-
-	if ((info->count == 1) && (info->flags & ROCKET_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		configure_r_port(info, NULL);
-	}
 	return 0;
 }
 
@@ -1201,7 +1191,6 @@
 	info->flags |= ROCKET_CLOSING;
 	spin_unlock_irqrestore(&info->slock, flags);
 
-	info->normal_termios = *tty->termios;
 	cp = &info->channel;
 
 	/*
@@ -1532,7 +1521,7 @@
 	if (!retports)
 		return -EFAULT;
 	memset(&tmp, 0, sizeof (tmp));
-	tmp.tty_major = rocket_driver.major;
+	tmp.tty_major = rocket_driver->major;
 
 	for (board = 0; board < 4; board++) {
 		tmp.rocketModel[board].model = rocketModel[board].model;
@@ -2588,6 +2577,30 @@
 	return (1);
 }
 
+static struct tty_operations rocket_ops = {
+	.open = rp_open,
+	.close = rp_close,
+	.write = rp_write,
+	.put_char = rp_put_char,
+	.write_room = rp_write_room,
+	.chars_in_buffer = rp_chars_in_buffer,
+	.flush_buffer = rp_flush_buffer,
+	.ioctl = rp_ioctl,
+	.throttle = rp_throttle,
+	.unthrottle = rp_unthrottle,
+	.set_termios = rp_set_termios,
+	.stop = rp_stop,
+	.start = rp_start,
+	.hangup = rp_hangup,
+	.break_ctl = rp_break,
+	.send_xchar = rp_send_xchar,
+	.wait_until_sent = rp_wait_until_sent,
+#if (LINUX_VERSION_CODE > VERSION_CODE(2,5,0))
+	.tiocmget = rp_tiocmget,
+	.tiocmset = rp_tiocmset,
+#endif /* Kernel > 2.5 */
+};
+
 /*
  * The module "startup" routine; it's run when the module is loaded.
  */
@@ -2599,6 +2612,10 @@
 	printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
 	       ROCKET_VERSION, ROCKET_DATE);
 
+	rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
+	if (!rocket_driver)
+		return -ENOMEM;
+
 	/*
 	 * Set up the timer channel.
 	 */
@@ -2622,6 +2639,7 @@
 
 	if (controller && check_region(controller, 4)) {
 		printk(KERN_INFO "Controller IO addresses in use, unloading driver.\n");
+		put_tty_driver(rocket_driver);
 		return -EBUSY;
 	}
 
@@ -2644,55 +2662,30 @@
 	 * Set up the tty driver structure and then register this
 	 * driver with the tty layer.
 	 */
-	memset(&rocket_driver, 0, sizeof (struct tty_driver));
-	rocket_driver.magic = TTY_DRIVER_MAGIC;
-	rocket_driver.flags = TTY_DRIVER_NO_DEVFS;
-	rocket_driver.devfs_name = "tts/R";
-	rocket_driver.name = "ttyR";
-	rocket_driver.driver_name = "Comtrol RocketPort";
-	rocket_driver.major = TTY_ROCKET_MAJOR;
-	rocket_driver.minor_start = 0;
-	rocket_driver.num = MAX_RP_PORTS;
-	rocket_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	rocket_driver.subtype = SERIAL_TYPE_NORMAL;
-	rocket_driver.init_termios = tty_std_termios;
-	rocket_driver.init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-#ifdef ROCKET_SOFT_FLOW
-	rocket_driver.flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-#endif
-	rocket_driver.refcount = &rocket_refcount;
-	rocket_driver.table = rocket_table;
-	rocket_driver.termios = rocket_termios;
-	rocket_driver.termios_locked = rocket_termios_locked;
-
-	rocket_driver.open = rp_open;
-	rocket_driver.close = rp_close;
-	rocket_driver.write = rp_write;
-	rocket_driver.put_char = rp_put_char;
-	rocket_driver.write_room = rp_write_room;
-	rocket_driver.chars_in_buffer = rp_chars_in_buffer;
-	rocket_driver.flush_buffer = rp_flush_buffer;
-	rocket_driver.ioctl = rp_ioctl;
-	rocket_driver.throttle = rp_throttle;
-	rocket_driver.unthrottle = rp_unthrottle;
-	rocket_driver.set_termios = rp_set_termios;
-	rocket_driver.stop = rp_stop;
-	rocket_driver.start = rp_start;
-	rocket_driver.hangup = rp_hangup;
-	rocket_driver.break_ctl = rp_break;
-	rocket_driver.send_xchar = rp_send_xchar;
-	rocket_driver.wait_until_sent = rp_wait_until_sent;
 
 #if (LINUX_VERSION_CODE > VERSION_CODE(2,5,0))
-	rocket_driver.owner = THIS_MODULE;
-	rocket_driver.tiocmget = rp_tiocmget;
-	rocket_driver.tiocmset = rp_tiocmset;
+	rocket_driver->owner = THIS_MODULE;
 #endif /* Kernel > 2.5 */
+	rocket_driver->flags = TTY_DRIVER_NO_DEVFS;
+	rocket_driver->devfs_name = "tts/R";
+	rocket_driver->name = "ttyR";
+	rocket_driver->driver_name = "Comtrol RocketPort";
+	rocket_driver->major = TTY_ROCKET_MAJOR;
+	rocket_driver->minor_start = 0;
+	rocket_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	rocket_driver->subtype = SERIAL_TYPE_NORMAL;
+	rocket_driver->init_termios = tty_std_termios;
+	rocket_driver->init_termios.c_cflag =
+	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+#ifdef ROCKET_SOFT_FLOW
+	rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+#endif
+	tty_set_operations(rocket_driver, &rocket_ops);
 
-	retval = tty_register_driver(&rocket_driver);
+	retval = tty_register_driver(rocket_driver);
 	if (retval < 0) {
 		printk(KERN_INFO "Couldn't install tty RocketPort driver (error %d)\n", -retval);
+		put_tty_driver(rocket_driver);
 		return -1;
 	}
 
@@ -2722,6 +2715,8 @@
 	if (max_board == 0) {
 		printk(KERN_INFO "No rocketport ports found; unloading driver.\n");
 		del_timer_sync(&rocket_timer);
+		tty_unregister_driver(rocket_driver);
+		put_tty_driver(rocket_driver);
 		return -ENXIO;
 	}
 
@@ -2745,10 +2740,11 @@
 
 	del_timer_sync(&rocket_timer);
 
-	retval = tty_unregister_driver(&rocket_driver);
+	retval = tty_unregister_driver(rocket_driver);
 	if (retval)
 		printk(KERN_INFO "Error %d while trying to unregister "
 		       "rocketport driver\n", -retval);
+	put_tty_driver(rocket_driver);
 
 	for (i = 0; i < MAX_RP_PORTS; i++) {
 		if (rp_table[i])
diff -urN linux-2.5.70-bk16/drivers/char/rocket_int.h linux-2.5.70-bk17/drivers/char/rocket_int.h
--- linux-2.5.70-bk16/drivers/char/rocket_int.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/rocket_int.h	2003-06-12 04:49:56.000000000 -0700
@@ -1229,8 +1229,6 @@
 	int ignore_status_mask;
 	int read_status_mask;
 	int cps;
-	struct termios normal_termios;
-	struct termios callout_termios;
 
 #ifdef DECLARE_WAITQUEUE
 	wait_queue_head_t open_wait;
diff -urN linux-2.5.70-bk16/drivers/char/selection.c linux-2.5.70-bk17/drivers/char/selection.c
--- linux-2.5.70-bk16/drivers/char/selection.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/selection.c	2003-06-12 04:49:56.000000000 -0700
@@ -23,6 +23,7 @@
 #include <linux/vt_kern.h>
 #include <linux/consolemap.h>
 #include <linux/selection.h>
+#include <linux/tiocl.h>
 
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
@@ -111,7 +112,7 @@
 }
 
 /* set the current selection. Invoked by ioctl() or by kernel code. */
-int set_selection(const unsigned long arg, struct tty_struct *tty, int user)
+int set_selection(const struct tiocl_selection *sel, struct tty_struct *tty, int user)
 {
 	int sel_mode, new_sel_start, new_sel_end, spc;
 	char *bp, *obp;
@@ -120,23 +121,22 @@
 
 	poke_blanked_console();
 
-	{ unsigned short *args, xs, ys, xe, ye;
+	{ unsigned short xs, ys, xe, ye;
 
-	  args = (unsigned short *)(arg + 1);
 	  if (user) {
-		  if (verify_area(VERIFY_READ, args, sizeof(short) * 5))
+		  if (verify_area(VERIFY_READ, sel, sizeof(*sel)))
 		  	return -EFAULT;
-		  __get_user(xs, args++);
-		  __get_user(ys, args++);
-		  __get_user(xe, args++);
-		  __get_user(ye, args++);
-		  __get_user(sel_mode, args);
+		  __get_user(xs, &sel->xs);
+		  __get_user(ys, &sel->ys);
+		  __get_user(xe, &sel->xe);
+		  __get_user(ye, &sel->ye);
+		  __get_user(sel_mode, &sel->sel_mode);
 	  } else {
-		  xs = *(args++); /* set selection from kernel */
-		  ys = *(args++);
-		  xe = *(args++);
-		  ye = *(args++);
-		  sel_mode = *args;
+		  xs = sel->xs; /* set selection from kernel */
+		  ys = sel->ys;
+		  xe = sel->xe;
+		  ye = sel->ye;
+		  sel_mode = sel->sel_mode;
 	  }
 	  xs--; ys--; xe--; ye--;
 	  xs = limit(xs, video_num_columns - 1);
@@ -146,14 +146,14 @@
 	  ps = ys * video_size_row + (xs << 1);
 	  pe = ye * video_size_row + (xe << 1);
 
-	  if (sel_mode == 4) {
+	  if (sel_mode == TIOCL_SELCLEAR) {
 	      /* useful for screendump without selection highlights */
 	      clear_selection();
 	      return 0;
 	  }
 
-	  if (mouse_reporting() && (sel_mode & 16)) {
-	      mouse_report(tty, sel_mode & 15, xs, ys);
+	  if (mouse_reporting() && (sel_mode & TIOCL_SELMOUSEREPORT)) {
+	      mouse_report(tty, sel_mode & TIOCL_SELBUTTONMASK, xs, ys);
 	      return 0;
 	  }
         }
@@ -172,11 +172,11 @@
 
 	switch (sel_mode)
 	{
-		case 0:	/* character-by-character selection */
+		case TIOCL_SELCHAR:	/* character-by-character selection */
 			new_sel_start = ps;
 			new_sel_end = pe;
 			break;
-		case 1:	/* word-by-word selection */
+		case TIOCL_SELWORD:	/* word-by-word selection */
 			spc = isspace(sel_pos(ps));
 			for (new_sel_start = ps; ; ps -= 2)
 			{
@@ -198,12 +198,12 @@
 					break;
 			}
 			break;
-		case 2:	/* line-by-line selection */
+		case TIOCL_SELLINE:	/* line-by-line selection */
 			new_sel_start = ps - ps % video_size_row;
 			new_sel_end = pe + video_size_row
 				    - pe % video_size_row - 2;
 			break;
-		case 3:
+		case TIOCL_SELPOINTER:
 			highlight_pointer(pe);
 			return 0;
 		default:
diff -urN linux-2.5.70-bk16/drivers/char/ser_a2232.c linux-2.5.70-bk17/drivers/char/ser_a2232.c
--- linux-2.5.70-bk16/drivers/char/ser_a2232.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/ser_a2232.c	2003-06-12 04:49:56.000000000 -0700
@@ -171,13 +171,7 @@
 static struct a2232_port a2232_ports[MAX_A2232_BOARDS*NUMLINES];
 
 /* TTY driver structs */
-static struct tty_driver a2232_driver;
-
-/* Variables used by the TTY driver */
-static int a2232_refcount;
-static struct tty_struct *a2232_table[MAX_A2232_BOARDS*NUMLINES] = { NULL, };
-static struct termios *a2232_termios[MAX_A2232_BOARDS*NUMLINES];
-static struct termios *a2232_termios_locked[MAX_A2232_BOARDS*NUMLINES];
+static struct tty_driver *a2232_driver;
 
 /* nr of cards completely (all ports) and correctly configured */
 static int nr_a2232; 
@@ -472,11 +466,6 @@
 		return retval;
 	}
 
-	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)){
-		*tty->termios = port->gs.normal_termios;
-		a2232_set_real_termios (port);
-	}
-
 	a2232_enable_rx_interrupts(port);
 	
 	return 0;
@@ -674,7 +663,6 @@
 		port->which_a2232 = i/NUMLINES;
 		port->which_port_on_a2232 = i%NUMLINES;
 		port->disable_rx = port->throttle_input = port->cd_status = 0;
-		port->gs.normal_termios = tty_std_termios;
 		port->gs.magic = A2232_MAGIC;
 		port->gs.close_delay = HZ/2;
 		port->gs.closing_wait = 30 * HZ;
@@ -687,47 +675,46 @@
 	}
 }
 
+static struct tty_operations a2232_ops = {
+	.open = a2232_open,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = a2232_ioctl,
+	.throttle = a2232_throttle,
+	.unthrottle = a2232_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+};
+
 static int a2232_init_drivers(void)
 {
 	int error;
 
-	memset(&a2232_driver, 0, sizeof(a2232_driver));
-	a2232_driver.magic = TTY_DRIVER_MAGIC;
-	a2232_driver.owner = THIS_MODULE;
-	a2232_driver.driver_name = "commodore_a2232";
-	a2232_driver.name = "ttyY";
-	a2232_driver.major = A2232_NORMAL_MAJOR;
-	a2232_driver.num = NUMLINES * nr_a2232;
-	a2232_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	a2232_driver.subtype = SERIAL_TTY_NORMAL;
-	a2232_driver.init_termios = tty_std_termios;
-	a2232_driver.init_termios.c_cflag =
+	a2232_driver = alloc_tty_driver(NUMLINES * nr_a2232);
+	if (!a2232_driver)
+		return -ENOMEM;
+	a2232_driver->owner = THIS_MODULE;
+	a2232_driver->driver_name = "commodore_a2232";
+	a2232_driver->name = "ttyY";
+	a2232_driver->major = A2232_NORMAL_MAJOR;
+	a2232_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	a2232_driver->subtype = SERIAL_TTY_NORMAL;
+	a2232_driver->init_termios = tty_std_termios;
+	a2232_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	a2232_driver.flags = TTY_DRIVER_REAL_RAW;
-	a2232_driver.refcount = &a2232_refcount;
-	a2232_driver.table = a2232_table;
-	a2232_driver.termios = a2232_termios;
-	a2232_driver.termios_locked = a2232_termios_locked;
-
-	a2232_driver.open = a2232_open;
-	a2232_driver.close = gs_close;
-	a2232_driver.write = gs_write;
-	a2232_driver.put_char = gs_put_char;
-	a2232_driver.flush_chars = gs_flush_chars;
-	a2232_driver.write_room = gs_write_room;
-	a2232_driver.chars_in_buffer = gs_chars_in_buffer;
-	a2232_driver.flush_buffer = gs_flush_buffer;
-	a2232_driver.ioctl = a2232_ioctl;
-	a2232_driver.throttle = a2232_throttle;
-	a2232_driver.unthrottle = a2232_unthrottle;
-	a2232_driver.set_termios = gs_set_termios;
-	a2232_driver.stop = gs_stop;
-	a2232_driver.start = gs_start;
-	a2232_driver.hangup = gs_hangup;
-
-	if ((error = tty_register_driver(&a2232_driver))) {
+	a2232_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(a2232_driver, &a2232_ops);
+	if ((error = tty_register_driver(a2232_driver))) {
 		printk(KERN_ERR "A2232: Couldn't register A2232 driver, error = %d\n",
 		       error);
+		put_tty_driver(a2232_driver);
 		return 1;
 	}
 	return 0;
@@ -840,7 +827,8 @@
 		zorro_release_device(zd_a2232[i]);
 	}
 
-	tty_unregister_driver(&a2232_driver);
+	tty_unregister_driver(a2232_driver);
+	put_tty_driver(a2232_driver);
 	free_irq(IRQ_AMIGA_VERTB, a2232_driver_ID);
 }
 #endif
diff -urN linux-2.5.70-bk16/drivers/char/serial167.c linux-2.5.70-bk17/drivers/char/serial167.c
--- linux-2.5.70-bk16/drivers/char/serial167.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/serial167.c	2003-06-12 04:49:56.000000000 -0700
@@ -100,7 +100,7 @@
 
 DECLARE_TASK_QUEUE(tq_cyclades);
 
-struct tty_driver cy_serial_driver;
+static struct tty_driver *cy_serial_driver;
 extern int serial_console;
 static struct cyclades_port *serial_console_info = NULL;
 static unsigned int serial_console_cflag = 0;
@@ -127,13 +127,6 @@
 };
 #define NR_PORTS        (sizeof(cy_port)/sizeof(struct cyclades_port))
 
-static int serial_refcount;
-
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -1902,12 +1895,6 @@
     if (info->count)
 	return;
     info->flags |= ASYNC_CLOSING;
-    /*
-     * Save the termios structure, since this port may have
-     * separate termios for callout and dialin.
-     */
-    if (info->flags & ASYNC_NORMAL_ACTIVE)
-	info->normal_termios = *tty->termios;
     if (info->flags & ASYNC_INITIALIZED)
 	tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
     shutdown(info);
@@ -2133,9 +2120,6 @@
         }
     }
 
-    if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-	*tty->termios = info->normal_termios;
-    }
     /*
      * Start up serial port
      */
@@ -2304,6 +2288,23 @@
 					rcor >> 5, rbpr);
 } /* serial_console_init */
 
+static struct tty_operations cy_ops = {
+	.open = cy_open,
+	.close = cy_close,
+	.write = cy_write,
+	.put_char = cy_put_char,
+	.flush_chars = cy_flush_chars,
+	.write_room = cy_write_room,
+	.chars_in_buffer = cy_chars_in_buffer,
+	.flush_buffer = cy_flush_buffer,
+	.ioctl = cy_ioctl,
+	.throttle = cy_throttle,
+	.unthrottle = cy_unthrottle,
+	.set_termios = cy_set_termios,
+	.stop = cy_stop,
+	.start = cy_start,
+	.hangup = cy_hangup,
+};
 /* The serial driver boot-time initialization code!
     Hardware I/O ports are mapped to character special devices on a
     first found, first allocated manner.  That is, this code searches
@@ -2336,6 +2337,10 @@
     if (!(mvme16x_config &MVME16x_CONFIG_GOT_CD2401))
 	return 0;
 
+    cy_serial_driver = alloc_tty_driver(NR_PORTS);
+    if (!cy_serial_driver)
+	return -ENOMEM;
+
 #if 0
 scrn[1] = '\0';
 #endif
@@ -2356,43 +2361,23 @@
 
     /* Initialize the tty_driver structure */
     
-    memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
-    cy_serial_driver.magic = TTY_DRIVER_MAGIC;
-    cy_serial_driver.owner = THIS_MODULE;
-    cy_serial_driver.devfs_name = "tts/";
-    cy_serial_driver.name = "ttyS";
-    cy_serial_driver.major = TTY_MAJOR;
-    cy_serial_driver.minor_start = 64;
-    cy_serial_driver.num = NR_PORTS;
-    cy_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-    cy_serial_driver.subtype = SERIAL_TYPE_NORMAL;
-    cy_serial_driver.init_termios = tty_std_termios;
-    cy_serial_driver.init_termios.c_cflag =
+    cy_serial_driver->owner = THIS_MODULE;
+    cy_serial_driver->devfs_name = "tts/";
+    cy_serial_driver->name = "ttyS";
+    cy_serial_driver->major = TTY_MAJOR;
+    cy_serial_driver->minor_start = 64;
+    cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+    cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
+    cy_serial_driver->init_termios = tty_std_termios;
+    cy_serial_driver->init_termios.c_cflag =
 	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-    cy_serial_driver.flags = TTY_DRIVER_REAL_RAW;
-    cy_serial_driver.refcount = &serial_refcount;
-    cy_serial_driver.table = serial_table;
-    cy_serial_driver.termios = serial_termios;
-    cy_serial_driver.termios_locked = serial_termios_locked;
-    cy_serial_driver.open = cy_open;
-    cy_serial_driver.close = cy_close;
-    cy_serial_driver.write = cy_write;
-    cy_serial_driver.put_char = cy_put_char;
-    cy_serial_driver.flush_chars = cy_flush_chars;
-    cy_serial_driver.write_room = cy_write_room;
-    cy_serial_driver.chars_in_buffer = cy_chars_in_buffer;
-    cy_serial_driver.flush_buffer = cy_flush_buffer;
-    cy_serial_driver.ioctl = cy_ioctl;
-    cy_serial_driver.throttle = cy_throttle;
-    cy_serial_driver.unthrottle = cy_unthrottle;
-    cy_serial_driver.set_termios = cy_set_termios;
-    cy_serial_driver.stop = cy_stop;
-    cy_serial_driver.start = cy_start;
-    cy_serial_driver.hangup = cy_hangup;
+    cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
+    tty_set_operations(cy_serial_driver, &cy_ops);
 
-    ret = tty_register_driver(&cy_serial_driver);
+    ret = tty_register_driver(cy_serial_driver);
     if (ret) {
 	    printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
+	    put_tty_driver(cy_serial_driver);
 	    return ret;
     }
 
@@ -2437,7 +2422,6 @@
 		info->default_timeout = 0;
 		info->tqueue.routine = do_softint;
 		info->tqueue.data = info;
-		info->normal_termios = cy_serial_driver.init_termios;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 		/* info->session */
@@ -2507,8 +2491,9 @@
 cleanup_irq_cd2401_errors:
     free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
 cleanup_serial_driver:
-    if (tty_unregister_driver(&cy_serial_driver))
+    if (tty_unregister_driver(cy_serial_driver))
 	    printk(KERN_ERR "Couldn't unregister MVME166/7 serial driver\n");
+    put_tty_driver(cy_serial_driver);
     return ret;
 } /* serial167_init */
 
@@ -2756,7 +2741,7 @@
 static struct tty_driver *serial167_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &cy_serial_driver;
+	return cy_serial_driver;
 }
 
 
diff -urN linux-2.5.70-bk16/drivers/char/serial_tx3912.c linux-2.5.70-bk17/drivers/char/serial_tx3912.c
--- linux-2.5.70-bk16/drivers/char/serial_tx3912.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/serial_tx3912.c	2003-06-12 04:49:56.000000000 -0700
@@ -59,12 +59,8 @@
 /*
  * Structures and such for TTY sessions and usage counts
  */
-static struct tty_driver rs_driver;
-static struct tty_struct * rs_table[TX3912_UART_NPORTS] = { NULL, };
-static struct termios ** rs_termios;
-static struct termios ** rs_termios_locked;
+static struct tty_driver *rs_driver;
 struct rs_port *rs_ports;
-int rs_refcount;
 int rs_initialized = 0;
 
 /*
@@ -593,11 +589,6 @@
 	}
 	/* tty->low_latency = 1; */
 
-	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = port->gs.normal_termios;
-		rs_set_real_termios (port);
-	}
-
 	func_exit();
 
 	/* Jim */
@@ -748,27 +739,9 @@
 	if (!rs_ports)
 		return -ENOMEM;
 
-	rs_termios        = ckmalloc(TX3912_UART_NPORTS * sizeof (struct termios *));
-	if (!rs_termios) {
-		kfree (rs_ports);
-		return -ENOMEM;
-	}
-
-	rs_termios_locked = ckmalloc(TX3912_UART_NPORTS * sizeof (struct termios *));
-	if (!rs_termios_locked) {
-		kfree (rs_ports);
-		kfree (rs_termios);
-		return -ENOMEM;
-	}
-
-	/* Adjust the values in the "driver" */
-	rs_driver.termios = rs_termios;
-	rs_driver.termios_locked = rs_termios_locked;
-
 	port = rs_ports;
 	for (i=0; i < TX3912_UART_NPORTS;i++) {
 		rs_dprintk (TX3912_UART_DEBUG_INIT, "initing port %d\n", i);
-		port->gs.normal_termios	= tty_std_termios;
 		port->gs.magic = SERIAL_MAGIC;
 		port->gs.close_delay = HZ/2;
 		port->gs.closing_wait = 30 * HZ;
@@ -791,49 +764,48 @@
 	return 0;
 }
 
+static struct tty_operations rs_ops = {
+	.open	= rs_open,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char, 
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+};
+
 static int rs_init_drivers(void)
 {
 	int error;
 
 	func_enter();
 
-	memset(&rs_driver, 0, sizeof(rs_driver));
-	rs_driver.magic = TTY_DRIVER_MAGIC;
-	rs_driver.owner = THIS_MODULE;
-	rs_driver.driver_name = "serial";
-	rs_driver.name = "ttyS";
-	rs_driver.major = TTY_MAJOR;
-	rs_driver.minor_start = 64;
-	rs_driver.num = TX3912_UART_NPORTS;
-	rs_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	rs_driver.subtype = SERIAL_TYPE_NORMAL;
-	rs_driver.init_termios = tty_std_termios;
-	rs_driver.init_termios.c_cflag =
+	rs_driver = alloc_tty_driver(TX3912_UART_NPORTS);
+	if (!rs_driver)
+		return -ENOMEM;
+	rs_driver->owner = THIS_MODULE;
+	rs_driver->driver_name = "serial";
+	rs_driver->name = "ttyS";
+	rs_driver->major = TTY_MAJOR;
+	rs_driver->minor_start = 64;
+	rs_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	rs_driver->subtype = SERIAL_TYPE_NORMAL;
+	rs_driver->init_termios = tty_std_termios;
+	rs_driver->init_termios.c_cflag =
 		B115200 | CS8 | CREAD | HUPCL | CLOCAL;
-	rs_driver.refcount = &rs_refcount;
-	rs_driver.table = rs_table;
-	rs_driver.termios = rs_termios;
-	rs_driver.termios_locked = rs_termios_locked;
-
-	rs_driver.open	= rs_open;
-	rs_driver.close = gs_close;
-	rs_driver.write = gs_write;
-	rs_driver.put_char = gs_put_char; 
-	rs_driver.flush_chars = gs_flush_chars;
-	rs_driver.write_room = gs_write_room;
-	rs_driver.chars_in_buffer = gs_chars_in_buffer;
-	rs_driver.flush_buffer = gs_flush_buffer;
-	rs_driver.ioctl = rs_ioctl;
-	rs_driver.throttle = rs_throttle;
-	rs_driver.unthrottle = rs_unthrottle;
-	rs_driver.set_termios = gs_set_termios;
-	rs_driver.stop = gs_stop;
-	rs_driver.start = gs_start;
-	rs_driver.hangup = gs_hangup;
-
-	if ((error = tty_register_driver(&rs_driver))) {
+	tty_set_operations(rs_driver, &rs_ops);
+	if ((error = tty_register_driver(rs_driver))) {
 		printk(KERN_ERR "Couldn't register serial driver, error = %d\n",
 		       error);
+		put_tty_driver(rs_driver);
 		return 1;
 	}
 	return 0;
@@ -955,7 +927,7 @@
 static struct tty_driver *serial_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &rs_driver;
+	return rs_driver;
 }
 
 static __init int serial_console_setup(struct console *co, char *options)
diff -urN linux-2.5.70-bk16/drivers/char/sh-sci.c linux-2.5.70-bk17/drivers/char/sh-sci.c
--- linux-2.5.70-bk16/drivers/char/sh-sci.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/sh-sci.c	2003-06-12 04:49:56.000000000 -0700
@@ -76,14 +76,10 @@
 static void sci_free_irq(struct sci_port *port);
 static int sci_init_drivers(void);
 
-static struct tty_driver sci_driver;
+static struct tty_driver *sci_driver;
 
 static struct sci_port sci_ports[SCI_NPORTS] = SCI_INIT;
-static struct tty_struct *sci_table[SCI_NPORTS] = { NULL, };
-static struct termios *sci_termios[SCI_NPORTS];
-static struct termios *sci_termios_locked[SCI_NPORTS];
 
-static int sci_refcount;
 static int sci_debug = 0;
 
 #ifdef MODULE
@@ -843,11 +839,6 @@
 		goto failed_3;
 	}
 
-	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = port->gs.normal_termios;
-		sci_set_real_termios(port);
-	}
-
 #ifdef CONFIG_SERIAL_CONSOLE
 	if (sercons.cflag && sercons.index == line) {
 		tty->termios->c_cflag = sercons.cflag;
@@ -981,6 +972,27 @@
 }
 #endif
 
+static struct tty_operations sci_ops = {
+	.open	= sci_open,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = sci_ioctl,
+	.throttle = sci_throttle,
+	.unthrottle = sci_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+#ifdef CONFIG_PROC_FS
+	.read_proc = sci_read_proc,
+#endif
+};
+
 /* ********************************************************************** *
  *                    Here are the initialization routines.               *
  * ********************************************************************** */
@@ -989,54 +1001,31 @@
 {
 	int error;
 	struct sci_port *port;
-
-	memset(&sci_driver, 0, sizeof(sci_driver));
-	sci_driver.magic = TTY_DRIVER_MAGIC;
-	sci_driver.owner = THIS_MODULE;
-	sci_driver.driver_name = "sci";
-	sci_driver.name = "ttySC";
-	sci_driver.devfs_name = "ttsc/";
-	sci_driver.major = SCI_MAJOR;
-	sci_driver.minor_start = SCI_MINOR_START;
-	sci_driver.num = SCI_NPORTS;
-	sci_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	sci_driver.subtype = SERIAL_TYPE_NORMAL;
-	sci_driver.init_termios = tty_std_termios;
-	sci_driver.init_termios.c_cflag =
+	sci_driver = alloc_tty_driver(SCI_NPORTS);
+	if (!sci_driver)
+		return -ENOMEM;
+
+	sci_driver->owner = THIS_MODULE;
+	sci_driver->driver_name = "sci";
+	sci_driver->name = "ttySC";
+	sci_driver->devfs_name = "ttsc/";
+	sci_driver->major = SCI_MAJOR;
+	sci_driver->minor_start = SCI_MINOR_START;
+	sci_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	sci_driver->subtype = SERIAL_TYPE_NORMAL;
+	sci_driver->init_termios = tty_std_termios;
+	sci_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL | CRTSCTS;
-	sci_driver.flags = TTY_DRIVER_REAL_RAW;
-	sci_driver.refcount = &sci_refcount;
-	sci_driver.table = sci_table;
-	sci_driver.termios = sci_termios;
-	sci_driver.termios_locked = sci_termios_locked;
-
-	sci_driver.open	= sci_open;
-	sci_driver.close = gs_close;
-	sci_driver.write = gs_write;
-	sci_driver.put_char = gs_put_char;
-	sci_driver.flush_chars = gs_flush_chars;
-	sci_driver.write_room = gs_write_room;
-	sci_driver.chars_in_buffer = gs_chars_in_buffer;
-	sci_driver.flush_buffer = gs_flush_buffer;
-	sci_driver.ioctl = sci_ioctl;
-	sci_driver.throttle = sci_throttle;
-	sci_driver.unthrottle = sci_unthrottle;
-	sci_driver.set_termios = gs_set_termios;
-	sci_driver.stop = gs_stop;
-	sci_driver.start = gs_start;
-	sci_driver.hangup = gs_hangup;
-#ifdef CONFIG_PROC_FS
-	sci_driver.read_proc = sci_read_proc;
-#endif
-
-	if ((error = tty_register_driver(&sci_driver))) {
+	sci_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(sci_driver, &sci_ops);
+	if ((error = tty_register_driver(sci_driver))) {
 		printk(KERN_ERR "sci: Couldn't register SCI driver, error = %d\n",
 		       error);
+		put_tty_driver(sci_driver);
 		return 1;
 	}
 
 	for (port = &sci_ports[0]; port < &sci_ports[SCI_NPORTS]; port++) {
-		port->gs.normal_termios	= sci_driver.init_termios;
 		port->gs.magic = SCI_MAGIC;
 		port->gs.close_delay = HZ/2;
 		port->gs.closing_wait = 30 * HZ;
@@ -1115,7 +1104,8 @@
 
 void cleanup_module(void)
 {
-	tty_unregister_driver(&sci_driver);
+	tty_unregister_driver(sci_driver);
+	put_tty_driver(sci_driver);
 }
 
 #include "generic_serial.c"
@@ -1135,7 +1125,7 @@
 static struct tty_driver *serial_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &sci_driver;
+	return sci_driver;
 }
 
 /*
diff -urN linux-2.5.70-bk16/drivers/char/specialix.c linux-2.5.70-bk17/drivers/char/specialix.c
--- linux-2.5.70-bk16/drivers/char/specialix.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/specialix.c	2003-06-12 04:49:56.000000000 -0700
@@ -176,11 +176,7 @@
 #undef RS_EVENT_WRITE_WAKEUP
 #define RS_EVENT_WRITE_WAKEUP	0
 
-static struct tty_driver specialix_driver;
-static int    specialix_refcount;
-static struct tty_struct * specialix_table[SX_NBOARD * SX_NPORT];
-static struct termios * specialix_termios[SX_NBOARD * SX_NPORT];
-static struct termios * specialix_termios_locked[SX_NBOARD * SX_NPORT];
+static struct tty_driver *specialix_driver;
 static unsigned char * tmp_buf;
 static DECLARE_MUTEX(tmp_buf_sem);
 
@@ -1442,12 +1438,6 @@
 	if ((error = block_til_ready(tty, filp, port)))
 		return error;
 
-	if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = port->normal_termios;
-		save_flags(flags); cli();
-		sx_change_speed(bp, port);
-		restore_flags(flags);
-	}
 	return 0;
 }
 
@@ -1486,12 +1476,6 @@
 	}
 	port->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (port->flags & ASYNC_NORMAL_ACTIVE)
-		port->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -2167,52 +2151,54 @@
 	}
 }
 
+static struct tty_operations sx_ops = {
+	.open  = sx_open,
+	.close = sx_close,
+	.write = sx_write,
+	.put_char = sx_put_char,
+	.flush_chars = sx_flush_chars,
+	.write_room = sx_write_room,
+	.chars_in_buffer = sx_chars_in_buffer,
+	.flush_buffer = sx_flush_buffer,
+	.ioctl = sx_ioctl,
+	.throttle = sx_throttle,
+	.unthrottle = sx_unthrottle,
+	.set_termios = sx_set_termios,
+	.stop = sx_stop,
+	.start = sx_start,
+	.hangup = sx_hangup,
+};
 
 static int sx_init_drivers(void)
 {
 	int error;
 	int i;
 
+	specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
+	if (!specialix_driver) {
+		printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
+		return 1;
+	}
 	
 	if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
 		printk(KERN_ERR "sx: Couldn't get free page.\n");
+		put_tty_driver(specialix_driver);
 		return 1;
 	}
 	init_bh(SPECIALIX_BH, do_specialix_bh);
-	memset(&specialix_driver, 0, sizeof(specialix_driver));
-	specialix_driver.magic = TTY_DRIVER_MAGIC;
-	specialix_driver.owner = THIS_MODULE;
-	specialix_driver.name = "ttyW";
-	specialix_driver.major = SPECIALIX_NORMAL_MAJOR;
-	specialix_driver.num = SX_NBOARD * SX_NPORT;
-	specialix_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	specialix_driver.subtype = SERIAL_TYPE_NORMAL;
-	specialix_driver.init_termios = tty_std_termios;
-	specialix_driver.init_termios.c_cflag =
+	specialix_driver->owner = THIS_MODULE;
+	specialix_driver->name = "ttyW";
+	specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
+	specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	specialix_driver->subtype = SERIAL_TYPE_NORMAL;
+	specialix_driver->init_termios = tty_std_termios;
+	specialix_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	specialix_driver.flags = TTY_DRIVER_REAL_RAW;
-	specialix_driver.refcount = &specialix_refcount;
-	specialix_driver.table = specialix_table;
-	specialix_driver.termios = specialix_termios;
-	specialix_driver.termios_locked = specialix_termios_locked;
-
-	specialix_driver.open  = sx_open;
-	specialix_driver.close = sx_close;
-	specialix_driver.write = sx_write;
-	specialix_driver.put_char = sx_put_char;
-	specialix_driver.flush_chars = sx_flush_chars;
-	specialix_driver.write_room = sx_write_room;
-	specialix_driver.chars_in_buffer = sx_chars_in_buffer;
-	specialix_driver.flush_buffer = sx_flush_buffer;
-	specialix_driver.ioctl = sx_ioctl;
-	specialix_driver.throttle = sx_throttle;
-	specialix_driver.unthrottle = sx_unthrottle;
-	specialix_driver.set_termios = sx_set_termios;
-	specialix_driver.stop = sx_stop;
-	specialix_driver.start = sx_start;
-	specialix_driver.hangup = sx_hangup;
+	specialix_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(specialix_driver, &sx_ops);
 
-	if ((error = tty_register_driver(&specialix_driver))) {
+	if ((error = tty_register_driver(specialix_driver))) {
+		put_tty_driver(specialix_driver);
 		free_page((unsigned long)tmp_buf);
 		printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
 		       error);
@@ -2220,7 +2206,6 @@
 	}
 	memset(sx_port, 0, sizeof(sx_port));
 	for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
-		sx_port[i].normal_termios  = specialix_driver.init_termios;
 		sx_port[i].magic = SPECIALIX_MAGIC;
 		sx_port[i].tqueue.routine = do_softint;
 		sx_port[i].tqueue.data = &sx_port[i];
@@ -2239,7 +2224,8 @@
 static void sx_release_drivers(void)
 {
 	free_page((unsigned long)tmp_buf);
-	tty_unregister_driver(&specialix_driver);
+	tty_unregister_driver(specialix_driver);
+	put_tty_driver(specialix_driver);
 }
 
 
diff -urN linux-2.5.70-bk16/drivers/char/specialix_io8.h linux-2.5.70-bk17/drivers/char/specialix_io8.h
--- linux-2.5.70-bk16/drivers/char/specialix_io8.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/specialix_io8.h	2003-06-12 04:49:56.000000000 -0700
@@ -118,7 +118,6 @@
 	int			xmit_head;
 	int			xmit_tail;
 	int			xmit_cnt;
-	struct termios          normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 	struct tq_struct	tqueue;
diff -urN linux-2.5.70-bk16/drivers/char/stallion.c linux-2.5.70-bk17/drivers/char/stallion.c
--- linux-2.5.70-bk16/drivers/char/stallion.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/stallion.c	2003-06-12 04:49:56.000000000 -0700
@@ -137,11 +137,7 @@
 static char	*stl_drvname = "stallion";
 static char	*stl_drvversion = "5.6.0";
 
-static struct tty_driver	stl_serial;
-static struct tty_struct	*stl_ttys[STL_MAXDEVS];
-static struct termios		*stl_termios[STL_MAXDEVS];
-static struct termios		*stl_termioslocked[STL_MAXDEVS];
-static int			stl_refcount;
+static struct tty_driver	*stl_serial;
 
 /*
  *	We will need to allocate a temporary write buffer for chars that
@@ -787,7 +783,8 @@
  *	a hangup on every open port - to try to flush out any processes
  *	hanging onto ports.
  */
-	i = tty_unregister_driver(&stl_serial);
+	i = tty_unregister_driver(stl_serial);
+	put_tty_driver(stl_serial);
 	if (i) {
 		printk("STALLION: failed to un-register tty driver, "
 			"errno=%d\n", -i);
@@ -1081,10 +1078,6 @@
 	}
 	portp->flags |= ASYNC_NORMAL_ACTIVE;
 
-	if ((portp->refcount == 1) && (portp->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = portp->normaltermios;
-		stl_setport(portp, tty->termios);
-	}
 	return(0);
 }
 
@@ -1176,9 +1169,6 @@
 	portp->refcount = 0;
 	portp->flags |= ASYNC_CLOSING;
 
-	if (portp->flags & ASYNC_NORMAL_ACTIVE)
-		portp->normaltermios = *tty->termios;
-
 /*
  *	May want to wait for any data to drain before closing. The BUSY
  *	flag keeps track of whether we are still sending or not - it is
@@ -2290,7 +2280,6 @@
 		portp->baud_base = STL_BAUDBASE;
 		portp->close_delay = STL_CLOSEDELAY;
 		portp->closing_wait = 30 * HZ;
-		portp->normaltermios = stl_deftermios;
 		INIT_WORK(&portp->tqueue, stl_offintr, portp);
 		init_waitqueue_head(&portp->open_wait);
 		init_waitqueue_head(&portp->close_wait);
@@ -3132,6 +3121,28 @@
 	return(rc);
 }
 
+static struct tty_operations stl_ops = {
+	.open = stl_open,
+	.close = stl_close,
+	.write = stl_write,
+	.put_char = stl_putchar,
+	.flush_chars = stl_flushchars,
+	.write_room = stl_writeroom,
+	.chars_in_buffer = stl_charsinbuffer,
+	.ioctl = stl_ioctl,
+	.set_termios = stl_settermios,
+	.throttle = stl_throttle,
+	.unthrottle = stl_unthrottle,
+	.stop = stl_stop,
+	.start = stl_start,
+	.hangup = stl_hangup,
+	.flush_buffer = stl_flushbuffer,
+	.break_ctl = stl_breakctl,
+	.wait_until_sent = stl_waituntilsent,
+	.send_xchar = stl_sendxchar,
+	.read_proc = stl_readproc,
+};
+
 /*****************************************************************************/
 
 int __init stl_init(void)
@@ -3141,6 +3152,10 @@
 
 	stl_initbrds();
 
+	stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+	if (!stl_serial)
+		return -1;
+
 /*
  *	Allocate a temporary write buffer.
  */
@@ -3163,49 +3178,23 @@
 				&stl_fsiomem, NULL, "staliomem/%d", i);
 	}
 
-/*
- *	Set up the tty driver structure and register us as a driver.
- */
-	memset(&stl_serial, 0, sizeof(struct tty_driver));
-	stl_serial.magic = TTY_DRIVER_MAGIC;
-	stl_serial.owner = THIS_MODULE;
-	stl_serial.driver_name = stl_drvname;
-	stl_serial.name = "ttyE";
-	stl_serial.devfs_name = "tts/E";
-	stl_serial.major = STL_SERIALMAJOR;
-	stl_serial.minor_start = 0;
-	stl_serial.num = STL_MAXBRDS * STL_MAXPORTS;
-	stl_serial.type = TTY_DRIVER_TYPE_SERIAL;
-	stl_serial.subtype = SERIAL_TYPE_NORMAL;
-	stl_serial.init_termios = stl_deftermios;
-	stl_serial.flags = TTY_DRIVER_REAL_RAW;
-	stl_serial.refcount = &stl_refcount;
-	stl_serial.table = stl_ttys;
-	stl_serial.termios = stl_termios;
-	stl_serial.termios_locked = stl_termioslocked;
-	
-	stl_serial.open = stl_open;
-	stl_serial.close = stl_close;
-	stl_serial.write = stl_write;
-	stl_serial.put_char = stl_putchar;
-	stl_serial.flush_chars = stl_flushchars;
-	stl_serial.write_room = stl_writeroom;
-	stl_serial.chars_in_buffer = stl_charsinbuffer;
-	stl_serial.ioctl = stl_ioctl;
-	stl_serial.set_termios = stl_settermios;
-	stl_serial.throttle = stl_throttle;
-	stl_serial.unthrottle = stl_unthrottle;
-	stl_serial.stop = stl_stop;
-	stl_serial.start = stl_start;
-	stl_serial.hangup = stl_hangup;
-	stl_serial.flush_buffer = stl_flushbuffer;
-	stl_serial.break_ctl = stl_breakctl;
-	stl_serial.wait_until_sent = stl_waituntilsent;
-	stl_serial.send_xchar = stl_sendxchar;
-	stl_serial.read_proc = stl_readproc;
+	stl_serial->owner = THIS_MODULE;
+	stl_serial->driver_name = stl_drvname;
+	stl_serial->name = "ttyE";
+	stl_serial->devfs_name = "tts/E";
+	stl_serial->major = STL_SERIALMAJOR;
+	stl_serial->minor_start = 0;
+	stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
+	stl_serial->subtype = SERIAL_TYPE_NORMAL;
+	stl_serial->init_termios = stl_deftermios;
+	stl_serial->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(stl_serial, &stl_ops);
 
-	if (tty_register_driver(&stl_serial))
+	if (tty_register_driver(stl_serial)) {
+		put_tty_driver(stl_serial);
 		printk("STALLION: failed to register serial driver\n");
+		return -1;
+	}
 
 	return(0);
 }
diff -urN linux-2.5.70-bk16/drivers/char/sx.c linux-2.5.70-bk17/drivers/char/sx.c
--- linux-2.5.70-bk16/drivers/char/sx.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/sx.c	2003-06-12 04:49:56.000000000 -0700
@@ -308,15 +308,10 @@
 static int sx_init_drivers(void);
 
 
-static struct tty_driver sx_driver;
-
-static struct tty_struct * sx_table[SX_NPORTS];
-static struct termios ** sx_termios;
-static struct termios ** sx_termios_locked;
+static struct tty_driver *sx_driver;
 
 static struct sx_board boards[SX_NBOARDS];
 static struct sx_port *sx_ports;
-static int sx_refcount;
 static int sx_initialized;
 static int sx_nports;
 static int sx_debug;
@@ -1486,11 +1481,6 @@
 	}
 	/* tty->low_latency = 1; */
 
-	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = port->gs.normal_termios;
-		sx_set_real_termios (port);
-	}
-
 	port->c_dcd = sx_get_CD (port);
 	sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
 	func_exit();
@@ -2220,6 +2210,24 @@
 	return 1;
 }
 
+static struct tty_operations sx_ops = {
+	.break_ctl = sx_break,
+	.open	= sx_open,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = sx_ioctl,
+	.throttle = sx_throttle,
+	.unthrottle = sx_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+};
 
 static int sx_init_drivers(void)
 {
@@ -2227,42 +2235,23 @@
 
 	func_enter();
 
-	memset(&sx_driver, 0, sizeof(sx_driver));
-	sx_driver.magic = TTY_DRIVER_MAGIC;
-	sx_driver.owner = THIS_MODULE;
-	sx_driver.driver_name = "specialix_sx";
-	sx_driver.name = "ttyX";
-	sx_driver.major = SX_NORMAL_MAJOR;
-	sx_driver.num = sx_nports;
-	sx_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	sx_driver.subtype = SERIAL_TYPE_NORMAL;
-	sx_driver.init_termios = tty_std_termios;
-	sx_driver.init_termios.c_cflag =
+	sx_driver = alloc_tty_driver(sx_nports);
+	if (!sx_driver)
+		return 1;
+	sx_driver->owner = THIS_MODULE;
+	sx_driver->driver_name = "specialix_sx";
+	sx_driver->name = "ttyX";
+	sx_driver->major = SX_NORMAL_MAJOR;
+	sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	sx_driver->subtype = SERIAL_TYPE_NORMAL;
+	sx_driver->init_termios = tty_std_termios;
+	sx_driver->init_termios.c_cflag =
 	  B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	sx_driver.flags = TTY_DRIVER_REAL_RAW;
-	sx_driver.refcount = &sx_refcount;
-	sx_driver.table = sx_table;
-	sx_driver.termios = sx_termios;
-	sx_driver.termios_locked = sx_termios_locked;
-	sx_driver.break_ctl = sx_break;
-
-	sx_driver.open	= sx_open;
-	sx_driver.close = gs_close;
-	sx_driver.write = gs_write;
-	sx_driver.put_char = gs_put_char;
-	sx_driver.flush_chars = gs_flush_chars;
-	sx_driver.write_room = gs_write_room;
-	sx_driver.chars_in_buffer = gs_chars_in_buffer;
-	sx_driver.flush_buffer = gs_flush_buffer;
-	sx_driver.ioctl = sx_ioctl;
-	sx_driver.throttle = sx_throttle;
-	sx_driver.unthrottle = sx_unthrottle;
-	sx_driver.set_termios = gs_set_termios;
-	sx_driver.stop = gs_stop;
-	sx_driver.start = gs_start;
-	sx_driver.hangup = gs_hangup;
+	sx_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(sx_driver, &sx_ops);
 
-	if ((error = tty_register_driver(&sx_driver))) {
+	if ((error = tty_register_driver(sx_driver))) {
+		put_tty_driver(sx_driver);
 		printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
 		       error);
 		return 1;
@@ -2299,30 +2288,12 @@
 	if (!sx_ports)
 		return -ENOMEM;
 
-	sx_termios        = ckmalloc(nports * sizeof (struct termios *));
-	if (!sx_termios) {
-		kfree (sx_ports);
-		return -ENOMEM;
-	}
-
-	sx_termios_locked = ckmalloc(nports * sizeof (struct termios *));
-	if (!sx_termios_locked) {
-		kfree (sx_ports);
-		kfree (sx_termios);
-		return -ENOMEM;
-	}
-
-	/* Adjust the values in the "driver" */
-	sx_driver.termios = sx_termios;
-	sx_driver.termios_locked = sx_termios_locked;
-
 	port = sx_ports;
 	for (i = 0; i < nboards; i++) {
 		board = &boards[i];
 		board->ports = port;
 		for (j=0; j < boards[i].nports;j++) {
 			sx_dprintk (SX_DEBUG_INIT, "initing port %d\n", j);
-			port->gs.normal_termios	= tty_std_termios;
 			port->gs.magic = SX_MAGIC;
 			port->gs.close_delay = HZ/2;
 			port->gs.closing_wait = 30 * HZ;
@@ -2381,7 +2352,8 @@
 static void __exit sx_release_drivers(void)
 {
 	func_enter();
-	tty_unregister_driver(&sx_driver);
+	tty_unregister_driver(sx_driver);
+	put_tty_driver(sx_driver);
 	func_exit();
 }
 
@@ -2640,8 +2612,6 @@
 		sx_release_drivers ();
 
 	kfree (sx_ports);
-	kfree (sx_termios);
-	kfree (sx_termios_locked);
 	func_exit();
 }
 
diff -urN linux-2.5.70-bk16/drivers/char/synclink.c linux-2.5.70-bk17/drivers/char/synclink.c
--- linux-2.5.70-bk16/drivers/char/synclink.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/synclink.c	2003-06-12 04:49:56.000000000 -0700
@@ -199,8 +199,6 @@
 	
 	struct mgsl_icount	icount;
 	
-	struct termios		normal_termios;
-
 	struct tty_struct 	*tty;
 	int			timeout;
 	int			x_char;		/* xon/xoff character */
@@ -934,8 +932,7 @@
 	.remove		= __devexit_p(synclink_remove_one),
 };
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
@@ -944,10 +941,6 @@
 static void mgsl_change_params(struct mgsl_struct *info);
 static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
 
-static struct tty_struct *serial_table[MAX_TOTAL_DEVICES];
-static struct termios *serial_termios[MAX_TOTAL_DEVICES];
-static struct termios *serial_termios_locked[MAX_TOTAL_DEVICES];
-
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
@@ -3206,12 +3199,6 @@
 	
 	info->flags |= ASYNC_CLOSING;
 	
-	/* Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-
 	/* set tty->closing to notify line discipline to 
 	 * only process XON/XOFF characters. Only the N_TTY
 	 * discipline appears to use this (ppp does not).
@@ -3568,12 +3555,6 @@
 		goto cleanup;
 	}
 
-	if ((info->count == 1) &&
-	    info->flags & ASYNC_SPLIT_TERMIOS) {
-		*tty->termios = info->normal_termios;
-		mgsl_change_params(info);
-	}
-	
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_open(%s) success\n",
 			 __FILE__,__LINE__, info->device_name);
@@ -4450,6 +4431,30 @@
 
 }	/* end of mgsl_allocate_device()*/
 
+static struct tty_operations mgsl_ops = {
+	.open = mgsl_open,
+	.close = mgsl_close,
+	.write = mgsl_write,
+	.put_char = mgsl_put_char,
+	.flush_chars = mgsl_flush_chars,
+	.write_room = mgsl_write_room,
+	.chars_in_buffer = mgsl_chars_in_buffer,
+	.flush_buffer = mgsl_flush_buffer,
+	.ioctl = mgsl_ioctl,
+	.throttle = mgsl_throttle,
+	.unthrottle = mgsl_unthrottle,
+	.send_xchar = mgsl_send_xchar,
+	.break_ctl = mgsl_break,
+	.wait_until_sent = mgsl_wait_until_sent,
+ 	.read_proc = mgsl_read_proc,
+	.set_termios = mgsl_set_termios,
+	.stop = mgsl_stop,
+	.start = mgsl_start,
+	.hangup = mgsl_hangup,
+	.tiocmget = tiocmget,
+	.tiocmset = tiocmset,
+};
+
 /*
  * perform tty device initialization
  */
@@ -4457,70 +4462,29 @@
 int mgsl_init_tty()
 {
 	struct mgsl_struct *info;
-
-	memset(serial_table,0,sizeof(struct tty_struct*)*MAX_TOTAL_DEVICES);
-	memset(serial_termios,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES);
-	memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES);
-
-	/* Initialize the tty_driver structure */
-	
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.owner = THIS_MODULE;
-	serial_driver.driver_name = "synclink";
-	serial_driver.name = "ttySL";
-	serial_driver.major = ttymajor;
-	serial_driver.minor_start = 64;
-	serial_driver.num = mgsl_device_count;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = mgsl_open;
-	serial_driver.close = mgsl_close;
-	serial_driver.write = mgsl_write;
-	serial_driver.put_char = mgsl_put_char;
-	serial_driver.flush_chars = mgsl_flush_chars;
-	serial_driver.write_room = mgsl_write_room;
-	serial_driver.chars_in_buffer = mgsl_chars_in_buffer;
-	serial_driver.flush_buffer = mgsl_flush_buffer;
-	serial_driver.ioctl = mgsl_ioctl;
-	serial_driver.throttle = mgsl_throttle;
-	serial_driver.unthrottle = mgsl_unthrottle;
-	serial_driver.send_xchar = mgsl_send_xchar;
-	serial_driver.break_ctl = mgsl_break;
-	serial_driver.wait_until_sent = mgsl_wait_until_sent;
- 	serial_driver.read_proc = mgsl_read_proc;
-	serial_driver.set_termios = mgsl_set_termios;
-	serial_driver.stop = mgsl_stop;
-	serial_driver.start = mgsl_start;
-	serial_driver.hangup = mgsl_hangup;
-	serial_driver.tiocmget = tiocmget;
-	serial_driver.tiocmset = tiocmset;
+	serial_driver = alloc_tty_driver(mgsl_device_count);
+	if (!serial_driver)
+		return -ENOMEM;
 	
-	if (tty_register_driver(&serial_driver) < 0)
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = "synclink";
+	serial_driver->name = "ttySL";
+	serial_driver->major = ttymajor;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &mgsl_ops);
+	if (tty_register_driver(serial_driver) < 0)
 		printk("%s(%d):Couldn't register serial driver\n",
 			__FILE__,__LINE__);
 			
  	printk("%s %s, tty major#%d\n",
 		driver_name, driver_version,
-		serial_driver.major);
-		
-	/* Propagate these values to all device instances */
-	
-	info = mgsl_device_list;
-	while(info){
-		info->normal_termios  = serial_driver.init_termios;
-		info = info->next_device;
-	}
-
+		serial_driver->major);
 	return 0;
 }
 
@@ -4609,10 +4573,11 @@
 
 	printk("Unloading %s: %s\n", driver_name, driver_version);
 
-	if ((rc = tty_unregister_driver(&serial_driver)))
+	if ((rc = tty_unregister_driver(serial_driver)))
 		printk("%s(%d) failed to unregister tty driver err=%d\n",
 		       __FILE__,__LINE__,rc);
 
+	put_tty_driver(serial_driver);
 	info = mgsl_device_list;
 	while(info) {
 #ifdef CONFIG_SYNCLINK_SYNCPPP
diff -urN linux-2.5.70-bk16/drivers/char/synclinkmp.c linux-2.5.70-bk17/drivers/char/synclinkmp.c
--- linux-2.5.70-bk16/drivers/char/synclinkmp.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/synclinkmp.c	2003-06-12 04:49:56.000000000 -0700
@@ -166,8 +166,6 @@
 
 	struct mgsl_icount	icount;
 
-	struct termios		normal_termios;
-
 	struct tty_struct 	*tty;
 	int			timeout;
 	int			x_char;		/* xon/xoff character */
@@ -521,16 +519,11 @@
 };
 
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
 
-static struct tty_struct *serial_table[MAX_DEVICES];
-static struct termios *serial_termios[MAX_DEVICES];
-static struct termios *serial_termios_locked[MAX_DEVICES];
-
 #ifndef MIN
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #endif
@@ -802,12 +795,6 @@
 		goto cleanup;
 	}
 
-	if ((info->count == 1) &&
-	    info->flags & ASYNC_SPLIT_TERMIOS) {
-		*tty->termios = info->normal_termios;
-		change_params(info);
-	}
-
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):%s open() success\n",
 			 __FILE__,__LINE__, info->device_name);
@@ -859,12 +846,6 @@
 
 	info->flags |= ASYNC_CLOSING;
 
-	/* Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-
 	/* set tty->closing to notify line discipline to
 	 * only process XON/XOFF characters. Only the N_TTY
 	 * discipline appears to use this (ppp does not).
@@ -3765,6 +3746,30 @@
 	}
 }
 
+static struct tty_operations ops = {
+	.open = open,
+	.close = close,
+	.write = write,
+	.put_char = put_char,
+	.flush_chars = flush_chars,
+	.write_room = write_room,
+	.chars_in_buffer = chars_in_buffer,
+	.flush_buffer = flush_buffer,
+	.ioctl = ioctl,
+	.throttle = throttle,
+	.unthrottle = unthrottle,
+	.send_xchar = send_xchar,
+	.break_ctl = set_break,
+	.wait_until_sent = wait_until_sent,
+ 	.read_proc = read_proc,
+	.set_termios = set_termios,
+	.stop = tx_hold,
+	.start = tx_release,
+	.hangup = hangup,
+	.tiocmget = tiocmget,
+	.tiocmset = tiocmset,
+};
+
 /* Driver initialization entry point.
  */
 
@@ -3787,68 +3792,31 @@
 		return -ENODEV;
 	}
 
-	memset(serial_table,0,sizeof(struct tty_struct*)*MAX_DEVICES);
-	memset(serial_termios,0,sizeof(struct termios*)*MAX_DEVICES);
-	memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_DEVICES);
+	serial_driver = alloc_tty_driver(synclinkmp_device_count);
+	if (!serial_driver)
+		return -ENOMEM;
 
 	/* Initialize the tty_driver structure */
 
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.owner = THIS_MODULE;
-	serial_driver.driver_name = "synclinkmp";
-	serial_driver.name = "ttySLM";
-	serial_driver.major = ttymajor;
-	serial_driver.minor_start = 64;
-	serial_driver.num = synclinkmp_device_count;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = "synclinkmp";
+	serial_driver->name = "ttySLM";
+	serial_driver->major = ttymajor;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = open;
-	serial_driver.close = close;
-	serial_driver.write = write;
-	serial_driver.put_char = put_char;
-	serial_driver.flush_chars = flush_chars;
-	serial_driver.write_room = write_room;
-	serial_driver.chars_in_buffer = chars_in_buffer;
-	serial_driver.flush_buffer = flush_buffer;
-	serial_driver.ioctl = ioctl;
-	serial_driver.throttle = throttle;
-	serial_driver.unthrottle = unthrottle;
-	serial_driver.send_xchar = send_xchar;
-	serial_driver.break_ctl = set_break;
-	serial_driver.wait_until_sent = wait_until_sent;
- 	serial_driver.read_proc = read_proc;
-	serial_driver.set_termios = set_termios;
-	serial_driver.stop = tx_hold;
-	serial_driver.start = tx_release;
-	serial_driver.hangup = hangup;
-	serial_driver.tiocmget = tiocmget;
-	serial_driver.tiocmset = tiocmset;
-
-	if (tty_register_driver(&serial_driver) < 0)
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &ops);
+	if (tty_register_driver(serial_driver) < 0)
 		printk("%s(%d):Couldn't register serial driver\n",
 			__FILE__,__LINE__);
 
  	printk("%s %s, tty major#%d\n",
 		driver_name, driver_version,
-		serial_driver.major);
-
-	/* Propagate these values to all device instances */
-
-	info = synclinkmp_device_list;
-	while(info){
-		info->normal_termios  = serial_driver.init_termios;
-		info = info->next_device;
-	}
+		serial_driver->major);
 
 	return 0;
 }
@@ -3862,9 +3830,10 @@
 
 	printk("Unloading %s %s\n", driver_name, driver_version);
 
-	if ((rc = tty_unregister_driver(&serial_driver)))
+	if ((rc = tty_unregister_driver(serial_driver)))
 		printk("%s(%d) failed to unregister tty driver err=%d\n",
 		       __FILE__,__LINE__,rc);
+	put_tty_driver(serial_driver);
 
 	info = synclinkmp_device_list;
 	while(info) {
diff -urN linux-2.5.70-bk16/drivers/char/tty_io.c linux-2.5.70-bk17/drivers/char/tty_io.c
--- linux-2.5.70-bk16/drivers/char/tty_io.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/tty_io.c	2003-06-12 04:49:56.000000000 -0700
@@ -126,8 +126,8 @@
 struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
 
 #ifdef CONFIG_UNIX98_PTYS
-extern struct tty_driver ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
-extern struct tty_driver pts_driver;	/* Unix98 pty slaves;  for /dev/ptmx */
+extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
+extern struct tty_driver *pts_driver;	/* Unix98 pty slaves;  for /dev/ptmx */
 #endif
 
 extern void disable_early_printk(void);
@@ -810,7 +810,7 @@
 	down_tty_sem(idx);
 
 	/* check whether we're reopening an existing tty */
-	tty = driver->table[idx];
+	tty = driver->ttys[idx];
 	if (tty) goto fast_track;
 
 	/*
@@ -889,14 +889,14 @@
 		/*
 		 * Everything allocated ... set up the o_tty structure.
 		 */
-		driver->other->table[idx] = o_tty;
+		driver->other->ttys[idx] = o_tty;
 		if (!*o_tp_loc)
 			*o_tp_loc = o_tp;
 		if (!*o_ltp_loc)
 			*o_ltp_loc = o_ltp;
 		o_tty->termios = *o_tp_loc;
 		o_tty->termios_locked = *o_ltp_loc;
-		(*driver->other->refcount)++;
+		driver->other->refcount++;
 		if (driver->subtype == PTY_TYPE_MASTER)
 			o_tty->count++;
 
@@ -910,7 +910,7 @@
 	 * Failures after this point use release_mem to clean up, so 
 	 * there's no need to null out the local pointers.
 	 */
-	driver->table[idx] = tty;
+	driver->ttys[idx] = tty;
 	
 	if (!*tp_loc)
 		*tp_loc = tp;
@@ -918,7 +918,7 @@
 		*ltp_loc = ltp;
 	tty->termios = *tp_loc;
 	tty->termios_locked = *ltp_loc;
-	(*driver->refcount)++;
+	driver->refcount++;
 	tty->count++;
 
 	/* 
@@ -1010,28 +1010,28 @@
 	struct termios *tp;
 
 	if ((o_tty = tty->link) != NULL) {
-		o_tty->driver->table[idx] = NULL;
+		o_tty->driver->ttys[idx] = NULL;
 		if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
 			tp = o_tty->driver->termios[idx];
 			o_tty->driver->termios[idx] = NULL;
 			kfree(tp);
 		}
 		o_tty->magic = 0;
-		(*o_tty->driver->refcount)--;
+		o_tty->driver->refcount--;
 		file_list_lock();
 		list_del(&o_tty->tty_files);
 		file_list_unlock();
 		free_tty_struct(o_tty);
 	}
 
-	tty->driver->table[idx] = NULL;
+	tty->driver->ttys[idx] = NULL;
 	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
 		tp = tty->driver->termios[idx];
 		tty->driver->termios[idx] = NULL;
 		kfree(tp);
 	}
 	tty->magic = 0;
-	(*tty->driver->refcount)--;
+	tty->driver->refcount--;
 	file_list_lock();
 	list_del(&tty->tty_files);
 	file_list_unlock();
@@ -1073,7 +1073,7 @@
 				  "free (%s)\n", tty->name);
 		return;
 	}
-	if (tty != tty->driver->table[idx]) {
+	if (tty != tty->driver->ttys[idx]) {
 		printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
 				  "for (%s)\n", idx, tty->name);
 		return;
@@ -1099,7 +1099,7 @@
 
 #ifdef TTY_PARANOIA_CHECK
 	if (tty->driver->other) {
-		if (o_tty != tty->driver->other->table[idx]) {
+		if (o_tty != tty->driver->other->ttys[idx]) {
 			printk(KERN_DEBUG "release_dev: other->table[%d] "
 					  "not o_tty for (%s)\n",
 			       idx, tty->name);
@@ -1322,8 +1322,8 @@
 #ifdef CONFIG_VT
 	if (IS_CONSOLE_DEV(device)) {
 		extern int fg_console;
-		extern struct tty_driver console_driver;
-		driver = &console_driver;
+		extern struct tty_driver *console_driver;
+		driver = console_driver;
 		index = fg_console;
 		noctty = 1;
 		goto got_driver;
@@ -1349,14 +1349,14 @@
 #ifdef CONFIG_UNIX98_PTYS
 		/* find a device that is not in use. */
 		retval = -1;
-		driver = &ptm_driver;
+		driver = ptm_driver;
 		for (index = 0; index < driver->num ; index++)
 			if (!init_dev(driver, index, &tty))
 				goto ptmx_found; /* ok! */
 		return -EIO; /* no free ptys */
 	ptmx_found:
 		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
-		devpts_pty_new(index, MKDEV(pts_driver.major, pts_driver.minor_start) + index);
+		devpts_pty_new(index, MKDEV(pts_driver->major, pts_driver->minor_start) + index);
 		noctty = 1;
 #else
 		return -ENODEV;
@@ -2213,6 +2213,58 @@
 EXPORT_SYMBOL(tty_unregister_device);
 
 static struct kobject tty_kobj = {.name = "tty"};
+
+struct tty_driver *alloc_tty_driver(int lines)
+{
+	struct tty_driver *driver;
+
+	driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
+	if (driver) {
+		memset(driver, 0, sizeof(struct tty_driver));
+		driver->magic = TTY_DRIVER_MAGIC;
+		driver->num = lines;
+		/* later we'll move allocation of tables here */
+	}
+	return driver;
+}
+
+void put_tty_driver(struct tty_driver *driver)
+{
+	kfree(driver);
+}
+
+void tty_set_operations(struct tty_driver *driver, struct tty_operations *op)
+{
+	driver->open = op->open;
+	driver->close = op->close;
+	driver->write = op->write;
+	driver->put_char = op->put_char;
+	driver->flush_chars = op->flush_chars;
+	driver->write_room = op->write_room;
+	driver->chars_in_buffer = op->chars_in_buffer;
+	driver->ioctl = op->ioctl;
+	driver->set_termios = op->set_termios;
+	driver->throttle = op->throttle;
+	driver->unthrottle = op->unthrottle;
+	driver->stop = op->stop;
+	driver->start = op->start;
+	driver->hangup = op->hangup;
+	driver->break_ctl = op->break_ctl;
+	driver->flush_buffer = op->flush_buffer;
+	driver->set_ldisc = op->set_ldisc;
+	driver->wait_until_sent = op->wait_until_sent;
+	driver->send_xchar = op->send_xchar;
+	driver->read_proc = op->read_proc;
+	driver->write_proc = op->write_proc;
+	driver->tiocmget = op->tiocmget;
+	driver->tiocmset = op->tiocmset;
+}
+
+
+EXPORT_SYMBOL(alloc_tty_driver);
+EXPORT_SYMBOL(put_tty_driver);
+EXPORT_SYMBOL(tty_set_operations);
+
 /*
  * Called by a tty driver to register itself.
  */
@@ -2222,10 +2274,16 @@
         int i;
 	dev_t dev;
 	char *s;
+	void **p;
 
 	if (driver->flags & TTY_DRIVER_INSTALLED)
 		return 0;
 
+	p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+	memset(p, 0, driver->num * 3 * sizeof(void *));
+
 	if (!driver->major) {
 		error = alloc_chrdev_region(&dev, driver->minor_start, driver->num,
 						(char*)driver->name);
@@ -2238,8 +2296,14 @@
 		error = register_chrdev_region(dev, driver->num,
 						(char*)driver->name);
 	}
-	if (error < 0)
+	if (error < 0) {
+		kfree(p);
 		return error;
+	}
+
+	driver->ttys = (struct tty_struct **)p;
+	driver->termios = (struct termios **)(p + driver->num);
+	driver->termios_locked = (struct termios **)(p + driver->num * 2);
 
 	driver->cdev.kobj.parent = &tty_kobj;
 	strcpy(driver->cdev.kobj.name, driver->name);
@@ -2251,6 +2315,9 @@
 	if (error) {
 		kobject_del(&driver->cdev.kobj);
 		unregister_chrdev_region(dev, driver->num);
+		driver->ttys = NULL;
+		driver->termios = driver->termios_locked = NULL;
+		kfree(p);
 		return error;
 	}
 
@@ -2274,8 +2341,9 @@
 {
 	int i;
 	struct termios *tp;
+	void *p;
 
-	if (*driver->refcount)
+	if (driver->refcount)
 		return -EBUSY;
 
 	cdev_unmap(MKDEV(driver->major, driver->minor_start), driver->num);
@@ -2303,7 +2371,11 @@
 		if (!(driver->flags & TTY_DRIVER_NO_DEVFS))
 			tty_unregister_device(driver, i);
 	}
+	p = driver->ttys;
 	proc_tty_unregister_driver(driver);
+	driver->ttys = NULL;
+	driver->termios = driver->termios_locked = NULL;
+	kfree(p);
 	cdev_del(&driver->cdev);
 	return 0;
 }
diff -urN linux-2.5.70-bk16/drivers/char/vme_scc.c linux-2.5.70-bk17/drivers/char/vme_scc.c
--- linux-2.5.70-bk16/drivers/char/vme_scc.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/vme_scc.c	2003-06-12 04:49:56.000000000 -0700
@@ -90,14 +90,10 @@
 static void scc_setsignals(struct scc_port *port, int dtr, int rts);
 static void scc_break_ctl(struct tty_struct *tty, int break_state);
 
-static struct tty_driver scc_driver;
+static struct tty_driver *scc_driver;
 
-static struct tty_struct *scc_table[2] = { NULL, };
-static struct termios * scc_termios[2];
-static struct termios * scc_termios_locked[2];
 struct scc_port scc_ports[2];
 
-int scc_refcount;
 int scc_initialized = 0;
 
 /*---------------------------------------------------------------------------
@@ -119,6 +115,25 @@
 };
 
 
+static struct tty_operations scc_ops = {
+	.open	= scc_open,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = scc_ioctl,
+	.throttle = scc_throttle,
+	.unthrottle = scc_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+	.break_ctl = scc_break_ctl,
+};
+
 /*----------------------------------------------------------------------------
  * vme_scc_init() and support functions
  *---------------------------------------------------------------------------*/
@@ -127,46 +142,27 @@
 {
 	int error;
 
-	memset(&scc_driver, 0, sizeof(scc_driver));
-	scc_driver.magic = TTY_DRIVER_MAGIC;
-	scc_driver.owner = THIS_MODULE;
-	scc_driver.driver_name = "scc";
-	scc_driver.name = "ttyS";
-	scc_driver.devfs_name = "tts/";
-	scc_driver.major = TTY_MAJOR;
-	scc_driver.minor_start = SCC_MINOR_BASE;
-	scc_driver.num = 2;
-	scc_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	scc_driver.subtype = SERIAL_TYPE_NORMAL;
-	scc_driver.init_termios = tty_std_termios;
-	scc_driver.init_termios.c_cflag =
+	scc_driver = alloc_tty_driver(2);
+	if (!scc_driver)
+		return -ENOMEM;
+	scc_driver->owner = THIS_MODULE;
+	scc_driver->driver_name = "scc";
+	scc_driver->name = "ttyS";
+	scc_driver->devfs_name = "tts/";
+	scc_driver->major = TTY_MAJOR;
+	scc_driver->minor_start = SCC_MINOR_BASE;
+	scc_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	scc_driver->subtype = SERIAL_TYPE_NORMAL;
+	scc_driver->init_termios = tty_std_termios;
+	scc_driver->init_termios.c_cflag =
 	  B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	scc_driver.flags = TTY_DRIVER_REAL_RAW;
-	scc_driver.refcount = &scc_refcount;
-	scc_driver.table = scc_table;
-	scc_driver.termios = scc_termios;
-	scc_driver.termios_locked = scc_termios_locked;
-
-	scc_driver.open	= scc_open;
-	scc_driver.close = gs_close;
-	scc_driver.write = gs_write;
-	scc_driver.put_char = gs_put_char;
-	scc_driver.flush_chars = gs_flush_chars;
-	scc_driver.write_room = gs_write_room;
-	scc_driver.chars_in_buffer = gs_chars_in_buffer;
-	scc_driver.flush_buffer = gs_flush_buffer;
-	scc_driver.ioctl = scc_ioctl;
-	scc_driver.throttle = scc_throttle;
-	scc_driver.unthrottle = scc_unthrottle;
-	scc_driver.set_termios = gs_set_termios;
-	scc_driver.stop = gs_stop;
-	scc_driver.start = gs_start;
-	scc_driver.hangup = gs_hangup;
-	scc_driver.break_ctl = scc_break_ctl;
+	scc_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(scc_driver, &scc_ops);
 
-	if ((error = tty_register_driver(&scc_driver))) {
+	if ((error = tty_register_driver(scc_driver))) {
 		printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
 		       error);
+		put_tty_driver(scc_driver);
 		return 1;
 	}
 
@@ -184,7 +180,6 @@
 
 	for (i = 0; i < 2; i++) {
 		port = scc_ports + i;
-		port->gs.normal_termios = tty_std_termios;
 		port->gs.magic = SCC_MAGIC;
 		port->gs.close_delay = HZ/2;
 		port->gs.closing_wait = 30 * HZ;
@@ -922,11 +917,6 @@
 		return retval;
 	}
 
-	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = port->gs.normal_termios;
-		scc_set_real_termios (port);
-	}
-
 	port->c_dcd = scc_get_CD (port);
 
 	scc_enable_rx_interrupts(port);
@@ -1040,7 +1030,7 @@
 static struct tty_driver *scc_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &scc_driver;
+	return scc_driver;
 }
 
 
diff -urN linux-2.5.70-bk16/drivers/char/vt.c linux-2.5.70-bk17/drivers/char/vt.c
--- linux-2.5.70-bk16/drivers/char/vt.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/vt.c	2003-06-12 04:49:56.000000000 -0700
@@ -90,6 +90,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
+#include <linux/tiocl.h>
 #include <linux/kbd_kern.h>
 #include <linux/consolemap.h>
 #include <linux/timer.h>
@@ -138,9 +139,6 @@
 extern int fb_console_init(void);
 #endif
 
-static struct tty_struct *console_table[MAX_NR_CONSOLES];
-static struct termios *console_termios[MAX_NR_CONSOLES];
-static struct termios *console_termios_locked[MAX_NR_CONSOLES];
 struct vc vc_cons [MAX_NR_CONSOLES];
 
 #ifndef VT_SINGLE_DRIVER
@@ -2187,12 +2185,12 @@
 	clear_bit(0, &printing);
 }
 
-struct tty_driver console_driver;
+struct tty_driver *console_driver;
 
 static struct tty_driver *vt_console_device(struct console *c, int *index)
 {
 	*index = c->index ? c->index-1 : fg_console;
-	return &console_driver;
+	return console_driver;
 }
 
 struct console vt_console_driver = {
@@ -2235,21 +2233,21 @@
 	ret = 0;
 	switch (type)
 	{
-		case 2:
+		case TIOCL_SETSEL:
 			acquire_console_sem();
-			ret = set_selection(arg, tty, 1);
+			ret = set_selection((struct tiocl_selection *)((char *)arg+1), tty, 1);
 			release_console_sem();
 			break;
-		case 3:
+		case TIOCL_PASTESEL:
 			ret = paste_selection(tty);
 			break;
-		case 4:
+		case TIOCL_UNBLANKSCREEN:
 			unblank_screen();
 			break;
-		case 5:
+		case TIOCL_SELLOADLUT:
 			ret = sel_loadlut(arg);
 			break;
-		case 6:
+		case TIOCL_GETSHIFTSTATE:
 			
 	/*
 	 * Make it possible to react to Shift+Mousebutton.
@@ -2260,14 +2258,14 @@
 	 		data = shift_state;
 			ret = __put_user(data, (char *) arg);
 			break;
-		case 7:
+		case TIOCL_GETMOUSEREPORTING:
 			data = mouse_reporting();
 			ret = __put_user(data, (char *) arg);
 			break;
-		case 10:
+		case TIOCL_SETVESABLANK:
 			set_vesa_blanking(arg);
 			break;;
-		case 11:	/* set kmsg redirect */
+		case TIOCL_SETKMSGREDIRECT:
 			if (!capable(CAP_SYS_ADMIN)) {
 				ret = -EPERM;
 			} else {
@@ -2277,10 +2275,10 @@
 					kmsg_redirect = data;
 			}
 			break;
-		case 12:	/* get fg_console */
+		case TIOCL_GETFGCONSOLE:
 			ret = fg_console;
 			break;
-		case 13:	/* scroll console */
+		case TIOCL_SCROLLCONSOLE:
 			if (get_user(lines, (char *)arg+1)) {
 				ret = -EFAULT;
 			} else {
@@ -2288,11 +2286,11 @@
 				ret = 0;
 			}
 			break;
-		case 14:	/* blank screen until explicitly unblanked, not only poked */
+		case TIOCL_BLANKSCREEN:	/* until explicitly unblanked, not only poked */
 			ignore_poke = 1;
 			do_blank_screen(0);
 			break;
-		case 15:	/* which console is blanked ? */
+		case TIOCL_BLANKEDSCREEN:
 			ret = console_blanked;
 			break;
 		default:
@@ -2472,8 +2470,6 @@
  * the appropriate escape-sequence.
  */
 
-static int console_refcount;
-
 static int __init con_init(void)
 {
 	const char *display_desc = NULL;
@@ -2526,39 +2522,37 @@
 }
 console_initcall(con_init);
 
+static struct tty_operations con_ops = {
+	.open = con_open,
+	.close = con_close,
+	.write = con_write,
+	.write_room = con_write_room,
+	.put_char = con_put_char,
+	.flush_chars = con_flush_chars,
+	.chars_in_buffer = con_chars_in_buffer,
+	.ioctl = vt_ioctl,
+	.stop = con_stop,
+	.start = con_start,
+	.throttle = con_throttle,
+	.unthrottle = con_unthrottle,
+};
+
 int __init vty_init(void)
 {
-	memset(&console_driver, 0, sizeof(struct tty_driver));
-	console_driver.magic = TTY_DRIVER_MAGIC;
-	console_driver.owner = THIS_MODULE;
-	console_driver.devfs_name = "vc/";
-	console_driver.name = "tty";
-	console_driver.name_base = 1;
-	console_driver.major = TTY_MAJOR;
-	console_driver.minor_start = 1;
-	console_driver.num = MAX_NR_CONSOLES;
-	console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
-	console_driver.init_termios = tty_std_termios;
-	console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
-	console_driver.refcount = &console_refcount;
-	console_driver.table = console_table;
-	console_driver.termios = console_termios;
-	console_driver.termios_locked = console_termios_locked;
-
-	console_driver.open = con_open;
-	console_driver.close = con_close;
-	console_driver.write = con_write;
-	console_driver.write_room = con_write_room;
-	console_driver.put_char = con_put_char;
-	console_driver.flush_chars = con_flush_chars;
-	console_driver.chars_in_buffer = con_chars_in_buffer;
-	console_driver.ioctl = vt_ioctl;
-	console_driver.stop = con_stop;
-	console_driver.start = con_start;
-	console_driver.throttle = con_throttle;
-	console_driver.unthrottle = con_unthrottle;
-
-	if (tty_register_driver(&console_driver))
+	console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
+	if (!console_driver)
+		panic("Couldn't allocate console driver\n");
+	console_driver->owner = THIS_MODULE;
+	console_driver->devfs_name = "vc/";
+	console_driver->name = "tty";
+	console_driver->name_base = 1;
+	console_driver->major = TTY_MAJOR;
+	console_driver->minor_start = 1;
+	console_driver->type = TTY_DRIVER_TYPE_CONSOLE;
+	console_driver->init_termios = tty_std_termios;
+	console_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
+	tty_set_operations(console_driver, &con_ops);
+	if (tty_register_driver(console_driver))
 		panic("Couldn't register console driver\n");
 
 	kbd_init();
diff -urN linux-2.5.70-bk16/drivers/char/vt_ioctl.c linux-2.5.70-bk17/drivers/char/vt_ioctl.c
--- linux-2.5.70-bk16/drivers/char/vt_ioctl.c	2003-05-26 18:00:44.000000000 -0700
+++ linux-2.5.70-bk17/drivers/char/vt_ioctl.c	2003-06-12 04:49:56.000000000 -0700
@@ -34,9 +34,9 @@
 #include <linux/selection.h>
 
 char vt_dont_switch;
-extern struct tty_driver console_driver;
+extern struct tty_driver *console_driver;
 
-#define VT_IS_IN_USE(i)	(console_driver.table[i] && console_driver.table[i]->count)
+#define VT_IS_IN_USE(i)	(console_driver->ttys[i] && console_driver->ttys[i]->count)
 #define VT_BUSY(i)	(VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
 
 /*
diff -urN linux-2.5.70-bk16/drivers/i2c/Kconfig linux-2.5.70-bk17/drivers/i2c/Kconfig
--- linux-2.5.70-bk16/drivers/i2c/Kconfig	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/i2c/Kconfig	2003-06-12 04:49:56.000000000 -0700
@@ -193,6 +193,10 @@
 	tristate "IBM on-chip I2C Adapter"
 	depends on I2C_IBM_OCP_ALGO
 
+config I2C_IOP3XX
+	tristate "Intel XScale IOP3xx on-chip I2C interface"
+	depends on ARCH_IOP3XX && I2C
+
 config I2C_CHARDEV
 	tristate "I2C device interface"
 	depends on I2C
diff -urN linux-2.5.70-bk16/drivers/i2c/Makefile linux-2.5.70-bk17/drivers/i2c/Makefile
--- linux-2.5.70-bk16/drivers/i2c/Makefile	2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk17/drivers/i2c/Makefile	2003-06-12 04:49:56.000000000 -0700
@@ -16,4 +16,5 @@
 obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
 obj-$(CONFIG_I2C_SENSOR)	+= i2c-sensor.o
+obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-y				+= busses/ chips/
diff -urN linux-2.5.70-bk16/drivers/i2c/chips/Kconfig linux-2.5.70-bk17/drivers/i2c/chips/Kconfig
--- linux-2.5.70-bk16/drivers/i2c/chips/Kconfig	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/drivers/i2c/chips/Kconfig	2003-06-12 04:49:56.000000000 -0700
@@ -47,6 +47,21 @@
 	  in the lm_sensors package, which you can download at 
 	  http://www.lm-sensors.nu
 	  
+config SENSORS_LM85
+	tristate "  National Semiconductors LM85 and compatibles"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for National Semiconductor LM85
+	  sensor chips and clones: ADT7463 and ADM1027.
+	  This can also be built as a module which can be inserted and
+	  removed while the kernel is running.
+
+	  The module will be called lm85.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at 
+	  http://www.lm-sensors.nu
+	  
 config SENSORS_VIA686A
 	tristate "  VIA686A"
 	depends on I2C && EXPERIMENTAL
@@ -76,8 +91,8 @@
 
 config I2C_SENSOR
 	tristate
-	default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y
-	default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m
+	default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y || SENSORS_LM85=y
+	default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m || SENSORS_LM85=m
 	default n
 
 endmenu
diff -urN linux-2.5.70-bk16/drivers/i2c/chips/Makefile linux-2.5.70-bk17/drivers/i2c/chips/Makefile
--- linux-2.5.70-bk16/drivers/i2c/chips/Makefile	2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk17/drivers/i2c/chips/Makefile	2003-06-12 04:49:56.000000000 -0700
@@ -5,5 +5,6 @@
 obj-$(CONFIG_SENSORS_ADM1021)	+= adm1021.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
 obj-$(CONFIG_SENSORS_LM75)	+= lm75.o
+obj-$(CONFIG_SENSORS_LM85)	+= lm85.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_W83781D)	+= w83781d.o
diff -urN linux-2.5.70-bk16/drivers/i2c/chips/lm85.c linux-2.5.70-bk17/drivers/i2c/chips/lm85.c
--- linux-2.5.70-bk16/drivers/i2c/chips/lm85.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk17/drivers/i2c/chips/lm85.c	2003-06-12 04:49:56.000000000 -0700
@@ -0,0 +1,1223 @@
+/*
+    lm85.c - Part of lm_sensors, Linux kernel modules for hardware
+             monitoring
+    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
+    Copyright (c) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
+    Copyright (c) 2003        Margit Schubert-While <margitsw@t-online.de>
+
+    Chip details at	      <http://www.national.com/ds/LM/LM85.pdf>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+/*
+#include <asm/io.h>
+*/
+
+#undef	LM85EXTENDEDFUNC	/* Extended functionality */
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_4(lm85b, lm85c, adm1027, adt7463);
+
+/* Enable debug if true */
+static int	lm85debug = 0;
+
+/* The LM85 registers */
+
+#define	LM85_REG_IN(nr)			(0x20 + (nr))
+#define	LM85_REG_IN_MIN(nr)		(0x44 + (nr) * 2)
+#define	LM85_REG_IN_MAX(nr)		(0x45 + (nr) * 2)
+
+#define	LM85_REG_TEMP(nr)		(0x25 + (nr))
+#define	LM85_REG_TEMP_MIN(nr)		(0x4e + (nr) * 2)
+#define	LM85_REG_TEMP_MAX(nr)		(0x4f + (nr) * 2)
+
+/* Fan speeds are LSB, MSB (2 bytes) */
+#define	LM85_REG_FAN(nr)		(0x28 + (nr) *2)
+#define	LM85_REG_FAN_MIN(nr)		(0x54 + (nr) *2)
+
+#define	LM85_REG_PWM(nr)		(0x30 + (nr))
+
+#define	ADT7463_REG_OPPOINT(nr)		(0x33 + (nr))
+
+#define	ADT7463_REG_TMIN_CTL1		0x36
+#define	ADT7463_REG_TMIN_CTL2		0x37
+
+#define	LM85_REG_DEVICE			0x3d
+#define	LM85_REG_COMPANY		0x3e
+#define	LM85_REG_VERSTEP		0x3f
+/* These are the recognized values for the above regs */
+#define	LM85_DEVICE_ADX			0x27
+#define	LM85_COMPANY_NATIONAL		0x01
+#define	LM85_COMPANY_ANALOG_DEV		0x41
+#define	LM85_VERSTEP_GENERIC		0x60
+#define	LM85_VERSTEP_LM85C		0x60
+#define	LM85_VERSTEP_LM85B		0x62
+#define	LM85_VERSTEP_ADM1027		0x60
+#define	LM85_VERSTEP_ADT7463		0x62
+
+#define	LM85_REG_CONFIG			0x40
+
+#define	LM85_REG_ALARM1			0x41
+#define	LM85_REG_ALARM2			0x42
+
+#define	LM85_REG_VID			0x43
+
+/* Automated FAN control */
+#define	LM85_REG_AFAN_CONFIG(nr)	(0x5c + (nr))
+#define	LM85_REG_AFAN_RANGE(nr)		(0x5f + (nr))
+#define	LM85_REG_AFAN_SPIKE1		0x62
+#define	LM85_REG_AFAN_SPIKE2		0x63
+#define	LM85_REG_AFAN_MINPWM(nr)	(0x64 + (nr))
+#define	LM85_REG_AFAN_LIMIT(nr)		(0x67 + (nr))
+#define	LM85_REG_AFAN_CRITICAL(nr)	(0x6a + (nr))
+#define	LM85_REG_AFAN_HYST1		0x6d
+#define	LM85_REG_AFAN_HYST2		0x6e
+
+#define	LM85_REG_TACH_MODE		0x74
+#define	LM85_REG_SPINUP_CTL		0x75
+
+#define	ADM1027_REG_TEMP_OFFSET(nr)	(0x70 + (nr))
+#define	ADM1027_REG_CONFIG2		0x73
+#define	ADM1027_REG_INTMASK1		0x74
+#define	ADM1027_REG_INTMASK2		0x75
+#define	ADM1027_REG_EXTEND_ADC1		0x76
+#define	ADM1027_REG_EXTEND_ADC2		0x77
+#define	ADM1027_REG_CONFIG3		0x78
+#define	ADM1027_REG_FAN_PPR		0x7b
+
+#define	ADT7463_REG_THERM		0x79
+#define	ADT7463_REG_THERM_LIMIT		0x7A
+
+#define	LM85_ALARM_IN0			0x0001
+#define	LM85_ALARM_IN1			0x0002
+#define	LM85_ALARM_IN2			0x0004
+#define	LM85_ALARM_IN3			0x0008
+#define	LM85_ALARM_TEMP1		0x0010
+#define	LM85_ALARM_TEMP2		0x0020
+#define	LM85_ALARM_TEMP3		0x0040
+#define	LM85_ALARM_ALARM2		0x0080
+#define	LM85_ALARM_IN4			0x0100
+#define	LM85_ALARM_RESERVED		0x0200
+#define	LM85_ALARM_FAN1			0x0400
+#define	LM85_ALARM_FAN2			0x0800
+#define	LM85_ALARM_FAN3			0x1000
+#define	LM85_ALARM_FAN4			0x2000
+#define	LM85_ALARM_TEMP1_FAULT		0x4000
+#define	LM85_ALARM_TEMP3_FAULT		0x8000
+
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG 
+   variants. Note that you should be a bit careful with which arguments
+   these macros are called: arguments may be evaluated more than once.
+ */
+
+/* IN are scaled 1.000 == 0xc0, mag = 3 */
+#define IN_TO_REG(val)		(SENSORS_LIMIT((((val)*0xc0+500)/1000),0,255))
+#define INEXT_FROM_REG(val,ext) (((val)*1000 + (ext)*250 + 96)/0xc0)
+#define IN_FROM_REG(val)	(INEXT_FROM_REG(val,0))
+
+/* IN are scaled acording to built-in resistors */
+static int lm85_scaling[] = {  /* .001 Volts */
+		2500, 2250, 3300, 5000, 12000
+	};
+#define SCALE(val,from,to)		(((val)*(to) + ((from)/2))/(from))
+#define INS_TO_REG(n,val)		(SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255))
+#define INSEXT_FROM_REG(n,val,ext)	(SCALE((val)*4 + (ext),192*4,lm85_scaling[n]))
+/*
+#define INS_FROM_REG(n,val)		(INSEXT_FROM_REG(n,val,0))
+*/
+#define INS_FROM_REG(n,val)		( ( (val*4*lm85_scaling[n]) + (192*4/2) ) / (192*4) )
+
+/* FAN speed is measured using 90kHz clock */
+#define FAN_TO_REG(val)		(SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
+#define FAN_FROM_REG(val)	((val)==0?-1:(val)==0xffff?0:5400000/(val))
+
+/* Temperature is reported in .01 degC increments */
+#define TEMP_TO_REG(val)		(SENSORS_LIMIT(((val)+50)/100,-127,127))
+#define TEMPEXT_FROM_REG(val,ext)	((val)*100 + (ext)*25)
+#define TEMP_FROM_REG(val)		(TEMPEXT_FROM_REG(val,0))
+#define EXTTEMP_TO_REG(val)		(SENSORS_LIMIT((val)/25,-127,127))
+
+#define PWM_TO_REG(val)			(SENSORS_LIMIT(val,0,255))
+#define PWM_FROM_REG(val)		(val)
+
+#define EXT_FROM_REG(val,sensor)	(((val)>>(sensor * 2))&0x03)
+
+#ifdef	LM85EXTENDEDFUNC	/* Extended functionality */
+
+/* ZONEs have the following parameters:
+ *    Limit (low) temp,           1. degC
+ *    Hysteresis (below limit),   1. degC (0-15)
+ *    Range of speed control,     .1 degC (2-80)
+ *    Critical (high) temp,       1. degC
+ *
+ * FAN PWMs have the following parameters:
+ *    Reference Zone,                 1, 2, 3, etc.
+ *    Spinup time,                    .05 sec
+ *    PWM value at limit/low temp,    1 count
+ *    PWM Frequency,                  1. Hz
+ *    PWM is Min or OFF below limit,  flag
+ *    Invert PWM output,              flag
+ *
+ * Some chips filter the temp, others the fan.
+ *    Filter constant (or disabled)   .1 seconds
+ */
+
+/* These are the zone temperature range encodings */
+static int lm85_range_map[] = {   /* .1 degC */
+		 20,  25,  33,  40,  50,  66,
+		 80, 100, 133, 160, 200, 266,
+		320, 400, 533, 800
+	};
+static int RANGE_TO_REG( int range )
+{
+	int i;
+
+	if( range >= lm85_range_map[15] ) { return 15 ; }
+	for( i = 0 ; i < 15 ; ++i )
+		if( range <= lm85_range_map[i] )
+			break ;
+	return( i & 0x0f );
+}
+#define RANGE_FROM_REG(val) (lm85_range_map[(val)&0x0f])
+
+/* These are the Acoustic Enhancement, or Temperature smoothing encodings
+ * NOTE: The enable/disable bit is INCLUDED in these encodings as the
+ *       MSB (bit 3, value 8).  If the enable bit is 0, the encoded value
+ *       is ignored, or set to 0.
+ */
+static int lm85_smooth_map[] = {  /* .1 sec */
+		350, 176, 118,  70,  44,   30,   16,    8
+/*    35.4 *    1/1, 1/2, 1/3, 1/5, 1/8, 1/12, 1/24, 1/48  */
+	};
+static int SMOOTH_TO_REG( int smooth )
+{
+	int i;
+
+	if( smooth <= 0 ) { return 0 ; }  /* Disabled */
+	for( i = 0 ; i < 7 ; ++i )
+		if( smooth >= lm85_smooth_map[i] )
+			break ;
+	return( (i & 0x07) | 0x08 );
+}
+#define SMOOTH_FROM_REG(val) ((val)&0x08?lm85_smooth_map[(val)&0x07]:0)
+
+/* These are the fan spinup delay time encodings */
+static int lm85_spinup_map[] = {  /* .1 sec */
+		0, 1, 2, 4, 7, 10, 20, 40
+	};
+static int SPINUP_TO_REG( int spinup )
+{
+	int i;
+
+	if( spinup >= lm85_spinup_map[7] ) { return 7 ; }
+	for( i = 0 ; i < 7 ; ++i )
+		if( spinup <= lm85_spinup_map[i] )
+			break ;
+	return( i & 0x07 );
+}
+#define SPINUP_FROM_REG(val) (lm85_spinup_map[(val)&0x07])
+
+/* These are the PWM frequency encodings */
+static int lm85_freq_map[] = { /* .1 Hz */
+		100, 150, 230, 300, 380, 470, 620, 980
+	};
+static int FREQ_TO_REG( int freq )
+{
+	int i;
+
+	if( freq >= lm85_freq_map[7] ) { return 7 ; }
+	for( i = 0 ; i < 7 ; ++i )
+		if( freq <= lm85_freq_map[i] )
+			break ;
+	return( i & 0x07 );
+}
+#define FREQ_FROM_REG(val) (lm85_freq_map[(val)&0x07])
+
+/* Since we can't use strings, I'm abusing these numbers
+ *   to stand in for the following meanings:
+ *      1 -- PWM responds to Zone 1
+ *      2 -- PWM responds to Zone 2
+ *      3 -- PWM responds to Zone 3
+ *     23 -- PWM responds to the higher temp of Zone 2 or 3
+ *    123 -- PWM responds to highest of Zone 1, 2, or 3
+ *      0 -- PWM is always at 0% (ie, off)
+ *     -1 -- PWM is always at 100%
+ *     -2 -- PWM responds to manual control
+ */
+
+#endif		/* Extended functionality */
+
+static int lm85_zone_map[] = { 1, 2, 3, -1, 0, 23, 123, -2 };
+#define ZONE_FROM_REG(val) (lm85_zone_map[((val)>>5)&0x07])
+
+#ifdef	LM85EXTENDEDFUNC	/* Extended functionality */
+
+static int ZONE_TO_REG( int zone )
+{
+	int i;
+
+	for( i = 0 ; i <= 7 ; ++i )
+		if( zone == lm85_zone_map[i] )
+			break ;
+	if( i > 7 )   /* Not found. */
+		i = 3;  /* Always 100% */
+	return( (i & 0x07)<<5 );
+}
+
+#endif		/* Extended functionality */
+
+#define HYST_TO_REG(val) (SENSORS_LIMIT((-(val)+5)/10,0,15))
+#define HYST_FROM_REG(val) (-(val)*10)
+
+#define OFFSET_TO_REG(val) (SENSORS_LIMIT((val)/25,-127,127))
+#define OFFSET_FROM_REG(val) ((val)*25)
+
+#define PPR_MASK(fan) (0x03<<(fan *2))
+#define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
+#define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
+
+/* i2c-vid.h defines vid_from_reg() */
+#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
+
+#define ALARMS_FROM_REG(val) (val)
+
+/* Unlike some other drivers we DO NOT set initial limits.  Use
+ * the config file to set limits.  Some users have reported
+ * motherboards shutting down when we set limits in a previous
+ * version of the driver.
+ */
+
+/* Typically used with Pentium 4 systems v9.1 VRM spec */
+#define LM85_INIT_VRM  91
+
+/* Chip sampling rates
+ *
+ * Some sensors are not updated more frequently than once per second
+ *    so it doesn't make sense to read them more often than that.
+ *    We cache the results and return the saved data if the driver
+ *    is called again before a second has elapsed.
+ *
+ * Also, there is significant configuration data for this chip
+ *    given the automatic PWM fan control that is possible.  There
+ *    are about 47 bytes of config data to only 22 bytes of actual
+ *    readings.  So, we keep the config data up to date in the cache
+ *    when it is written and only sample it once every 1 *minute*
+ */
+#define LM85_DATA_INTERVAL  (HZ + HZ / 2)
+#define LM85_CONFIG_INTERVAL  (1 * 60 * HZ)
+
+/* For each registered LM85, we need to keep some data in memory. That
+   data is pointed to by lm85_list[NR]->data. The structure itself is
+   dynamically allocated, at the same time when a new lm85 client is
+   allocated. */
+
+/* LM85 can automatically adjust fan speeds based on temperature
+ * This structure encapsulates an entire Zone config.  There are
+ * three zones (one for each temperature input) on the lm85
+ */
+struct lm85_zone {
+	s8 limit;	/* Low temp limit */
+	u8 hyst;	/* Low limit hysteresis. (0-15) */
+	u8 range;	/* Temp range, encoded */
+	s8 critical;	/* "All fans ON" temp limit */
+};
+
+struct lm85_autofan {
+	u8 config;	/* Register value */
+	u8 freq;	/* PWM frequency, encoded */
+	u8 min_pwm;	/* Minimum PWM value, encoded */
+	u8 min_off;	/* Min PWM or OFF below "limit", flag */
+};
+
+struct lm85_data {
+	struct semaphore lock;
+	enum chips type;
+
+	struct semaphore update_lock;
+	int valid;		/* !=0 if following fields are valid */
+	unsigned long last_reading;	/* In jiffies */
+	unsigned long last_config;	/* In jiffies */
+
+	u8 in[5];		/* Register value */
+	u8 in_max[5];		/* Register value */
+	u8 in_min[5];		/* Register value */
+	s8 temp[3];		/* Register value */
+	s8 temp_min[3];		/* Register value */
+	s8 temp_max[3];		/* Register value */
+	s8 temp_offset[3];	/* Register value */
+	u16 fan[4];		/* Register value */
+	u16 fan_min[4];		/* Register value */
+	u8 pwm[3];		/* Register value */
+	u8 spinup_ctl;		/* Register encoding, combined */
+	u8 tach_mode;		/* Register encoding, combined */
+	u16 extend_adc;		/* Register value */
+	u8 fan_ppr;		/* Register value */
+	u8 smooth[3];		/* Register encoding */
+	u8 vid;			/* Register value */
+	u8 vrm;			/* VRM version */
+	u8 syncpwm3;		/* Saved PWM3 for TACH 2,3,4 config */
+	u8 oppoint[3];		/* Register value */
+	u16 tmin_ctl;		/* Register value */
+	u32 therm_total;	/* Cummulative therm count */
+	u8 therm_limit;		/* Register value */
+	u16 alarms;		/* Register encoding, combined */
+	struct lm85_autofan autofan[3];
+	struct lm85_zone zone[3];
+};
+
+static int lm85_attach_adapter(struct i2c_adapter *adapter);
+static int lm85_detect(struct i2c_adapter *adapter, int address,
+			int kind);
+static int lm85_detach_client(struct i2c_client *client);
+
+static int lm85_read_value(struct i2c_client *client, u8 register);
+static int lm85_write_value(struct i2c_client *client, u8 register, int value);
+static void lm85_update_client(struct i2c_client *client);
+static void lm85_init_client(struct i2c_client *client);
+
+
+static struct i2c_driver lm85_driver = {
+	.owner          = THIS_MODULE,
+	.name           = "lm85",
+	.id             = I2C_DRIVERID_LM85,
+	.flags          = I2C_DF_NOTIFY,
+	.attach_adapter = lm85_attach_adapter,
+	.detach_client  = lm85_detach_client,
+};
+
+/* Unique ID assigned to each LM85 detected */
+static int lm85_id = 0;
+
+
+/* 4 Fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr]) );
+}
+static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr]) );
+}
+static ssize_t set_fan_min(struct device *dev, const char *buf, 
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	int val = simple_strtol(buf, NULL, 10);
+	data->fan_min[nr] = FAN_TO_REG(val);
+	lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]);
+	return count;
+}
+
+#define show_fan_offset(offset)						\
+static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
+{									\
+	return show_fan(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\
+{									\
+	return show_fan_min(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t set_fan_##offset##_min (struct device *dev, 		\
+	const char *buf, size_t count) 					\
+{									\
+	return set_fan_min(dev, buf, count, 0x##offset - 1);		\
+}									\
+static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_fan_##offset, NULL) \
+static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, 			\
+		show_fan_##offset##_min, set_fan_##offset##_min)
+
+show_fan_offset(1);
+show_fan_offset(2);
+show_fan_offset(3);
+show_fan_offset(4);
+
+/* vid, vrm, alarms */
+
+static ssize_t show_vid_reg(struct device *dev, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL)
+
+static ssize_t show_vrm_reg(struct device *dev, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf, "%ld\n", (long) data->vrm);
+}
+
+static ssize_t store_vrm_reg(struct device *dev, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->vrm = val;
+	return count;
+}
+
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg)
+
+static ssize_t show_alarms_reg(struct device *dev, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+
+/* pwm */
+
+static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm[nr]) );
+}
+static ssize_t set_pwm(struct device *dev, const char *buf, 
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	int val = simple_strtol(buf, NULL, 10);
+	data->pwm[nr] = PWM_TO_REG(val);
+	lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]);
+	return count;
+}
+static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+	int	pwm_zone;
+
+	lm85_update_client(client);
+	pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
+	return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) );
+}
+
+#define show_pwm_reg(offset)						\
+static ssize_t show_pwm_##offset (struct device *dev, char *buf)	\
+{									\
+	return show_pwm(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t set_pwm_##offset (struct device *dev,			\
+				 const char *buf, size_t count)		\
+{									\
+	return set_pwm(dev, buf, count, 0x##offset - 1);		\
+}									\
+static ssize_t show_pwm_enable##offset (struct device *dev, char *buf)	\
+{									\
+	return show_pwm_enable(dev, buf, 0x##offset - 1);			\
+}									\
+static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, 			\
+		show_pwm_##offset, set_pwm_##offset)			\
+static DEVICE_ATTR(pwm_enable##offset, S_IRUGO, show_pwm_enable##offset, NULL)
+
+show_pwm_reg(1);
+show_pwm_reg(2);
+show_pwm_reg(3);
+
+/* Voltages */
+
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]) );
+}
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]) );
+}
+static ssize_t set_in_min(struct device *dev, const char *buf, 
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	int val = simple_strtol(buf, NULL, 10);
+	data->in_min[nr] = INS_TO_REG(nr, val);
+	lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]);
+	return count;
+}
+static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]) );
+}
+static ssize_t set_in_max(struct device *dev, const char *buf, 
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	int val = simple_strtol(buf, NULL, 10);
+	data->in_max[nr] = INS_TO_REG(nr, val);
+	lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]);
+	return count;
+}
+#define show_in_reg(offset)						\
+static ssize_t show_in_##offset (struct device *dev, char *buf)		\
+{									\
+	return show_in(dev, buf, 0x##offset);				\
+}									\
+static ssize_t show_in_##offset##_min (struct device *dev, char *buf)	\
+{									\
+	return show_in_min(dev, buf, 0x##offset);			\
+}									\
+static ssize_t show_in_##offset##_max (struct device *dev, char *buf)	\
+{									\
+	return show_in_max(dev, buf, 0x##offset);			\
+}									\
+static ssize_t set_in_##offset##_min (struct device *dev, 		\
+	const char *buf, size_t count) 					\
+{									\
+	return set_in_min(dev, buf, count, 0x##offset);			\
+}									\
+static ssize_t set_in_##offset##_max (struct device *dev, 		\
+	const char *buf, size_t count) 					\
+{									\
+	return set_in_max(dev, buf, count, 0x##offset);			\
+}									\
+static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in_##offset, NULL)	\
+static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, 			\
+		show_in_##offset##_min, set_in_##offset##_min)		\
+static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, 			\
+		show_in_##offset##_max, set_in_##offset##_max)
+
+show_in_reg(0);
+show_in_reg(1);
+show_in_reg(2);
+show_in_reg(3);
+show_in_reg(4);
+
+/* Temps */
+
+static ssize_t show_temp(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) );
+}
+static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]) );
+}
+static ssize_t set_temp_min(struct device *dev, const char *buf, 
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	int val = simple_strtol(buf, NULL, 10);
+	data->temp_min[nr] = TEMP_TO_REG(val);
+	lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]);
+	return count;
+}
+static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	lm85_update_client(client);
+	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) );
+}
+static ssize_t set_temp_max(struct device *dev, const char *buf, 
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	int val = simple_strtol(buf, NULL, 10);
+	data->temp_max[nr] = TEMP_TO_REG(val);
+	lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]);
+	return count;
+}
+#define show_temp_reg(offset)						\
+static ssize_t show_temp_##offset (struct device *dev, char *buf)	\
+{									\
+	return show_temp(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t show_temp_##offset##_min (struct device *dev, char *buf)	\
+{									\
+	return show_temp_min(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t show_temp_##offset##_max (struct device *dev, char *buf)	\
+{									\
+	return show_temp_max(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t set_temp_##offset##_min (struct device *dev, 		\
+	const char *buf, size_t count) 					\
+{									\
+	return set_temp_min(dev, buf, count, 0x##offset - 1);		\
+}									\
+static ssize_t set_temp_##offset##_max (struct device *dev, 		\
+	const char *buf, size_t count) 					\
+{									\
+	return set_temp_max(dev, buf, count, 0x##offset - 1);		\
+}									\
+static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL)	\
+static DEVICE_ATTR(temp_min##offset, S_IRUGO | S_IWUSR, 		\
+		show_temp_##offset##_min, set_temp_##offset##_min)	\
+static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, 		\
+		show_temp_##offset##_max, set_temp_##offset##_max)
+
+show_temp_reg(1);
+show_temp_reg(2);
+show_temp_reg(3);
+
+
+int lm85_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_detect(adapter, &addr_data, lm85_detect);
+}
+
+int lm85_detect(struct i2c_adapter *adapter, int address,
+		int kind)
+{
+	int company, verstep ;
+	struct i2c_client *new_client = NULL;
+	struct lm85_data *data;
+	int err = 0;
+	const char *type_name = "";
+
+	if (i2c_is_isa_adapter(adapter)) {
+		/* This chip has no ISA interface */
+		goto ERROR0 ;
+	};
+
+	if (!i2c_check_functionality(adapter,
+					I2C_FUNC_SMBUS_BYTE_DATA)) {
+		/* We need to be able to do byte I/O */
+		goto ERROR0 ;
+	};
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access lm85_{read,write}_value. */
+
+	if (!(new_client = kmalloc((sizeof(struct i2c_client)) +
+				    sizeof(struct lm85_data),
+				    GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto ERROR0;
+	}
+
+	memset(new_client, 0, sizeof(struct i2c_client) +
+			      sizeof(struct lm85_data));
+	data = (struct lm85_data *) (new_client + 1);
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &lm85_driver;
+	new_client->flags = 0;
+
+	/* Now, we do the remaining detection. */
+
+	company = lm85_read_value(new_client, LM85_REG_COMPANY);
+	verstep = lm85_read_value(new_client, LM85_REG_VERSTEP);
+
+	if (lm85debug) {
+		printk("lm85: Detecting device at %d,0x%02x with"
+		" COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
+		i2c_adapter_id(new_client->adapter), new_client->addr,
+		company, verstep);
+	}
+
+	/* If auto-detecting, Determine the chip type. */
+	if (kind <= 0) {
+		if (lm85debug) {
+			printk("lm85: Autodetecting device at %d,0x%02x ...\n",
+			i2c_adapter_id(adapter), address );
+		}
+		if( company == LM85_COMPANY_NATIONAL
+		    && verstep == LM85_VERSTEP_LM85C ) {
+			kind = lm85c ;
+		} else if( company == LM85_COMPANY_NATIONAL
+		    && verstep == LM85_VERSTEP_LM85B ) {
+			kind = lm85b ;
+		} else if( company == LM85_COMPANY_NATIONAL
+		    && (verstep & 0xf0) == LM85_VERSTEP_GENERIC ) {
+			printk("lm85: Unrecgonized version/stepping 0x%02x"
+			    " Defaulting to LM85.\n", verstep );
+			kind = any_chip ;
+		} else if( company == LM85_COMPANY_ANALOG_DEV
+		    && verstep == LM85_VERSTEP_ADM1027 ) {
+			kind = adm1027 ;
+		} else if( company == LM85_COMPANY_ANALOG_DEV
+		    && verstep == LM85_VERSTEP_ADT7463 ) {
+			kind = adt7463 ;
+		} else if( company == LM85_COMPANY_ANALOG_DEV
+		    && (verstep & 0xf0) == LM85_VERSTEP_GENERIC ) {
+			printk("lm85: Unrecgonized version/stepping 0x%02x"
+			    " Defaulting to ADM1027.\n", verstep );
+			kind = adm1027 ;
+		} else if( kind == 0 && (verstep & 0xf0) == 0x60) {
+			printk("lm85: Generic LM85 Version 6 detected\n");
+			/* Leave kind as "any_chip" */
+		} else {
+			if (lm85debug) {
+				printk("lm85: Autodetection failed\n");
+			}
+			/* Not an LM85 ... */
+			if( kind == 0 ) {  /* User used force=x,y */
+			    printk("lm85: Generic LM85 Version 6 not"
+				" found at %d,0x%02x. Try force_lm85c.\n",
+				i2c_adapter_id(adapter), address );
+			}
+			err = 0 ;
+			goto ERROR1;
+		}
+	}
+
+	/* Fill in the chip specific driver values */
+	if ( kind == any_chip ) {
+		type_name = "lm85";
+		strlcpy(new_client->dev.name, "Generic LM85", DEVICE_NAME_SIZE);
+	} else if ( kind == lm85b ) {
+		type_name = "lm85b";
+		strlcpy(new_client->dev.name, "National LM85-B", DEVICE_NAME_SIZE);
+	} else if ( kind == lm85c ) {
+		type_name = "lm85c";
+		strlcpy(new_client->dev.name, "National LM85-C", DEVICE_NAME_SIZE);
+	} else if ( kind == adm1027 ) {
+		type_name = "adm1027";
+		strlcpy(new_client->dev.name, "Analog Devices ADM1027", DEVICE_NAME_SIZE);
+	} else if ( kind == adt7463 ) {
+		type_name = "adt7463";
+		strlcpy(new_client->dev.name, "Analog Devices ADT7463", DEVICE_NAME_SIZE);
+	} else {
+		dev_dbg(&adapter->dev, "Internal error, invalid kind (%d)!", kind);
+		err = -EFAULT ;
+		goto ERROR1;
+	}
+
+	/* Fill in the remaining client fields */
+	new_client->id = lm85_id++;
+	data->type = kind;
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	if (lm85debug) {
+		printk("lm85: Assigning ID %d to %s at %d,0x%02x\n",
+		new_client->id, new_client->dev.name,
+		i2c_adapter_id(new_client->adapter),
+		new_client->addr);
+	}
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto ERROR1;
+
+	/* Set the VRM version */
+	data->vrm = LM85_INIT_VRM ;
+
+	device_create_file(&new_client->dev, &dev_attr_fan_input1);
+	device_create_file(&new_client->dev, &dev_attr_fan_input2);
+	device_create_file(&new_client->dev, &dev_attr_fan_input3);
+	device_create_file(&new_client->dev, &dev_attr_fan_input4);
+	device_create_file(&new_client->dev, &dev_attr_fan_min1);
+	device_create_file(&new_client->dev, &dev_attr_fan_min2);
+	device_create_file(&new_client->dev, &dev_attr_fan_min3);
+	device_create_file(&new_client->dev, &dev_attr_fan_min4);
+	device_create_file(&new_client->dev, &dev_attr_pwm1);
+	device_create_file(&new_client->dev, &dev_attr_pwm2);
+	device_create_file(&new_client->dev, &dev_attr_pwm3);
+	device_create_file(&new_client->dev, &dev_attr_pwm_enable1);
+	device_create_file(&new_client->dev, &dev_attr_pwm_enable2);
+	device_create_file(&new_client->dev, &dev_attr_pwm_enable3);
+	device_create_file(&new_client->dev, &dev_attr_in_input0);
+	device_create_file(&new_client->dev, &dev_attr_in_input1);
+	device_create_file(&new_client->dev, &dev_attr_in_input2);
+	device_create_file(&new_client->dev, &dev_attr_in_input3);
+	device_create_file(&new_client->dev, &dev_attr_in_input4);
+	device_create_file(&new_client->dev, &dev_attr_in_min0);
+	device_create_file(&new_client->dev, &dev_attr_in_min1);
+	device_create_file(&new_client->dev, &dev_attr_in_min2);
+	device_create_file(&new_client->dev, &dev_attr_in_min3);
+	device_create_file(&new_client->dev, &dev_attr_in_min4);
+	device_create_file(&new_client->dev, &dev_attr_in_max0);
+	device_create_file(&new_client->dev, &dev_attr_in_max1);
+	device_create_file(&new_client->dev, &dev_attr_in_max2);
+	device_create_file(&new_client->dev, &dev_attr_in_max3);
+	device_create_file(&new_client->dev, &dev_attr_in_max4);
+	device_create_file(&new_client->dev, &dev_attr_temp_input1);
+	device_create_file(&new_client->dev, &dev_attr_temp_input2);
+	device_create_file(&new_client->dev, &dev_attr_temp_input3);
+	device_create_file(&new_client->dev, &dev_attr_temp_min1);
+	device_create_file(&new_client->dev, &dev_attr_temp_min2);
+	device_create_file(&new_client->dev, &dev_attr_temp_min3);
+	device_create_file(&new_client->dev, &dev_attr_temp_max1);
+	device_create_file(&new_client->dev, &dev_attr_temp_max2);
+	device_create_file(&new_client->dev, &dev_attr_temp_max3);
+	device_create_file(&new_client->dev, &dev_attr_vrm);
+	device_create_file(&new_client->dev, &dev_attr_vid);
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+
+	/* Initialize the LM85 chip */
+	lm85_init_client(new_client);
+	return 0;
+
+	/* Error out and cleanup code */
+    ERROR1:
+	kfree(new_client);
+    ERROR0:
+	return err;
+}
+
+int lm85_detach_client(struct i2c_client *client)
+{
+	i2c_detach_client(client);
+	kfree(client);
+	return 0;
+}
+
+
+int lm85_read_value(struct i2c_client *client, u8 reg)
+{
+	int res;
+
+	/* What size location is it? */
+	switch( reg ) {
+	case LM85_REG_FAN(0) :  /* Read WORD data */
+	case LM85_REG_FAN(1) :
+	case LM85_REG_FAN(2) :
+	case LM85_REG_FAN(3) :
+	case LM85_REG_FAN_MIN(0) :
+	case LM85_REG_FAN_MIN(1) :
+	case LM85_REG_FAN_MIN(2) :
+	case LM85_REG_FAN_MIN(3) :
+	case LM85_REG_ALARM1 :	/* Read both bytes at once */
+	case ADM1027_REG_EXTEND_ADC1 :  /* Read two bytes at once */
+		res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
+		res |= i2c_smbus_read_byte_data(client, reg+1) << 8 ;
+		break ;
+	case ADT7463_REG_TMIN_CTL1 :  /* Read WORD MSB, LSB */
+		res = i2c_smbus_read_byte_data(client, reg) << 8 ;
+		res |= i2c_smbus_read_byte_data(client, reg+1) & 0xff ;
+		break ;
+	default:	/* Read BYTE data */
+		res = i2c_smbus_read_byte_data(client, reg);
+		break ;
+	}
+
+	return res ;
+}
+
+int lm85_write_value(struct i2c_client *client, u8 reg, int value)
+{
+	int res ;
+
+	switch( reg ) {
+	case LM85_REG_FAN(0) :  /* Write WORD data */
+	case LM85_REG_FAN(1) :
+	case LM85_REG_FAN(2) :
+	case LM85_REG_FAN(3) :
+	case LM85_REG_FAN_MIN(0) :
+	case LM85_REG_FAN_MIN(1) :
+	case LM85_REG_FAN_MIN(2) :
+	case LM85_REG_FAN_MIN(3) :
+	/* NOTE: ALARM is read only, so not included here */
+		res = i2c_smbus_write_byte_data(client, reg, value & 0xff) ;
+		res |= i2c_smbus_write_byte_data(client, reg+1, (value>>8) & 0xff) ;
+		break ;
+	case ADT7463_REG_TMIN_CTL1 :  /* Write WORD MSB, LSB */
+		res = i2c_smbus_write_byte_data(client, reg, (value>>8) & 0xff);
+		res |= i2c_smbus_write_byte_data(client, reg+1, value & 0xff) ;
+		break ;
+	default:	/* Write BYTE data */
+		res = i2c_smbus_write_byte_data(client, reg, value);
+		break ;
+	}
+
+	return res ;
+}
+
+void lm85_init_client(struct i2c_client *client)
+{
+	int value;
+	struct lm85_data *data = i2c_get_clientdata(client);
+
+	if (lm85debug) {
+		printk("lm85(%d): Initializing device\n", client->id);
+	}
+
+	/* Warn if part was not "READY" */
+	value = lm85_read_value(client, LM85_REG_CONFIG);
+	if (lm85debug) {
+		printk("lm85(%d): LM85_REG_CONFIG is: 0x%02x\n", client->id, value );
+	}
+	if( value & 0x02 ) {
+		printk("lm85(%d): Client (%d,0x%02x) config is locked.\n",
+			    client->id,
+			    i2c_adapter_id(client->adapter), client->addr );
+	};
+	if( ! (value & 0x04) ) {
+		printk("lm85(%d): Client (%d,0x%02x) is not ready.\n",
+			    client->id,
+			    i2c_adapter_id(client->adapter), client->addr );
+	};
+	if( value & 0x10
+	    && ( data->type == adm1027
+		|| data->type == adt7463 ) ) {
+		printk("lm85(%d): Client (%d,0x%02x) VxI mode is set.  "
+			"Please report this to the lm85 maintainer.\n",
+			    client->id,
+			    i2c_adapter_id(client->adapter), client->addr );
+	};
+
+	/* WE INTENTIONALLY make no changes to the limits,
+	 *   offsets, pwms, fans and zones.  If they were
+	 *   configured, we don't want to mess with them.
+	 *   If they weren't, the default is 100% PWM, no
+	 *   control and will suffice until 'sensors -s'
+	 *   can be run by the user.
+	 */
+
+	/* Start monitoring */
+	value = lm85_read_value(client, LM85_REG_CONFIG);
+	/* Try to clear LOCK, Set START, save everything else */
+	value = (value & ~ 0x02) | 0x01 ;
+	if (lm85debug) {
+		printk("lm85(%d): Setting CONFIG to: 0x%02x\n", client->id, value );
+	}
+	lm85_write_value(client, LM85_REG_CONFIG, value);
+
+}
+
+void lm85_update_client(struct i2c_client *client)
+{
+	struct lm85_data *data = i2c_get_clientdata(client);
+	int i;
+
+	down(&data->update_lock);
+
+	if ( !data->valid ||
+	     (jiffies - data->last_reading > LM85_DATA_INTERVAL ) ) {
+		/* Things that change quickly */
+
+		if (lm85debug) {
+			printk("lm85(%d): Reading sensor values\n", client->id);
+		}
+		/* Have to read extended bits first to "freeze" the
+		 * more significant bits that are read later.
+		 */
+		if ( (data->type == adm1027) || (data->type == adt7463) ) {
+			data->extend_adc =
+			    lm85_read_value(client, ADM1027_REG_EXTEND_ADC1);
+		}
+
+		for (i = 0; i <= 4; ++i) {
+			data->in[i] =
+			    lm85_read_value(client, LM85_REG_IN(i));
+		}
+
+		for (i = 0; i <= 3; ++i) {
+			data->fan[i] =
+			    lm85_read_value(client, LM85_REG_FAN(i));
+		}
+
+		for (i = 0; i <= 2; ++i) {
+			data->temp[i] =
+			    lm85_read_value(client, LM85_REG_TEMP(i));
+		}
+
+		for (i = 0; i <= 2; ++i) {
+			data->pwm[i] =
+			    lm85_read_value(client, LM85_REG_PWM(i));
+		}
+
+		if ( data->type == adt7463 ) {
+			if( data->therm_total < ULONG_MAX - 256 ) {
+			    data->therm_total +=
+				lm85_read_value(client, ADT7463_REG_THERM );
+			}
+		}
+
+		data->alarms = lm85_read_value(client, LM85_REG_ALARM1);
+
+		data->last_reading = jiffies ;
+	};  /* last_reading */
+
+	if ( !data->valid ||
+	     (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) {
+		/* Things that don't change often */
+
+		if (lm85debug) {
+			printk("lm85(%d): Reading config values\n", client->id);
+		}
+		for (i = 0; i <= 4; ++i) {
+			data->in_min[i] =
+			    lm85_read_value(client, LM85_REG_IN_MIN(i));
+			data->in_max[i] =
+			    lm85_read_value(client, LM85_REG_IN_MAX(i));
+		}
+
+		for (i = 0; i <= 3; ++i) {
+			data->fan_min[i] =
+			    lm85_read_value(client, LM85_REG_FAN_MIN(i));
+		}
+
+		for (i = 0; i <= 2; ++i) {
+			data->temp_min[i] =
+			    lm85_read_value(client, LM85_REG_TEMP_MIN(i));
+			data->temp_max[i] =
+			    lm85_read_value(client, LM85_REG_TEMP_MAX(i));
+		}
+
+		data->vid = lm85_read_value(client, LM85_REG_VID);
+
+		for (i = 0; i <= 2; ++i) {
+			int val ;
+			data->autofan[i].config =
+			    lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
+			val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
+			data->autofan[i].freq = val & 0x07 ;
+			data->zone[i].range = (val >> 4) & 0x0f ;
+			data->autofan[i].min_pwm =
+			    lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
+			data->zone[i].limit =
+			    lm85_read_value(client, LM85_REG_AFAN_LIMIT(i));
+			data->zone[i].critical =
+			    lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i));
+		}
+
+		i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
+		data->smooth[0] = i & 0x0f ;
+		data->syncpwm3 = i & 0x10 ;  /* Save PWM3 config */
+		data->autofan[0].min_off = (i & 0x20) != 0 ;
+		data->autofan[1].min_off = (i & 0x40) != 0 ;
+		data->autofan[2].min_off = (i & 0x80) != 0 ;
+		i = lm85_read_value(client, LM85_REG_AFAN_SPIKE2);
+		data->smooth[1] = (i>>4) & 0x0f ;
+		data->smooth[2] = i & 0x0f ;
+
+		i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
+		data->zone[0].hyst = (i>>4) & 0x0f ;
+		data->zone[1].hyst = i & 0x0f ;
+
+		i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
+		data->zone[2].hyst = (i>>4) & 0x0f ;
+
+		if ( (data->type == lm85b) || (data->type == lm85c) ) {
+			data->tach_mode = lm85_read_value(client,
+				LM85_REG_TACH_MODE );
+			data->spinup_ctl = lm85_read_value(client,
+				LM85_REG_SPINUP_CTL );
+		} else if ( (data->type == adt7463) || (data->type == adm1027) ) {
+			if ( data->type == adt7463 ) {
+				for (i = 0; i <= 2; ++i) {
+				    data->oppoint[i] = lm85_read_value(client,
+					ADT7463_REG_OPPOINT(i) );
+				}
+				data->tmin_ctl = lm85_read_value(client,
+					ADT7463_REG_TMIN_CTL1 );
+				data->therm_limit = lm85_read_value(client,
+					ADT7463_REG_THERM_LIMIT );
+			}
+			for (i = 0; i <= 2; ++i) {
+			    data->temp_offset[i] = lm85_read_value(client,
+				ADM1027_REG_TEMP_OFFSET(i) );
+			}
+			data->tach_mode = lm85_read_value(client,
+				ADM1027_REG_CONFIG3 );
+			data->fan_ppr = lm85_read_value(client,
+				ADM1027_REG_FAN_PPR );
+		}
+	
+		data->last_config = jiffies;
+	};  /* last_config */
+
+	data->valid = 1;
+
+	up(&data->update_lock);
+}
+
+
+static int __init sm_lm85_init(void)
+{
+	return i2c_add_driver(&lm85_driver);
+}
+
+static void  __exit sm_lm85_exit(void)
+{
+	i2c_del_driver(&lm85_driver);
+}
+
+/* Thanks to Richard Barrington for adding the LM85 to sensors-detect.
+ * Thanks to Margit Schubert-While <margitsw@t-online.de> for help with
+ *     post 2.7.0 CVS changes
+ */
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, Margit Schubert-While <margitsw@t-online.de>");
+MODULE_DESCRIPTION("LM85-B, LM85-C driver");
+MODULE_PARM(lm85debug, "i");
+MODULE_PARM_DESC(lm85debug, "Enable debugging statements");
+
+module_init(sm_lm85_init);
+module_exit(sm_lm85_exit);
diff -urN linux-2.5.70-bk16/drivers/i2c/i2c-core.c linux-2.5.70-bk17/drivers/i2c/i2c-core.c
--- linux-2.5.70-bk16/drivers/i2c/i2c-core.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/i2c/i2c-core.c	2003-06-12 04:49:56.000000000 -0700
@@ -510,7 +510,7 @@
 		msg.addr   = client->addr;
 		msg.flags = client->flags & I2C_M_TEN;
 		msg.len = count;
-		(const char *)msg.buf = buf;
+		msg.buf = (char *)buf;
 	
 		DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
 				count));
@@ -861,13 +861,13 @@
 	return 0;	
 }
 
-extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
+s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
 {
 	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
  	                      value,0,I2C_SMBUS_QUICK,NULL);
 }
 
-extern s32 i2c_smbus_read_byte(struct i2c_client * client)
+s32 i2c_smbus_read_byte(struct i2c_client *client)
 {
 	union i2c_smbus_data data;
 	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -877,14 +877,14 @@
 		return 0x0FF & data.byte;
 }
 
-extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value)
+s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
 {
 	union i2c_smbus_data data;	/* only for PEC */
 	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
 	                      I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
 }
 
-extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
+s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
 {
 	union i2c_smbus_data data;
 	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -894,8 +894,7 @@
 		return 0x0FF & data.byte;
 }
 
-extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, u8 command,
-                                     u8 value)
+s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
 {
 	union i2c_smbus_data data;
 	data.byte = value;
@@ -904,7 +903,7 @@
 	                      I2C_SMBUS_BYTE_DATA,&data);
 }
 
-extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command)
+s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
 {
 	union i2c_smbus_data data;
 	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -914,8 +913,7 @@
 		return 0x0FFFF & data.word;
 }
 
-extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
-                                     u8 command, u16 value)
+s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
 {
 	union i2c_smbus_data data;
 	data.word = value;
@@ -924,8 +922,7 @@
 	                      I2C_SMBUS_WORD_DATA,&data);
 }
 
-extern s32 i2c_smbus_process_call(struct i2c_client * client,
-                                  u8 command, u16 value)
+s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
 {
 	union i2c_smbus_data data;
 	data.word = value;
@@ -938,8 +935,7 @@
 }
 
 /* Returns the number of read bytes */
-extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
-                                     u8 command, u8 *values)
+s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, u8 *values)
 {
 	union i2c_smbus_data data;
 	int i;
@@ -954,8 +950,7 @@
 	}
 }
 
-extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
-                                      u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
 {
 	union i2c_smbus_data data;
 	int i;
@@ -970,8 +965,7 @@
 }
 
 /* Returns the number of read bytes */
-extern s32 i2c_smbus_block_process_call(struct i2c_client * client,
-                                        u8 command, u8 length, u8 *values)
+s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values)
 {
 	union i2c_smbus_data data;
 	int i;
@@ -990,8 +984,7 @@
 }
 
 /* Returns the number of read bytes */
-extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
-                                         u8 command, u8 *values)
+s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
 {
 	union i2c_smbus_data data;
 	int i;
@@ -1006,8 +999,7 @@
 	}
 }
 
-extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
-                                          u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
 {
 	union i2c_smbus_data data;
 	int i;
diff -urN linux-2.5.70-bk16/drivers/i2c/i2c-dev.c linux-2.5.70-bk17/drivers/i2c/i2c-dev.c
--- linux-2.5.70-bk16/drivers/i2c/i2c-dev.c	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk17/drivers/i2c/i2c-dev.c	2003-06-12 04:49:56.000000000 -0700
@@ -122,7 +122,7 @@
 }
 static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
 
-static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
+static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
                             loff_t *offset)
 {
 	char *tmp;
@@ -147,7 +147,7 @@
 	return ret;
 }
 
-static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
+static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t count,
                              loff_t *offset)
 {
 	int ret;
@@ -211,12 +211,12 @@
 		return 0;
 	case I2C_FUNCS:
 		funcs = i2c_get_functionality(client->adapter);
-		return (copy_to_user((unsigned long *)arg,&funcs,
+		return (copy_to_user((unsigned long __user *)arg, &funcs,
 		                     sizeof(unsigned long)))?-EFAULT:0;
 
         case I2C_RDWR:
 		if (copy_from_user(&rdwr_arg, 
-				   (struct i2c_rdwr_ioctl_data *)arg, 
+				   (struct i2c_rdwr_ioctl_data __user *)arg, 
 				   sizeof(rdwr_arg)))
 			return -EFAULT;
 
@@ -284,7 +284,7 @@
 
 	case I2C_SMBUS:
 		if (copy_from_user(&data_arg,
-		                   (struct i2c_smbus_ioctl_data *) arg,
+		                   (struct i2c_smbus_ioctl_data __user *) arg,
 		                   sizeof(struct i2c_smbus_ioctl_data)))
 			return -EFAULT;
 		if ((data_arg.size != I2C_SMBUS_BYTE) && 
diff -urN linux-2.5.70-bk16/drivers/i2c/i2c-iop3xx.c linux-2.5.70-bk17/drivers/i2c/i2c-iop3xx.c
--- linux-2.5.70-bk16/drivers/i2c/i2c-iop3xx.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk17/drivers/i2c/i2c-iop3xx.c	2003-06-12 04:49:56.000000000 -0700
@@ -0,0 +1,536 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx                */
+/* ------------------------------------------------------------------------- */
+/*   Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
+ *                      <Peter dot Milne at D hyphen TACQ dot com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, version 2.
+
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.                */
+/* ------------------------------------------------------------------------- */
+/*
+   With acknowledgements to i2c-algo-ibm_ocp.c by 
+   Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
+
+   And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
+
+     Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
+   
+   And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
+   Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
+
+  ---------------------------------------------------------------------------*/
+
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+
+
+#include <asm/arch-iop3xx/iop321.h>
+#include <asm/arch-iop3xx/iop321-irqs.h>
+#include "i2c-iop3xx.h"
+
+
+/* ----- global defines ----------------------------------------------- */
+#define PASSERT(x) do { if (!(x) ) \
+		printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
+	} while (0)
+
+
+/* ----- global variables ---------------------------------------------	*/
+
+
+static inline unsigned char iic_cook_addr(struct i2c_msg *msg) 
+{
+	unsigned char addr;
+
+	addr = (msg->addr << 1);
+
+	if (msg->flags & I2C_M_RD)
+		addr |= 1;
+
+	/* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
+	if (msg->flags & I2C_M_REV_DIR_ADDR)
+		addr ^= 1;
+
+	return addr;   
+}
+
+
+static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+	/* Follows devman 9.3 */
+	*iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
+	*iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
+	*iop3xx_adap->biu->CR = 0;
+} 
+
+static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+	*iop3xx_adap->biu->SAR = MYSAR;
+}
+
+static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+	u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
+
+	/* NB SR bits not same position as CR IE bits :-( */
+	iop3xx_adap->biu->SR_enabled = 
+		IOP321_ISR_ALD | IOP321_ISR_BERRD |
+		IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY;
+
+	cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
+		IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE;
+
+	*iop3xx_adap->biu->CR = cr;
+}
+
+static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+	unsigned cr = *iop3xx_adap->biu->CR;
+	
+	cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE | 
+		IOP321_ICR_MSTOP | IOP321_ICR_SCLEN);
+	*iop3xx_adap->biu->CR = cr;
+}
+
+static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+	unsigned cr = *iop3xx_adap->biu->CR;
+	
+	cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
+		IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE);
+	iop3xx_adap->biu->SR_enabled = 0;
+	*iop3xx_adap->biu->CR = cr;
+}
+
+/* 
+ * NB: the handler has to clear the source of the interrupt! 
+ * Then it passes the SR flags of interest to BH via adap data
+ */
+static void iop3xx_i2c_handler(int this_irq, 
+				void *dev_id, 
+				struct pt_regs *regs) 
+{
+	struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
+
+	u32 sr = *iop3xx_adap->biu->SR;
+
+	if ((sr &= iop3xx_adap->biu->SR_enabled)) {
+		*iop3xx_adap->biu->SR = sr;
+		iop3xx_adap->biu->SR_received |= sr;
+		wake_up_interruptible(&iop3xx_adap->waitq);
+	}
+}
+
+/* check all error conditions, clear them , report most important */
+static int iop3xx_adap_error(u32 sr)
+{
+	int rc = 0;
+
+	if ((sr&IOP321_ISR_BERRD)) {
+		if ( !rc ) rc = -I2C_ERR_BERR;
+	}
+	if ((sr&IOP321_ISR_ALD)) {
+		if ( !rc ) rc = -I2C_ERR_ALD;		
+	}
+	return rc;	
+}
+
+static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+	unsigned long flags;
+	u32 sr;
+
+	spin_lock_irqsave(&iop3xx_adap->lock, flags);
+	sr = iop3xx_adap->biu->SR_received;
+	iop3xx_adap->biu->SR_received = 0;
+	spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
+
+	return sr;
+}
+
+/*
+ * sleep until interrupted, then recover and analyse the SR
+ * saved by handler
+ */
+typedef int (* compare_func)(unsigned test, unsigned mask);
+/* returns 1 on correct comparison */
+
+static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, 
+				  unsigned flags, unsigned* status,
+				  compare_func compare)
+{
+	unsigned sr = 0;
+	int interrupted;
+	int done;
+	int rc;
+
+	do {
+		interrupted = wait_event_interruptible_timeout (
+			iop3xx_adap->waitq,
+			(done = compare( sr = get_srstat(iop3xx_adap),flags )),
+			iop3xx_adap->timeout
+			);
+		if ((rc = iop3xx_adap_error(sr)) < 0) {
+			*status = sr;
+			return rc;
+		}else if (!interrupted) {
+			*status = sr;
+			return rc = -ETIMEDOUT;
+		}
+	} while(!done);
+
+	*status = sr;
+
+	return rc = 0;
+}
+
+/*
+ * Concrete compare_funcs 
+ */
+static int all_bits_clear(unsigned test, unsigned mask)
+{
+	return (test & mask) == 0;
+}
+static int any_bits_set(unsigned test, unsigned mask)
+{
+	return (test & mask) != 0;
+}
+
+static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+{
+	return iop3xx_adap_wait_event( 
+		iop3xx_adap, 
+	        IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+		status, any_bits_set);
+}
+
+static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+{
+	return iop3xx_adap_wait_event( 
+		iop3xx_adap, 
+		IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+		status,	any_bits_set);
+}
+
+static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+{
+	return iop3xx_adap_wait_event( 
+		iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear);
+}
+
+/*
+ * Description: This performs the IOP3xx initialization sequence
+ * Valid for IOP321. Maybe valid for IOP310?.
+ */
+static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap)
+{
+	*IOP321_GPOD &= ~(iop3xx_adap->channel==0 ?
+			  IOP321_GPOD_I2C0:
+			  IOP321_GPOD_I2C1);
+
+	iop3xx_adap_reset(iop3xx_adap);
+	iop3xx_adap_set_slave_addr(iop3xx_adap);
+	iop3xx_adap_enable(iop3xx_adap);
+	
+        return 0;
+}
+
+static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
+					      struct i2c_msg* msg)
+{
+	unsigned cr = *iop3xx_adap->biu->CR;
+	int status;
+	int rc;
+
+	*iop3xx_adap->biu->DBR = iic_cook_addr(msg);
+	
+	cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK);
+	cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
+
+	*iop3xx_adap->biu->CR = cr;
+	rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
+	/* this assert fires every time, contrary to IOP manual	
+	PASSERT((status&IOP321_ISR_UNITBUSY)!=0);
+	*/
+	PASSERT((status&IOP321_ISR_RXREAD)==0);
+	     
+	return rc;
+}
+
+static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop)
+{
+	unsigned cr = *iop3xx_adap->biu->CR;
+	int status;
+	int rc;
+
+	*iop3xx_adap->biu->DBR = byte;
+	cr &= ~IOP321_ICR_MSTART;
+	if (stop) {
+		cr |= IOP321_ICR_MSTOP;
+	} else {
+		cr &= ~IOP321_ICR_MSTOP;
+	}
+	*iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+	rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
+
+	return rc;
+} 
+
+static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
+				 char* byte, int stop)
+{
+	unsigned cr = *iop3xx_adap->biu->CR;
+	int status;
+	int rc;
+
+	cr &= ~IOP321_ICR_MSTART;
+
+	if (stop) {
+		cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
+	} else {
+		cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+	}
+	*iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+
+	rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status);
+
+	*byte = *iop3xx_adap->biu->DBR;
+
+	return rc;
+}
+
+static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, 
+				 const char *buf, int count)
+{
+	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+	int ii;
+	int rc = 0;
+
+	for (ii = 0; rc == 0 && ii != count; ++ii) {
+		rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1);
+	}
+	return rc;
+}
+
+static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, 
+				char *buf, int count)
+{
+	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+	int ii;
+	int rc = 0;
+
+	for (ii = 0; rc == 0 && ii != count; ++ii) {
+		rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
+	}
+	return rc;
+}
+
+/*
+ * Description:  This function implements combined transactions.  Combined
+ * transactions consist of combinations of reading and writing blocks of data.
+ * FROM THE SAME ADDRESS
+ * Each transfer (i.e. a read or a write) is separated by a repeated start
+ * condition.
+ */
+static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) 
+{
+	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+	int rc;
+
+	rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg);
+	if (rc < 0) {
+		return rc;
+	}
+
+	if ((pmsg->flags&I2C_M_RD)) {
+		return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len);
+	} else {
+		return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len);
+	}
+}
+
+/*
+ * master_xfer() - main read/write entry
+ */
+static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+{
+	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
+	int im = 0;
+	int ret = 0;
+	int status;
+
+	iop3xx_adap_wait_idle(iop3xx_adap, &status);
+	iop3xx_adap_reset(iop3xx_adap);
+	iop3xx_adap_enable(iop3xx_adap);
+
+	for (im = 0; ret == 0 && im != num; ++im) {
+		ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
+	}
+
+	iop3xx_adap_transaction_cleanup(iop3xx_adap);
+
+	return ret;   
+}
+
+static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
+			unsigned long arg)
+{
+	return 0;
+}
+
+static u32 iic_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+
+/* -----exported algorithm data: -------------------------------------	*/
+
+static struct i2c_algorithm iic_algo = {
+	.name		= "IOP3xx I2C algorithm",
+	.id		= I2C_ALGO_OCP_IOP3XX,
+	.master_xfer	= iop3xx_master_xfer,
+	.algo_control	= algo_control,
+	.functionality	= iic_func,
+};
+
+/* 
+ * registering functions to load algorithms at runtime 
+ */
+static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
+{
+	struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+
+	if (!request_region( REGION_START(iop3xx_adap), 
+			      REGION_LENGTH(iop3xx_adap),
+			      iic_adap->name)) {
+		return -ENODEV;
+	}
+
+	init_waitqueue_head(&iop3xx_adap->waitq);
+	spin_lock_init(&iop3xx_adap->lock);
+
+	if (request_irq( 
+		     iop3xx_adap->biu->irq,
+		     iop3xx_i2c_handler,
+		     /* SA_SAMPLE_RANDOM */ 0,
+		     iic_adap->name,
+		     iop3xx_adap)) {
+		return -ENODEV;
+	}			  
+
+	/* register new iic_adapter to i2c module... */
+	iic_adap->id |= iic_algo.id;
+	iic_adap->algo = &iic_algo;
+
+	iic_adap->timeout = 100;	/* default values, should */
+	iic_adap->retries = 3;		/* be replaced by defines */
+
+	iop3xx_adap_init(iic_adap->algo_data);
+	i2c_add_adapter(iic_adap);
+	return 0;
+}
+
+static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
+{
+	struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+
+	iop3xx_adap_final_cleanup(iop3xx_adap);
+	free_irq(iop3xx_adap->biu->irq, iop3xx_adap);
+
+	release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
+
+	return i2c_del_adapter(iic_adap);
+}
+
+#ifdef CONFIG_ARCH_IOP321
+
+static struct iop3xx_biu biu0 = {
+	.CR	= IOP321_ICR0,
+	.SR	= IOP321_ISR0,
+	.SAR	= IOP321_ISAR0,
+	.DBR	= IOP321_IDBR0,
+	.BMR	= IOP321_IBMR0,
+	.irq	= IRQ_IOP321_I2C_0,
+};
+
+static struct iop3xx_biu biu1 = {
+	.CR	= IOP321_ICR1,
+	.SR	= IOP321_ISR1,
+	.SAR	= IOP321_ISAR1,
+	.DBR	= IOP321_IDBR1,
+	.BMR	= IOP321_IBMR1,
+	.irq	= IRQ_IOP321_I2C_1,
+};
+
+#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
+#else
+#error Please define the BIU struct iop3xx_biu for your processor arch
+#endif
+
+static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = {
+	.channel		= 0,
+	.biu			= &biu0,
+	.timeout		= 1*HZ,
+};
+static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = {
+	.channel		= 1,
+	.biu			= &biu1,
+	.timeout		= 1*HZ,
+};
+
+static struct i2c_adapter iop3xx_ops0 = {
+	.owner			= THIS_MODULE,
+	.name			= ADAPTER_NAME_ROOT "0",
+	.id			= I2C_HW_IOP321,
+	.algo_data		= &algo_iop3xx_data0,
+};
+static struct i2c_adapter iop3xx_ops1 = {
+	.owner			= THIS_MODULE,
+	.name			= ADAPTER_NAME_ROOT "1",
+	.id			= I2C_HW_IOP321,
+	.algo_data		= &algo_iop3xx_data1,
+};
+
+static int __init i2c_iop3xx_init (void)
+{
+	return i2c_iop3xx_add_bus(&iop3xx_ops0) ||
+		i2c_iop3xx_add_bus(&iop3xx_ops1);
+}
+
+static void __exit i2c_iop3xx_exit (void)
+{
+	i2c_iop3xx_del_bus(&iop3xx_ops0);
+	i2c_iop3xx_del_bus(&iop3xx_ops1);
+}
+
+module_init (i2c_iop3xx_init);
+module_exit (i2c_iop3xx_exit);
+
+MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
+MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(i2c_debug,"i");
+
+MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
+
diff -urN linux-2.5.70-bk16/drivers/i2c/i2c-iop3xx.h linux-2.5.70-bk17/drivers/i2c/i2c-iop3xx.h
--- linux-2.5.70-bk16/drivers/i2c/i2c-iop3xx.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk17/drivers/i2c/i2c-iop3xx.h	2003-06-12 04:49:56.000000000 -0700
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-iop3xx.h algorithm driver definitions private to i2c-iop3xx.c         */
+/* ------------------------------------------------------------------------- */
+/*   Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
+ *                      <Peter dot Milne at D hyphen TACQ dot com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, version 2.
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.                */
+/* ------------------------------------------------------------------------- */
+
+
+#ifndef I2C_IOP3XX_H
+#define I2C_IOP3XX_H 1
+
+/*
+ * iop321 hardware bit definitions
+ */
+#define IOP321_ICR_FAST_MODE	0x8000	/* 1=400kBps, 0=100kBps */
+#define IOP321_ICR_UNIT_RESET	0x4000	/* 1=RESET */
+#define IOP321_ICR_SADIE	0x2000	/* 1=Slave Detect Interrupt Enable */
+#define IOP321_ICR_ALDIE	0x1000	/* 1=Arb Loss Detect Interrupt Enable */
+#define IOP321_ICR_SSDIE	0x0800	/* 1=Slave STOP Detect Interrupt Enable */
+#define IOP321_ICR_BERRIE	0x0400	/* 1=Bus Error Interrupt Enable */
+#define IOP321_ICR_RXFULLIE	0x0200	/* 1=Receive Full Interrupt Enable */
+#define IOP321_ICR_TXEMPTYIE	0x0100	/* 1=Transmit Empty Interrupt Enable */
+#define IOP321_ICR_GCD		0x0080	/* 1=General Call Disable */
+/*
+ * IOP321_ICR_GCD: 1 disables response as slave. "This bit must be set
+ * when sending a master mode general call message from the I2C unit"
+ */
+#define IOP321_ICR_UE		0x0040	/* 1=Unit Enable */
+/*
+ * "NOTE: To avoid I2C bus integrity problems, 
+ * the user needs to ensure that the GPIO Output Data Register - 
+ * GPOD bits associated with an I2C port are cleared prior to setting 
+ * the enable bit for that I2C serial port. 
+ * The user prepares to enable I2C port 0 and 
+ * I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively.
+ */
+#define IOP321_ICR_SCLEN	0x0020	/* 1=SCL enable for master mode */
+#define IOP321_ICR_MABORT	0x0010	/* 1=Send a STOP with no data 
+					 * NB TBYTE must be clear */
+#define IOP321_ICR_TBYTE	0x0008	/* 1=Send/Receive a byte. i2c clears */
+#define IOP321_ICR_NACK		0x0004	/* 1=reply with NACK */
+#define IOP321_ICR_MSTOP	0x0002	/* 1=send a STOP after next data byte */
+#define IOP321_ICR_MSTART	0x0001	/* 1=initiate a START */
+
+
+#define IOP321_ISR_BERRD	0x0400	/* 1=BUS ERROR Detected */
+#define IOP321_ISR_SAD		0x0200	/* 1=Slave ADdress Detected */
+#define IOP321_ISR_GCAD		0x0100	/* 1=General Call Address Detected */
+#define IOP321_ISR_RXFULL	0x0080	/* 1=Receive Full */
+#define IOP321_ISR_TXEMPTY	0x0040	/* 1=Transmit Empty */
+#define IOP321_ISR_ALD		0x0020	/* 1=Arbitration Loss Detected */
+#define IOP321_ISR_SSD		0x0010	/* 1=Slave STOP Detected */
+#define IOP321_ISR_BBUSY	0x0008	/* 1=Bus BUSY */
+#define IOP321_ISR_UNITBUSY	0x0004	/* 1=Unit Busy */
+#define IOP321_ISR_NACK		0x0002	/* 1=Unit Rx or Tx a NACK */
+#define IOP321_ISR_RXREAD	0x0001	/* 1=READ 0=WRITE (R/W bit of slave addr */
+
+#define IOP321_ISR_CLEARBITS	0x07f0
+
+#define IOP321_ISAR_SAMASK	0x007f
+
+#define IOP321_IDBR_MASK	0x00ff
+
+#define IOP321_IBMR_SCL		0x0002
+#define IOP321_IBMR_SDA		0x0001
+
+#define IOP321_GPOD_I2C0	0x00c0	/* clear these bits to enable ch0 */
+#define IOP321_GPOD_I2C1	0x0030	/* clear these bits to enable ch1 */
+
+#define MYSAR			0x02	/* SWAG a suitable slave address */
+
+#define I2C_ERR			321
+#define I2C_ERR_BERR		(I2C_ERR+0)
+#define I2C_ERR_ALD		(I2C_ERR+1)
+
+
+struct iop3xx_biu {                /* Bus Interface Unit - the hardware */
+/* physical hardware defs - regs*/
+	u32 *CR;
+	u32 *SR;
+	u32 *SAR;
+	u32 *DBR;
+	u32 *BMR;
+/* irq bit vector */
+	u32 irq;
+/* stored flags */
+	u32 SR_enabled, SR_received;
+};
+
+struct i2c_algo_iop3xx_data {
+	int channel;
+
+	wait_queue_head_t waitq;
+	spinlock_t lock;
+	int timeout;
+	struct iop3xx_biu* biu;
+};
+
+#define REGION_START(adap)	((u32)((adap)->biu->CR))
+#define REGION_END(adap)	((u32)((adap)->biu->BMR+1))
+#define REGION_LENGTH(adap)	(REGION_END(adap)-REGION_START(adap))
+
+#define IRQ_STATUS_MASK(adap)	(1<<adap->biu->irq)
+
+#endif /* I2C_IOP3XX_H */
diff -urN linux-2.5.70-bk16/drivers/isdn/capi/capi.c linux-2.5.70-bk17/drivers/isdn/capi/capi.c
--- linux-2.5.70-bk16/drivers/isdn/capi/capi.c	2003-05-26 18:00:59.000000000 -0700
+++ linux-2.5.70-bk17/drivers/isdn/capi/capi.c	2003-06-12 04:49:57.000000000 -0700
@@ -1263,26 +1263,42 @@
 }
 
 #define CAPINC_NR_PORTS 256
-static struct tty_driver capinc_tty_driver;
-static int capinc_tty_refcount;
-static struct tty_struct *capinc_tty_table[CAPINC_NR_PORTS];
-static struct termios *capinc_tty_termios[CAPINC_NR_PORTS];
-static struct termios *capinc_tty_termios_locked[CAPINC_NR_PORTS];
+static struct tty_driver *capinc_tty_driver;
+
+static struct tty_operations capinc_ops = {
+	.open = capinc_tty_open,
+	.close = capinc_tty_close,
+	.write = capinc_tty_write,
+	.put_char = capinc_tty_put_char,
+	.flush_chars = capinc_tty_flush_chars,
+	.write_room = capinc_tty_write_room,
+	.chars_in_buffer = capinc_tty_chars_in_buffer,
+	.ioctl = capinc_tty_ioctl,
+	.set_termios = capinc_tty_set_termios,
+	.throttle = capinc_tty_throttle,
+	.unthrottle = capinc_tty_unthrottle,
+	.stop = capinc_tty_stop,
+	.start = capinc_tty_start,
+	.hangup = capinc_tty_hangup,
+	.break_ctl = capinc_tty_break_ctl,
+	.flush_buffer = capinc_tty_flush_buffer,
+	.set_ldisc = capinc_tty_set_ldisc,
+	.send_xchar = capinc_tty_send_xchar,
+	.read_proc = capinc_tty_read_proc,
+};
 
 static int capinc_tty_init(void)
 {
-	struct tty_driver *drv = &capinc_tty_driver;
+	struct tty_driver *drv = alloc_tty_driver(CAPINC_NR_PORTS);
+
+	if (!drv)
+		return -ENOMEM;
 
-	/* Initialize the tty_driver structure */
-	
-	memset(drv, 0, sizeof(struct tty_driver));
-	drv->magic = TTY_DRIVER_MAGIC;
 	drv->owner = THIS_MODULE;
 	drv->driver_name = "capi_nc";
 	drv->name = "capi/";
 	drv->major = capi_ttymajor;
 	drv->minor_start = 0;
-	drv->num = CAPINC_NR_PORTS;
 	drv->type = TTY_DRIVER_TYPE_SERIAL;
 	drv->subtype = SERIAL_TYPE_NORMAL;
 	drv->init_termios = tty_std_termios;
@@ -1291,43 +1307,23 @@
 	drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	drv->init_termios.c_lflag = 0;
 	drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS;
-	drv->refcount = &capinc_tty_refcount;
-	drv->table = capinc_tty_table;
-	drv->termios = capinc_tty_termios;
-	drv->termios_locked = capinc_tty_termios_locked;
-
-	drv->open = capinc_tty_open;
-	drv->close = capinc_tty_close;
-	drv->write = capinc_tty_write;
-	drv->put_char = capinc_tty_put_char;
-	drv->flush_chars = capinc_tty_flush_chars;
-	drv->write_room = capinc_tty_write_room;
-	drv->chars_in_buffer = capinc_tty_chars_in_buffer;
-	drv->ioctl = capinc_tty_ioctl;
-	drv->set_termios = capinc_tty_set_termios;
-	drv->throttle = capinc_tty_throttle;
-	drv->unthrottle = capinc_tty_unthrottle;
-	drv->stop = capinc_tty_stop;
-	drv->start = capinc_tty_start;
-	drv->hangup = capinc_tty_hangup;
-	drv->break_ctl = capinc_tty_break_ctl;
-	drv->flush_buffer = capinc_tty_flush_buffer;
-	drv->set_ldisc = capinc_tty_set_ldisc;
-	drv->send_xchar = capinc_tty_send_xchar;
-	drv->read_proc = capinc_tty_read_proc;
+	tty_set_operations(drv, &capinc_ops);
 	if (tty_register_driver(drv)) {
+		put_tty_driver(drv);
 		printk(KERN_ERR "Couldn't register capi_nc driver\n");
 		return -1;
 	}
+	capinc_tty_driver = drv;
 	return 0;
 }
 
 static void capinc_tty_exit(void)
 {
-	struct tty_driver *drv = &capinc_tty_driver;
+	struct tty_driver *drv = capinc_tty_driver;
 	int retval;
 	if ((retval = tty_unregister_driver(drv)))
 		printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval);
+	put_tty_driver(drv);
 }
 
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
diff -urN linux-2.5.70-bk16/drivers/isdn/eicon/linchr.c linux-2.5.70-bk17/drivers/isdn/eicon/linchr.c
--- linux-2.5.70-bk16/drivers/isdn/eicon/linchr.c	2003-05-26 18:00:22.000000000 -0700
+++ linux-2.5.70-bk17/drivers/isdn/eicon/linchr.c	2003-06-12 04:49:57.000000000 -0700
@@ -153,17 +153,15 @@
 	klog_t *pHeadItem;
 
 	if (BufferSize < sizeof(klog_t))
-	{
-		printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n",
-			BufferSize, sizeof(klog_t));
 		return -EIO;
-	}
 
 	pHeadItem = (klog_t *) DivasLogFifoRead();
 
-	if (pHeadItem)
-	{
-		memcpy(pClientLogBuffer, pHeadItem, sizeof(klog_t));
+	if (pHeadItem) {
+		if (copy_to_user(pClientLogBuffer, pHeadItem, sizeof(klog_t))) {
+			kfree(pHeadItem);
+			return -EFAULT;
+		}
 		kfree(pHeadItem);
 		return sizeof(klog_t);
 	}
diff -urN linux-2.5.70-bk16/drivers/isdn/i4l/isdn_tty.c linux-2.5.70-bk17/drivers/isdn/i4l/isdn_tty.c
--- linux-2.5.70-bk16/drivers/isdn/i4l/isdn_tty.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/isdn/i4l/isdn_tty.c	2003-06-12 04:49:57.000000000 -0700
@@ -1762,10 +1762,6 @@
 #endif
 		return retval;
 	}
-	if ((info->count == 1) && (info->flags & ISDN_ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		isdn_tty_change_speed(info);
-	}
 #ifdef ISDN_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
 #endif
@@ -1820,13 +1816,6 @@
 		goto out;
 	}
 	info->flags |= ISDN_ASYNC_CLOSING;
-	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-
 	tty->closing = 1;
 	/*
 	 * At this point we stop accepting input.  To do this, we
@@ -1997,6 +1986,21 @@
 		group_send_sig_info(SIGIO, SEND_SIG_PRIV, dev->profd);
 }
 
+static struct tty_operations modem_ops = {
+	.open = isdn_tty_open,
+	.close = isdn_tty_close,
+	.write = isdn_tty_write,
+	.flush_chars = isdn_tty_flush_chars,
+	.write_room = isdn_tty_write_room,
+	.chars_in_buffer = isdn_tty_chars_in_buffer,
+	.flush_buffer = isdn_tty_flush_buffer,
+	.ioctl = isdn_tty_ioctl,
+	.throttle = isdn_tty_throttle,
+	.unthrottle = isdn_tty_unthrottle,
+	.set_termios = isdn_tty_set_termios,
+	.hangup = isdn_tty_hangup,
+};
+
 int
 isdn_tty_init(void)
 {
@@ -2005,40 +2009,21 @@
 	modem_info *info;
 
 	m = &isdn_mdm;
-	memset(&m->tty_modem, 0, sizeof(struct tty_driver));
-	m->tty_modem.magic = TTY_DRIVER_MAGIC;
-	m->tty_modem.name = "ttyI";
-	m->tty_modem.devfs_name = "isdn/ttyI";
-	m->tty_modem.major = ISDN_TTY_MAJOR;
-	m->tty_modem.minor_start = 0;
-	m->tty_modem.num = ISDN_MAX_CHANNELS;
-	m->tty_modem.type = TTY_DRIVER_TYPE_SERIAL;
-	m->tty_modem.subtype = SERIAL_TYPE_NORMAL;
-	m->tty_modem.init_termios = tty_std_termios;
-	m->tty_modem.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	m->tty_modem.flags = TTY_DRIVER_REAL_RAW;
-	m->tty_modem.refcount = &m->refcount;
-	m->tty_modem.table = m->modem_table;
-	m->tty_modem.termios = m->modem_termios;
-	m->tty_modem.termios_locked = m->modem_termios_locked;
-	m->tty_modem.open = isdn_tty_open;
-	m->tty_modem.close = isdn_tty_close;
-	m->tty_modem.write = isdn_tty_write;
-	m->tty_modem.put_char = NULL;
-	m->tty_modem.flush_chars = isdn_tty_flush_chars;
-	m->tty_modem.write_room = isdn_tty_write_room;
-	m->tty_modem.chars_in_buffer = isdn_tty_chars_in_buffer;
-	m->tty_modem.flush_buffer = isdn_tty_flush_buffer;
-	m->tty_modem.ioctl = isdn_tty_ioctl;
-	m->tty_modem.throttle = isdn_tty_throttle;
-	m->tty_modem.unthrottle = isdn_tty_unthrottle;
-	m->tty_modem.set_termios = isdn_tty_set_termios;
-	m->tty_modem.stop = NULL;
-	m->tty_modem.start = NULL;
-	m->tty_modem.hangup = isdn_tty_hangup;
-	m->tty_modem.driver_name = "isdn_tty";
-
-	retval = tty_register_driver(&m->tty_modem);
+	m->tty_modem = alloc_tty_driver(ISDN_MAX_CHANNELS);
+	if (!m->tty_modem)
+		return -ENOMEM;
+	m->tty_modem->name = "ttyI";
+	m->tty_modem->devfs_name = "isdn/ttyI";
+	m->tty_modem->major = ISDN_TTY_MAJOR;
+	m->tty_modem->minor_start = 0;
+	m->tty_modem->type = TTY_DRIVER_TYPE_SERIAL;
+	m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
+	m->tty_modem->init_termios = tty_std_termios;
+	m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	m->tty_modem->flags = TTY_DRIVER_REAL_RAW;
+	m->tty_modem->driver_name = "isdn_tty";
+	tty_set_operations(m->tty_modem, &modem_ops);
+	retval = tty_register_driver(m->tty_modem);
 	if (retval) {
 		printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n");
 		goto err;
@@ -2066,7 +2051,6 @@
 		info->x_char = 0;
 		info->count = 0;
 		info->blocked_open = 0;
-		info->normal_termios = m->tty_modem.init_termios;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 		info->isdn_slot = NULL;
@@ -2112,8 +2096,10 @@
 		kfree(info->xmit_buf - 4);
 	}
  err_unregister_tty:
-	tty_unregister_driver(&isdn_mdm.tty_modem);
+	tty_unregister_driver(&isdn_mdm->tty_modem);
  err:
+	put_tty_driver(&isdn_mdm->tty_modem);
+	isdn_mdm->tty_modem = NULL;
 	return retval;
 }
 
@@ -2132,7 +2118,9 @@
 #endif
 		kfree(info->xmit_buf - 4);
 	}
-	tty_unregister_driver(&isdn_mdm.tty_modem);
+	tty_unregister_driver(&isdn_mdm->tty_modem);
+	put_tty_driver(&isdn_mdm->tty_modem);
+	isdn_mdm->tty_modem = NULL;
 }
 
 /*
diff -urN linux-2.5.70-bk16/drivers/isdn/i4l/isdn_tty.h linux-2.5.70-bk17/drivers/isdn/i4l/isdn_tty.h
--- linux-2.5.70-bk16/drivers/isdn/i4l/isdn_tty.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/isdn/i4l/isdn_tty.h	2003-06-12 04:49:57.000000000 -0700
@@ -114,11 +114,7 @@
 extern void isdn_tty_exit(void);
 
 struct isdn_modem {
-  int                refcount;			   /* Number of opens        */
-  struct tty_driver  tty_modem;			   /* tty-device             */
-  struct tty_struct  *modem_table[ISDN_MAX_CHANNELS]; /* ?? copied from Orig */
-  struct termios     *modem_termios[ISDN_MAX_CHANNELS];
-  struct termios     *modem_termios_locked[ISDN_MAX_CHANNELS];
+  struct tty_driver  *tty_modem;		   /* tty-device             */
   modem_info         info[ISDN_MAX_CHANNELS];	   /* Private data           */
 };
 
diff -urN linux-2.5.70-bk16/drivers/macintosh/macserial.c linux-2.5.70-bk17/drivers/macintosh/macserial.c
--- linux-2.5.70-bk16/drivers/macintosh/macserial.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/macintosh/macserial.c	2003-06-12 04:49:57.000000000 -0700
@@ -105,9 +105,6 @@
 #endif
 #define ZS_CLOCK         3686400 	/* Z8530 RTxC input clock rate */
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
-
 /* serial subtype definitions */
 #define SERIAL_TYPE_NORMAL	1
 
@@ -159,10 +156,6 @@
 static void rxdma_start(struct mac_serial * info, int current);
 static void rxdma_to_tty(struct mac_serial * info);
 
-static struct tty_struct *serial_table[NUM_CHANNELS];
-static struct termios *serial_termios[NUM_CHANNELS];
-static struct termios *serial_termios_locked[NUM_CHANNELS];
-
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
@@ -1959,12 +1952,6 @@
 	}
 	info->flags |= ZILOG_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ZILOG_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -2258,10 +2245,6 @@
 		return retval;
 	}
 
-	if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		change_speed(info, 0);
-	}
 #ifdef CONFIG_SERIAL_CONSOLE
 	if (sercons.cflag && sercons.index == line) {
 		tty->termios->c_cflag = sercons.cflag;
@@ -2502,6 +2485,26 @@
 #endif /* CONFIG_PMAC_PBOOK */
 }
 
+static struct tty_operations serial_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.break_ctl = rs_break,
+	.wait_until_sent = rs_wait_until_sent,
+	.read_proc = macserial_read_proc,
+};
+
 /* rs_init inits the driver */
 int macserial_init(void)
 {
@@ -2512,6 +2515,10 @@
 	if (zs_chain == 0)
 		probe_sccs();
 
+	serial_driver = alloc_tty_driver(zs_channels_found);
+	if (!serial_driver)
+		return -ENOMEM;
+
 	/* XXX assume it's a powerbook if we have a via-pmu
 	 * 
 	 * This is OK for core99 machines as well.
@@ -2526,6 +2533,7 @@
 		struct device_node* ch = zs_soft[i].dev_node;
 		if (!request_OF_resource(ch, 0, NULL)) {
 			printk(KERN_ERR "macserial: can't request IO resource !\n");
+			put_tty_driver(serial_driver);
 			return -ENODEV;
 		}
 		if (zs_soft[i].has_dma) {
@@ -2564,46 +2572,21 @@
 	/* Initialize the tty_driver structure */
 	/* Not all of this is exactly right for us. */
 
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.owner = THIS_MODULE;
-	serial_driver.driver_name = "macserial";
-	serial_driver.devfs_name = "tts/";
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = zs_channels_found;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-
-	serial_driver.init_termios.c_cflag =
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = "macserial";
+	serial_driver->devfs_name = "tts/";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		B38400 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_open;
-	serial_driver.close = rs_close;
-	serial_driver.write = rs_write;
-	serial_driver.flush_chars = rs_flush_chars;
-	serial_driver.write_room = rs_write_room;
-	serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	serial_driver.flush_buffer = rs_flush_buffer;
-	serial_driver.ioctl = rs_ioctl;
-	serial_driver.throttle = rs_throttle;
-	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.set_termios = rs_set_termios;
-	serial_driver.stop = rs_stop;
-	serial_driver.start = rs_start;
-	serial_driver.hangup = rs_hangup;
-	serial_driver.break_ctl = rs_break;
-	serial_driver.wait_until_sent = rs_wait_until_sent;
-	serial_driver.read_proc = macserial_read_proc;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &serial_ops);
 
-	if (tty_register_driver(&serial_driver))
+	if (tty_register_driver(serial_driver))
 		printk(KERN_ERR "Error: couldn't register serial driver\n");
 
 	for (channel = 0; channel < zs_channels_found; ++channel) {
@@ -2655,7 +2638,6 @@
 		info->blocked_open = 0;
 		INIT_WORK(&info->tqueue, do_softint, info);
 		spin_lock_init(&info->lock);
-		info->normal_termios = serial_driver.init_termios;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 		info->timeout = HZ;
@@ -2699,7 +2681,8 @@
 		}
 	}
 	spin_unlock_irqrestore(&info->lock, flags);
-	tty_unregister_driver(&serial_driver);
+	tty_unregister_driver(serial_driver);
+	put_tty_driver(serial_driver);
 
 	if (tmp_buf) {
 		free_page((unsigned long) tmp_buf);
@@ -2775,11 +2758,12 @@
 	/* Don't disable the transmitter. */
 }
 
-extern struct tty_driver serial_driver;
+static struct tty_driver *serial_driver;
+
 static struct tty_driver *serial_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 /*
diff -urN linux-2.5.70-bk16/drivers/macintosh/macserial.h linux-2.5.70-bk17/drivers/macintosh/macserial.h
--- linux-2.5.70-bk16/drivers/macintosh/macserial.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/macintosh/macserial.h	2003-06-12 04:49:57.000000000 -0700
@@ -161,7 +161,6 @@
 	int			xmit_tail;
 	int			xmit_cnt;
 	struct work_struct	tqueue;
-	struct termios		normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 
diff -urN linux-2.5.70-bk16/drivers/net/wan/pc300_tty.c linux-2.5.70-bk17/drivers/net/wan/pc300_tty.c
--- linux-2.5.70-bk16/drivers/net/wan/pc300_tty.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/net/wan/pc300_tty.c	2003-06-12 04:49:57.000000000 -0700
@@ -110,16 +110,12 @@
 	} st_cpc_tty_area;
 
 /* TTY data structures */
-static struct tty_struct *cpc_tty_serial_table[CPC_TTY_NPORTS];
-static struct termios *cpc_tty_serial_termios[CPC_TTY_NPORTS];
-static struct termios *cpc_tty_serial_termios_locked[CPC_TTY_NPORTS];
 static struct tty_driver serial_drv;
 
 /* local variables */
 st_cpc_tty_area	cpc_tty_area[CPC_TTY_NPORTS];
 
 int cpc_tty_cnt=0;	/* number of intrfaces configured with MLPPP */
-int cpc_tty_refcount;
 int cpc_tty_unreg_flag = 0;
 
 /* TTY functions prototype */
@@ -227,12 +223,6 @@
 		serial_drv.init_termios = tty_std_termios;
 		serial_drv.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
 		serial_drv.flags = TTY_DRIVER_REAL_RAW;
-		serial_drv.refcount = &cpc_tty_refcount;
-
-		/* tty data structures */
-		serial_drv.table = cpc_tty_serial_table;
-		serial_drv.termios = cpc_tty_serial_termios;
-		serial_drv.termios_locked = cpc_tty_serial_termios_locked;
 
 		/* interface routines from the upper tty layer to the tty driver */
 		serial_drv.open = cpc_tty_open;
@@ -415,7 +405,7 @@
 
 	CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name);
 	
-	if (!cpc_tty_refcount && cpc_tty_unreg_flag) {
+	if (!serial_drv.refcount && cpc_tty_unreg_flag) {
 		cpc_tty_unreg_flag = 0;
 		CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name);
 		if ((res=tty_unregister_driver(&serial_drv))) { 
@@ -663,7 +653,7 @@
 		CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
 		return ;
 	}
-	if (!cpc_tty_refcount && cpc_tty_unreg_flag) {
+	if (!serial_drv.refcount && cpc_tty_unreg_flag) {
 		cpc_tty_unreg_flag = 0;
 		CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name);
 		if ((res=tty_unregister_driver(&serial_drv))) { 
@@ -1058,9 +1048,9 @@
 	}
 
 	if (--cpc_tty_cnt == 0) { 
-		if (cpc_tty_refcount) {
+		if (serial_drv.refcount) {
 			CPC_TTY_DBG("%s: unregister is not possible, refcount=%d",
-							cpc_tty->name, cpc_tty_refcount);
+							cpc_tty->name, serial_drv.refcount);
 			cpc_tty_cnt++;
 			cpc_tty_unreg_flag = 1;
 			return;
diff -urN linux-2.5.70-bk16/drivers/net/wan/sdla_chdlc.c linux-2.5.70-bk17/drivers/net/wan/sdla_chdlc.c
--- linux-2.5.70-bk16/drivers/net/wan/sdla_chdlc.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/net/wan/sdla_chdlc.c	2003-06-12 04:49:57.000000000 -0700
@@ -285,13 +285,9 @@
 static void wanpipe_tty_trigger_poll(sdla_t *card);
 
 static struct tty_driver serial_driver;
-static int serial_refcount=1;
 static int tty_init_cnt=0;
 
 static struct serial_state rs_table[NR_PORTS];
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
 
 static char tty_driver_mode=WANOPT_TTY_SYNC;
 
@@ -1057,7 +1053,7 @@
 		struct serial_state * state;
 		if (!(--tty_init_cnt)){
 			int e1;
-			*serial_driver.refcount=0;
+			serial_driver.refcount=0;
 			
 			if ((e1 = tty_unregister_driver(&serial_driver)))
 				printk("SERIAL: failed to unregister serial driver (%d)\n",
@@ -4415,10 +4411,7 @@
 			B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 		serial_driver.flags = TTY_DRIVER_REAL_RAW;
 		
-		serial_driver.refcount = &serial_refcount;
-		serial_driver.table = serial_table;
-		serial_driver.termios = serial_termios;
-		serial_driver.termios_locked = serial_termios_locked;
+		serial_driver.refcount = 1;	/* !@!@^#^&!! */
 
 		serial_driver.open = wanpipe_tty_open;
 		serial_driver.close = wanpipe_tty_close;
@@ -4473,7 +4466,6 @@
 	state->custom_divisor = 0;
 	state->close_delay = 5*HZ/10;
 	state->closing_wait = 30*HZ;
-	state->normal_termios = serial_driver.init_termios;
 	state->icount.cts = state->icount.dsr = 
 		state->icount.rng = state->icount.dcd = 0;
 	state->icount.rx = state->icount.tx = 0;
diff -urN linux-2.5.70-bk16/drivers/net/wan/z85230.h linux-2.5.70-bk17/drivers/net/wan/z85230.h
--- linux-2.5.70-bk16/drivers/net/wan/z85230.h	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/net/wan/z85230.h	2003-06-12 04:49:57.000000000 -0700
@@ -333,7 +333,6 @@
 
 	struct tty_struct 	*tty;		/* Attached terminal */
 	int			line;		/* Minor number */
-	struct termios		normal_termios;	/* Terminal settings */
 	wait_queue_head_t	open_wait;	/* Tasks waiting to open */
 	wait_queue_head_t	close_wait;	/* and for close to end */
 	unsigned long		event;		/* Pending events */
diff -urN linux-2.5.70-bk16/drivers/oprofile/buffer_sync.c linux-2.5.70-bk17/drivers/oprofile/buffer_sync.c
--- linux-2.5.70-bk16/drivers/oprofile/buffer_sync.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/drivers/oprofile/buffer_sync.c	2003-06-12 04:49:57.000000000 -0700
@@ -236,8 +236,6 @@
 	struct vm_area_struct * vma;
 
 	for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
-		if (!vma)
-			goto out;
  
 		if (!vma->vm_file)
 			continue;
@@ -250,7 +248,7 @@
 		*offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; 
 		break;
 	}
-out:
+
 	return cookie;
 }
 
@@ -274,12 +272,17 @@
 		add_event_entry(KERNEL_EXIT_SWITCH_CODE); 
 }
  
-static void add_user_ctx_switch(pid_t pid, unsigned long cookie)
+static void
+add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
 {
 	add_event_entry(ESCAPE_CODE);
 	add_event_entry(CTX_SWITCH_CODE); 
-	add_event_entry(pid);
+	add_event_entry(task->pid);
 	add_event_entry(cookie);
+	/* Another code for daemon back-compat */
+	add_event_entry(ESCAPE_CODE);
+	add_event_entry(CTX_TGID_CODE);
+	add_event_entry(task->tgid);
 }
 
  
@@ -446,7 +449,7 @@
 				mm = take_tasks_mm(new);
 
 				cookie = get_exec_dcookie(mm);
-				add_user_ctx_switch(new->pid, cookie);
+				add_user_ctx_switch(new, cookie);
 			}
 		} else {
 			add_sample(mm, s, in_kernel);
diff -urN linux-2.5.70-bk16/drivers/oprofile/event_buffer.h linux-2.5.70-bk17/drivers/oprofile/event_buffer.h
--- linux-2.5.70-bk16/drivers/oprofile/event_buffer.h	2003-05-26 18:00:24.000000000 -0700
+++ linux-2.5.70-bk17/drivers/oprofile/event_buffer.h	2003-06-12 04:49:57.000000000 -0700
@@ -31,6 +31,7 @@
 #define KERNEL_ENTER_SWITCH_CODE	4
 #define KERNEL_EXIT_SWITCH_CODE		5
 #define MODULE_LOADED_CODE		6
+#define CTX_TGID_CODE			7
  
 /* add data to the event buffer */
 void add_event_entry(unsigned long data);
diff -urN linux-2.5.70-bk16/drivers/oprofile/oprof.c linux-2.5.70-bk17/drivers/oprofile/oprof.c
--- linux-2.5.70-bk16/drivers/oprofile/oprof.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/drivers/oprofile/oprof.c	2003-06-12 04:49:57.000000000 -0700
@@ -131,36 +131,33 @@
 
 static int __init oprofile_init(void)
 {
-	int err = -ENODEV;
+	/* Architecture must fill in the interrupt ops and the
+	 * logical CPU type, or we can fall back to the timer
+	 * interrupt profiler.
+	 */
+	int err = oprofile_arch_init(&oprofile_ops);
 
-	if (!timer) {
-		/* Architecture must fill in the interrupt ops and the
-		 * logical CPU type, or we can fall back to the timer
-		 * interrupt profiler.
-		 */
-		err = oprofile_arch_init(&oprofile_ops);
-	}
-
-	if (err == -ENODEV) {
+	if (err == -ENODEV || timer) {
 		timer_init(&oprofile_ops);
 		err = 0;
-	}
-
-	if (err)
+	} else if (err) {
 		goto out;
+	}
 
 	if (!oprofile_ops->cpu_type) {
 		printk(KERN_ERR "oprofile: cpu_type not set !\n");
 		err = -EFAULT;
-		goto out;
+	} else {
+		err = oprofilefs_register();
 	}
-
-	err = oprofilefs_register();
-	if (err)
-		goto out;
  
+	if (err)
+		goto out_exit;
 out:
 	return err;
+out_exit:
+	oprofile_arch_exit();
+	goto out;
 }
 
 
diff -urN linux-2.5.70-bk16/drivers/pcmcia/Kconfig linux-2.5.70-bk17/drivers/pcmcia/Kconfig
--- linux-2.5.70-bk16/drivers/pcmcia/Kconfig	2003-05-26 18:00:45.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/Kconfig	2003-06-12 04:49:57.000000000 -0700
@@ -29,8 +29,8 @@
 	  and ds.  If you want to compile it as a module, say M here and
 	  read <file:Documentation/modules.txt>.
 
-config CARDBUS
-	bool "CardBus support"
+config YENTA
+	tristate "CardBus yenta-compatible bridge support"
 	depends on PCMCIA && PCI
 	---help---
 	  CardBus is a bus mastering architecture for PC-cards, which allows
@@ -48,6 +48,11 @@
 
 	  If unsure, say Y.
 
+config CARDBUS
+	bool
+	depends on YENTA
+	default y if YENTA
+
 config I82092
 	tristate "i82092 compatible bridge support"
 	depends on PCMCIA && PCI
@@ -58,7 +63,7 @@
 
 config I82365
 	tristate "i82365 compatible bridge support"
-	depends on PCMCIA
+	depends on PCMCIA && ISA
 	help
 	  Say Y here to include support for ISA-bus PCMCIA host bridges that
 	  are register compatible with the Intel i82365.  These are found on
diff -urN linux-2.5.70-bk16/drivers/pcmcia/Makefile linux-2.5.70-bk17/drivers/pcmcia/Makefile
--- linux-2.5.70-bk16/drivers/pcmcia/Makefile	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/Makefile	2003-06-12 04:49:57.000000000 -0700
@@ -3,9 +3,7 @@
 #
 
 obj-$(CONFIG_PCMCIA)				+= pcmcia_core.o ds.o
-ifeq ($(CONFIG_CARDBUS),y)
-  obj-$(CONFIG_PCMCIA) 				+= yenta_socket.o
-endif
+obj-$(CONFIG_YENTA) 				+= yenta.o
 
 obj-$(CONFIG_I82365)				+= i82365.o
 obj-$(CONFIG_I82092)				+= i82092.o
@@ -14,8 +12,6 @@
 obj-$(CONFIG_PCMCIA_SA1100)			+= sa11xx_core.o sa1100_cs.o
 obj-$(CONFIG_PCMCIA_SA1111)			+= sa11xx_core.o sa1111_cs.o
 
-yenta_socket-y					+= pci_socket.o yenta.o
-
 pcmcia_core-y					+= cistpl.o rsrc_mgr.o bulkmem.o cs.o
 pcmcia_core-$(CONFIG_CARDBUS)			+= cardbus.o
 
diff -urN linux-2.5.70-bk16/drivers/pcmcia/bulkmem.c linux-2.5.70-bk17/drivers/pcmcia/bulkmem.c
--- linux-2.5.70-bk16/drivers/pcmcia/bulkmem.c	2003-05-26 18:01:03.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/bulkmem.c	2003-06-12 04:49:57.000000000 -0700
@@ -63,7 +63,7 @@
 {
     int ret, tries;
     client_t *mtd;
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     
     mtd = handle->mtd;
     if (mtd == NULL)
@@ -130,7 +130,7 @@
     eraseq_entry_t *erase = busy->erase;
     mtd_request_t req;
     client_t *mtd;
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     int ret;
 
     DEBUG(2, "cs: trying erase request 0x%p...\n", busy);
@@ -259,27 +259,27 @@
 	win->ctl.flags |= MAP_ATTRIB;
     win->ctl.speed = req->AccessSpeed;
     win->ctl.card_start = req->CardOffset;
-    win->sock->ss_entry->set_mem_map(win->sock->sock, &win->ctl);
+    win->sock->ss_entry->set_mem_map(win->sock, &win->ctl);
     return CS_SUCCESS;
 }
 
 static int mtd_set_vpp(client_handle_t handle, mtd_vpp_req_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
     if (req->Vpp1 != req->Vpp2)
 	return CS_BAD_VPP;
     s = SOCKET(handle);
     s->socket.Vpp = req->Vpp1;
-    if (s->ss_entry->set_socket(s->sock, &s->socket))
+    if (s->ss_entry->set_socket(s, &s->socket))
 	return CS_BAD_VPP;
     return CS_SUCCESS;
 }
 
 static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
     s = SOCKET(handle);
@@ -287,7 +287,7 @@
 	s->socket.csc_mask |= SS_READY;
     else
 	s->socket.csc_mask &= ~SS_READY;
-    if (s->ss_entry->set_socket(s->sock, &s->socket))
+    if (s->ss_entry->set_socket(s, &s->socket))
 	return CS_GENERAL_FAILURE;
     return CS_SUCCESS;
 }
@@ -417,7 +417,7 @@
 
 int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn)
 {
-    socket_info_t *s = SOCKET(handle);
+    struct pcmcia_socket *s = SOCKET(handle);
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
     
@@ -450,7 +450,7 @@
 int pcmcia_register_mtd(client_handle_t handle, mtd_reg_t *reg)
 {
     memory_handle_t list;
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
@@ -533,12 +533,12 @@
 
 int pcmcia_open_memory(client_handle_t *handle, open_mem_t *open, memory_handle_t *mh)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     memory_handle_t region;
     
     if ((handle == NULL) || CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
-    s = SOCKET(*handle);
+    s = (*handle)->Socket;
     if (open->Attributes & MEMORY_TYPE_AM)
 	region = s->a_region;
     else
diff -urN linux-2.5.70-bk16/drivers/pcmcia/cardbus.c linux-2.5.70-bk17/drivers/pcmcia/cardbus.c
--- linux-2.5.70-bk16/drivers/pcmcia/cardbus.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/cardbus.c	2003-06-12 04:49:58.000000000 -0700
@@ -119,11 +119,11 @@
 
     These are similar to setup_cis_mem and release_cis_mem for 16-bit
     cards.  The "result" that is used externally is the cb_cis_virt
-    pointer in the socket_info_t structure.
+    pointer in the struct pcmcia_socket structure.
     
 =====================================================================*/
 
-static void cb_release_cis_mem(socket_info_t * s)
+static void cb_release_cis_mem(struct pcmcia_socket * s)
 {
 	if (s->cb_cis_virt) {
 		DEBUG(1, "cs: cb_release_cis_mem()\n");
@@ -133,7 +133,7 @@
 	}
 }
 
-static int cb_setup_cis_mem(socket_info_t * s, struct resource *res)
+static int cb_setup_cis_mem(struct pcmcia_socket * s, struct resource *res)
 {
 	unsigned int start, size;
 
@@ -162,7 +162,7 @@
     
 =====================================================================*/
 
-int read_cb_mem(socket_info_t * s, int space, u_int addr, u_int len, void *ptr)
+int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void *ptr)
 {
 	struct pci_dev *dev;
 	struct resource *res;
@@ -237,7 +237,7 @@
 	}
 }
 
-int cb_alloc(socket_info_t * s)
+int cb_alloc(struct pcmcia_socket * s)
 {
 	struct pci_bus *bus = s->cap.cb_dev->subordinate;
 	struct pci_dev *dev;
@@ -266,7 +266,7 @@
 	return CS_SUCCESS;
 }
 
-void cb_free(socket_info_t * s)
+void cb_free(struct pcmcia_socket * s)
 {
 	struct pci_dev *bridge = s->cap.cb_dev;
 
diff -urN linux-2.5.70-bk16/drivers/pcmcia/cistpl.c linux-2.5.70-bk17/drivers/pcmcia/cistpl.c
--- linux-2.5.70-bk16/drivers/pcmcia/cistpl.c	2003-05-26 18:00:27.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/cistpl.c	2003-06-12 04:49:58.000000000 -0700
@@ -82,11 +82,11 @@
 
 INT_MODULE_PARM(cis_width,	0);		/* 16-bit CIS? */
 
-void release_cis_mem(socket_info_t *s)
+void release_cis_mem(struct pcmcia_socket *s)
 {
     if (s->cis_mem.sys_start != 0) {
 	s->cis_mem.flags &= ~MAP_ACTIVE;
-	s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
+	s->ss_entry->set_mem_map(s, &s->cis_mem);
 	if (!(s->cap.features & SS_CAP_STATIC_MAP))
 	    release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
 	iounmap(s->cis_virt);
@@ -101,7 +101,7 @@
  * map the memory space.
  */
 static unsigned char *
-set_cis_map(socket_info_t *s, unsigned int card_offset, unsigned int flags)
+set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
 {
     pccard_mem_map *mem = &s->cis_mem;
     if (!(s->cap.features & SS_CAP_STATIC_MAP) &&
@@ -119,7 +119,7 @@
     }
     mem->card_start = card_offset;
     mem->flags = flags;
-    s->ss_entry->set_mem_map(s->sock, mem);
+    s->ss_entry->set_mem_map(s, mem);
     if (s->cap.features & SS_CAP_STATIC_MAP) {
 	if (s->cis_virt)
 	    iounmap(s->cis_virt);
@@ -139,7 +139,7 @@
 #define IS_ATTR		1
 #define IS_INDIRECT	8
 
-int read_cis_mem(socket_info_t *s, int attr, u_int addr,
+int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		 u_int len, void *ptr)
 {
     u_char *sys, *end, *buf = ptr;
@@ -202,7 +202,7 @@
     return 0;
 }
 
-void write_cis_mem(socket_info_t *s, int attr, u_int addr,
+void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		   u_int len, void *ptr)
 {
     u_char *sys, *end, *buf = ptr;
@@ -266,7 +266,7 @@
     
 ======================================================================*/
 
-static void read_cis_cache(socket_info_t *s, int attr, u_int addr,
+static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
 			   u_int len, void *ptr)
 {
     struct cis_cache_entry *cis;
@@ -306,7 +306,7 @@
 }
 
 static void
-remove_cis_cache(socket_info_t *s, int attr, u_int addr, u_int len)
+remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len)
 {
 	struct cis_cache_entry *cis;
 
@@ -318,7 +318,7 @@
 		}
 }
 
-void destroy_cis_cache(socket_info_t *s)
+void destroy_cis_cache(struct pcmcia_socket *s)
 {
 	struct list_head *l, *n;
 
@@ -337,7 +337,7 @@
     
 ======================================================================*/
 
-int verify_cis_cache(socket_info_t *s)
+int verify_cis_cache(struct pcmcia_socket *s)
 {
 	struct cis_cache_entry *cis;
 	char buf[256];
@@ -369,7 +369,7 @@
 
 int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
     s = SOCKET(handle);
@@ -409,7 +409,7 @@
 
 int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
     s = SOCKET(handle);
@@ -445,7 +445,7 @@
     return pcmcia_get_next_tuple(handle, tuple);
 }
 
-static int follow_link(socket_info_t *s, tuple_t *tuple)
+static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
 {
     u_char link[5];
     u_int ofs;
@@ -487,7 +487,7 @@
 
 int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     u_char link[2], tmp;
     int ofs, i, attr;
     
@@ -588,7 +588,7 @@
 
 int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     u_int len;
     
     if (CHECK_HANDLE(handle))
diff -urN linux-2.5.70-bk16/drivers/pcmcia/cs.c linux-2.5.70-bk17/drivers/pcmcia/cs.c
--- linux-2.5.70-bk16/drivers/pcmcia/cs.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/cs.c	2003-06-12 04:49:58.000000000 -0700
@@ -124,9 +124,11 @@
     0, SS_DETECT, 0, 0, 0
 };
 
-/* Table of sockets */
-socket_t sockets = 0;
-socket_info_t *socket_table[MAX_SOCK];
+
+/* List of all sockets, protected by a rwsem */
+LIST_HEAD(pcmcia_socket_list);
+DECLARE_RWSEM(pcmcia_socket_list_rwsem);
+
 
 #ifdef CONFIG_PROC_FS
 struct proc_dir_entry *proc_pccard = NULL;
@@ -235,48 +237,48 @@
 
 ======================================================================*/
 
-static int register_callback(socket_info_t *s, void (*handler)(void *, unsigned int), void * info)
+static int register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
 {
 	int error;
 
 	if (handler && !try_module_get(s->ss_entry->owner))
 		return -ENODEV;
-	error = s->ss_entry->register_callback(s->sock, handler, info);
+	error = s->ss_entry->register_callback(s, handler, info);
 	if (!handler)
 		module_put(s->ss_entry->owner);
 	return error;
 }
 
-static int get_socket_status(socket_info_t *s, int *val)
+static int get_socket_status(struct pcmcia_socket *s, int *val)
 {
-	return s->ss_entry->get_status(s->sock, val);
+	return s->ss_entry->get_status(s, val);
 }
 
-static int set_socket(socket_info_t *s, socket_state_t *state)
+static int set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
-	return s->ss_entry->set_socket(s->sock, state);
+	return s->ss_entry->set_socket(s, state);
 }
 
-static int set_io_map(socket_info_t *s, struct pccard_io_map *io)
+static int set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
 {
-	return s->ss_entry->set_io_map(s->sock, io);
+	return s->ss_entry->set_io_map(s, io);
 }
 
-static int set_mem_map(socket_info_t *s, struct pccard_mem_map *mem)
+static int set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
 {
-	return s->ss_entry->set_mem_map(s->sock, mem);
+	return s->ss_entry->set_mem_map(s, mem);
 }
 
-static int suspend_socket(socket_info_t *s)
+static int suspend_socket(struct pcmcia_socket *s)
 {
 	s->socket = dead_socket;
-	return s->ss_entry->suspend(s->sock);
+	return s->ss_entry->suspend(s);
 }
 
-static int init_socket(socket_info_t *s)
+static int init_socket(struct pcmcia_socket *s)
 {
 	s->socket = dead_socket;
-	return s->ss_entry->init(s->sock);
+	return s->ss_entry->init(s);
 }
 
 /*====================================================================*/
@@ -285,7 +287,7 @@
 static int proc_read_clients(char *buf, char **start, off_t pos,
 			     int count, int *eof, void *data)
 {
-    socket_info_t *s = data;
+    struct pcmcia_socket *s = data;
     client_handle_t c;
     char *p = buf;
 
@@ -303,145 +305,226 @@
     
 ======================================================================*/
 
-static int pccardd(void *__skt);
-void pcmcia_unregister_socket(struct class_device *dev);
+/**
+ * socket drivers are expected to use the following callbacks in their 
+ * .drv struct:
+ *  - pcmcia_socket_dev_suspend
+ *  - pcmcia_socket_dev_resume
+ * These functions check for the appropriate struct pcmcia_soket arrays,
+ * and pass them to the low-level functions pcmcia_{suspend,resume}_socket
+ */
+static int socket_resume(struct pcmcia_socket *skt);
+static int socket_suspend(struct pcmcia_socket *skt);
+
+int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct pcmcia_socket *socket;
+
+	if (level != SUSPEND_SAVE_STATE)
+		return 0;
+
+	down_read(&pcmcia_socket_list_rwsem);
+	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+		if (socket->dev.dev != dev)
+			continue;
+		down(&socket->skt_sem);
+		socket_suspend(socket);
+		up(&socket->skt_sem);
+	}
+	up_read(&pcmcia_socket_list_rwsem);
+
+	return 0;
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
+
+int pcmcia_socket_dev_resume(struct device *dev, u32 level)
+{
+	struct pcmcia_socket *socket;
 
+	if (level != RESUME_RESTORE_STATE)
+		return 0;
+
+	down_read(&pcmcia_socket_list_rwsem);
+	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
+		if (socket->dev.dev != dev)
+			continue;
+		down(&socket->skt_sem);
+		socket_resume(socket);
+		up(&socket->skt_sem);
+	}
+	up_read(&pcmcia_socket_list_rwsem);
+
+	return 0;
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_resume);
+
+
+static int pccardd(void *__skt);
 #define to_class_data(dev) dev->class_data
 
-/**
- * pcmcia_register_socket - add a new pcmcia socket device
- */
-int pcmcia_register_socket(struct class_device *class_dev)
+static int pcmcia_add_socket(struct class_device *class_dev)
 {
-	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
-	socket_info_t *s_info;
-	unsigned int i, j, ret;
+	struct pcmcia_socket *socket = class_get_devdata(class_dev);
+	int ret = 0;
 
-	if (!cls_d)
-		return -EINVAL;
+	/* base address = 0, map = 0 */
+	socket->cis_mem.flags = 0;
+	socket->cis_mem.speed = cis_speed;
+	socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy;
+	INIT_LIST_HEAD(&socket->cis_cache);
+	spin_lock_init(&socket->lock);
+
+	init_socket(socket);
+	socket->ss_entry->inquire_socket(socket, &socket->cap);
+
+	init_completion(&socket->thread_done);
+	init_waitqueue_head(&socket->thread_wait);
+	init_MUTEX(&socket->skt_sem);
+	spin_lock_init(&socket->thread_lock);
+	ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
+	if (ret < 0)
+		return ret;
 
-	DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", cls_d->ops);
+	wait_for_completion(&socket->thread_done);
+	BUG_ON(!socket->thread);
 
-	s_info = kmalloc(cls_d->nsock * sizeof(struct socket_info_t), GFP_KERNEL);
-	if (!s_info)
-		return -ENOMEM;
-	memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t));
-
-	cls_d->s_info = s_info;
-	ret = 0;
-
-	/* socket initialization */
-	for (i = 0; i < cls_d->nsock; i++) {
-		socket_info_t *s = &s_info[i];
-
-		s->ss_entry = cls_d->ops;
-		s->sock = i + cls_d->sock_offset;
-
-		/* base address = 0, map = 0 */
-		s->cis_mem.flags = 0;
-		s->cis_mem.speed = cis_speed;
-		s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
-		INIT_LIST_HEAD(&s->cis_cache);
-		spin_lock_init(&s->lock);
-
-		/* TBD: remove usage of socket_table, use class_for_each_dev instead */
-		for (j = 0; j < sockets; j++)
-			if (socket_table[j] == NULL) break;
-		socket_table[j] = s;
-		if (j == sockets) sockets++;
-
-		init_socket(s);
-		s->ss_entry->inquire_socket(s->sock, &s->cap);
-
-		init_completion(&s->thread_done);
-		init_waitqueue_head(&s->thread_wait);
-		init_MUTEX(&s->skt_sem);
-		spin_lock_init(&s->thread_lock);
-		ret = kernel_thread(pccardd, s, CLONE_KERNEL);
-		if (ret < 0) {
-			pcmcia_unregister_socket(class_dev);
-			break;
-		}
+#ifdef CONFIG_PROC_FS
+	if (proc_pccard) {
+		char name[3];
+		sprintf(name, "%02d", socket->sock);
+		socket->proc = proc_mkdir(name, proc_pccard);
+		if (socket->proc)
+			socket->ss_entry->proc_setup(socket, socket->proc);
+#ifdef PCMCIA_DEBUG
+		if (socket->proc)
+			create_proc_read_entry("clients", 0, socket->proc,
+					       proc_read_clients, socket);
+#endif
+	}
+#endif
+	return 0;
+}
 
-		wait_for_completion(&s->thread_done);
-		BUG_ON(!s->thread);
+static void pcmcia_remove_socket(struct class_device *class_dev)
+{
+	struct pcmcia_socket *socket = class_get_devdata(class_dev);
+	client_t *client;
 
 #ifdef CONFIG_PROC_FS
-		if (proc_pccard) {
-			char name[3];
-			sprintf(name, "%02d", j);
-			s->proc = proc_mkdir(name, proc_pccard);
-			if (s->proc)
-				s->ss_entry->proc_setup(i, s->proc);
+	if (proc_pccard) {
+		char name[3];
+		sprintf(name, "%02d", socket->sock);
 #ifdef PCMCIA_DEBUG
-			if (s->proc)
-				create_proc_read_entry("clients", 0, s->proc,
-				       proc_read_clients, s);
+		remove_proc_entry("clients", socket->proc);
 #endif
-		}
+		remove_proc_entry(name, proc_pccard);
+	}
 #endif
+	if (socket->thread) {
+		init_completion(&socket->thread_done);
+		socket->thread = NULL;
+		wake_up(&socket->thread_wait);
+		wait_for_completion(&socket->thread_done);
 	}
-	return ret;
+	release_cis_mem(socket);
+	while (socket->clients) {
+		client = socket->clients;
+		socket->clients = socket->clients->next;
+		kfree(client);
+	}
+	socket->ss_entry = NULL;
+}
+
+
+/**
+ * pcmcia_register_socket - add a new pcmcia socket device
+ */
+int pcmcia_register_socket(struct pcmcia_socket *socket)
+{
+	if (!socket || !socket->ss_entry || !socket->dev.dev)
+		return -EINVAL;
+
+	DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", socket->ss_entry);
+
+	/* try to obtain a socket number [yes, it gets ugly if we
+	 * register more than 2^sizeof(unsigned int) pcmcia 
+	 * sockets... but the socket number is deprecated 
+	 * anyways, so I don't care] */
+	down_write(&pcmcia_socket_list_rwsem);
+	if (list_empty(&pcmcia_socket_list))
+		socket->sock = 0;
+	else {
+		unsigned int found, i = 1;
+		struct pcmcia_socket *tmp;
+		do {
+			found = 1;
+			list_for_each_entry(tmp, &pcmcia_socket_list, socket_list) {
+				if (tmp->sock == i)
+					found = 0;
+			}
+			i++;
+		} while (!found);
+		socket->sock = i - 1;
+	}
+	list_add_tail(&socket->socket_list, &pcmcia_socket_list);
+	up_write(&pcmcia_socket_list_rwsem);
+
+
+	/* set proper values in socket->dev */
+	socket->dev.class_data = socket;
+	socket->dev.class = &pcmcia_socket_class;
+	snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u\n", socket->sock);
+
+	/* register with the device core */
+	if (class_device_register(&socket->dev)) {
+		down_write(&pcmcia_socket_list_rwsem);
+		list_del(&socket->socket_list);
+		up_write(&pcmcia_socket_list_rwsem);
+		return -EINVAL;
+	}
+
+	return 0;
 } /* pcmcia_register_socket */
+EXPORT_SYMBOL(pcmcia_register_socket);
 
 
 /**
  * pcmcia_unregister_socket - remove a pcmcia socket device
  */
-void pcmcia_unregister_socket(struct class_device *class_dev)
+void pcmcia_unregister_socket(struct pcmcia_socket *socket)
 {
-	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
-	unsigned int i;
-	int j, socket = -1;
-	client_t *client;
-	socket_info_t *s;
-
-	if (!cls_d)
+	if (!socket)
 		return;
 
-	s = (socket_info_t *) cls_d->s_info;
+	DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ss_entry);
 
-	for (i = 0; i < cls_d->nsock; i++) {
-		for (j = 0; j < MAX_SOCK; j++)
-			if (socket_table [j] == s) {
-				socket = j;
-				break;
-			}
-		if (socket < 0)
-			continue;
-		
-#ifdef CONFIG_PROC_FS
-		if (proc_pccard) {
-			char name[3];
-			sprintf(name, "%02d", socket);
-#ifdef PCMCIA_DEBUG
-			remove_proc_entry("clients", s->proc);
-#endif
-			remove_proc_entry(name, proc_pccard);
-		}
-#endif
-		if (s->thread) {
-			init_completion(&s->thread_done);
-			s->thread = NULL;
-			wake_up(&s->thread_wait);
-			wait_for_completion(&s->thread_done);
-		}
-		release_cis_mem(s);
-		while (s->clients) {
-			client = s->clients;
-			s->clients = s->clients->next;
-			kfree(client);
-		}
-		s->ss_entry = NULL;
-		socket_table[socket] = NULL;
-		for (j = socket; j < sockets-1; j++)
-			socket_table[j] = socket_table[j+1];
-		sockets--;
+	/* remove from the device core */
+	class_device_unregister(&socket->dev);
 
-		s++;
-	}
-	kfree(cls_d->s_info);
+	/* remove from our own list */
+	down_write(&pcmcia_socket_list_rwsem);
+	list_del(&socket->socket_list);
+	up_write(&pcmcia_socket_list_rwsem);
 } /* pcmcia_unregister_socket */
+EXPORT_SYMBOL(pcmcia_unregister_socket);
+
+
+struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
+{
+	struct pcmcia_socket *s;
+
+	down_read(&pcmcia_socket_list_rwsem);
+	list_for_each_entry(s, &pcmcia_socket_list, socket_list)
+		if (s->sock == nr) {
+			up_read(&pcmcia_socket_list_rwsem);
+			return s;
+		}
+	up_read(&pcmcia_socket_list_rwsem);
+
+	return NULL;
+
+}
+EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
 
 
 /*======================================================================
@@ -465,9 +548,9 @@
     }
 }
 
-static int send_event(socket_info_t *s, event_t event, int priority);
+static int send_event(struct pcmcia_socket *s, event_t event, int priority);
 
-static void shutdown_socket(socket_info_t *s)
+static void shutdown_socket(struct pcmcia_socket *s)
 {
     client_t **c;
     
@@ -522,7 +605,7 @@
     
 ======================================================================*/
 
-static int send_event(socket_info_t *s, event_t event, int priority)
+static int send_event(struct pcmcia_socket *s, event_t event, int priority)
 {
     client_t *client = s->clients;
     int ret;
@@ -543,7 +626,7 @@
     return ret;
 } /* send_event */
 
-static void pcmcia_error(socket_info_t *skt, const char *fmt, ...)
+static void pcmcia_error(struct pcmcia_socket *skt, const char *fmt, ...)
 {
 	static char buf[128];
 	va_list ap;
@@ -559,7 +642,7 @@
 
 #define cs_to_timeout(cs) (((cs) * HZ + 99) / 100)
 
-static void socket_remove_drivers(socket_info_t *skt)
+static void socket_remove_drivers(struct pcmcia_socket *skt)
 {
 	client_t *client;
 
@@ -570,7 +653,7 @@
 			client->state |= CLIENT_STALE;
 }
 
-static void socket_shutdown(socket_info_t *skt)
+static void socket_shutdown(struct pcmcia_socket *skt)
 {
 	socket_remove_drivers(skt);
 	set_current_state(TASK_UNINTERRUPTIBLE);
@@ -579,7 +662,7 @@
 	shutdown_socket(skt);
 }
 
-static int socket_reset(socket_info_t *skt)
+static int socket_reset(struct pcmcia_socket *skt)
 {
 	int status, i;
 
@@ -609,7 +692,7 @@
 	return CS_GENERAL_FAILURE;
 }
 
-static int socket_setup(socket_info_t *skt, int initial_delay)
+static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 {
 	int status, i;
 
@@ -673,7 +756,7 @@
  * Handle card insertion.  Setup the socket, reset the card,
  * and then tell the rest of PCMCIA that a card is present.
  */
-static int socket_insert(socket_info_t *skt)
+static int socket_insert(struct pcmcia_socket *skt)
 {
 	int ret;
 
@@ -693,7 +776,7 @@
 	return ret;
 }
 
-static int socket_suspend(socket_info_t *skt)
+static int socket_suspend(struct pcmcia_socket *skt)
 {
 	if (skt->state & SOCKET_SUSPEND)
 		return CS_IN_USE;
@@ -710,7 +793,7 @@
  * our cached copy.  If they are different, the card has been
  * replaced, and we need to tell the drivers.
  */
-static int socket_resume(socket_info_t *skt)
+static int socket_resume(struct pcmcia_socket *skt)
 {
 	int ret;
 
@@ -742,7 +825,7 @@
 
 static int pccardd(void *__skt)
 {
-	socket_info_t *skt = __skt;
+	struct pcmcia_socket *skt = __skt;
 	DECLARE_WAITQUEUE(wait, current);
 
 	daemonize("pccardd");
@@ -799,7 +882,7 @@
 
 static void parse_events(void *info, u_int events)
 {
-	socket_info_t *s = info;
+	struct pcmcia_socket *s = info;
 
 	spin_lock(&s->thread_lock);
 	s->thread_events |= events;
@@ -808,68 +891,6 @@
 	wake_up(&s->thread_wait);
 } /* parse_events */
 
-/*======================================================================
-
-    Another event handler, for power management events.
-
-    This does not comply with the latest PC Card spec for handling
-    power management events.
-    
-======================================================================*/
-
-void pcmcia_suspend_socket (socket_info_t *skt)
-{
-	down(&skt->skt_sem);
-	socket_suspend(skt);
-	up(&skt->skt_sem);
-}
-
-void pcmcia_resume_socket (socket_info_t *skt)
-{
-	down(&skt->skt_sem);
-	socket_resume(skt);
-	up(&skt->skt_sem);
-}
-
-
-int pcmcia_socket_dev_suspend(struct pcmcia_socket_class_data *cls_d, u32 state, u32 level)
-{
-	socket_info_t *s;
-	int i;
-
-	if ((!cls_d) || (level != SUSPEND_SAVE_STATE))
-		return 0;
-
-	s = (socket_info_t *) cls_d->s_info;
-
-	for (i = 0; i < cls_d->nsock; i++) {
-		pcmcia_suspend_socket(s);
-		s++;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
-
-int pcmcia_socket_dev_resume(struct pcmcia_socket_class_data *cls_d, u32 level)
-{
-	socket_info_t *s;
-	int i;
-
-	if ((!cls_d) || (level != RESUME_RESTORE_STATE))
-		return 0;
-
-	s = (socket_info_t *) cls_d->s_info;
-
-	for (i = 0; i < cls_d->nsock; i++) {
-		pcmcia_resume_socket(s);
-		s++;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(pcmcia_socket_dev_resume);
-
 
 /*======================================================================
 
@@ -877,7 +898,7 @@
     
 ======================================================================*/
 
-static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
+static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
 			  ioaddr_t num, u_int lines, char *name)
 {
     int i;
@@ -941,7 +962,7 @@
     return (i == MAX_IO_WIN);
 } /* alloc_io_space */
 
-static void release_io_space(socket_info_t *s, ioaddr_t base,
+static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
 			     ioaddr_t num)
 {
     int i;
@@ -969,7 +990,7 @@
 int pcmcia_access_configuration_register(client_handle_t handle,
 					 conf_reg_t *reg)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     config_t *c;
     int addr;
     u_char val;
@@ -1020,18 +1041,18 @@
 int pcmcia_bind_device(bind_req_t *req)
 {
     client_t *client;
-    socket_info_t *s;
+    struct pcmcia_socket *s;
 
-    if (CHECK_SOCKET(req->Socket))
-	return CS_BAD_SOCKET;
-    s = SOCKET(req);
+    s = req->Socket;
+    if (!s)
+	    return CS_BAD_SOCKET;
 
     client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL);
     if (!client) return CS_OUT_OF_RESOURCE;
     memset(client, '\0', sizeof(client_t));
     client->client_magic = CLIENT_MAGIC;
     strlcpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
-    client->Socket = req->Socket;
+    client->Socket = s;
     client->Function = req->Function;
     client->state = CLIENT_UNBOUND;
     client->erase_busy.next = &client->erase_busy;
@@ -1055,12 +1076,12 @@
 
 int pcmcia_bind_mtd(mtd_bind_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     memory_handle_t region;
     
-    if (CHECK_SOCKET(req->Socket))
-	return CS_BAD_SOCKET;
-    s = SOCKET(req);
+    s = req->Socket;
+    if (!s)
+	    return CS_BAD_SOCKET;
     
     if (req->Attributes & REGION_TYPE_AM)
 	region = s->a_region;
@@ -1085,10 +1106,10 @@
 int pcmcia_deregister_client(client_handle_t handle)
 {
     client_t **client;
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     memory_handle_t region;
     u_long flags;
-    int i, sn;
+    int i;
     
     DEBUG(1, "cs: deregister_client(%p)\n", handle);
     if (CHECK_HANDLE(handle))
@@ -1109,8 +1130,6 @@
 	    if (region->mtd == handle) region->mtd = NULL;
     }
     
-    sn = handle->Socket; s = socket_table[sn];
-
     if ((handle->state & CLIENT_STALE) ||
 	(handle->Attributes & INFO_MASTER_CLIENT)) {
 	spin_lock_irqsave(&s->lock, flags);
@@ -1142,7 +1161,7 @@
 int pcmcia_get_configuration_info(client_handle_t handle,
 				  config_info_t *config)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     config_t *c;
     
     if (CHECK_HANDLE(handle))
@@ -1212,9 +1231,15 @@
 
 int pcmcia_get_card_services_info(servinfo_t *info)
 {
+    unsigned int socket_count = 0;
+    struct list_head *tmp;
     info->Signature[0] = 'C';
     info->Signature[1] = 'S';
-    info->Count = sockets;
+    down_read(&pcmcia_socket_list_rwsem);
+    list_for_each(tmp, &pcmcia_socket_list)
+	    socket_count++;
+    up_read(&pcmcia_socket_list_rwsem);
+    info->Count = socket_count;
     info->Revision = CS_RELEASE_CODE;
     info->CSLevel = 0x0210;
     info->VendorString = (char *)release;
@@ -1231,15 +1256,17 @@
 int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req)
 {
     socket_t s;
+    struct pcmcia_socket *socket;
     if (req->Attributes & CLIENT_THIS_SOCKET)
 	s = req->Socket;
     else
 	s = 0;
-    if (CHECK_SOCKET(req->Socket))
+    socket = pcmcia_get_socket_by_nr(s);
+    if (!socket)
 	return CS_BAD_SOCKET;
-    if (socket_table[s]->clients == NULL)
+    if (socket->clients == NULL)
 	return CS_NO_MORE_ITEMS;
-    *handle = socket_table[s]->clients;
+    *handle = socket->clients;
     return CS_SUCCESS;
 } /* get_first_client */
 
@@ -1247,13 +1274,13 @@
 
 int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     if ((handle == NULL) || CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
     if ((*handle)->next == NULL) {
 	if (req->Attributes & CLIENT_THIS_SOCKET)
 	    return CS_NO_MORE_ITEMS;
-	s = SOCKET(*handle);
+	s = (*handle)->Socket;
 	if (s->clients == NULL)
 	    return CS_NO_MORE_ITEMS;
 	*handle = s->clients;
@@ -1266,12 +1293,12 @@
 
 int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     window_t *win;
     int w;
 
     if (idx == 0)
-	s = SOCKET((client_handle_t)*handle);
+	s = ((client_handle_t)*handle)->Socket;
     else
 	s = (*handle)->sock;
     if (!(s->state & SOCKET_PRESENT))
@@ -1321,7 +1348,7 @@
 
 struct pci_bus *pcmcia_lookup_bus(client_handle_t handle)
 {
-	socket_info_t *s;
+	struct pcmcia_socket *s;
 
 	if (CHECK_HANDLE(handle))
 		return NULL;
@@ -1345,7 +1372,7 @@
 
 int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     config_t *c;
     int val;
     
@@ -1424,7 +1451,7 @@
 
 int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     if ((win == NULL) || (win->magic != WINDOW_MAGIC))
 	return CS_BAD_HANDLE;
     if (req->Page != 0)
@@ -1445,7 +1472,7 @@
 int pcmcia_modify_configuration(client_handle_t handle,
 				modconf_t *mod)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     config_t *c;
     
     if (CHECK_HANDLE(handle))
@@ -1522,14 +1549,13 @@
 
 int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
 {
-    client_t *client;
-    socket_info_t *s;
-    socket_t ns;
+    client_t *client = NULL;
+    struct pcmcia_socket *s;
     
     /* Look for unbound client with matching dev_info */
-    client = NULL;
-    for (ns = 0; ns < sockets; ns++) {
-	client = socket_table[ns]->clients;
+    down_read(&pcmcia_socket_list_rwsem);
+    list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
+	client = s->clients;
 	while (client != NULL) {
 	    if ((strcmp(client->dev_info, (char *)req->dev_info) == 0)
 		&& (client->state & CLIENT_UNBOUND)) break;
@@ -1537,10 +1563,10 @@
 	}
 	if (client != NULL) break;
     }
+    up_read(&pcmcia_socket_list_rwsem);
     if (client == NULL)
 	return CS_OUT_OF_RESOURCE;
 
-    s = socket_table[ns];
     if (++s->real_clients == 1) {
 	register_callback(s, &parse_events, s);
 	parse_events(s, SS_DETECT);
@@ -1548,7 +1574,7 @@
 
     *handle = client;
     client->state &= ~CLIENT_UNBOUND;
-    client->Socket = ns;
+    client->Socket = s;
     client->Attributes = req->Attributes;
     client->EventMask = req->EventMask;
     client->event_handler = req->event_handler;
@@ -1577,8 +1603,8 @@
 	  client, client->Socket, client->dev_info);
     if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
 	EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
-    if ((socket_table[ns]->state & SOCKET_PRESENT) &&
-	!(socket_table[ns]->state & SOCKET_SETUP_PENDING)) {
+    if ((s->state & SOCKET_PRESENT) &&
+	!(s->state & SOCKET_SETUP_PENDING)) {
 	if (client->EventMask & CS_EVENT_CARD_INSERTION)
 	    EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
 	else
@@ -1592,7 +1618,7 @@
 int pcmcia_release_configuration(client_handle_t handle)
 {
     pccard_io_map io = { 0, 0, 0, 0, 1 };
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     int i;
     
     if (CHECK_HANDLE(handle) ||
@@ -1642,7 +1668,7 @@
 
 int pcmcia_release_io(client_handle_t handle, io_req_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     
     if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
 	return CS_BAD_HANDLE;
@@ -1677,7 +1703,7 @@
 
 int pcmcia_release_irq(client_handle_t handle, irq_req_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ))
 	return CS_BAD_HANDLE;
     handle->state &= ~CLIENT_IRQ_REQ;
@@ -1713,7 +1739,7 @@
 
 int pcmcia_release_window(window_handle_t win)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     
     if ((win == NULL) || (win->magic != WINDOW_MAGIC))
 	return CS_BAD_HANDLE;
@@ -1743,13 +1769,13 @@
 {
     int i;
     u_int base;
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     config_t *c;
     pccard_io_map iomap;
     
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
-    i = handle->Socket; s = socket_table[i];
+    s = SOCKET(handle);
     if (!(s->state & SOCKET_PRESENT))
 	return CS_NO_CARD;
     
@@ -1872,7 +1898,7 @@
 
 int pcmcia_request_io(client_handle_t handle, io_req_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     config_t *c;
     
     if (CHECK_HANDLE(handle))
@@ -1936,7 +1962,7 @@
 
 int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     config_t *c;
     int ret = 0, irq = 0;
     
@@ -2011,14 +2037,14 @@
 
 int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh)
 {
-    socket_info_t *s;
+    struct pcmcia_socket *s;
     window_t *win;
     u_long align;
     int w;
     
     if (CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
-    s = SOCKET(*handle);
+    s = (*handle)->Socket;
     if (!(s->state & SOCKET_PRESENT))
 	return CS_NO_CARD;
     if (req->Attributes & (WIN_PAGED | WIN_SHARED))
@@ -2096,7 +2122,7 @@
 
 int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
 {
-	socket_info_t *skt;
+	struct pcmcia_socket *skt;
 	int ret;
     
 	if (CHECK_HANDLE(handle))
@@ -2145,7 +2171,7 @@
 
 int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
 {
-	socket_info_t *skt;
+	struct pcmcia_socket *skt;
 	int ret;
     
 	if (CHECK_HANDLE(handle))
@@ -2172,7 +2198,7 @@
 
 int pcmcia_resume_card(client_handle_t handle, client_req_t *req)
 {
-	socket_info_t *skt;
+	struct pcmcia_socket *skt;
 	int ret;
     
 	if (CHECK_HANDLE(handle))
@@ -2205,7 +2231,7 @@
 
 int pcmcia_eject_card(client_handle_t handle, client_req_t *req)
 {
-	socket_info_t *skt;
+	struct pcmcia_socket *skt;
 	int ret;
     
 	if (CHECK_HANDLE(handle))
@@ -2234,7 +2260,7 @@
 
 int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
 {
-	socket_info_t *skt;
+	struct pcmcia_socket *skt;
 	int ret;
 
 	if (CHECK_HANDLE(handle))
@@ -2519,11 +2545,6 @@
 EXPORT_SYMBOL(proc_pccard);
 #endif
 
-EXPORT_SYMBOL(pcmcia_register_socket);
-EXPORT_SYMBOL(pcmcia_unregister_socket);
-EXPORT_SYMBOL(pcmcia_suspend_socket);
-EXPORT_SYMBOL(pcmcia_resume_socket);
-
 struct class pcmcia_socket_class = {
 	.name = "pcmcia_socket",
 };
@@ -2531,8 +2552,8 @@
 
 static struct class_interface pcmcia_socket = {
 	.class = &pcmcia_socket_class,
-	.add = &pcmcia_register_socket,
-	.remove = &pcmcia_unregister_socket,
+	.add = &pcmcia_add_socket,
+	.remove = &pcmcia_remove_socket,
 };
 
 
diff -urN linux-2.5.70-bk16/drivers/pcmcia/cs_internal.h linux-2.5.70-bk17/drivers/pcmcia/cs_internal.h
--- linux-2.5.70-bk16/drivers/pcmcia/cs_internal.h	2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/cs_internal.h	2003-06-12 04:49:58.000000000 -0700
@@ -21,13 +21,6 @@
 
 #include <linux/config.h>
 
-typedef struct erase_busy_t {
-    eraseq_entry_t	*erase;
-    client_handle_t	client;
-    struct timer_list	timeout;
-    struct erase_busy_t	*prev, *next;
-} erase_busy_t;
-
 #define ERASEQ_MAGIC	0xFA67
 typedef struct eraseq_t {
     u_short		eraseq_magic;
@@ -39,7 +32,7 @@
 #define CLIENT_MAGIC 	0x51E6
 typedef struct client_t {
     u_short		client_magic;
-    socket_t		Socket;
+    struct pcmcia_socket *Socket;
     u_char		Function;
     dev_info_t		dev_info;
     u_int		Attributes;
@@ -63,23 +56,6 @@
 #define CLIENT_WIN_REQ(i)	(0x20<<(i))
 #define CLIENT_CARDBUS		0x8000
 
-typedef struct io_window_t {
-    u_int		Attributes;
-    ioaddr_t		BasePort, NumPorts;
-    ioaddr_t		InUse, Config;
-} io_window_t;
-
-#define WINDOW_MAGIC	0xB35C
-typedef struct window_t {
-    u_short		magic;
-    u_short		index;
-    client_handle_t	handle;
-    struct socket_info_t *sock;
-    u_long		base;
-    u_long		size;
-    pccard_mem_map	ctl;
-} window_t;
-
 #define REGION_MAGIC	0xE3C9
 typedef struct region_t {
     u_short		region_magic;
@@ -108,12 +84,6 @@
     } irq;
 } config_t;
 
-/* Maximum number of IO windows per socket */
-#define MAX_IO_WIN 2
-
-/* Maximum number of memory windows per socket */
-#define MAX_WIN 4
-
 struct cis_cache_entry {
 	struct list_head	node;
 	unsigned int		addr;
@@ -122,48 +92,6 @@
 	unsigned char		cache[0];
 };
 
-typedef struct socket_info_t {
-    spinlock_t			lock;
-    struct pccard_operations *	ss_entry;
-    u_int			sock;
-    socket_state_t		socket;
-    socket_cap_t		cap;
-    u_int			state;
-    u_short			functions;
-    u_short			lock_count;
-    client_handle_t		clients;
-    u_int			real_clients;
-    pccard_mem_map		cis_mem;
-    u_char			*cis_virt;
-    config_t			*config;
-#ifdef CONFIG_CARDBUS
-    struct resource *		cb_cis_res;
-    u_char			*cb_cis_virt;
-#endif
-    struct {
-	u_int			AssignedIRQ;
-	u_int			Config;
-    } irq;
-    io_window_t			io[MAX_IO_WIN];
-    window_t			win[MAX_WIN];
-    region_t			*c_region, *a_region;
-    erase_busy_t		erase_busy;
-    struct list_head		cis_cache;
-    u_int			fake_cis_len;
-    char			*fake_cis;
-#ifdef CONFIG_PROC_FS
-    struct proc_dir_entry	*proc;
-#endif
-
-    struct semaphore		skt_sem;	/* protects socket h/w state */
-
-    struct task_struct		*thread;
-    struct completion		thread_done;
-    wait_queue_head_t		thread_wait;
-    spinlock_t			thread_lock;	/* protects thread_events */
-    unsigned int		thread_events;
-} socket_info_t;
-
 /* Flags in config state */
 #define CONFIG_LOCKED		0x01
 #define CONFIG_IRQ_REQ		0x02
@@ -187,7 +115,7 @@
 #define CHECK_SOCKET(s) \
     (((s) >= sockets) || (socket_table[s]->ss_entry == NULL))
 
-#define SOCKET(h) (socket_table[(h)->Socket])
+#define SOCKET(h) (h->Socket)
 #define CONFIG(h) (&SOCKET(h)->config[(h)->Function])
 
 #define CHECK_REGION(r) \
@@ -200,19 +128,19 @@
     ((h)->event_handler((e), (p), &(h)->event_callback_args))
 
 /* In cardbus.c */
-int cb_alloc(socket_info_t *s);
-void cb_free(socket_info_t *s);
-int read_cb_mem(socket_info_t *s, int space, u_int addr, u_int len, void *ptr);
+int cb_alloc(struct pcmcia_socket *s);
+void cb_free(struct pcmcia_socket *s);
+int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr);
 
 /* In cistpl.c */
-int read_cis_mem(socket_info_t *s, int attr,
+int read_cis_mem(struct pcmcia_socket *s, int attr,
 		 u_int addr, u_int len, void *ptr);
-void write_cis_mem(socket_info_t *s, int attr,
+void write_cis_mem(struct pcmcia_socket *s, int attr,
 		   u_int addr, u_int len, void *ptr);
-void release_cis_mem(socket_info_t *s);
-void destroy_cis_cache(socket_info_t *s);
-int verify_cis_cache(socket_info_t *s);
-void preload_cis_cache(socket_info_t *s);
+void release_cis_mem(struct pcmcia_socket *s);
+void destroy_cis_cache(struct pcmcia_socket *s);
+int verify_cis_cache(struct pcmcia_socket *s);
+void preload_cis_cache(struct pcmcia_socket *s);
 int get_first_tuple(client_handle_t handle, tuple_t *tuple);
 int get_next_tuple(client_handle_t handle, tuple_t *tuple);
 int get_tuple_data(client_handle_t handle, tuple_t *tuple);
@@ -236,11 +164,11 @@
 int copy_memory(memory_handle_t handle, copy_op_t *req);
 
 /* In rsrc_mgr */
-void validate_mem(socket_info_t *s);
+void validate_mem(struct pcmcia_socket *s);
 int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
-		   char *name, socket_info_t *s);
+		   char *name, struct pcmcia_socket *s);
 int find_mem_region(u_long *base, u_long num, u_long align,
-		    int force_low, char *name, socket_info_t *s);
+		    int force_low, char *name, struct pcmcia_socket *s);
 int try_irq(u_int Attributes, int irq, int specific);
 void undo_irq(u_int Attributes, int irq);
 int adjust_resource_info(client_handle_t handle, adjust_t *adj);
@@ -250,9 +178,8 @@
 int proc_read_mem(char *buf, char **start, off_t pos,
 		  int count, int *eof, void *data);
 
-#define MAX_SOCK 8
-extern socket_t sockets;
-extern socket_info_t *socket_table[MAX_SOCK];
+extern struct rw_semaphore pcmcia_socket_list_rwsem;
+extern struct list_head pcmcia_socket_list;
 
 #ifdef CONFIG_PROC_FS
 extern struct proc_dir_entry *proc_pccard;
diff -urN linux-2.5.70-bk16/drivers/pcmcia/ds.c linux-2.5.70-bk17/drivers/pcmcia/ds.c
--- linux-2.5.70-bk16/drivers/pcmcia/ds.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/ds.c	2003-06-12 04:49:58.000000000 -0700
@@ -107,8 +107,7 @@
 	struct work_struct	removal;
 	socket_bind_t		*bind;
 	struct device		*socket_dev;
-	struct list_head	socket_list;
-	unsigned int		socket_no; /* deprecated */
+	struct pcmcia_socket	*parent;
 };
 
 #define SOCKET_PRESENT		0x01
@@ -122,10 +121,6 @@
 
 static int major_dev = -1;
 
-/* list of all sockets registered with the pcmcia bus driver */
-static DECLARE_RWSEM(bus_socket_list_rwsem);
-static LIST_HEAD(bus_socket_list);
-
 extern struct proc_dir_entry *proc_pccard;
 
 /*====================================================================*/
@@ -164,20 +159,6 @@
  */
 void pcmcia_unregister_driver(struct pcmcia_driver *driver)
 {
-	socket_bind_t *b;
-	struct pcmcia_bus_socket *bus_sock;
-
-	if (driver->use_count > 0) {
-		/* Blank out any left-over device instances */
-		driver->attach = NULL; driver->detach = NULL;
-		down_read(&bus_socket_list_rwsem);
-		list_for_each_entry(bus_sock, &bus_socket_list, socket_list) {
-			for (b = bus_sock->bind; b; b = b->next)
-				if (b->driver == driver) 
-					b->instance = NULL;
-		}
-		up_read(&bus_socket_list_rwsem);
-	}
 	driver_unregister(&driver->drv);
 }
 EXPORT_SYMBOL(pcmcia_unregister_driver);
@@ -319,14 +300,14 @@
 
     bind_req.dev_info = &mtd_info->dev_info;
     bind_req.Attributes = mtd_info->Attributes;
-    bind_req.Socket = bus_sock->socket_no;
+    bind_req.Socket = bus_sock->parent;
     bind_req.CardOffset = mtd_info->CardOffset;
     ret = pcmcia_bind_mtd(&bind_req);
     if (ret != CS_SUCCESS) {
 	cs_error(NULL, BindMTD, ret);
 	printk(KERN_NOTICE "ds: unable to bind MTD '%s' to socket %d"
 	       " offset 0x%x\n",
-	       (char *)bind_req.dev_info, bus_sock->socket_no, bind_req.CardOffset);
+	       (char *)bind_req.dev_info, bus_sock->parent->sock, bind_req.CardOffset);
 	return -ENODEV;
     }
     return 0;
@@ -351,7 +332,7 @@
     if (!s)
 	    return -EINVAL;
 
-    DEBUG(2, "bind_request(%d, '%s')\n", s->socket_no,
+    DEBUG(2, "bind_request(%d, '%s')\n", s->parent->sock,
 	  (char *)bind_info->dev_info);
     driver = get_pcmcia_driver(&bind_info->dev_info);
     if (!driver)
@@ -366,14 +347,18 @@
 	return -EBUSY;
     }
 
-    bind_req.Socket = s->socket_no;
+    if (!try_module_get(driver->owner))
+	    return -EINVAL;
+
+    bind_req.Socket = s->parent;
     bind_req.Function = bind_info->function;
     bind_req.dev_info = (dev_info_t *) driver->drv.name;
     ret = pcmcia_bind_device(&bind_req);
     if (ret != CS_SUCCESS) {
 	cs_error(NULL, BindDevice, ret);
 	printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
-	       (char *)dev_info, s->socket_no);
+	       (char *)dev_info, s->parent->sock);
+	module_put(driver->owner);
 	return -ENODEV;
     }
 
@@ -383,6 +368,7 @@
     if (!b) 
     {
     	driver->use_count--;
+	module_put(driver->owner);
 	return -ENOMEM;    
     }
     b->driver = driver;
@@ -396,6 +382,7 @@
 	if (b->instance == NULL) {
 	    printk(KERN_NOTICE "ds: unable to create instance "
 		   "of '%s'!\n", (char *)bind_info->dev_info);
+	    module_put(driver->owner);
 	    return -ENODEV;
 	}
     }
@@ -476,7 +463,7 @@
 {
     socket_bind_t **b, *c;
 
-    DEBUG(2, "unbind_request(%d, '%s')\n", s->socket_no,
+    DEBUG(2, "unbind_request(%d, '%s')\n", s->parent->sock,
 	  (char *)bind_info->dev_info);
     for (b = &s->bind; *b; b = &(*b)->next)
 	if ((strcmp((char *)(*b)->driver->drv.name,
@@ -492,9 +479,9 @@
 	if (c->instance)
 	    c->driver->detach(c->instance);
     }
+    module_put(c->driver->owner);
     *b = c->next;
     kfree(c);
-    
     return 0;
 } /* unbind_request */
 
@@ -832,13 +819,13 @@
 	.poll		= ds_poll,
 };
 
-static int __devinit pcmcia_bus_add_socket(struct device *dev, unsigned int socket_nr)
+static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
 {
+	struct pcmcia_socket *socket = class_dev->class_data;
 	client_reg_t client_reg;
 	bind_req_t bind;
-	struct pcmcia_bus_socket *s, *tmp_s;
+	struct pcmcia_bus_socket *s;
 	int ret;
-	int i;
 
 	s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL);
 	if(!s)
@@ -855,28 +842,15 @@
 	init_waitqueue_head(&s->queue);
 	init_waitqueue_head(&s->request);
 
-	/* find the lowest, unused socket no. Please note that this is a
-	 * temporary workaround until "struct pcmcia_socket" is introduced
-	 * into cs.c which will include this number, and which will be
-	 * accessible to ds.c directly */
-	i = 0;
- next_try:
-	list_for_each_entry(tmp_s, &bus_socket_list, socket_list) {
-		if (tmp_s->socket_no == i) {
-			i++;
-			goto next_try;
-		}
-	}
-	s->socket_no = i;
-
 	/* initialize data */
-	s->socket_dev = dev;
+	s->socket_dev = socket->dev.dev;
 	INIT_WORK(&s->removal, handle_removal, s);
-    
+	s->parent = socket;
+
 	/* Set up hotline to Card Services */
 	client_reg.dev_info = bind.dev_info = &dev_info;
 
-	bind.Socket = s->socket_no;
+	bind.Socket = socket;
 	bind.Function = BIND_FN_ALL;
 	ret = pcmcia_bind_device(&bind);
 	if (ret != CS_SUCCESS) {
@@ -901,50 +875,26 @@
 		return -EINVAL;
 	}
 
-	list_add(&s->socket_list, &bus_socket_list);
+	socket->pcmcia = s;
 
 	return 0;
 }
 
 
-static int pcmcia_bus_add_socket_dev(struct class_device *class_dev)
+static void pcmcia_bus_remove_socket(struct class_device *class_dev)
 {
-	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
-	unsigned int i;
-	unsigned int ret = 0;
-
-	if (!cls_d)
-		return -ENODEV;
+	struct pcmcia_socket *socket = class_dev->class_data;
 
-	down_write(&bus_socket_list_rwsem);
-        for (i = 0; i < cls_d->nsock; i++)
-		ret += pcmcia_bus_add_socket(class_dev->dev, i);
-	up_write(&bus_socket_list_rwsem);
-
-	return ret;
-}
-
-static void pcmcia_bus_remove_socket_dev(struct class_device *class_dev)
-{
-	struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev);
-	struct list_head *list_loop;
-	struct list_head *tmp_storage;
-
-	if (!cls_d)
+	if (!socket || !socket->pcmcia)
 		return;
 
 	flush_scheduled_work();
 
-	down_write(&bus_socket_list_rwsem);
-	list_for_each_safe(list_loop, tmp_storage, &bus_socket_list) {
-		struct pcmcia_bus_socket *bus_sock = container_of(list_loop, struct pcmcia_bus_socket, socket_list);
-		if (bus_sock->socket_dev == class_dev->dev) {
-			pcmcia_deregister_client(bus_sock->handle);
-			list_del(&bus_sock->socket_list);
-			kfree(bus_sock);
-		}
-	}
-	up_write(&bus_socket_list_rwsem);
+	pcmcia_deregister_client(socket->pcmcia->handle);
+
+	kfree(socket->pcmcia);
+	socket->pcmcia = NULL;
+
 	return;
 }
 
@@ -952,8 +902,8 @@
 /* the pcmcia_bus_interface is used to handle pcmcia socket devices */
 static struct class_interface pcmcia_bus_interface = {
 	.class = &pcmcia_socket_class,
-	.add = &pcmcia_bus_add_socket_dev,
-	.remove = &pcmcia_bus_remove_socket_dev,
+	.add = &pcmcia_bus_add_socket,
+	.remove = &pcmcia_bus_remove_socket,
 };
 
 
@@ -1008,18 +958,13 @@
 
 /* helpers for backwards-compatible functions */
 
-
 static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr)
 {
-	struct pcmcia_bus_socket * s;
-	down_read(&bus_socket_list_rwsem);
-	list_for_each_entry(s, &bus_socket_list, socket_list)
-		if (s->socket_no == nr) {
-			up_read(&bus_socket_list_rwsem);
-			return s;
-		}
-	up_read(&bus_socket_list_rwsem);
-	return NULL;
+	struct pcmcia_socket * s = pcmcia_get_socket_by_nr(nr);
+	if (s && s->pcmcia)
+		return s->pcmcia;
+	else
+		return NULL;
 }
 
 /* backwards-compatible accessing of driver --- by name! */
diff -urN linux-2.5.70-bk16/drivers/pcmcia/i82092.c linux-2.5.70-bk17/drivers/pcmcia/i82092.c
--- linux-2.5.70-bk16/drivers/pcmcia/i82092.c	2003-05-26 18:01:03.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/i82092.c	2003-06-12 04:49:58.000000000 -0700
@@ -44,14 +44,12 @@
 
 static int i82092aa_socket_suspend (struct pci_dev *dev, u32 state)
 {
-	struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
-	return pcmcia_socket_dev_suspend(cls_d, state, 0);
+	return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
 }
 
 static int i82092aa_socket_resume (struct pci_dev *dev)
 {
-	struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
-	return pcmcia_socket_dev_resume(cls_d, RESUME_RESTORE_STATE);
+	return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
 }
 
 static struct pci_driver i82092aa_pci_drv = {
@@ -82,6 +80,7 @@
 /* The card can do upto 4 sockets, allocate a structure for each of them */
 
 struct socket_info {
+	int	number;
 	int	card_state; 	/*  0 = no socket,
 				    1 = empty socket, 
 				    2 = card but not initialized,
@@ -95,6 +94,7 @@
 				/* callback to the driver of the card */
 	void	*info;		/* to be passed to the handler */
 	
+	struct pcmcia_socket socket;
 	struct pci_dev *dev;	/* The PCI device for the socket */
 };
 
@@ -107,7 +107,6 @@
 {
 	unsigned char configbyte;
 	int i, ret;
-	struct pcmcia_socket_class_data *cls_d;
 	
 	enter("i82092aa_pci_probe");
 	
@@ -146,6 +145,8 @@
 		sockets[i].cap.map_size = 0x1000;
 		sockets[i].cap.irq_mask = 0;
 		sockets[i].cap.pci_irq  = dev->irq;
+
+		sockets[i].number = i;
 		
 		if (card_present(i)) {
 			sockets[i].card_state = 3;
@@ -166,26 +167,26 @@
 		goto err_out_free_res;
 	}
 
-	
-	cls_d = kmalloc(sizeof(*cls_d), GFP_KERNEL);
-	if (!cls_d) {
-		printk(KERN_ERR "i82092aa: kmalloc failed\n");
-		goto err_out_free_irq;
-	}
-	memset(cls_d, 0, sizeof(*cls_d));
-	cls_d->nsock = socket_count;
-	cls_d->ops = &i82092aa_operations;
-	pci_set_drvdata(dev, &cls_d);
-	cls_d->class_dev.class = &pcmcia_socket_class;
-	cls_d->class_dev.dev = &dev->dev;
-	strlcpy(cls_d->class_dev.class_id, dev->dev.name, BUS_ID_SIZE);
-	class_set_devdata(&cls_d->class_dev, cls_d);
-	class_device_register(&cls_d->class_dev);
+	pci_set_drvdata(dev, &sockets[i].socket);
+
+	for (i = 0; i<socket_count; i++) {
+		sockets[i].socket.dev.dev = &dev->dev;
+		sockets[i].socket.ss_entry = &i82092aa_operations;
+		ret = pcmcia_register_socket(&sockets[i].socket);
+		if (ret) {
+			goto err_out_free_sockets;
+		}
+	}
 
 	leave("i82092aa_pci_probe");
 	return 0;
 
-err_out_free_irq:
+err_out_free_sockets:
+	if (i) {
+		for (i--;i>=0;i--) {
+			pcmcia_unregister_socket(&sockets[i].socket);
+		}
+	}
 	free_irq(dev->irq, i82092aa_interrupt);
 err_out_free_res:
 	release_region(pci_resource_start(dev, 0), 2);
@@ -196,16 +197,14 @@
 
 static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
 {
-	struct pcmcia_socket_class_data *cls_d = pci_get_drvdata(dev);
+	struct pcmcia_socket *socket = pci_get_drvdata(dev);
 
 	enter("i82092aa_pci_remove");
 	
 	free_irq(dev->irq, i82092aa_interrupt);
 
-	if (cls_d) {
-		class_device_unregister(&cls_d->class_dev);
-		kfree(cls_d);
-	}
+	if (socket)
+		pcmcia_unregister_socket(socket);
 
 	leave("i82092aa_pci_remove");
 }
@@ -447,7 +446,7 @@
 
 
       
-static int i82092aa_init(unsigned int s)
+static int i82092aa_init(struct pcmcia_socket *sock)
 {
 	int i;
         pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -456,21 +455,21 @@
         enter("i82092aa_init");
                         
         mem.sys_stop = 0x0fff;
-        i82092aa_set_socket(s, &dead_socket);
+        i82092aa_set_socket(sock, &dead_socket);
         for (i = 0; i < 2; i++) {
         	io.map = i;
-                i82092aa_set_io_map(s, &io);
+                i82092aa_set_io_map(sock, &io);
 	}
         for (i = 0; i < 5; i++) {
         	mem.map = i;
-                i82092aa_set_mem_map(s, &mem);
+                i82092aa_set_mem_map(sock, &mem);
 	}
 	
 	leave("i82092aa_init");
 	return 0;
 }
                                                                                                                                                                                                                                               
-static int i82092aa_suspend(unsigned int sock)
+static int i82092aa_suspend(struct pcmcia_socket *sock)
 {
 	int retval;
 	enter("i82092aa_suspend");
@@ -479,8 +478,9 @@
         return retval;
 }
        
-static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	enter("i82092aa_register_callback");
 	sockets[sock].handler = handler;
         sockets[sock].info = info;
@@ -488,8 +488,9 @@
 	return 0;
 } /* i82092aa_register_callback */
                                         
-static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int i82092aa_inquire_socket(struct pcmcia_socket *socket, socket_cap_t *cap)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	enter("i82092aa_inquire_socket");
 	*cap = sockets[sock].cap;
 	leave("i82092aa_inquire_socket");
@@ -497,8 +498,9 @@
 } /* i82092aa_inquire_socket */
 
 
-static int i82092aa_get_status(unsigned int sock, u_int *value)
+static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned int status;
 	
 	enter("i82092aa_get_status");
@@ -539,8 +541,9 @@
 }
 
 
-static int i82092aa_get_socket(unsigned int sock, socket_state_t *state) 
+static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state) 
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned char reg,vcc,vpp;
 	
 	enter("i82092aa_get_socket");
@@ -610,8 +613,9 @@
 	return 0;
 }
 
-static int i82092aa_set_socket(unsigned int sock, socket_state_t *state) 
+static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) 
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned char reg;
 	
 	enter("i82092aa_set_socket");
@@ -706,8 +710,9 @@
 	return 0;
 }
 
-static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io)
+static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned char map, ioctl;
 	
 	enter("i82092aa_set_io_map");
@@ -749,8 +754,9 @@
 	return 0;
 }
 
-static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem)
+static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem)
 {
+	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
 	unsigned short base, i;
 	unsigned char map;
 	
@@ -826,7 +832,7 @@
 	return 0;
 }
 
-static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void i82092aa_proc_setup(struct pcmcia_socket *socket, struct proc_dir_entry *base)
 {
 	
 }
diff -urN linux-2.5.70-bk16/drivers/pcmcia/i82092aa.h linux-2.5.70-bk17/drivers/pcmcia/i82092aa.h
--- linux-2.5.70-bk16/drivers/pcmcia/i82092aa.h	2003-05-26 18:00:23.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/i82092aa.h	2003-06-12 04:49:58.000000000 -0700
@@ -28,16 +28,16 @@
 
 
 
-static int i82092aa_get_status(unsigned int sock, u_int *value);
-static int i82092aa_get_socket(unsigned int sock, socket_state_t *state);
-static int i82092aa_set_socket(unsigned int sock, socket_state_t *state);
-static int i82092aa_set_io_map(unsigned int sock, struct pccard_io_map *io);
-static int i82092aa_set_mem_map(unsigned int sock, struct pccard_mem_map *mem);
-static int i82092aa_init(unsigned int s);
-static int i82092aa_suspend(unsigned int sock);
-static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info);
-static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap);
-static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base);
+static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value);
+static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state);
+static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state);
+static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io);
+static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem);
+static int i82092aa_init(struct pcmcia_socket *socket);
+static int i82092aa_suspend(struct pcmcia_socket *socket);
+static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info);
+static int i82092aa_inquire_socket(struct pcmcia_socket *socket, socket_cap_t *cap);
+static void i82092aa_proc_setup(struct pcmcia_socket *socket, struct proc_dir_entry *base);
 
 #endif
 
diff -urN linux-2.5.70-bk16/drivers/pcmcia/i82365.c linux-2.5.70-bk17/drivers/pcmcia/i82365.c
--- linux-2.5.70-bk16/drivers/pcmcia/i82365.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/i82365.c	2003-06-12 04:49:58.000000000 -0700
@@ -91,7 +91,6 @@
 
 /* Parameters that can be set with 'insmod' */
 
-#ifdef CONFIG_ISA
 /* Default base address for i82365sl and other ISA chips */
 static int i365_base = 0x3e0;
 /* Should we probe at 0x3e2 for an extra ISA controller? */
@@ -103,7 +102,6 @@
 static int irq_list[16] = { -1 };
 /* The card status change interrupt -- 0 means autoselect */
 static int cs_irq = 0;
-#endif
 
 /* Probe for safe interrupts? */
 static int do_scan = 1;
@@ -122,14 +120,11 @@
 static int cmd_time = -1;
 static int recov_time = -1;
 
-#ifdef CONFIG_ISA
 /* Vadem options */
 static int async_clock = -1;
 static int cable_mode = -1;
 static int wakeup = 0;
-#endif
 
-#ifdef CONFIG_ISA
 MODULE_PARM(i365_base, "i");
 MODULE_PARM(ignore, "i");
 MODULE_PARM(extra_sockets, "i");
@@ -139,7 +134,6 @@
 MODULE_PARM(async_clock, "i");
 MODULE_PARM(cable_mode, "i");
 MODULE_PARM(wakeup, "i");
-#endif
 
 MODULE_PARM(do_scan, "i");
 MODULE_PARM(poll_interval, "i");
@@ -164,8 +158,10 @@
     u_char		ctl, ema;
 } vg46x_state_t;
 
-typedef struct socket_info_t {
+struct i82365_socket {
     u_short		type, flags;
+    struct pcmcia_socket	socket;
+    unsigned int	number;
     socket_cap_t	cap;
     ioaddr_t		ioaddr;
     u_short		psock;
@@ -179,26 +175,21 @@
 	cirrus_state_t		cirrus;
 	vg46x_state_t		vg46x;
     } state;
-} socket_info_t;
+};
 
 /* Where we keep track of our sockets... */
 static int sockets = 0;
-static socket_info_t socket[8] = {
+static struct i82365_socket socket[8] = {
     { 0, }, /* ... */
 };
 
 /* Default ISA interrupt mask */
 #define I365_MASK	0xdeb8	/* irq 15,14,12,11,10,9,7,5,4,3 */
 
-#ifdef CONFIG_ISA
 static int grab_irq;
 static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
 #define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f)
 #define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f)
-#else
-#define ISA_LOCK(n, f) do { } while (0)
-#define ISA_UNLOCK(n, f) do { } while (0)
-#endif
 
 static struct timer_list poll_timer;
 
@@ -209,13 +200,11 @@
 		  PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
 
 /* These definitions must match the pcic table! */
-#ifdef CONFIG_ISA
 typedef enum pcic_id {
     IS_I82365A, IS_I82365B, IS_I82365DF,
     IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
     IS_PD6710, IS_PD672X, IS_VT83C469,
 } pcic_id;
-#endif
 
 /* Flags for classifying groups of controllers */
 #define IS_VADEM	0x0001
@@ -237,7 +226,6 @@
 } pcic_t;
 
 static pcic_t pcic[] = {
-#ifdef CONFIG_ISA
     { "Intel i82365sl A step", 0 },
     { "Intel i82365sl B step", 0 },
     { "Intel i82365sl DF", IS_DF_PWR },
@@ -249,7 +237,6 @@
     { "Cirrus PD6710", IS_CIRRUS },
     { "Cirrus PD672x", IS_CIRRUS },
     { "VIA VT83C469", IS_CIRRUS|IS_VIA },
-#endif
 };
 
 #define PCIC_COUNT	(sizeof(pcic)/sizeof(pcic_t))
@@ -364,7 +351,7 @@
 
 static u_int __init cirrus_set_opts(u_short s, char *buf)
 {
-    socket_info_t *t = &socket[s];
+    struct i82365_socket *t = &socket[s];
     cirrus_state_t *p = &socket[s].state.cirrus;
     u_int mask = 0xffff;
 
@@ -421,8 +408,6 @@
     
 ======================================================================*/
 
-#ifdef CONFIG_ISA
-
 static void vg46x_get_state(u_short s)
 {
     vg46x_state_t *p = &socket[s].state.vg46x;
@@ -464,9 +449,6 @@
     return 0xffff;
 }
 
-#endif
-
-
 /*======================================================================
 
     Generic routines to get and set controller options
@@ -475,18 +457,16 @@
 
 static void get_bridge_state(u_short s)
 {
-    socket_info_t *t = &socket[s];
+    struct i82365_socket *t = &socket[s];
     if (t->flags & IS_CIRRUS)
 	cirrus_get_state(s);
-#ifdef CONFIG_ISA
     else if (t->flags & IS_VADEM)
 	vg46x_get_state(s);
-#endif
 }
 
 static void set_bridge_state(u_short s)
 {
-    socket_info_t *t = &socket[s];
+    struct i82365_socket *t = &socket[s];
     if (t->flags & IS_CIRRUS)
 	cirrus_set_state(s);
     else {
@@ -494,10 +474,8 @@
 	i365_set(s, I365_GENCTL, 0x00);
     }
     i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr);
-#ifdef CONFIG_ISA
     if (t->flags & IS_VADEM)
 	vg46x_set_state(s);
-#endif
 }
 
 static u_int __init set_bridge_opts(u_short s, u_short ns)
@@ -515,10 +493,8 @@
 	get_bridge_state(i);
 	if (socket[i].flags & IS_CIRRUS)
 	    m = cirrus_set_opts(i, buf);
-#ifdef CONFIG_ISA
 	else if (socket[i].flags & IS_VADEM)
 	    m = vg46x_set_opts(i, buf);
-#endif
 	set_bridge_state(i);
 	printk(KERN_INFO "    host opts [%d]:%s\n", i,
 	       (*buf) ? buf : " none");
@@ -571,7 +547,6 @@
     return (irq_hits != 1);
 }
 
-#ifdef CONFIG_ISA
 
 static u_int __init isa_scan(u_short sock, u_int mask0)
 {
@@ -617,7 +592,6 @@
     return mask1;
 }
 
-#endif /* CONFIG_ISA */
 
 /*====================================================================*/
 
@@ -630,7 +604,6 @@
 
 /*====================================================================*/
 
-#ifdef CONFIG_ISA
 
 static int __init identify(u_short port, u_short sock)
 {
@@ -691,8 +664,6 @@
     return type;
 } /* identify */
 
-#endif
-
 /*======================================================================
 
     See if a card is present, powered up, in IO mode, and already
@@ -737,7 +708,7 @@
 {
     u_int mask = 0, i, base;
     int use_pci = 0, isa_irq = 0;
-    socket_info_t *t = &socket[sockets-ns];
+    struct i82365_socket *t = &socket[sockets-ns];
 
     base = sockets-ns;
     if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
@@ -748,23 +719,17 @@
 	       t->ioaddr, t->psock*0x40);
     printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
 
-#ifdef CONFIG_ISA
     /* Set host options, build basic interrupt mask */
     if (irq_list[0] == -1)
 	mask = irq_mask;
     else
 	for (i = mask = 0; i < 16; i++)
 	    mask |= (1<<irq_list[i]);
-#endif
     mask &= I365_MASK & set_bridge_opts(base, ns);
-#ifdef CONFIG_ISA
     /* Scan for ISA interrupts */
     mask = isa_scan(base, mask);
-#else
     printk(KERN_INFO "    PCI card interrupts,");
-#endif
         
-#ifdef CONFIG_ISA
     /* Poll if only two interrupts available */
     if (!use_pci && !poll_interval) {
 	u_int tmp = (mask & 0xff20);
@@ -786,7 +751,6 @@
 	    printk(" status change on irq %d\n", cs_irq);
 	}
     }
-#endif
     
     if (!use_pci && !isa_irq) {
 	if (poll_interval == 0)
@@ -809,7 +773,6 @@
 
 /*====================================================================*/
 
-#ifdef CONFIG_ISA
 
 #ifdef CONFIG_PNP
 static struct isapnp_device_id id_table[] __initdata = {
@@ -902,7 +865,6 @@
     }
 }
 
-#endif
 
 /*====================================================================*/
 
@@ -940,9 +902,7 @@
 {
     int i, j, csc;
     u_int events, active;
-#ifdef CONFIG_ISA
     u_long flags = 0;
-#endif
     int handled = 0;
 
     DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
@@ -1013,8 +973,9 @@
 
 /*====================================================================*/
 
-static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+static int pcic_register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info)
 {
+    unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
     socket[sock].handler = handler;
     socket[sock].info = info;
     return 0;
@@ -1022,8 +983,9 @@
 
 /*====================================================================*/
 
-static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int pcic_inquire_socket(struct pcmcia_socket *s, socket_cap_t *cap)
 {
+    unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
     *cap = socket[sock].cap;
     return 0;
 } /* pcic_inquire_socket */
@@ -1048,7 +1010,6 @@
     *value |= (status & I365_CS_READY) ? SS_READY : 0;
     *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
 
-#ifdef CONFIG_ISA
     if (socket[sock].type == IS_VG469) {
 	status = i365_get(sock, VG469_VSENSE);
 	if (socket[sock].psock & 1) {
@@ -1059,7 +1020,6 @@
 	    *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
 	}
     }
-#endif
     
     DEBUG(1, "i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
     return 0;
@@ -1069,7 +1029,7 @@
 
 static int i365_get_socket(u_short sock, socket_state_t *state)
 {
-    socket_info_t *t = &socket[sock];
+    struct i82365_socket *t = &socket[sock];
     u_char reg, vcc, vpp;
     
     reg = i365_get(sock, I365_POWER);
@@ -1141,7 +1101,7 @@
 
 static int i365_set_socket(u_short sock, socket_state_t *state)
 {
-    socket_info_t *t = &socket[sock];
+    struct i82365_socket *t = &socket[sock];
     u_char reg;
     
     DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
@@ -1337,7 +1297,7 @@
 static int proc_read_info(char *buf, char **start, off_t pos,
 			  int count, int *eof, void *data)
 {
-    socket_info_t *s = data;
+    struct i82365_socket *s = data;
     char *p = buf;
     p += sprintf(p, "type:     %s\npsock:    %d\n",
 		 pcic[s->type].name, s->psock);
@@ -1347,13 +1307,11 @@
 static int proc_read_exca(char *buf, char **start, off_t pos,
 			  int count, int *eof, void *data)
 {
-    u_short sock = (socket_info_t *)data - socket;
+    u_short sock = (struct i82365_socket *)data - socket;
     char *p = buf;
     int i, top;
     
-#ifdef CONFIG_ISA
     u_long flags = 0;
-#endif
     ISA_LOCK(sock, flags);
     top = 0x40;
     for (i = 0; i < top; i += 4) {
@@ -1370,9 +1328,9 @@
     return (p - buf);
 }
 
-static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void pcic_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
 {
-    socket_info_t *s = &socket[sock];
+    struct i82365_socket *s = container_of(sock, struct i82365_socket, socket);
 
     if (s->flags & IS_ALIVE)
     	return;
@@ -1398,15 +1356,8 @@
 
 /*====================================================================*/
 
-/*
- * The locking is rather broken. Why do we only lock for ISA, not for
- * all other cases? If there are reasons to lock, we should lock. Not
- * this silly conditional.
- *
- * Plan: make it bug-for-bug compatible with the old stuff, and clean
- * it up when the infrastructure is done.
- */
-#ifdef CONFIG_ISA
+/* this is horribly ugly... proper locking needs to be done here at 
+ * some time... */
 #define LOCKED(x) do { \
 	int retval; \
 	unsigned long flags; \
@@ -1415,13 +1366,12 @@
 	spin_unlock_irqrestore(&isa_lock, flags); \
 	return retval; \
 } while (0)
-#else
-#define LOCKED(x) return x
-#endif
 	
 
-static int pcic_get_status(unsigned int sock, u_int *value)
+static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
 {
+	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
+
 	if (socket[sock].flags & IS_ALIVE) {
 		*value = 0;
 		return -EINVAL;
@@ -1430,39 +1380,45 @@
 	LOCKED(i365_get_status(sock, value));
 }
 
-static int pcic_get_socket(unsigned int sock, socket_state_t *state)
+static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
+	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
+
 	if (socket[sock].flags & IS_ALIVE)
 		return -EINVAL;
 
 	LOCKED(i365_get_socket(sock, state));
 }
 
-static int pcic_set_socket(unsigned int sock, socket_state_t *state)
+static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
+	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
+
 	if (socket[sock].flags & IS_ALIVE)
 		return -EINVAL;
 
 	LOCKED(i365_set_socket(sock, state));
 }
 
-static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io)
+static int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
 {
+	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
 	if (socket[sock].flags & IS_ALIVE)
 		return -EINVAL;
 
 	LOCKED(i365_set_io_map(sock, io));
 }
 
-static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
 {
+	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
 	if (socket[sock].flags & IS_ALIVE)
 		return -EINVAL;
 
 	LOCKED(i365_set_mem_map(sock, mem));
 }
 
-static int pcic_init(unsigned int s)
+static int pcic_init(struct pcmcia_socket *s)
 {
 	int i;
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -1481,7 +1437,7 @@
 	return 0;
 }
 
-static int pcic_suspend(unsigned int sock)
+static int pcic_suspend(struct pcmcia_socket *sock)
 {
 	return pcic_set_socket(sock, &dead_socket);
 }
@@ -1502,15 +1458,11 @@
 
 /*====================================================================*/
 
-static struct pcmcia_socket_class_data i82365_data = {
-	.ops = &pcic_operations,
-};
-
 static struct device_driver i82365_driver = {
 	.name = "i82365",
 	.bus = &platform_bus_type,
-/*	.suspend = pcmcia_socket_dev_suspend,	FIXME?	*/
-/*	.resume = pcmcia_socket_dev_resume,	FIXME?	*/
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device i82365_device = {
@@ -1521,13 +1473,11 @@
 	},
 };
 
-static struct class_device i82365_class_data = {
-	.class = &pcmcia_socket_class,
-};
-
 static int __init init_i82365(void)
 {
     servinfo_t serv;
+    int i, ret;
+
     pcmcia_get_card_services_info(&serv);
     if (serv.Revision != CS_RELEASE_CODE) {
 	printk(KERN_NOTICE "i82365: Card Services release "
@@ -1541,9 +1491,7 @@
     printk(KERN_INFO "Intel PCIC probe: ");
     sockets = 0;
 
-#ifdef CONFIG_ISA
     isa_probe();
-#endif
 
     if (sockets == 0) {
 	printk("not found.\n");
@@ -1551,19 +1499,24 @@
 	return -ENODEV;
     }
 
+    platform_device_register(&i82365_device);
+
     /* Set up interrupt handler(s) */
-#ifdef CONFIG_ISA
     if (grab_irq != 0)
 	request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
-#endif
     
-    i82365_data.nsock = sockets;
-    i82365_class_data.dev = &i82365_device.dev;
-    i82365_class_data.class_data = &i82365_data;
-    strlcpy(i82365_class_data.class_id, "i82365", BUS_ID_SIZE);
-    
-    platform_device_register(&i82365_device);
-    class_device_register(&i82365_class_data);
+    /* register sockets with the pcmcia core */
+    for (i = 0; i < sockets; i++) {
+	    socket[i].socket.dev.dev = &i82365_device.dev;
+	    socket[i].socket.ss_entry = &pcic_operations;
+	    socket[i].number = i;
+	    ret = pcmcia_register_socket(&socket[i].socket);	    
+	    if (ret && i--) {
+		    for (; i>= 0; i--)
+			    pcmcia_unregister_socket(&socket[i].socket);
+		    break;
+	    }
+    }
 
     /* Finally, schedule a polling interrupt */
     if (poll_interval != 0) {
@@ -1581,23 +1534,23 @@
 static void __exit exit_i82365(void)
 {
     int i;
+    for (i = 0; i < sockets; i++) {
+	    pcmcia_unregister_socket(&socket[i].socket);
 #ifdef CONFIG_PROC_FS
-    for (i = 0; i < sockets; i++) pcic_proc_remove(i);
+	    pcic_proc_remove(i);
 #endif
-    class_device_unregister(&i82365_class_data);
+    }
     platform_device_unregister(&i82365_device);
     if (poll_interval != 0)
 	del_timer_sync(&poll_timer);
-#ifdef CONFIG_ISA
     if (grab_irq != 0)
 	free_irq(cs_irq, pcic_interrupt);
-#endif
     for (i = 0; i < sockets; i++) {
 	/* Turn off all interrupt sources! */
 	i365_set(i, I365_CSCINT, 0);
 	release_region(socket[i].ioaddr, 2);
     }
-#if defined(CONFIG_ISA) && defined(__ISAPNP__)
+#ifdef __ISAPNP__
     if (i82365_pnpdev)
     		pnp_disable_dev(i82365_pnpdev);
 #endif
diff -urN linux-2.5.70-bk16/drivers/pcmcia/pci_socket.c linux-2.5.70-bk17/drivers/pcmcia/pci_socket.c
--- linux-2.5.70-bk16/drivers/pcmcia/pci_socket.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/pci_socket.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,250 +0,0 @@
-/*
- * Generic PCI pccard driver interface.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * This implements the common parts of PCI pccard drivers,
- * notably detection and infrastructure conversion (ie change
- * from socket index to "struct pci_dev" etc)
- *
- * This does NOT implement the actual low-level driver details,
- * and this has on purpose been left generic enough that it can
- * be used to set up a PCI PCMCIA controller (ie non-cardbus),
- * or to set up a controller.
- *
- * See for example the "yenta" driver for PCI cardbus controllers
- * conforming to the yenta cardbus specifications.
- */
-#include <linux/module.h>
-
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-
-#include <pcmcia/ss.h>
-
-#include <asm/io.h>
-
-#include "pci_socket.h"
-
-
-/*
- * Arbitrary define. This is the array of active cardbus
- * entries.
- */
-#define MAX_SOCKETS (8)
-static pci_socket_t pci_socket_array[MAX_SOCKETS];
-
-static int pci_init_socket(unsigned int sock)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	if (socket->op && socket->op->init)
-		return socket->op->init(socket);
-	return -EINVAL;
-}
-
-static int pci_suspend_socket(unsigned int sock)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	if (socket->op && socket->op->suspend)
-		return socket->op->suspend(socket);
-	return -EINVAL;
-}
-
-static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	socket->handler = handler;
-	socket->info = info;
-	return 0;
-}
-
-static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	*cap = socket->cap;
-	return 0;
-}
-
-static int pci_get_status(unsigned int sock, unsigned int *value)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	if (socket->op && socket->op->get_status)
-		return socket->op->get_status(socket, value);
-	*value = 0;
-	return -EINVAL;
-}
-
-static int pci_get_socket(unsigned int sock, socket_state_t *state)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	if (socket->op && socket->op->get_socket)
-		return socket->op->get_socket(socket, state);
-	return -EINVAL;
-}
-
-static int pci_set_socket(unsigned int sock, socket_state_t *state)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	if (socket->op && socket->op->set_socket)
-		return socket->op->set_socket(socket, state);
-	return -EINVAL;
-}
-
-static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	if (socket->op && socket->op->set_io_map)
-		return socket->op->set_io_map(socket, io);
-	return -EINVAL;
-}
-
-static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	if (socket->op && socket->op->set_mem_map)
-		return socket->op->set_mem_map(socket, mem);
-	return -EINVAL;
-}
-
-static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
-{
-	pci_socket_t *socket = pci_socket_array + sock;
-
-	if (socket->op && socket->op->proc_setup)
-		socket->op->proc_setup(socket, base);
-}
-
-static struct pccard_operations pci_socket_operations = {
-	.owner			= THIS_MODULE,
-	.init			= pci_init_socket,
-	.suspend		= pci_suspend_socket,
-	.register_callback	= pci_register_callback,
-	.inquire_socket		= pci_inquire_socket,
-	.get_status		= pci_get_status,
-	.get_socket		= pci_get_socket,
-	.set_socket		= pci_set_socket,
-	.set_io_map		= pci_set_io_map,
-	.set_mem_map		= pci_set_mem_map,
-	.proc_setup		= pci_proc_setup,
-};
-
-static int __devinit add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
-{
-	pci_socket_t *socket = nr + pci_socket_array;
-	int err;
-	
-	memset(socket, 0, sizeof(*socket));
-
-	/* prepare class_data */
-	socket->cls_d.sock_offset = nr;
-	socket->cls_d.nsock = 1; /* yenta is 1, no other low-level driver uses
-			     this yet */
-	socket->cls_d.ops = &pci_socket_operations;
-	socket->cls_d.class_dev.class = &pcmcia_socket_class;
-	socket->cls_d.class_dev.dev = &dev->dev;
-	strlcpy(socket->cls_d.class_dev.class_id, dev->dev.bus_id, BUS_ID_SIZE);
-	class_set_devdata(&socket->cls_d.class_dev, &socket->cls_d);
-
-	/* prepare pci_socket_t */
-	socket->dev = dev;
-	socket->op = ops;
-	pci_set_drvdata(dev, socket);
-	spin_lock_init(&socket->event_lock);
-	err = socket->op->open(socket);
-	if (err) {
-		socket->dev = NULL;
-		pci_set_drvdata(dev, NULL);
-	} else {
-		class_device_register(&socket->cls_d.class_dev);
-	}
-	return err;
-}
-
-int cardbus_register(struct pci_dev *p_dev)
-{
-	return 0;
-}
-
-static int __devinit
-cardbus_probe (struct pci_dev *dev, const struct pci_device_id *id)
-{
-	int	s;
-
-	for (s = 0; s < MAX_SOCKETS; s++) {
-		if (pci_socket_array [s].dev == 0) {
-			return add_pci_socket (s, dev, &yenta_operations);
-		}
-	}
-	return -ENODEV;
-}
-
-static void __devexit cardbus_remove (struct pci_dev *dev)
-{
-	pci_socket_t *socket = pci_get_drvdata(dev);
-
-	/* note: we are already unregistered from the cs core */
-	class_device_unregister(&socket->cls_d.class_dev);
-	if (socket->op && socket->op->close)
-		socket->op->close(socket);
-	pci_set_drvdata(dev, NULL);
-}
-
-static int cardbus_suspend (struct pci_dev *dev, u32 state)
-{
-	pci_socket_t *socket = pci_get_drvdata(dev);
-	return pcmcia_socket_dev_suspend(&socket->cls_d, state, 0);
-}
-
-static int cardbus_resume (struct pci_dev *dev)
-{
-	pci_socket_t *socket = pci_get_drvdata(dev);
-	return pcmcia_socket_dev_resume(&socket->cls_d, RESUME_RESTORE_STATE);
-}
-
-
-static struct pci_device_id cardbus_table [] __devinitdata = { {
-	.class		= PCI_CLASS_BRIDGE_CARDBUS << 8,
-	.class_mask	= ~0,
-
-	.vendor		= PCI_ANY_ID,
-	.device		= PCI_ANY_ID,
-	.subvendor	= PCI_ANY_ID,
-	.subdevice	= PCI_ANY_ID,
-}, { /* all zeroes */ }
-};
-MODULE_DEVICE_TABLE(pci, cardbus_table);
-
-static struct pci_driver pci_cardbus_driver = {
-	.name		= "cardbus",
-	.id_table	= cardbus_table,
-	.probe		= cardbus_probe,
-	.remove		= __devexit_p(cardbus_remove),
-	.suspend	= cardbus_suspend,
-	.resume		= cardbus_resume,
-};
-
-static int __init pci_socket_init(void)
-{
-	return pci_register_driver (&pci_cardbus_driver);
-}
-
-static void __exit pci_socket_exit (void)
-{
-	pci_unregister_driver (&pci_cardbus_driver);
-}
-
-module_init(pci_socket_init);
-module_exit(pci_socket_exit);
diff -urN linux-2.5.70-bk16/drivers/pcmcia/pci_socket.h linux-2.5.70-bk17/drivers/pcmcia/pci_socket.h
--- linux-2.5.70-bk16/drivers/pcmcia/pci_socket.h	2003-05-26 18:00:25.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/pci_socket.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,48 +0,0 @@
-/*
- * drivers/pcmcia/pci_socket.h
- *
- * (C) Copyright 1999 Linus Torvalds
- */
-
-#ifndef __PCI_SOCKET_H
-#define __PCI_SOCKET_H
-
-struct pci_socket_ops;
-struct socket_info_t;
-
-typedef struct pci_socket {
-	struct pci_dev *dev;
-	int cb_irq, io_irq;
-	void *base;
-	void (*handler)(void *, unsigned int);
-	void *info;
-	struct pci_socket_ops *op;
-	socket_cap_t cap;
-	spinlock_t event_lock;
-	unsigned int events;
-	struct work_struct tq_task;
-	struct timer_list poll_timer;
-
-	struct pcmcia_socket_class_data cls_d;
-	/* A few words of private data for the low-level driver.. */
-	unsigned int private[8];
-} pci_socket_t;
-
-struct pci_socket_ops {
-	int (*open)(struct pci_socket *);
-	void (*close)(struct pci_socket *);
-
-	int (*init)(struct pci_socket *);
-	int (*suspend)(struct pci_socket *);
-	int (*get_status)(struct pci_socket *, unsigned int *);
-	int (*get_socket)(struct pci_socket *, socket_state_t *);
-	int (*set_socket)(struct pci_socket *, socket_state_t *);
-	int (*set_io_map)(struct pci_socket *, struct pccard_io_map *);
-	int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *);
-	void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base);
-};
-
-extern struct pci_socket_ops yenta_operations;
-extern struct pci_socket_ops ricoh_operations;
-
-#endif
diff -urN linux-2.5.70-bk16/drivers/pcmcia/ricoh.h linux-2.5.70-bk17/drivers/pcmcia/ricoh.h
--- linux-2.5.70-bk16/drivers/pcmcia/ricoh.h	2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/ricoh.h	2003-06-12 04:49:58.000000000 -0700
@@ -125,11 +125,26 @@
 #define rl_mem(socket)		((socket)->private[3])
 #define rl_config(socket)	((socket)->private[4])
 
+static int ricoh_init(struct pcmcia_socket *sock)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	yenta_init(sock);
+
+	config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
+	config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
+	config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
+	config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
+	config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
+	
+	return 0;
+}
+
+
 /*
  * Magic Ricoh initialization code.. Save state at
  * beginning, re-initialize it after suspend.
  */
-static int ricoh_open(pci_socket_t *socket)
+static int ricoh_override(struct yenta_socket *socket)
 {
 	rl_misc(socket) = config_readw(socket, RL5C4XX_MISC);
 	rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL);
@@ -146,35 +161,11 @@
 		rl_config(socket) |= RL5C4XX_CONFIG_PREFETCH;
 	}
 
-	return 0;
-}
-
-static int ricoh_init(pci_socket_t *socket)
-{
-	yenta_init(socket);
+	socket->socket.ss_entry->init = ricoh_init;
 
-	config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
-	config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
-	config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
-	config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
-	config_writew(socket, RL5C4XX_CONFIG, rl_config(socket));
-	
 	return 0;
 }
 
-static struct pci_socket_ops ricoh_ops = {
-	ricoh_open,
-	yenta_close,
-	ricoh_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
-};
-
 #endif /* CONFIG_CARDBUS */
 
 #endif /* _LINUX_RICOH_H */
diff -urN linux-2.5.70-bk16/drivers/pcmcia/rsrc_mgr.c linux-2.5.70-bk17/drivers/pcmcia/rsrc_mgr.c
--- linux-2.5.70-bk16/drivers/pcmcia/rsrc_mgr.c	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/rsrc_mgr.c	2003-06-12 04:49:58.000000000 -0700
@@ -90,7 +90,7 @@
 typedef struct irq_info_t {
     u_int			Attributes;
     int				time_share, dyn_share;
-    struct socket_info_t	*Socket;
+    struct pcmcia_socket	*Socket;
 } irq_info_t;
 
 /* Table of IRQ assignments */
@@ -341,7 +341,7 @@
 ======================================================================*/
 
 /* Validation function for cards with a valid CIS */
-static int cis_readable(socket_info_t *s, u_long base)
+static int cis_readable(struct pcmcia_socket *s, u_long base)
 {
     cisinfo_t info1, info2;
     int ret;
@@ -364,7 +364,7 @@
 }
 
 /* Validation function for simple memory cards */
-static int checksum(socket_info_t *s, u_long base)
+static int checksum(struct pcmcia_socket *s, u_long base)
 {
     int i, a, b, d;
     s->cis_mem.sys_start = base;
@@ -372,7 +372,7 @@
     s->cis_virt = ioremap(base, s->cap.map_size);
     s->cis_mem.card_start = 0;
     s->cis_mem.flags = MAP_ACTIVE;
-    s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
+    s->ss_entry->set_mem_map(s, &s->cis_mem);
     /* Don't bother checking every word... */
     a = 0; b = -1;
     for (i = 0; i < s->cap.map_size; i += 44) {
@@ -383,7 +383,7 @@
     return (b == -1) ? -1 : (a>>1);
 }
 
-static int checksum_match(socket_info_t *s, u_long base)
+static int checksum_match(struct pcmcia_socket *s, u_long base)
 {
     int a = checksum(s, base), b = checksum(s, base+s->cap.map_size);
     return ((a == b) && (a >= 0));
@@ -397,7 +397,7 @@
     
 ======================================================================*/
 
-static int do_mem_probe(u_long base, u_long num, socket_info_t *s)
+static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
 {
     u_long i, j, bad, fail, step;
 
@@ -435,7 +435,7 @@
 
 #ifdef CONFIG_PCMCIA_PROBE
 
-static u_long inv_probe(resource_map_t *m, socket_info_t *s)
+static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
 {
     u_long ok;
     if (m == &mem_db)
@@ -451,7 +451,7 @@
     return do_mem_probe(m->base, m->num, s);
 }
 
-void validate_mem(socket_info_t *s)
+void validate_mem(struct pcmcia_socket *s)
 {
     resource_map_t *m, *n;
     static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
@@ -497,7 +497,7 @@
 
 #else /* CONFIG_PCMCIA_PROBE */
 
-void validate_mem(socket_info_t *s)
+void validate_mem(struct pcmcia_socket *s)
 {
     resource_map_t *m, *n;
     static int done = 0;
@@ -529,7 +529,7 @@
 ======================================================================*/
 
 int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
-		   char *name, socket_info_t *s)
+		   char *name, struct pcmcia_socket *s)
 {
     ioaddr_t try;
     resource_map_t *m;
@@ -556,7 +556,7 @@
 }
 
 int find_mem_region(u_long *base, u_long num, u_long align,
-		    int force_low, char *name, socket_info_t *s)
+		    int force_low, char *name, struct pcmcia_socket *s)
 {
     u_long try;
     resource_map_t *m;
@@ -726,7 +726,7 @@
 static int adjust_memory(adjust_t *adj)
 {
     u_long base, num;
-    int i, ret;
+    int ret;
 
     base = adj->resource.memory.Base;
     num = adj->resource.memory.Size;
@@ -743,9 +743,11 @@
     case REMOVE_MANAGED_RESOURCE:
 	ret = sub_interval(&mem_db, base, num);
 	if (ret == CS_SUCCESS) {
-	    for (i = 0; i < sockets; i++) {
-		release_cis_mem(socket_table[i]);
-	    }
+		struct pcmcia_socket *socket;
+		down_read(&pcmcia_socket_list_rwsem);
+		list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
+			release_cis_mem(socket);
+		up_read(&pcmcia_socket_list_rwsem);
 	}
 	break;
     default:
diff -urN linux-2.5.70-bk16/drivers/pcmcia/sa1100_generic.c linux-2.5.70-bk17/drivers/pcmcia/sa1100_generic.c
--- linux-2.5.70-bk16/drivers/pcmcia/sa1100_generic.c	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/sa1100_generic.c	2003-06-12 04:49:58.000000000 -0700
@@ -106,19 +106,10 @@
 	.remove		= sa11xx_drv_pcmcia_remove,
 	.name		= "sa11x0-pcmcia",
 	.bus		= &platform_bus_type,
-	.devclass	= &pcmcia_socket_class,
 	.suspend 	= pcmcia_socket_dev_suspend,
 	.resume 	= pcmcia_socket_dev_resume,
 };
 
-static struct platform_device sa11x0_pcmcia_device = {
-	.name		= "sa11x0-pcmcia",
-	.id		= 0,
-	.dev		= {
-		.name	= "Intel Corporation SA11x0 [PCMCIA]",
-	},
-};
-
 /* sa11x0_pcmcia_init()
  * ^^^^^^^^^^^^^^^^^^^^
  *
@@ -129,16 +120,7 @@
  */
 static int __init sa11x0_pcmcia_init(void)
 {
-	int ret;
-
-	ret = driver_register(&sa11x0_pcmcia_driver);
-	if (ret == 0) {
-		ret = platform_device_register(&sa11x0_pcmcia_device);
-		if (ret)
-			driver_unregister(&sa11x0_pcmcia_driver);
-	}
-
-	return ret;
+	return driver_register(&sa11x0_pcmcia_driver);
 }
 
 /* sa11x0_pcmcia_exit()
@@ -148,7 +130,6 @@
  */
 static void __exit sa11x0_pcmcia_exit(void)
 {
-	platform_device_unregister(&sa11x0_pcmcia_device);
 	driver_unregister(&sa11x0_pcmcia_driver);
 }
 
diff -urN linux-2.5.70-bk16/drivers/pcmcia/sa11xx_core.c linux-2.5.70-bk17/drivers/pcmcia/sa11xx_core.c
--- linux-2.5.70-bk16/drivers/pcmcia/sa11xx_core.c	2003-05-26 18:00:25.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/sa11xx_core.c	2003-06-12 04:49:58.000000000 -0700
@@ -69,6 +69,8 @@
 
 #define PCMCIA_SOCKET(x)	(sa1100_pcmcia_socket + (x))
 
+#define to_sa1100_socket(x)	container_of(x, struct sa1100_pcmcia_socket, socket)
+
 /*
  * sa1100_pcmcia_default_mecr_timing
  * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -226,9 +228,9 @@
  *
  * Returns: 0
  */
-static int sa1100_pcmcia_sock_init(unsigned int sock)
+static int sa1100_pcmcia_sock_init(struct pcmcia_socket *sock)
 {
-	struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 
 	DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, skt->nr);
 
@@ -248,9 +250,9 @@
  *
  * Returns: 0
  */
-static int sa1100_pcmcia_suspend(unsigned int sock)
+static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock)
 {
-	struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 	int ret;
 
 	DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, skt->nr);
@@ -348,11 +350,11 @@
  * Returns: 0
  */
 static int
-sa1100_pcmcia_register_callback(unsigned int sock,
+sa1100_pcmcia_register_callback(struct pcmcia_socket *sock,
 				void (*handler)(void *, unsigned int),
 				void *info)
 {
-	struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 
 	if (handler) {
 		if (!try_module_get(skt->ops->owner))
@@ -392,9 +394,9 @@
  * Return value is irrelevant; the pcmcia subsystem ignores it.
  */
 static int
-sa1100_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap)
+sa1100_pcmcia_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
 {
-	struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 	int ret = -1;
 
 	if (skt) {
@@ -430,9 +432,9 @@
  * Returns: 0
  */
 static int
-sa1100_pcmcia_get_status(unsigned int sock, unsigned int *status)
+sa1100_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
 {
-	struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 
 	skt->status = sa1100_pcmcia_skt_state(skt);
 	*status = skt->status;
@@ -450,9 +452,9 @@
  * Returns: 0
  */
 static int
-sa1100_pcmcia_get_socket(unsigned int sock, socket_state_t *state)
+sa1100_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
-  struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+  struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 
   DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
 
@@ -472,9 +474,9 @@
  * Returns: 0
  */
 static int
-sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state)
+sa1100_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
-  struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+  struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 
   DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
 
@@ -508,9 +510,9 @@
  * Returns: 0 on success, -1 on error
  */
 static int
-sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
+sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
 {
-	struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 	unsigned short speed = map->speed;
 
 	DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
@@ -564,9 +566,9 @@
  * Returns: 0 on success, -1 on error
  */
 static int
-sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
+sa1100_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
 {
-	struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+	struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
 	struct resource *res;
 	unsigned short speed = map->speed;
 
@@ -708,7 +710,7 @@
  * Returns: 0 on success, -1 on error
  */
 static void
-sa1100_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+sa1100_pcmcia_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
 {
 	struct proc_dir_entry *entry;
 
@@ -717,7 +719,7 @@
 		return;
 	}
 	entry->read_proc = sa1100_pcmcia_proc_status;
-	entry->data = PCMCIA_SOCKET(sock);
+	entry->data = to_sa1100_socket(sock);
 }
 #else
 #define sa1100_pcmcia_proc_setup	NULL
@@ -800,22 +802,16 @@
 	"PCMCIA socket 1",
 };
 
+struct skt_dev_info {
+	int nskt;
+};
+
 int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
 {
-	struct pcmcia_socket_class_data *cls;
+	struct skt_dev_info *sinfo;
 	unsigned int cpu_clock;
 	int ret, i;
 
-	cls = kmalloc(sizeof(struct pcmcia_socket_class_data), GFP_KERNEL);
-	if (!cls) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	memset(cls, 0, sizeof(struct pcmcia_socket_class_data));
-	cls->ops	= &sa11xx_pcmcia_operations;
-	cls->nsock	= nr;
-
 	/*
 	 * set default MECR calculation if the board specific
 	 * code did not specify one...
@@ -823,6 +819,15 @@
 	if (!ops->socket_get_timing)
 		ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
 
+	sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
+	if (!sinfo) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memset(sinfo, 0, sizeof(struct skt_dev_info));
+	sinfo->nskt = nr;
+
 	cpu_clock = cpufreq_get(0);
 
 	/*
@@ -832,6 +837,9 @@
 		struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
 		memset(skt, 0, sizeof(*skt));
 
+		skt->socket.ss_entry = &sa11xx_pcmcia_operations;
+		skt->socket.dev.dev = dev;
+
 		INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt);
 
 		init_timer(&skt->poll_timer);
@@ -898,16 +906,26 @@
 			goto out_err_6;
 
 		skt->status = sa1100_pcmcia_skt_state(skt);
+
+		ret = pcmcia_register_socket(&skt->socket);
+		if (ret)
+			goto out_err_7;
+
+		WARN_ON(skt->socket.sock != i);
+
 		add_timer(&skt->poll_timer);
 	}
 
-	dev->class_data = cls;
+	dev_set_drvdata(dev, sinfo);
 	return 0;
 
 	do {
 		struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
 
 		del_timer_sync(&skt->poll_timer);
+		pcmcia_unregister_socket(&skt->socket);
+
+ out_err_7:
 		flush_scheduled_work();
 
 		ops->hw_shutdown(skt);
@@ -925,7 +943,7 @@
 		i--;
 	} while (i > 0);
 
-	kfree(cls);
+	kfree(sinfo);
 
  out:
 	return ret;
@@ -934,19 +952,22 @@
 
 int sa11xx_drv_pcmcia_remove(struct device *dev)
 {
-	struct pcmcia_socket_class_data *cls = dev->class_data;
+	struct skt_dev_info *sinfo = dev_get_drvdata(dev);
 	int i;
 
-	dev->class_data = NULL;
-
-	for (i = 0; i < cls->nsock; i++) {
-		struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(cls->sock_offset + i);
+	dev_set_drvdata(dev, NULL);
 
-		skt->ops->hw_shutdown(skt);
+	for (i = 0; i < sinfo->nskt; i++) {
+		struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
 
 		del_timer_sync(&skt->poll_timer);
+
+		pcmcia_unregister_socket(&skt->socket);
+
 		flush_scheduled_work();
 
+		skt->ops->hw_shutdown(skt);
+
 		sa1100_pcmcia_config_skt(skt, &dead_socket);
 
 		iounmap(skt->virt_io);
@@ -957,7 +978,7 @@
 		release_resource(&skt->res_skt);
 	}
 
-	kfree(cls);
+	kfree(sinfo);
 
 	return 0;
 }
@@ -977,7 +998,8 @@
 
 	for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) {
 		struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
-		sa1100_pcmcia_set_mecr(skt, clock);
+		if (skt->ops)
+			sa1100_pcmcia_set_mecr(skt, clock);
 	}
 }
 
diff -urN linux-2.5.70-bk16/drivers/pcmcia/sa11xx_core.h linux-2.5.70-bk17/drivers/pcmcia/sa11xx_core.h
--- linux-2.5.70-bk16/drivers/pcmcia/sa11xx_core.h	2003-05-26 18:00:43.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/sa11xx_core.h	2003-06-12 04:49:58.000000000 -0700
@@ -44,6 +44,8 @@
  * use when responding to a Card Services query of some kind.
  */
 struct sa1100_pcmcia_socket {
+	struct pcmcia_socket	socket;
+
 	/*
 	 * Info from low level handler
 	 */
diff -urN linux-2.5.70-bk16/drivers/pcmcia/tcic.c linux-2.5.70-bk17/drivers/pcmcia/tcic.c
--- linux-2.5.70-bk16/drivers/pcmcia/tcic.c	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/tcic.c	2003-06-12 04:49:58.000000000 -0700
@@ -115,19 +115,20 @@
 static void tcic_timer(u_long data);
 static struct pccard_operations tcic_operations;
 
-typedef struct socket_info_t {
+struct tcic_socket {
     u_short	psock;
     void	(*handler)(void *info, u_int events);
     void	*info;
     u_char	last_sstat;
     u_char	id;
-} socket_info_t;
+    struct pcmcia_socket	socket;
+};
 
 static struct timer_list poll_timer;
 static int tcic_timer_pending;
 
 static int sockets;
-static socket_info_t socket_table[2];
+static struct tcic_socket socket_table[2];
 
 static socket_cap_t tcic_cap = {
 	/* only 16-bit cards, memory windows must be size-aligned */
@@ -372,15 +373,11 @@
 
 /*====================================================================*/
 
-static struct pcmcia_socket_class_data tcic_data = {
-	.ops = &tcic_operations,
-};
-
 static struct device_driver tcic_driver = {
 	.name = "tcic-pcmcia",
 	.bus = &platform_bus_type,
-/*	.suspend = pcmcia_socket_dev_suspend,	FIXME?	*/
-/*	.resume = pcmcia_socket_dev_resume,	FIXME?	*/
+	.suspend = pcmcia_socket_dev_suspend,
+	.resume = pcmcia_socket_dev_resume,
 };
 
 static struct platform_device tcic_device = {
@@ -391,13 +388,10 @@
 	},
 };
 
-static struct class_device tcic_class_data = {
-	.class = &pcmcia_socket_class,
-};
 
 static int __init init_tcic(void)
 {
-    int i, sock;
+    int i, sock, ret = 0;
     u_int mask, scan;
     servinfo_t serv;
 
@@ -524,13 +518,17 @@
     /* jump start interrupt handler, if needed */
     tcic_interrupt(0, NULL, NULL);
 
-    tcic_data.nsock = sockets;
-    tcic_class_data.dev = &tcic_device.dev;
-    tcic_class_data.class_data = &tcic_data;
-    strlcpy(tcic_class_data.class_id, "tcic-pcmcia", BUS_ID_SIZE);
-    
     platform_device_register(&tcic_device);
-    class_device_register(&tcic_class_data);
+
+    for (i = 0; i < sockets; i++) {
+	    socket_table[i].socket.ss_entry = &tcic_operations;
+	    socket_table[i].socket.dev.dev = &tcic_device.dev;
+	    ret = pcmcia_register_socket(&socket_table[i].socket);	    
+	    if (ret && i)
+		    pcmcia_unregister_socket(&socket_table[0].socket);
+    }
+    
+    return ret;
 
     return 0;
     
@@ -540,13 +538,19 @@
 
 static void __exit exit_tcic(void)
 {
+    int i;
+
     del_timer_sync(&poll_timer);
     if (cs_irq != 0) {
 	tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
 	free_irq(cs_irq, tcic_interrupt);
     }
     release_region(tcic_base, 16);
-    class_device_unregister(&tcic_class_data);
+
+    for (i = 0; i < sockets; i++) {
+	    pcmcia_unregister_socket(&socket_table[i].socket);	    
+    }
+
     platform_device_unregister(&tcic_device);
     driver_unregister(&tcic_driver);
 } /* exit_tcic */
@@ -640,18 +644,19 @@
 
 /*====================================================================*/
 
-static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info)
+static int tcic_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
 {
-    socket_table[lsock].handler = handler;
-    socket_table[lsock].info = info;
+    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
+    socket_table[psock].handler = handler;
+    socket_table[psock].info = info;
     return 0;
 } /* tcic_register_callback */
 
 /*====================================================================*/
 
-static int tcic_get_status(unsigned int lsock, u_int *value)
+static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
     u_char reg;
 
     tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
@@ -675,7 +680,7 @@
   
 /*====================================================================*/
 
-static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
+static int tcic_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
 {
     *cap = tcic_cap;
     return 0;
@@ -683,9 +688,9 @@
 
 /*====================================================================*/
 
-static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
+static int tcic_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
     u_char reg;
     u_short scf1, scf2;
     
@@ -736,9 +741,9 @@
 
 /*====================================================================*/
 
-static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
+static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
     u_char reg;
     u_short scf1, scf2;
 
@@ -811,9 +816,9 @@
   
 /*====================================================================*/
 
-static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
+static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
     u_int addr;
     u_short base, len, ioctl;
     
@@ -848,9 +853,9 @@
 
 /*====================================================================*/
 
-static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
+static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 {
-    u_short psock = socket_table[lsock].psock;
+    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
     u_short addr, ctl;
     u_long base, len, mmap;
 
@@ -892,11 +897,11 @@
 
 /*====================================================================*/
 
-static void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+static void tcic_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
 {
 }
 
-static int tcic_init(unsigned int s)
+static int tcic_init(struct pcmcia_socket *s)
 {
 	int i;
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -915,7 +920,7 @@
 	return 0;
 }
 
-static int tcic_suspend(unsigned int sock)
+static int tcic_suspend(struct pcmcia_socket *sock)
 {
 	return tcic_set_socket(sock, &dead_socket);
 }
diff -urN linux-2.5.70-bk16/drivers/pcmcia/ti113x.h linux-2.5.70-bk17/drivers/pcmcia/ti113x.h
--- linux-2.5.70-bk16/drivers/pcmcia/ti113x.h	2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/ti113x.h	2003-06-12 04:49:58.000000000 -0700
@@ -136,6 +136,26 @@
 
 #ifdef CONFIG_CARDBUS
 
+static int ti_intctl(struct yenta_socket *socket)
+{
+	u8 new, reg = exca_readb(socket, I365_INTCTL);
+
+	new = reg & ~I365_INTR_ENA;
+	if (socket->cb_irq)
+		new |= I365_INTR_ENA;
+	if (new != reg)
+		exca_writeb(socket, I365_INTCTL, new);
+	return 0;
+}
+
+static int ti_init(struct pcmcia_socket *sock)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	yenta_init(sock);
+	ti_intctl(socket);
+	return 0;
+}
+
 /*
  * Generic TI init - TI has an extension for the
  * INTCTL register that sets the PCI CSC interrupt.
@@ -148,70 +168,28 @@
  *   This makes us correctly get PCI CSC interrupt
  *   events.
  */
-static int ti_open(pci_socket_t *socket)
+static int ti_override(struct yenta_socket *socket)
 {
 	u8 new, reg = exca_readb(socket, I365_INTCTL);
 
 	new = reg & ~I365_INTR_ENA;
 	if (new != reg)
 		exca_writeb(socket, I365_INTCTL, new);
+	socket->socket.ss_entry->init = ti_init;
 	return 0;
 }
 
-static int ti_intctl(pci_socket_t *socket)
-{
-	u8 new, reg = exca_readb(socket, I365_INTCTL);
-
-	new = reg & ~I365_INTR_ENA;
-	if (socket->cb_irq)
-		new |= I365_INTR_ENA;
-	if (new != reg)
-		exca_writeb(socket, I365_INTCTL, new);
-	return 0;
-}
-
-static int ti_init(pci_socket_t *socket)
-{
-	yenta_init(socket);
-	ti_intctl(socket);
-	return 0;
-}
-
-static struct pci_socket_ops ti_ops = {
-	ti_open,
-	yenta_close,
-	ti_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
-};
-
 #define ti_sysctl(socket)	((socket)->private[0])
 #define ti_cardctl(socket)	((socket)->private[1])
 #define ti_devctl(socket)	((socket)->private[2])
 #define ti_diag(socket)		((socket)->private[3])
 #define ti_irqmux(socket)	((socket)->private[4])
 
-static int ti113x_open(pci_socket_t *socket)
-{
-	ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
-	ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
-	ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
-
-	ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
-	if (socket->cb_irq)
-		ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
-	ti_open(socket);
-	return 0;
-}
 
-static int ti113x_init(pci_socket_t *socket)
+static int ti113x_init(struct pcmcia_socket *sock)
 {
-	yenta_init(socket);
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	yenta_init(sock);
 
 	config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket));
 	config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket));
@@ -220,35 +198,26 @@
 	return 0;
 }
 
-static struct pci_socket_ops ti113x_ops = {
-	ti113x_open,
-	yenta_close,
-	ti113x_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
-};
-
-
-static int ti1250_open(pci_socket_t *socket)
+static int ti113x_override(struct yenta_socket *socket)
 {
-	ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+	ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
+	ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
+	ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
 
-	ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
+	ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
 	if (socket->cb_irq)
-		ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
-	ti113x_open(socket);
+		ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
+	ti_override(socket);
+	socket->socket.ss_entry->init = ti113x_init;
 	return 0;
 }
 
-static int ti1250_init(pci_socket_t *socket)
+
+static int ti1250_init(struct pcmcia_socket *sock)
 {
-	yenta_init(socket);
-	ti113x_init(socket);
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	yenta_init(sock);
+	ti113x_init(sock);
 	ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX);
 	ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */
 	if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE))
@@ -260,18 +229,17 @@
 	return 0;
 }
 
-static struct pci_socket_ops ti1250_ops = {
-	ti1250_open,
-	yenta_close,
-	ti1250_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
-};
+static int ti1250_override(struct yenta_socket *socket)
+{
+	ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+
+	ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
+	if (socket->cb_irq)
+		ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
+	ti113x_override(socket);
+	socket->socket.ss_entry->init = ti1250_init;
+	return 0;
+}
 
 #endif /* CONFIG_CARDBUS */
 
diff -urN linux-2.5.70-bk16/drivers/pcmcia/yenta.c linux-2.5.70-bk17/drivers/pcmcia/yenta.c
--- linux-2.5.70-bk16/drivers/pcmcia/yenta.c	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/yenta.c	2003-06-12 04:49:58.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * Regular lowlevel cardbus driver ("yenta")
+ * Regular cardbus driver ("yenta")
  *
  * (C) Copyright 1999, 2000 Linus Torvalds
  *
@@ -7,6 +7,8 @@
  * Aug 2002: Manfred Spraul <manfred@colorfullife.com>
  * 	Dynamically adjust the size of the bridge resource
  * 	
+ * May 2003: Dominik Brodowski <linux@brodo.de>
+ * 	Merge pci_socket.c and yenta.c into one file
  */
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -26,6 +28,7 @@
 #include "yenta.h"
 #include "i82365.h"
 
+
 #if 0
 #define DEBUG(x,args...)	printk("%s: " x, __FUNCTION__, ##args)
 #else
@@ -41,20 +44,20 @@
  * regular memory space ("cb_xxx"), configuration space
  * ("config_xxx") and compatibility space ("exca_xxxx")
  */
-static inline u32 cb_readl(pci_socket_t *socket, unsigned reg)
+static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg)
 {
 	u32 val = readl(socket->base + reg);
 	DEBUG("%p %04x %08x\n", socket, reg, val);
 	return val;
 }
 
-static inline void cb_writel(pci_socket_t *socket, unsigned reg, u32 val)
+static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
 {
 	DEBUG("%p %04x %08x\n", socket, reg, val);
 	writel(val, socket->base + reg);
 }
 
-static inline u8 config_readb(pci_socket_t *socket, unsigned offset)
+static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
 {
 	u8 val;
 	pci_read_config_byte(socket->dev, offset, &val);
@@ -62,7 +65,7 @@
 	return val;
 }
 
-static inline u16 config_readw(pci_socket_t *socket, unsigned offset)
+static inline u16 config_readw(struct yenta_socket *socket, unsigned offset)
 {
 	u16 val;
 	pci_read_config_word(socket->dev, offset, &val);
@@ -70,7 +73,7 @@
 	return val;
 }
 
-static inline u32 config_readl(pci_socket_t *socket, unsigned offset)
+static inline u32 config_readl(struct yenta_socket *socket, unsigned offset)
 {
 	u32 val;
 	pci_read_config_dword(socket->dev, offset, &val);
@@ -78,32 +81,32 @@
 	return val;
 }
 
-static inline void config_writeb(pci_socket_t *socket, unsigned offset, u8 val)
+static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val)
 {
 	DEBUG("%p %04x %02x\n", socket, offset, val);
 	pci_write_config_byte(socket->dev, offset, val);
 }
 
-static inline void config_writew(pci_socket_t *socket, unsigned offset, u16 val)
+static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val)
 {
 	DEBUG("%p %04x %04x\n", socket, offset, val);
 	pci_write_config_word(socket->dev, offset, val);
 }
 
-static inline void config_writel(pci_socket_t *socket, unsigned offset, u32 val)
+static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val)
 {
 	DEBUG("%p %04x %08x\n", socket, offset, val);
 	pci_write_config_dword(socket->dev, offset, val);
 }
 
-static inline u8 exca_readb(pci_socket_t *socket, unsigned reg)
+static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg)
 {
 	u8 val = readb(socket->base + 0x800 + reg);
 	DEBUG("%p %04x %02x\n", socket, reg, val);
 	return val;
 }
 
-static inline u8 exca_readw(pci_socket_t *socket, unsigned reg)
+static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg)
 {
 	u16 val;
 	val = readb(socket->base + 0x800 + reg);
@@ -112,13 +115,13 @@
 	return val;
 }
 
-static inline void exca_writeb(pci_socket_t *socket, unsigned reg, u8 val)
+static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val)
 {
 	DEBUG("%p %04x %02x\n", socket, reg, val);
 	writeb(val, socket->base + 0x800 + reg);
 }
 
-static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val)
+static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
 {
 	DEBUG("%p %04x %04x\n", socket, reg, val);
 	writeb(val, socket->base + 0x800 + reg);
@@ -129,8 +132,9 @@
  * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
  * on what kind of card is inserted..
  */
-static int yenta_get_status(pci_socket_t *socket, unsigned int *value)
+static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	unsigned int val;
 	u32 state = cb_readl(socket, CB_SOCKET_STATE);
 
@@ -181,8 +185,9 @@
 	}
 }
 
-static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state)
+static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	u8 reg;
 	u32 control;
 
@@ -221,7 +226,7 @@
 	return 0;
 }
 
-static void yenta_set_power(pci_socket_t *socket, socket_state_t *state)
+static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
 {
 	u32 reg = 0;	/* CB_SC_STPCLK? */
 	switch (state->Vcc) {
@@ -238,8 +243,9 @@
 		cb_writel(socket, CB_SOCKET_CONTROL, reg);
 }
 
-static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state)
+static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	u16 bridge;
 
 	if (state->flags & SS_DEBOUNCED) {
@@ -300,8 +306,9 @@
 	return 0;
 }
 
-static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	int map;
 	unsigned char ioctl, addr, enable;
 
@@ -333,8 +340,9 @@
 	return 0;
 }
 
-static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	int map;
 	unsigned char addr, enable;
 	unsigned int start, stop, card_start;
@@ -386,12 +394,12 @@
 	return 0;
 }
 
-static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base)
+static void yenta_proc_setup(struct pcmcia_socket *sock, struct proc_dir_entry *base)
 {
 	/* Not done yet */
 }
 
-static unsigned int yenta_events(pci_socket_t *socket)
+static unsigned int yenta_events(struct yenta_socket *socket)
 {
 	u8 csc;
 	u32 cb_event;
@@ -418,7 +426,7 @@
 
 static void yenta_bh(void *data)
 {
-	pci_socket_t *socket = data;
+	struct yenta_socket *socket = data;
 	unsigned int events;
 
 	spin_lock_irq(&socket->event_lock);
@@ -432,7 +440,7 @@
 static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned int events;
-	pci_socket_t *socket = (pci_socket_t *) dev_id;
+	struct yenta_socket *socket = (struct yenta_socket *) dev_id;
 
 	events = yenta_events(socket);
 	if (events) {
@@ -447,7 +455,7 @@
 
 static void yenta_interrupt_wrapper(unsigned long data)
 {
-	pci_socket_t *socket = (pci_socket_t *) data;
+	struct yenta_socket *socket = (struct yenta_socket *) data;
 
 	yenta_interrupt(0, (void *)socket, NULL);
 	socket->poll_timer.expires = jiffies + HZ;
@@ -465,7 +473,7 @@
  */
 static u32 isa_interrupts = 0x0ef8;
 
-static unsigned int yenta_probe_irq(pci_socket_t *socket, u32 isa_irq_mask)
+static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask)
 {
 	int i;
 	unsigned long val;
@@ -509,7 +517,7 @@
 /*
  * Set static data that doesn't need re-initializing..
  */
-static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask)
+static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask)
 {
 	socket->cap.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
 	socket->cap.map_size = 0x1000;
@@ -520,28 +528,38 @@
 	printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq);
 }
 
-static void yenta_clear_maps(pci_socket_t *socket)
+static int yenta_inquire_socket(struct pcmcia_socket *sock, socket_cap_t *cap)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+	*cap = socket->cap;
+
+	return 0;
+}
+
+
+static void yenta_clear_maps(struct yenta_socket *socket)
 {
 	int i;
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
 	pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
 
 	mem.sys_stop = 0x0fff;
-	yenta_set_socket(socket, &dead_socket);
+	yenta_set_socket(&socket->socket, &dead_socket);
 	for (i = 0; i < 2; i++) {
 		io.map = i;
-		yenta_set_io_map(socket, &io);
+		yenta_set_io_map(&socket->socket, &io);
 	}
 	for (i = 0; i < 5; i++) {
 		mem.map = i;
-		yenta_set_mem_map(socket, &mem);
+		yenta_set_mem_map(&socket->socket, &mem);
 	}
 }
 
 /*
  * Initialize the standard cardbus registers
  */
-static void yenta_config_init(pci_socket_t *socket)
+static void yenta_config_init(struct yenta_socket *socket)
 {
 	u16 bridge;
 	struct pci_dev *dev = socket->dev;
@@ -586,8 +604,9 @@
 }
 
 /* Called at resume and initialization events */
-static int yenta_init(pci_socket_t *socket)
+static int yenta_init(struct pcmcia_socket *sock)
 {
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	yenta_config_init(socket);
 	yenta_clear_maps(socket);
 
@@ -596,9 +615,11 @@
 	return 0;
 }
 
-static int yenta_suspend(pci_socket_t *socket)
+static int yenta_suspend(struct pcmcia_socket *sock)
 {
-	yenta_set_socket(socket, &dead_socket);
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+	yenta_set_socket(sock, &dead_socket);
 
 	/* Disable interrupts */
 	cb_writel(socket, CB_SOCKET_MASK, 0x0);
@@ -630,7 +651,7 @@
 #define BRIDGE_IO_MAX 256
 #define BRIDGE_IO_MIN 32
 
-static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
+static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type)
 {
 	struct pci_bus *bus;
 	struct resource *root, *res;
@@ -711,7 +732,7 @@
 /*
  * Allocate the bridge mappings for the device..
  */
-static void yenta_allocate_resources(pci_socket_t *socket)
+static void yenta_allocate_resources(struct yenta_socket *socket)
 {
 	yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH);
 	yenta_allocate_res(socket, 1, IORESOURCE_MEM);
@@ -719,10 +740,11 @@
 	yenta_allocate_res(socket, 3, IORESOURCE_IO);	/* PCI isn't clever enough to use this one yet */
 }
 
+
 /*
  * Free the bridge mappings for the device..
  */
-static void yenta_free_resources(pci_socket_t *socket)
+static void yenta_free_resources(struct yenta_socket *socket)
 {
 	int i;
 	for (i=0;i<4;i++) {
@@ -733,11 +755,15 @@
 		res->start = res->end = 0;
 	}
 }
+
+
 /*
  * Close it down - release our resources and go home..
  */
-static void yenta_close(pci_socket_t *sock)
+static void yenta_close(struct pci_dev *dev)
 {
+	struct yenta_socket *sock = pci_get_drvdata(dev);
+
 	/* Disable all events so we don't die in an IRQ storm */
 	cb_writel(sock, CB_SOCKET_MASK, 0x0);
 	exca_writeb(sock, I365_CSCINT, 0);
@@ -750,8 +776,37 @@
 	if (sock->base)
 		iounmap(sock->base);
 	yenta_free_resources(sock);
+
+	pcmcia_unregister_socket(&sock->socket);
+	pci_set_drvdata(dev, NULL);
 }
 
+
+static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+	socket->handler = handler;
+	socket->info = info;
+	return 0;
+}
+
+
+static struct pccard_operations yenta_socket_operations = {
+	.owner			= THIS_MODULE,
+	.init			= yenta_init,
+	.suspend		= yenta_suspend,
+	.register_callback	= yenta_register_callback,
+	.inquire_socket		= yenta_inquire_socket,
+	.get_status		= yenta_get_status,
+	.get_socket		= yenta_get_socket,
+	.set_socket		= yenta_set_socket,
+	.set_io_map		= yenta_set_io_map,
+	.set_mem_map		= yenta_set_mem_map,
+	.proc_setup		= yenta_proc_setup,
+};
+
+
 #include "ti113x.h"
 #include "ricoh.h"
 
@@ -760,49 +815,62 @@
  * initialization sequences etc details. List them here..
  */
 #define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y
-static struct cardbus_override_struct {
+struct cardbus_override_struct {
 	unsigned short vendor;
 	unsigned short device;
-	struct pci_socket_ops *op;
+	int (*override) (struct yenta_socket *socket);
 } cardbus_override[] = {
-	{ PD(TI,1130),	&ti113x_ops },
-	{ PD(TI,1031),	&ti_ops },
-	{ PD(TI,1131),	&ti113x_ops },
-	{ PD(TI,1250),	&ti1250_ops },
-	{ PD(TI,1220),	&ti_ops },
-	{ PD(TI,1221),	&ti_ops },
-	{ PD(TI,1210),	&ti_ops },
-	{ PD(TI,1450),	&ti_ops },
-	{ PD(TI,1225),	&ti_ops },
-	{ PD(TI,1251A),	&ti_ops },
-	{ PD(TI,1211),	&ti_ops },
-	{ PD(TI,1251B),	&ti_ops },
-	{ PD(TI,1410),	&ti1250_ops },
-	{ PD(TI,1420),	&ti_ops },
-	{ PD(TI,4410),	&ti_ops },
-	{ PD(TI,4451),	&ti_ops },
-
-	{ PD(RICOH,RL5C465), &ricoh_ops },
-	{ PD(RICOH,RL5C466), &ricoh_ops },
-	{ PD(RICOH,RL5C475), &ricoh_ops },
-	{ PD(RICOH,RL5C476), &ricoh_ops },
-	{ PD(RICOH,RL5C478), &ricoh_ops }
-};
-
-#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))
+	{ PD(TI,1130),	&ti113x_override },
+	{ PD(TI,1031),	&ti_override },
+	{ PD(TI,1131),	&ti113x_override },
+	{ PD(TI,1250),	&ti1250_override },
+	{ PD(TI,1220),	&ti_override },
+	{ PD(TI,1221),	&ti_override },
+	{ PD(TI,1210),	&ti_override },
+	{ PD(TI,1450),	&ti_override },
+	{ PD(TI,1225),	&ti_override },
+	{ PD(TI,1251A),	&ti_override },
+	{ PD(TI,1211),	&ti_override },
+	{ PD(TI,1251B),	&ti_override },
+	{ PD(TI,1410),	ti1250_override },
+	{ PD(TI,1420),	&ti_override },
+	{ PD(TI,4410),	&ti_override },
+	{ PD(TI,4451),	&ti_override },
+
+	{ PD(RICOH,RL5C465), &ricoh_override },
+	{ PD(RICOH,RL5C466), &ricoh_override },
+	{ PD(RICOH,RL5C475), &ricoh_override },
+	{ PD(RICOH,RL5C476), &ricoh_override },
+	{ PD(RICOH,RL5C478), &ricoh_override },
 
+	{ }, /* all zeroes */
+};
 
-extern int cardbus_register(struct pci_dev *p_dev);
 
 /*
  * Initialize a cardbus controller. Make sure we have a usable
  * interrupt, and that we can map the cardbus area. Fill in the
  * socket information structure..
  */
-static int yenta_open(pci_socket_t *socket)
+static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
-	int i;
-	struct pci_dev *dev = socket->dev;
+	struct yenta_socket *socket;
+	struct cardbus_override_struct *d;
+	
+	socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
+	if (!socket)
+		return -ENOMEM;
+	memset(socket, 0, sizeof(*socket));
+
+	/* prepare pcmcia_socket */
+	socket->socket.ss_entry = &yenta_socket_operations;
+	socket->socket.dev.dev = &dev->dev;
+	socket->socket.driver_data = socket;
+
+	/* prepare struct yenta_socket */
+	socket->dev = dev;
+	pci_set_drvdata(dev, socket);
+	spin_lock_init(&socket->event_lock);
 
 	/*
 	 * Do some basic sanity checking..
@@ -833,16 +901,14 @@
 	socket->cb_irq = dev->irq;
 
 	/* Do we have special options for the device? */
-	for (i = 0; i < NR_OVERRIDES; i++) {
-		struct cardbus_override_struct *d = cardbus_override+i;
-		if (dev->vendor == d->vendor && dev->device == d->device) {
-			socket->op = d->op;
-			if (d->op->open) {
-				int retval = d->op->open(socket);
-				if (retval < 0)
-					return retval;
-			}
+	d = cardbus_override;
+	while (d->override) {
+		if ((dev->vendor == d->vendor) && (dev->device == d->device)) {
+			int retval = d->override(socket);
+			if (retval < 0)
+				return retval;
 		}
+		d++;
 	}
 
 	/* We must finish initialization here */
@@ -864,23 +930,58 @@
 	printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
 
 	/* Register it with the pcmcia layer.. */
-	return cardbus_register(dev);
+	return pcmcia_register_socket(&socket->socket);
 }
 
-/*
- * Standard plain cardbus - no frills, no extensions
- */
-struct pci_socket_ops yenta_operations = {
-	yenta_open,
-	yenta_close,
-	yenta_init,
-	yenta_suspend,
-	yenta_get_status,
-	yenta_get_socket,
-	yenta_set_socket,
-	yenta_set_io_map,
-	yenta_set_mem_map,
-	yenta_proc_setup
+
+static int yenta_dev_suspend (struct pci_dev *dev, u32 state)
+{
+	return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
+}
+
+
+static int yenta_dev_resume (struct pci_dev *dev)
+{
+	return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE);
+}
+
+
+static struct pci_device_id yenta_table [] __devinitdata = { {
+	.class		= PCI_CLASS_BRIDGE_CARDBUS << 8,
+	.class_mask	= ~0,
+
+	.vendor		= PCI_ANY_ID,
+	.device		= PCI_ANY_ID,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+}, { /* all zeroes */ }
 };
-EXPORT_SYMBOL(yenta_operations);
+MODULE_DEVICE_TABLE(pci, yenta_table);
+
+
+static struct pci_driver yenta_cardbus_driver = {
+	.name		= "yenta_cardbus",
+	.id_table	= yenta_table,
+	.probe		= yenta_probe,
+	.remove		= __devexit_p(yenta_close),
+	.suspend	= yenta_dev_suspend,
+	.resume		= yenta_dev_resume,
+};
+
+
+static int __init yenta_socket_init(void)
+{
+	return pci_register_driver (&yenta_cardbus_driver);
+}
+
+
+static void __exit yenta_socket_exit (void)
+{
+	pci_unregister_driver (&yenta_cardbus_driver);
+}
+
+
+module_init(yenta_socket_init);
+module_exit(yenta_socket_exit);
+
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.70-bk16/drivers/pcmcia/yenta.h linux-2.5.70-bk17/drivers/pcmcia/yenta.h
--- linux-2.5.70-bk16/drivers/pcmcia/yenta.h	2003-05-26 18:00:37.000000000 -0700
+++ linux-2.5.70-bk17/drivers/pcmcia/yenta.h	2003-06-12 04:49:58.000000000 -0700
@@ -2,7 +2,6 @@
 #define __YENTA_H
 
 #include <asm/io.h>
-#include "pci_socket.h"
 
 #define CB_SOCKET_EVENT		0x00
 #define    CB_CSTSEVENT		0x00000001	/* Card status event */
@@ -96,4 +95,23 @@
  */
 #define CB_MEM_PAGE(map)	(0x40 + (map))
 
+struct yenta_socket {
+	struct pci_dev *dev;
+	int cb_irq, io_irq;
+	void *base;
+	void (*handler)(void *, unsigned int);
+	void *info;
+	socket_cap_t cap;
+	spinlock_t event_lock;
+	unsigned int events;
+	struct work_struct tq_task;
+	struct timer_list poll_timer;
+
+	struct pcmcia_socket socket;
+
+	/* A few words of private data for special stuff of overrides... */
+	unsigned int private[8];
+};
+
+
 #endif
diff -urN linux-2.5.70-bk16/drivers/s390/char/con3215.c linux-2.5.70-bk17/drivers/s390/char/con3215.c
--- linux-2.5.70-bk16/drivers/s390/char/con3215.c	2003-05-26 18:00:43.000000000 -0700
+++ linux-2.5.70-bk17/drivers/s390/char/con3215.c	2003-06-12 04:49:58.000000000 -0700
@@ -107,11 +107,7 @@
 /* spinlock to protect free list */
 static spinlock_t raw3215_freelist_lock;
 
-static struct tty_driver tty3215_driver;
-static struct tty_struct *tty3215_table[NR_3215];
-static struct termios *tty3215_termios[NR_3215];
-static struct termios *tty3215_termios_locked[NR_3215];
-static int tty3215_refcount;
+static struct tty_driver *tty3215_driver;
 
 /*
  * Get a request structure from the free list
@@ -843,7 +839,7 @@
 static struct tty_driver *con3215_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &tty3215_driver;
+	return tty3215_driver;
 }
 
 /*
@@ -1155,6 +1151,21 @@
 	}
 }
 
+static struct tty_operations tty3215_ops = {
+	.open = tty3215_open,
+	.close = tty3215_close,
+	.write = tty3215_write,
+	.put_char = tty3215_put_char,
+	.flush_chars = tty3215_flush_chars,
+	.write_room = tty3215_write_room,
+	.chars_in_buffer = tty3215_chars_in_buffer,
+	.flush_buffer = tty3215_flush_buffer,
+	.ioctl = tty3215_ioctl,
+	.throttle = tty3215_throttle,
+	.unthrottle = tty3215_unthrottle,
+	.stop = tty3215_stop,
+	.start = tty3215_start,
+};
 
 /*
  * 3215 tty registration code called from tty_init().
@@ -1163,70 +1174,54 @@
 int __init
 tty3215_init(void)
 {
+	struct tty_driver *driver;
 	int ret;
 
 	if (!CONSOLE_IS_3215)
 		return 0;
 
+	driver = alloc_tty_driver(NR_3215);
+	if (!driver)
+		return -ENOMEM;
+
 	ret = ccw_driver_register(&raw3215_ccw_driver);
-	if (ret)
+	if (ret) {
+		put_tty_driver(driver);
 		return ret;
+	}
 	/*
 	 * Initialize the tty_driver structure
 	 * Entries in tty3215_driver that are NOT initialized:
 	 * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc
 	 */
 
-	memset(&tty3215_driver, 0, sizeof(struct tty_driver));
-	tty3215_driver.magic = TTY_DRIVER_MAGIC;
-	tty3215_driver.owner = THIS_MODULE;
-	tty3215_driver.driver_name = "tty3215";
-	tty3215_driver.name = "ttyS";
-	tty3215_driver.major = TTY_MAJOR;
-	tty3215_driver.minor_start = 64;
-	tty3215_driver.num = NR_3215;
-	tty3215_driver.type = TTY_DRIVER_TYPE_SYSTEM;
-	tty3215_driver.subtype = SYSTEM_TYPE_TTY;
-	tty3215_driver.init_termios = tty_std_termios;
-	tty3215_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
-	tty3215_driver.init_termios.c_oflag = ONLCR | XTABS;
-	tty3215_driver.init_termios.c_lflag = ISIG;
-	tty3215_driver.flags = TTY_DRIVER_REAL_RAW;
-	tty3215_driver.refcount = &tty3215_refcount;
-	tty3215_driver.table = tty3215_table;
-	tty3215_driver.termios = tty3215_termios;
-	tty3215_driver.termios_locked = tty3215_termios_locked;
-
-	tty3215_driver.open = tty3215_open;
-	tty3215_driver.close = tty3215_close;
-	tty3215_driver.write = tty3215_write;
-	tty3215_driver.put_char = tty3215_put_char;
-	tty3215_driver.flush_chars = tty3215_flush_chars;
-	tty3215_driver.write_room = tty3215_write_room;
-	tty3215_driver.chars_in_buffer = tty3215_chars_in_buffer;
-	tty3215_driver.flush_buffer = tty3215_flush_buffer;
-	tty3215_driver.ioctl = tty3215_ioctl;
-	tty3215_driver.throttle = tty3215_throttle;
-	tty3215_driver.unthrottle = tty3215_unthrottle;
-	tty3215_driver.send_xchar = NULL;
-	tty3215_driver.set_termios = NULL;
-	tty3215_driver.stop = tty3215_stop;
-	tty3215_driver.start = tty3215_start;
-	tty3215_driver.hangup = NULL;
-	tty3215_driver.break_ctl = NULL;
-	tty3215_driver.wait_until_sent = NULL;
-	tty3215_driver.read_proc = NULL;
-
-	ret = tty_register_driver(&tty3215_driver);
-	if (ret)
+	driver->owner = THIS_MODULE;
+	driver->driver_name = "tty3215";
+	driver->name = "ttyS";
+	driver->major = TTY_MAJOR;
+	driver->minor_start = 64;
+	driver->type = TTY_DRIVER_TYPE_SYSTEM;
+	driver->subtype = SYSTEM_TYPE_TTY;
+	driver->init_termios = tty_std_termios;
+	driver->init_termios.c_iflag = IGNBRK | IGNPAR;
+	driver->init_termios.c_oflag = ONLCR | XTABS;
+	driver->init_termios.c_lflag = ISIG;
+	driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(driver, &tty3215_ops);
+	ret = tty_register_driver(driver);
+	if (ret) {
 		printk("Couldn't register tty3215 driver\n");
-	return ret;
+		put_tty_driver(driver);
+		return ret;
+	}
+	tty3215_driver = driver;
 }
 
 static void __exit
 tty3215_exit(void)
 {
-	tty_unregister_driver(&tty3215_driver);
+	tty_unregister_driver(tty3215_driver);
+	put_tty_driver(tty3215_driver);
 	ccw_driver_unregister(&raw3215_ccw_driver);
 }
 
diff -urN linux-2.5.70-bk16/drivers/s390/char/sclp_con.c linux-2.5.70-bk17/drivers/s390/char/sclp_con.c
--- linux-2.5.70-bk16/drivers/s390/char/sclp_con.c	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/drivers/s390/char/sclp_con.c	2003-06-12 04:49:58.000000000 -0700
@@ -163,7 +163,7 @@
 sclp_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &sclp_tty_driver;
+	return sclp_tty_driver;
 }
 
 /*
diff -urN linux-2.5.70-bk16/drivers/s390/char/sclp_tty.c linux-2.5.70-bk17/drivers/s390/char/sclp_tty.c
--- linux-2.5.70-bk16/drivers/s390/char/sclp_tty.c	2003-05-26 18:00:24.000000000 -0700
+++ linux-2.5.70-bk17/drivers/s390/char/sclp_tty.c	2003-06-12 04:49:58.000000000 -0700
@@ -57,11 +57,7 @@
 static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE];
 static unsigned short int sclp_tty_chars_count;
 
-struct tty_driver sclp_tty_driver;
-static struct tty_struct * sclp_tty_table[1];
-static struct termios * sclp_tty_termios[1];
-static struct termios * sclp_tty_termios_locked[1];
-static int sclp_tty_refcount = 0;
+struct tty_driver *sclp_tty_driver;
 
 extern struct termios  tty_std_termios;
 
@@ -712,28 +708,48 @@
 	.receiver_fn = sclp_tty_receiver
 };
 
+static struct tty_operations sclp_ops = {
+	.open = sclp_tty_open,
+	.close = sclp_tty_close,
+	.write = sclp_tty_write,
+	.put_char = sclp_tty_put_char,
+	.flush_chars = sclp_tty_flush_chars,
+	.write_room = sclp_tty_write_room,
+	.chars_in_buffer = sclp_tty_chars_in_buffer,
+	.flush_buffer = sclp_tty_flush_buffer,
+	.ioctl = sclp_tty_ioctl,
+};
+
 int __init
 sclp_tty_init(void)
 {
+	struct tty_driver *driver;
 	void *page;
 	int i;
 	int rc;
 
 	if (!CONSOLE_IS_SCLP)
 		return 0;
+	driver = alloc_tty_driver(1);
+	if (!driver)
+		return -ENOMEM;
+
 	rc = sclp_rw_init();
 	if (rc) {
 		printk(KERN_ERR SCLP_TTY_PRINT_HEADER
 		       "could not register tty - "
 		       "sclp_rw_init returned %d\n", rc);
+		put_tty_driver(driver);
 		return rc;
 	}
 	/* Allocate pages for output buffering */
 	INIT_LIST_HEAD(&sclp_tty_pages);
 	for (i = 0; i < MAX_KMEM_PAGES; i++) {
 		page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
-		if (page == NULL)
+		if (page == NULL) {
+			put_tty_driver(driver);
 			return -ENOMEM;
+		}
 		list_add_tail((struct list_head *) page, &sclp_tty_pages);
 	}
 	INIT_LIST_HEAD(&sclp_tty_outqueue);
@@ -756,67 +772,33 @@
 	sclp_tty = NULL;
 
 	rc = sclp_register(&sclp_input_event);
-	if (rc)
+	if (rc) {
+		put_tty_driver(driver);
 		return rc;
+	}
 
-	memset (&sclp_tty_driver, 0, sizeof(struct tty_driver));
-	sclp_tty_driver.magic = TTY_DRIVER_MAGIC;
-	sclp_tty_driver.owner = THIS_MODULE;
-	sclp_tty_driver.driver_name = "sclp_line";
-	sclp_tty_driver.name = "ttyS";
-	sclp_tty_driver.major = TTY_MAJOR;
-	sclp_tty_driver.minor_start = 64;
-	sclp_tty_driver.num = 1;
-	sclp_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
-	sclp_tty_driver.subtype = SYSTEM_TYPE_TTY;
-	sclp_tty_driver.init_termios = tty_std_termios;
-	sclp_tty_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
-	sclp_tty_driver.init_termios.c_oflag = ONLCR | XTABS;
-	sclp_tty_driver.init_termios.c_lflag = ISIG | ECHO;
-	sclp_tty_driver.flags = TTY_DRIVER_REAL_RAW;
-	sclp_tty_driver.refcount = &sclp_tty_refcount;
-	/* sclp_tty_driver.proc_entry ?	 */
-	sclp_tty_driver.table = sclp_tty_table;
-	sclp_tty_driver.termios = sclp_tty_termios;
-	sclp_tty_driver.termios_locked = sclp_tty_termios_locked;
-	sclp_tty_driver.open = sclp_tty_open;
-	sclp_tty_driver.close = sclp_tty_close;
-	sclp_tty_driver.write = sclp_tty_write;
-	sclp_tty_driver.put_char = sclp_tty_put_char;
-	sclp_tty_driver.flush_chars = sclp_tty_flush_chars;
-	sclp_tty_driver.write_room = sclp_tty_write_room;
-	sclp_tty_driver.chars_in_buffer = sclp_tty_chars_in_buffer;
-	sclp_tty_driver.flush_buffer = sclp_tty_flush_buffer;
-	sclp_tty_driver.ioctl = sclp_tty_ioctl;
-	/*
-	 * No need for these function because they would be only called when
-	 * the line discipline is close to full. That means that there must be
-	 * collected nearly 4kB of input data. I suppose it is very difficult
-	 * for the operator to enter lines quickly enough to let overrun the
-	 * line discipline. Besides the n_tty line discipline does not try to
-	 * call such functions if the pointers are set to NULL. Finally I have
-	 * no idea what to do within these function. I can not prevent the
-	 * operator and the SCLP to deliver input. Because of the reasons
-	 * above it seems not worth to implement a buffer mechanism.
-	 */
-	sclp_tty_driver.throttle = NULL;
-	sclp_tty_driver.unthrottle = NULL;
-	sclp_tty_driver.send_xchar = NULL;
-	sclp_tty_driver.set_termios = NULL;
-	sclp_tty_driver.set_ldisc = NULL;
-	sclp_tty_driver.stop = NULL;
-	sclp_tty_driver.start = NULL;
-	sclp_tty_driver.hangup = NULL;
-	sclp_tty_driver.break_ctl = NULL;
-	sclp_tty_driver.wait_until_sent = NULL;
-	sclp_tty_driver.read_proc = NULL;
-	sclp_tty_driver.write_proc = NULL;
-
-	rc = tty_register_driver(&sclp_tty_driver);
-	if (rc)
+	driver->owner = THIS_MODULE;
+	driver->driver_name = "sclp_line";
+	driver->name = "ttyS";
+	driver->major = TTY_MAJOR;
+	driver->minor_start = 64;
+	driver->type = TTY_DRIVER_TYPE_SYSTEM;
+	driver->subtype = SYSTEM_TYPE_TTY;
+	driver->init_termios = tty_std_termios;
+	driver->init_termios.c_iflag = IGNBRK | IGNPAR;
+	driver->init_termios.c_oflag = ONLCR | XTABS;
+	driver->init_termios.c_lflag = ISIG | ECHO;
+	driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(driver, &sclp_ops);
+	rc = tty_register_driver(driver);
+	if (rc) {
 		printk(KERN_ERR SCLP_TTY_PRINT_HEADER
 		       "could not register tty - "
 		       "tty_register_driver returned %d\n", rc);
-	return rc;
+		put_tty_driver(driver);
+		return rc;
+	}
+	sclp_tty_driver = driver;
+	return 0;
 }
 module_init(sclp_tty_init);
diff -urN linux-2.5.70-bk16/drivers/s390/char/sclp_tty.h linux-2.5.70-bk17/drivers/s390/char/sclp_tty.h
--- linux-2.5.70-bk16/drivers/s390/char/sclp_tty.h	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/drivers/s390/char/sclp_tty.h	2003-06-12 04:49:58.000000000 -0700
@@ -66,6 +66,6 @@
 /* get the number of buffers/pages got from kernel at startup */
 #define TIOCSCLPGKBUF	_IOR(SCLP_IOCTL_LETTER, 20, unsigned short)
 
-extern struct tty_driver sclp_tty_driver;
+extern struct tty_driver *sclp_tty_driver;
 
 #endif	/* __SCLP_TTY_H__ */
diff -urN linux-2.5.70-bk16/drivers/s390/char/tuball.c linux-2.5.70-bk17/drivers/s390/char/tuball.c
--- linux-2.5.70-bk16/drivers/s390/char/tuball.c	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk17/drivers/s390/char/tuball.c	2003-06-12 04:49:58.000000000 -0700
@@ -147,8 +147,8 @@
 static struct tty_driver *tub3270_con_device(struct console *conp, int *index)
 {
 	*index = conp->index + 1;
-	extern struct tty_driver tty3270_driver;
-	return &tty3270_driver;
+	extern struct tty_driver *tty3270_driver;
+	return tty3270_driver;
 }
 
 static void
diff -urN linux-2.5.70-bk16/drivers/s390/char/tubio.h linux-2.5.70-bk17/drivers/s390/char/tubio.h
--- linux-2.5.70-bk16/drivers/s390/char/tubio.h	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/drivers/s390/char/tubio.h	2003-06-12 04:49:58.000000000 -0700
@@ -336,7 +336,7 @@
 extern int tty3270_major;
 extern int tty3270_proc_misc;
 extern enum tubwhat tty3270_proc_what;
-extern struct tty_driver tty3270_driver;
+extern struct tty_driver *tty3270_driver;
 
 #ifndef spin_trylock_irqsave
 #define spin_trylock_irqsave(lock, flags) \
@@ -380,7 +380,7 @@
 	unsigned int minor = minor(ip->i_rdev);
 	tub_t *tubp = NULL;
 	if (minor == 0 && current->tty) {
-		if (current->tty->driver == &tty3270_driver)
+		if (current->tty->driver == tty3270_driver)
 			minor = current->tty->index;
 	}
 	if (minor <= tubnummins && minor > 0)
diff -urN linux-2.5.70-bk16/drivers/s390/char/tubtty.c linux-2.5.70-bk17/drivers/s390/char/tubtty.c
--- linux-2.5.70-bk16/drivers/s390/char/tubtty.c	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk17/drivers/s390/char/tubtty.c	2003-06-12 04:49:58.000000000 -0700
@@ -48,113 +48,64 @@
 static int tty3270_show_tube(int, char *, int);
 
 static int tty3270_major = -1;
-struct tty_driver tty3270_driver;
-static int tty3270_refcount;
-static struct tty_struct *tty3270_table[TUBMAXMINS];
-static struct termios *tty3270_termios[TUBMAXMINS];
-static struct termios *tty3270_termios_locked[TUBMAXMINS];
-#ifdef CONFIG_TN3270_CONSOLE
-static int con3270_major = -1;
-static struct tty_driver con3270_driver;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
-static int con3270_refcount;
-static struct tty_struct *con3270_table[1];
-static struct termios *con3270_termios[1];
-static struct termios *con3270_termios_locked[1];
-#endif
-#endif /* CONFIG_TN3270_CONSOLE */
+struct tty_driver *tty3270_driver;
 
 static int tty3270_proc_index;
 static int tty3270_proc_data;
 static int tty3270_proc_misc;
 static enum tubwhat tty3270_proc_what;
 
+static struct tty_operations tty3270_ops = {
+	.open = tty3270_open,
+	.close = tty3270_close,
+	.write = tty3270_write,
+	.put_char = tty3270_put_char,
+	.flush_chars = tty3270_flush_chars,
+	.write_room = tty3270_write_room,
+	.chars_in_buffer = tty3270_chars_in_buffer,
+#if 0
+	.ioctl = tty3270_ioctl,
+#endif
+	.set_termios = tty3270_set_termios,
+	.hangup = tty3270_hangup,
+	.flush_buffer = tty3270_flush_buffer,
+	.read_proc = tty3270_read_proc,
+	.write_proc = tty3270_write_proc,
+};
+
 /*
  * tty3270_init() -- Register the tty3270 driver
  */
 int
 tty3270_init(void)
 {
-	struct tty_driver *td = &tty3270_driver;
+	struct tty_driver *td = alloc_tty_driver(TUBMAXMINS);
 	int rc;
 
+	if (!td)
+		return -ENOMEM;
+
 	/* Initialize for tty driver */
-	td->magic = TTY_DRIVER_MAGIC;
 	td->owner = THIS_MODULE;
 	td->driver_name = "tty3270";
 	td->name = "tty3270";
 	td->major = IBM_TTY3270_MAJOR;
 	td->minor_start = 0;
-	td->num = TUBMAXMINS;
 	td->type = TTY_DRIVER_TYPE_SYSTEM;
 	td->subtype = SYSTEM_TYPE_TTY;
 	td->init_termios = tty_std_termios;
-	td->flags = TTY_DRIVER_RESET_TERMIOS;
-	td->flags |= TTY_DRIVER_NO_DEVFS;
-	td->refcount = &tty3270_refcount;
-	td->table = tty3270_table;
-	td->termios = tty3270_termios;
-	td->termios_locked = tty3270_termios_locked;
-
-	td->open = tty3270_open;
-	td->close = tty3270_close;
-	td->write = tty3270_write;
-	td->put_char = tty3270_put_char;
-	td->flush_chars = tty3270_flush_chars;
-	td->write_room = tty3270_write_room;
-	td->chars_in_buffer = tty3270_chars_in_buffer;
-	td->ioctl = tty3270_ioctl;
-	td->ioctl = NULL;
-	td->set_termios = tty3270_set_termios;
-	td->throttle = NULL;
-	td->unthrottle = NULL;
-	td->stop = NULL;
-	td->start = NULL;
-	td->hangup = tty3270_hangup;
-	td->break_ctl = NULL;
-	td->flush_buffer = tty3270_flush_buffer;
-	td->set_ldisc = NULL;
-	td->wait_until_sent = NULL;
-	td->send_xchar = NULL;
-	td->read_proc = tty3270_read_proc;
-	td->write_proc = tty3270_write_proc;
-
+	td->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
+	tty_set_operations(td, &tty3270_ops);
 	rc = tty_register_driver(td);
 	if (rc) {
+		put_tty_driver(td);
 		printk(KERN_ERR "tty3270 registration failed with %d\n", rc);
 	} else {
 		tty3270_major = IBM_TTY3270_MAJOR;
 		if (td->proc_entry != NULL)
 			td->proc_entry->mode = S_IRUGO | S_IWUGO;
+		tty3270_driver = td;
 	}
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
-#ifdef CONFIG_TN3270_CONSOLE
-	if (CONSOLE_IS_3270) {
-		tty3270_con_driver = *td;
-		td = &tty3270_con_driver;
-		td->driver_name = "con3270";
-		td->name = "con3270";
-		td->major = MAJOR(S390_CONSOLE_DEV);
-		td->minor_start = MINOR(S390_CONSOLE_DEV);
-		td->num = 1;
-		td->refcount = &con3270_refcount;
-		td->table = con3270_table;
-		td->termios = con3270_termios;
-		td->termios_locked = con3270_termios_locked;
-
-		rc = tty_register_driver(td);
-		if (rc) {
-			printk(KERN_ERR
-			       "con3270 registration failed with %d\n", rc);
-		} else {
-			con3270_major = MAJOR(S390_CONSOLE_DEV);
-			if (td->proc_entry != NULL)
-				td->proc_entry->mode = S_IRUGO | S_IWUGO;
-		}
-	}
-#endif /* ifdef CONFIG_TN3270_CONSOLE */
-#endif /* if LINUX_VERSION_CODE */
-
 	return rc;
 }
 
@@ -165,15 +116,11 @@
 tty3270_fini(void)
 {
 	if (tty3270_major != -1) {
-		tty_unregister_driver(&tty3270_driver);
+		tty_unregister_driver(tty3270_driver);
+		put_tty_driver(tty3270_driver);
+		tty3270_driver = NULL;
 		tty3270_major = -1;
 	}
-#ifdef CONFIG_TN3270_CONSOLE
-	if (CONSOLE_IS_3270 && con3270_major != -1) {
-		tty_unregister_driver(&con3270_driver);
-		con3270_major = -1;
-	}
-#endif
 }
 
 static int 
@@ -537,7 +484,7 @@
 	 */
 	tubp = NULL;
 	tty = current->tty;
-	if (tty && tty->driver == &tty3270_driver)
+	if (tty && tty->driver == tty3270_driver)
 		tubp = (*tubminors)[tty->index];
 	if (tubp) {
 		if ((rc = tty3270_aid_set(tubp, mybuf, mycount + 1)))
diff -urN linux-2.5.70-bk16/drivers/s390/net/ctctty.c linux-2.5.70-bk17/drivers/s390/net/ctctty.c
--- linux-2.5.70-bk16/drivers/s390/net/ctctty.c	2003-06-12 04:49:50.000000000 -0700
+++ linux-2.5.70-bk17/drivers/s390/net/ctctty.c	2003-06-12 04:49:58.000000000 -0700
@@ -61,7 +61,6 @@
   struct sk_buff_head   tx_queue;        /* transmit queue                 */
   struct sk_buff_head   rx_queue;        /* receive queue                  */
   struct tty_struct 	*tty;            /* Pointer to corresponding tty   */
-  struct termios	normal_termios;  /* For saving termios structs     */
   wait_queue_head_t	open_wait;
   wait_queue_head_t	close_wait;
   struct semaphore      write_sem;
@@ -71,11 +70,7 @@
 
 /* Description of one CTC-tty */
 typedef struct {
-  int                refcount;			   /* Number of opens        */
-  struct tty_driver  ctc_tty_device;		   /* tty-device             */
-  struct tty_struct  *modem_table[CTC_TTY_MAX_DEVICES];
-  struct termios     *modem_termios[CTC_TTY_MAX_DEVICES];
-  struct termios     *modem_termios_locked[CTC_TTY_MAX_DEVICES];
+  struct tty_driver  *ctc_tty_device;		   /* tty-device             */
   ctc_tty_info       info[CTC_TTY_MAX_DEVICES];	   /* Private data           */
 } ctc_tty_driver;
 
@@ -998,10 +993,6 @@
 #endif
 		return retval;
 	}
-	if ((info->count == 1) && (info->flags & CTC_ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		ctc_tty_change_speed(info);
-	}
 #ifdef CTC_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "ctc_tty_open %s successful...\n", tty->name);
 #endif
@@ -1050,13 +1041,6 @@
 		return;
 	}
 	info->flags |= CTC_ASYNC_CLOSING;
-	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & CTC_ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-
 	tty->closing = 1;
 	/*
 	 * At this point we stop accepting input.  To do this, we
@@ -1146,6 +1130,21 @@
 	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
 }
 
+static struct tty_operations ctc_ops = {
+	.open = ctc_tty_open,
+	.close = ctc_tty_close,
+	.write = ctc_tty_write,
+	.flush_chars = ctc_tty_flush_chars,
+	.write_room = ctc_tty_write_room,
+	.chars_in_buffer = ctc_tty_chars_in_buffer,
+	.flush_buffer = ctc_tty_flush_buffer,
+	.ioctl = ctc_tty_ioctl,
+	.throttle = ctc_tty_throttle,
+	.unthrottle = ctc_tty_unthrottle,
+	.set_termios = ctc_tty_set_termios,
+	.hangup = ctc_tty_hangup,
+};
+
 int
 ctc_tty_init(void)
 {
@@ -1159,45 +1158,31 @@
 		return -ENOMEM;
 	}
 	memset(driver, 0, sizeof(ctc_tty_driver));
-	device = &driver->ctc_tty_device;
+	device = alloc_tty_driver(CTC_TTY_MAX_DEVICES);
+	if (!device) {
+		kfree(driver);
+		printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
+		return -ENOMEM;
+	}
 
-	device->magic = TTY_DRIVER_MAGIC;
 	device->devfs_name = "ctc/" CTC_TTY_NAME;
 	device->name = CTC_TTY_NAME;
 	device->major = CTC_TTY_MAJOR;
 	device->minor_start = 0;
-	device->num = CTC_TTY_MAX_DEVICES;
 	device->type = TTY_DRIVER_TYPE_SERIAL;
 	device->subtype = SERIAL_TYPE_NORMAL;
 	device->init_termios = tty_std_termios;
 	device->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	device->flags = TTY_DRIVER_REAL_RAW;
-	device->refcount = &driver->refcount;
-	device->table = driver->modem_table;
-	device->termios = driver->modem_termios;
-	device->termios_locked = driver->modem_termios_locked;
-	device->open = ctc_tty_open;
-	device->close = ctc_tty_close;
-	device->write = ctc_tty_write;
-	device->put_char = NULL;
-	device->flush_chars = ctc_tty_flush_chars;
-	device->write_room = ctc_tty_write_room;
-	device->chars_in_buffer = ctc_tty_chars_in_buffer;
-	device->flush_buffer = ctc_tty_flush_buffer;
-	device->ioctl = ctc_tty_ioctl;
-	device->throttle = ctc_tty_throttle;
-	device->unthrottle = ctc_tty_unthrottle;
-	device->set_termios = ctc_tty_set_termios;
-	device->stop = NULL;
-	device->start = NULL;
-	device->hangup = ctc_tty_hangup;
-	device->driver_name = "ctc_tty";
-
+	device->driver_name = "ctc_tty",
+	tty_set_operations(device, &ctc_ops);
 	if (tty_register_driver(device)) {
 		printk(KERN_WARNING "ctc_tty: Couldn't register serial-device\n");
+		put_tty_driver(device);
 		kfree(driver);
 		return -1;
 	}
+	driver->ctc_tty_device = device;
 	for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) {
 		info = &driver->info[i];
 		init_MUTEX(&info->write_sem);
@@ -1208,7 +1193,6 @@
 		info->tty = 0;
 		info->count = 0;
 		info->blocked_open = 0;
-		info->normal_termios = device->init_termios;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 		skb_queue_head_init(&info->tx_queue);
@@ -1279,8 +1263,9 @@
 	
 	spin_lock_irqsave(&ctc_tty_lock, saveflags);
 	ctc_tty_shuttingdown = 1;
-	tty_unregister_driver(&driver->ctc_tty_device);
+	tty_unregister_driver(driver->ctc_tty_device);
 	kfree(driver);
+	put_tty_driver(driver->ctc_tty_device);
 	driver = NULL;
 	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
 }
diff -urN linux-2.5.70-bk16/drivers/sbus/char/aurora.c linux-2.5.70-bk17/drivers/sbus/char/aurora.c
--- linux-2.5.70-bk16/drivers/sbus/char/aurora.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/sbus/char/aurora.c	2003-06-12 04:49:58.000000000 -0700
@@ -85,7 +85,7 @@
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #endif
 
-static struct tty_driver aurora_driver;
+static struct tty_driver *aurora_driver;
 static struct Aurora_board aurora_board[AURORA_NBOARD] = {
 	{0,},
 };
@@ -97,10 +97,6 @@
 /* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/
 static unsigned char * tmp_buf = NULL;
 static DECLARE_MUTEX(tmp_buf_sem);
-static int    aurora_refcount = 0;
-static struct tty_struct * aurora_table[AURORA_TNPORTS] = { NULL, };
-static struct termios * aurora_termios[AURORA_TNPORTS] = { NULL, };
-static struct termios * aurora_termios_locked[AURORA_TNPORTS] = { NULL, };
 
 DECLARE_TASK_QUEUE(tq_aurora);
 
@@ -1444,13 +1440,6 @@
 		return error;
 	}
 	
-	if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = port->normal_termios;
-		save_flags(flags); cli();
-		aurora_change_speed(bp, port);
-		restore_flags(flags);
-	}
-
 #ifdef AURORA_DEBUG
 	printk("aurora_open: end\n");
 #endif
@@ -1499,12 +1488,6 @@
 	}
 	port->flags |= ASYNC_CLOSING;
 
-	/* Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (port->flags & ASYNC_NORMAL_ACTIVE)
-		port->normal_termios = *tty->termios;
-
 	/* Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -2269,6 +2252,24 @@
 #endif
 }
 
+static struct tty_operations aurora_ops = {
+	.open  = aurora_open,
+	.close = aurora_close,
+	.write = aurora_write,
+	.put_char = aurora_put_char,
+	.flush_chars = aurora_flush_chars,
+	.write_room = aurora_write_room,
+	.chars_in_buffer = aurora_chars_in_buffer,
+	.flush_buffer = aurora_flush_buffer,
+	.ioctl = aurora_ioctl,
+	.throttle = aurora_throttle,
+	.unthrottle = aurora_unthrottle,
+	.set_termios = aurora_set_termios,
+	.stop = aurora_stop,
+	.start = aurora_start,
+	.hangup = aurora_hangup,
+};
+
 static int aurora_init_drivers(void)
 {
 	int error;
@@ -2283,42 +2284,25 @@
 		return 1;
 	}
 	init_bh(AURORA_BH, do_aurora_bh);
-/*	memset(IRQ_to_board, 0, sizeof(IRQ_to_board));*/
-	memset(&aurora_driver, 0, sizeof(aurora_driver));
-	aurora_driver.magic = TTY_DRIVER_MAGIC;
-	aurora_driver.owner = THIS_MODULE;
-	aurora_driver.name = "ttyA";
-	aurora_driver.major = AURORA_MAJOR;
-	aurora_driver.num = AURORA_TNPORTS;
-	aurora_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	aurora_driver.subtype = SERIAL_TYPE_NORMAL;
-	aurora_driver.init_termios = tty_std_termios;
-	aurora_driver.init_termios.c_cflag =
+	aurora_driver = alloc_tty_driver(AURORA_INPORTS);
+	if (!aurora_driver) {
+		printk(KERN_ERR "aurora: Couldn't allocate tty driver.\n");
+		free_page((unsigned long) tmp_buf);
+		return 1;
+	}
+	aurora_driver->owner = THIS_MODULE;
+	aurora_driver->name = "ttyA";
+	aurora_driver->major = AURORA_MAJOR;
+	aurora_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	aurora_driver->subtype = SERIAL_TYPE_NORMAL;
+	aurora_driver->init_termios = tty_std_termios;
+	aurora_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	aurora_driver.flags = TTY_DRIVER_REAL_RAW;
-	aurora_driver.refcount = &aurora_refcount;
-	aurora_driver.table = aurora_table;
-	aurora_driver.termios = aurora_termios;
-	aurora_driver.termios_locked = aurora_termios_locked;
-
-	aurora_driver.open  = aurora_open;
-	aurora_driver.close = aurora_close;
-	aurora_driver.write = aurora_write;
-	aurora_driver.put_char = aurora_put_char;
-	aurora_driver.flush_chars = aurora_flush_chars;
-	aurora_driver.write_room = aurora_write_room;
-	aurora_driver.chars_in_buffer = aurora_chars_in_buffer;
-	aurora_driver.flush_buffer = aurora_flush_buffer;
-	aurora_driver.ioctl = aurora_ioctl;
-	aurora_driver.throttle = aurora_throttle;
-	aurora_driver.unthrottle = aurora_unthrottle;
-	aurora_driver.set_termios = aurora_set_termios;
-	aurora_driver.stop = aurora_stop;
-	aurora_driver.start = aurora_start;
-	aurora_driver.hangup = aurora_hangup;
-
-	error = tty_register_driver(&aurora_driver);
+	aurora_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(aurora_driver, &aurora_ops);
+	error = tty_register_driver(aurora_driver);
 	if (error) {
+		put_tty_driver(aurora_driver);
 		free_page((unsigned long) tmp_buf);
 		printk(KERN_ERR "aurora: Couldn't register aurora driver, error = %d\n",
 		       error);
@@ -2327,7 +2311,6 @@
 	
 	memset(aurora_port, 0, sizeof(aurora_port));
 	for (i = 0; i < AURORA_TNPORTS; i++)  {
-		aurora_port[i].normal_termios  = aurora_driver.init_termios;
 		aurora_port[i].magic = AURORA_MAGIC;
 		aurora_port[i].tqueue.routine = do_softint;
 		aurora_port[i].tqueue.data = &aurora_port[i];
@@ -2350,7 +2333,8 @@
 	printk("aurora_release_drivers: start\n");
 #endif
 	free_page((unsigned long)tmp_buf);
-	tty_unregister_driver(&aurora_driver);
+	tty_unregister_driver(aurora_driver);
+	put_tty_driver(aurora_driver);
 #ifdef AURORA_DEBUG
 	printk("aurora_release_drivers: end\n");
 #endif
diff -urN linux-2.5.70-bk16/drivers/sbus/char/aurora.h linux-2.5.70-bk17/drivers/sbus/char/aurora.h
--- linux-2.5.70-bk16/drivers/sbus/char/aurora.h	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/sbus/char/aurora.h	2003-06-12 04:49:58.000000000 -0700
@@ -252,7 +252,6 @@
 	int			xmit_head;
 	int			xmit_tail;
 	int			xmit_cnt;
-	struct termios          normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 	struct tq_struct	tqueue;
diff -urN linux-2.5.70-bk16/drivers/serial/68328serial.c linux-2.5.70-bk17/drivers/serial/68328serial.c
--- linux-2.5.70-bk16/drivers/serial/68328serial.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/serial/68328serial.c	2003-06-12 04:49:59.000000000 -0700
@@ -83,8 +83,7 @@
 extern wait_queue_head_t keypress_wait; 
 #endif
 
-struct tty_driver serial_driver;
-static int serial_refcount;
+struct tty_driver *serial_driver;
 
 /* serial subtype definitions */
 #define SERIAL_TYPE_NORMAL	1
@@ -105,10 +104,6 @@
 
 static void change_speed(struct m68k_serial *info);
 
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
 /*
  *	Setup for console. Argument comes from the boot command line.
  */
@@ -1172,12 +1167,6 @@
 	}
 	info->flags |= S_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & S_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -1363,17 +1352,7 @@
 	if (retval)
 		return retval;
 
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-		return retval;
-	}
-
-	if ((info->count == 1) && (info->flags & S_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		change_speed(info);
-	}
-
-	return 0;
+	return block_til_ready(tty, filp, info);
 }
 
 /* Finally, routines used to initialize the serial driver. */
@@ -1436,53 +1415,56 @@
 #endif
 
 
+static struct tty_operations rs_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.set_ldisc = rs_set_ldisc,
+};
+
 /* rs_init inits the driver */
 static int __init
 rs68328_init(void)
 {
 	int flags, i;
 	struct m68k_serial *info;
-	
+
+	serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!serial_driver)
+		return -ENOMEM;
+
 	show_serial_version();
 
 	/* Initialize the tty_driver structure */
 	/* SPARC: Not all of this is exactly right for us. */
 	
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NR_PORTS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag = 
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag = 
 			m68328_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_open;
-	serial_driver.close = rs_close;
-	serial_driver.write = rs_write;
-	serial_driver.flush_chars = rs_flush_chars;
-	serial_driver.write_room = rs_write_room;
-	serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	serial_driver.flush_buffer = rs_flush_buffer;
-	serial_driver.ioctl = rs_ioctl;
-	serial_driver.throttle = rs_throttle;
-	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.set_termios = rs_set_termios;
-	serial_driver.stop = rs_stop;
-	serial_driver.start = rs_start;
-	serial_driver.hangup = rs_hangup;
-	serial_driver.set_ldisc = rs_set_ldisc;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &rs_ops);
 
-	if (tty_register_driver(&serial_driver))
-		panic("Couldn't register serial driver\n");
+	if (tty_register_driver(serial_driver)) {
+		put_tty_driver(serial_driver);
+		printk(KERN_ERR "Couldn't register serial driver\n");
+		return -ENOMEM;
+	}
 
 	save_flags(flags); cli();
 
@@ -1502,13 +1484,12 @@
 	    info->blocked_open = 0;
 	    INIT_WORK(&info->tqueue, do_softint, info);
 	    INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);
-	    info->normal_termios = serial_driver.init_termios;
 	    init_waitqueue_head(&info->open_wait);
 	    init_waitqueue_head(&info->close_wait);
 	    info->line = i;
 	    info->is_cons = 1; /* Means shortcuts work */
 	    
-	    printk("%s%d at 0x%08x (irq = %d)", serial_driver.name, info->line, 
+	    printk("%s%d at 0x%08x (irq = %d)", serial_driver->name, info->line, 
 		   info->port, info->irq);
 	    printk(" is a builtin MC68328 UART\n");
 	    
@@ -1615,7 +1596,7 @@
 static struct tty_driver *m68328_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 
diff -urN linux-2.5.70-bk16/drivers/serial/68328serial.h linux-2.5.70-bk17/drivers/serial/68328serial.h
--- linux-2.5.70-bk16/drivers/serial/68328serial.h	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/serial/68328serial.h	2003-06-12 04:49:59.000000000 -0700
@@ -161,7 +161,6 @@
 	int			xmit_cnt;
 	struct work_struct	tqueue;
 	struct work_struct	tqueue_hangup;
-	struct termios		normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 };
diff -urN linux-2.5.70-bk16/drivers/serial/68360serial.c linux-2.5.70-bk17/drivers/serial/68360serial.c
--- linux-2.5.70-bk16/drivers/serial/68360serial.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/serial/68360serial.c	2003-06-12 04:49:59.000000000 -0700
@@ -73,8 +73,7 @@
 static char *serial_name = "CPM UART driver";
 static char *serial_version = "0.03";
 
-static struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 int serial_console_setup(struct console *co, char *options);
 
 /*
@@ -163,7 +162,6 @@
         unsigned short  close_delay;
         unsigned short  closing_wait; /* time to wait before closing */
         struct async_icount_24     icount; 
-        struct termios          normal_termios;
         int     io_type;
         struct async_struct *info;
 };
@@ -216,10 +214,6 @@
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
 
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
 /* The number of buffer descriptors and their sizes.
  */
 #define RX_NUM_FIFO	4
@@ -1709,12 +1703,6 @@
 	}
 	info->flags |= ASYNC_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->state->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -2036,12 +2024,6 @@
 		return retval;
 	}
 
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->state->normal_termios;
-		change_speed(info);
-	}
-
 #ifdef SERIAL_DEBUG_OPEN
 	printk("rs_open %s successful...", tty->name);
 #endif
@@ -2480,7 +2462,7 @@
 static struct tty_struct *serial_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 
@@ -2513,6 +2495,25 @@
 */
 static	int	baud_idx;
 
+static struct tty_operations rs_360_ops = {
+	.open = rs_360_open,
+	.close = rs_360_close,
+	.write = rs_360_write,
+	.put_char = rs_360_put_char,
+	.write_room = rs_360_write_room,
+	.chars_in_buffer = rs_360_chars_in_buffer,
+	.flush_buffer = rs_360_flush_buffer,
+	.ioctl = rs_360_ioctl,
+	.throttle = rs_360_throttle,
+	.unthrottle = rs_360_unthrottle,
+	/* .send_xchar = rs_360_send_xchar, */
+	.set_termios = rs_360_set_termios,
+	.stop = rs_360_stop,
+	.start = rs_360_start,
+	.hangup = rs_360_hangup,
+	/* .wait_until_sent = rs_360_wait_until_sent, */
+	/* .read_proc = rs_360_read_proc, */
+};
 
 /* int __init rs_360_init(void) */
 int rs_360_init(void)
@@ -2531,49 +2532,24 @@
 	volatile	struct uart_pram	*sup;
 	/* volatile	immap_t		*immap; */
 	
-	show_serial_version();
+	serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!serial_driver)
+		return -1;
 
-	/* Initialize the tty_driver structure */
-	
-	/* __clear_user(&serial_driver,sizeof(struct tty_driver)); */
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
+	show_serial_version();
 
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	/* serial_driver.driver_name = "serial"; */
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NR_PORTS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_360_open;
-	serial_driver.close = rs_360_close;
-	serial_driver.write = rs_360_write;
-	serial_driver.put_char = rs_360_put_char;
-	serial_driver.write_room = rs_360_write_room;
-	serial_driver.chars_in_buffer = rs_360_chars_in_buffer;
-	serial_driver.flush_buffer = rs_360_flush_buffer;
-	serial_driver.ioctl = rs_360_ioctl;
-	serial_driver.throttle = rs_360_throttle;
-	serial_driver.unthrottle = rs_360_unthrottle;
-	/* serial_driver.send_xchar = rs_360_send_xchar; */
-	serial_driver.set_termios = rs_360_set_termios;
-	serial_driver.stop = rs_360_stop;
-	serial_driver.start = rs_360_start;
-	serial_driver.hangup = rs_360_hangup;
-	/* serial_driver.wait_until_sent = rs_360_wait_until_sent; */
-	/* serial_driver.read_proc = rs_360_read_proc; */
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &rs_360_ops);
 	
-	if (tty_register_driver(&serial_driver))
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 
 	cp = pquicc;	/* Get pointer to Communication Processor */
@@ -2633,7 +2609,6 @@
 		state->custom_divisor = 0;
 		state->close_delay = 5*HZ/10;
 		state->closing_wait = 30*HZ;
-		state->normal_termios = serial_driver.init_termios;
 		state->icount.cts = state->icount.dsr = 
 			state->icount.rng = state->icount.dcd = 0;
 		state->icount.rx = state->icount.tx = 0;
@@ -2882,7 +2857,7 @@
 			/* cpm_install_handler(IRQ_MACHSPEC | state->irq, rs_360_interrupt, info);  */
 			/*request_irq(IRQ_MACHSPEC | state->irq, rs_360_interrupt, */
 			request_irq(state->irq, rs_360_interrupt,
-						IRQ_FLG_LOCK, serial_driver.name, (void *)info);
+						IRQ_FLG_LOCK, "ttyS", (void *)info);
 
 			/* Set up the baud rate generator.
 			*/
diff -urN linux-2.5.70-bk16/drivers/serial/core.c linux-2.5.70-bk17/drivers/serial/core.c
--- linux-2.5.70-bk16/drivers/serial/core.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/serial/core.c	2003-06-12 04:49:59.000000000 -0700
@@ -2061,6 +2061,32 @@
 	up(&state->sem);
 }
 
+static struct tty_operations uart_ops = {
+	.open		= uart_open,
+	.close		= uart_close,
+	.write		= uart_write,
+	.put_char	= uart_put_char,
+	.flush_chars	= uart_flush_chars,
+	.write_room	= uart_write_room,
+	.chars_in_buffer= uart_chars_in_buffer,
+	.flush_buffer	= uart_flush_buffer,
+	.ioctl		= uart_ioctl,
+	.throttle	= uart_throttle,
+	.unthrottle	= uart_unthrottle,
+	.send_xchar	= uart_send_xchar,
+	.set_termios	= uart_set_termios,
+	.stop		= uart_stop,
+	.start		= uart_start,
+	.hangup		= uart_hangup,
+	.break_ctl	= uart_break_ctl,
+	.wait_until_sent= uart_wait_until_sent,
+#ifdef CONFIG_PROC_FS
+	.read_proc	= uart_read_proc,
+#endif
+	.tiocmget	= uart_tiocmget,
+	.tiocmset	= uart_tiocmset,
+};
+
 /**
  *	uart_register_driver - register a driver with the uart core layer
  *	@drv: low level driver structure
@@ -2077,83 +2103,40 @@
 int uart_register_driver(struct uart_driver *drv)
 {
 	struct tty_driver *normal = NULL;
-	struct termios **termios = NULL;
 	int i, retval;
 
 	BUG_ON(drv->state);
 
 	/*
 	 * Maybe we should be using a slab cache for this, especially if
-	 * we have a large number of ports to handle.  Note that we also
-	 * allocate space for an integer for reference counting.
+	 * we have a large number of ports to handle.
 	 */
-	drv->state = kmalloc(sizeof(struct uart_state) * drv->nr +
-			     sizeof(int), GFP_KERNEL);
+	drv->state = kmalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
 	retval = -ENOMEM;
 	if (!drv->state)
 		goto out;
 
-	memset(drv->state, 0, sizeof(struct uart_state) * drv->nr +
-			sizeof(int));
-
-	termios = kmalloc(sizeof(struct termios *) * drv->nr * 2 +
-			  sizeof(struct tty_struct *) * drv->nr, GFP_KERNEL);
-	if (!termios)
-		goto out;
-
-	memset(termios, 0, sizeof(struct termios *) * drv->nr * 2 +
-			   sizeof(struct tty_struct *) * drv->nr);
+	memset(drv->state, 0, sizeof(struct uart_state) * drv->nr);
 
-	normal  = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
+	normal  = alloc_tty_driver(drv->nr);
 	if (!normal)
 		goto out;
 
-	memset(normal, 0, sizeof(struct tty_driver));
-
 	drv->tty_driver = normal;
 
-	normal->magic		= TTY_DRIVER_MAGIC;
 	normal->owner		= drv->owner;
 	normal->driver_name	= drv->driver_name;
 	normal->devfs_name	= drv->devfs_name;
 	normal->name		= drv->dev_name;
 	normal->major		= drv->major;
 	normal->minor_start	= drv->minor;
-	normal->num		= drv->nr;
 	normal->type		= TTY_DRIVER_TYPE_SERIAL;
 	normal->subtype		= SERIAL_TYPE_NORMAL;
 	normal->init_termios	= tty_std_termios;
 	normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	normal->flags		= TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-	normal->refcount	= (int *)(drv->state + drv->nr);
-	normal->termios		= termios;
-	normal->termios_locked	= termios + drv->nr;
-	normal->table		= (struct tty_struct **)(termios + drv->nr * 2);
 	normal->driver_state    = drv;
-
-	normal->open		= uart_open;
-	normal->close		= uart_close;
-	normal->write		= uart_write;
-	normal->put_char	= uart_put_char;
-	normal->flush_chars	= uart_flush_chars;
-	normal->write_room	= uart_write_room;
-	normal->chars_in_buffer	= uart_chars_in_buffer;
-	normal->flush_buffer	= uart_flush_buffer;
-	normal->ioctl		= uart_ioctl;
-	normal->throttle	= uart_throttle;
-	normal->unthrottle	= uart_unthrottle;
-	normal->send_xchar	= uart_send_xchar;
-	normal->set_termios	= uart_set_termios;
-	normal->stop		= uart_stop;
-	normal->start		= uart_start;
-	normal->hangup		= uart_hangup;
-	normal->break_ctl	= uart_break_ctl;
-	normal->wait_until_sent	= uart_wait_until_sent;
-#ifdef CONFIG_PROC_FS
-	normal->read_proc	= uart_read_proc;
-#endif
-	normal->tiocmget	= uart_tiocmget;
-	normal->tiocmset	= uart_tiocmset;
+	tty_set_operations(normal, &uart_ops);
 
 	/*
 	 * Initialise the UART state(s).
@@ -2170,9 +2153,8 @@
 	retval = tty_register_driver(normal);
  out:
 	if (retval < 0) {
-		kfree(normal);
+		put_tty_driver(normal);
 		kfree(drv->state);
-		kfree(termios);
 	}
 	return retval;
 }
@@ -2190,9 +2172,8 @@
 {
 	struct tty_driver *p = drv->tty_driver;
 	tty_unregister_driver(p);
+	put_tty_driver(p);
 	kfree(drv->state);
-	kfree(p->termios);
-	kfree(p);
 	drv->tty_driver = NULL;
 }
 
diff -urN linux-2.5.70-bk16/drivers/serial/mcfserial.c linux-2.5.70-bk17/drivers/serial/mcfserial.c
--- linux-2.5.70-bk16/drivers/serial/mcfserial.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/serial/mcfserial.c	2003-06-12 04:49:59.000000000 -0700
@@ -76,12 +76,8 @@
 /*
  *	Driver data structures.
  */
-struct tty_driver	mcfrs_serial_driver;
-static int		mcfrs_serial_refcount;
+static struct tty_driver *mcfrs_serial_driver;
 
-/* serial subtype definitions */
-#define SERIAL_TYPE_NORMAL	1
-  
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
 
@@ -109,10 +105,6 @@
 
 #define	NR_PORTS	(sizeof(mcfrs_table) / sizeof(struct mcf_serial))
 
-static struct tty_struct	*mcfrs_serial_table[NR_PORTS];
-static struct termios		*mcfrs_serial_termios[NR_PORTS];
-static struct termios		*mcfrs_serial_termios_locked[NR_PORTS];
-
 /*
  * This is used to figure out the divisor speeds and the timeouts.
  */
@@ -1190,13 +1182,6 @@
 	info->flags |= ASYNC_CLOSING;
 
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -1408,11 +1393,6 @@
 		return retval;
 	}
 
-	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		mcfrs_change_speed(info);
-	}
-
 #ifdef SERIAL_DEBUG_OPEN
 	printk("mcfrs_open %s successful...\n", tty->name);
 #endif
@@ -1562,6 +1542,24 @@
 	printk(mcfrs_drivername);
 }
 
+static struct tty_operations mcfrs_ops = {
+	.open = mcfrs_open,
+	.close = mcfrs_close,
+	.write = mcfrs_write,
+	.flush_chars = mcfrs_flush_chars,
+	.write_room = mcfrs_write_room,
+	.chars_in_buffer = mcfrs_chars_in_buffer,
+	.flush_buffer = mcfrs_flush_buffer,
+	.ioctl = mcfrs_ioctl,
+	.throttle = mcfrs_throttle,
+	.unthrottle = mcfrs_unthrottle,
+	.set_termios = mcfrs_set_termios,
+	.stop = mcfrs_stop,
+	.start = mcfrs_start,
+	.hangup = mcfrs_hangup,
+	.read_proc = mcfrs_readproc,
+}
+
 /* mcfrs_init inits the driver */
 static int __init
 mcfrs_init(void)
@@ -1579,47 +1577,30 @@
 	add_timer(&mcfrs_timer_struct);
 	mcfrs_ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1);
 #endif
+	mcfrs_serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!mcfrs_serial_driver)
+		return -ENOMEM;
 
 	show_serial_version();
 
 	/* Initialize the tty_driver structure */
-	memset(&mcfrs_serial_driver, 0, sizeof(struct tty_driver));
-	mcfrs_serial_driver.magic = TTY_DRIVER_MAGIC;
-	mcfrs_serial_driver.name = "ttyS";
-	mcfrs_serial_driver.major = TTY_MAJOR;
-	mcfrs_serial_driver.minor_start = 64;
-	mcfrs_serial_driver.num = NR_PORTS;
-	mcfrs_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	mcfrs_serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	mcfrs_serial_driver.init_termios = tty_std_termios;
+	mcfrs_serial_driver->name = "ttyS";
+	mcfrs_serial_driver->driver_name = "serial";
+	mcfrs_serial_driver->major = TTY_MAJOR;
+	mcfrs_serial_driver->minor_start = 64;
+	mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	mcfrs_serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	mcfrs_serial_driver->init_termios = tty_std_termios;
 
-	mcfrs_serial_driver.init_termios.c_cflag =
+	mcfrs_serial_driver->init_termios.c_cflag =
 		mcfrs_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL;
-	mcfrs_serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	mcfrs_serial_driver.refcount = &mcfrs_serial_refcount;
-	mcfrs_serial_driver.table = mcfrs_serial_table;
-	mcfrs_serial_driver.termios = mcfrs_serial_termios;
-	mcfrs_serial_driver.termios_locked = mcfrs_serial_termios_locked;
-
-	mcfrs_serial_driver.open = mcfrs_open;
-	mcfrs_serial_driver.close = mcfrs_close;
-	mcfrs_serial_driver.write = mcfrs_write;
-	mcfrs_serial_driver.flush_chars = mcfrs_flush_chars;
-	mcfrs_serial_driver.write_room = mcfrs_write_room;
-	mcfrs_serial_driver.chars_in_buffer = mcfrs_chars_in_buffer;
-	mcfrs_serial_driver.flush_buffer = mcfrs_flush_buffer;
-	mcfrs_serial_driver.ioctl = mcfrs_ioctl;
-	mcfrs_serial_driver.throttle = mcfrs_throttle;
-	mcfrs_serial_driver.unthrottle = mcfrs_unthrottle;
-	mcfrs_serial_driver.set_termios = mcfrs_set_termios;
-	mcfrs_serial_driver.stop = mcfrs_stop;
-	mcfrs_serial_driver.start = mcfrs_start;
-	mcfrs_serial_driver.hangup = mcfrs_hangup;
-	mcfrs_serial_driver.read_proc = mcfrs_readproc;
-	mcfrs_serial_driver.driver_name = "serial";
+	mcfrs_serial_driver->flags = TTY_DRIVER_REAL_RAW;
+
+	tty_set_operations(mcfrs_serial_driver, &mcfrs_ops);
 
-	if (tty_register_driver(&mcfrs_serial_driver)) {
+	if (tty_register_driver(mcfrs_serial_driver)) {
 		printk("MCFRS: Couldn't register serial driver\n");
+		put_tty_driver(mcfrs_serial_driver);
 		return(-EBUSY);
 	}
 
@@ -1641,7 +1622,6 @@
 		info->blocked_open = 0;
 		INIT_WORK(&info->tqueue, mcfrs_offintr, info);
 		INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info);
-		info->normal_termios = mcfrs_serial_driver.init_termios;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 
@@ -1649,8 +1629,7 @@
 		mcfrs_setsignals(info, 0, 0);
 		mcfrs_irqinit(info);
 
-		printk("%s%d at 0x%04x (irq = %d)", mcfrs_serial_driver.name,
-			info->line, info->addr, info->irq);
+		printk("ttyS%d at 0x%04x (irq = %d)", info->line, info->addr, info->irq);
 		printk(" is a builtin ColdFire UART\n");
 	}
 
@@ -1742,7 +1721,7 @@
 static struct tty_driver *mcfrs_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &mcfrs_serial_driver;
+	return mcfrs_serial_driver;
 }
 
 
diff -urN linux-2.5.70-bk16/drivers/serial/mcfserial.h linux-2.5.70-bk17/drivers/serial/mcfserial.h
--- linux-2.5.70-bk16/drivers/serial/mcfserial.h	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/serial/mcfserial.h	2003-06-12 04:49:59.000000000 -0700
@@ -65,7 +65,6 @@
 	struct mcf_stats	stats;
 	struct work_struct	tqueue;
 	struct work_struct	tqueue_hangup;
-	struct termios		normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 
diff -urN linux-2.5.70-bk16/drivers/sgi/char/sgiserial.c linux-2.5.70-bk17/drivers/sgi/char/sgiserial.c
--- linux-2.5.70-bk16/drivers/sgi/char/sgiserial.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/sgi/char/sgiserial.c	2003-06-12 04:49:59.000000000 -0700
@@ -97,9 +97,8 @@
 
 DECLARE_TASK_QUEUE(tq_serial);
 
-struct tty_driver serial_driver;
+static struct tty_driver *serial_driver;
 struct console *sgisercon;
-static int serial_refcount;
 
 /* serial subtype definitions */
 #define SERIAL_TYPE_NORMAL	1
@@ -121,10 +120,6 @@
 
 static void change_speed(struct sgi_serial *info);
 
-static struct tty_struct *serial_table[NUM_CHANNELS];
-static struct termios *serial_termios[NUM_CHANNELS];
-static struct termios *serial_termios_locked[NUM_CHANNELS];
-
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
@@ -1508,12 +1503,6 @@
 	}
 	info->flags |= ZILOG_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ZILOG_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -1728,11 +1717,6 @@
 		return retval;
 	}
 
-	if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		change_speed(info);
-	}
-
 	/* If this is the serial console change the speed to 
 	 * the right value
 	 */
@@ -1810,7 +1794,22 @@
 	}
 }
 
-volatile int test_done;
+static struct tty_operations serial_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+};
 
 /* rs_init inits the driver */
 int rs_init(void)
@@ -1818,6 +1817,9 @@
 	int chip, channel, i, flags;
 	struct sgi_serial *info;
 
+	serial_driver = tty_alloc_serial(NUM_CHANNELS);
+	if (!serial_driver)
+		return -ENOMEM;
 
 	/* Setup base handler, and timer table. */
 	init_bh(SERIAL_BH, do_serial_bh);
@@ -1826,42 +1828,22 @@
 
 	/* Initialize the tty_driver structure */
 	/* SGI: Not all of this is exactly right for us. */
-	
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.owner = THIS_MODULE;
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NUM_CHANNELS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
 
-	serial_driver.init_termios.c_cflag =
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+
+	serial_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_open;
-	serial_driver.close = rs_close;
-	serial_driver.write = rs_write;
-	serial_driver.flush_chars = rs_flush_chars;
-	serial_driver.write_room = rs_write_room;
-	serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	serial_driver.flush_buffer = rs_flush_buffer;
-	serial_driver.ioctl = rs_ioctl;
-	serial_driver.throttle = rs_throttle;
-	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.set_termios = rs_set_termios;
-	serial_driver.stop = rs_stop;
-	serial_driver.start = rs_start;
-	serial_driver.hangup = rs_hangup;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+
+	tty_set_operations(serial_driver, &serial_ops);
 
-	if (tty_register_driver(&serial_driver))
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 
 	save_flags(flags); cli();
@@ -1950,7 +1932,6 @@
 		info->tqueue.data = info;
 		info->tqueue_hangup.routine = do_serial_hangup;
 		info->tqueue_hangup.data = info;
-		info->normal_termios = serial_driver.init_termios;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 		printk("tty%02d at 0x%04x (irq = %d)", info->line, 
@@ -2063,7 +2044,7 @@
 static struct tty_driver *zs_console_device(struct console *con, int *index)
 {
 	*index = con->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 
diff -urN linux-2.5.70-bk16/drivers/sgi/char/sgiserial.h linux-2.5.70-bk17/drivers/sgi/char/sgiserial.h
--- linux-2.5.70-bk16/drivers/sgi/char/sgiserial.h	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/sgi/char/sgiserial.h	2003-06-12 04:49:59.000000000 -0700
@@ -154,7 +154,6 @@
 	int			xmit_cnt;
 	struct tq_struct	tqueue;
 	struct tq_struct	tqueue_hangup;
-	struct termios		normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 };
diff -urN linux-2.5.70-bk16/drivers/tc/zs.c linux-2.5.70-bk17/drivers/tc/zs.c
--- linux-2.5.70-bk16/drivers/tc/zs.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/tc/zs.c	2003-06-12 04:49:59.000000000 -0700
@@ -180,8 +180,7 @@
 
 DECLARE_TASK_QUEUE(tq_zs_serial);
 
-struct tty_driver serial_driver;
-static int serial_refcount;
+static struct tty_driver *serial_driver;
 
 /* serial subtype definitions */
 #define SERIAL_TYPE_NORMAL	1
@@ -213,10 +212,6 @@
 static void change_speed(struct dec_serial *info);
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
 
-static struct tty_struct *serial_table[NUM_CHANNELS];
-static struct termios *serial_termios[NUM_CHANNELS];
-static struct termios *serial_termios_locked[NUM_CHANNELS];
-
 #ifndef MIN
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
@@ -1391,12 +1386,6 @@
 	}
 	info->flags |= ZILOG_CLOSING;
 	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ZILOG_NORMAL_ACTIVE)
-		info->normal_termios = *tty->termios;
-	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
@@ -1661,10 +1650,6 @@
 		return retval;
 	}
 
-	if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) {
-		*tty->termios = info->normal_termios;
-		change_speed(info);
-	}
 #ifdef CONFIG_SERIAL_CONSOLE
 	if (sercons.cflag && sercons.index == line) {
 		tty->termios->c_cflag = sercons.cflag;
@@ -1815,6 +1800,25 @@
 	restore_flags(flags); */
 }
 
+static struct tty_operations serial_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.break_ctl = rs_break,
+	.wait_until_sent = rs_wait_until_sent,
+};
+
 /* zs_init inits the driver */
 int __init zs_init(void)
 {
@@ -1832,49 +1836,29 @@
 	if (zs_chain == 0)
 		probe_sccs();
 
+	serial_driver = alloc_tty_driver(zs_channels_found);
+	if (!serial_driver)
+		return -ENOMEM;
+
 	show_serial_version();
 
 	/* Initialize the tty_driver structure */
 	/* Not all of this is exactly right for us. */
 
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.owner = THIS_MODULE;
-	serial_driver.devfs_name = "tts/";
-	serial_driver.name = "ttyS";
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = zs_channels_found;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-
-	serial_driver.init_termios.c_cflag =
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->devfs_name = "tts/";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_open;
-	serial_driver.close = rs_close;
-	serial_driver.write = rs_write;
-	serial_driver.flush_chars = rs_flush_chars;
-	serial_driver.write_room = rs_write_room;
-	serial_driver.chars_in_buffer = rs_chars_in_buffer;
-	serial_driver.flush_buffer = rs_flush_buffer;
-	serial_driver.ioctl = rs_ioctl;
-	serial_driver.throttle = rs_throttle;
-	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.set_termios = rs_set_termios;
-	serial_driver.stop = rs_stop;
-	serial_driver.start = rs_start;
-	serial_driver.hangup = rs_hangup;
-	serial_driver.break_ctl = rs_break;
-	serial_driver.wait_until_sent = rs_wait_until_sent;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	tty_set_operations(serial_driver, &serial_ops);
 
-	if (tty_register_driver(&serial_driver))
+	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
 
 	save_flags(flags); cli();
@@ -1913,13 +1897,12 @@
 		info->blocked_open = 0;
 		info->tqueue.routine = do_softint;
 		info->tqueue.data = info;
-		info->normal_termios = serial_driver.init_termios;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
 		printk("ttyS%02d at 0x%08x (irq = %d)", info->line, 
 		       info->port, info->irq);
 		printk(" is a Z85C30 SCC\n");
-		tty_register_device(&serial_driver, info->line, NULL);
+		tty_register_device(serial_driver, info->line, NULL);
 	}
 
 	restore_flags(flags);
@@ -2071,7 +2054,7 @@
 static struct tty_driver *serial_console_device(struct console *c, int *index)
 {
 	*index = c->index;
-	return &serial_driver;
+	return serial_driver;
 }
 
 /*
diff -urN linux-2.5.70-bk16/drivers/tc/zs.h linux-2.5.70-bk17/drivers/tc/zs.h
--- linux-2.5.70-bk16/drivers/tc/zs.h	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/tc/zs.h	2003-06-12 04:49:59.000000000 -0700
@@ -150,7 +150,6 @@
 	int			xmit_cnt;
 	struct tq_struct	tqueue;
 	struct tq_struct	tqueue_hangup;
-	struct termios		normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 };
diff -urN linux-2.5.70-bk16/drivers/usb/class/bluetty.c linux-2.5.70-bk17/drivers/usb/class/bluetty.c
--- linux-2.5.70-bk16/drivers/usb/class/bluetty.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/usb/class/bluetty.c	2003-06-12 04:49:59.000000000 -0700
@@ -241,11 +241,7 @@
 	.id_table =	usb_bluetooth_ids,
 };
 
-static int			bluetooth_refcount;
-static struct tty_driver	bluetooth_tty_driver;
-static struct tty_struct *	bluetooth_tty[BLUETOOTH_TTY_MINORS];
-static struct termios *		bluetooth_termios[BLUETOOTH_TTY_MINORS];
-static struct termios *		bluetooth_termios_locked[BLUETOOTH_TTY_MINORS];
+static struct tty_driver	*bluetooth_tty_driver;
 static struct usb_bluetooth	*bluetooth_table[BLUETOOTH_TTY_MINORS];
 
 
@@ -1199,7 +1195,7 @@
 		     bluetooth, endpoint->bInterval);
 
 	/* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */
-	tty_register_device (&bluetooth_tty_driver, minor, &intf->dev);
+	tty_register_device (bluetooth_tty_driver, minor, &intf->dev);
 	info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor);
 
 	bluetooth_table[minor] = bluetooth;
@@ -1264,7 +1260,7 @@
 		if (bluetooth->interrupt_in_buffer)
 			kfree (bluetooth->interrupt_in_buffer);
 
-		tty_unregister_device (&bluetooth_tty_driver, bluetooth->minor);
+		tty_unregister_device (bluetooth_tty_driver, bluetooth->minor);
 
 		for (i = 0; i < NUM_BULK_URBS; ++i) {
 			if (bluetooth->write_urb_pool[i]) {
@@ -1294,24 +1290,7 @@
 	}
 }
 
-
-static struct tty_driver bluetooth_tty_driver = {
-	.magic =		TTY_DRIVER_MAGIC,
-	.owner =		THIS_MODULE,
-	.driver_name =		"usb-bluetooth",
-	.name =			"usb/ttub/",
-	.major =		BLUETOOTH_TTY_MAJOR,
-	.minor_start =		0,
-	.num =			BLUETOOTH_TTY_MINORS,
-	.type =			TTY_DRIVER_TYPE_SERIAL,
-	.subtype =		SERIAL_TYPE_NORMAL,
-	.flags =		TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
-
-	.refcount =		&bluetooth_refcount,
-	.table =		bluetooth_tty,
-	.termios =		bluetooth_termios,
-	.termios_locked =	bluetooth_termios_locked,
-
+static struct tty_operations bluetooth_ops = {
 	.open =			bluetooth_open,
 	.close =		bluetooth_close,
 	.write =		bluetooth_write,
@@ -1323,7 +1302,6 @@
 	.chars_in_buffer =	bluetooth_chars_in_buffer,
 };
 
-
 int usb_bluetooth_init(void)
 {
 	int i;
@@ -1336,18 +1314,32 @@
 
 	info ("USB Bluetooth support registered");
 
-	/* register the tty driver */
-	bluetooth_tty_driver.init_termios          = tty_std_termios;
-	bluetooth_tty_driver.init_termios.c_cflag  = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	if (tty_register_driver (&bluetooth_tty_driver)) {
+	bluetooth_tty_driver = alloc_tty_driver(BLUETOOTH_TTY_MINORS);
+	if (!bluetooth_tty_driver)
+		return -ENOMEM;
+
+	bluetooth_tty_driver->owner = THIS_MODULE;
+	bluetooth_tty_driver->driver_name = "usb-bluetooth";
+	bluetooth_tty_driver->name = "usb/ttub/";
+	bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR;
+	bluetooth_tty_driver->minor_start = 0;
+	bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	bluetooth_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	bluetooth_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	bluetooth_tty_driver->init_termios = tty_std_termios;
+	bluetooth_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	tty_set_operations(bluetooth_tty_driver, &bluetooth_ops);
+	if (tty_register_driver (bluetooth_tty_driver)) {
 		err("%s - failed to register tty driver", __FUNCTION__);
+		put_tty_driver(bluetooth_tty_driver);
 		return -1;
 	}
 
 	/* register the USB driver */
 	result = usb_register(&usb_bluetooth_driver);
 	if (result < 0) {
-		tty_unregister_driver(&bluetooth_tty_driver);
+		tty_unregister_driver(bluetooth_tty_driver);
+		put_tty_driver(bluetooth_tty_driver);
 		err("usb_register failed for the USB bluetooth driver. Error number %d", result);
 		return -1;
 	}
@@ -1361,7 +1353,8 @@
 void usb_bluetooth_exit(void)
 {
 	usb_deregister(&usb_bluetooth_driver);
-	tty_unregister_driver(&bluetooth_tty_driver);
+	tty_unregister_driver(bluetooth_tty_driver);
+	put_tty_driver(bluetooth_tty_driver);
 }
 
 
diff -urN linux-2.5.70-bk16/drivers/usb/class/cdc-acm.c linux-2.5.70-bk17/drivers/usb/class/cdc-acm.c
--- linux-2.5.70-bk16/drivers/usb/class/cdc-acm.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/usb/class/cdc-acm.c	2003-06-12 04:49:59.000000000 -0700
@@ -154,7 +154,7 @@
 };
 
 static struct usb_driver acm_driver;
-static struct tty_driver acm_tty_driver;
+static struct tty_driver *acm_tty_driver;
 static struct acm *acm_table[ACM_TTY_MINORS];
 
 #define ACM_READY(acm)	(acm && acm->dev && acm->used)
@@ -364,7 +364,7 @@
 			usb_unlink_urb(acm->writeurb);
 			usb_unlink_urb(acm->readurb);
 		} else {
-			tty_unregister_device(&acm_tty_driver, acm->minor);
+			tty_unregister_device(acm_tty_driver, acm->minor);
 			acm_table[acm->minor] = NULL;
 			usb_free_urb(acm->ctrlurb);
 			usb_free_urb(acm->readurb);
@@ -667,7 +667,7 @@
 		usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
 		usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
 
-		tty_register_device(&acm_tty_driver, minor, &intf->dev);
+		tty_register_device(acm_tty_driver, minor, &intf->dev);
 
 		acm_table[minor] = acm;
 		usb_set_intfdata (intf, acm);
@@ -699,7 +699,7 @@
 	usb_driver_release_interface(&acm_driver, acm->iface + 1);
 
 	if (!acm->used) {
-		tty_unregister_device(&acm_tty_driver, acm->minor);
+		tty_unregister_device(acm_tty_driver, acm->minor);
 		acm_table[acm->minor] = NULL;
 		usb_free_urb(acm->ctrlurb);
 		usb_free_urb(acm->readurb);
@@ -736,30 +736,7 @@
  * TTY driver structures.
  */
 
-static int acm_tty_refcount;
-
-static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
-static struct termios *acm_tty_termios[ACM_TTY_MINORS];
-static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
-
-static struct tty_driver acm_tty_driver = {
-	.magic =		TTY_DRIVER_MAGIC,
-	.owner =		THIS_MODULE,
-	.driver_name =		"acm",
-	.name =			"usb/acm/",
-	.major =		ACM_TTY_MAJOR,
-	.minor_start =		0,
-	.num =			ACM_TTY_MINORS,
-	.type =			TTY_DRIVER_TYPE_SERIAL,
-	.subtype =		SERIAL_TYPE_NORMAL,
-	.flags =		TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
-
-	.refcount =		&acm_tty_refcount,
-
-	.table =		acm_tty_table,
-	.termios =		acm_tty_termios,
-	.termios_locked =	acm_tty_termios_locked,
-
+static struct tty_operations acm_ops = {
 	.open =			acm_tty_open,
 	.close =		acm_tty_close,
 	.write =		acm_tty_write,
@@ -780,14 +757,29 @@
 
 static int __init acm_init(void)
 {
-	acm_tty_driver.init_termios =		tty_std_termios;
-	acm_tty_driver.init_termios.c_cflag =	B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	acm_tty_driver = alloc_tty_driver(ACM_TTY_MINORS);
+	if (!acm_tty_driver)
+		return -ENOMEM;
+	acm_tty_driver->owner = THIS_MODULE,
+	acm_tty_driver->driver_name = "acm",
+	acm_tty_driver->name = "usb/acm/",
+	acm_tty_driver->major = ACM_TTY_MAJOR,
+	acm_tty_driver->minor_start = 0,
+	acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
+	acm_tty_driver->subtype = SERIAL_TYPE_NORMAL,
+	acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
+	acm_tty_driver->init_termios = tty_std_termios;
+	acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	tty_set_operations(acm_tty_driver, &acm_ops);
 
-	if (tty_register_driver(&acm_tty_driver))
+	if (tty_register_driver(acm_tty_driver)) {
+		put_tty_driver(acm_tty_driver);
 		return -1;
+	}
 
 	if (usb_register(&acm_driver) < 0) {
-		tty_unregister_driver(&acm_tty_driver);
+		tty_unregister_driver(acm_tty_driver);
+		put_tty_driver(acm_tty_driver);
 		return -1;
 	}
 
@@ -799,7 +791,8 @@
 static void __exit acm_exit(void)
 {
 	usb_deregister(&acm_driver);
-	tty_unregister_driver(&acm_tty_driver);
+	tty_unregister_driver(acm_tty_driver);
+	put_tty_driver(acm_tty_driver);
 }
 
 module_init(acm_init);
diff -urN linux-2.5.70-bk16/drivers/usb/image/mdc800.c linux-2.5.70-bk17/drivers/usb/image/mdc800.c
--- linux-2.5.70-bk16/drivers/usb/image/mdc800.c	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/drivers/usb/image/mdc800.c	2003-06-12 04:50:00.000000000 -0700
@@ -748,8 +748,12 @@
 		}
 		else
 		{
-			/* memcpy Bytes */
-			memcpy (ptr, &mdc800->out [mdc800->out_ptr], sts);
+			/* Copy Bytes */
+			if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr],
+						sts)) {
+				up(&mdc800->io_lock);
+				return -EFAULT;
+			}
 			ptr+=sts;
 			left-=sts;
 			mdc800->out_ptr+=sts;
@@ -786,14 +790,21 @@
 
 	while (i<len)
 	{
+		unsigned char c;
 		if (signal_pending (current)) 
 		{
 			up (&mdc800->io_lock);
 			return -EINTR;
 		}
+		
+		if(get_user(c, buf+i))
+		{
+			up(&mdc800->io_lock);
+			return -EFAULT;
+		}
 
 		/* check for command start */
-		if (buf [i] == (char) 0x55)
+		if (c == 0x55)
 		{
 			mdc800->in_count=0;
 			mdc800->out_count=0;
@@ -804,12 +815,11 @@
 		/* save command byte */
 		if (mdc800->in_count < 8)
 		{
-			mdc800->in[mdc800->in_count]=buf[i];
+			mdc800->in[mdc800->in_count] = c;
 			mdc800->in_count++;
 		}
 		else
 		{
-			err ("Command is too long !\n");
 			up (&mdc800->io_lock);
 			return -EIO;
 		}
@@ -884,8 +894,8 @@
 							return -EIO;
 						}
 
-						/* Write dummy data, (this is ugly but part of the USB Protokoll */
-						/* if you use endpoint 1 as bulk and not as irq */
+						/* Write dummy data, (this is ugly but part of the USB Protocol */
+						/* if you use endpoint 1 as bulk and not as irq) */
 						memcpy (mdc800->out, mdc800->camera_response,8);
 
 						/* This is the interpreted answer */
diff -urN linux-2.5.70-bk16/drivers/usb/serial/bus.c linux-2.5.70-bk17/drivers/usb/serial/bus.c
--- linux-2.5.70-bk16/drivers/usb/serial/bus.c	2003-05-26 18:01:03.000000000 -0700
+++ linux-2.5.70-bk17/drivers/usb/serial/bus.c	2003-06-12 04:50:00.000000000 -0700
@@ -76,7 +76,7 @@
 	}
 
 	minor = port->number;
-	tty_register_device (&usb_serial_tty_driver, minor, dev);
+	tty_register_device (usb_serial_tty_driver, minor, dev);
 	dev_info(&port->serial->dev->dev, 
 		 "%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)\n",
 		 driver->name, minor, minor);
@@ -109,7 +109,7 @@
 	}
 exit:
 	minor = port->number;
-	tty_unregister_device (&usb_serial_tty_driver, minor);
+	tty_unregister_device (usb_serial_tty_driver, minor);
 	dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
 		 driver->name, minor);
 
diff -urN linux-2.5.70-bk16/drivers/usb/serial/usb-serial.c linux-2.5.70-bk17/drivers/usb/serial/usb-serial.c
--- linux-2.5.70-bk16/drivers/usb/serial/usb-serial.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/drivers/usb/serial/usb-serial.c	2003-06-12 04:50:00.000000000 -0700
@@ -382,10 +382,6 @@
    drivers depend on it.
 */
 
-static int			serial_refcount;
-static struct tty_struct *	serial_tty[SERIAL_TTY_MINORS];
-static struct termios *		serial_termios[SERIAL_TTY_MINORS];
-static struct termios *		serial_termios_locked[SERIAL_TTY_MINORS];
 static struct usb_serial	*serial_table[SERIAL_TTY_MINORS];	/* initially all NULL */
 static LIST_HEAD(usb_serial_driver_list);
 
@@ -1299,25 +1295,7 @@
 	dev_info(dev, "device disconnected\n");
 }
 
-
-struct tty_driver usb_serial_tty_driver = {
-	.magic =		TTY_DRIVER_MAGIC,
-	.owner =		THIS_MODULE,
-	.driver_name =		"usbserial",
-	.devfs_name =		"usb/tts/",
-	.name =			"ttyUSB",
-	.major =		SERIAL_TTY_MAJOR,
-	.minor_start =		0,
-	.num =			SERIAL_TTY_MINORS,
-	.type =			TTY_DRIVER_TYPE_SERIAL,
-	.subtype =		SERIAL_TYPE_NORMAL,
-	.flags =		TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
-
-	.refcount =		&serial_refcount,
-	.table =		serial_tty,
-	.termios =		serial_termios,
-	.termios_locked =	serial_termios_locked,
-
+static struct tty_operations serial_ops = {
 	.open =			serial_open,
 	.close =		serial_close,
 	.write =		serial_write,
@@ -1333,12 +1311,17 @@
 	.tiocmset =		serial_tiocmset,
 };
 
+struct tty_driver *usb_serial_tty_driver;
 
 static int __init usb_serial_init(void)
 {
 	int i;
 	int result = 0;
 
+	usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
+	if (!usb_serial_tty_driver)
+		return -ENOMEM;
+
 	/* Initialize our global data */
 	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
 		serial_table[i] = NULL;
@@ -1353,10 +1336,19 @@
 		goto exit;
 	}
 
-	/* register the tty driver */
-	usb_serial_tty_driver.init_termios = tty_std_termios;
-	usb_serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	result = tty_register_driver (&usb_serial_tty_driver);
+	usb_serial_tty_driver->owner = THIS_MODULE;
+	usb_serial_tty_driver->driver_name = "usbserial";
+	usb_serial_tty_driver->devfs_name = "usb/tts/";
+	usb_serial_tty_driver->name = 	"ttyUSB";
+	usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
+	usb_serial_tty_driver->minor_start = 0;
+	usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	usb_serial_tty_driver->init_termios = tty_std_termios;
+	usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	tty_set_operations(usb_serial_tty_driver, &serial_ops);
+	result = tty_register_driver(usb_serial_tty_driver);
 	if (result) {
 		err("%s - tty_register_driver failed", __FUNCTION__);
 		goto exit_generic;
@@ -1374,13 +1366,14 @@
 	return result;
 
 exit_tty:
-	tty_unregister_driver(&usb_serial_tty_driver);
+	tty_unregister_driver(usb_serial_tty_driver);
 
 exit_generic:
 	usb_serial_generic_deregister();
 
 exit:
 	err ("%s - returning with error %d", __FUNCTION__, result);
+	put_tty_driver(usb_serial_tty_driver);
 	return result;
 }
 
@@ -1392,7 +1385,8 @@
 	usb_serial_generic_deregister();
 
 	usb_deregister(&usb_serial_driver);
-	tty_unregister_driver(&usb_serial_tty_driver);
+	tty_unregister_driver(usb_serial_tty_driver);
+	put_tty_driver(usb_serial_tty_driver);
 	bus_unregister(&usb_serial_bus_type);
 }
 
diff -urN linux-2.5.70-bk16/drivers/usb/serial/usb-serial.h linux-2.5.70-bk17/drivers/usb/serial/usb-serial.h
--- linux-2.5.70-bk16/drivers/usb/serial/usb-serial.h	2003-05-26 18:01:04.000000000 -0700
+++ linux-2.5.70-bk17/drivers/usb/serial/usb-serial.h	2003-06-12 04:50:00.000000000 -0700
@@ -297,7 +297,7 @@
 
 extern struct usb_serial_device_type usb_serial_generic_device;
 extern struct bus_type usb_serial_bus_type;
-extern struct tty_driver usb_serial_tty_driver;
+extern struct tty_driver *usb_serial_tty_driver;
 
 /* Inline functions to check the sanity of a pointer that is passed to us */
 static inline int serial_paranoia_check (struct usb_serial *serial, const char *function)
diff -urN linux-2.5.70-bk16/fs/bio.c linux-2.5.70-bk17/fs/bio.c
--- linux-2.5.70-bk16/fs/bio.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/fs/bio.c	2003-06-12 04:50:05.000000000 -0700
@@ -259,84 +259,6 @@
 }
 
 /**
- *	bio_copy	-	create copy of a bio
- *	@bio: bio to copy
- *	@gfp_mask: allocation priority
- *	@copy: copy data to allocated bio
- *
- *	Create a copy of a &bio. Caller will own the returned bio and
- *	the actual data it points to. Reference count of returned
- * 	bio will be one.
- */
-struct bio *bio_copy(struct bio *bio, int gfp_mask, int copy)
-{
-	struct bio *b = bio_alloc(gfp_mask, bio->bi_vcnt);
-	unsigned long flags = 0; /* gcc silly */
-	struct bio_vec *bv;
-	int i;
-
-	if (unlikely(!b))
-		return NULL;
-
-	/*
-	 * iterate iovec list and alloc pages + copy data
-	 */
-	__bio_for_each_segment(bv, bio, i, 0) {
-		struct bio_vec *bbv = &b->bi_io_vec[i];
-		char *vfrom, *vto;
-
-		bbv->bv_page = alloc_page(gfp_mask);
-		if (bbv->bv_page == NULL)
-			goto oom;
-
-		bbv->bv_len = bv->bv_len;
-		bbv->bv_offset = bv->bv_offset;
-
-		/*
-		 * if doing a copy for a READ request, no need
-		 * to memcpy page data
-		 */
-		if (!copy)
-			continue;
-
-		if (gfp_mask & __GFP_WAIT) {
-			vfrom = kmap(bv->bv_page);
-			vto = kmap(bbv->bv_page);
-		} else {
-			local_irq_save(flags);
-			vfrom = kmap_atomic(bv->bv_page, KM_BIO_SRC_IRQ);
-			vto = kmap_atomic(bbv->bv_page, KM_BIO_DST_IRQ);
-		}
-
-		memcpy(vto + bbv->bv_offset, vfrom + bv->bv_offset, bv->bv_len);
-		if (gfp_mask & __GFP_WAIT) {
-			kunmap(bbv->bv_page);
-			kunmap(bv->bv_page);
-		} else {
-			kunmap_atomic(vto, KM_BIO_DST_IRQ);
-			kunmap_atomic(vfrom, KM_BIO_SRC_IRQ);
-			local_irq_restore(flags);
-		}
-	}
-
-	b->bi_sector = bio->bi_sector;
-	b->bi_bdev = bio->bi_bdev;
-	b->bi_rw = bio->bi_rw;
-
-	b->bi_vcnt = bio->bi_vcnt;
-	b->bi_size = bio->bi_size;
-
-	return b;
-
-oom:
-	while (--i >= 0)
-		__free_page(b->bi_io_vec[i].bv_page);
-
-	mempool_free(b, bio_pool);
-	return NULL;
-}
-
-/**
  *	bio_get_nr_vecs		- return approx number of vecs
  *	@bdev:  I/O target
  *
@@ -905,7 +827,6 @@
 EXPORT_SYMBOL(bio_put);
 EXPORT_SYMBOL(bio_endio);
 EXPORT_SYMBOL(bio_init);
-EXPORT_SYMBOL(bio_copy);
 EXPORT_SYMBOL(__bio_clone);
 EXPORT_SYMBOL(bio_clone);
 EXPORT_SYMBOL(bio_phys_segments);
diff -urN linux-2.5.70-bk16/fs/char_dev.c linux-2.5.70-bk17/fs/char_dev.c
--- linux-2.5.70-bk16/fs/char_dev.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/fs/char_dev.c	2003-06-12 04:50:06.000000000 -0700
@@ -221,7 +221,7 @@
 out:
 	kobject_put(&cdev->kobj);
 out2:
-	__unregister_chrdev_region(cd->major, 0, 256);
+	kfree(__unregister_chrdev_region(cd->major, 0, 256));
 	return err;
 }
 
@@ -366,7 +366,10 @@
 	int err = kobject_add(&p->kobj);
 	if (err)
 		return err;
-	return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
+	err = kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
+	if (err)
+		kobject_del(&p->kobj);
+	return err;
 }
 
 void cdev_unmap(dev_t dev, unsigned count)
diff -urN linux-2.5.70-bk16/fs/intermezzo/vfs.c linux-2.5.70-bk17/fs/intermezzo/vfs.c
--- linux-2.5.70-bk16/fs/intermezzo/vfs.c	2003-05-26 18:00:28.000000000 -0700
+++ linux-2.5.70-bk17/fs/intermezzo/vfs.c	2003-06-12 04:50:11.000000000 -0700
@@ -1236,7 +1236,7 @@
                 goto exit_lock;
         }
         error = presto_do_symlink(fset, nd.dentry,
-                                  dentry, oldname, info);
+                                  dentry, from, info);
         path_release(&nd);
         EXIT;
  exit_lock:
diff -urN linux-2.5.70-bk16/fs/jfs/inode.c linux-2.5.70-bk17/fs/jfs/inode.c
--- linux-2.5.70-bk16/fs/jfs/inode.c	2003-05-26 18:00:19.000000000 -0700
+++ linux-2.5.70-bk17/fs/jfs/inode.c	2003-06-12 04:50:13.000000000 -0700
@@ -36,17 +36,11 @@
 struct address_space_operations jfs_aops;
 extern int freeZeroLink(struct inode *);
 
-struct inode *jfs_iget(struct super_block *sb, ino_t ino)
+void jfs_read_inode(struct inode *inode)
 {
-	struct inode *inode = iget_locked(sb, ino);
-
-	if (!inode || !(inode->i_state & I_NEW))
-		return inode;
-
 	if (diRead(inode)) { 
 		make_bad_inode(inode);
-		unlock_new_inode(inode);
-		return NULL;
+		return;
 	}
 
 	if (S_ISREG(inode->i_mode)) {
@@ -69,8 +63,6 @@
 		init_special_inode(inode, inode->i_mode,
 				   kdev_t_to_nr(inode->i_rdev));
 	}
-	unlock_new_inode(inode);
-	return inode;
 }
 
 /* This define is from fs/open.c */
diff -urN linux-2.5.70-bk16/fs/jfs/namei.c linux-2.5.70-bk17/fs/jfs/namei.c
--- linux-2.5.70-bk16/fs/jfs/namei.c	2003-05-26 18:00:45.000000000 -0700
+++ linux-2.5.70-bk17/fs/jfs/namei.c	2003-06-12 04:50:13.000000000 -0700
@@ -35,7 +35,6 @@
 
 extern int jfs_fsync(struct file *, struct dentry *, int);
 extern void jfs_truncate_nolock(struct inode *, loff_t);
-extern struct inode *jfs_iget(struct super_block *, ino_t);
 extern int jfs_init_acl(struct inode *, struct inode *);
 
 /*
@@ -1406,9 +1405,11 @@
 		}
 	}
 
-	ip = jfs_iget(dip->i_sb, inum);
-	if (ip == NULL) {
+	ip = iget(dip->i_sb, inum);
+	if (ip == NULL || is_bad_inode(ip)) {
 		jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);
+		if (ip)
+			iput(ip);
 		return ERR_PTR(-EACCES);
 	}
 
@@ -1421,12 +1422,16 @@
 	struct dentry *parent = ERR_PTR(-EACCES);
 	struct inode *inode;
 
-	inode = jfs_iget(sb, JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);
+	inode = iget(sb, JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);
 	if (inode) {
-		parent = d_alloc_anon(inode);
-		if (!parent) {
-			parent = ERR_PTR(-ENOMEM);
+		if (is_bad_inode(inode))
 			iput(inode);
+		else {
+			parent = d_alloc_anon(inode);
+			if (!parent) {
+				parent = ERR_PTR(-ENOMEM);
+				iput(inode);
+			}
 		}
 	}
 
diff -urN linux-2.5.70-bk16/fs/jfs/super.c linux-2.5.70-bk17/fs/jfs/super.c
--- linux-2.5.70-bk16/fs/jfs/super.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/fs/jfs/super.c	2003-06-12 04:50:13.000000000 -0700
@@ -58,8 +58,6 @@
 /*
  * External declarations
  */
-extern struct inode *jfs_iget(struct super_block *, ino_t);
-
 extern int jfs_mount(struct super_block *);
 extern int jfs_mount_rw(struct super_block *, int);
 extern int jfs_umount(struct super_block *);
@@ -69,6 +67,7 @@
 extern int jfs_lazycommit(void *);
 extern int jfs_sync(void *);
 
+extern void jfs_read_inode(struct inode *inode);
 extern void jfs_dirty_inode(struct inode *inode);
 extern void jfs_delete_inode(struct inode *inode);
 extern void jfs_write_inode(struct inode *inode, int wait);
@@ -313,7 +312,7 @@
 
 	sb->s_magic = JFS_SUPER_MAGIC;
 
-	inode = jfs_iget(sb, ROOT_I);
+	inode = iget(sb, ROOT_I);
 	if (!inode || is_bad_inode(inode))
 		goto out_no_root;
 	sb->s_root = d_alloc_root(inode);
@@ -397,6 +396,7 @@
 static struct super_operations jfs_super_operations = {
 	.alloc_inode	= jfs_alloc_inode,
 	.destroy_inode	= jfs_destroy_inode,
+	.read_inode	= jfs_read_inode,
 	.dirty_inode	= jfs_dirty_inode,
 	.write_inode	= jfs_write_inode,
 	.delete_inode	= jfs_delete_inode,
diff -urN linux-2.5.70-bk16/fs/nfs/idmap.c linux-2.5.70-bk17/fs/nfs/idmap.c
--- linux-2.5.70-bk16/fs/nfs/idmap.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/fs/nfs/idmap.c	2003-06-12 04:50:14.000000000 -0700
@@ -106,7 +106,7 @@
 	    "%s/idmap", idmap->idmap_server->client->cl_pathname);
 
         idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path,
-	    idmap->idmap_server, &idmap_upcall_ops);
+	    idmap->idmap_server, &idmap_upcall_ops, 0);
         if (IS_ERR(idmap->idmap_dentry))
 		goto err_free;
 
diff -urN linux-2.5.70-bk16/fs/nfs/nfs4state.c linux-2.5.70-bk17/fs/nfs/nfs4state.c
--- linux-2.5.70-bk16/fs/nfs/nfs4state.c	2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk17/fs/nfs/nfs4state.c	2003-06-12 04:50:14.000000000 -0700
@@ -65,7 +65,7 @@
 	struct nfs4_client *clp;
 
 	if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL)))
-		memset(clp, 0, sizeof(nfs4_verifier));
+		memset(clp, 0, sizeof(*clp));
 	return clp;
 }
 
diff -urN linux-2.5.70-bk16/fs/sysfs/bin.c linux-2.5.70-bk17/fs/sysfs/bin.c
--- linux-2.5.70-bk16/fs/sysfs/bin.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/fs/sysfs/bin.c	2003-06-12 04:50:15.000000000 -0700
@@ -22,7 +22,7 @@
 }
 
 static ssize_t
-read(struct file * file, char * userbuf, size_t count, loff_t * off)
+read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
 {
 	char *buffer = file->private_data;
 	struct dentry *dentry = file->f_dentry;
@@ -65,7 +65,7 @@
 	return attr->write(kobj, buffer, offset, count);
 }
 
-static ssize_t write(struct file * file, const char * userbuf,
+static ssize_t write(struct file * file, const char __user * userbuf,
 		     size_t count, loff_t * off)
 {
 	char *buffer = file->private_data;
diff -urN linux-2.5.70-bk16/fs/sysfs/file.c linux-2.5.70-bk17/fs/sysfs/file.c
--- linux-2.5.70-bk16/fs/sysfs/file.c	2003-06-12 04:49:51.000000000 -0700
+++ linux-2.5.70-bk17/fs/sysfs/file.c	2003-06-12 04:50:15.000000000 -0700
@@ -109,7 +109,7 @@
  *	the amount they specify each time.
  *	This may be called continuously until the buffer is empty.
  */
-static int flush_read_buffer(struct sysfs_buffer * buffer, char * buf, 
+static int flush_read_buffer(struct sysfs_buffer * buffer, char __user * buf,
 			     size_t count, loff_t * ppos)
 {
 	int error;
@@ -143,7 +143,7 @@
  */
 
 static ssize_t
-sysfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
+sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
 	struct sysfs_buffer * buffer = file->private_data;
 	ssize_t retval = 0;
@@ -169,7 +169,7 @@
  */
 
 static int 
-fill_write_buffer(struct sysfs_buffer * buffer, const char * buf, size_t count)
+fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count)
 {
 	int error;
 
@@ -224,7 +224,7 @@
  */
 
 static ssize_t
-sysfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
+sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	struct sysfs_buffer * buffer = file->private_data;
 
diff -urN linux-2.5.70-bk16/include/asm-arm/arch-iop3xx/iop321.h linux-2.5.70-bk17/include/asm-arm/arch-iop3xx/iop321.h
--- linux-2.5.70-bk16/include/asm-arm/arch-iop3xx/iop321.h	2003-05-26 18:01:03.000000000 -0700
+++ linux-2.5.70-bk17/include/asm-arm/arch-iop3xx/iop321.h	2003-06-12 04:50:16.000000000 -0700
@@ -14,9 +14,16 @@
 #ifndef _IOP321_HW_H_
 #define _IOP321_HW_H_
 
+
+#ifndef __ASSEMBLY__
+#define iop_is_321() ((processor_id & 0xfffff7e0) == 0x69052420)
+#endif
+
+
 /*
  * IOP321 I/O and Mem space regions for PCI autoconfiguration
  */
+
 #define	IOP321_PCI_IO_BASE		0x90000000
 #define	IOP321_PCI_IO_SIZE		0x00010000
 #define IOP321_PCI_MEM_BASE		0x40000000
@@ -26,6 +33,7 @@
  * IOP321 chipset registers
  */
 #define IOP321_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
+
 #define IOP321_PHY_MEM_BASE  0xffffe000  /* chip physical memory address */
 #define IOP321_REG_ADDR(reg) (IOP321_VIRT_MEM_BASE | (reg))
 
@@ -97,12 +105,93 @@
 #define IOP321_PCIIRSR    (volatile u32 *)IOP321_REG_ADDR(0x000001EC)
 
 /* Messaging Unit 0x00000300 through 0x000003FF */
+
+/* Reserved 0x00000300 through 0x0000030c */
+#define IOP321_IMR0       (volatile u32 *)IOP321_REG_ADDR(0x00000310)
+#define IOP321_IMR1       (volatile u32 *)IOP321_REG_ADDR(0x00000314)
+#define IOP321_OMR0       (volatile u32 *)IOP321_REG_ADDR(0x00000318)
+#define IOP321_OMR1       (volatile u32 *)IOP321_REG_ADDR(0x0000031C)
+#define IOP321_IDR        (volatile u32 *)IOP321_REG_ADDR(0x00000320)
+#define IOP321_IISR       (volatile u32 *)IOP321_REG_ADDR(0x00000324)
+#define IOP321_IIMR       (volatile u32 *)IOP321_REG_ADDR(0x00000328)
+#define IOP321_ODR        (volatile u32 *)IOP321_REG_ADDR(0x0000032C)
+#define IOP321_OISR       (volatile u32 *)IOP321_REG_ADDR(0x00000330)
+#define IOP321_OIMR       (volatile u32 *)IOP321_REG_ADDR(0x00000334)
+/* Reserved 0x00000338 through 0x0000034F */
+#define IOP321_MUCR       (volatile u32 *)IOP321_REG_ADDR(0x00000350)
+#define IOP321_QBAR       (volatile u32 *)IOP321_REG_ADDR(0x00000354)
+/* Reserved 0x00000358 through 0x0000035C */
+#define IOP321_IFHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000360)
+#define IOP321_IFTPR      (volatile u32 *)IOP321_REG_ADDR(0x00000364)
+#define IOP321_IPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000368)
+#define IOP321_IPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000036C)
+#define IOP321_OFHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000370)
+#define IOP321_OFTPR      (volatile u32 *)IOP321_REG_ADDR(0x00000374)
+#define IOP321_OPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000378)
+#define IOP321_OPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000037C)
+#define IOP321_IAR        (volatile u32 *)IOP321_REG_ADDR(0x00000380)
+/* Reserved 0x00000384 through 0x000003FF */
+
 /* DMA Controller 0x00000400 through 0x000004FF */
+#define IOP321_DMA0_CCR   (volatile u32 *)IOP321_REG_ADDR(0x00000400)
+#define IOP321_DMA0_CSR   (volatile u32 *)IOP321_REG_ADDR(0x00000404)
+#define IOP321_DMA0_DAR   (volatile u32 *)IOP321_REG_ADDR(0x0000040C)
+#define IOP321_DMA0_NDAR  (volatile u32 *)IOP321_REG_ADDR(0x00000410)
+#define IOP321_DMA0_PADR  (volatile u32 *)IOP321_REG_ADDR(0x00000414)
+#define IOP321_DMA0_PUADR (volatile u32 *)IOP321_REG_ADDR(0x00000418)
+#define IOP321_DMA0_LADR  (volatile u32 *)IOP321_REG_ADDR(0X0000041C)
+#define IOP321_DMA0_BCR   (volatile u32 *)IOP321_REG_ADDR(0x00000420)
+#define IOP321_DMA0_DCR   (volatile u32 *)IOP321_REG_ADDR(0x00000424)
+/* Reserved 0x00000428 through 0x0000043C */
+#define IOP321_DMA1_CCR   (volatile u32 *)IOP321_REG_ADDR(0x00000440)
+#define IOP321_DMA1_CSR   (volatile u32 *)IOP321_REG_ADDR(0x00000444)
+#define IOP321_DMA1_DAR   (volatile u32 *)IOP321_REG_ADDR(0x0000044C)
+#define IOP321_DMA1_NDAR  (volatile u32 *)IOP321_REG_ADDR(0x00000450)
+#define IOP321_DMA1_PADR  (volatile u32 *)IOP321_REG_ADDR(0x00000454)
+#define IOP321_DMA1_PUADR (volatile u32 *)IOP321_REG_ADDR(0x00000458)
+#define IOP321_DMA1_LADR  (volatile u32 *)IOP321_REG_ADDR(0x0000045C)
+#define IOP321_DMA1_BCR   (volatile u32 *)IOP321_REG_ADDR(0x00000460)
+#define IOP321_DMA1_DCR   (volatile u32 *)IOP321_REG_ADDR(0x00000464)
+/* Reserved 0x00000468 through 0x000004FF */
+
 /* Memory controller 0x00000500 through 0x0005FF */
+
 /* Peripheral bus interface unit 0x00000680 through 0x0006FF */
+#define IOP321_PBCR       (volatile u32 *)IOP321_REG_ADDR(0x00000680)
+#define IOP321_PBISR      (volatile u32 *)IOP321_REG_ADDR(0x00000684)
+#define IOP321_PBBAR0     (volatile u32 *)IOP321_REG_ADDR(0x00000688)
+#define IOP321_PBLR0      (volatile u32 *)IOP321_REG_ADDR(0x0000068C)
+#define IOP321_PBBAR1     (volatile u32 *)IOP321_REG_ADDR(0x00000690)
+#define IOP321_PBLR1      (volatile u32 *)IOP321_REG_ADDR(0x00000694)
+#define IOP321_PBBAR2     (volatile u32 *)IOP321_REG_ADDR(0x00000698)
+#define IOP321_PBLR2      (volatile u32 *)IOP321_REG_ADDR(0x0000069C)
+#define IOP321_PBBAR3     (volatile u32 *)IOP321_REG_ADDR(0x000006A0)
+#define IOP321_PBLR3      (volatile u32 *)IOP321_REG_ADDR(0x000006A4)
+#define IOP321_PBBAR4     (volatile u32 *)IOP321_REG_ADDR(0x000006A8)
+#define IOP321_PBLR4      (volatile u32 *)IOP321_REG_ADDR(0x000006AC)
+#define IOP321_PBBAR5     (volatile u32 *)IOP321_REG_ADDR(0x000006B0)
+#define IOP321_PBLR5      (volatile u32 *)IOP321_REG_ADDR(0x000006B4)
+#define IOP321_PBDSCR     (volatile u32 *)IOP321_REG_ADDR(0x000006B8)
+/* Reserved 0x000006BC */
+#define IOP321_PMBR0      (volatile u32 *)IOP321_REG_ADDR(0x000006C0)
+/* Reserved 0x000006C4 through 0x000006DC */
+#define IOP321_PMBR1      (volatile u32 *)IOP321_REG_ADDR(0x000006E0)
+#define IOP321_PMBR2      (volatile u32 *)IOP321_REG_ADDR(0x000006E4)
+
+#define IOP321_PBCR_EN    0x1
+
+#define IOP321_PBISR_BOOR_ERR 0x1
+
+
+
 /* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
 /* Internal arbitration unit 0x00000780 through 0x0007BF */
 
+/* General Purpose I/O Registers */
+#define IOP321_GPOE       (volatile u32 *)IOP321_REG_ADDR(0x000007C4)
+#define IOP321_GPID       (volatile u32 *)IOP321_REG_ADDR(0x000007C8)
+#define IOP321_GPOD       (volatile u32 *)IOP321_REG_ADDR(0x000007CC)
+
 /* Interrupt Controller */
 #define IOP321_INTCTL     (volatile u32 *)IOP321_REG_ADDR(0x000007D0)
 #define IOP321_INTSTR     (volatile u32 *)IOP321_REG_ADDR(0x000007D4)
@@ -131,11 +220,40 @@
 #define IOP321_TU_TISR    (volatile u32 *)IOP321_REG_ADDR(0x000007F8)
 #define IOP321_TU_WDTCR   (volatile u32 *)IOP321_REG_ADDR(0x000007FC)
 
+
+
 /* Application accelerator unit 0x00000800 - 0x000008FF */
-#define IOP321_AAUACR     (volatile u32 *)IOP321_REG_ADDR(0x00000800)
-#define IOP321_AAUASR     (volatile u32 *)IOP321_REG_ADDR(0x00000804)
-#define IOP321_AAUANDAR   (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
+#define IOP321_AAU_ACR     (volatile u32 *)IOP321_REG_ADDR(0x00000800)
+#define IOP321_AAU_ASR     (volatile u32 *)IOP321_REG_ADDR(0x00000804)
+#define IOP321_AAU_ADAR    (volatile u32 *)IOP321_REG_ADDR(0x00000808)
+#define IOP321_AAU_ANDAR   (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
+#define IOP321_AAU_SAR1    (volatile u32 *)IOP321_REG_ADDR(0x00000810)
+/* SAR2...SAR32 0x00000814 - 0x000008A4 */
+#define IOP321_AAU_DAR     (volatile u32 *)IOP321_REG_ADDR(0x00000820)
+#define IOP321_AAU_ABCR    (volatile u32 *)IOP321_REG_ADDR(0x00000824)
+#define IOP321_AAU_ADCR    (volatile u32 *)IOP321_REG_ADDR(0x00000828)
+#define IOP321_AAU_EDCR0   (volatile u32 *)IOP321_REG_ADDR(0x0000083c)
+#define IOP321_AAU_EDCR1   (volatile u32 *)IOP321_REG_ADDR(0x00000860)
+#define IOP321_AAU_EDCR2   (volatile u32 *)IOP321_REG_ADDR(0x00000884)
+
 
 /* SSP serial port unit 0x00001600 - 0x0000167F */
 /* I2C bus interface unit 0x00001680 - 0x000016FF */
+#define IOP321_ICR0       (volatile u32 *)IOP321_REG_ADDR(0x00001680)
+#define IOP321_ISR0       (volatile u32 *)IOP321_REG_ADDR(0x00001684)
+#define IOP321_ISAR0      (volatile u32 *)IOP321_REG_ADDR(0x00001688)
+#define IOP321_IDBR0      (volatile u32 *)IOP321_REG_ADDR(0x0000168C)
+/* Reserved 0x00001690 */
+#define IOP321_IBMR0      (volatile u32 *)IOP321_REG_ADDR(0x00001694)
+/* Reserved 0x00001698 */
+/* Reserved 0x0000169C */
+#define IOP321_ICR1       (volatile u32 *)IOP321_REG_ADDR(0x000016A0)
+#define IOP321_ISR1       (volatile u32 *)IOP321_REG_ADDR(0x000016A4)
+#define IOP321_ISAR1      (volatile u32 *)IOP321_REG_ADDR(0x000016A8)
+#define IOP321_IDBR1      (volatile u32 *)IOP321_REG_ADDR(0x000016AC)
+#define IOP321_IBMR1      (volatile u32 *)IOP321_REG_ADDR(0x000016B4)
+/* Reserved 0x000016B8 through 0x000016FC */
+
+/* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
+
 #endif // _IOP321_HW_H_
diff -urN linux-2.5.70-bk16/include/asm-ia64/hardirq.h linux-2.5.70-bk17/include/asm-ia64/hardirq.h
--- linux-2.5.70-bk16/include/asm-ia64/hardirq.h	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/include/asm-ia64/hardirq.h	2003-06-12 04:50:16.000000000 -0700
@@ -16,6 +16,9 @@
 /*
  * No irq_cpustat_t for IA-64.  The data is held in the per-CPU data structure.
  */
+
+#define __ARCH_IRQ_STAT	1
+
 #define softirq_pending(cpu)		(cpu_data(cpu)->softirq_pending)
 #define syscall_count(cpu)		/* unused on IA-64 */
 #define ksoftirqd_task(cpu)		(cpu_data(cpu)->ksoftirqd)
diff -urN linux-2.5.70-bk16/include/asm-x86_64/hardirq.h linux-2.5.70-bk17/include/asm-x86_64/hardirq.h
--- linux-2.5.70-bk16/include/asm-x86_64/hardirq.h	2003-05-26 18:00:25.000000000 -0700
+++ linux-2.5.70-bk17/include/asm-x86_64/hardirq.h	2003-06-12 04:50:19.000000000 -0700
@@ -12,10 +12,6 @@
    special access macros. This would generate better code. */ 
 #define __IRQ_STAT(cpu,member) (read_pda(me)->member)
 
-typedef struct {
-	/* Empty. All the fields have moved to the PDA. */
-} irq_cpustat_t; 
-
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
 
 /*
diff -urN linux-2.5.70-bk16/include/linux/acpi.h linux-2.5.70-bk17/include/linux/acpi.h
--- linux-2.5.70-bk16/include/linux/acpi.h	2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/acpi.h	2003-06-12 04:50:19.000000000 -0700
@@ -401,6 +401,15 @@
 int acpi_pci_irq_enable (struct pci_dev *dev);
 int acpi_pci_irq_init (void);
 
+struct acpi_pci_driver {
+	struct acpi_pci_driver *next;
+	int (*add)(acpi_handle *handle);
+	void (*remove)(acpi_handle *handle);
+};
+
+int acpi_pci_register_driver(struct acpi_pci_driver *driver);
+void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
+
 #endif /*CONFIG_ACPI_PCI*/
 
 #ifdef CONFIG_ACPI_EC
diff -urN linux-2.5.70-bk16/include/linux/bio.h linux-2.5.70-bk17/include/linux/bio.h
--- linux-2.5.70-bk16/include/linux/bio.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/bio.h	2003-06-12 04:50:19.000000000 -0700
@@ -235,7 +235,6 @@
 
 extern inline void __bio_clone(struct bio *, struct bio *);
 extern struct bio *bio_clone(struct bio *, int);
-extern struct bio *bio_copy(struct bio *, int, int);
 
 extern inline void bio_init(struct bio *);
 
diff -urN linux-2.5.70-bk16/include/linux/cyclades.h linux-2.5.70-bk17/include/linux/cyclades.h
--- linux-2.5.70-bk16/include/linux/cyclades.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/cyclades.h	2003-06-12 04:50:20.000000000 -0700
@@ -596,7 +596,6 @@
         int                     default_timeout;
 	unsigned long		jiffies[3];
 	unsigned long		rflush_count;
-	struct termios		normal_termios;
 	struct cyclades_monitor	mon;
 	struct cyclades_idle_stats	idle_stats;
 	struct cyclades_icount	icount;
diff -urN linux-2.5.70-bk16/include/linux/generic_serial.h linux-2.5.70-bk17/include/linux/generic_serial.h
--- linux-2.5.70-bk16/include/linux/generic_serial.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/generic_serial.h	2003-06-12 04:50:20.000000000 -0700
@@ -36,7 +36,6 @@
   int                     xmit_cnt;
   /*  struct semaphore        port_write_sem; */
   int                     flags;
-  struct termios          normal_termios;
   wait_queue_head_t       open_wait;
   wait_queue_head_t       close_wait;
   int                     count;
diff -urN linux-2.5.70-bk16/include/linux/hayesesp.h linux-2.5.70-bk17/include/linux/hayesesp.h
--- linux-2.5.70-bk16/include/linux/hayesesp.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/hayesesp.h	2003-06-12 04:50:20.000000000 -0700
@@ -102,7 +102,6 @@
 	int			xmit_cnt;
 	struct work_struct	tqueue;
 	struct work_struct	tqueue_hangup;
-	struct termios		normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 	wait_queue_head_t	delta_msr_wait;
diff -urN linux-2.5.70-bk16/include/linux/i2c-dev.h linux-2.5.70-bk17/include/linux/i2c-dev.h
--- linux-2.5.70-bk16/include/linux/i2c-dev.h	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/i2c-dev.h	2003-06-12 04:50:20.000000000 -0700
@@ -34,13 +34,13 @@
 	__u8 read_write;
 	__u8 command;
 	__u32 size;
-	union i2c_smbus_data *data;
+	union i2c_smbus_data __user *data;
 };
 
 /* This is the structure as used in the I2C_RDWR ioctl call */
 struct i2c_rdwr_ioctl_data {
-	struct i2c_msg *msgs;	/* pointers to i2c_msgs */
-	__u32 nmsgs;		/* number of i2c_msgs */
+	struct i2c_msg __user *msgs;	/* pointers to i2c_msgs */
+	__u32 nmsgs;			/* number of i2c_msgs */
 };
 
 #endif /* _LINUX_I2C_DEV_H */
diff -urN linux-2.5.70-bk16/include/linux/i2c.h linux-2.5.70-bk17/include/linux/i2c.h
--- linux-2.5.70-bk16/include/linux/i2c.h	2003-05-26 18:00:25.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/i2c.h	2003-06-12 04:50:20.000000000 -0700
@@ -176,7 +176,7 @@
 
 static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
 {
-	return dev_set_drvdata (&dev->dev, data);
+	dev_set_drvdata (&dev->dev, data);
 }
 
 #define I2C_DEVNAME(str)   .dev = { .name = str }
@@ -261,7 +261,7 @@
 
 static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
 {
-	return dev_set_drvdata (&dev->dev, data);
+	dev_set_drvdata (&dev->dev, data);
 }
 
 /*flags for the driver struct: */
diff -urN linux-2.5.70-bk16/include/linux/irq_cpustat.h linux-2.5.70-bk17/include/linux/irq_cpustat.h
--- linux-2.5.70-bk16/include/linux/irq_cpustat.h	2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/irq_cpustat.h	2003-06-12 04:50:21.000000000 -0700
@@ -17,9 +17,8 @@
  * definitions instead of differing sets for each arch.
  */
 
-extern irq_cpustat_t irq_stat[];			/* defined in asm/hardirq.h */
-
-#ifndef __ARCH_IRQ_STAT /* Some architectures can do this more efficiently */ 
+#ifndef __ARCH_IRQ_STAT
+extern irq_cpustat_t irq_stat[];		/* defined in asm/hardirq.h */
 #ifdef CONFIG_SMP
 #define __IRQ_STAT(cpu, member)	(irq_stat[cpu].member)
 #else
@@ -31,8 +30,11 @@
 #define softirq_pending(cpu)	__IRQ_STAT((cpu), __softirq_pending)
 #define local_softirq_pending()	softirq_pending(smp_processor_id())
 #define syscall_count(cpu)	__IRQ_STAT((cpu), __syscall_count)
+#define local_syscall_count()	syscall_count(smp_processor_id())
 #define ksoftirqd_task(cpu)	__IRQ_STAT((cpu), __ksoftirqd_task)
+#define local_ksoftirqd_task()	ksoftirqd_task(smp_processor_id())
+
   /* arch dependent irq_stat fields */
-#define nmi_count(cpu)		__IRQ_STAT((cpu), __nmi_count)		/* i386, ia64 */
+#define nmi_count(cpu)		__IRQ_STAT((cpu), __nmi_count)	/* i386 */
 
 #endif	/* __irq_cpustat_h */
diff -urN linux-2.5.70-bk16/include/linux/isdn.h linux-2.5.70-bk17/include/linux/isdn.h
--- linux-2.5.70-bk16/include/linux/isdn.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/isdn.h	2003-06-12 04:50:21.000000000 -0700
@@ -343,7 +343,6 @@
   struct timer_list     ring_timer;      /* for writing 'RING' responses   */
   struct timer_list     connect_timer;   /* waiting for CONNECT            */
   struct timer_list     read_timer;      /* read incoming data             */
-  struct termios	normal_termios;  /* For saving termios structs     */
   wait_queue_head_t	open_wait, close_wait;
   struct semaphore      write_sem;
 } modem_info;
diff -urN linux-2.5.70-bk16/include/linux/isicom.h linux-2.5.70-bk17/include/linux/isicom.h
--- linux-2.5.70-bk16/include/linux/isicom.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/isicom.h	2003-06-12 04:50:21.000000000 -0700
@@ -158,7 +158,6 @@
 	int			xmit_head;
 	int			xmit_tail;
 	int			xmit_cnt;
-	struct termios 		normal_termios;
 };
 
 
diff -urN linux-2.5.70-bk16/include/linux/istallion.h linux-2.5.70-bk17/include/linux/istallion.h
--- linux-2.5.70-bk16/include/linux/istallion.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/istallion.h	2003-06-12 04:50:21.000000000 -0700
@@ -78,7 +78,6 @@
 	wait_queue_head_t	raw_wait;
 #endif
 	struct work_struct	tqhangup;
-	struct termios		normaltermios;
 	asysigs_t		asig;
 	unsigned long		addr;
 	unsigned long		rxoffset;
diff -urN linux-2.5.70-bk16/include/linux/loop.h linux-2.5.70-bk17/include/linux/loop.h
--- linux-2.5.70-bk16/include/linux/loop.h	2003-05-26 18:01:02.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/loop.h	2003-06-12 04:50:21.000000000 -0700
@@ -70,7 +70,6 @@
  */
 #define LO_FLAGS_DO_BMAP	1
 #define LO_FLAGS_READ_ONLY	2
-#define LO_FLAGS_BH_REMAP	4
 
 #include <asm/posix_types.h>	/* for __kernel_old_dev_t */
 #include <asm/types.h>		/* for __u64 */
diff -urN linux-2.5.70-bk16/include/linux/node.h linux-2.5.70-bk17/include/linux/node.h
--- linux-2.5.70-bk16/include/linux/node.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/node.h	2003-06-12 04:50:21.000000000 -0700
@@ -28,7 +28,6 @@
 
 extern int register_node(struct node *, int, struct node *);
 
-#define to_node(_root) container_of(_root, struct node, sysroot)
-#define to_root(_dev) container_of(_dev, struct sys_root, dev)
+#define to_node(sys_device) container_of(sys_device, struct node, sysdev)
 
 #endif /* _LINUX_NODE_H_ */
diff -urN linux-2.5.70-bk16/include/linux/oprofile.h linux-2.5.70-bk17/include/linux/oprofile.h
--- linux-2.5.70-bk16/include/linux/oprofile.h	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/oprofile.h	2003-06-12 04:50:21.000000000 -0700
@@ -40,7 +40,9 @@
 
 /**
  * One-time initialisation. *ops must be set to a filled-in
- * operations structure.
+ * operations structure. This is called even in timer interrupt
+ * mode.
+ *
  * Return 0 on success.
  */
 int oprofile_arch_init(struct oprofile_operations ** ops);
diff -urN linux-2.5.70-bk16/include/linux/reboot.h linux-2.5.70-bk17/include/linux/reboot.h
--- linux-2.5.70-bk16/include/linux/reboot.h	2003-05-26 18:01:03.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/reboot.h	2003-06-12 04:50:22.000000000 -0700
@@ -9,6 +9,7 @@
 #define	LINUX_REBOOT_MAGIC2	672274793
 #define	LINUX_REBOOT_MAGIC2A	85072278
 #define	LINUX_REBOOT_MAGIC2B	369367448
+#define	LINUX_REBOOT_MAGIC2C	537993216
 
 
 /*
diff -urN linux-2.5.70-bk16/include/linux/selection.h linux-2.5.70-bk17/include/linux/selection.h
--- linux-2.5.70-bk16/include/linux/selection.h	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/selection.h	2003-06-12 04:50:22.000000000 -0700
@@ -7,12 +7,13 @@
 #ifndef _LINUX_SELECTION_H_
 #define _LINUX_SELECTION_H_
 
+#include <linux/tiocl.h>
 #include <linux/vt_buffer.h>
 
 extern int sel_cons;
 
 extern void clear_selection(void);
-extern int set_selection(const unsigned long arg, struct tty_struct *tty, int user);
+extern int set_selection(const struct tiocl_selection *sel, struct tty_struct *tty, int user);
 extern int paste_selection(struct tty_struct *tty);
 extern int sel_loadlut(const unsigned long arg);
 extern int mouse_reporting(void);
diff -urN linux-2.5.70-bk16/include/linux/serial167.h linux-2.5.70-bk17/include/linux/serial167.h
--- linux-2.5.70-bk16/include/linux/serial167.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/serial167.h	2003-06-12 04:50:22.000000000 -0700
@@ -50,7 +50,6 @@
         int                     default_threshold;
         int                     default_timeout;
 	struct work_struct	tqueue;
-	struct termios		normal_termios;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
         struct cyclades_monitor mon;
diff -urN linux-2.5.70-bk16/include/linux/serialP.h linux-2.5.70-bk17/include/linux/serialP.h
--- linux-2.5.70-bk16/include/linux/serialP.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/serialP.h	2003-06-12 04:50:22.000000000 -0700
@@ -49,7 +49,6 @@
 	unsigned short	close_delay;
 	unsigned short	closing_wait; /* time to wait before closing */
 	struct async_icount	icount;	
-	struct termios		normal_termios;
 	int	io_type;
 	struct async_struct *info;
 	struct pci_dev	*dev;
diff -urN linux-2.5.70-bk16/include/linux/shmem_fs.h linux-2.5.70-bk17/include/linux/shmem_fs.h
--- linux-2.5.70-bk16/include/linux/shmem_fs.h	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/shmem_fs.h	2003-06-12 04:50:22.000000000 -0700
@@ -7,8 +7,6 @@
 
 #define SHMEM_NR_DIRECT 16
 
-extern atomic_t shmem_nrpages;
-
 struct shmem_inode_info {
 	spinlock_t		lock;
 	unsigned long		next_index;
diff -urN linux-2.5.70-bk16/include/linux/stallion.h linux-2.5.70-bk17/include/linux/stallion.h
--- linux-2.5.70-bk16/include/linux/stallion.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/stallion.h	2003-06-12 04:50:22.000000000 -0700
@@ -100,7 +100,6 @@
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 #endif
-	struct termios		normaltermios;
 	struct work_struct	tqueue;
 	comstats_t		stats;
 	stlrq_t			tx;
diff -urN linux-2.5.70-bk16/include/linux/sunrpc/auth.h linux-2.5.70-bk17/include/linux/sunrpc/auth.h
--- linux-2.5.70-bk16/include/linux/sunrpc/auth.h	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/sunrpc/auth.h	2003-06-12 04:50:22.000000000 -0700
@@ -127,6 +127,7 @@
 int			rpcauth_refreshcred(struct rpc_task *);
 void			rpcauth_invalcred(struct rpc_task *);
 int			rpcauth_uptodatecred(struct rpc_task *);
+int			rpcauth_deadcred(struct rpc_task *);
 void			rpcauth_init_credcache(struct rpc_auth *);
 void			rpcauth_free_credcache(struct rpc_auth *);
 
diff -urN linux-2.5.70-bk16/include/linux/sunrpc/gss_api.h linux-2.5.70-bk17/include/linux/sunrpc/gss_api.h
--- linux-2.5.70-bk16/include/linux/sunrpc/gss_api.h	2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/sunrpc/gss_api.h	2003-06-12 04:50:22.000000000 -0700
@@ -39,12 +39,12 @@
 u32 gss_get_mic(
 		struct gss_ctx		*ctx_id,
 		u32			qop,
-		struct xdr_netobj	*message_buffer,
-		struct xdr_netobj	*message_token);
+		struct xdr_netobj	*message,
+		struct xdr_netobj	*mic_token);
 u32 gss_verify_mic(
 		struct gss_ctx		*ctx_id,
-		struct xdr_netobj	*signbuf,
-		struct xdr_netobj	*checksum,
+		struct xdr_netobj	*message,
+		struct xdr_netobj	*mic_token,
 		u32			*qstate);
 u32 gss_delete_sec_context(
 		struct gss_ctx		**ctx_id);
@@ -95,12 +95,12 @@
 	u32 (*gss_get_mic)(
 			struct gss_ctx		*ctx_id,
 			u32			qop, 
-			struct xdr_netobj	*message_buffer,
-			struct xdr_netobj	*message_token);
+			struct xdr_netobj	*message,
+			struct xdr_netobj	*mic_token);
 	u32 (*gss_verify_mic)(
 			struct gss_ctx		*ctx_id,
-			struct xdr_netobj	*signbuf,
-			struct xdr_netobj	*checksum,
+			struct xdr_netobj	*message,
+			struct xdr_netobj	*mic_token,
 			u32			*qstate);
 	void (*gss_delete_sec_context)(
 			void			*internal_ctx_id);
diff -urN linux-2.5.70-bk16/include/linux/sunrpc/rpc_pipe_fs.h linux-2.5.70-bk17/include/linux/sunrpc/rpc_pipe_fs.h
--- linux-2.5.70-bk16/include/linux/sunrpc/rpc_pipe_fs.h	2003-05-26 18:00:28.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/sunrpc/rpc_pipe_fs.h	2003-06-12 04:50:22.000000000 -0700
@@ -24,6 +24,8 @@
 	int pipelen;
 	int nreaders;
 	wait_queue_head_t waitq;
+#define RPC_PIPE_WAIT_FOR_OPEN	1
+	int flags;
 	struct rpc_pipe_ops *ops;
 };
 
@@ -38,10 +40,11 @@
 
 extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
 extern int rpc_rmdir(char *);
-extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *);
+extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
 extern int rpc_unlink(char *);
 
 void __rpc_purge_current_upcall(struct file *);
+void __rpc_purge_one_upcall(struct file *filp, struct rpc_pipe_msg *target);
 
 #endif
 #endif
diff -urN linux-2.5.70-bk16/include/linux/sysdev.h linux-2.5.70-bk17/include/linux/sysdev.h
--- linux-2.5.70-bk16/include/linux/sysdev.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/sysdev.h	2003-06-12 04:50:22.000000000 -0700
@@ -72,6 +72,7 @@
 	u32		id;
 	struct sysdev_class	* cls;
 	struct kobject		kobj;
+	struct list_head	entry;
 };
 
 extern int sys_device_register(struct sys_device *);
diff -urN linux-2.5.70-bk16/include/linux/tiocl.h linux-2.5.70-bk17/include/linux/tiocl.h
--- linux-2.5.70-bk16/include/linux/tiocl.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk17/include/linux/tiocl.h	2003-06-12 04:50:22.000000000 -0700
@@ -0,0 +1,38 @@
+#ifndef _LINUX_TIOCL_H
+#define _LINUX_TIOCL_H
+
+#define TIOCL_SETSEL	2	/* set a selection */
+#define 	TIOCL_SELCHAR	0	/* select characters */
+#define 	TIOCL_SELWORD	1	/* select whole words */
+#define 	TIOCL_SELLINE	2	/* select whole lines */
+#define 	TIOCL_SELPOINTER	3	/* show the pointer */
+#define 	TIOCL_SELCLEAR	4	/* clear visibility of selection */
+#define 	TIOCL_SELMOUSEREPORT	16	/* report beginning of selection */
+#define 	TIOCL_SELBUTTONMASK	15	/* button mask for report */
+/* selection extent */
+struct tiocl_selection {
+	unsigned short xs;	/* X start */
+	unsigned short ys;	/* Y start */
+	unsigned short xe;	/* X end */
+	unsigned short ye;	/* Y end */
+	unsigned short sel_mode;	/* selection mode */
+};
+
+#define TIOCL_PASTESEL	3	/* paste previous selection */
+#define TIOCL_UNBLANKSCREEN	4	/* unblank screen */
+
+#define TIOCL_SELLOADLUT	5
+	/* set characters to be considered alphabetic when selecting */
+	/* u32[8] bit array, 4 bytes-aligned with type */
+
+/* these two don't return a value: they write it back in the type */
+#define TIOCL_GETSHIFTSTATE	6	/* write shift state */
+#define TIOCL_GETMOUSEREPORTING	7	/* write whether mouse event are reported */
+#define TIOCL_SETVESABLANK	10	/* set vesa blanking mode */
+#define TIOCL_SETKMSGREDIRECT	11	/* restrict kernel messages to a vt */
+#define TIOCL_GETFGCONSOLE	12	/* get foreground vt */
+#define TIOCL_SCROLLCONSOLE	13	/* scroll console */
+#define TIOCL_BLANKSCREEN	14	/* keep screen blank even if a key is pressed */
+#define TIOCL_BLANKEDSCREEN	15	/* return which vt was blanked */
+
+#endif /* _LINUX_TIOCL_H */
diff -urN linux-2.5.70-bk16/include/linux/tty_driver.h linux-2.5.70-bk17/include/linux/tty_driver.h
--- linux-2.5.70-bk16/include/linux/tty_driver.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/linux/tty_driver.h	2003-06-12 04:50:22.000000000 -0700
@@ -119,6 +119,39 @@
 #include <linux/list.h>
 #include <linux/cdev.h>
 
+struct tty_struct;
+
+struct tty_operations {
+	int  (*open)(struct tty_struct * tty, struct file * filp);
+	void (*close)(struct tty_struct * tty, struct file * filp);
+	int  (*write)(struct tty_struct * tty, int from_user,
+		      const unsigned char *buf, int count);
+	void (*put_char)(struct tty_struct *tty, unsigned char ch);
+	void (*flush_chars)(struct tty_struct *tty);
+	int  (*write_room)(struct tty_struct *tty);
+	int  (*chars_in_buffer)(struct tty_struct *tty);
+	int  (*ioctl)(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg);
+	void (*set_termios)(struct tty_struct *tty, struct termios * old);
+	void (*throttle)(struct tty_struct * tty);
+	void (*unthrottle)(struct tty_struct * tty);
+	void (*stop)(struct tty_struct *tty);
+	void (*start)(struct tty_struct *tty);
+	void (*hangup)(struct tty_struct *tty);
+	void (*break_ctl)(struct tty_struct *tty, int state);
+	void (*flush_buffer)(struct tty_struct *tty);
+	void (*set_ldisc)(struct tty_struct *tty);
+	void (*wait_until_sent)(struct tty_struct *tty, int timeout);
+	void (*send_xchar)(struct tty_struct *tty, char ch);
+	int (*read_proc)(char *page, char **start, off_t off,
+			  int count, int *eof, void *data);
+	int (*write_proc)(struct file *file, const char *buffer,
+			  unsigned long count, void *data);
+	int (*tiocmget)(struct tty_struct *tty, struct file *file);
+	int (*tiocmset)(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear);
+};
+
 struct tty_driver {
 	int	magic;		/* magic number for this structure */
 	struct cdev cdev;
@@ -134,21 +167,21 @@
 	short	subtype;	/* subtype of tty driver */
 	struct termios init_termios; /* Initial termios */
 	int	flags;		/* tty driver flags */
-	int	*refcount;	/* for loadable tty drivers */
+	int	refcount;	/* for loadable tty drivers */
 	struct proc_dir_entry *proc_entry; /* /proc fs entry */
 	struct tty_driver *other; /* only used for the PTY driver */
 
 	/*
 	 * Pointer to the tty data structures
 	 */
-	struct tty_struct **table;
+	struct tty_struct **ttys;
 	struct termios **termios;
 	struct termios **termios_locked;
 	void *driver_state;	/* only used for the PTY driver */
 	
 	/*
 	 * Interface routines from the upper tty layer to the tty
-	 * driver.
+	 * driver.	Will be replaced with struct tty_operations.
 	 */
 	int  (*open)(struct tty_struct * tty, struct file * filp);
 	void (*close)(struct tty_struct * tty, struct file * filp);
@@ -178,11 +211,16 @@
 	int (*tiocmget)(struct tty_struct *tty, struct file *file);
 	int (*tiocmset)(struct tty_struct *tty, struct file *file,
 			unsigned int set, unsigned int clear);
+
 	struct list_head tty_drivers;
 };
 
 extern struct list_head tty_drivers;
 
+struct tty_driver *alloc_tty_driver(int lines);
+void put_tty_driver(struct tty_driver *driver);
+void tty_set_operations(struct tty_driver *driver, struct tty_operations *op);
+
 /* tty driver magic number */
 #define TTY_DRIVER_MAGIC		0x5402
 
diff -urN linux-2.5.70-bk16/include/net/irda/ircomm_tty.h linux-2.5.70-bk17/include/net/irda/ircomm_tty.h
--- linux-2.5.70-bk16/include/net/irda/ircomm_tty.h	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/include/net/irda/ircomm_tty.h	2003-06-12 04:50:23.000000000 -0700
@@ -92,8 +92,6 @@
 	void *skey;
 	void *ckey;
 
-	struct termios	  normal_termios;
-
 	wait_queue_head_t open_wait;
 	wait_queue_head_t close_wait;
 	struct timer_list watchdog_timer;
diff -urN linux-2.5.70-bk16/include/pcmcia/cs.h linux-2.5.70-bk17/include/pcmcia/cs.h
--- linux-2.5.70-bk16/include/pcmcia/cs.h	2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk17/include/pcmcia/cs.h	2003-06-12 04:50:23.000000000 -0700
@@ -316,7 +316,7 @@
 
 /* Special stuff for binding drivers to sockets */
 typedef struct bind_req_t {
-    socket_t	Socket;
+    struct pcmcia_socket	*Socket;
     u_char	Function;
     dev_info_t	*dev_info;
 } bind_req_t;
@@ -325,7 +325,7 @@
 #define BIND_FN_ALL	0xff
 
 typedef struct mtd_bind_t {
-    socket_t	Socket;
+    struct pcmcia_socket	*Socket;
     u_int	Attributes;
     u_int	CardOffset;
     dev_info_t	*dev_info;
diff -urN linux-2.5.70-bk16/include/pcmcia/ss.h linux-2.5.70-bk17/include/pcmcia/ss.h
--- linux-2.5.70-bk16/include/pcmcia/ss.h	2003-05-26 18:00:59.000000000 -0700
+++ linux-2.5.70-bk17/include/pcmcia/ss.h	2003-06-12 04:50:23.000000000 -0700
@@ -31,6 +31,8 @@
 #define _LINUX_SS_H
 
 #include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bulkmem.h>
 #include <linux/device.h>
 
 /* Definitions for card status flags for GetStatus */
@@ -124,37 +126,138 @@
 /*
  * Socket operations.
  */
+struct pcmcia_socket;
+
 struct pccard_operations {
 	struct module *owner;
-	int (*init)(unsigned int sock);
-	int (*suspend)(unsigned int sock);
-	int (*register_callback)(unsigned int sock, void (*handler)(void *, unsigned int), void * info);
-	int (*inquire_socket)(unsigned int sock, socket_cap_t *cap);
-	int (*get_status)(unsigned int sock, u_int *value);
-	int (*get_socket)(unsigned int sock, socket_state_t *state);
-	int (*set_socket)(unsigned int sock, socket_state_t *state);
-	int (*set_io_map)(unsigned int sock, struct pccard_io_map *io);
-	int (*set_mem_map)(unsigned int sock, struct pccard_mem_map *mem);
-	void (*proc_setup)(unsigned int sock, struct proc_dir_entry *base);
+	int (*init)(struct pcmcia_socket *sock);
+	int (*suspend)(struct pcmcia_socket *sock);
+	int (*register_callback)(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info);
+	int (*inquire_socket)(struct pcmcia_socket *sock, socket_cap_t *cap);
+	int (*get_status)(struct pcmcia_socket *sock, u_int *value);
+	int (*get_socket)(struct pcmcia_socket *sock, socket_state_t *state);
+	int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state);
+	int (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io);
+	int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem);
+	void (*proc_setup)(struct pcmcia_socket *sock, struct proc_dir_entry *base);
 };
 
 /*
  *  Calls to set up low-level "Socket Services" drivers
  */
+struct pcmcia_socket;
 
 struct pcmcia_socket_class_data {
 	unsigned int nsock;			/* number of sockets */
 	unsigned int sock_offset;		/* socket # (which is
 	 * returned to driver) = sock_offset + (0, 1, .. , (nsock-1) */
 	struct pccard_operations *ops;		/* see above */
-	void *s_info;				/* socket_info_t */
+	struct pcmcia_socket *s_info;
 	struct class_device class_dev;		/* generic class structure */
 };
 
+typedef struct erase_busy_t {
+	eraseq_entry_t		*erase;
+	client_handle_t		client;
+	struct timer_list	timeout;
+	struct erase_busy_t	*prev, *next;
+} erase_busy_t;
+
+typedef struct io_window_t {
+	u_int			Attributes;
+	ioaddr_t		BasePort, NumPorts;
+	ioaddr_t		InUse, Config;
+} io_window_t;
+
+#define WINDOW_MAGIC	0xB35C
+typedef struct window_t {
+	u_short			magic;
+	u_short			index;
+	client_handle_t		handle;
+	struct pcmcia_socket 	*sock;
+	u_long			base;
+	u_long			size;
+	pccard_mem_map		ctl;
+} window_t;
+
+/* Maximum number of IO windows per socket */
+#define MAX_IO_WIN 2
+
+/* Maximum number of memory windows per socket */
+#define MAX_WIN 4
+
+struct config_t;
+struct region_t;
+
+struct pcmcia_socket {
+	spinlock_t			lock;
+	struct pccard_operations *	ss_entry;
+	socket_state_t			socket;
+	socket_cap_t			cap;
+	u_int				state;
+	u_short				functions;
+	u_short				lock_count;
+	client_handle_t			clients;
+	u_int				real_clients;
+	pccard_mem_map			cis_mem;
+	u_char				*cis_virt;
+	struct config_t			*config;
+	struct {
+		u_int			AssignedIRQ;
+		u_int			Config;
+	} irq;
+	io_window_t			io[MAX_IO_WIN];
+	window_t			win[MAX_WIN];
+	struct region_t			*c_region, *a_region;
+	erase_busy_t			erase_busy;
+	struct list_head		cis_cache;
+	u_int				fake_cis_len;
+	char				*fake_cis;
+
+	struct list_head		socket_list;
+
+ 	/* deprecated */
+	unsigned int			sock;		/* socket number */
+
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry		*proc;
+#endif
+
+	/* state thread */
+	struct semaphore		skt_sem;	/* protects socket h/w state */
+
+	struct task_struct		*thread;
+	struct completion		thread_done;
+	wait_queue_head_t		thread_wait;
+	spinlock_t			thread_lock;	/* protects thread_events */
+	unsigned int			thread_events;
+
+	/* pcmcia (16-bit) */
+	struct pcmcia_bus_socket	*pcmcia;
+
+	/* cardbus (32-bit) */
+#ifdef CONFIG_CARDBUS
+	struct resource *		cb_cis_res;
+	u_char				*cb_cis_virt;
+#endif
+
+	/* socket device */
+	struct class_device		dev;
+	void				*driver_data;	/* data internal to the socket driver */
+
+};
+
+struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr);
+
+
+
+extern int pcmcia_register_socket(struct pcmcia_socket *socket);
+extern void pcmcia_unregister_socket(struct pcmcia_socket *socket);
+
 extern struct class pcmcia_socket_class;
 
 /* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct pcmcia_socket_class_data *cls_d, u32 state, u32 level);
-extern int pcmcia_socket_dev_resume(struct pcmcia_socket_class_data *cls_d, u32 level);
+extern int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level);
+extern int pcmcia_socket_dev_resume(struct device *dev, u32 level);
 
 #endif /* _LINUX_SS_H */
diff -urN linux-2.5.70-bk16/kernel/ksyms.c linux-2.5.70-bk17/kernel/ksyms.c
--- linux-2.5.70-bk16/kernel/ksyms.c	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/kernel/ksyms.c	2003-06-12 04:50:24.000000000 -0700
@@ -403,7 +403,6 @@
 EXPORT_SYMBOL(del_timer);
 EXPORT_SYMBOL(request_irq);
 EXPORT_SYMBOL(free_irq);
-EXPORT_SYMBOL(irq_stat);
 
 /* waitqueue handling */
 EXPORT_SYMBOL(add_wait_queue);
diff -urN linux-2.5.70-bk16/kernel/resource.c linux-2.5.70-bk17/kernel/resource.c
--- linux-2.5.70-bk16/kernel/resource.c	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/kernel/resource.c	2003-06-12 04:50:24.000000000 -0700
@@ -82,20 +82,7 @@
 
 static int ioresources_open(struct file *file, struct resource *root)
 {
-	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	struct seq_file *m;
-	int res;
-
-	if (!buf)
-		return -ENOMEM;
-	res = single_open(file, ioresources_show, root);
-	if (!res) {
-		m = file->private_data;
-		m->buf = buf;
-		m->size = PAGE_SIZE;
-	} else
-		kfree(buf);
-	return res;
+	return single_open(file, ioresources_show, root);
 }
 
 static int ioports_open(struct inode *inode, struct file *file)
diff -urN linux-2.5.70-bk16/kernel/softirq.c linux-2.5.70-bk17/kernel/softirq.c
--- linux-2.5.70-bk16/kernel/softirq.c	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/kernel/softirq.c	2003-06-12 04:50:24.000000000 -0700
@@ -34,7 +34,10 @@
    - Tasklets: serialized wrt itself.
  */
 
+#ifndef __ARCH_IRQ_STAT
 irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned;
+EXPORT_SYMBOL(irq_stat);
+#endif
 
 static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp;
 
@@ -322,7 +325,7 @@
 	__set_current_state(TASK_INTERRUPTIBLE);
 	mb();
 
-	ksoftirqd_task(cpu) = current;
+	local_ksoftirqd_task() = current;
 
 	for (;;) {
 		if (!local_softirq_pending())
diff -urN linux-2.5.70-bk16/kernel/sys.c linux-2.5.70-bk17/kernel/sys.c
--- linux-2.5.70-bk16/kernel/sys.c	2003-05-26 18:00:23.000000000 -0700
+++ linux-2.5.70-bk17/kernel/sys.c	2003-06-12 04:50:24.000000000 -0700
@@ -392,8 +392,10 @@
 
 	/* For safety, we require "magic" arguments. */
 	if (magic1 != LINUX_REBOOT_MAGIC1 ||
-	    (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
-			magic2 != LINUX_REBOOT_MAGIC2B))
+	    (magic2 != LINUX_REBOOT_MAGIC2 &&
+	                magic2 != LINUX_REBOOT_MAGIC2A &&
+			magic2 != LINUX_REBOOT_MAGIC2B &&
+	                magic2 != LINUX_REBOOT_MAGIC2C))
 		return -EINVAL;
 
 	lock_kernel();
diff -urN linux-2.5.70-bk16/lib/kobject.c linux-2.5.70-bk17/lib/kobject.c
--- linux-2.5.70-bk16/lib/kobject.c	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/lib/kobject.c	2003-06-12 04:50:25.000000000 -0700
@@ -252,14 +252,15 @@
 
 	if (kobj->kset) {
 		down_write(&kobj->kset->subsys->rwsem);
-		if (parent) 
-			list_add_tail(&kobj->entry,&parent->entry);
-		else {
-			list_add_tail(&kobj->entry,&kobj->kset->list);
-			kobj->parent = kobject_get(&kobj->kset->kobj);
-		}
+
+		if (!parent)
+			parent = kobject_get(&kobj->kset->kobj);
+
+		list_add_tail(&kobj->entry,&kobj->kset->list);
 		up_write(&kobj->kset->subsys->rwsem);
 	}
+	kobj->parent = parent;
+
 	error = create_dir(kobj);
 	if (error)
 		unlink(kobj);
diff -urN linux-2.5.70-bk16/mm/shmem.c linux-2.5.70-bk17/mm/shmem.c
--- linux-2.5.70-bk16/mm/shmem.c	2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk17/mm/shmem.c	2003-06-12 04:50:25.000000000 -0700
@@ -6,8 +6,22 @@
  *		 2000-2001 Christoph Rohland
  *		 2000-2001 SAP AG
  *		 2002 Red Hat Inc.
+ * Copyright (C) 2002-2003 Hugh Dickins.
+ * Copyright (C) 2002-2003 VERITAS Software Corporation.
  *
- * This file is released under the GPL.
+ *  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
  */
 
 /*
@@ -128,9 +142,8 @@
 	.memory_backed	= 1,	/* Does not contribute to dirty memory */
 };
 
-LIST_HEAD (shmem_inodes);
+LIST_HEAD(shmem_inodes);
 static spinlock_t shmem_ilock = SPIN_LOCK_UNLOCKED;
-atomic_t shmem_nrpages = ATOMIC_INIT(0); /* Not used right now */
 
 static void shmem_free_block(struct inode *inode)
 {
@@ -488,16 +501,6 @@
 	}
 done2:
 	BUG_ON(info->swapped > info->next_index);
-	if (inode->i_mapping->nrpages) {
-		/*
-		 * Call truncate_inode_pages again: racing shmem_unuse_inode
-		 * may have swizzled a page in from swap since vmtruncate or
-		 * generic_delete_inode did it, before we lowered next_index.
-		 */
-		spin_unlock(&info->lock);
-		truncate_inode_pages(inode->i_mapping, inode->i_size);
-		spin_lock(&info->lock);
-	}
 	shmem_recalc_inode(inode);
 	spin_unlock(&info->lock);
 }
@@ -579,6 +582,7 @@
 
 static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
 {
+	struct inode *inode;
 	unsigned long idx;
 	unsigned long size;
 	unsigned long limit;
@@ -643,8 +647,15 @@
 	spin_unlock(&info->lock);
 	return 0;
 found:
-	if (move_from_swap_cache(page, idx + offset,
-			info->vfs_inode.i_mapping) == 0)
+	idx += offset;
+	inode = &info->vfs_inode;
+
+	/* Racing against delete or truncate? Must leave out of page cache */
+	limit = (inode->i_state & I_FREEING)? 0:
+		(inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+	if (idx >= limit ||
+	    move_from_swap_cache(page, idx, inode->i_mapping) == 0)
 		shmem_swp_set(info, ptr + offset, 0);
 	shmem_swp_unmap(ptr);
 	spin_unlock(&info->lock);
@@ -653,7 +664,7 @@
 	 * try_to_unuse will skip over mms, then reincrement count.
 	 */
 	swap_free(entry);
-	return 1;
+	return idx < limit;
 }
 
 /*
@@ -967,7 +978,7 @@
 	size = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	if (pgoff >= size || pgoff + (len >> PAGE_SHIFT) > size)
 		return -EINVAL;
-	
+
 	while ((long) len > 0) {
 		struct page *page = NULL;
 		int err;
@@ -1186,30 +1197,32 @@
 			left = __copy_from_user(kaddr + offset, buf, bytes);
 			kunmap(page);
 		}
+
+		written += bytes;
+		count -= bytes;
+		pos += bytes;
+		buf += bytes;
+		if (pos > inode->i_size)
+			inode->i_size = pos;
+
 		flush_dcache_page(page);
+		set_page_dirty(page);
+		if (!PageReferenced(page))
+			SetPageReferenced(page);
+		page_cache_release(page);
+
 		if (left) {
-			page_cache_release(page);
+			pos -= left;
+			written -= left;
 			err = -EFAULT;
 			break;
 		}
 
-		if (!PageReferenced(page))
-			SetPageReferenced(page);
-		set_page_dirty(page);
-		page_cache_release(page);
-
 		/*
 		 * Our dirty pages are not counted in nr_dirty,
 		 * and we do not attempt to balance dirty pages.
 		 */
 
-		written += bytes;
-		count -= bytes;
-		pos += bytes;
-		buf += bytes;
-		if (pos > inode->i_size)
-			inode->i_size = pos;
-
 		cond_resched();
 	} while (count);
 
diff -urN linux-2.5.70-bk16/net/bluetooth/rfcomm/tty.c linux-2.5.70-bk17/net/bluetooth/rfcomm/tty.c
--- linux-2.5.70-bk16/net/bluetooth/rfcomm/tty.c	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/net/bluetooth/rfcomm/tty.c	2003-06-12 04:50:26.000000000 -0700
@@ -852,31 +852,10 @@
 }
 
 /* ---- TTY structure ---- */
-static int    rfcomm_tty_refcount;       /* If we manage several devices */
 
-static struct tty_struct *rfcomm_tty_table[RFCOMM_TTY_PORTS];
-static struct termios *rfcomm_tty_termios[RFCOMM_TTY_PORTS];
-static struct termios *rfcomm_tty_termios_locked[RFCOMM_TTY_PORTS];
-
-static struct tty_driver rfcomm_tty_driver = {
-	.owner			= THIS_MODULE,
-
-	.magic			= TTY_DRIVER_MAGIC,
-	.driver_name		= "rfcomm",
-	.devfs_name		= "bluetooth/rfcomm/",
-	.name			= "rfcomm",
-	.major			= RFCOMM_TTY_MAJOR,
-	.minor_start		= RFCOMM_TTY_MINOR,
-	.num			= RFCOMM_TTY_PORTS,
-	.type			= TTY_DRIVER_TYPE_SERIAL,
-	.subtype		= SERIAL_TYPE_NORMAL,
-	.flags			= TTY_DRIVER_REAL_RAW,
-
-	.refcount		= &rfcomm_tty_refcount,
-	.table			= rfcomm_tty_table,
-	.termios		= rfcomm_tty_termios,
-	.termios_locked		= rfcomm_tty_termios_locked,
+static struct tty_driver *rfcomm_tty_driver;
 
+static struct tty_operations rfcomm_ops = {
 	.open			= rfcomm_tty_open,
 	.close			= rfcomm_tty_close,
 	.write			= rfcomm_tty_write,
@@ -888,8 +867,6 @@
 	.unthrottle		= rfcomm_tty_unthrottle,
 	.set_termios		= rfcomm_tty_set_termios,
 	.send_xchar		= rfcomm_tty_send_xchar,
-	.stop			= NULL,
-	.start			= NULL,
 	.hangup			= rfcomm_tty_hangup,
 	.wait_until_sent	= rfcomm_tty_wait_until_sent,
 	.read_proc		= rfcomm_tty_read_proc,
@@ -899,17 +876,27 @@
 {
 	int i;
 
-	/* Initialize our global data */
-	for (i = 0; i < RFCOMM_TTY_PORTS; i++)
-		rfcomm_tty_table[i] = NULL;
-
-	/* Register the TTY driver */
-	rfcomm_tty_driver.init_termios = tty_std_termios;
-	rfcomm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rfcomm_tty_driver.flags = TTY_DRIVER_REAL_RAW;
+	rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
+	if (!rfcomm_tty_driver)
+		return -1;
+
+	rfcomm_tty_driver->owner	= THIS_MODULE,
+	rfcomm_tty_driver->driver_name	= "rfcomm",
+	rfcomm_tty_driver->devfs_name	= "bluetooth/rfcomm/",
+	rfcomm_tty_driver->name		= "rfcomm",
+	rfcomm_tty_driver->major	= RFCOMM_TTY_MAJOR,
+	rfcomm_tty_driver->minor_start	= RFCOMM_TTY_MINOR,
+	rfcomm_tty_driver->type		= TTY_DRIVER_TYPE_SERIAL,
+	rfcomm_tty_driver->subtype	= SERIAL_TYPE_NORMAL,
+	rfcomm_tty_driver->flags	= TTY_DRIVER_REAL_RAW,
+	rfcomm_tty_driver->init_termios = tty_std_termios;
+	rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
 
-	if (tty_register_driver(&rfcomm_tty_driver)) {
+	if (tty_register_driver(rfcomm_tty_driver)) {
 		BT_ERR("Can't register RFCOMM TTY driver");
+		put_tty_driver(rfcomm_tty_driver);
 		return -1;
 	}
 
@@ -920,6 +907,6 @@
 
 void rfcomm_cleanup_ttys(void)
 {
-	tty_unregister_driver(&rfcomm_tty_driver);
-	return;
+	tty_unregister_driver(rfcomm_tty_driver);
+	put_tty_driver(rfcomm_tty_driver);
 }
diff -urN linux-2.5.70-bk16/net/irda/ircomm/ircomm_tty.c linux-2.5.70-bk17/net/irda/ircomm/ircomm_tty.c
--- linux-2.5.70-bk16/net/irda/ircomm/ircomm_tty.c	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/net/irda/ircomm/ircomm_tty.c	2003-06-12 04:50:28.000000000 -0700
@@ -74,15 +74,31 @@
 static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
 				int *eof, void *unused);
 #endif /* CONFIG_PROC_FS */
-static struct tty_driver driver;
-static int ircomm_tty_refcount;       /* If we manage several devices */
-
-static struct tty_struct *ircomm_tty_table[NR_PTYS];
-static struct termios *ircomm_tty_termios[NR_PTYS];
-static struct termios *ircomm_tty_termios_locked[NR_PTYS];
+static struct tty_driver *driver;
 
 hashbin_t *ircomm_tty = NULL;
 
+static struct tty_operations ops = {
+	.open            = ircomm_tty_open,
+	.close           = ircomm_tty_close,
+	.write           = ircomm_tty_write,
+	.write_room      = ircomm_tty_write_room,
+	.chars_in_buffer = ircomm_tty_chars_in_buffer,
+	.flush_buffer    = ircomm_tty_flush_buffer,
+	.ioctl           = ircomm_tty_ioctl,
+	.throttle        = ircomm_tty_throttle,
+	.unthrottle      = ircomm_tty_unthrottle,
+	.send_xchar      = ircomm_tty_send_xchar,
+	.set_termios     = ircomm_tty_set_termios,
+	.stop            = ircomm_tty_stop,
+	.start           = ircomm_tty_start,
+	.hangup          = ircomm_tty_hangup,
+	.wait_until_sent = ircomm_tty_wait_until_sent,
+#ifdef CONFIG_PROC_FS
+	.read_proc       = ircomm_tty_read_proc,
+#endif /* CONFIG_PROC_FS */
+};
+
 /*
  * Function ircomm_tty_init()
  *
@@ -90,49 +106,30 @@
  *
  */
 int __init ircomm_tty_init(void)
-{	
+{
+	driver = alloc_tty_driver(IRCOMM_TTY_PORTS);
+	if (!driver)
+		return -ENOMEM;
 	ircomm_tty = hashbin_new(HB_LOCK); 
 	if (ircomm_tty == NULL) {
 		ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
+		put_tty_driver(driver);
 		return -ENOMEM;
 	}
 
-	memset(&driver, 0, sizeof(struct tty_driver));
-	driver.magic           = TTY_DRIVER_MAGIC;
-	driver.driver_name     = "ircomm";
-	driver.name            = "ircomm";
-	driver.major           = IRCOMM_TTY_MAJOR;
-	driver.minor_start     = IRCOMM_TTY_MINOR;
-	driver.num             = IRCOMM_TTY_PORTS;
-	driver.type            = TTY_DRIVER_TYPE_SERIAL;
-	driver.subtype         = SERIAL_TYPE_NORMAL;
-	driver.init_termios    = tty_std_termios;
-	driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	driver.flags           = TTY_DRIVER_REAL_RAW;
-	driver.refcount        = &ircomm_tty_refcount;
-	driver.table           = ircomm_tty_table;
-	driver.termios         = ircomm_tty_termios;
-	driver.termios_locked  = ircomm_tty_termios_locked;
-	driver.open            = ircomm_tty_open;
-	driver.close           = ircomm_tty_close;
-	driver.write           = ircomm_tty_write;
-	driver.write_room      = ircomm_tty_write_room;
-	driver.chars_in_buffer = ircomm_tty_chars_in_buffer;
-	driver.flush_buffer    = ircomm_tty_flush_buffer;
-	driver.ioctl           = ircomm_tty_ioctl;
-	driver.throttle        = ircomm_tty_throttle;
-	driver.unthrottle      = ircomm_tty_unthrottle;
-	driver.send_xchar      = ircomm_tty_send_xchar;
-	driver.set_termios     = ircomm_tty_set_termios;
-	driver.stop            = ircomm_tty_stop;
-	driver.start           = ircomm_tty_start;
-	driver.hangup          = ircomm_tty_hangup;
-	driver.wait_until_sent = ircomm_tty_wait_until_sent;
-#ifdef CONFIG_PROC_FS
-	driver.read_proc       = ircomm_tty_read_proc;
-#endif /* CONFIG_PROC_FS */
-	if (tty_register_driver(&driver)) {
+	driver->driver_name     = "ircomm";
+	driver->name            = "ircomm";
+	driver->major           = IRCOMM_TTY_MAJOR;
+	driver->minor_start     = IRCOMM_TTY_MINOR;
+	driver->type            = TTY_DRIVER_TYPE_SERIAL;
+	driver->subtype         = SERIAL_TYPE_NORMAL;
+	driver->init_termios    = tty_std_termios;
+	driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	driver->flags           = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(driver, &ops);
+	if (tty_register_driver(driver)) {
 		ERROR("%s(): Couldn't register serial driver\n", __FUNCTION__);
+		put_tty_driver(driver);
 		return -1;
 	}
 	return 0;
@@ -163,13 +160,14 @@
 
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	
 
-	ret = tty_unregister_driver(&driver);
+	ret = tty_unregister_driver(driver);
         if (ret) {
                 ERROR("%s(), failed to unregister driver\n", __FUNCTION__);
 		return;
 	}
 
 	hashbin_delete(ircomm_tty, (FREE_FUNC) __ircomm_tty_cleanup);
+	put_tty_driver(driver);
 }
 
 /*
diff -urN linux-2.5.70-bk16/net/sunrpc/auth.c linux-2.5.70-bk17/net/sunrpc/auth.c
--- linux-2.5.70-bk16/net/sunrpc/auth.c	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk17/net/sunrpc/auth.c	2003-06-12 04:50:30.000000000 -0700
@@ -369,3 +369,9 @@
 		(task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
 }
 
+int
+rpcauth_deadcred(struct rpc_task *task)
+{
+	return !(task->tk_msg.rpc_cred) ||
+		(task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_DEAD);
+}
diff -urN linux-2.5.70-bk16/net/sunrpc/auth_gss/auth_gss.c linux-2.5.70-bk17/net/sunrpc/auth_gss/auth_gss.c
--- linux-2.5.70-bk16/net/sunrpc/auth_gss/auth_gss.c	2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk17/net/sunrpc/auth_gss/auth_gss.c	2003-06-12 04:50:30.000000000 -0700
@@ -156,7 +156,7 @@
 }
 
 static struct gss_cl_ctx *
-gss_cred_get_ctx(struct rpc_cred *cred)
+gss_cred_get_uptodate_ctx(struct rpc_cred *cred)
 {
 	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
 	struct gss_cl_ctx *ctx = NULL;
@@ -206,9 +206,22 @@
 	return 0;
 }
 
+static struct gss_cl_ctx *
+gss_cred_get_ctx(struct rpc_cred *cred)
+{
+	struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+	struct gss_cl_ctx *ctx = NULL;
+
+	read_lock(&gss_ctx_lock);
+	if (gss_cred->gc_ctx)
+		ctx = gss_get_ctx(gss_cred->gc_ctx);
+	read_unlock(&gss_ctx_lock);
+	return ctx;
+}
+
 static int
 gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
-		struct gss_cl_ctx **gc, uid_t *uid)
+		struct gss_cl_ctx **gc, uid_t *uid, int *gss_err)
 {
 	char *end = buf->data + buf->len;
 	char *p = buf->data;
@@ -231,8 +244,17 @@
 	/* FIXME: discarded timeout for now */
 	if (simple_get_bytes(&p, end, &timeout, sizeof(timeout)))
 		goto err_free_ctx;
+	*gss_err = 0;
 	if (simple_get_bytes(&p, end, &ctx->gc_win, sizeof(ctx->gc_win)))
 		goto err_free_ctx;
+	/* gssd signals an error by passing ctx->gc_win = 0: */
+	if (!ctx->gc_win) {
+		/* in which case the next int is an error code: */
+		if (simple_get_bytes(&p, end, gss_err, sizeof(*gss_err)))
+			goto err_free_ctx;
+		err = 0;
+		goto err_free_ctx;
+	}
 	if (simple_get_netobj(&p, end, &tmp_buf))
 		goto err_free_ctx;
 	if (dup_netobj(&tmp_buf, &ctx->gc_wire_ctx)) {
@@ -261,6 +283,7 @@
 struct gss_upcall_msg {
 	struct rpc_pipe_msg msg;
 	struct list_head list;
+	struct gss_auth *auth;
 	struct rpc_wait_queue waitq;
 	uid_t	uid;
 	atomic_t count;
@@ -296,8 +319,6 @@
 	gss_msg = gss_find_upcall(gss_auth, task->tk_msg.rpc_cred->cr_uid);
 	if (gss_msg) {
 		rpc_wake_up(&gss_msg->waitq);
-		list_del(&gss_msg->list);
-		gss_release_msg(gss_msg);
 	}
 	spin_unlock(&gss_auth->lock);
 }
@@ -328,19 +349,24 @@
 	memset(gss_new, 0, sizeof(*gss_new));
 	INIT_LIST_HEAD(&gss_new->list);
 	INIT_RPC_WAITQ(&gss_new->waitq, "RPCSEC_GSS upcall waitq");
-	atomic_set(&gss_new->count, 2);
+	atomic_set(&gss_new->count, 1);
 	msg = &gss_new->msg;
 	msg->data = &gss_new->uid;
 	msg->len = sizeof(gss_new->uid);
 	gss_new->uid = uid;
+	gss_new->auth = gss_auth;
 	list_add(&gss_new->list, &gss_auth->upcalls);
 	gss_new = NULL;
+	task->tk_timeout = 5 * HZ;
 	rpc_sleep_on(&gss_msg->waitq, task, gss_release_callback, NULL);
 	spin_unlock(&gss_auth->lock);
 	res = rpc_queue_upcall(dentry->d_inode, msg);
 	spin_lock(&gss_auth->lock);
-	if (res)
+	if (res) {
+		rpc_wake_up(&gss_msg->waitq);
+		list_del(&gss_msg->list);
 		gss_release_msg(gss_msg);
+	}
 	return res;
 out_sleep:
 	rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
@@ -354,13 +380,12 @@
 		char *dst, size_t buflen)
 {
 	char *data = (char *)msg->data + msg->copied;
-	ssize_t mlen = msg->len - msg->copied;
+	ssize_t mlen = msg->len;
 	ssize_t left;
 
 	if (mlen > buflen)
 		mlen = buflen;
 	left = copy_to_user(dst, data, mlen);
-	msg->copied += mlen - left;
 	return mlen - left;
 }
 
@@ -381,9 +406,10 @@
 	struct auth_cred acred = { 0 };
 	struct rpc_cred *cred;
 	struct gss_upcall_msg *gss_msg;
-	struct gss_cl_ctx *ctx;
+	struct gss_cl_ctx *ctx = NULL;
 	ssize_t left;
 	int err;
+	int gss_err;
 
 	if (mlen > sizeof(buf))
 		return -ENOSPC;
@@ -395,23 +421,30 @@
 	auth = clnt->cl_auth;
 	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
 	mech = gss_auth->mech;
-	err = gss_parse_init_downcall(mech, &obj, &ctx, &acred.uid);
+	err = gss_parse_init_downcall(mech, &obj, &ctx, &acred.uid, &gss_err);
 	if (err)
 		goto err;
 	cred = rpcauth_lookup_credcache(auth, &acred, 0);
 	if (!cred)
-		goto err_release_ctx;
-	gss_cred_set_ctx(cred, ctx);
+		goto err;
+	if (gss_err)
+		cred->cr_flags |= RPCAUTH_CRED_DEAD;
+	else
+		gss_cred_set_ctx(cred, ctx);
 	spin_lock(&gss_auth->lock);
 	gss_msg = gss_find_upcall(gss_auth, acred.uid);
-	if (gss_msg)
+	if (gss_msg) {
+		list_del(&gss_msg->list);
+		__rpc_purge_one_upcall(filp, &gss_msg->msg);
 		rpc_wake_up(&gss_msg->waitq);
+		gss_release_msg(gss_msg);
+	}
 	spin_unlock(&gss_auth->lock);
 	rpc_release_client(clnt);
 	return mlen;
-err_release_ctx:
-	gss_destroy_ctx(ctx);
 err:
+	if (ctx)
+		gss_destroy_ctx(ctx);
 	rpc_release_client(clnt);
 	dprintk("RPC: gss_pipe_downcall returning %d\n", err);
 	return err;
@@ -421,9 +454,13 @@
 gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
 {
 	struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg);
+	struct gss_auth *gss_auth = gss_msg->auth;
 
+	spin_lock(&gss_auth->lock);
+	list_del(&gss_msg->list);
 	rpc_wake_up(&gss_msg->waitq);
 	gss_release_msg(gss_msg);
+	spin_unlock(&gss_auth->lock);
 }
 
 /* 
@@ -459,7 +496,7 @@
 	snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
 			clnt->cl_pathname,
 			gss_auth->mech->gm_ops->name);
-	gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops);
+	gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
 	if (IS_ERR(gss_auth->dentry))
 		goto err_free;
 
@@ -637,7 +674,7 @@
 
 	task->tk_timeout = xprt->timeout.to_current;
 	spin_lock(&gss_auth->lock);
-	if (gss_cred_get_ctx(cred))
+	if (gss_cred_get_uptodate_ctx(cred))
 		goto out;
 	err = gss_upcall(clnt, task, cred->cr_uid);
 out:
@@ -648,8 +685,8 @@
 static u32 *
 gss_validate(struct rpc_task *task, u32 *p)
 {
-	struct gss_cred *cred = (struct gss_cred *)task->tk_msg.rpc_cred; 
-	struct gss_cl_ctx	*ctx = cred->gc_ctx;
+	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
 	u32		seq, qop_state;
 	struct xdr_netobj bufin;
 	struct xdr_netobj bufout;
diff -urN linux-2.5.70-bk16/net/sunrpc/auth_gss/gss_mech_switch.c linux-2.5.70-bk17/net/sunrpc/auth_gss/gss_mech_switch.c
--- linux-2.5.70-bk16/net/sunrpc/auth_gss/gss_mech_switch.c	2003-05-26 18:00:42.000000000 -0700
+++ linux-2.5.70-bk17/net/sunrpc/auth_gss/gss_mech_switch.c	2003-06-12 04:50:30.000000000 -0700
@@ -190,33 +190,33 @@
 		->gss_import_sec_context(input_token, *ctx_id);
 }
 
-/* gss_verify_mic: hash messages_buffer and return gss verify token. */
+/* gss_get_mic: compute a mic over message and return mic_token. */
 
 u32
 gss_get_mic(struct gss_ctx	*context_handle,
 	    u32			qop,
-	    struct xdr_netobj	*message_buffer,
-	    struct xdr_netobj	*message_token)
+	    struct xdr_netobj	*message,
+	    struct xdr_netobj	*mic_token)
 {
 	 return context_handle->mech_type->gm_ops
 		->gss_get_mic(context_handle,
 			      qop,
-			      message_buffer,
-			      message_token);
+			      message,
+			      mic_token);
 }
 
-/* gss_verify_mic: hash messages_buffer and return gss verify token. */
+/* gss_verify_mic: check whether the provided mic_token verifies message. */
 
 u32
 gss_verify_mic(struct gss_ctx		*context_handle,
-		struct xdr_netobj	*signbuf,
-		struct xdr_netobj	*checksum,
-		u32			*qstate)
+	       struct xdr_netobj	*message,
+	       struct xdr_netobj	*mic_token,
+	       u32			*qstate)
 {
 	return context_handle->mech_type->gm_ops
 		->gss_verify_mic(context_handle,
-				 signbuf,
-				 checksum,
+				 message,
+				 mic_token,
 				 qstate);
 }
 
diff -urN linux-2.5.70-bk16/net/sunrpc/clnt.c linux-2.5.70-bk17/net/sunrpc/clnt.c
--- linux-2.5.70-bk16/net/sunrpc/clnt.c	2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk17/net/sunrpc/clnt.c	2003-06-12 04:50:30.000000000 -0700
@@ -850,17 +850,16 @@
 
 	task->tk_status = 0;
 	task->tk_action = call_reserve;
-	if (status >= 0)
+	if (status >= 0 && rpcauth_uptodatecred(task))
+		return;
+	if (rpcauth_deadcred(task)) {
+		rpc_exit(task, -EACCES);
 		return;
-	switch (status) {
-		case -EPIPE:
-			rpc_delay(task, 3*HZ);
-		case -ETIMEDOUT:
-			task->tk_action = call_refresh;
-			break;
-		default:
-			rpc_exit(task, -EACCES);
 	}
+	task->tk_action = call_refresh;
+	if (status != -ETIMEDOUT)
+		rpc_delay(task, 3*HZ);
+	return;
 }
 
 /*
@@ -909,6 +908,8 @@
 		switch ((n = ntohl(*p++))) {
 		case RPC_AUTH_REJECTEDCRED:
 		case RPC_AUTH_REJECTEDVERF:
+		case RPCSEC_GSS_CREDPROBLEM:
+		case RPCSEC_GSS_CTXPROBLEM:
 			if (!task->tk_cred_retry)
 				break;
 			task->tk_cred_retry--;
diff -urN linux-2.5.70-bk16/net/sunrpc/rpc_pipe.c linux-2.5.70-bk17/net/sunrpc/rpc_pipe.c
--- linux-2.5.70-bk16/net/sunrpc/rpc_pipe.c	2003-05-26 18:00:27.000000000 -0700
+++ linux-2.5.70-bk17/net/sunrpc/rpc_pipe.c	2003-06-12 04:50:30.000000000 -0700
@@ -75,6 +75,28 @@
 		msg->errno = 0;
 }
 
+void
+__rpc_purge_one_upcall(struct file *filp, struct rpc_pipe_msg *target)
+{
+	struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+	struct rpc_pipe_msg *msg;
+
+	msg = filp->private_data;
+	if (msg == target) {
+		filp->private_data = NULL;
+		goto found;
+	}
+	list_for_each_entry(msg, &rpci->pipe, list) {
+		if (msg == target) {
+			list_del(&msg->list);
+			goto found;
+		}
+	}
+	BUG();
+found:
+	return;
+}
+
 int
 rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
 {
@@ -82,7 +104,7 @@
 	int res = 0;
 
 	down(&inode->i_sem);
-	if (rpci->nreaders) {
+	if (rpci->nreaders || (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN)) {
 		list_add_tail(&msg->list, &rpci->pipe);
 		rpci->pipelen += msg->len;
 	} else
@@ -149,7 +171,7 @@
 	down(&inode->i_sem);
 	if (filp->f_mode & FMODE_READ)
 		rpci->nreaders --;
-	if (!rpci->nreaders)
+	if (!rpci->nreaders && !(rpci->flags & RPC_PIPE_WAIT_FOR_OPEN))
 		__rpc_purge_upcall(inode, -EPIPE);
 	up(&inode->i_sem);
 	return 0;
@@ -273,6 +295,8 @@
 			clnt->cl_prog, clnt->cl_vers);
 	seq_printf(m, "address: %u.%u.%u.%u\n",
 			NIPQUAD(clnt->cl_xprt->addr.sin_addr.s_addr));
+	seq_printf(m, "protocol: %s\n",
+			clnt->cl_xprt->prot == IPPROTO_UDP ? "udp" : "tcp");
 	return 0;
 }
 
@@ -644,7 +668,7 @@
 }
 
 struct dentry *
-rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops)
+rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
 {
 	struct nameidata nd;
 	struct dentry *dentry;
@@ -663,6 +687,7 @@
 	d_instantiate(dentry, inode);
 	rpci = RPC_I(inode);
 	rpci->private = private;
+	rpci->flags = flags;
 	rpci->ops = ops;
 	inode_dir_notify(dir, DN_CREATE);
 out:
diff -urN linux-2.5.70-bk16/net/sunrpc/sunrpc_syms.c linux-2.5.70-bk17/net/sunrpc/sunrpc_syms.c
--- linux-2.5.70-bk16/net/sunrpc/sunrpc_syms.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk17/net/sunrpc/sunrpc_syms.c	2003-06-12 04:50:30.000000000 -0700
@@ -57,6 +57,7 @@
 EXPORT_SYMBOL(rpc_queue_upcall);
 EXPORT_SYMBOL(rpc_mkpipe);
 EXPORT_SYMBOL(__rpc_purge_current_upcall);
+EXPORT_SYMBOL(__rpc_purge_one_upcall);
 
 /* Client transport */
 EXPORT_SYMBOL(xprt_create_proto);
diff -urN linux-2.5.70-bk16/net/sunrpc/xprt.c linux-2.5.70-bk17/net/sunrpc/xprt.c
--- linux-2.5.70-bk16/net/sunrpc/xprt.c	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/net/sunrpc/xprt.c	2003-06-12 04:50:30.000000000 -0700
@@ -678,7 +678,8 @@
 	struct rpc_xprt	*xprt;
 	struct rpc_rqst *rovr;
 	struct sk_buff	*skb;
-	int		err, repsize, copied;
+	int err, repsize, copied;
+	u32 xid;
 
 	read_lock(&sk->sk_callback_lock);
 	dprintk("RPC:      udp_data_ready...\n");
@@ -701,16 +702,18 @@
 		goto dropit;
 	}
 
+	/* Copy the XID from the skb... */
+	if (skb_copy_bits(skb, sizeof(struct udphdr), &xid, sizeof(xid)) < 0)
+		goto dropit;
+
 	/* Look up and lock the request corresponding to the given XID */
 	spin_lock(&xprt->sock_lock);
-	rovr = xprt_lookup_rqst(xprt, *(u32 *) (skb->h.raw + sizeof(struct udphdr)));
+	rovr = xprt_lookup_rqst(xprt, xid);
 	if (!rovr)
 		goto out_unlock;
 	task = rovr->rq_task;
 
 	dprintk("RPC: %4d received reply\n", task->tk_pid);
-	xprt_pktdump("packet data:",
-		     (u32 *) (skb->h.raw+sizeof(struct udphdr)), repsize);
 
 	if ((copied = rovr->rq_rlen) > repsize)
 		copied = repsize;
diff -urN linux-2.5.70-bk16/net/x25/x25_facilities.c linux-2.5.70-bk17/net/x25/x25_facilities.c
--- linux-2.5.70-bk16/net/x25/x25_facilities.c	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk17/net/x25/x25_facilities.c	2003-06-12 04:50:30.000000000 -0700
@@ -105,8 +105,8 @@
 			printk(KERN_DEBUG "X.25: unknown facility %02X, "
 			       "length %d, values %02X, %02X, %02X, %02X\n",
 			       p[0], p[1], p[2], p[3], p[4], p[5]);
-			p   += p[1] + 2;
 			len -= p[1] + 2;
+			p   += p[1] + 2;
 			break;
 		}
 	}
diff -urN linux-2.5.70-bk16/sound/oss/emu10k1/audio.c linux-2.5.70-bk17/sound/oss/emu10k1/audio.c
--- linux-2.5.70-bk16/sound/oss/emu10k1/audio.c	2003-05-26 18:00:23.000000000 -0700
+++ linux-2.5.70-bk17/sound/oss/emu10k1/audio.c	2003-06-12 04:50:32.000000000 -0700
@@ -1187,7 +1187,8 @@
 
 		if ((woinst = (struct woinst *) kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
 			ERROR();
-			return -ENODEV;
+			kfree(wave_dev);
+			return -ENOMEM;
 		}
 
 		if (wave_dev->wiinst != NULL) {
diff -urN linux-2.5.70-bk16/sound/oss/i810_audio.c linux-2.5.70-bk17/sound/oss/i810_audio.c
--- linux-2.5.70-bk16/sound/oss/i810_audio.c	2003-06-12 04:49:52.000000000 -0700
+++ linux-2.5.70-bk17/sound/oss/i810_audio.c	2003-06-12 04:50:32.000000000 -0700
@@ -2493,6 +2493,11 @@
 	}
 	if(file->f_mode & FMODE_WRITE) {
 		if((dmabuf->write_channel = card->alloc_pcm_channel(card)) == NULL) {
+			/* free any read channel allocated earlier */
+			if(file->f_mode & FMODE_READ)
+				card->free_pcm_channel(card,
+						dmabuf->read_channel->num);
+
 			kfree (card->states[i]);
 			card->states[i] = NULL;;
 			return -EBUSY;
diff -urN linux-2.5.70-bk16/sound/oss/mpu401.c linux-2.5.70-bk17/sound/oss/mpu401.c
--- linux-2.5.70-bk16/sound/oss/mpu401.c	2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk17/sound/oss/mpu401.c	2003-06-12 04:50:32.000000000 -0700
@@ -792,7 +792,10 @@
 	{
 
 		case SNDCTL_SYNTH_INFO:
-			memcpy((&((char *) arg)[0]), (char *) &mpu_synth_info[midi_dev], sizeof(struct synth_info));
+			if (copy_to_user((&((char *) arg)[0]),
+					(char *) &mpu_synth_info[midi_dev],
+					sizeof(struct synth_info)))
+				return -EFAULT;
 			return 0;
 
 		case SNDCTL_SYNTH_MEMAVL:
