diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Wed Nov 27 14:36:31 2002
+++ b/CREDITS	Wed Nov 27 14:36:31 2002
@@ -156,6 +156,14 @@
 S: Calgary, Alberta
 S: Canada
 
+N: Miles Bader
+E: miles@gnu.org
+D: v850 port (uClinux)
+S: NEC Corporation
+S: 1753 Shimonumabe, Nakahara-ku
+S: Kawasaki 211-8666
+S: Japan
+
 N: Ralf Baechle
 E: ralf@gnu.org
 P: 1024/AF7B30C1 CF 97 C2 CC 6D AE A7 FE  C8 BA 9C FC 88 DE 32 C3
@@ -1507,16 +1515,17 @@
 S: USA
 
 N: Dave Jones
+E: davej@codemonkey.org.uk
 E: davej@suse.de
 W: http://www.codemonkey.org.uk
 D: x86 errata/setup maintenance.
 D: Backport/Forwardport merge monkey.
 D: Various Janitor work.
 S: c/o SuSE Linux UK Ltd
-S: The Kinetic Centre
-S: Theobald Street
-S: Borehamwood
-S: Herts, WD6 4PJ
+S: Appleton House
+S: 139 King Street
+S: Hammersmith
+S: W6 9JG
 S: United Kingdom
 
 N: Ani Joshi
diff -Nru a/Documentation/BK-usage/unbz64wrap b/Documentation/BK-usage/unbz64wrap
--- a/Documentation/BK-usage/unbz64wrap	Wed Nov 27 14:36:30 2002
+++ b/Documentation/BK-usage/unbz64wrap	Wed Nov 27 14:36:30 2002
@@ -15,7 +15,7 @@
 		case $LINE in
 		begin-base64*) SHOW=YES ;;
 		====) SHOW= ;;
-		*) [ "$SHOW" ] && echo $LINE ;;
+		*) [ "$SHOW" ] && echo "$LINE" ;;
 		esac
 	done | mimencode -u | bunzip2
 	exit $?
diff -Nru a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl
--- a/Documentation/DocBook/journal-api.tmpl	Wed Nov 27 14:36:27 2002
+++ b/Documentation/DocBook/journal-api.tmpl	Wed Nov 27 14:36:27 2002
@@ -196,6 +196,8 @@
 Lock is also providing through journal_{un,}lock_updates(),
 ext3 uses this when it wants a window with a clean and stable fs for a moment.
 eg. 
+</para>
+
 <programlisting>
 
 	journal_lock_updates() //stop new stuff happening..
@@ -216,9 +218,13 @@
 Using the journal is a matter of wrapping the different context changes,
 being each mount, each modification (transaction) and each changed buffer
 to tell the journalling layer about them.
+</para>
 
+<para>
 Here is a some pseudo code to give you an idea of how it works, as
 an example.
+</para>
+
 <programlisting>
   journal_t* my_jnrl = journal_create();
   journal_init_{dev,inode}(jnrl,...)
diff -Nru a/Documentation/DocBook/lsm.tmpl b/Documentation/DocBook/lsm.tmpl
--- a/Documentation/DocBook/lsm.tmpl	Wed Nov 27 14:36:31 2002
+++ b/Documentation/DocBook/lsm.tmpl	Wed Nov 27 14:36:31 2002
@@ -203,29 +203,6 @@
 permission when accessing an inode.
 </para>
 
-<para>
-LSM adds a general <function>security</function> system call that
-simply invokes the <function>sys_security</function> hook.  This
-system call and hook permits security modules to implement new system
-calls for security-aware applications.  The interface is similar to
-socketcall, but also has an <parameter>id</parameter> to help identify
-the security module whose call is being invoked.  
-To eliminate the need for a central registry of ids,
-the recommended convention for creating the hexadecimal id value is:
-<programlisting>
-<![CDATA[
- echo "Name_of_module" | md5sum | cut -c -8
-]]>
-</programlisting>
-C code will need to prefix this result with ``0x''.
-For example, the id for ``SGI Trusted Linux'' could be used in C as:
-<programlisting>
-<![CDATA[
- #define SYS_SECURITY_MODID 0xc4c7be22
-]]>
-</programlisting>
-</para>
-
 </sect1>
 
 <sect1 id="cap"><title>LSM Capabilities Module</title>
diff -Nru a/Documentation/DocBook/mousedrivers.tmpl b/Documentation/DocBook/mousedrivers.tmpl
--- a/Documentation/DocBook/mousedrivers.tmpl	Wed Nov 27 14:36:31 2002
+++ b/Documentation/DocBook/mousedrivers.tmpl	Wed Nov 27 14:36:31 2002
@@ -153,11 +153,17 @@
 __init ourmouse_init(void)
 {
 
-        if(check_region(OURMOUSE_BASE, 3))
+        if (request_region(OURMOUSE_BASE, 3, "ourmouse") < 0) {
+		printk(KERN_ERR "ourmouse: request_region failed.\n");
                 return -ENODEV;
-        request_region(OURMOUSE_BASE, 3, "ourmouse");
+	}
+
+        if (misc_register(&amp;our_mouse) < 0) {
+		printk(KERN_ERR "ourmouse: cannot register misc device.\n");
+		release_region(OURMOUSE_BASE, 3);
+		return -EBUSY;
+	}
 
-        misc_register(&amp;our_mouse);
         return 0;
 }
   </programlisting>
@@ -177,18 +183,20 @@
     so it is a good idea to obtain a current copy of this file first.
   </para>
   <para>
-    Our code then is fairly simple. We check nobody else has taken our 
-    address space. Having done so we reserve it to ensure nobody stamps 
-    on our device while probing for other ISA bus devices. Such a probe 
-    might confuse our device.
+    Our code then is fairly simple. We reserve our I/O address space with
+    request_region, checking to make sure that it succeeded (i.e. the
+    space wasn't reserved by anyone else). 
   </para>
   <para>
-    Then we tell the misc driver that we wish to own a minor number. We also
+    Then we ask the misc driver to allocate our minor device number. We also
     hand it our name (which is used in 
     <filename class="directory">/proc/misc</filename>) and a set of file 
     operations that are to be used. The file operations work exactly like the 
     file operations you would register for a normal character device. The misc 
     device itself is simply acting as a redirector for requests.
+    Since misc_register can fail, it is important to check for failure
+    and act accordingly (which in the case of a mouse driver is to abort,
+    since you can't use the mouse without a working device node).
   </para>
   <para>
     Next, in order to be able to use and test our code we need to add some 
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	Wed Nov 27 14:36:32 2002
+++ b/Documentation/kernel-parameters.txt	Wed Nov 27 14:36:32 2002
@@ -1,21 +1,22 @@
-July 2000		  Kernel Parameters			v2.4.0
-			  ~~~~~~~~~~~~~~~~~
+November 2002             Kernel Parameters                     v2.5.49
+                          ~~~~~~~~~~~~~~~~~
 
 The following is a consolidated list of the kernel parameters as implemented
-by the __setup() macro and sorted into English Dictionary order (defined      
-as ignoring all punctuation and sorting digits before letters in a case
-insensitive manner), and with descriptions where known.
+(mostly) by the __setup() macro and sorted into English Dictionary order
+(defined as ignoring all punctuation and sorting digits before letters in a
+case insensitive manner), and with descriptions where known.
 
 The text in square brackets at the beginning of the description state the
 restrictions on the kernel for the said kernel parameter to be valid. The
 restrictions referred to are that the relevant option is valid if:
 
-	ACPI    ACPI support is enabled.
+	ACPI	ACPI support is enabled.
+	ALSA	ALSA sound support is enabled.
 	APIC	APIC support is enabled.
-	APM 	Advanced Power Management support is enabled.
+	APM	Advanced Power Management support is enabled.
 	AX25	Appropriate AX.25 support is enabled.
 	CD	Appropriate CD support is enabled.
-	DEVFS   devfs support is enabled. 
+	DEVFS	devfs support is enabled. 
 	DRM	Direct Rendering Management support is enabled. 
 	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
@@ -24,38 +25,47 @@
 	IA-32	IA-32 aka i386 architecture is enabled.
 	IA-64	IA-64 architecture is enabled.
 	IP_PNP	IP DCHP, BOOTP, or RARP is enabled.
-	ISAPNP  ISA PnP code is enabled.
+	ISAPNP	ISA PnP code is enabled.
 	ISDN	Appropriate ISDN support is enabled.
-	JOY 	Appropriate joystick support is enabled.
+	JOY	Appropriate joystick support is enabled.
 	LP	Printer support is enabled.
 	LOOP	Loopback device support is enabled.
-	M68k	M68k architecture is enabled. 
-	MCA 	MCA bus support is enabled.
-	MDA 	MDA console support is enabled.
+	M68k	M68k architecture is enabled.
+			These options have more detailed description inside of
+			Documentation/m68k/kernel-options.txt.
+	MCA	MCA bus support is enabled.
+	MDA	MDA console support is enabled.
 	MOUSE	Appropriate mouse support is enabled.
-	NET 	Appropriate network support is enabled.
-	NFS 	Appropriate NFS support is enabled.
+	MTD	MTD support is nebaled.
+	NET	Appropriate network support is enabled.
+	NFS	Appropriate NFS support is enabled.
+	OSS	OSS sound support is enabled.
 	PARIDE	The ParIDE subsystem is enabled.
-	PCI 	PCI bus support is enabled.
+	PCI	PCI bus support is enabled.
 	PCMCIA	The PCMCIA subsystem is enabled.
-	PNP 	Plug & Play support is enabled.
+	PNP	Plug & Play support is enabled.
+	PPC	PowerPC architecture is enabled.
 	PPT	Parallel port support is enabled.
-	PS2 	Appropriate PS/2 support is enabled.
-	RAM 	RAM disk support is enabled.
+	PS2	Appropriate PS/2 support is enabled.
+	RAM	RAM disk support is enabled.
+	S390	S390 architecture is enabled.
 	SCSI	Appropriate SCSI support is enabled.
+			A lot of drivers has their options described inside of
+			Documentation/scsi/.
 	SERIAL	Serial support is enabled.
-	SMP 	The kernel is an SMP kernel.
-	SOUND	Appropriate sound system support is enabled.
-	SWSUSP  Software suspension is enabled.
+	SMP	The kernel is an SMP kernel.
+	SPARC	Sparc architecture is enabled.
+	SWSUSP	Software suspension is enabled.
+	USB	USB support is enabled.
 	V4L	Video For Linux support is enabled.
-	VGA 	The VGA console has been enabled.
+	VGA	The VGA console has been enabled.
 	VT	Virtual terminal support is enabled.
 	XT	IBM PC/XT MFM hard disk support is enabled.
 
 In addition, the following text indicates that the option:
 
 	BUGS=	Relates to possible processor bugs on the said processor.
-	KNL 	Is a kernel start-up parameter.
+	KNL	Is a kernel start-up parameter.
 	BOOT	Is a boot loader parameter.
 
 Parameters denoted with BOOT are actually interpreted by the boot
@@ -67,66 +77,113 @@
 it will appear as a kernel argument readable via /proc/cmdline by programs
 running once the system is up.
 
-	53c7xx=		[HW,SCSI] Amiga SCSI controllers.
+	53c7xx=		[HW,SCSI] Amiga SCSI controllers
+			See header of drivers/scsi/53c7xx.c.
+			See also Documentation/scsi/ncr53c7xx.txt.
 
 	acpi=		[HW,ACPI] Advanced Configuration and Power Interface 
+			Format: off[,<...>]
+			See also Documentation/pm.txt.
  
-	ad1816=		[HW,SOUND]
+	ad1816=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>
+			See also Documentation/sound/oss/AD1816.
 
-	ad1848=		[HW,SOUND]
- 
-	adb_buttons=	[HW,MOUSE]
+	ad1848=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>,<type>
 
-	adlib=		[HW,SOUND]
+	adlib=		[HW,OSS]
+			Format: <io>
  
 	advansys=	[HW,SCSI]
+			See header of drivers/scsi/advansys.c.
 
-	aedsp16=	[HW,SOUND]
+	aedsp16=	[HW,OSS] Audio Excel DSP 16
+			Format: <io>,<irq>,<dma>,<mss_io>,<mpu_io>,<mpu_irq>
+			See also header of sound/oss/aedsp16.c.
  
 	aha152x=	[HW,SCSI]
+			See Documentation/scsi/aha152x.txt.
 
 	aha1542=	[HW,SCSI]
+			Format: <portbase>[,<buson>,<busoff>[,<dmaspeed>]]
 
 	aic7xxx=	[HW,SCSI]
+			See Documentation/scsi/aic7xxx.txt.
+
+	allowdma0	[ISAPNP]
 
 	AM53C974=	[HW,SCSI]
+			Format: <host-scsi-id>,<target-scsi-id>,<max-rate>,<max-offset>
+			See also header of drivers/scsi/AM53C974.c.
 
 	amijoy=		[HW,JOY] Amiga joystick support 
+
+	apc=		[HW,SPARC] Power management functions (SPARCstation-4/5 + deriv.)
+			Format: noidle
+			Disable APC CPU standby support. SPARCstation-Fox does
+			not play well with APC CPU idle - disable it if you have
+			APC and your system crashes randomly.
  
-	apm=		[APM] Advanced Power Management.
+	apm=		[APM] Advanced Power Management
+			See header of arch/i386/kernel/apm.c.
 
 	applicom=	[HW]
+			Format: <mem>,<irq>
  
-	arcrimi=	[HW,NET]
+	arcrimi=	[HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards
+			Format: <io>,<irq>,<nodeID>
 
 	ataflop=	[HW,M68k]
 
-	atarimouse=	[HW,MOUSE] Atari Mouse.
+	atarimouse=	[HW,MOUSE] Atari Mouse
 
-	atascsi=	[HW,SCSI] Atari SCSI.
+	atascsi=	[HW,SCSI] Atari SCSI
 
-	awe=            [HW,SOUND]
- 
-	aztcd=		[HW,CD] Aztec CD driver.
+	atkbd_set=	[HW] Select keyboard code set
+			Format: <int>
 
-	baycom_epp=	[HW,AX25]
- 
-	baycom_par= 	[HW,AX25] BayCom Parallel Port AX.25 Modem.
-
-	baycom_ser_fdx=	[HW,AX25] BayCom Serial Port AX.25 Modem in Full
-			Duplex Mode.
+	atkbd_reset	[HW] Reset keyboard during initialization
 
-	baycom_ser_hdx=	[HW,AX25] BayCom Serial Port AX.25 Modem in Half
-			Duplex Mode.
+	autotest	[IA64]
 
-	bmouse=		[HW,MOUSE,PS2] Bus mouse.
+	awe=		[HW,OSS] AWE32/SB32/AWE64 wave table synth
+			Format: <io>,<memsize>,<isapnp>
+ 
+	aztcd=		[HW,CD] Aztech CD268 CDROM driver
+			Format: <io>,0x79 (?)
 
-	bttv.card=	[HW,V4L] bttv (bt848 + bt878 based grabber cards), most
-	bttv.radio=	important insmod options are available as kernel args too.
-	bttv.pll=	see Documentation/video4linux/bttv/Insmod-options
+	baycom_epp=	[HW,AX25]
+			Format: <io>,<mode>
+ 
+	baycom_par=	[HW,AX25] BayCom Parallel Port AX.25 Modem
+			Format: <io>,<mode>
+			See header of drivers/net/hamradio/baycom_par.c.
+
+	baycom_ser_fdx=	[HW,AX25] BayCom Serial Port AX.25 Modem (Full Duplex Mode)
+			Format: <io>,<irq>,<mode>[,<baud>]
+			See header of drivers/net/hamradio/baycom_ser_fdx.c.
+
+	baycom_ser_hdx=	[HW,AX25] BayCom Serial Port AX.25 Modem (Half Duplex Mode)
+			Format: <io>,<irq>,<mode>
+			See header of drivers/net/hamradio/baycom_ser_hdx.c.
+
+	blkmtd_device=	[HW,MTD]
+	blkmtd_erasesz=
+	blkmtd_ro=
+	blkmtd_bs=
+	blkmtd_count=
+
+	bttv.card=	[HW,V4L] bttv (bt848 + bt878 based grabber cards)
+	bttv.radio=	Most important insmod options are available as kernel args too.
+	bttv.pll=	See Documentation/video4linux/bttv/Insmod-options
 	bttv.tuner=	and Documentation/video4linux/bttv/CARDLIST
 
 	BusLogic=	[HW,SCSI]
+			See drivers/scsi/BusLogic.c, comment before function
+			BusLogic_ParseDriverOptions().
+
+	c101=		[NET] Moxa C101 synchronous serial card
 
 	cachesize=	[BUGS=IA-32] Override level 2 CPU cache size detection.
 			Sometimes CPU hardware bugs make them report the cache
@@ -136,54 +193,87 @@
 			This option provides an override for these situations.
 
 	cdu31a=		[HW,CD]
+			Format: <io>,<irq>[,PAS]
+			See header of drivers/cdrom/cdu31a.c.
 
-	chandev=	[HW,NET] 
+	chandev=	[HW,NET] Generic channel device initialisation
  
 	cm206=		[HW,CD]
+			Format: { auto | [<io>,][<irq>] }
 
-	com20020=	[HW,NET]
+	com20020=	[HW,NET] ARCnet - COM20020 chipset
+			Format: <io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
 
-	com90io=	[HW,NET]
+	com90io=	[HW,NET] ARCnet - COM90xx chipset (IO-mapped buffers)
+			Format: <io>[,<irq>]
 
-	com90xx=	[HW,NET]
+	com90xx=	[HW,NET] ARCnet - COM90xx chipset (memory-mapped buffers)
+			Format: <io>[,<irq>[,<memstart>]]
 
-	condev=		[HW]
+	condev=		[HW,S390] console device
+	conmode=
  
-	console=	[KNL] output console + comm spec (speed, control,
-			parity).
+	console=	[KNL] Output console
+			Console device and comm spec (speed, control, parity).
+
+	cpcihp_generic=	[HW,PCI] Generic port I/O CompactPCI driver
+			Format: <first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
 
 	cpia_pp=	[HW,PPT]
+			Format: { parport<nr> | auto | none }
 
-	cs4232=		[HW,SOUND]
+	cs4232=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>
 
 	cs89x0_dma=	[HW,NET]
+			Format: <dma>
+
+	cs89x0_media=	[HW,NET]
+			Format: { rj45 | aui | bnc }
 
 	ctc=		[HW,NET]
+			See drivers/s390/net/ctcmain.c, comment before function
+			ctc_setup().
  
 	cyclades=	[HW,SERIAL] Cyclades multi-serial port adapter.
  
 	dasd=		[HW,NET]    
+			See header of drivers/s390/block/dasd_devmap.c.
 
-	db9=		[HW,JOY]
+	dasd_discipline=
+			[HW,NET]
+			See header of drivers/s390/block/dasd.c.
 
-	db9_2=		[HW,JOY]
-
-	db9_3=		[HW,JOY]
+	db9=		[HW,JOY]
+	db9_2=
+	db9_3=
  
 	debug		[KNL] Enable kernel debugging (events log level).
 
 	decnet=		[HW,NET]
+			Format: <area>[,<node>]
+			See also Documentation/networking/decnet.txt.
 
-	devfs=          [DEVFS]
+	decr_overclock= [PPC]
+	decr_overclock_proc0=
+
+	devfs=		[DEVFS]
+			See Documentation/filesystems/devfs/boot-options.
  
-	digi=		[HW,SERIAL] io parameters + enable/disable command.
+	digi=		[HW,SERIAL]
+			IO parameters + enable/disable command.
 
 	digiepca=	[HW,SERIAL]
+			See drivers/char/README.epca and
+			Documentation/digiepca.txt.
 
 	dmascc=		[HW,AX25,SERIAL] AX.25 Z80SCC driver with DMA
 			support available.
+			Format: <io_dev0>[,<io_dev1>[,..<io_dev32>]]
+
+	dmasound=	[HW,OSS] Sound subsystem buffers
 
-	dmasound=	[HW,SOUND] (sound subsystem buffers).
+	dscc4.setup=	[NET]
 
 	dtc3181e=	[HW,SCSI]
 
@@ -194,101 +284,155 @@
 	edb=		[HW,PS2]
 
 	eicon=		[HW,ISDN] 
+			Format: <id>,<membase>,<irq>
 
-	es1370=		[HW,SOUND]
+	eisa_irq_edge=	[PARISC]
+			See header of drivers/parisc/eisa.c.
 
-	es1371=		[HW,SOUND]
- 
-	ether=		[HW,NET] Ethernet cards parameters (irq,
-			base_io_addr, mem_start, mem_end, name.
-			(mem_start is often overloaded to mean something
-			different and driver-specific).
+	elanfreq=	[IA-32]
+			See comment before function elanfreq_setup() in
+			arch/i386/kernel/cpu/cpufreq/elanfreq.c.
+
+	es1370=		[HW,OSS]
+			Format: <lineout>[,<micbias>]
+			See also header of sound/oss/es1370.c.
+
+	es1371=		[HW,OSS]
+			Format: <spdif>,[<nomix>,[<amplifier>]]
+			See also header of sound/oss/es1371.c.
+ 
+	ether=		[HW,NET] Ethernet cards parameters
+			This option is obsoleted by the "netdev=" option, which
+			has equivalent usage. See its documentation for details.
 
 	fd_mcs=		[HW,SCSI]
+			See header of drivers/scsi/fd_mcs.c.
 
 	fdomain=	[HW,SCSI]
+			See header of drivers/scsi/fdomain.c.
 
 	floppy=		[HW]
+			See Documentation/floppy.txt.
 
 	ftape=		[HW] Floppy Tape subsystem debugging options.
+			See Documentation/ftape.txt.
 
 	gamma=		[HW,DRM]
 
 	gc=		[HW,JOY]
-
-	gc_2=		[HW,JOY]
-	 
-	gc_3=		[HW,JOY]
+	gc_2=		See Documentation/input/joystick-parport.txt.
+	gc_3=		
  
 	gdth=		[HW,SCSI]
+			See header of drivers/scsi/gdth.c.
 
-	gpt             [EFI] Forces disk with valid GPT signature but
+	gpt		[EFI] Forces disk with valid GPT signature but
 			invalid Protective MBR to be treated as GPT.
 
 	gscd=		[HW,CD]
+			Format: <io>
+
+	gt96100eth=	[NET] MIPS GT96100 Advanced Communication Controller
 
-	gus=		[HW,SOUND] 
+	gus=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma16>
  
 	gvp11=		[HW,SCSI]
 
-	hd= 		[EIDE] (E)IDE hard drive subsystem geometry
-			(Cyl/heads/sectors) or tune parameters.
+	hcl=		[IA-64] SGI's Hardware Graph compatibility layer
 
-	hfmodem=	[HW,AX25]
+	hd=		[EIDE] (E)IDE hard drive subsystem geometry
+			Format: <cyl>,<head>,<sect>
+
+	hd?=		[HW] (E)IDE subsystem
+	hd?lun=		See Documentation/ide.txt.
 
 	hisax=		[HW,ISDN]
+			See Documentation/isdn/README.HiSax.
+
+	hugepages=	[HW,IA-32] Maximal number of HugeTLB pages
+
+	i8042_direct	[HW] Non-translated mode
+	i8042_dumbkbd
+	i8042_noaux
+	i8042_nomux
+	i8042_reset	[HW] Reset the controller during init and cleanup
+	i8042_unlock	[HW] Unlock (ignore) the keylock
 
 	i810=		[HW,DRM]
 
-	ibmmcascsi=	[HW,MCA,SCSI] IBM MicroChannel SCSI adapter.
+	ibmmcascsi=	[HW,MCA,SCSI] IBM MicroChannel SCSI adapter
+			See Documentation/mca.txt.
 
 	icn=		[HW,ISDN]
+			Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
 
-	ide?=		[HW] (E)IDE subsystem : config (iomem/irq), tuning or
-			debugging (serialize,reset,no{dma,tune,probe}) or
-			chipset specific parameters.
+	ide?=		[HW] (E)IDE subsystem
+			Config (iomem/irq), tuning or debugging
+			(serialize,reset,no{dma,tune,probe}) or chipset
+			specific parameters.
+			See Documentation/ide.txt.
 	
-	idebus=		[HW] (E)IDE subsystem : VLB/PCI bus speed.
+	idebus=		[HW] (E)IDE subsystem - VLB/PCI bus speed
+			See Documentation/ide.txt.
 
 	idle=		[HW]
+			Format: poll
  
 	in2000=		[HW,SCSI]
+			See header of drivers/scsi/in2000.c.
 
 	init=		[KNL]
+			Format: <full_path>
+			Run specified binary instead of /sbin/init as init
+			process.
 
-	initrd=		[BOOT] Specify the location of the initial ramdisk. 
+	initrd=		[BOOT] Specify the location of the initial ramdisk
 
-	ip=		[IP_PNP]
+	inport_irq=	[HW] Inport (ATI XL and Microsoft) busmouse driver
+			Format: <irq>
 
-	isapnp=		[ISAPNP] Specify RDP, reset, pci_scan and verbosity.
+	inttest=	[IA64]
 
-	isapnp_reserve_irq= [ISAPNP] Exclude IRQs for the autoconfiguration.
+	ip=		[IP_PNP]
+			See Documentation/nfsroot.txt.
 
-	isapnp_reserve_dma= [ISAPNP] Exclude DMAs for the autoconfiguration.
+	ip2=		[HW] Set IO/IRQ pairs for up to 4 IntelliPort boards
+			See comment before ip2_setup() in drivers/char/ip2.c.
 
-	isapnp_reserve_io= [ISAPNP] Exclude I/O ports for the autoconfiguration.
-				    Ranges are in pairs (I/O port base and size).
+	ips=		[HW,SCSI] Adaptec / IBM ServeRAID controller
+			See header of drivers/scsi/ips.c.
 
-	isapnp_reserve_mem= [ISAPNP] Exclude memory regions for the autoconfiguration.
-				     Ranges are in pairs (memory base and size).
+	isapnp=		[ISAPNP]
+			Format: <RDP>, <reset>, <pci_scan>, <verbosity>
 
 	isp16=		[HW,CD]
+			Format: <io>,<irq>,<dma>,<setup>
 
 	iucv=		[HW,NET] 
 
 	js=		[HW,JOY] Analog joystick
- 
-	kbd-reset	[VT]
+			See Documentation/input/joystick.txt.
 
-	keepinitrd	[HW, ARM]
+	keepinitrd	[HW,ARM]
 
-	load_ramdisk=	[RAM] List of ramdisks to load from floppy.
+	l2cr=		[PPC]
+
+	lasi=		[HW,SCSI] PARISC LASI driver for the 53c700 chip
+			Format: addr:<io>,irq:<irq>
+
+	llsc*=		[IA64]
+			See function print_params() in arch/ia64/sn/kernel/llsc4.c.
+
+	load_ramdisk=	[RAM] List of ramdisks to load from floppy
+			See Documentation/ramdisk.txt.
 
 	lockd.udpport=	[NFS]
 
 	lockd.tcpport=	[NFS]
 
-	logi_busmouse=	[HW, MOUSE]
+	logibm_irq=	[HW,MOUSE] Logitech Bus Mouse Driver
+			Format: <irq>
 
 	lp=0		[LP]	Specify parallel ports to use, e.g,
 	lp=port[,port...]	lp=none,parport0 (lp0 not configured, lp1 uses
@@ -305,62 +449,93 @@
 				from each port should be examined, to see if
 				an IEEE 1284-compliant printer is attached; if
 				so, the driver will manage that printer.
+				See also header of drivers/char/lp.c.
 
-	ltpc=		[HW]
+	ltpc=		[NET]
+			Format: <io>,<irq>,<dma>
 
 	mac5380=	[HW,SCSI]
+			Format: <can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
 
-	mac53c9x= 	[HW,SCSI]
+	mac53c9x=	[HW,SCSI]
+			Format: <num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
 	
-	mad16=		[HW,SOUND]
+	mad16=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma16>,<mpu_io>,<mpu_irq>,<joystick>
 
-	maui=		[HW,SOUND]
+	maui=		[HW,OSS]
+			Format: <io>,<irq>
  
-	max_loop=[0-255] [LOOP] Set the maximum number of loopback devices
-				that can be mounted.
+	max_loop=       [LOOP] Maximum number of loopback devices that can
+			be mounted
+			Format: <1-256>
 
-	maxcpus=	[SMP] States the maximum number of processors that
-			an SMP kernel should make use of.
+	maxcpus=	[SMP] Maximum number of processors that	an SMP kernel
+			should make use of
 
 	max_scsi_luns=	[SCSI]
 
-	mca		[IA-32] On some pentium machines the mce support defaults
-				to off as the mainboard support is not always present.
-				You must activate it as a boot option
+	max_scsi_report_luns=
+			[SCSI] Maximum number of LUNs received
+			Should be between 1 and 16384.
 
 	mca-pentium	[BUGS=IA-32]
 
+	mcatest=	[IA-64]
+
 	mcd=		[HW,CD]
+			Format: <port>,<irq>,<mitsumi_bug_93_wait>
 
 	mcdx=		[HW,CD]
 
-	md=		[HW] RAID subsystems devices and level.
+	mce		[IA-32] Machine Check Exception
 
-	mdisk=		[HW]
+	md=		[HW] RAID subsystems devices and level
+			See Documentation/md.txt.
  
 	mdacon=		[MDA]
-
-	megaraid=	[HW,SCSI]
+			Format: <first>,<last>
  
-	mem=exactmap	[KNL,BOOT,IA-32] enable setting of an exact
-			e820 memory map, as specified by the user.
-			Such mem=exactmap lines can be constructed
-			based on BIOS output or other requirements.
+	mem=exactmap	[KNL,BOOT,IA-32] Enable setting of an exact
+			E820 memory map, as specified by the user.
+			Such mem=exactmap lines can be constructed based on
+			BIOS output or other requirements. See the mem=nn@ss
+			option description.
 
-	mem=nn[KMG]	[KNL,BOOT] force use of a specific amount of
-			memory; to be used when the kernel is not able
+	mem=nn[KMG]	[KNL,BOOT] Force usage of a specific amount of memory
+			Amount of memory to be used when the kernel is not able
 			to see the whole system memory or for test.
 
-	memfrac=	[KNL]
+	mem=nn[KMG]@ss[KMG]
+			[KNL,BOOT] Force usage of a specific region of memory
+			Region of memory to be used, from ss to ss+nn.
 
 	mem=nopentium	[BUGS=IA-32] Disable usage of 4MB pages for kernel
 			memory.
 
+	memfrac=	[KNL]
+
+	meye=		[HW] Set MotionEye Camera parameters
+			See Documentation/video4linux/meye.txt.
+
 	mga=		[HW,DRM]
 
-	mpu401=		[HW,SOUND]
- 
-	msmouse=	[HW,MOUSE] Microsoft Mouse.
+	mpu401=		[HW,OSS]
+			Format: <io>,<irq>
+
+	MTD_Partition=	[MTD]
+			Format: <name>,<region-number>,<size>,<offset>
+
+	MTD_Region=	[MTD]
+			Format: <name>,<region-number>[,<base>,<size>,<buswidth>,<altbuswidth>]
+
+	mtdparts=	[MTD]
+			See drivers/mtd/cmdline.c.
+
+	n2=		[NET] SDL Inc. RISCom/N2 synchronous serial card
+
+	NCR_D700=	[HW,SCSI]
+			See header of drivers/scsi/NCR_D700.c.
 
 	ncr5380=	[HW,SCSI]
 
@@ -372,17 +547,18 @@
 
 	ncr53c8xx=	[HW,SCSI]
 
-	netdev=		[NET] Ethernet cards parameters (irq,
-			base_io_addr, mem_start, mem_end, name.
-			(mem_start is often overloaded to mean something
-			different and driver-specific).
-			(cf: ether=)
+	netdev=		[NET] Network devices parameters
+			Format: <irq>,<io>,<mem_start>,<mem_end>,<name>
+			Note that mem_start is often overloaded to mean
+			something different and driver-specific.
  
 	nfsaddrs=	[NFS]
+			See Documentation/nfsroot.txt.
 
 	nfsroot=	[NFS] nfs root filesystem for disk-less boxes.
+			See Documentation/nfsroot.txt.
 
-	nmi_watchdog=	[KNL,BUGS=IA-32] debugging features for SMP kernels.
+	nmi_watchdog=	[KNL,BUGS=IA-32] Debugging features for SMP kernels
 
 	no387		[BUGS=IA-32] Tells the kernel to use the 387 maths
 			emulation library even if a 387 maths coprocessor
@@ -393,12 +569,16 @@
 	noapic		[SMP,APIC] Tells the kernel not to make use of any
 			APIC that may be present on the system.
 
-	noasync		[HW, M68K] Disables async and sync negotiation for
+	noasync		[HW,M68K] Disables async and sync negotiation for
 			all devices.
 
 	nocache		[ARM]
  
-	nodisconnect	[HW,SCSI, M68K] Disables SCSI disconnects.
+	nodisconnect	[HW,SCSI,M68K] Disables SCSI disconnects.
+
+	nofxsr		[BUGS=IA-32]
+
+	nohighio	[BUGS=IA-32] Disable highmem block I/O.
 
 	nohlt		[BUGS=ARM]
  
@@ -415,27 +595,42 @@
 
 	nointroute	[IA-64]
 
+	nomce		[IA-32] Machine Check Exception
+
 	noresume	[SWSUSP] Disables resume and restore original swap space.
  
 	no-scroll	[VGA]
 
+	nosbagart	[IA-64]
+
 	nosmp		[SMP] Tells an SMP kernel to act as a UP kernel.
 
-	nosync		[HW, M68K] Disables sync negotiation for all devices.
+	nosync		[HW,M68K] Disables sync negotiation for all devices.
 
-	notsc           [BUGS=IA-32] Disable Time Stamp Counter
+	notsc		[BUGS=IA-32] Disable Time Stamp Counter
+
+	nousb		[USB] Disable the USB subsystem
 
 	nowb		[ARM]
  
-	opl3=		[HW,SOUND]
+	opl3=		[HW,OSS]
+			Format: <io>
 
-	opl3sa=		[HW,SOUND]
+	opl3sa=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>,<mpu_io>,<mpu_irq>
 
-	opl3sa2=	[HW,SOUND]
+	opl3sa2=	[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>,<mss_io>,<mpu_io>,<ymode>,<loopback>[,<isapnp>,<multiple]
  
 	optcd=		[HW,CD]
+			Format: <io>
+
+	osst=		[HW,SCSI] SCSI Tape Driver
+			Format: <buffer_size>,<write_threshold>
+			See also Documentation/scsi/st.txt.
 
-	panic=		[KNL] kernel behaviour on panic.
+	panic=		[KNL] Kernel behaviour on panic
+			Format: <timeout>
 
 	parport=0	[HW,PPT]	Specify parallel ports. 0 disables.
 	parport=auto			Use 'auto' to force the driver to use
@@ -452,13 +647,17 @@
 					order they are specified on the command
 					line, starting with parport0.
 
-	pas2=		[HW,SOUND]
+	pas2=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma16>,<sb_io>,<sb_irq>,<sb_dma>,<sb_dma16>
  
 	pas16=		[HW,SCSI]
+			See header of drivers/scsi/pas16.c.
 
 	pcbit=		[HW,ISDN]
 
 	pcd.		[PARIDE]
+			See header of drivers/block/paride/pcd.c.
+			See also Documentation/paride.txt.
 
 	pci=option[,option...]		[PCI] various PCI subsystem options:
 		off			[IA-32] don't probe for the PCI bus
@@ -503,153 +702,407 @@
 					have no effect if ACPI IRQ routing is
 					enabled.
 
+	pcmv=		[HW,PCMCIA] BadgePAD 4
+
 	pd.		[PARIDE]
+			See Documentation/paride.txt.
 
 	pf.		[PARIDE]
+			See Documentation/paride.txt.
 
 	pg.		[PARIDE]
+			See Documentation/paride.txt.
+
+	pirq=		[SMP,APIC] Manual mp-table setup
+			See Documentation/i386/IO-APIC.txt.
+
+	plip=		[PPT,NET] Parallel port network link
+			Format: { parport<nr> | timid | 0 }
+			See also Documentation/parport.txt.
+
+	pnpbios=	[ISAPNP]
+			{ on | off | curr | res | no-curr | no-res }
 
-	pirq=		[SMP,APIC] mp-table.
+	pnp_reserve_irq=
+			[ISAPNP] Exclude IRQs for the autoconfiguration
 
-	plip=		[PPT,NET] Parallel port network link.
+	pnp_reserve_dma=
+			[ISAPNP] Exclude DMAs for the autoconfiguration
 
-	profile=	[KNL] enable kernel profiling via /proc/profile
-			(param:log level).
+	pnp_reserve_io=	[ISAPNP] Exclude I/O ports for the autoconfiguration
+		     	Ranges are in pairs (I/O port base and size).
+
+	pnp_reserve_mem=
+			[ISAPNP] Exclude memory regions for the autoconfiguration
+			Ranges are in pairs (memory base and size).
+
+	profile=	[KNL] Enable kernel profiling via /proc/profile
+			Format: <log_level>
 
 	prompt_ramdisk=	[RAM] List of RAM disks to prompt for floppy disk
 			before loading.
+			See Documentation/ramdisk.txt.
+
+	psmouse_noext	[HW,MOUSE] Disable probing for PS2 mouse protocol extensions
+
+	pss=		[HW,OSS] Personal Sound System (ECHO ESC614)
+			Format: <io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
 
-	pss=		[HW,SOUND] 
- 
 	pt.		[PARIDE]
+			See Documentation/paride.txt.
 
-	quiet=		[KNL] Disable log messages.
+	quiet=		[KNL] Disable log messages
  
 	r128=		[HW,DRM]
 
 	raid=		[HW,RAID]
+			See Documentation/md.txt.
 
-	ramdisk=	[RAM] Sizes of RAM disks in kilobytes [deprecated].
+	ramdisk=	[RAM] Sizes of RAM disks in kilobytes [deprecated]
+			See Documentation/ramdisk.txt.
 
 	ramdisk_blocksize=
 			[RAM]
+			See Documentation/ramdisk.txt.
  
-	ramdisk_size=	[RAM] New name for the ramdisk parameter.
+	ramdisk_size=	[RAM] Sizes of RAM disks in kilobytes
+			New name for the ramdisk parameter.
+			See Documentation/ramdisk.txt.
 
 	ramdisk_start=	[RAM] Starting block of RAM disk image (so you can
 			place it after the kernel image on a boot floppy).
+			See Documentation/ramdisk.txt.
 
-	reboot=		[BUGS=IA-32]
+	reboot=		[BUGS=IA-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
+			Format: <reboot_mode>[,<reboot_mode2>[,...]]
+			See arch/*/kernel/reboot.c.
 
-	reserve=	[KNL,BUGS] force the kernel to ignore some iomem area.
+	reserve=	[KNL,BUGS] Force the kernel to ignore some iomem area
 
-	resume=		[SWSUSP] specify the partition device for software suspension.
+	resume=		[SWSUSP] Specify the partition device for software suspension
 
 	riscom8=	[HW,SERIAL]
+			Format: <io_board1>[,<io_board2>[,...<io_boardN>]]
 
-	ro		[KNL] Mount root device read-only on boot.
+	ro		[KNL] Mount root device read-only on boot
 
-	root=		[KNL] root filesystem.
+	root=		[KNL] Root filesystem
 
-	rootflags=	[KNL] set root filesystem mount option string
+	rootflags=	[KNL] Set root filesystem mount option string
 
-	rootfstype=	[KNL] set root filesystem type
+	rootfstype=	[KNL] Set root filesystem type
 
-	rw		[KNL] Mount root device read-write on boot.
+	rw		[KNL] Mount root device read-write on boot
 
-	S		[KNL] run init in single mode.
+	S		[KNL] Run init in single mode
 
-	sb=		[HW,SOUND]
+	sa1100ir	[NET]
+			See drivers/net/irda/sa1100_ir.c.
+
+	sb=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>
+
+	sbni=		[NET] Granch SBNI12 leased line adapter
  
-	sbpcd=		[HW,CD] Soundblaster CD adapter.
+	sbpcd=		[HW,CD] Soundblaster CD adapter
+			Format: <io>,<type>
+			See a comment before function sbpcd_setup() in
+			drivers/cdrom/sbpcd.c.
+
+	scsi_debug_*=	[SCSI]
+			See drivers/scsi/scsi_debug.c.
+
+	scsi_default_dev_flags=
+			[SCSI] SCSI default device flags
+			Format: <integer>
+
+	scsi_dev_flags=	[SCSI] Black/white list entry for vendor and model
+			Format: <vendor>:<model>:<flags>
+			(flags are integer value)
 
 	scsi_logging=	[SCSI]
 
 	scsihosts=	[SCSI]
 
+	serialnumber	[BUGS=IA-32]
+
+	sf16fm=		[HW] SF16FMI radio driver for Linux
+			Format: <io>
+
 	sg_def_reserved_size=
 			[SCSI]
  
-	sgalaxy=	[HW,SOUND]
+	sgalaxy=	[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>,<sgbase>
+
+	shapers=	[NET]
+			Maximal number of shapers.
  
 	sim710=		[SCSI,HW]
+			See header of drivers/scsi/sim710.c.
+
+	simeth=		[IA-64]
+	simscsi=
  
 	sjcd=		[HW,CD]
+			Format: <io>,<irq>,<dma>
+			See header of drivers/cdrom/sjcd.c.
+
+	slram=		[HW,MTD]
 
 	smart2=		[HW]
+			Format: <io1>[,<io2>[,...,<io8>]]
+
+	snd-ad1816a=	[HW,ALSA]
+
+	snd-ad1848=	[HW,ALSA]
+
+	snd-ali5451=	[HW,ALSA]
+
+	snd-als100=	[HW,ALSA]
+
+	snd-als4000=	[HW,ALSA]
+
+	snd-azt2320=	[HW,ALSA]
+
+	snd-cmi8330=	[HW,ALSA]
+
+	snd-cmipci=	[HW,ALSA]
+
+	snd-cs4231=	[HW,ALSA]
+
+	snd-cs4232=	[HW,ALSA]
+
+	snd-cs4236=	[HW,ALSA]
+
+	snd-cs4281=	[HW,ALSA]
+
+	snd-cs46xx=	[HW,ALSA]
+
+	snd-dt019x=	[HW,ALSA]
+
+	snd-dummy=	[HW,ALSA]
+
+	snd-emu10k1=	[HW,ALSA]
+
+	snd-ens1370=	[HW,ALSA]
+
+	snd-ens1371=	[HW,ALSA]
+
+	snd-es968=	[HW,ALSA]
+
+	snd-es1688=	[HW,ALSA]
+
+	snd-es18xx=	[HW,ALSA]
+
+	snd-es1938=	[HW,ALSA]
+
+	snd-es1968=	[HW,ALSA]
+
+	snd-fm801=	[HW,ALSA]
+
+	snd-gusclassic=	[HW,ALSA]
+
+	snd-gusextreme=	[HW,ALSA]
+
+	snd-gusmax=	[HW,ALSA]
+
+	snd-hdsp=	[HW,ALSA]
+
+	snd-ice1712=	[HW,ALSA]
+
+	snd-intel8x0=	[HW,ALSA]
+
+	snd-interwave=	[HW,ALSA]
+
+	snd-interwave-stb=
+			[HW,ALSA]
+
+	snd-korg1212=	[HW,ALSA]
+
+	snd-maestro3=	[HW,ALSA]
+
+	snd-mpu401=	[HW,ALSA]
+
+	snd-mtpav=	[HW,ALSA]
+
+	snd-nm256=	[HW,ALSA]
+
+	snd-opl3sa2=	[HW,ALSA]
+
+	snd-opti92x-ad1848=
+			[HW,ALSA]
+
+	snd-opti92x-cs4231=
+			[HW,ALSA]
+
+	snd-opti93x=	[HW,ALSA]
+
+	snd-pmac=	[HW,ALSA]
+
+	snd-rme32=	[HW,ALSA]
+
+	snd-rme96=	[HW,ALSA]
+
+	snd-rme9652=	[HW,ALSA]
+
+	snd-sb8=	[HW,ALSA]
+
+	snd-sb16=	[HW,ALSA]
+
+	snd-sbawe=	[HW,ALSA]
+
+	snd-serial=	[HW,ALSA]
+
+	snd-sgalaxy=	[HW,ALSA]
+
+	snd-sonicvibes=	[HW,ALSA]
+
+	snd-sun-amd7930=
+			[HW,ALSA]
+
+	snd-sun-cs4231=	[HW,ALSA]
+
+	snd-trident=	[HW,ALSA]
+
+	snd-usb-audio=	[HW,ALSA,USB]
+
+	snd-via82xx=	[HW,ALSA]
+
+	snd-virmidi=	[HW,ALSA]
+
+	snd-wavefront=	[HW,ALSA]
+
+	snd-ymfpci=	[HW,ALSA]
  
-	sonicvibes=	[HW,SOUND]
+	sonicvibes=	[HW,OSS]
+			Format: <reverb>
  
 	sonycd535=	[HW,CD]
+			Format: <io>[,<irq>]
 
-	sound=		[SOUND]
+	sonypi=		[HW] Sony Programmable I/O Control Device driver
+			Format: <minor>,<verbose>,<fnkeyinit>,<camera>,<compat>,<nojogdial>
 
-	soundmodem=	[HW,AX25,SOUND] Use sound card as packet radio modem.
+	specialix=	[HW,SERIAL] Specialix multi-serial port adapter
+			See Documentation/specialix.txt.
 
-	specialix=	[HW,SERIAL] Specialix multi-serial port adapter.
+	speedstep_coppermine=
+			[HW,IA-32] Take CPU in your notebook as SpeedStep-capable
+			See comment before function speedstep_setup() in
+			arch/i386/kernel/cpu/cpufreq/speedstep.c.
 
-	sscape=		[HW,SOUND]
+	spia_io_base=	[HW,MTD]
+	spia_fio_base=
+	spia_pedr=
+	spia_peddr=
+
+	spread_lpevents=
+			[PPC]
+
+	sscape=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<mpu_io>,<mpu_irq>
  
-	st=		[HW,SCSI] SCSI tape parameters (buffers, etc.).
+	st=		[HW,SCSI] SCSI tape parameters (buffers, etc.)
+			See Documentation/scsi/st.txt.
 
 	st0x=		[HW,SCSI]
+			See header of drivers/scsi/seagate.c.
 
-	stram_swap=	[HW]
+	stram_swap=	[HW,M68k]
 
-	swiotlb=        [IA-64] Number of I/O TLB slabs.
+	swiotlb=	[IA-64] Number of I/O TLB slabs
  
-	switches=	[HW, M68K]
+	switches=	[HW,M68k]
 
 	sym53c416=	[HW,SCSI]
+			See header of drivers/scsi/sym53c416.c.
 
 	sym53c8xx=	[HW,SCSI]
+			See Documentation/scsi/ncr53c8xx.txt.
 
 	t128=		[HW,SCSI]
+			See header of drivers/scsi/t128.c.
 
 	tdfx=		[HW,DRM]
  
-	tgfx=		[HW,JOY]
+	tgfx=		[HW,JOY] TurboGraFX parallel port interface
+	tgfx_2=		See Documentation/input/joystick-parport.txt.
+	tgfx_3=
 
-	tgfx_2=		[HW,JOY]
+	tipar=		[HW]
+			See header of drivers/char/tipar.c.
 
-	tgfx_3=		[HW,JOY]
+	tiusb=		[HW,USB] Texas Instruments' USB GraphLink (aka SilverLink)
+			Format: <timeout>
  
 	tmc8xx=		[HW,SCSI]
+			See header of drivers/scsi/seagate.c.
 
 	tmscsim=	[HW,SCSI]
+			See comment before function dc390_setup() in
+			drivers/scsi/tmscsim.c.
 
 	tp720=		[HW,PS2]
 
-	trix=		[HW,SOUND]
+	trix=		[HW,OSS] MediaTrix AudioTrix Pro
+			Format: <io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
  
-	u14-34f=	[HW,SCSI]
+	u14-34f=	[HW,SCSI] UltraStor 14F/34F SCSI host adapter
+			See header of drivers/scsi/u14-34f.c.
 
-	uart401=	[HW,SOUND]
+	uart401=	[HW,OSS]
+			Format: <io>,<irq>
 
-	uart6850=	[HW,SOUND]
- 
-	usbfix		[BUGS=IA-64] 
- 
-	video=		[FB] frame buffer configuration.
-
-	vga=		[BOOT] on IA-32, select a particular video mode
-			(use vga=ask for menu).  This is actually a
-			boot loader parameter; the value is passed to
-			the kernel using a special protocol.  See
-			linux/Documentation/i386/boot.txt for information.
+	uart6850=	[HW,OSS]
+			Format: <io>,<irq>
+ 
+	video=		[FB] Frame buffer configuration
+			See Documentation/fb/modedb.txt.
+
+	vga=		[BOOT,IA-32] Select a particular video mode
+			See Documentation/i386/boot.txt and Documentation/svga.txt.
+			Use vga=ask for menu.
+			This is actually a boot loader parameter; the value is
+			passed to the kernel using a special protocol.
 
 	vmhalt=		[KNL,S390]
 
 	vmpoff=		[KNL,S390] 
  
-	waveartist=	[HW,SOUND]
+	waveartist=	[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>
  
 	wd33c93=	[HW,SCSI]
+			See header of drivers/scsi/wd33c93.c.
 
 	wd7000=		[HW,SCSI]
+			See header of drivers/scsi/wd7000.c.
 
-	wdt=		[HW]
+	wdt=		[HW] Watchdog
+			See Documentation/watchdog.txt.
 
 	xd=		[HW,XT] Original XT pre-IDE (RLL encoded) disks.
+	xd_geo=		See header of drivers/block/xd.c.
+
+	xirc2ps_cs=	[NET,PCMCIA]
+			Format: <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
+
+
+
+Changelog:
+
+	The last known update (for 2.4.0) - the changelog was not kept before.
+	2000-06-??	Mr. Unknown
+
+	Update for 2.5.49, description for most of the options introduced,
+	references to other documentation (C files, READMEs, ..), added S390,
+	PPC, SPARC, MTD, ALSA and OSS category. Minor corrections and
+	reformatting.
+	2002-11-24	Petr Baudis <pasky@ucw.cz>
+			Randy Dunlap <randy.dunlap@verizon.net>
+
+TODO:
 
-	xd_geo=		[HW,XT]
+	Add documentation for ALSA options.
+	Add more DRM drivers.
diff -Nru a/Documentation/magic-number.txt b/Documentation/magic-number.txt
--- a/Documentation/magic-number.txt	Wed Nov 27 14:36:30 2002
+++ b/Documentation/magic-number.txt	Wed Nov 27 14:36:30 2002
@@ -43,57 +43,115 @@
 					<mailto: kgb@knm.org.pl>
 					29 Jul 1998
 
+Updated the magic table to Linux 2.5.45. Right over the feature freeze,
+but it is possible that some new magic numbers will sneak into the
+kernel before 2.6.x yet.
+
+					Petr Baudis
+					<pasky@ucw.cz>
+					03 Nov 2002
+
 Magic Name            Number      Structure            File
 ===========================================================================
-PG_MAGIC	      'P'	  pg_{read,write}_hdr include/linux/pg.h
+PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
+CMAGIC                0x0111      user              include/linux/a.out.h
 MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
 RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
+SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
+AURORA_MAGIC          0x0A18      Aurora_port       drivers/sbus/char/aurora.h
+HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
 APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
 FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
-PTY_MAGIC	      0x5001	  (none at the moment)
-					            drivers/char/pty.c
-PPP_MAGIC             0x5002      ppp               include/linux/if_ppp.h
+ISICOM_MAGIC          0x4d54      isi_port          include/linux/isicom.h
+PTY_MAGIC             0x5001      (none at the moment)
+                                                    drivers/char/pty.c
+PPP_MAGIC             0x5002      ppp               include/linux/if_pppvar.h
 SERIAL_MAGIC          0x5301      async_struct      include/linux/serial.h
 SSTATE_MAGIC          0x5302      serial_state      include/linux/serial.h
 SLIP_MAGIC            0x5302      slip              drivers/net/slip.h
 STRIP_MAGIC           0x5303      strip             drivers/net/strip.c
 X25_ASY_MAGIC         0x5303      x25_asy           drivers/net/x25_asy.h
-SIXPACK_MAGIC	      0x5304      sixpack	    drivers/net/hamradio/6pack.h
+SIXPACK_MAGIC         0x5304      sixpack           drivers/net/hamradio/6pack.h
 AX25_MAGIC            0x5316      ax_disp           drivers/net/mkiss.h
 ESP_MAGIC             0x53ee      esp_struct        drivers/char/esp.h
 TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
+MGSL_MAGIC            0x5401      mgsl_info         drivers/char/synclink.c
 TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
+MGSLPC_MAGIC          0x5402      mgslpc_info       drivers/char/pcmcia/synclink_cs.c
 TTY_LDISC_MAGIC       0x5403      tty_ldisc         include/linux/tty_ldisc.h
-SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
-CG_MAGIC	      0x090255    ufs_cylinder_group include/linux/ufs_fs.h
-RPORT_MAGIC           0x525001    r_port            drivers/char/rocket_int.h
-GDTIOCTL_MAGIC	      0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
+USB_SERIAL_MAGIC      0x6702      usb_serial        drivers/usb/serial/usb-serial.h
+USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
+RFCOMM_TTY_MAGIC      0x6d02      (note at the moment)
+                                                    net/bluetooth/rfcomm/tty.c
+USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
+CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
+A2232_MAGIC           0x000a2232  gs_port           drivers/char/ser_a2232.h
+SOLARIS_SOCKET_MAGIC  0x000ADDED  sol_socket_struct arch/sparc64/solaris/socksys.h
+RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
+LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
+GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
+RIO_MAGIC             0x12345678  gs_port           drivers/char/rio/rio_linux.c
+SX_MAGIC              0x12345678  gs_port           drivers/char/sx.h
 NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
-SLAB_RED_MAGIC2       0x170fc2a5  (any)             mm/slab.c
+RED_MAGIC2            0x170fc2a5  (any)             mm/slab.c
 BAYCOM_MAGIC          0x19730510  baycom_state      drivers/net/baycom_epp.c
 ISDN_X25IFACE_MAGIC   0x1e75a2b9  isdn_x25iface_proto_data
                                                     drivers/isdn/isdn_x25iface.h
 ECP_MAGIC             0x21504345  cdkecpsig         include/linux/cdk.h
+LSOMAGIC              0x27091997  lso               drivers/fc4/fc.c
 LSMAGIC               0x2a3b4d2a  ls                drivers/fc4/fc.c
-LSOMAGIC              0x2a3c4e3c  lso               drivers/fc4/fc.c
 WANPIPE_MAGIC         0x414C4453  sdla_{dump,exec}  include/linux/wanpipe.h
-CODA_CNODE_MAGIC      0x47114711  coda_inode_info   include/linux/coda_fs_i.h
+CS_CARD_MAGIC         0x43525553  cs_card           sound/oss/cs46xx.c
+LABELCL_MAGIC         0x4857434c  labelcl_info_s    include/asm/ia64/sn/labelcl.h
 ISDN_ASYNC_MAGIC      0x49344C01  modem_info        include/linux/isdn.h
-ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  include/linux/isdn.h
+CTC_ASYNC_MAGIC       0x49344C01  ctc_tty_info      drivers/s390/net/ctctty.c
+ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  drivers/isdn/i4l/isdn_net_lib.h
+SAVEKMSG_MAGIC2       0x4B4D5347  savekmsg          arch/*/amiga/config.c
 STLI_BOARDMAGIC       0x4bc6c825  stlibrd           include/linux/istallion.h
+CS_STATE_MAGIC        0x4c4f4749  cs_state          sound/oss/cs46xx.c
 SLAB_C_MAGIC          0x4f17a36d  kmem_cache_s      mm/slab.c
+COW_MAGIC             0x4f4f4f4d  cow_header_v1     arch/um/drivers/ubd_user.c
+I810_CARD_MAGIC       0x5072696E  i810_card         sound/oss/i810_audio.c
+TRIDENT_CARD_MAGIC    0x5072696E  trident_card      sound/oss/trident.c
 ROUTER_MAGIC          0x524d4157  wan_device        include/linux/wanrouter.h
-SLAB_RED_MAGIC1       0x5a2cf071  (any)             mm/slab.c
+SCC_MAGIC             0x52696368  gs_port           drivers/char/scc.h
+SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
+GDA_MAGIC             0x58464552  gda               include/asm-mips64/sn/gda.h
+RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
 STL_PORTMAGIC         0x5a7182c9  stlport           include/linux/stallion.h
 HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
-EPCA_MAGIC     	      0x5c6df104  channel           include/linux/epca.h
+EPCA_MAGIC            0x5c6df104  channel           include/linux/epca.h
 PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
+KV_MAGIC              0x5f4b565f  kernel_vars_s     include/asm-mips64/sn/klkernvars.h
+I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
+TRIDENT_STATE_MAGIC   0x63657373  trient_state      sound/oss/trident.c
+M3_CARD_MAGIC         0x646e6f50  m3_card           sound/oss/maestro3.c
+SLOT_MAGIC            0x67267321  slot              drivers/hotplug/cpqphp.h
+SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
 LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
+M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
 STL_PANELMAGIC        0x7ef621a1  stlpanel          include/linux/stallion.h
+VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
+KMALLOC_MAGIC         0x87654321  snd_alloc_track   sound/core/memory.c
+PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
 NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
 STL_BOARDMAGIC        0xa2267f52  stlbrd            include/linux/stallion.h
-SLAB_MAGIC_ALLOC      0xa5c32f2b  kmem_slab_s       mm/slab.c
-SLAB_MAGIC_DESTROYED  0xb2f23c5a  kmem_slab_s       mm/slab.c
+SCI_MAGIC             0xbabeface  gs_port           drivers/char/sh-sci.h
+CODA_MAGIC            0xC0DAC0DA  coda_file_info    include/linux/coda_fs_i.h
 STLI_PORTMAGIC        0xe671c7a1  stliport          include/linux/istallion.h
+YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
 CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
+HTB_CMAGIC            0xFEFAFEF1  htb_class         net/sched/sch_htb.c
+NMI_MAGIC             0x48414d4d455201 nmi_s        include/asm-mips64/sn/nmi.h
+
+Note that there are also defined special per-driver magic numbers in sound
+memory managment. See include/sound/sndmagic.h for complete list of them. Many
+OSS sound drivers have their magic numbers constructed from the soundcard PCI
+ID - these are not listed here as well.
+
+IrDA subsystem also uses large number of own magic numbers, see
+include/net/irda/irda.h for a complete list of them.
+
+HFS is another larger user of magic numbers - you can find them in
+fs/hfs/hfs.h.
diff -Nru a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
--- a/Documentation/networking/00-INDEX	Wed Nov 27 14:36:31 2002
+++ b/Documentation/networking/00-INDEX	Wed Nov 27 14:36:31 2002
@@ -104,8 +104,6 @@
 	- the driver for SMC's 9000 series of Ethernet cards
 smctr.txt
 	- SMC TokenCard TokenRing Linux driver info.
-soundmodem.txt
-	- Linux driver for sound cards as AX.25 modems
 tcp.txt
 	- short blurb on how TCP output takes place.
 tlan.txt
diff -Nru a/Documentation/networking/soundmodem.txt b/Documentation/networking/soundmodem.txt
--- a/Documentation/networking/soundmodem.txt	Wed Nov 27 14:36:27 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,90 +0,0 @@
-	     LINUX DRIVER FOR SOUNDCARDS AS AX.25 MODEMS
-
-       Thomas M. Sailer, HB9JNX/AE4WA, <sailer@ife.ee.ethz.ch>
-
-This driver allows either SoundBlaster (sbc) or Windows Sound System (wss)
-compatible soundcards to be used as either 1200 baud AFSK or 9600 baud FSK
-AX.25 packet radio modems. Only half duplex operation is supported; an
-attempt to include full duplex support failed because the hardware did
-not support it (it appeared that the card only provides one DMA channel,
-although the codec chip would support two channels). The driver needs
-some processing power! A 66 MHz 486 DX2 is a minimum requirement.  Otherwise
-interactive performance of the computer may become sluggish. This driver
-does *not* support telephone modem standards, it is intended for radio
-use only.
-
-
-The Interface of the driver
-
-The driver provides kernel network drivers named sm[0-3]. sethdlc 
-from the ax25 utilities may be used to set driver states etc. Users
-of userland AX.25 stacks may use the net2kiss utility (also available
-in the ax25 utilities package) to convert packets of a network interface
-to a KISS stream on a pseudo tty. There's also a patch available from
-me for WAMPES which allows attaching a kernel network interface directly.
-
-
-Configuring the driver
-
-Some sound cards need to be initialized before they operate in either
-SoundBlaster or WSS compatibility mode. The driver does _NOT_ do this;
-you may use the standard linux sound driver to initialize the soundcard;
-compile it as a module, and do
-  insmod sound
-  rmmod sound
-The soundcard should then be initialized correctly. If this does not help,
-you'll have to write your own initialization utility.
-
-Every time the driver is inserted into the kernel, it has to know which
-modems it should access at which ports. This can be done with the setbaycom
-utility. If you are only using one modem, you can also configure the
-driver from the insmod command line (or by means of an option line in
-/etc/modules.conf).
-
-Examples:
-  insmod soundmodem mode="sbc:afsk1200" iobase=0x220 irq=5 dma=1
-  sethdlc -i sm0 -p mode "sbc:afsk1200" io 0x220 irq 5 dma 1
-
-Both lines configure the first port to drive a soundblaster card
-in 1200 baud AFSK mode.
-
-The channel access parameters can be set with sethdlc -a or kissparms.
-Note that both utilities interpret the values slightly different.
-
-
-Input and output levels
-
-It is important that the input and output levels are adjusted properly.
-There are two utilities, available in the ax25 utilities distribution,
-to facilitate this: smmixer and smdiag. smdiag allows you to display
-the input signal in an oscilloscope like display or an eye diagram.
-smmixer allows you to adjust input/output levels. See the respective
-man pages.
-
-
-Transmitter keying
-
-Since soundcards do not have a DC coupled output; PTT keying options include
-the following:
-* VOX circuitry
-* Serial port pin
-* Parallel port pin
-* MPU401 MIDI output via a retriggerable monoflop.
-Circuit schematics may be found at
-http://www.ife.ee.ethz.ch/~sailer/pcf/ptt_circ/ptt.html.
-
-
-Compatibility with the rest of the Linux kernel
-
-The sound driver and the soundcard modem driver compete for the same
-hardware resources. Of course only one driver can access a given
-interface at a time. Worse yet, the sound driver grabs the soundcard
-at startup time. Therefore the soundcard modem driver subsequently won't
-be able to access the soundcard. You might therefore find it necessary to
-unload the sound driver before using the soundcard modem driver.
-
-
-
-vy 73s de
-Tom Sailer, sailer@ife.ee.ethz.ch
-hb9jnx @ hb9w.ampr.org
diff -Nru a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
--- a/Documentation/sysctl/kernel.txt	Wed Nov 27 14:36:30 2002
+++ b/Documentation/sysctl/kernel.txt	Wed Nov 27 14:36:30 2002
@@ -17,29 +17,42 @@
 Currently, these files might (depending on your configuration)
 show up in /proc/sys/kernel:
 - acct
+- core_pattern
+- core_uses_pid
 - ctrl-alt-del
 - dentry-state
 - domainname
 - hostname
 - htab-reclaim                [ PPC only ]
+- hotplug
 - java-appletviewer           [ binfmt_java, obsolete ]
 - java-interpreter            [ binfmt_java, obsolete ]
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/kmod.txt
+- msgmax
+- msgmnb
+- msgmni
 - osrelease
 - ostype
 - overflowgid
 - overflowuid
 - panic
+- pid_max
 - powersave-nap               [ PPC only ]
 - printk
 - real-root-dev               ==> Documentation/initrd.txt
 - reboot-cmd                  [ SPARC only ]
-- rtsig-nr
 - rtsig-max
+- rtsig-nr
+- sem
 - sg-big-buff                 [ generic SCSI device (sg) ]
+- shmall
 - shmmax                      [ sysv ipc ]
+- shmmni
+- stop-a                      [ SPARC only ]
+- sysrq                       ==> Documentation/sysrq.txt
 - tainted
+- threads-max
 - version
 - zero-paged                  [ PPC only ]
 
@@ -62,6 +75,41 @@
 
 ==============================================================
 
+core_pattern:
+
+core_pattern is used to specify a core dumpfile pattern name.
+. max length 64 characters; default value is "core"
+. core_pattern is used as a pattern template for the output filename;
+  certain string patterns (beginning with '%') are substituted with
+  their actual values.
+. backward compatibility with core_uses_pid:
+	If core_pattern does not include "%p" (default does not)
+	and core_uses_pid is set, then .PID will be appended to
+	the filename.
+. corename format specifiers:
+	%<NUL>	'%' is dropped
+	%%	output one '%'
+	%p	pid
+	%u	uid
+	%g	gid
+	%s	signal number
+	%t	UNIX time of dump
+	%h	hostname
+	%e	executable filename
+	%<OTHER> both are dropped
+
+==============================================================
+
+core_uses_pid:
+
+The default coredump filename is "core".  By setting
+core_uses_pid to 1, the coredump filename becomes core.PID.
+If core_pattern does not include "%p" (default does not)
+and core_uses_pid is set, then .PID will be appended to
+the filename.
+
+==============================================================
+
 ctrl-alt-del:
 
 When the value in this file is 0, ctrl-alt-del is trapped and
@@ -105,6 +153,13 @@
  
 ==============================================================
 
+hotplug:
+
+Path for the hotplug policy agent.
+Default value is "/sbin/hotplug".
+
+==============================================================
+
 l2cr: (PPC only)
 
 This flag controls the L2 cache of G3 processor boards. If
@@ -149,6 +204,14 @@
 
 ==============================================================
 
+pid_max:
+
+PID allocation wrap value.  When the kenrel's next PID value
+reaches this value, it wraps back to a minimum PID value.
+PIDs of value pid_max or larger are not allocated.
+
+==============================================================
+
 powersave-nap: (PPC only)
 
 If set, Linux-PPC will use the 'nap' mode of powersaving,
@@ -195,7 +258,7 @@
 of POSIX realtime (queued) signals that can be outstanding
 in the system.
 
-Rtsig-nr shows the number of RT signals currently queued.
+rtsig-nr shows the number of RT signals currently queued.
 
 ==============================================================
 
@@ -231,6 +294,7 @@
       Set by modutils >= 2.4.9.
   2 - A module was force loaded by insmod -f.
       Set by modutils >= 2.4.9.
+  4 - Unsafe SMP processors: SMP with CPUs not designed for SMP.
 
 ==============================================================
 
diff -Nru a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt
--- a/Documentation/usb/ov511.txt	Wed Nov 27 14:36:27 2002
+++ b/Documentation/usb/ov511.txt	Wed Nov 27 14:36:27 2002
@@ -255,6 +255,15 @@
 	might be necessary if your camera has a custom lens assembly. This has
 	no effect with video capture devices.
 
+  NAME: ov518_color
+  TYPE: integer (Boolean)
+  DEFAULT: 0 (off)
+  DESC: Enable OV518 color support. This is off by default since it doesn't
+	work most of the time. If you want to try it, you must also load
+	ov518_decomp with the "nouv=0" parameter. If you get improper colors or
+	diagonal lines through the image, restart your video app and try again.
+	Repeat as necessary.
+
 WORKING FEATURES:
  o Color streaming/capture at most widths and heights that are multiples of 8.
  o Monochrome (use force_palette=1 to enable)
diff -Nru a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
--- a/Documentation/usb/usb-serial.txt	Wed Nov 27 14:36:27 2002
+++ b/Documentation/usb/usb-serial.txt	Wed Nov 27 14:36:27 2002
@@ -94,10 +94,11 @@
 Compaq iPAQ, HP Jornada and Casio EM500 driver
 
   This driver can be used to connect to Compaq iPAQ, HP Jornada and Casio EM500
-  PDAs running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle. It
-  has been tested only on the Compaq H3135, but is rumoured to work on
-  with the H3600 and later models as well as the Jornada 548 and 568.
-  With minor modifications, it may work for other CE based handhelds too.
+  PDAs running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle.
+  It's very likely that every device supported by ActiveSync USB works with this
+  driver. The driver supports the Compaq iPAQ, Jornada 548/568 and the Casio
+  EM500 out of the box. For others, please use module parameters to specify
+  the product and vendor id. e.g. modprobe ipaq vendor=0x3f0 product=0x1125
 
   The driver presents a serial interface (usually on /dev/ttyUSB0) over
   which one may run ppp and establish a TCP/IP link to the iPAQ. Once this
@@ -105,36 +106,12 @@
   significant advantage of using USB is speed - you can get 73 to 113
   kbytes/sec for download/upload to the iPAQ.
 
-  The driver works intermittently with the usb-uhci driver but quite
-  reliably with the uhci driver. However, performance is much better
-  with usb-uhci. It does not seem to work with ohci at all.
+  This driver is only one of a set of components required to utilize
+  the USB connection. Please visit http://synce.sourceforge.net which
+  contains the necessary packages and a simple step-by-step howto.
 
-  You must setup hotplug to invoke pppd as soon as the iPAQ is connected.
-  A ppp script like the one below should be kept in the file
-  /etc/hotplug/usb/ipaq Remember to chmod +x. Make sure there are no
-  options in /etc/ppp/options or ~/.ppprc which conflict with the ones
-  given below.
-
-	#!/bin/bash
-
-	MYIP=linux.box.ip
-	REMOTEIP=ipaq.ip
-	MYDNS=my.dns.server
-	killall -9 pppd
-	/usr/sbin/pppd /dev/ttyUSB0 \
-	connect "/usr/sbin/chat -v TIMEOUT 60 CLIENT 'CLIENTSERVER\c'" \
-	nocrtscts local debug passive $MYIP:$REMOTEIP ms-dns $MYDNS noauth \
-	proxyarp
-
-  You must also download and install asyncd from http://synce.sourceforge.net
-  This is required to emulate keep-alive packets which are exchanged by
-  ActiveSync and the iPAQ.
-
-  On connecting the cable, you should see the usual "Device Connected",
-  "User Authenticated" messages flash by on your iPAQ. Once connected,
-  you can use Win CE programs like ftpView, Pocket Outlook from the iPAQ
-  and xcerdisp, synce utilities from the Linux side. Remember to enable IP
-  forwarding. 
+  Once connected, you can use Win CE programs like ftpView, Pocket Outlook
+  from the iPAQ and xcerdisp, synce utilities from the Linux side.
 
   To use Pocket IE, follow the instructions given at
   http://www.tekguru.co.uk/EM500/usbtonet.htm to achieve the same thing
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Wed Nov 27 14:36:27 2002
+++ b/Makefile	Wed Nov 27 14:36:27 2002
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 49
+SUBLEVEL = 50
 EXTRAVERSION =
 
 # *DOCUMENTATION*
@@ -168,7 +168,10 @@
 
 CPPFLAGS	:= -D__KERNEL__ -Iinclude
 CFLAGS 		:= $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
-	  	   -fomit-frame-pointer -fno-strict-aliasing -fno-common
+	  	   -fno-strict-aliasing -fno-common
+ifndef CONFIG_FRAME_POINTER
+CFLAGS		+= -fomit-frame-pointer
+endif
 AFLAGS		:= -D__ASSEMBLY__ $(CPPFLAGS)
 
 export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
diff -Nru a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
--- a/arch/alpha/kernel/systbls.S	Wed Nov 27 14:36:31 2002
+++ b/arch/alpha/kernel/systbls.S	Wed Nov 27 14:36:31 2002
@@ -399,7 +399,7 @@
 	.quad sys_getdents64
 	.quad sys_gettid
 	.quad sys_readahead
-	.quad sys_ni_syscall			/* 380, sys_security */
+	.quad sys_ni_syscall			/* 380 */
 	.quad sys_tkill
 	.quad sys_setxattr
 	.quad sys_lsetxattr
diff -Nru a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c
--- a/arch/arm/boot/compressed/ofw-shark.c	Wed Nov 27 14:36:30 2002
+++ b/arch/arm/boot/compressed/ofw-shark.c	Wed Nov 27 14:36:30 2002
@@ -27,7 +27,7 @@
 	/* Head of the taglist */
 	tag->hdr.tag  = ATAG_CORE;
 	tag->hdr.size = tag_size(tag_core);
-	tag->u.core.flags = FLAG_READONLY;
+	tag->u.core.flags = 1;
 	tag->u.core.pagesize = PAGE_SIZE;
 	tag->u.core.rootdev = 0;
 
diff -Nru a/arch/arm/def-configs/shark b/arch/arm/def-configs/shark
--- a/arch/arm/def-configs/shark	Wed Nov 27 14:36:27 2002
+++ b/arch/arm/def-configs/shark	Wed Nov 27 14:36:27 2002
@@ -40,6 +40,7 @@
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
@@ -110,6 +111,12 @@
 # CONFIG_H3600_SLEEVE is not set
 
 #
+# Intel PXA250/210 Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_ARCH_PXA_IDP is not set
+
+#
 # CLPS711X/EP721X Implementations
 #
 # CONFIG_ARCH_AUTCPU12 is not set
@@ -120,6 +127,19 @@
 # CONFIG_ARCH_FORTUNET is not set
 # CONFIG_ARCH_EP7211 is not set
 # CONFIG_ARCH_EP7212 is not set
+
+#
+# IOP310 Implementation Options
+#
+# CONFIG_ARCH_IQ80310 is not set
+
+#
+# IOP310 Chipset Features
+#
+# CONFIG_IOP310_AAU is not set
+# CONFIG_IOP310_DMA is not set
+# CONFIG_IOP310_MU is not set
+# CONFIG_IOP310_PMON is not set
 # CONFIG_ARCH_ACORN is not set
 # CONFIG_FOOTBRIDGE is not set
 # CONFIG_FOOTBRIDGE_HOST is not set
@@ -159,6 +179,9 @@
 CONFIG_ISA=y
 CONFIG_ISA_DMA=y
 # CONFIG_FIQ is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
 # CONFIG_PCI_NAMES is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_PCMCIA is not set
@@ -177,10 +200,11 @@
 # CONFIG_PREEMPT is not set
 # CONFIG_APM is not set
 # CONFIG_ARTHUR is not set
+CONFIG_CMDLINE=""
 CONFIG_LEDS=y
 CONFIG_LEDS_TIMER=y
 # CONFIG_LEDS_CPU is not set
-# CONFIG_ALIGNMENT_TRAP is not set
+CONFIG_ALIGNMENT_TRAP=y
 
 #
 # Parallel port support
@@ -201,6 +225,11 @@
 # CONFIG_PARPORT_1284 is not set
 
 #
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
 # Plug and Play configuration
 #
 # CONFIG_PNP is not set
@@ -217,6 +246,7 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
 # CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
@@ -254,7 +284,6 @@
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -263,6 +292,11 @@
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
 # CONFIG_DECNET is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
@@ -378,7 +412,7 @@
 # CONFIG_WAN is not set
 
 #
-# "Tulip" family network device support
+# Tulip family network device support
 #
 # CONFIG_NET_TULIP is not set
 
@@ -393,38 +427,66 @@
 # CONFIG_IRDA is not set
 
 #
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
-
-#
-# ATA and ATAPI Block devices
-#
 CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
 # CONFIG_BLK_DEV_HD_IDE is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 # CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 # CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_IDECS is not set
 
 #
-# IDE chipset support
+# ATA host controller support
 #
+# CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
+
+#
+#   PCI host controller support
+#
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_IDE_TCQ is not set
+# CONFIG_BLK_DEV_IDE_TCQ_DEFAULT is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC6280_BURST is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_IVB is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
@@ -451,6 +513,7 @@
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_REPORT_LUNS is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 
@@ -462,7 +525,6 @@
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_DPT_I2O is not set
@@ -522,42 +584,60 @@
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN is not set
+# CONFIG_ISDN_BOOL is not set
 
 #
 # Input device support
 #
 # CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
 # CONFIG_INPUT_KEYBDEV is not set
 # CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 # CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_TSLIBDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Input I/O drivers
+#
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_GAMEPORT_NS558 is not set
 # CONFIG_GAMEPORT_L4 is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_GAMEPORT_PCIGAME is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
 # CONFIG_GAMEPORT_FM801 is not set
 # CONFIG_GAMEPORT_CS461x is not set
 # CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
 # CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
+
+#
+# Input Device Drivers
+#
 
 #
 # Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_CS is not set
 # CONFIG_SERIAL_8250_EXTENDED is not set
 # CONFIG_SERIAL_8250_MANY_PORTS is not set
 # CONFIG_SERIAL_8250_SHARE_IRQ is not set
@@ -568,10 +648,6 @@
 #
 # Non-8250 serial port support
 #
-
-#
-# ARM Serial drivers
-#
 # CONFIG_ATOMWIDE_SERIAL is not set
 # CONFIG_DUALSP_SERIAL is not set
 # CONFIG_SERIAL_ANAKIN is not set
@@ -580,6 +656,7 @@
 # CONFIG_SERIAL_AMBA_CONSOLE is not set
 # CONFIG_SERIAL_CLPS711X is not set
 # CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X_OLD_NAME is not set
 # CONFIG_SERIAL_21285 is not set
 # CONFIG_SERIAL_21285_OLD is not set
 # CONFIG_SERIAL_21285_CONSOLE is not set
@@ -587,6 +664,8 @@
 # CONFIG_SERIAL_UART00_CONSOLE is not set
 # CONFIG_SERIAL_SA1100 is not set
 # CONFIG_SERIAL_SA1100_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
 CONFIG_PRINTER=m
@@ -615,17 +694,13 @@
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
 # CONFIG_QIC02_TAPE is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
 # CONFIG_DTLK is not set
@@ -638,6 +713,7 @@
 # CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
 
 #
 # Multimedia devices
@@ -648,6 +724,8 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -711,6 +789,7 @@
 # CONFIG_NFSD_TCP is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -741,6 +820,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
 # CONFIG_SMB_NLS is not set
 CONFIG_NLS=y
 
@@ -769,6 +849,7 @@
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
 # CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
@@ -788,8 +869,6 @@
 #
 # Console drivers
 #
-CONFIG_PC_KEYB=y
-CONFIG_PC_KEYMAP=y
 # CONFIG_VGA_CONSOLE is not set
 
 #
@@ -797,7 +876,6 @@
 #
 CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_RIVA is not set
 # CONFIG_FB_CLGEN is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_PM3 is not set
@@ -806,6 +884,7 @@
 # CONFIG_FB_CLPS711X is not set
 # CONFIG_FB_SA1100 is not set
 CONFIG_FB_CYBER2000=y
+# CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_ATY is not set
 # CONFIG_FB_RADEON is not set
@@ -814,6 +893,8 @@
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_PM3 is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -903,6 +984,8 @@
 # Console Switches
 #
 # CONFIG_SWITCHES is not set
+# CONFIG_SWITCHES_SA1100 is not set
+# CONFIG_SWITCHES_UCB1X00 is not set
 
 #
 # USB support
@@ -930,6 +1013,11 @@
 # CONFIG_DEBUG_LL is not set
 # CONFIG_DEBUG_DC21285_PORT is not set
 # CONFIG_DEBUG_CLPS711X_UART2 is not set
+
+#
+# Security options
+#
+CONFIG_SECURITY_CAPABILITIES=y
 
 #
 # Library routines
diff -Nru a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c
--- a/arch/arm/kernel/arthur.c	Wed Nov 27 14:36:28 2002
+++ b/arch/arm/kernel/arthur.c	Wed Nov 27 14:36:28 2002
@@ -17,7 +17,6 @@
 #include <linux/personality.h>
 #include <linux/stddef.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
@@ -64,13 +63,13 @@
 }
 
 static struct exec_domain arthur_exec_domain = {
-	"Arthur",	/* name */
-	arthur_lcall7,
-	PER_RISCOS, PER_RISCOS,
-	arthur_to_linux_signals,
-	linux_to_arthur_signals,
-	THIS_MODULE,
-	NULL		/* Nothing after this in the list. */
+	.name		= "Arthur",
+	.handler	= arthur_lcall7,
+	.pers_low	= PER_RISCOS,
+	.pers_high	= PER_RISCOS,
+	.signal_map	= arthur_to_linux_signals,
+	.signal_invmap	= linux_to_arthur_signals,
+	.module		= THIS_MODULE,
 };
 
 /*
@@ -78,12 +77,12 @@
  * processes are using it.
  */
 
-int __init arthur_init(void)
+static int __init arthur_init(void)
 {
 	return register_exec_domain(&arthur_exec_domain);
 }
 
-void __exit arthur_exit(void)
+static void __exit arthur_exit(void)
 {
 	unregister_exec_domain(&arthur_exec_domain);
 }
diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
--- a/arch/arm/kernel/calls.S	Wed Nov 27 14:36:32 2002
+++ b/arch/arm/kernel/calls.S	Wed Nov 27 14:36:32 2002
@@ -237,7 +237,7 @@
 /* 220 */	.long	sys_madvise
 		.long	sys_fcntl64
 		.long	sys_ni_syscall /* TUX */
-		.long	sys_security
+		.long	sys_ni_syscall
 		.long	sys_gettid
 /* 225 */	.long	sys_readahead
 		.long	sys_setxattr
diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
--- a/arch/arm/kernel/ptrace.c	Wed Nov 27 14:36:27 2002
+++ b/arch/arm/kernel/ptrace.c	Wed Nov 27 14:36:27 2002
@@ -711,8 +711,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/arch/arm/kernel/via82c505.c b/arch/arm/kernel/via82c505.c
--- a/arch/arm/kernel/via82c505.c	Wed Nov 27 14:36:27 2002
+++ b/arch/arm/kernel/via82c505.c	Wed Nov 27 14:36:27 2002
@@ -20,7 +20,7 @@
 via82c505_read_config(struct pci_bus *bus, unsigned int devfn, int where,
 		      int size, u32 *value)
 {
-	outl(CONFIG_CMD(dev,where),0xCF8);
+	outl(CONFIG_CMD(bus,devfn,where),0xCF8);
 	switch (size) {
 	case 1:
 		*value=inb(0xCFC + (where&3));
@@ -36,7 +36,7 @@
 }
 
 static int
-via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where
+via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 		       int size, u32 value)
 {
 	outl(CONFIG_CMD(bus,devfn,where),0xCF8);
@@ -61,8 +61,6 @@
 
 void __init via82c505_preinit(void *sysdata)
 {
-	struct pci_bus *bus;
-
 	printk(KERN_DEBUG "PCI: VIA 82c505\n");
 	if (!request_region(0xA8,2,"via config")) {
 		printk(KERN_WARNING"VIA 82c505: Unable to request region 0xA8\n");
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
--- a/arch/arm/mach-sa1100/cpu-sa1110.c	Wed Nov 27 14:36:27 2002
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c	Wed Nov 27 14:36:27 2002
@@ -305,7 +305,7 @@
 	.verify		 = sa11x0_verify_speed,
 	.setpolicy	 = sa1110_setspeed,
 	.policy		 = &sa1110_policy,
-	.cpu_min_freq[0] = 59000,
+	.cpu_min_freq	 = { 59000, },
 };
 
 static int __init sa1110_clk_init(void)
diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
--- a/arch/arm/mach-sa1100/generic.h	Wed Nov 27 14:36:31 2002
+++ b/arch/arm/mach-sa1100/generic.h	Wed Nov 27 14:36:31 2002
@@ -21,5 +21,5 @@
 struct cpufreq_policy;
 
 extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
-extern void sa11x0_verify_speed(struct cpufreq_policy *policy);
+extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
 extern unsigned int sa11x0_getspeed(void);
diff -Nru a/arch/arm/mach-sa1100/sa1111-pcibuf.c b/arch/arm/mach-sa1100/sa1111-pcibuf.c
--- a/arch/arm/mach-sa1100/sa1111-pcibuf.c	Wed Nov 27 14:36:27 2002
+++ b/arch/arm/mach-sa1100/sa1111-pcibuf.c	Wed Nov 27 14:36:27 2002
@@ -31,6 +31,14 @@
 #define DPRINTK(...) do { } while (0)
 #endif
 
+//#define STATS
+#ifdef STATS
+#define DO_STATS(X) do { X ; } while (0)
+#else
+#define DO_STATS(X) do { } while (0)
+#endif
+
+/* ************************************************** */
 
 struct safe_buffer {
 	struct list_head node;
@@ -50,10 +58,24 @@
 
 
 #define SIZE_SMALL	1024
-#define SIZE_LARGE	(16*1024)
+#define SIZE_LARGE	(4*1024)
 
 static struct pci_pool *small_buffer_pool, *large_buffer_pool;
 
+#ifdef STATS
+static unsigned long sbp_allocs __initdata = 0;
+static unsigned long lbp_allocs __initdata = 0;
+static unsigned long total_allocs __initdata= 0;
+
+static void print_alloc_stats(void)
+{
+	printk(KERN_INFO
+	       "sa1111_pcibuf: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
+	       sbp_allocs, lbp_allocs,
+	       total_allocs - sbp_allocs - lbp_allocs, total_allocs);
+}
+#endif
+
 static int __init
 create_safe_buffer_pools(void)
 {
@@ -81,6 +103,10 @@
 		return -1;
 	}
 
+	printk(KERN_INFO
+	       "sa1111_pcibuf: buffer sizes: small=%u, large=%u\n",
+	       SIZE_SMALL, SIZE_LARGE);
+
 	return 0;
 }
 
@@ -108,6 +134,8 @@
 	DPRINTK("%s(ptr=%p, size=%d, direction=%d)\n",
 		__func__, ptr, size, direction);
 
+	DO_STATS ( total_allocs++ );
+
 	buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
 	if (buf == 0) {
 		printk(KERN_WARNING "%s: kmalloc failed\n", __func__);
@@ -117,12 +145,14 @@
 	if (size <= SIZE_SMALL) {
 		pool = small_buffer_pool;
 		safe = pci_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
+
+		DO_STATS ( sbp_allocs++ );
 	} else if (size <= SIZE_LARGE) {
 		pool = large_buffer_pool;
 		safe = pci_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
+
+		DO_STATS ( lbp_allocs++ );
 	} else {
-		printk(KERN_DEBUG
-		       "sa111_pcibuf: resorting to pci_alloc_consistent\n");
 		pool = 0;
 		safe = pci_alloc_consistent(SA1111_FAKE_PCIDEV, size,
 					    &safe_dma_addr);
@@ -136,6 +166,11 @@
 		return 0;
 	}
 
+#ifdef STATS
+	if (total_allocs % 1000 == 0)
+		print_alloc_stats();
+#endif
+
 	BUG_ON(sa1111_check_dma_bug(safe_dma_addr));	// paranoia
 
 	buf->ptr = ptr;
@@ -204,37 +239,39 @@
 	return ((physaddr + size - 1) < (1<<20));
 }
 
-/*
- * see if a buffer address is in an 'unsafe' range.  if it is
- * allocate a 'safe' buffer and copy the unsafe buffer into it.
- * substitute the safe buffer for the unsafe one.
- * (basically move the buffer from an unsafe area to a safe one)
- */
-dma_addr_t
-sa1111_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
-{
-	unsigned long flags;
-	dma_addr_t dma_addr;
+/* ************************************************** */
 
-	DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n",
-	       __func__, hwdev, ptr, size, direction);
+#ifdef STATS
+static unsigned long map_op_count __initdata = 0;
+static unsigned long bounce_count __initdata = 0;
 
-	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
-	BUG_ON(direction == PCI_DMA_NONE);
+static void print_map_stats(void)
+{
+	printk(KERN_INFO
+	       "sa1111_pcibuf: map_op_count=%lu, bounce_count=%lu\n",
+	       map_op_count, bounce_count);
+}
+#endif
 
-	local_irq_save(flags);
+static dma_addr_t
+map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+{
+	dma_addr_t dma_addr;
+
+	DO_STATS ( map_op_count++ );
 
 	dma_addr = virt_to_bus(ptr);
 
 	if (!dma_range_is_safe(dma_addr, size)) {
 		struct safe_buffer *buf;
 
+		DO_STATS ( bounce_count++ ) ;
+
 		buf = alloc_safe_buffer(hwdev, ptr, size, direction);
 		if (buf == 0) {
 			printk(KERN_ERR
 			       "%s: unable to map unsafe buffer %p!\n",
 			       __func__, ptr);
-			local_irq_restore(flags);
 			return 0;
 		}
 
@@ -256,33 +293,22 @@
 		consistent_sync(ptr, size, direction);
 	}
 
-	local_irq_restore(flags);
+#ifdef STATS
+	if (map_op_count % 1000 == 0)
+		print_map_stats();
+#endif
+
 	return dma_addr;
 }
 
-/*
- * see if a mapped address was really a "safe" buffer and if so, copy
- * the data from the safe buffer back to the unsafe buffer and free up
- * the safe buffer.  (basically return things back to the way they
- * should be)
- */
-
-void
-sa1111_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-		    size_t size, int direction)
+static void
+unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+	     size_t size, int direction)
 {
-	unsigned long flags;
 	struct safe_buffer *buf;
 
-	DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n",
-		__func__, hwdev, (void *) dma_addr, size, direction);
-
-	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
-	BUG_ON(direction == PCI_DMA_NONE);
-
-	local_irq_save(flags);
-
 	buf = find_safe_buffer(dma_addr);
+
 	if (buf) {
 		BUG_ON(buf->size != size);
 		BUG_ON(buf->direction != direction);
@@ -292,6 +318,9 @@
 			buf->ptr, (void *) virt_to_bus(buf->ptr),
 			buf->safe, (void *) buf->safe_dma_addr);
 
+
+		DO_STATS ( bounce_count++ );
+
 		if ((direction == PCI_DMA_FROMDEVICE) ||
 		    (direction == PCI_DMA_BIDIRECTIONAL)) {
 			DPRINTK("%s: copy back from safe %p, to unsafe %p size %d\n",
@@ -300,39 +329,16 @@
 		}
 		free_safe_buffer(buf);
 	}
-
-	local_irq_restore(flags);
-}
-
-int
-sa1111_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-	      int nents, int direction)
-{
-	BUG();			/* Not implemented. */
 }
 
-void
-sa1111_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
-	     int direction)
-{
-	BUG();			/* Not implemented. */
-}
-
-void
-sa1111_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+static void
+sync_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
 		       size_t size, int direction)
 {
-	unsigned long flags;
 	struct safe_buffer *buf;
 
-	DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n",
-		__func__, hwdev, (void *) dma_addr, size, direction);
-
-	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
-
-	local_irq_save(flags);
-
 	buf = find_safe_buffer(dma_addr);
+
 	if (buf) {
 		BUG_ON(buf->size != size);
 		BUG_ON(buf->direction != direction);
@@ -342,6 +348,8 @@
 			buf->ptr, (void *) virt_to_bus(buf->ptr),
 			buf->safe, (void *) buf->safe_dma_addr);
 
+		DO_STATS ( bounce_count++ );
+
 		switch (direction) {
 		case PCI_DMA_FROMDEVICE:
 			DPRINTK("%s: copy back from safe %p, to unsafe %p size %d\n",
@@ -362,15 +370,159 @@
 	} else {
 		consistent_sync(bus_to_virt(dma_addr), size, direction);
 	}
+}
+
+/* ************************************************** */
+
+/*
+ * see if a buffer address is in an 'unsafe' range.  if it is
+ * allocate a 'safe' buffer and copy the unsafe buffer into it.
+ * substitute the safe buffer for the unsafe one.
+ * (basically move the buffer from an unsafe area to a safe one)
+ */
+dma_addr_t
+sa1111_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+{
+	unsigned long flags;
+	dma_addr_t dma_addr;
+
+	DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n",
+	       __func__, hwdev, ptr, size, direction);
+
+	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	local_irq_save(flags);
+
+	dma_addr = map_single(hwdev, ptr, size, direction);
+
+	local_irq_restore(flags);
+
+	return dma_addr;
+}
+
+/*
+ * see if a mapped address was really a "safe" buffer and if so, copy
+ * the data from the safe buffer back to the unsafe buffer and free up
+ * the safe buffer.  (basically return things back to the way they
+ * should be)
+ */
+
+void
+sa1111_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+		    size_t size, int direction)
+{
+	unsigned long flags;
+
+	DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n",
+		__func__, hwdev, (void *) dma_addr, size, direction);
+
+	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	local_irq_save(flags);
+
+	unmap_single(hwdev, dma_addr, size, direction);
+
+	local_irq_restore(flags);
+}
+
+int
+sa1111_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+	      int nents, int direction)
+{
+	unsigned long flags;
+	int i;
+
+	DPRINTK("%s(hwdev=%p,sg=%p,nents=%d,dir=%x)\n",
+		__func__, hwdev, sg, nents, direction);
+
+	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < nents; i++, sg++) {
+		struct page *page = sg->page;
+		unsigned int offset = sg->offset;
+		unsigned int length = sg->length;
+		void *ptr = page_address(page) + offset;
+
+		sg->dma_address =
+			map_single(hwdev, ptr, length, direction);
+	}
+
+	local_irq_restore(flags);
+
+	return nents;
+}
+
+void
+sa1111_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
+	     int direction)
+{
+	unsigned long flags;
+	int i;
+
+	DPRINTK("%s(hwdev=%p,sg=%p,nents=%d,dir=%x)\n",
+		__func__, hwdev, sg, nents, direction);
+
+	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < nents; i++, sg++) {
+		dma_addr_t dma_addr = sg->dma_address;
+		unsigned int length = sg->length;
+
+		unmap_single(hwdev, dma_addr, length, direction);
+	}
+
+	local_irq_restore(flags);
+}
+
+void
+sa1111_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+		       size_t size, int direction)
+{
+	unsigned long flags;
+
+	DPRINTK("%s(hwdev=%p,ptr=%p,size=%d,dir=%x)\n",
+		__func__, hwdev, (void *) dma_addr, size, direction);
+
+	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
+
+	local_irq_save(flags);
+
+	sync_single(hwdev, dma_addr, size, direction);
 
 	local_irq_restore(flags);
 }
 
 void
 sa1111_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-		   int nelems, int direction)
+		   int nents, int direction)
 {
-	BUG();			/* Not implemented. */
+	unsigned long flags;
+	int i;
+
+	DPRINTK("%s(hwdev=%p,sg=%p,nents=%d,dir=%x)\n",
+		__func__, hwdev, sg, nents, direction);
+
+	BUG_ON(hwdev != SA1111_FAKE_PCIDEV);
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	local_irq_save(flags);
+
+	for (i = 0; i < nents; i++, sg++) {
+		dma_addr_t dma_addr = sg->dma_address;
+		unsigned int length = sg->length;
+
+		sync_single(hwdev, dma_addr, length, direction);
+	}
+
+	local_irq_restore(flags);
 }
 
 EXPORT_SYMBOL(sa1111_map_single);
@@ -398,6 +550,11 @@
 static void __exit sa1111_pcibuf_exit(void)
 {
 	BUG_ON(!list_empty(&safe_buffers));
+
+#ifdef STATS
+	print_alloc_stats();
+	print_map_stats();
+#endif
 
 	destroy_safe_buffer_pools();
 }
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Wed Nov 27 14:36:28 2002
+++ b/arch/i386/Kconfig	Wed Nov 27 14:36:28 2002
@@ -1612,6 +1612,20 @@
 	  symbolic stack backtraces. This increases the size of the kernel
 	  somewhat, as all symbols have to be loaded into the kernel image.
 
+config DEBUG_SPINLOCK_SLEEP
+	bool "Sleep-inside-spinlock checking"
+	help
+	  If you say Y here, various routines which may sleep will become very
+	  noisy if they are called with a spinlock held.	
+
+config FRAME_POINTER
+	bool "Compile the kernel with frame pointers"
+	help
+	  If you say Y here the resulting kernel image will be slightly larger
+	  and slower, but it will give very useful debugging information.
+	  If you don't debug the kernel, you can say N, but we may not be able
+	  to solve problems without frame pointers.
+
 config X86_EXTRA_IRQS
 	bool
 	depends on X86_LOCAL_APIC
diff -Nru a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
--- a/arch/i386/kernel/cpu/cyrix.c	Wed Nov 27 14:36:28 2002
+++ b/arch/i386/kernel/cpu/cyrix.c	Wed Nov 27 14:36:28 2002
@@ -106,6 +106,89 @@
 	}
 }
 
+
+static void __init set_cx86_reorder(void)
+{
+#ifdef CONFIG_OOSTORE
+	u8 ccr3;
+
+	printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n");
+	ccr3 = getCx86(CX86_CCR3);
+	setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
+
+	/* Load/Store Serialize to mem access disable (=reorder it)  */
+	setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80);
+#ifdef CONFIG_NOHIGHMEM
+	/* set load/store serialize from 1GB to 4GB */
+	ccr3 |= 0xe0;
+#endif
+	setCx86(CX86_CCR3, ccr3);
+#endif	
+}
+
+static void __init set_cx86_memwb(void)
+{
+	u32 cr0;
+
+	printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n");
+
+	/* CCR2 bit 2: unlock NW bit */
+	setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
+	/* set 'Not Write-through' */
+	cr0 = 0x20000000;
+	__asm__("movl %%cr0,%%eax\n\t"
+		"orl %0,%%eax\n\t"
+		"movl %%eax,%%cr0\n"
+		: : "r" (cr0)
+		:"ax");
+	/* CCR2 bit 2: lock NW bit and set WT1 */
+	setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
+}
+
+static void __init set_cx86_inc(void)
+{
+	unsigned char ccr3;
+
+	printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n");
+
+	ccr3 = getCx86(CX86_CCR3);
+	setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
+	/* PCR1 -- Performance Control */
+	/* Incrementor on, whatever that is */
+	setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02);
+	/* PCR0 -- Performance Control */
+	/* Incrementor Margin 10 */
+	setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04); 
+	setCx86(CX86_CCR3, ccr3);	/* disable MAPEN */
+}
+
+/*
+ *	Configure later MediaGX and/or Geode processor.
+ */
+
+static void __init geode_configure(void)
+{
+	unsigned long flags;
+	u8 ccr3, ccr4;
+	unsigned long cr0;
+	local_irq_save(flags);
+	
+	ccr3 = getCx86(CX86_CCR3);
+	setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);	/* Enable */
+	
+	ccr4 = getCx86(CX86_CCR4);
+	ccr4 |= 0x38;		/* FPU fast, DTE cache, Mem bypass */
+	
+	setCx86(CX86_CCR3, ccr3);
+	
+	set_cx86_memwb();
+	set_cx86_reorder();	
+	set_cx86_inc();
+	
+	local_irq_restore(flags);
+}
+
+
 static void __init init_cyrix(struct cpuinfo_x86 *c)
 {
 	unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
@@ -201,7 +284,10 @@
 		if (c->cpuid_level == 2) {
 			/* Enable cxMMX extensions (GX1 Datasheet 54) */
 			setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1);
-
+			
+			/* GXlv/GXm/GX1 */
+			if((dir1 >= 0x50 && dir1 <= 0x54) || dir1 >= 0x63)
+				geode_configure();
 			get_model_name(c);  /* get CPU marketing name */
 			return;
 		}
diff -Nru a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c
--- a/arch/i386/kernel/cpu/mcheck/non-fatal.c	Wed Nov 27 14:36:28 2002
+++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c	Wed Nov 27 14:36:28 2002
@@ -49,7 +49,6 @@
 
 static void do_mce_timer(void *data)
 { 
-	mce_checkregs (NULL);
 	smp_call_function (mce_checkregs, NULL, 1, 1);
 } 
 
@@ -57,11 +56,10 @@
 
 static void mce_timerfunc (unsigned long data)
 {
+	mce_checkregs (NULL);
 #ifdef CONFIG_SMP
 	if (num_online_cpus() > 1) 
 		schedule_work (&mce_work); 
-#else
-	mce_checkregs (NULL);
 #endif
 	mce_timer.expires = jiffies + MCE_RATE;
 	add_timer (&mce_timer);
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Wed Nov 27 14:36:28 2002
+++ b/arch/i386/kernel/entry.S	Wed Nov 27 14:36:28 2002
@@ -707,7 +707,7 @@
 	.long sys_getdents64	/* 220 */
 	.long sys_fcntl64
 	.long sys_ni_syscall	/* reserved for TUX */
-	.long sys_security	/* reserved for Security */
+	.long sys_ni_syscall
 	.long sys_gettid
 	.long sys_readahead	/* 225 */
 	.long sys_setxattr
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Wed Nov 27 14:36:28 2002
+++ b/arch/i386/kernel/io_apic.c	Wed Nov 27 14:36:28 2002
@@ -44,6 +44,12 @@
 static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
 
 /*
+ *	Is the SiS APIC rmw bug present ?
+ *	-1 = dont know, 0 = no, 1 = yes
+ */
+int sis_apic_bug = -1;
+
+/*
  * # of IRQ routing registers
  */
 int nr_ioapic_registers[MAX_IO_APICS];
@@ -122,7 +128,7 @@
 			break;						\
 		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
 		reg ACTION;						\
-		io_apic_modify(entry->apic, reg);			\
+		io_apic_modify(entry->apic, 0x10 + R + pin*2, reg);	\
 		if (!entry->next)					\
 			break;						\
 		entry = irq_2_pin + entry->next;			\
@@ -1738,6 +1744,18 @@
 	print_IO_APIC();
 }
 
+/*
+ *	Called after all the initialization is done. If we didnt find any
+ *	APIC bugs then we can allow the modify fast path
+ */
+ 
+static void __init io_apic_bug_finalize(void)
+{
+	if(sis_apic_bug == -1)
+		sis_apic_bug = 0;
+}
+
+late_initcall(io_apic_bug_finalize);
 
 /* --------------------------------------------------------------------------
                           ACPI-based IOAPIC Configuration
diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
+++ b/arch/i386/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
@@ -160,8 +160,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
--- a/arch/i386/kernel/semaphore.c	Wed Nov 27 14:36:29 2002
+++ b/arch/i386/kernel/semaphore.c	Wed Nov 27 14:36:29 2002
@@ -191,6 +191,10 @@
 ".align 4\n"
 ".globl __down_failed\n"
 "__down_failed:\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"pushl %ebp\n\t"
+	"movl  %esp,%ebp\n\t"
+#endif
 	"pushl %eax\n\t"
 	"pushl %edx\n\t"
 	"pushl %ecx\n\t"
@@ -198,6 +202,10 @@
 	"popl %ecx\n\t"
 	"popl %edx\n\t"
 	"popl %eax\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"movl %ebp,%esp\n\t"
+	"popl %ebp\n\t"
+#endif
 	"ret"
 );
 
@@ -206,11 +214,19 @@
 ".align 4\n"
 ".globl __down_failed_interruptible\n"
 "__down_failed_interruptible:\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"pushl %ebp\n\t"
+	"movl  %esp,%ebp\n\t"
+#endif
 	"pushl %edx\n\t"
 	"pushl %ecx\n\t"
 	"call __down_interruptible\n\t"
 	"popl %ecx\n\t"
 	"popl %edx\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"movl %ebp,%esp\n\t"
+	"popl %ebp\n\t"
+#endif
 	"ret"
 );
 
@@ -219,11 +235,19 @@
 ".align 4\n"
 ".globl __down_failed_trylock\n"
 "__down_failed_trylock:\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"pushl %ebp\n\t"
+	"movl  %esp,%ebp\n\t"
+#endif
 	"pushl %edx\n\t"
 	"pushl %ecx\n\t"
 	"call __down_trylock\n\t"
 	"popl %ecx\n\t"
 	"popl %edx\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"movl %ebp,%esp\n\t"
+	"popl %ebp\n\t"
+#endif
 	"ret"
 );
 
diff -Nru a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
--- a/arch/i386/pci/direct.c	Wed Nov 27 14:36:28 2002
+++ b/arch/i386/pci/direct.c	Wed Nov 27 14:36:28 2002
@@ -261,7 +261,6 @@
 	}
 
 	local_irq_restore(flags);
-	pci_root_ops = NULL;
 	return 0;
 }
 
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Wed Nov 27 14:36:28 2002
+++ b/arch/ia64/kernel/entry.S	Wed Nov 27 14:36:28 2002
@@ -1241,7 +1241,7 @@
 	data8 sys_futex				// 1230
 	data8 sys_sched_setaffinity
 	data8 sys_sched_getaffinity
-	data8 sys_security
+	data8 sys_ni_syscall
 	data8 sys_alloc_hugepages
 	data8 sys_free_hugepages		// 1235
 	data8 sys_exit_group
diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c	Wed Nov 27 14:36:32 2002
+++ b/arch/ia64/kernel/ptrace.c	Wed Nov 27 14:36:32 2002
@@ -1101,8 +1101,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		current->ptrace |= PT_PTRACED;
 		ret = 0;
diff -Nru a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
--- a/arch/m68k/lib/checksum.c	Wed Nov 27 14:36:32 2002
+++ b/arch/m68k/lib/checksum.c	Wed Nov 27 14:36:32 2002
@@ -243,7 +243,7 @@
 	     "8:\n"
 		".section .fixup,\"ax\"\n"
 		".even\n"
-		/* If any execption occurs zero out the rest.
+		/* If any exception occurs zero out the rest.
 		   Similarities with the code above are intentional :-) */
 	     "90:\t"
 		"clrw %3@+\n\t"
diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig
--- a/arch/mips64/Kconfig	Wed Nov 27 14:36:28 2002
+++ b/arch/mips64/Kconfig	Wed Nov 27 14:36:28 2002
@@ -693,7 +693,7 @@
 	  architecture than the one it is intended to run on.
 
 config MIPS_FPE_MODULE
-	bool "Build fp execption handler module"
+	bool "Build fp exception handler module"
 	depends on MODULES
 	help
 	  Build the floating point exception handler module. This option is
diff -Nru a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
--- a/arch/ppc/kernel/entry.S	Wed Nov 27 14:36:31 2002
+++ b/arch/ppc/kernel/entry.S	Wed Nov 27 14:36:31 2002
@@ -182,9 +182,7 @@
 	.globl	ret_from_fork
 ret_from_fork:
 	REST_NVGPRS(r1)
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 	bl	schedule_tail
-#endif
 	li	r3,0
 	b	ret_from_syscall
 
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	Wed Nov 27 14:36:31 2002
+++ b/arch/ppc/kernel/misc.S	Wed Nov 27 14:36:31 2002
@@ -1006,6 +1006,7 @@
 	mr	r31,r4		/* argument */
 	ori	r3,r5,CLONE_VM	/* flags */
 	oris	r3,r3,CLONE_UNTRACED>>16
+	li	r4,0		/* new sp (unused) */
 	li	r0,__NR_clone
 	sc
 	cmpi	0,r3,0		/* parent or child? */
@@ -1279,7 +1280,7 @@
 	.long sys_futex
 	.long sys_sched_setaffinity
 	.long sys_sched_getaffinity
-	.long sys_security
+	.long sys_ni_syscall
 	.long sys_ni_syscall	/* 225 - reserved for Tux */
 	.long sys_sendfile64
 	.long sys_io_setup
diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
--- a/arch/ppc/kernel/process.c	Wed Nov 27 14:36:30 2002
+++ b/arch/ppc/kernel/process.c	Wed Nov 27 14:36:30 2002
@@ -332,7 +332,7 @@
 	unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
 	unsigned long childframe;
 
-	p->user_tid = NULL;
+	p->set_child_tid = p->clear_child_tid = NULL;
 
 	CHECK_FULL_REGS(regs);
 	/* Copy registers */
@@ -344,8 +344,10 @@
 		childregs->gpr[1] = sp + sizeof(struct pt_regs);
 		childregs->gpr[2] = (unsigned long) p;
 		p->thread.regs = NULL;	/* no user register state */
-	} else
+	} else {
+		childregs->gpr[1] = usp;
 		p->thread.regs = childregs;
+	}
 	childregs->gpr[3] = 0;  /* Result from fork() */
 	sp -= STACK_FRAME_OVERHEAD;
 	childframe = sp;
@@ -449,9 +451,9 @@
  	struct task_struct *p;
 
 	CHECK_FULL_REGS(regs);
-	if ((p1 & (CLONE_SETTID | CLONE_CLEARTID)) == 0)
-		p3 = 0;
- 	p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3);
+	if (p2 == 0)
+		p2 = regs->gpr[1];	/* stack pointer for child */
+ 	p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3, (int *)p4);
  	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -460,7 +462,7 @@
 {
 	struct task_struct *p;
 	CHECK_FULL_REGS(regs);
-	p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL);
+	p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -469,7 +471,8 @@
 {
 	struct task_struct *p;
 	CHECK_FULL_REGS(regs);
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL);
+	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs,
+		    0, NULL, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
diff -Nru a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
--- a/arch/ppc/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
+++ b/arch/ppc/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
@@ -166,8 +166,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Wed Nov 27 14:36:31 2002
+++ b/arch/ppc64/kernel/misc.S	Wed Nov 27 14:36:31 2002
@@ -730,7 +730,7 @@
 	.llong .sys_futex
 	.llong .sys32_sched_setaffinity
 	.llong .sys32_sched_getaffinity
-	.llong .sys_security
+	.llong .sys_ni_syscall
 	.llong .sys_ni_syscall		/* 225 - reserved for tux */
 	.llong .sys32_sendfile64
 	.llong .sys_ni_syscall		/* reserved for sys_io_setup */
@@ -973,7 +973,7 @@
 	.llong .sys_futex
 	.llong .sys_sched_setaffinity
 	.llong .sys_sched_getaffinity
-	.llong .sys_security
+	.llong .sys_ni_syscall
 	.llong .sys_ni_syscall		/* 225 - reserved for tux */
 	.llong .sys_ni_syscall		/* 32bit only sendfile64 */
 	.llong .sys_io_setup
diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
--- a/arch/ppc64/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
+++ b/arch/ppc64/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
@@ -59,8 +59,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
--- a/arch/ppc64/kernel/ptrace32.c	Wed Nov 27 14:36:30 2002
+++ b/arch/ppc64/kernel/ptrace32.c	Wed Nov 27 14:36:30 2002
@@ -48,8 +48,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	Wed Nov 27 14:36:31 2002
+++ b/arch/ppc64/kernel/sys_ppc32.c	Wed Nov 27 14:36:31 2002
@@ -53,6 +53,7 @@
 #include <linux/mman.h>
 #include <linux/sysctl.h>
 #include <linux/binfmts.h>
+#include <linux/security.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
@@ -3520,8 +3521,7 @@
 	if ((retval = bprm.envc) < 0)
 		goto out_mm;
 
-	retval = security_ops->bprm_alloc_security(&bprm);
-	if (retval) 
+	if ((retval = security_bprm_alloc(&bprm)))
 		goto out;
 
 	retval = prepare_binprm(&bprm);
@@ -3544,7 +3544,7 @@
 	retval = search_binary_handler(&bprm,regs);
 	if (retval >= 0) {
 		/* execve success */
-		security_ops->bprm_free_security(&bprm);
+		security_bprm_free(&bprm);
 		return retval;
 	}
 
@@ -3557,7 +3557,7 @@
 	}
 
 	if (bprm.security)
-		security_ops->bprm_free_security(&bprm);
+		security_bprm_free(&bprm);
 
 out_mm:
 	mmdrop(bprm.mm);
diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
--- a/arch/s390/kernel/entry.S	Wed Nov 27 14:36:28 2002
+++ b/arch/s390/kernel/entry.S	Wed Nov 27 14:36:28 2002
@@ -588,7 +588,7 @@
 	.long  sys_futex
 	.long  sys_sched_setaffinity
 	.long  sys_sched_getaffinity	 /* 240 */
-	.long  sys_security
+	.long  sys_ni_syscall
 	.long  sys_ni_syscall		 /* reserved for TUX */
 	.long  sys_io_setup
 	.long  sys_io_destroy
diff -Nru a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
--- a/arch/s390/kernel/ptrace.c	Wed Nov 27 14:36:31 2002
+++ b/arch/s390/kernel/ptrace.c	Wed Nov 27 14:36:31 2002
@@ -323,8 +323,7 @@
 		ret = -EPERM;
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S
--- a/arch/s390x/kernel/entry.S	Wed Nov 27 14:36:28 2002
+++ b/arch/s390x/kernel/entry.S	Wed Nov 27 14:36:28 2002
@@ -617,7 +617,7 @@
 	.long  SYSCALL(sys_futex,sys32_futex_wrapper)
 	.long  SYSCALL(sys_sched_setaffinity,sys32_sched_setaffinity_wrapper)
 	.long  SYSCALL(sys_sched_getaffinity,sys32_sched_getaffinity_wrapper) /* 240 */
-	.long  SYSCALL(sys_security,sys_ni_syscall)
+	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
 	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* reserved for TUX */
 	.long  SYSCALL(sys_io_setup,sys_ni_syscall)
 	.long  SYSCALL(sys_io_destroy,sys_ni_syscall)
diff -Nru a/arch/s390x/kernel/ptrace.c b/arch/s390x/kernel/ptrace.c
--- a/arch/s390x/kernel/ptrace.c	Wed Nov 27 14:36:27 2002
+++ b/arch/s390x/kernel/ptrace.c	Wed Nov 27 14:36:27 2002
@@ -32,6 +32,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/security.h>
 
 #include <asm/segment.h>
 #include <asm/page.h>
@@ -562,8 +563,7 @@
 		ret = -EPERM;
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/arch/sh/kernel/hd64465_gpio.c b/arch/sh/kernel/hd64465_gpio.c
--- a/arch/sh/kernel/hd64465_gpio.c	Wed Nov 27 14:36:31 2002
+++ b/arch/sh/kernel/hd64465_gpio.c	Wed Nov 27 14:36:31 2002
@@ -165,12 +165,19 @@
 
 static int __init hd64465_gpio_init(void)
 {
-    	/* TODO: check return values */
-    	request_region(HD64465_REG_GPACR, 0x1000, MODNAME);
-	request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt,
-	    SA_INTERRUPT, MODNAME, 0);
+	int err;
+	
+	if (!request_region(HD64465_REG_GPACR, 0x1000, MODNAME))
+		return -EIO;
+	err = request_irq (HD64465_IRQ_GPIO, hd64465_gpio_interrupt,
+					SA_INTERRUPT, MODNAME, 0);
+	if (err) {
+		printk(KERN_ERR"HD64465: Unable to get irq %d.\n", HD64465_IRQ_GPIO);
+		release_region(HD64465_REG_GPACR, 0x1000);
+		return err;
+	}
 
-    	printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO);
+	printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO);
 	return 0;
 }
 
diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig
--- a/arch/sparc/Kconfig	Wed Nov 27 14:36:27 2002
+++ b/arch/sparc/Kconfig	Wed Nov 27 14:36:27 2002
@@ -1424,6 +1424,12 @@
 config DEBUG_SPINLOCK
 	bool "Spinlock debugging"
 
+config DEBUG_SPINLOCK_SLEEP
+	bool "Sleep-inside-spinlock checking"
+	help
+	  If you say Y here, various routines which may sleep will become very
+	  noisy if they are called with a spinlock held.	
+
 endmenu
 
 source "security/Kconfig"
diff -Nru a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
--- a/arch/sparc/kernel/ptrace.c	Wed Nov 27 14:36:32 2002
+++ b/arch/sparc/kernel/ptrace.c	Wed Nov 27 14:36:32 2002
@@ -291,8 +291,7 @@
 			pt_error_return(regs, EPERM);
 			goto out;
 		}
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret) {
+		if ((ret = security_ptrace(current->parent, current))) {
 			pt_error_return(regs, -ret);
 			goto out;
 		}
diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
--- a/arch/sparc/kernel/signal.c	Wed Nov 27 14:36:31 2002
+++ b/arch/sparc/kernel/signal.c	Wed Nov 27 14:36:31 2002
@@ -1135,7 +1135,7 @@
 			if (current->pid == 1)
 				continue;
 			switch (signr) {
-			case SIGCONT: case SIGCHLD: case SIGWINCH:
+			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
 				continue;
 
 			case SIGTSTP: case SIGTTIN: case SIGTTOU:
diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	Wed Nov 27 14:36:30 2002
+++ b/arch/sparc/kernel/systbls.S	Wed Nov 27 14:36:30 2002
@@ -49,7 +49,7 @@
 /*140*/	.long sys_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys_getrlimit
 /*145*/	.long sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
-/*155*/	.long sys_fcntl64, sys_security, sys_statfs, sys_fstatfs, sys_oldumount
+/*155*/	.long sys_fcntl64, sys_ni_syscall, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/	.long sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
 /*165*/	.long sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr
 /*170*/	.long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
--- a/arch/sparc64/Kconfig	Wed Nov 27 14:36:31 2002
+++ b/arch/sparc64/Kconfig	Wed Nov 27 14:36:31 2002
@@ -1681,6 +1681,12 @@
 	  best used in conjunction with the NMI watchdog so that spinlock
 	  deadlocks are also debuggable.
 
+config DEBUG_SPINLOCK_SLEEP
+	bool "Sleep-inside-spinlock checking"
+	help
+	  If you say Y here, various routines which may sleep will become very
+	  noisy if they are called with a spinlock held.	
+
 config DEBUG_BUGVERBOSE
 	bool "Verbose BUG() reporting (adds 70K)"
 	depends on DEBUG_KERNEL
diff -Nru a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
--- a/arch/sparc64/kernel/binfmt_elf32.c	Wed Nov 27 14:36:31 2002
+++ b/arch/sparc64/kernel/binfmt_elf32.c	Wed Nov 27 14:36:31 2002
@@ -32,12 +32,10 @@
 	for(i = 0; i < 16; i++)				\
 		dest[i] = (unsigned int) src->u_regs[i];\
 	/* Don't try this at home kids... */		\
-	set_fs(USER_DS);				\
 	sp = (unsigned int *) (src->u_regs[14] &	\
 		0x00000000fffffffc);			\
 	for(i = 0; i < 16; i++)				\
 		__get_user(dest[i+16], &sp[i]);		\
-	set_fs(KERNEL_DS);				\
 	dest[32] = tstate_to_psr(src->tstate);		\
 	dest[33] = (unsigned int) src->tpc;		\
 	dest[34] = (unsigned int) src->tnpc;		\
diff -Nru a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
--- a/arch/sparc64/kernel/ptrace.c	Wed Nov 27 14:36:32 2002
+++ b/arch/sparc64/kernel/ptrace.c	Wed Nov 27 14:36:32 2002
@@ -140,8 +140,7 @@
 			pt_error_return(regs, EPERM);
 			goto out;
 		}
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret) {
+		if ((ret = security_ptrace(current->parent, current))) {
 			pt_error_return(regs, -ret);
 			goto out;
 		}
diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
--- a/arch/sparc64/kernel/signal.c	Wed Nov 27 14:36:30 2002
+++ b/arch/sparc64/kernel/signal.c	Wed Nov 27 14:36:30 2002
@@ -682,7 +682,7 @@
 			if (current->pid == 1)
 				continue;
 			switch (signr) {
-			case SIGCONT: case SIGCHLD: case SIGWINCH:
+			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
 				continue;
 
 			case SIGTSTP: case SIGTTIN: case SIGTTOU:
diff -Nru a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
--- a/arch/sparc64/kernel/signal32.c	Wed Nov 27 14:36:27 2002
+++ b/arch/sparc64/kernel/signal32.c	Wed Nov 27 14:36:27 2002
@@ -1353,7 +1353,7 @@
 			if (current->pid == 1)
 				continue;
 			switch (signr) {
-			case SIGCONT: case SIGCHLD: case SIGWINCH:
+			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
 				continue;
 
 			case SIGTSTP: case SIGTTIN: case SIGTTOU:
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Wed Nov 27 14:36:31 2002
+++ b/arch/sparc64/kernel/sys_sparc32.c	Wed Nov 27 14:36:31 2002
@@ -3026,8 +3026,7 @@
 	if ((retval = bprm.envc) < 0)
 		goto out_mm;
 
-	retval = security_ops->bprm_alloc_security(&bprm);
-	if (retval) 
+	if ((retval = security_bprm_alloc(&bprm)))
 		goto out;
 
 	retval = prepare_binprm(&bprm);
@@ -3050,7 +3049,7 @@
 	retval = search_binary_handler(&bprm, regs);
 	if (retval >= 0) {
 		/* execve success */
-		security_ops->bprm_free_security(&bprm);
+		security_bprm_free(&bprm);
 		return retval;
 	}
 
@@ -3063,7 +3062,7 @@
 	}
 
 	if (bprm.security)
-		security_ops->bprm_free_security(&bprm);
+		security_bprm_free(&bprm);
 
 out_mm:
 	mmdrop(bprm.mm);
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Wed Nov 27 14:36:30 2002
+++ b/arch/sparc64/kernel/systbls.S	Wed Nov 27 14:36:30 2002
@@ -50,7 +50,7 @@
 /*140*/	.word sys32_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys32_getrlimit
 	.word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
 /*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
-	.word sys32_fcntl64, sys_security, sys32_statfs, sys32_fstatfs, sys_oldumount
+	.word sys32_fcntl64, sys_ni_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
 /*160*/	.word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
 	.word sys_quotactl, sys_set_tid_address, sys32_mount, sys_ustat, sys_setxattr
 /*170*/	.word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents
@@ -109,7 +109,7 @@
 /*140*/	.word sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit
 	.word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/	.word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
-	.word sys_nis_syscall, sys_security, sys_statfs, sys_fstatfs, sys_oldumount
+	.word sys_nis_syscall, sys_ni_syscall, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/	.word sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_utrap_install
 	.word sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr
 /*170*/	.word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
diff -Nru a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
--- a/arch/um/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
+++ b/arch/um/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
@@ -33,8 +33,7 @@
 		if (current->ptrace & PT_PTRACED)
 			goto out;
 
-		ret = security_ops->ptrace(current->parent, current);
-		if(ret)
+		if ((ret = security_ptrace(current->parent, current)))
  			goto out;
 
 		/* set the ptrace bit in the process flags. */
diff -Nru a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
--- a/arch/um/kernel/sys_call_table.c	Wed Nov 27 14:36:31 2002
+++ b/arch/um/kernel/sys_call_table.c	Wed Nov 27 14:36:31 2002
@@ -217,7 +217,6 @@
 extern syscall_handler_t sys_madvise;
 extern syscall_handler_t sys_fcntl64;
 extern syscall_handler_t sys_getdents64;
-extern syscall_handler_t sys_security;
 extern syscall_handler_t sys_gettid;
 extern syscall_handler_t sys_readahead;
 extern syscall_handler_t sys_tkill;
@@ -458,7 +457,6 @@
 	[ __NR_fstat64 ] = sys_fstat64,
 	[ __NR_fcntl64 ] = sys_fcntl64,
 	[ __NR_getdents64 ] = sys_getdents64,
-        [ __NR_security ] = sys_security,
 	[ __NR_gettid ] = sys_gettid,
 	[ __NR_readahead ] = sys_readahead,
 	[ __NR_setxattr ] = sys_ni_syscall,
diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig
--- a/arch/v850/Kconfig	Wed Nov 27 14:36:30 2002
+++ b/arch/v850/Kconfig	Wed Nov 27 14:36:30 2002
@@ -63,6 +63,8 @@
       	     bool "NA85E2C-FPGA"
       config V850E2_ANNA
       	     bool "Anna"
+      config V850E_AS85EP1
+      	     bool "AS85EP1"
    endchoice
 
 
diff -Nru a/arch/v850/Makefile b/arch/v850/Makefile
--- a/arch/v850/Makefile	Wed Nov 27 14:36:32 2002
+++ b/arch/v850/Makefile	Wed Nov 27 14:36:32 2002
@@ -22,6 +22,9 @@
 CFLAGS += -fno-builtin
 CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\"
 
+LDFLAGS_BLOB := -b binary --oformat elf32-little
+OBJCOPY_FLAGS_BLOB := -I binary -O elf32-little -B v850e
+
 
 HEAD := $(arch_dir)/kernel/head.o $(arch_dir)/kernel/init_task.o
 core-y += $(arch_dir)/kernel/
@@ -40,10 +43,8 @@
 # This results in it being built anew each time, but that's alright.
 root_fs_image.o: root_fs_image_force
 
-# Note that we use the build-system's objcopy, as the v850 tools are fairly
-# old, and don't have the --rename-section option.
 root_fs_image_force: $(ROOT_FS_IMAGE)
-	objcopy -I binary -O elf32-little -B i386 --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o
+	$(OBJCOPY) $(OBJCOPY_FLAGS_BLOB) --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o
 endif
 
 
diff -Nru a/arch/v850/anna-rom.ld b/arch/v850/anna-rom.ld
--- a/arch/v850/anna-rom.ld	Wed Nov 27 14:36:28 2002
+++ b/arch/v850/anna-rom.ld	Wed Nov 27 14:36:28 2002
@@ -80,6 +80,11 @@
 		__root_fs_image_start = . ;
 		*(.root)
 		__root_fs_image_end = . ;
+
+		. = ALIGN (4) ;
+		___initramfs_start = . ;
+			*(.init.ramfs)
+		___initramfs_end = . ;
 	} > ROM
 
 	__rom_copy_src_start = . ;
diff -Nru a/arch/v850/anna.ld b/arch/v850/anna.ld
--- a/arch/v850/anna.ld	Wed Nov 27 14:36:29 2002
+++ b/arch/v850/anna.ld	Wed Nov 27 14:36:29 2002
@@ -103,6 +103,12 @@
 			*(.initcall7.init)
 		. = ALIGN (4) ;
 		___initcall_end = . ;
+
+		. = ALIGN (4) ;
+		___initramfs_start = . ;
+			*(.init.ramfs)
+		___initramfs_end = . ;
+
 		__init_end = . ;
 
 		__kram_end = . ;
diff -Nru a/arch/v850/as85ep1.ld b/arch/v850/as85ep1.ld
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/as85ep1.ld	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,147 @@
+/* Linker script for the NEC AS85EP1 V850E evaluation board
+   (CONFIG_V850E_AS85EP1).  */
+
+/* Note, all symbols are prefixed with an extra `_' for compatibility with
+   the existing linux sources.  */
+
+_jiffies = _jiffies_64 ;
+
+MEMORY {
+       /* 1MB of internal memory ($BFbB"L?Na(BRAM).  */
+       iMEM0 : ORIGIN = 0,	    LENGTH = 0x00100000
+
+       /* 1MB of static RAM.  */
+       SRAM  : ORIGIN = 0x00400000, LENGTH = 0x00100000
+
+       /* About 58MB of DRAM.  This can actually be at one of two positions,
+	  determined by jump JP3; we have to use the first position because the
+	  second is partially out of processor instruction addressing range
+	  (though in the second position there's actually 64MB available).  */
+       SDRAM : ORIGIN = 0x00600000, LENGTH = 0x039F8000
+}
+
+SECTIONS {
+	.resetv : {
+		__intv_start = . ;
+			*(.intv.reset)	/* Reset vector */
+	} > iMEM0
+
+	.text : {
+		 __kram_start = . ;
+
+		__stext = . ;
+        	*(.text)
+			*(.exit.text)	/* 2.5 convention */
+			*(.text.exit)	/* 2.4 convention */
+			*(.text.lock)
+			*(.exitcall.exit)
+		__real_etext = . ;	/* There may be data after here.  */
+			*(.rodata)
+
+		. = ALIGN (0x4) ;
+			*(.kstrtab)
+
+		. = ALIGN (4) ;
+		    	*(.call_table_data)
+			*(.call_table_text)
+
+		. = ALIGN (16) ;	/* Exception table.  */
+		___start___ex_table = . ;
+			*(__ex_table)
+		___stop___ex_table = . ;
+
+		___start___ksymtab = . ;/* Kernel symbol table.  */
+			*(__ksymtab)
+		___stop___ksymtab = . ;
+		. = ALIGN (4) ;
+		__etext = . ;
+	} > SRAM
+
+	.data ALIGN (0x4) : {
+		__sdata = . ;
+		___data_start = . ;
+        	*(.data)
+			*(.exit.data)	/* 2.5 convention */
+			*(.data.exit)	/* 2.4 convention */
+		. = ALIGN (16) ;
+		*(.data.cacheline_aligned)
+		. = ALIGN (0x2000) ;
+        	*(.data.init_task)
+		. = ALIGN (0x2000) ;
+		__edata = . ;
+	} > SRAM
+
+	.bss ALIGN (0x4) : {
+		__sbss = . ;
+			*(.bss)
+			*(COMMON)
+		. = ALIGN (4) ;
+		__init_stack_end = . ;
+		__ebss = . ;
+	} > SRAM
+
+	.init ALIGN (4096) : {
+		__init_start = . ;
+			*(.init.text)	/* 2.5 convention */
+			*(.init.data)
+			*(.text.init)	/* 2.4 convention */
+			*(.data.init)
+		. = ALIGN (16) ;
+		___setup_start = . ;
+			*(.init.setup)	/* 2.5 convention */
+			*(.setup.init)	/* 2.4 convention */
+		___setup_end = . ;
+		___initcall_start = . ;
+			*(.initcall.init)
+			*(.initcall1.init)
+			*(.initcall2.init)
+			*(.initcall3.init)
+			*(.initcall4.init)
+			*(.initcall5.init)
+			*(.initcall6.init)
+			*(.initcall7.init)
+		. = ALIGN (4) ;
+		___initcall_end = . ;
+
+		. = ALIGN (4) ;
+		___initramfs_start = . ;
+			*(.init.ramfs)
+		___initramfs_end = . ;
+
+		/* We stick most of the interrupt vectors here; they'll be
+		   copied into the proper location by the early init code (we
+		   can't put them directly in the right place because of
+		   hardware bugs).  The vectors shouldn't need to be
+		   relocated, so we don't have to use `> ...  AT> ...' to
+		   split the load/vm addresses (and we can't because of
+		   problems with the loader).  */
+		. = ALIGN (0x10) ;
+		__intv_copy_src_start = . ;
+			*(.intv.common)	/* Vectors common to all v850e proc. */
+			*(.intv.mach)	/* Machine-specific int. vectors.  */
+		. = ALIGN (0x10) ;
+		__intv_copy_src_end = . ;
+
+		/* This is here so that when we free init memory, the initial
+		   load-area of the interrupt vectors is freed too.  */
+		__init_end = . ;
+		__kram_end = . ;
+		   
+		__bootmap = . ;
+		. = . + 4096 ;		/* enough for 128MB.   */
+	} > SRAM
+
+	/* Where we end up putting the vectors.  */
+	__intv_copy_dst_start = 0x10 ;
+	__intv_copy_dst_end = __intv_copy_dst_start + (__intv_copy_src_end - __intv_copy_src_start) ;
+
+	__intv_end = __intv_copy_dst_end ;
+
+	/* Device contents for the root filesystem.  */
+	.root : {
+		. = ALIGN (4096) ;
+		__root_fs_image_start = . ;
+		*(.root)
+		__root_fs_image_end = . ;
+	} > SDRAM
+}
diff -Nru a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
--- a/arch/v850/kernel/Makefile	Wed Nov 27 14:36:32 2002
+++ b/arch/v850/kernel/Makefile	Wed Nov 27 14:36:32 2002
@@ -15,11 +15,12 @@
 	 signal.o irq.o mach.o ptrace.o bug.o
 export-objs += v850_ksyms.o rte_mb_a_pci.o
 
-obj-$(CONFIG_MODULES)		+= v850_ksyms.o
+obj-$(CONFIG_MODULES)		+= module.o v850_ksyms.o
 # chip-specific code
 obj-$(CONFIG_V850E_MA1)		+= ma.o	nb85e_utils.o nb85e_timer_d.o
 obj-$(CONFIG_V850E_NB85E)	+= nb85e_intc.o
 obj-$(CONFIG_V850E2_ANNA)	+= anna.o nb85e_intc.o nb85e_utils.o nb85e_timer_d.o
+obj-$(CONFIG_V850E_AS85EP1)	+= as85ep1.o nb85e_intc.o nb85e_utils.o nb85e_timer_d.o
 # platform-specific code
 obj-$(CONFIG_V850E_SIM)		+= sim.o simcons.o
 obj-$(CONFIG_V850E2_SIM85E2C)	+= sim85e2c.o nb85e_intc.o memcons.o
diff -Nru a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c
--- a/arch/v850/kernel/anna.c	Wed Nov 27 14:36:30 2002
+++ b/arch/v850/kernel/anna.c	Wed Nov 27 14:36:30 2002
@@ -27,11 +27,14 @@
 #include "mach.h"
 
 
-/* SRAM and SDRAM are vaguely contiguous (with a hole in between; see
-   mach_reserve_bootmem for details), so just use both as one big area.  */
+/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
+   mach_reserve_bootmem for details); use both as one big area.  */
 #define RAM_START 	SRAM_ADDR
 #define RAM_END		(SDRAM_ADDR + SDRAM_SIZE)
 
+/* The bits of this port are connected to an 8-LED bar-graph.  */
+#define LEDS_PORT	0
+
 
 static void anna_led_tick (void);
 
@@ -44,7 +47,7 @@
 	ANNA_BPC    = 0;
 	ANNA_BSC    = 0xAAAA;
 	ANNA_BEC    = 0;
-	ANNA_BHC    = 0x00FF;	/* icache all memory, dcache none */
+	ANNA_BHC    = 0xFFFF;	/* icache all memory, dcache all */
 	ANNA_BCT(0) = 0xB088;
 	ANNA_BCT(1) = 0x0008;
 	ANNA_DWC(0) = 0x0027;
@@ -60,17 +63,11 @@
 
 void __init mach_setup (char **cmdline)
 {
-	printk (KERN_INFO
-		"CPU: %s\n"
-		"Platform: %s\n",
-		CPU_MODEL_LONG,
-		PLATFORM_LONG);
-
 #ifdef CONFIG_V850E_NB85E_UART_CONSOLE
 	nb85e_uart_cons_init (1);
 #endif
 
-	ANNA_PORT_PM (0) = 0;	/* Make all LED pins output pins.  */
+	ANNA_PORT_PM (LEDS_PORT) = 0;	/* Make all LED pins output pins.  */
 	mach_tick = anna_led_tick;
 }
 
@@ -138,7 +135,7 @@
 	disable_reset_guard ();
 #endif
 	local_irq_disable ();	/* Ignore all interrupts.  */
-	ANNA_PORT_IO(0) = 0xAA;	/* Note that we halted.  */
+	ANNA_PORT_IO(LEDS_PORT) = 0xAA;	/* Note that we halted.  */
 	for (;;)
 		asm ("halt; nop; nop; nop; nop; nop");
 }
@@ -191,9 +188,9 @@
 
 			if (pos + dir <= max_pos) {
 				/* Each bit of port 0 has a LED. */
-				clear_bit (pos, &ANNA_PORT_IO(0));
+				clear_bit (pos, &ANNA_PORT_IO(LEDS_PORT));
 				pos += dir;
-				set_bit (pos, &ANNA_PORT_IO(0));
+				set_bit (pos, &ANNA_PORT_IO(LEDS_PORT));
 			}
 		}
 
diff -Nru a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/as85ep1.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,241 @@
+/*
+ * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board
+ *
+ *  Copyright (C) 2002  NEC Corporation
+ *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/major.h>
+#include <linux/irq.h>
+
+#include <asm/machdep.h>
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <asm/nb85e_timer_d.h>
+#include <asm/nb85e_uart.h>
+
+#include "mach.h"
+
+
+/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
+   mach_reserve_bootmem for details); use both as one big area.  */
+#define RAM_START 	SRAM_ADDR
+#define RAM_END		(SDRAM_ADDR + SDRAM_SIZE)
+
+/* The bits of this port are connected to an 8-LED bar-graph.  */
+#define LEDS_PORT	4
+
+
+static void as85ep1_led_tick (void);
+
+extern char _intv_copy_src_start, _intv_copy_src_end;
+extern char _intv_copy_dst_start;
+
+
+void __init mach_early_init (void)
+{
+	const u32 *src;
+	register u32 *dst asm ("ep");
+
+	AS85EP1_CSC(0) = 0x0403;
+	AS85EP1_BCT(0) = 0xB8B8;
+	AS85EP1_DWC(0) = 0x0104;
+	AS85EP1_BCC    = 0x0012;
+	AS85EP1_ASC    = 0;
+	AS85EP1_LBS    = 0x00A9;
+	AS85EP1_RFS(1) = 0x8205;
+	AS85EP1_RFS(3) = 0x8205;
+	AS85EP1_SCR(1) = 0x20A9;
+	AS85EP1_SCR(3) = 0x20A9;
+
+	AS85EP1_PORT_PMC(6)  = 0xFF; /* A20-25, A0,A1 $BM-8z(B */
+	AS85EP1_PORT_PMC(7)  = 0x0E; /* CS1,2,3       $BM-8z(B */
+	AS85EP1_PORT_PMC(9)  = 0xFF; /* D16-23        $BM-8z(B */
+	AS85EP1_PORT_PMC(10) = 0xFF; /* D24-31        $BM-8z(B */
+
+	AS85EP1_IRAMM = 0x3;	/* $BFbB"L?Na(BRAM$B$O!V(Bwrite-mode$B!W$K$J$j$^$9(B */
+
+	/* The early chip we have is buggy, so that writing the interrupt
+	   vectors into low RAM may screw up, so for non-ROM kernels, we
+	   only rely on the reset vector being downloaded, and copy the
+	   rest of the interrupt vectors into place here.  The specific bug
+	   is that writing address N, where (N & 0x10) == 0x10, will _also_
+	   write to address (N - 0x10).  We avoid this (effectively) by
+	   writing in 16-byte chunks backwards from the end.  */
+	src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF);
+	dst = (u32 *)&_intv_copy_dst_start
+		+ (src - (u32 *)&_intv_copy_src_start);
+	do {
+		u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
+		dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
+		dst -= 4;
+		src -= 4;
+	} while (src > (u32 *)&_intv_copy_src_start);
+
+	AS85EP1_IRAMM = 0x0;	/* $BFbB"L?Na(BRAM$B$O!V(Bread-mode$B!W$K$J$j$^$9(B */
+
+	nb85e_intc_disable_irqs ();
+}
+
+void __init mach_setup (char **cmdline)
+{
+#ifdef CONFIG_V850E_NB85E_UART_CONSOLE
+	nb85e_uart_cons_init (1);
+#endif
+
+	AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */
+	AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins.  */
+	mach_tick = as85ep1_led_tick;
+
+	ROOT_DEV = MKDEV (BLKMEM_MAJOR, 0);
+}
+
+void __init mach_get_physical_ram (unsigned long *ram_start,
+				   unsigned long *ram_len)
+{
+	*ram_start = RAM_START;
+	*ram_len = RAM_END - RAM_START;
+}
+
+void __init mach_reserve_bootmem ()
+{
+	extern char _root_fs_image_start, _root_fs_image_end;
+	u32 root_fs_image_start = (u32)&_root_fs_image_start;
+	u32 root_fs_image_end = (u32)&_root_fs_image_end;
+
+	/* We can't use the space between SRAM and SDRAM, so prevent the
+	   kernel from trying.  */
+	reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
+			 SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE));
+
+	/* Reserve the memory used by the root filesystem image if it's
+	   in RAM.  */
+	if (root_fs_image_end > root_fs_image_start
+	    && root_fs_image_start >= RAM_START
+	    && root_fs_image_start < RAM_END)
+		reserve_bootmem (root_fs_image_start,
+				 root_fs_image_end - root_fs_image_start);
+}
+
+void mach_gettimeofday (struct timeval *tv)
+{
+	tv->tv_sec = 0;
+	tv->tv_usec = 0;
+}
+
+void __init mach_sched_init (struct irqaction *timer_action)
+{
+	/* Start hardware timer.  */
+	nb85e_timer_d_configure (0, HZ);
+	/* Install timer interrupt handler.  */
+	setup_irq (IRQ_INTCMD(0), timer_action);
+}
+
+static struct nb85e_intc_irq_init irq_inits[] = {
+	{ "IRQ", 0, 		NUM_MACH_IRQS,	1, 7 },
+	{ "CCC", IRQ_INTCCC(0),	IRQ_INTCCC_NUM, 1, 5 },
+	{ "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM,	1, 5 },
+	{ "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM,	3, 3 },
+	{ "SR",	 IRQ_INTSR(0),	IRQ_INTSR_NUM, 	3, 4 },
+	{ "ST",  IRQ_INTST(0), 	IRQ_INTST_NUM, 	3, 5 },
+	{ 0 }
+};
+#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
+
+static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
+
+void __init mach_init_irqs (void)
+{
+	nb85e_intc_init_irq_types (irq_inits, hw_itypes);
+}
+
+void machine_restart (char *__unused)
+{
+#ifdef CONFIG_RESET_GUARD
+	disable_reset_guard ();
+#endif
+	asm ("jmp r0"); /* Jump to the reset vector.  */
+}
+
+void machine_halt (void)
+{
+#ifdef CONFIG_RESET_GUARD
+	disable_reset_guard ();
+#endif
+	local_irq_disable ();	/* Ignore all interrupts.  */
+	AS85EP1_PORT_IO (LEDS_PORT) = 0xAA;	/* Note that we halted.  */
+	for (;;)
+		asm ("halt; nop; nop; nop; nop; nop");
+}
+
+void machine_power_off (void)
+{
+	machine_halt ();
+}
+
+/* Called before configuring an on-chip UART.  */
+void as85ep1_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
+{
+	/* Make the shared uart/port pins be uart pins.  */
+	AS85EP1_PORT_PMC(3) |= (0x5 << chan);
+
+	/* The AS85EP1 connects some general-purpose I/O pins on the CPU to
+	   the RTS/CTS lines of UART 1's serial connection.  I/O pins P53
+	   and P54 are RTS and CTS respectively.  */
+	if (chan == 1) {
+		/* Put P53 & P54 in I/O port mode.  */
+		AS85EP1_PORT_PMC(5) &= ~0x18;
+		/* Make P53 an output, and P54 an input.  */
+		AS85EP1_PORT_PM(5) |=  0x10;
+	}
+}
+
+/* Minimum and maximum bounds for the moving upper LED boundary in the
+   clock tick display.  */
+#define MIN_MAX_POS 0
+#define MAX_MAX_POS 7
+
+/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
+   we pick 6 and 0 as above, we get 49 cycles, which is when divided into
+   the standard 100 value for HZ, gives us an almost 1s total time.  */
+#define TICKS_PER_FRAME \
+	(HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
+
+static void as85ep1_led_tick ()
+{
+	static unsigned counter = 0;
+	
+	if (++counter == TICKS_PER_FRAME) {
+		static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
+
+		if (dir > 0 && pos == max_pos) {
+			dir = -1;
+			if (max_pos == MIN_MAX_POS)
+				max_pos = MAX_MAX_POS;
+			else
+				max_pos--;
+		} else {
+			if (dir < 0 && pos == 0)
+				dir = 1;
+
+			if (pos + dir <= max_pos) {
+				/* Each bit of port 0 has a LED. */
+				set_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
+				pos += dir;
+				clear_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
+			}
+		}
+
+		counter = 0;
+	}
+}
diff -Nru a/arch/v850/kernel/bug.c b/arch/v850/kernel/bug.c
--- a/arch/v850/kernel/bug.c	Wed Nov 27 14:36:31 2002
+++ b/arch/v850/kernel/bug.c	Wed Nov 27 14:36:31 2002
@@ -60,3 +60,76 @@
 	machine_halt ();
 }
 #endif /* CONFIG_RESET_GUARD */
+
+
+
+struct spec_reg_name {
+	const char *name;
+	int gpr;
+};
+
+struct spec_reg_name spec_reg_names[] = {
+	{ "sp", GPR_SP },
+	{ "gp", GPR_GP },
+	{ "tp", GPR_TP },
+	{ "ep", GPR_EP },
+	{ "lp", GPR_LP },
+	{ 0, 0 }
+};
+
+void show_regs (struct pt_regs *regs)
+{
+	int gpr_base, gpr_offs;
+
+	printk ("     pc 0x%08lx    psw 0x%08lx                       kernel_mode %d\n",
+		regs->pc, regs->psw, regs->kernel_mode);
+	printk ("   ctpc 0x%08lx  ctpsw 0x%08lx   ctbp 0x%08lx\n",
+		regs->ctpc, regs->ctpsw, regs->ctbp);
+
+	for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) {
+		for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) {
+			int gpr = gpr_base + gpr_offs;
+			long val = regs->gpr[gpr];
+			struct spec_reg_name *srn;
+
+			for (srn = spec_reg_names; srn->name; srn++)
+				if (srn->gpr == gpr)
+					break;
+
+			if (srn->name)
+				printk ("%7s 0x%08lx", srn->name, val);
+			else
+				printk ("    r%02d 0x%08lx", gpr, val);
+		}
+
+		printk ("\n");
+	}
+}
+
+void show_stack (unsigned long *sp)
+{
+	unsigned long end;
+	unsigned long addr = (unsigned long)sp;
+
+	if (! addr)
+		addr = stack_addr ();
+
+	addr = addr & ~3;
+	end = (addr + THREAD_SIZE - 1) & THREAD_MASK;
+
+	while (addr < end) {
+		printk ("%8lX: ", addr);
+		while (addr < end) {
+			printk (" %8lX", *(unsigned long *)addr);
+			addr += sizeof (unsigned long);
+			if (! (addr & 0xF))
+				break;
+		}
+		printk ("\n");
+	}
+}
+
+void dump_stack ()
+{
+	show_stack (0);
+}
diff -Nru a/arch/v850/kernel/entry.S b/arch/v850/kernel/entry.S
--- a/arch/v850/kernel/entry.S	Wed Nov 27 14:36:31 2002
+++ b/arch/v850/kernel/entry.S	Wed Nov 27 14:36:31 2002
@@ -657,6 +657,12 @@
 	shl	16, r6			// clear upper 16 bits
 	shr	20, r6			// shift back, and remove lower nibble
 	add	-8, r6			// remove bias for irqs
+
+	// If the IRQ index is negative, it's actually one of the exception
+	// traps below 0x80 (currently, the illegal instruction trap, and
+	// the `debug trap').  Handle these separately.
+	bn	exception
+
 	// Call the high-level interrupt handling code.
 	jarl	CSYM(handle_irq), lp
 	// fall through
@@ -665,6 +671,23 @@
    handlers, below).  */
 ret_from_irq:
 	RETURN(IRQ)
+
+exception:
+	mov	hilo(ret_from_irq), lp	// where the handler should return
+	
+	cmp	-2, r6
+	bne	1f
+	// illegal instruction exception
+	addi	SIGILL, r0, r6		// Arg 0: signal number
+	mov	CURRENT_TASK, r7	// Arg 1: task
+	jr	CSYM(force_sig)		// tail call
+
+1:	cmp	-1, r6
+	bne	bad_trap_wrapper
+	// `dbtrap' exception
+	movea	PTO, sp, r6		// Arg 0: user regs
+	jr	CSYM(debug_trap)	// tail call
+
 END(irq)
 
 
@@ -692,44 +715,7 @@
 	jarl	CSYM(handle_irq), lp
 
 	RETURN(NMI)
-END(nmi0)
-
-
-/*
- * Illegal instruction trap.
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- */
-G_ENTRY(illegal_instruction):
-	SAVE_STATE (IRQ, r0, ENTRY_SP)	// Save registers. 
-	ei
-	addi	SIGILL, r0, r6		// Arg 0: signal number
-	mov	CURRENT_TASK, r7	// Arg 1: task
-	mov	hilo(ret_from_irq), lp	// where the handler should return
-	jr	CSYM(force_sig)
-END(illegal_instruction)
-
-
-/*
- * `Debug' trap
- *
- * The stack-pointer (r3) should have already been saved to the memory
- * location ENTRY_SP (the reason for this is that the interrupt vectors may be
- * beyond a 22-bit signed offset jump from the actual interrupt handler, and
- * this allows them to save the stack-pointer and use that register to do an
- * indirect jump).
- */
-G_ENTRY(dbtrap):
-	SAVE_STATE (IRQ, r0, ENTRY_SP)	// Save registers. 
-	ei
-	movea	PTO, sp, r6		// Arg 0: user regs
-	mov	hilo(ret_from_irq), lp	// where the handler should return
-	jr	CSYM(debug_trap)
-END(dbtrap)
+END(nmi)
 
 
 /*
@@ -771,8 +757,7 @@
 	.data
 
 	.align 4
-	.globl CSYM(trap_table)
-CSYM(trap_table):
+C_DATA(trap_table):
 	.long bad_trap_wrapper		// trap 0, doesn't use trap table. 
 	.long syscall_long		// trap 1, `long' syscall. 
 	.long bad_trap_wrapper
@@ -789,13 +774,13 @@
 	.long bad_trap_wrapper
 	.long bad_trap_wrapper
 	.long bad_trap_wrapper
+C_END(trap_table)
 
 
 	.section .rodata
 	
 	.align 4
-	.globl CSYM(sys_call_table)
-CSYM(sys_call_table):
+C_DATA(sys_call_table):
 	.long CSYM(sys_ni_syscall)	// 0  -  old "setup()" system call
 	.long CSYM(sys_exit)
 	.long sys_fork_wrapper
@@ -923,10 +908,10 @@
 	.long CSYM(sys_adjtimex)
 	.long CSYM(sys_ni_syscall)	// 125 - sys_mprotect
 	.long CSYM(sys_sigprocmask)
-	.long CSYM(sys_create_module)
+	.long CSYM(sys_ni_syscall)	// sys_create_module
 	.long CSYM(sys_init_module)
 	.long CSYM(sys_delete_module)
-	.long CSYM(sys_get_kernel_syms) // 130
+	.long CSYM(sys_ni_syscall)	// 130 - sys_get_kernel_syms
 	.long CSYM(sys_quotactl)
 	.long CSYM(sys_getpgid)
 	.long CSYM(sys_fchdir)
@@ -963,7 +948,7 @@
 	.long CSYM(sys_setresuid)
 	.long CSYM(sys_getresuid)	// 165
 	.long CSYM(sys_ni_syscall)	// for vm86
-	.long CSYM(sys_query_module)
+	.long CSYM(sys_ni_syscall)	// sys_query_module
 	.long CSYM(sys_poll)
 	.long CSYM(sys_nfsservctl)
 	.long CSYM(sys_setresgid)	// 170
@@ -1003,3 +988,4 @@
 	.long CSYM(sys_ni_syscall)	// sys_madvise
 
 	.space (NR_syscalls-205)*4
+C_END(sys_call_table)
diff -Nru a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c
--- a/arch/v850/kernel/fpga85e2c.c	Wed Nov 27 14:36:31 2002
+++ b/arch/v850/kernel/fpga85e2c.c	Wed Nov 27 14:36:31 2002
@@ -73,8 +73,6 @@
 
 void __init mach_setup (char **cmdline)
 {
-	printk (KERN_INFO "CPU: NEC V850E2 (NA85E2C FPGA implementation)\n");
-
 	memcons_setup ();
 
 	/* Setup up NMI0 to copy the registers to a known memory location.
diff -Nru a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c
--- a/arch/v850/kernel/gbus_int.c	Wed Nov 27 14:36:32 2002
+++ b/arch/v850/kernel/gbus_int.c	Wed Nov 27 14:36:32 2002
@@ -14,11 +14,10 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <linux/sched.h>	/* For some unfathomable reason,
-				   request_irq/free_irq are declared here.  */
+#include <linux/interrupt.h>
+#include <linux/signal.h>
 
 #include <asm/machdep.h>
-#include <asm/irq.h>
 
 
 /* The number of shared GINT interrupts. */
@@ -72,7 +71,7 @@
 }
 
 /* Disable all GBUS irqs.  */
-int gbus_int_disable_irqs ()
+void gbus_int_disable_irqs ()
 {
 	unsigned w, n;
 	for (w = 0; w < GBUS_INT_NUM_WORDS; w++)
@@ -183,7 +182,7 @@
 {
 	struct gbus_int_irq_init *init;
 	for (init = inits; init->name; init++) {
-		int i;
+		unsigned i;
 		struct hw_interrupt_type *hwit = hw_irq_types++;
 
 		hwit->typename = init->name;
@@ -200,7 +199,7 @@
 
 		/* Set the interrupt priorities.  */
 		for (i = 0; i < init->num; i++) {
-			int j;
+			unsigned j;
 			for (j = 0; j < NUM_USED_GINTS; j++)
 				if (used_gint[j].priority > init->priority)
 					break;
@@ -222,7 +221,7 @@
 
 /* GBUS interrupts themselves.  */
 
-__init struct gbus_int_irq_init gbus_irq_inits[] = {
+struct gbus_int_irq_init gbus_irq_inits[] __initdata = {
 	/* First set defaults.  */
 	{ "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6},
 	{ 0 }
@@ -236,7 +235,7 @@
 /* Initialize GBUS interrupts.  */
 void __init gbus_int_init_irqs (void)
 {
-	int i;
+	unsigned i;
 
 	/* First initialize the shared gint interrupts.  */
 	for (i = 0; i < NUM_USED_GINTS; i++) {
diff -Nru a/arch/v850/kernel/head.S b/arch/v850/kernel/head.S
--- a/arch/v850/kernel/head.S	Wed Nov 27 14:36:27 2002
+++ b/arch/v850/kernel/head.S	Wed Nov 27 14:36:27 2002
@@ -118,4 +118,4 @@
 	// Start Linux kernel.
 	mov	hilo(CSYM(machine_halt)), lp
 	jr	CSYM(start_kernel)
-END(start)
+C_END(start)
diff -Nru a/arch/v850/kernel/intv.S b/arch/v850/kernel/intv.S
--- a/arch/v850/kernel/intv.S	Wed Nov 27 14:36:30 2002
+++ b/arch/v850/kernel/intv.S	Wed Nov 27 14:36:30 2002
@@ -52,10 +52,10 @@
 	JUMP_TO_HANDLER (trap, ENTRY_SP)	// TRAP1n
 
 	.balign	0x10
-	JUMP_TO_HANDLER (illegal_instruction, ENTRY_SP) // illegal insn trap
+	JUMP_TO_HANDLER (irq, ENTRY_SP)		// illegal insn trap
 
 	.balign	0x10
-	JUMP_TO_HANDLER (dbtrap, ENTRY_SP)	// DBTRAP insn
+	JUMP_TO_HANDLER (irq, ENTRY_SP)		// DBTRAP insn
 
 
 	/* Hardware interrupt vectors.  */
diff -Nru a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
--- a/arch/v850/kernel/irq.c	Wed Nov 27 14:36:31 2002
+++ b/arch/v850/kernel/irq.c	Wed Nov 27 14:36:31 2002
@@ -252,7 +252,7 @@
 	unsigned int status;
 
 	irq_enter();
-	kstat.irqs[cpu][irq]++;
+	kstat_cpu(cpu).irqs[irq]++;
 	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
 	/*
diff -Nru a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/module.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,225 @@
+/*
+ * arch/v850/kernel/module.c -- Architecture-specific module functions
+ *
+ *  Copyright (C) 2002  NEC Corporation
+ *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001  Rusty Russell
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ *
+ * Derived in part from arch/ppc/kernel/module.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt , ...)
+#endif
+
+void *module_alloc (unsigned long size)
+{
+	return size == 0 ? 0 : vmalloc (size);
+}
+
+void module_free (struct module *mod, void *module_region)
+{
+	vfree (module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+int module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+		     struct module *mod)
+{
+	return 0;
+}
+
+/* Count how many different relocations (different symbol, different
+   addend) */
+static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
+{
+	unsigned int i, j, ret = 0;
+
+	/* Sure, this is order(n^2), but it's usually short, and not
+           time critical */
+	for (i = 0; i < num; i++) {
+		for (j = 0; j < i; j++) {
+			/* If this addend appeared before, it's
+                           already been counted */
+			if (ELF32_R_SYM(rela[i].r_info)
+			    == ELF32_R_SYM(rela[j].r_info)
+			    && rela[i].r_addend == rela[j].r_addend)
+				break;
+		}
+		if (j == i) ret++;
+	}
+	return ret;
+}
+
+/* Get the potential trampolines size required of the init and
+   non-init sections */
+static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
+				  const Elf32_Shdr *sechdrs,
+				  const char *secstrings,
+				  int is_init)
+{
+	unsigned long ret = 0;
+	unsigned i;
+
+	/* Everything marked ALLOC (this includes the exported
+           symbols) */
+	for (i = 1; i < hdr->e_shnum; i++) {
+		/* If it's called *.init*, and we're not init, we're
+                   not interested */
+		if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
+		    != is_init)
+			continue;
+
+		if (sechdrs[i].sh_type == SHT_RELA) {
+			DEBUGP("Found relocations in section %u\n", i);
+			DEBUGP("Ptr: %p.  Number: %u\n",
+			       (void *)hdr + sechdrs[i].sh_offset,
+			       sechdrs[i].sh_size / sizeof(Elf32_Rela));
+			ret += count_relocs((void *)hdr
+					     + sechdrs[i].sh_offset,
+					     sechdrs[i].sh_size
+					     / sizeof(Elf32_Rela))
+				* sizeof(struct v850_plt_entry);
+		}
+	}
+
+	return ret;
+}
+
+long module_core_size (const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs,
+		       const char *secstrings, struct module *mod)
+{
+	mod->arch.core_plt_offset = (mod->core_size + 3) & ~3;
+	return mod->core_size + get_plt_size (hdr, sechdrs, secstrings, 1);
+}
+
+long module_init_size (const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs,
+		       const char *secstrings, struct module *mod)
+{
+	mod->arch.init_plt_offset = (mod->init_size + 3) & ~3;
+	return mod->init_size + get_plt_size (hdr, sechdrs, secstrings, 1);
+}
+
+int apply_relocate (Elf32_Shdr *sechdrs, const char *strtab,
+		    unsigned int symindex, unsigned int relsec,
+		    struct module *mod)
+{
+	printk ("Barf\n");
+	return -ENOEXEC;
+}
+
+/* Set up a trampoline in the PLT to bounce us to the distant function */
+static uint32_t do_plt_call(void *location, Elf32_Addr val, struct module *mod)
+{
+	struct v850_plt_entry *entry;
+	/* Instructions used to do the indirect jump.  */
+	uint32_t tramp[2];
+
+	/* We have to trash a register, so we assume that any control
+	   transfer more than 21-bits away must be a function call
+	   (so we can use a call-clobbered register).  */
+	tramp[0] = 0x0621 + ((val & 0xffff) << 16);   /* mov sym, r1 ... */
+	tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
+
+	/* Init, or core PLT? */
+	if (location >= mod->module_core
+	    && location < mod->module_core + mod->arch.core_plt_offset)
+		entry = mod->module_core + mod->arch.core_plt_offset;
+	else
+		entry = mod->module_init + mod->arch.init_plt_offset;
+
+	/* Find this entry, or if that fails, the next avail. entry */
+	while (entry->tramp[0])
+		if (entry->tramp[0] == tramp[0] && entry->tramp[1] == tramp[1])
+			return (uint32_t)entry;
+		else
+			entry++;
+
+	entry->tramp[0] = tramp[0];
+	entry->tramp[1] = tramp[1];
+
+	return (uint32_t)entry;
+}
+
+int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab,
+			unsigned int symindex, unsigned int relsec,
+			struct module *mod)
+{
+	unsigned int i;
+	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_offset;
+
+	DEBUGP ("Applying relocate section %u to %u\n", relsec,
+		sechdrs[relsec].sh_info);
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) {
+		/* This is where to make the change */
+		uint32_t *loc
+			= ((void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+			   + rela[i].r_offset);
+		/* This is the symbol it is referring to */
+		Elf32_Sym *sym
+			= ((Elf32_Sym *)sechdrs[symindex].sh_offset
+			   + ELF32_R_SYM (rela[i].r_info));
+		uint32_t val = sym->st_value;
+
+		if (! val) {
+			printk (KERN_WARNING "%s: Unknown symbol %s\n",
+				mod->name, strtab + sym->st_name);
+			return -ENOENT;
+		}
+
+		val += rela[i].r_addend;
+
+		switch (ELF32_R_TYPE (rela[i].r_info)) {
+		case R_V850_32:
+			/* We write two shorts instead of a long because even
+			   32-bit insns only need half-word alignment, but
+			   32-bit data writes need to be long-word aligned.  */
+			val += ((uint16_t *)loc)[0];
+			val += ((uint16_t *)loc)[1] << 16;
+			((uint16_t *)loc)[0] = val & 0xffff;
+			((uint16_t *)loc)[1] = (val >> 16) & 0xffff;
+			break;
+
+		case R_V850_22_PCREL:
+			/* Maybe jump indirectly via a PLT table entry.  */
+			if ((int32_t)(val - (uint32_t)loc) > 0x1fffff
+			    || (int32_t)(val - (uint32_t)loc) < -0x200000)
+				val = do_plt_call (loc, val, mod);
+
+			val -= (uint32_t)loc;
+
+			/* We write two shorts instead of a long because
+			   even 32-bit insns only need half-word alignment,
+			   but 32-bit data writes need to be long-word
+			   aligned.  */
+			((uint16_t *)loc)[0] =
+				(*(uint16_t *)loc & 0xffc0) /* opcode + reg */
+				| ((val >> 16) & 0xffc03f); /* offs high */
+			((uint16_t *)loc)[1] =
+				(val & 0xffff);		    /* offs low */
+			break;
+
+		default:
+			printk (KERN_ERR "module %s: Unknown reloc: %u\n",
+				mod->name, ELF32_R_TYPE (rela[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+
+	return 0;
+}
diff -Nru a/arch/v850/kernel/nb85e_intc.c b/arch/v850/kernel/nb85e_intc.c
--- a/arch/v850/kernel/nb85e_intc.c	Wed Nov 27 14:36:28 2002
+++ b/arch/v850/kernel/nb85e_intc.c	Wed Nov 27 14:36:28 2002
@@ -33,7 +33,7 @@
 {
 	struct nb85e_intc_irq_init *init;
 	for (init = inits; init->name; init++) {
-		int i;
+		unsigned i;
 		struct hw_interrupt_type *hwit = hw_irq_types++;
 
 		hwit->typename = init->name;
diff -Nru a/arch/v850/kernel/nb85e_utils.c b/arch/v850/kernel/nb85e_utils.c
--- a/arch/v850/kernel/nb85e_utils.c	Wed Nov 27 14:36:28 2002
+++ b/arch/v850/kernel/nb85e_utils.c	Wed Nov 27 14:36:28 2002
@@ -2,8 +2,8 @@
  * include/asm-v850/nb85e_utils.h -- Utility functions associated with
  *	the NB85E cpu core
  *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02  NEC Corporation
+ *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -40,7 +40,7 @@
 	/* Find the lowest clock divider setting that can represent RATE.  */
 	for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) {
 		/* Minimum interrupt rate possible using this divider.  */
-		int min_int_rate
+		unsigned min_int_rate
 			= (base_freq >> _divlog2) >> counter_size;
 
 		if (min_int_rate <= rate) {
diff -Nru a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
--- a/arch/v850/kernel/process.c	Wed Nov 27 14:36:28 2002
+++ b/arch/v850/kernel/process.c	Wed Nov 27 14:36:28 2002
@@ -58,49 +58,6 @@
 	(*idle) ();
 }
 
-struct spec_reg_name {
-	const char *name;
-	int gpr;
-};
-
-struct spec_reg_name spec_reg_names[] = {
-	{ "sp", GPR_SP },
-	{ "gp", GPR_GP },
-	{ "tp", GPR_TP },
-	{ "ep", GPR_EP },
-	{ "lp", GPR_LP },
-	{ 0, 0 }
-};
-
-void show_regs (struct pt_regs *regs)
-{
-	int gpr_base, gpr_offs;
-
-	printk ("     pc 0x%08lx    psw 0x%08lx                       kernel_mode %d\n",
-		regs->pc, regs->psw, regs->kernel_mode);
-	printk ("   ctpc 0x%08lx  ctpsw 0x%08lx   ctbp 0x%08lx\n",
-		regs->ctpc, regs->ctpsw, regs->ctbp);
-
-	for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) {
-		for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) {
-			int gpr = gpr_base + gpr_offs;
-			long val = regs->gpr[gpr];
-			struct spec_reg_name *srn;
-
-			for (srn = spec_reg_names; srn->name; srn++)
-				if (srn->gpr == gpr)
-					break;
-
-			if (srn->name)
-				printk ("%7s 0x%08lx", srn->name, val);
-			else
-				printk ("    r%02d 0x%08lx", gpr, val);
-		}
-
-		printk ("\n");
-	}
-}
-
 /*
  * This is the mechanism for creating a new kernel thread.
  *
@@ -231,7 +188,7 @@
    are in entry.S).  */
 int fork_common (int flags, unsigned long new_sp, struct pt_regs *regs)
 {
-	struct task_struct *p = do_fork (flags, new_sp, regs, 0, 0);
+	struct task_struct *p = do_fork (flags, new_sp, regs, 0, 0, 0);
 	return IS_ERR (p) ? PTR_ERR (p) : p->pid;
 }
 
diff -Nru a/arch/v850/kernel/procfs.c b/arch/v850/kernel/procfs.c
--- a/arch/v850/kernel/procfs.c	Wed Nov 27 14:36:30 2002
+++ b/arch/v850/kernel/procfs.c	Wed Nov 27 14:36:30 2002
@@ -24,7 +24,7 @@
 #else
 	seq_printf (m, "CPU-Model:	%s\n", CPU_MODEL);
 #endif
- 
+
 #ifdef CPU_CLOCK_FREQ
 	seq_printf (m, "CPU-Clock:	%ld (%ld MHz)\n",
 		    (long)CPU_CLOCK_FREQ,
diff -Nru a/arch/v850/kernel/rte_cb.c b/arch/v850/kernel/rte_cb.c
--- a/arch/v850/kernel/rte_cb.c	Wed Nov 27 14:36:27 2002
+++ b/arch/v850/kernel/rte_cb.c	Wed Nov 27 14:36:27 2002
@@ -60,25 +60,11 @@
 
 void __init mach_setup (char **cmdline)
 {
-	printk (KERN_INFO
-		"CPU: %s\n"
-		"Platform: %s%s\n",
-		CPU_MODEL_LONG,
-		PLATFORM_LONG,
-#ifdef CONFIG_ROM_KERNEL
-		""
-#elif defined (CONFIG_RTE_CB_MULTI)
-		" (with Multi ROM monitor)"
-#else
-		" (with ROM monitor)"
-#endif		
-		);
-
 	/* Probe for Mother-A, and print a message if we find it.  */
-	*(volatile long *)MB_A_SRAM_ADDR = 0xDEADBEEF;
-	if (*(volatile long *)MB_A_SRAM_ADDR == 0xDEADBEEF) {
-		*(volatile long *)MB_A_SRAM_ADDR = 0x12345678;
-		if (*(volatile long *)MB_A_SRAM_ADDR == 0x12345678)
+	*(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF;
+	if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) {
+		*(volatile unsigned long *)MB_A_SRAM_ADDR = 0x12345678;
+		if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0x12345678)
 			printk (KERN_INFO
 				"          NEC SolutionGear/Midas lab"
 				" RTE-MOTHER-A motherboard\n");
diff -Nru a/arch/v850/kernel/rte_cb_leds.c b/arch/v850/kernel/rte_cb_leds.c
--- a/arch/v850/kernel/rte_cb_leds.c	Wed Nov 27 14:36:27 2002
+++ b/arch/v850/kernel/rte_cb_leds.c	Wed Nov 27 14:36:27 2002
@@ -109,10 +109,12 @@
 	else if (whence == 2)
 		offs += LED_NUM_DIGITS; /* end-relative */
 
-	if (offs >= 0 && offs <= LED_NUM_DIGITS)
-		file->f_pos = offs;
-	else
+	if (offs < 0 || offs > LED_NUM_DIGITS)
 		return -EINVAL;
+
+	file->f_pos = offs;
+
+	return 0;
 }
 
 static struct file_operations leds_fops = {
diff -Nru a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
--- a/arch/v850/kernel/rte_mb_a_pci.c	Wed Nov 27 14:36:28 2002
+++ b/arch/v850/kernel/rte_mb_a_pci.c	Wed Nov 27 14:36:28 2002
@@ -239,7 +239,7 @@
 	struct resource *r;
 
 	pci_for_each_dev (dev) {
-		int di_num;
+		unsigned di_num;
 		unsigned class = dev->class >> 8;
 
 		if (class && class != PCI_CLASS_BRIDGE_HOST) {
diff -Nru a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
--- a/arch/v850/kernel/setup.c	Wed Nov 27 14:36:30 2002
+++ b/arch/v850/kernel/setup.c	Wed Nov 27 14:36:30 2002
@@ -78,6 +78,9 @@
 	/* ... and tell the kernel about it.  */
 	init_mem_alloc (ram_start, ram_len);
 
+	printk (KERN_INFO "CPU: %s\nPlatform: %s\n",
+		CPU_MODEL_LONG, PLATFORM_LONG);
+
 	/* do machine-specific setups.  */
 	mach_setup (cmdline);
 
@@ -266,6 +269,16 @@
 	   initial gap from PAGE_OFFSET to ram_start.  */
 	zones_size[ZONE_DMA]
 		= ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET));
+
+	/* The allocator is very picky about the address of the first
+	   allocatable page -- it must be at least as aligned as the
+	   maximum allocation -- so try to detect cases where it will get
+	   confused and signal them at compile time (this is a common
+	   problem when porting to a new platform with ).  There is a
+	   similar runtime check in free_area_init_core.  */
+#if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1))
+#error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it)
+#endif
 
 	free_area_init_node (0, NODE_DATA(0), 0, zones_size,
 			     ADDR_TO_PAGE (PAGE_OFFSET), 0);
diff -Nru a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
--- a/arch/v850/kernel/signal.c	Wed Nov 27 14:36:32 2002
+++ b/arch/v850/kernel/signal.c	Wed Nov 27 14:36:32 2002
@@ -512,9 +512,10 @@
 	/* Did we come from a system call? */
 	if (PT_REGS_SYSCALL (regs)) {
 		/* Restart the system call - no handlers present */
-		if (regs->gpr[GPR_RVAL] == -ERESTARTNOHAND ||
-		    regs->gpr[GPR_RVAL] == -ERESTARTSYS ||
-		    regs->gpr[GPR_RVAL] == -ERESTARTNOINTR) {
+		if (regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTNOHAND ||
+		    regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTSYS ||
+		    regs->gpr[GPR_RVAL] == (v850_reg_t)-ERESTARTNOINTR)
+		{
 			regs->gpr[12] = PT_REGS_SYSCALL (regs);
 			regs->pc -= 4; /* Size of `trap 0' insn.  */
 		}
diff -Nru a/arch/v850/kernel/sim.c b/arch/v850/kernel/sim.c
--- a/arch/v850/kernel/sim.c	Wed Nov 27 14:36:31 2002
+++ b/arch/v850/kernel/sim.c	Wed Nov 27 14:36:31 2002
@@ -42,8 +42,6 @@
 	const char *err;
 	unsigned long root_dev_addr, root_dev_len;
 
-	printk (KERN_INFO "CPU: NEC V850E (GDB simulator)\n");
-
 	simcons_setup ();
 
 	printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS);
diff -Nru a/arch/v850/kernel/sim85e2c.c b/arch/v850/kernel/sim85e2c.c
--- a/arch/v850/kernel/sim85e2c.c	Wed Nov 27 14:36:30 2002
+++ b/arch/v850/kernel/sim85e2c.c	Wed Nov 27 14:36:30 2002
@@ -79,8 +79,6 @@
 
 void __init mach_setup (char **cmdline)
 {
-	printk (KERN_INFO "CPU: NEC V850E2 (sim85e2c simulator)\n");
-
 	memcons_setup ();
 }
 
diff -Nru a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c
--- a/arch/v850/kernel/simcons.c	Wed Nov 27 14:36:31 2002
+++ b/arch/v850/kernel/simcons.c	Wed Nov 27 14:36:31 2002
@@ -154,5 +154,5 @@
 {
 	V850_SIM_SYSCALL (make_raw, 0);
 	register_console (&simcons);
-	printk (KERN_INFO "Console: GDB/v850e simulator stdio\n");
+	printk (KERN_INFO "Console: GDB V850E simulator stdio\n");
 }
diff -Nru a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
--- a/arch/v850/kernel/v850_ksyms.c	Wed Nov 27 14:36:30 2002
+++ b/arch/v850/kernel/v850_ksyms.c	Wed Nov 27 14:36:30 2002
@@ -27,6 +27,9 @@
 extern void dump_thread (struct pt_regs *, struct user *);
 EXPORT_SYMBOL (dump_thread);
 EXPORT_SYMBOL (kernel_thread);
+EXPORT_SYMBOL (enable_irq);
+EXPORT_SYMBOL (disable_irq);
+EXPORT_SYMBOL (disable_irq_nosync);
 EXPORT_SYMBOL (__bug);
 
 /* Networking helper routines. */
@@ -46,7 +49,6 @@
 EXPORT_SYMBOL_NOVERS (strlen);
 EXPORT_SYMBOL_NOVERS (strnlen);
 EXPORT_SYMBOL_NOVERS (strpbrk);
-EXPORT_SYMBOL_NOVERS (strtok);
 EXPORT_SYMBOL_NOVERS (strrchr);
 EXPORT_SYMBOL_NOVERS (strstr);
 EXPORT_SYMBOL_NOVERS (memset);
diff -Nru a/arch/v850/rte_ma1_cb-ksram.ld b/arch/v850/rte_ma1_cb-ksram.ld
--- a/arch/v850/rte_ma1_cb-ksram.ld	Wed Nov 27 14:36:32 2002
+++ b/arch/v850/rte_ma1_cb-ksram.ld	Wed Nov 27 14:36:32 2002
@@ -93,6 +93,11 @@
 			*(.initcall7.init)
 		. = ALIGN (4) ;
 		___initcall_end = . ;
+
+		. = ALIGN (4) ;
+		___initramfs_start = . ;
+			*(.init.ramfs)
+		___initramfs_end = . ;
 	} > SRAM
 
 	/* This provides address at which the interrupt vectors are
diff -Nru a/arch/v850/rte_ma1_cb-rom.ld b/arch/v850/rte_ma1_cb-rom.ld
--- a/arch/v850/rte_ma1_cb-rom.ld	Wed Nov 27 14:36:31 2002
+++ b/arch/v850/rte_ma1_cb-rom.ld	Wed Nov 27 14:36:31 2002
@@ -45,9 +45,14 @@
 		___stop___ksymtab = . ;
 		. = ALIGN (4) ;
 		__etext = . ;
+
+		. = ALIGN (4) ;
+		___initramfs_start = . ;
+			*(.init.ramfs)
+		___initramfs_end = . ;
 	} > ROM
 
-	__data_load_start = . ;
+	__rom_copy_src_start = . ;
 
 	.data : {
 	        __kram_start = . ;
diff -Nru a/arch/v850/rte_ma1_cb.ld b/arch/v850/rte_ma1_cb.ld
--- a/arch/v850/rte_ma1_cb.ld	Wed Nov 27 14:36:27 2002
+++ b/arch/v850/rte_ma1_cb.ld	Wed Nov 27 14:36:27 2002
@@ -98,10 +98,15 @@
 			*(.initcall7.init)
 		. = ALIGN (4) ;
 		___initcall_end = . ;
+
+		. = ALIGN (4) ;
+		___initramfs_start = . ;
+			*(.init.ramfs)
+		___initramfs_end = . ;
 	} > SDRAM
 
-	/* This provides address at which the interrupt vectors are
-	   initially loaded by the loader.  */
+	/* The address at which the interrupt vectors are initially
+	   loaded by the loader.  */
 	__intv_load_start = ALIGN (0x10) ;
 
 	/* Interrupt vector space.  Because we're using the monitor
diff -Nru a/arch/v850/sim.ld b/arch/v850/sim.ld
--- a/arch/v850/sim.ld	Wed Nov 27 14:36:27 2002
+++ b/arch/v850/sim.ld	Wed Nov 27 14:36:27 2002
@@ -96,6 +96,12 @@
 			*(.initcall7.init)
 		. = ALIGN (4) ;
 		___initcall_end = . ;
+
+		. = ALIGN (4) ;
+		___initramfs_start = . ;
+			*(.init.ramfs)
+		___initramfs_end = . ;
+
 		__init_end = . ;
 
 		__kram_end = . ;
diff -Nru a/arch/v850/sim85e2c.ld b/arch/v850/sim85e2c.ld
--- a/arch/v850/sim85e2c.ld	Wed Nov 27 14:36:32 2002
+++ b/arch/v850/sim85e2c.ld	Wed Nov 27 14:36:32 2002
@@ -86,6 +86,12 @@
 			*(.initcall7.init)
 		. = ALIGN (4) ;
 		___initcall_end = . ;
+
+		. = ALIGN (4) ;
+		___initramfs_start = . ;
+			*(.init.ramfs)
+		___initramfs_end = . ;
+
 		__init_end = . ;
 	} > IRAM
 
diff -Nru a/arch/v850/vmlinux.lds.S b/arch/v850/vmlinux.lds.S
--- a/arch/v850/vmlinux.lds.S	Wed Nov 27 14:36:31 2002
+++ b/arch/v850/vmlinux.lds.S	Wed Nov 27 14:36:31 2002
@@ -20,6 +20,10 @@
 # endif
 #endif
 
+#ifdef CONFIG_V850E_AS85EP1
+# include "as85ep1.ld"
+#endif
+
 #ifdef CONFIG_RTE_CB_MA1
 # ifdef CONFIG_ROM_KERNEL
 #  include "rte_ma1_cb-rom.ld"
diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
--- a/arch/x86_64/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
+++ b/arch/x86_64/kernel/ptrace.c	Wed Nov 27 14:36:28 2002
@@ -178,8 +178,7 @@
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
 			goto out;
-		ret = security_ops->ptrace(current->parent, current);
-		if (ret)
+		if ((ret = security_ptrace(current->parent, current)))
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	Wed Nov 27 14:36:31 2002
+++ b/drivers/Makefile	Wed Nov 27 14:36:31 2002
@@ -8,6 +8,9 @@
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
 obj-$(CONFIG_ACPI)		+= acpi/
+# PnP must come after ACPI since it will eventually need to check if acpi
+# was used and do nothing if so
+obj-$(CONFIG_PNP)		+= pnp/
 obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-y				+= base/ char/ block/ misc/ net/ media/
@@ -26,7 +29,6 @@
 obj-$(CONFIG_ZORRO)		+= zorro/
 obj-$(CONFIG_ALL_PPC)		+= macintosh/
 obj-$(CONFIG_MAC)		+= macintosh/
-obj-$(CONFIG_PNP)		+= pnp/
 obj-$(CONFIG_SGI)		+= sgi/
 obj-$(CONFIG_VT)		+= video/
 obj-$(CONFIG_PARIDE) 		+= block/paride/
diff -Nru a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile
--- a/drivers/acorn/char/Makefile	Wed Nov 27 14:36:27 2002
+++ b/drivers/acorn/char/Makefile	Wed Nov 27 14:36:27 2002
@@ -2,7 +2,6 @@
 # Makefile for the acorn character device drivers.
 #
 
-# All the objects that export symbols.
 obj-arc		:= keyb_arc.o defkeymap-acorn.o
 
 obj-$(CONFIG_ARCH_ACORN)	+= i2c.o pcf8583.o
diff -Nru a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c
--- a/drivers/acorn/scsi/acornscsi.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/acorn/scsi/acornscsi.c	Wed Nov 27 14:36:30 2002
@@ -137,10 +137,10 @@
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/proc_fs.h>
-#include <linux/stat.h>
 #include <linux/ioport.h>
 #include <linux/blk.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/bitops.h>
diff -Nru a/drivers/acorn/scsi/arxescsi.h b/drivers/acorn/scsi/arxescsi.h
--- a/drivers/acorn/scsi/arxescsi.h	Wed Nov 27 14:36:27 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,80 +0,0 @@
-/*
- * ARXE SCSI card driver
- *
- * Copyright (C) 1997-2000 Russell King
- *
- * Changes to support ARXE 16-bit SCSI card by Stefan Hanske
- */
-#ifndef ARXE_SCSI_H
-#define ARXE_SCSI_H
-
-#define MANU_ARXE 	0x0041
-#define PROD_ARXE_SCSI	0x00be
-
-extern int arxescsi_detect (Scsi_Host_Template *);
-extern int arxescsi_release (struct Scsi_Host *);
-extern const char *arxescsi_info (struct Scsi_Host *);
-extern int arxescsi_proc_info (char *buffer, char **start, off_t offset,
-				int length, int hostno, int inout);
-
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-
-#ifndef CAN_QUEUE
-/*
- * Default queue size
- */
-#define CAN_QUEUE	1
-#endif
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN	1
-#endif
-
-#ifndef SCSI_ID
-/*
- * Default SCSI host ID
- */
-#define SCSI_ID		7
-#endif
-
-#include <scsi/scsicam.h>
-
-#include "fas216.h"
-
-#define ARXEScsi {					\
-proc_info:			arxescsi_proc_info,	\
-name:				"ARXE SCSI card",	\
-detect:				arxescsi_detect,	\
-release:			arxescsi_release,	\
-info:				arxescsi_info,		\
-can_queue:			CAN_QUEUE,		\
-this_id:			SCSI_ID,		\
-sg_tablesize:			SG_ALL,			\
-cmd_per_lun:			CMD_PER_LUN,		\
-use_clustering:			DISABLE_CLUSTERING,	\
-command:			fas216_command,		\
-queuecommand:			fas216_queue_command,	\
-eh_host_reset_handler:		fas216_eh_host_reset,	\
-eh_bus_reset_handler:		fas216_eh_bus_reset,	\
-eh_device_reset_handler:	fas216_eh_device_reset,	\
-eh_abort_handler:		fas216_eh_abort,	\
-	}
-
-#ifndef HOSTS_C
-
-typedef struct {
-    FAS216_Info info;
-
-    /* other info... */
-    unsigned int	cstatus;	/* card status register	*/
-    unsigned int	dmaarea;	/* Pseudo DMA area	*/
-} ARXEScsi_Info;
-
-#define CSTATUS_IRQ	(1 << 0)
-#define CSTATUS_DRQ	(1 << 0)
-
-#endif /* HOSTS_C */
-
-#endif /* ARXE_SCSI_H */
diff -Nru a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c
--- a/drivers/acorn/scsi/cumana_2.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/acorn/scsi/cumana_2.c	Wed Nov 27 14:36:31 2002
@@ -23,10 +23,8 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
-#include <linux/unistd.h>
-#include <linux/stat.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c
--- a/drivers/acorn/scsi/eesox.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/acorn/scsi/eesox.c	Wed Nov 27 14:36:32 2002
@@ -29,10 +29,8 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
-#include <linux/unistd.h>
-#include <linux/stat.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
diff -Nru a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c
--- a/drivers/acorn/scsi/fas216.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/acorn/scsi/fas216.c	Wed Nov 27 14:36:29 2002
@@ -44,8 +44,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
-#include <linux/unistd.h>
-#include <linux/stat.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 
diff -Nru a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c
--- a/drivers/acorn/scsi/powertec.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/acorn/scsi/powertec.c	Wed Nov 27 14:36:31 2002
@@ -14,10 +14,8 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
-#include <linux/unistd.h>
-#include <linux/stat.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
diff -Nru a/drivers/acpi/ac.c b/drivers/acpi/ac.c
--- a/drivers/acpi/ac.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/acpi/ac.c	Wed Nov 27 14:36:29 2002
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/compatmac.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
@@ -53,6 +54,7 @@
 
 int acpi_ac_add (struct acpi_device *device);
 int acpi_ac_remove (struct acpi_device *device, int type);
+static int acpi_ac_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_ac_driver = {
 	.name =		ACPI_AC_DRIVER_NAME,
@@ -69,6 +71,12 @@
 	unsigned long		state;
 };
 
+static struct file_operations acpi_ac_fops = {
+	.open		= acpi_ac_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 /* --------------------------------------------------------------------------
                                AC Adapter Management
@@ -103,53 +111,40 @@
 
 struct proc_dir_entry		*acpi_ac_dir = NULL;
 
-static int
-acpi_ac_read_state (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+int acpi_ac_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_ac		*ac = (struct acpi_ac *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_ac		*ac = (struct acpi_ac *) seq->private;
 
-	ACPI_FUNCTION_TRACE("acpi_ac_read_state");
+	ACPI_FUNCTION_TRACE("acpi_ac_seq_show");
 
-	if (!ac || (off != 0))
-		goto end;
+	if (!ac)
+		return 0;
 
 	if (acpi_ac_get_state(ac)) {
-		p += sprintf(p, "ERROR: Unable to read AC Adapter state\n");
-		goto end;
+		seq_puts(seq, "ERROR: Unable to read AC Adapter state\n");
+		return 0;
 	}
 
-	p += sprintf(p, "state:                   ");
+	seq_puts(seq, "state:                   ");
 	switch (ac->state) {
 	case ACPI_AC_STATUS_OFFLINE:
-		p += sprintf(p, "off-line\n");
+		seq_puts(seq, "off-line\n");
 		break;
 	case ACPI_AC_STATUS_ONLINE:
-		p += sprintf(p, "on-line\n");
+		seq_puts(seq, "on-line\n");
 		break;
 	default:
-		p += sprintf(p, "unknown\n");
+		seq_puts(seq, "unknown\n");
 		break;
 	}
 
-end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
+}
+	
+static int acpi_ac_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_ac_seq_show, PDE(inode)->data);
 }
-
 
 static int
 acpi_ac_add_fs (
@@ -174,7 +169,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_AC_FILE_STATE));
 	else {
-		entry->read_proc = acpi_ac_read_state;
+		entry->proc_fops = &acpi_ac_fops;
 		entry->data = acpi_driver_data(device);
 	}
 
diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c
--- a/drivers/acpi/button.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/acpi/button.c	Wed Nov 27 14:36:27 2002
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/compatmac.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
@@ -69,6 +70,7 @@
 
 int acpi_button_add (struct acpi_device *device);
 int acpi_button_remove (struct acpi_device *device, int type);
+static int acpi_button_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_button_driver = {
 	.name =		ACPI_BUTTON_DRIVER_NAME,
@@ -87,6 +89,12 @@
 	unsigned long		pushed;
 };
 
+static struct file_operations acpi_button_fops = {
+	.open		= acpi_button_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
@@ -94,39 +102,26 @@
 
 static struct proc_dir_entry	*acpi_button_dir = NULL;
 
-static int
-acpi_button_read_info (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_button_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_button	*button = (struct acpi_button *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_button	*button = (struct acpi_button *) seq->private;
 
-	ACPI_FUNCTION_TRACE("acpi_button_read_info");
+	ACPI_FUNCTION_TRACE("acpi_button_seq_show");
 
 	if (!button || !button->device)
-		goto end;
+		return 0;
 
-	p += sprintf(p, "type:                    %s\n", 
+	seq_printf(seq, "type:                    %s\n", 
 		acpi_device_name(button->device));
 
-end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
 }
 
-
+static int acpi_button_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_button_seq_show, PDE(inode)->data);
+}
+	
 static int
 acpi_button_add_fs (
 	struct acpi_device	*device)
@@ -170,7 +165,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_BUTTON_FILE_INFO));
 	else {
-		entry->read_proc = acpi_button_read_info;
+		entry->proc_fops = &acpi_button_fops;
 		entry->data = acpi_driver_data(device);
 	}
 
diff -Nru a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
--- a/drivers/acpi/dispatcher/dsmthdat.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/acpi/dispatcher/dsmthdat.c	Wed Nov 27 14:36:29 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: dsmthdat - control method arguments and local variables
- *              $Revision: 64 $
+ *              $Revision: 66 $
  *
  ******************************************************************************/
 
@@ -28,6 +28,7 @@
 #include "acdispat.h"
 #include "amlcode.h"
 #include "acnamesp.h"
+#include "acinterp.h"
 
 
 #define _COMPONENT          ACPI_DISPATCHER
@@ -274,6 +275,7 @@
  * RETURN:      Status
  *
  * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
+ *              Note: There is no "implicit conversion" for locals.
  *
  ******************************************************************************/
 
@@ -286,11 +288,17 @@
 {
 	acpi_status             status;
 	acpi_namespace_node     *node;
+	acpi_operand_object     *new_desc = object;
 
 
 	ACPI_FUNCTION_TRACE ("Ds_method_data_set_value");
 
 
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+		"obj %p op %X, ref count = %d [%s]\n", object,
+		opcode, object->common.reference_count,
+		acpi_ut_get_type_name (object->common.type)));
+
 	/* Get the namespace node for the arg/local */
 
 	status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
@@ -298,14 +306,30 @@
 		return_ACPI_STATUS (status);
 	}
 
-	/* Increment ref count so object can't be deleted while installed */
+	/*
+	 * If the object has just been created and is not attached to anything,
+	 * (the reference count is 1), then we can just store it directly into
+	 * the arg/local.  Otherwise, we must copy it.
+	 */
+	if (object->common.reference_count > 1) {
+		status = acpi_ut_copy_iobject_to_iobject (object, &new_desc, walk_state);
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+		}
 
-	acpi_ut_add_reference (object);
+	   ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object Copied %p, new %p\n",
+		   object, new_desc));
+	}
+	else {
+		/* Increment ref count so object can't be deleted while installed */
 
-	/* Install the object into the stack entry */
+		acpi_ut_add_reference (new_desc);
+	}
 
-	node->object = object;
-	return_ACPI_STATUS (AE_OK);
+	/* Install the object */
+
+	node->object = new_desc;
+	return_ACPI_STATUS (status);
 }
 
 
@@ -560,7 +584,8 @@
 
 	current_obj_desc = acpi_ns_get_attached_object (node);
 	if (current_obj_desc == obj_desc) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n", obj_desc));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n",
+			obj_desc));
 		return_ACPI_STATUS (status);
 	}
 
@@ -609,16 +634,12 @@
 					"Arg (%p) is an Obj_ref(Node), storing in node %p\n",
 					obj_desc, current_obj_desc));
 
-				/* Detach an existing object from the referenced Node */
-
-				acpi_ns_detach_object (current_obj_desc->reference.object);
-
 				/*
-				 * Store this object into the Node
+				 * Store this object to the Node
 				 * (perform the indirect store)
 				 */
-				status = acpi_ns_attach_object (current_obj_desc->reference.object,
-						  obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc));
+				status = acpi_ex_store_object_to_node (obj_desc,
+						 current_obj_desc->reference.object, walk_state);
 				return_ACPI_STATUS (status);
 			}
 		}
diff -Nru a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
--- a/drivers/acpi/events/evevent.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/acpi/events/evevent.c	Wed Nov 27 14:36:31 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: evevent - Fixed and General Purpose Even handling and dispatch
- *              $Revision: 96 $
+ *              $Revision: 99 $
  *
  *****************************************************************************/
 
@@ -331,11 +331,8 @@
 	 *  FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
 	 *  to be the same size."
 	 */
-	acpi_gbl_gpe_block_info[0].address_space_id = acpi_gbl_FADT->Xgpe0_blk.address_space_id;
-	acpi_gbl_gpe_block_info[1].address_space_id = acpi_gbl_FADT->Xgpe1_blk.address_space_id;
-
-	acpi_gbl_gpe_block_info[0].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe0_blk.register_bit_width);
-	acpi_gbl_gpe_block_info[1].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe1_blk.register_bit_width);
+	acpi_gbl_gpe_block_info[0].register_count = 0;
+	acpi_gbl_gpe_block_info[1].register_count = 0;
 
 	acpi_gbl_gpe_block_info[0].block_address = &acpi_gbl_FADT->Xgpe0_blk;
 	acpi_gbl_gpe_block_info[1].block_address = &acpi_gbl_FADT->Xgpe1_blk;
@@ -343,28 +340,25 @@
 	acpi_gbl_gpe_block_info[0].block_base_number = 0;
 	acpi_gbl_gpe_block_info[1].block_base_number = acpi_gbl_FADT->gpe1_base;
 
-	/* Warn and exit if there are no GPE registers */
-
-	acpi_gbl_gpe_register_count = acpi_gbl_gpe_block_info[0].register_count +
-			 acpi_gbl_gpe_block_info[1].register_count;
-	if (!acpi_gbl_gpe_register_count) {
-		ACPI_REPORT_WARNING (("There are no GPE blocks defined in the FADT\n"));
-		return_ACPI_STATUS (AE_OK);
-	}
 
 	/*
 	 * Determine the maximum GPE number for this machine.
 	 * Note: both GPE0 and GPE1 are optional, and either can exist without
-	 * the other
+	 * the other.
+	 * If EITHER the register length OR the block address are zero, then that
+	 * particular block is not supported.
 	 */
-	if (acpi_gbl_gpe_block_info[0].register_count) {
-		/* GPE block 0 exists */
+	if (acpi_gbl_FADT->Xgpe0_blk.register_bit_width && ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0_blk.address)) {
+		/* GPE block 0 exists (has length and address > 0) */
 
-		acpi_gbl_gpe_number_max = ACPI_MUL_8 (acpi_gbl_gpe_block_info[0].register_count) - 1;
+		acpi_gbl_gpe_block_info[0].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe0_blk.register_bit_width);
+		acpi_gbl_gpe_number_max                 = ACPI_MUL_8 (acpi_gbl_gpe_block_info[0].register_count) - 1;
 	}
 
-	if (acpi_gbl_gpe_block_info[1].register_count) {
-		/* GPE block 1 exists */
+	if (acpi_gbl_FADT->Xgpe1_blk.register_bit_width && ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address)) {
+		/* GPE block 1 exists (has length and address > 0) */
+
+		acpi_gbl_gpe_block_info[1].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe1_blk.register_bit_width);
 
 		/* Check for GPE0/GPE1 overlap (if both banks exist) */
 
@@ -385,6 +379,15 @@
 				 (ACPI_MUL_8 (acpi_gbl_gpe_block_info[1].register_count) - 1);
 	}
 
+	/* Warn and exit if there are no GPE registers */
+
+	acpi_gbl_gpe_register_count = acpi_gbl_gpe_block_info[0].register_count +
+			 acpi_gbl_gpe_block_info[1].register_count;
+	if (!acpi_gbl_gpe_register_count) {
+		ACPI_REPORT_WARNING (("There are no GPE blocks defined in the FADT\n"));
+		return_ACPI_STATUS (AE_OK);
+	}
+
 	/* Check for Max GPE number out-of-range */
 
 	if (acpi_gbl_gpe_number_max > ACPI_GPE_MAX) {
@@ -460,8 +463,8 @@
 							  + i
 							  + acpi_gbl_gpe_block_info[gpe_block].register_count));
 
-			gpe_register_info->status_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id;
-			gpe_register_info->enable_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id;
+			gpe_register_info->status_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].block_address->address_space_id;
+			gpe_register_info->enable_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].block_address->address_space_id;
 			gpe_register_info->status_address.register_bit_width = 8;
 			gpe_register_info->enable_address.register_bit_width = 8;
 			gpe_register_info->status_address.register_bit_offset = 8;
@@ -565,7 +568,7 @@
 	/* Extract the name from the object and convert to a string */
 
 	ACPI_MOVE_UNALIGNED32_TO_32 (name,
-			  &((acpi_namespace_node *) obj_handle)->name.integer);
+			 &((acpi_namespace_node *) obj_handle)->name.integer);
 	name[ACPI_NAME_SIZE] = 0;
 
 	/*
@@ -614,8 +617,8 @@
 	 * Now we can add this information to the Gpe_info block
 	 * for use during dispatch of this GPE.
 	 */
-	acpi_gbl_gpe_number_info [gpe_number_index].type    = type;
-	acpi_gbl_gpe_number_info [gpe_number_index].method_handle = obj_handle;
+	acpi_gbl_gpe_number_info [gpe_number_index].type  = type;
+	acpi_gbl_gpe_number_info [gpe_number_index].method_node = (acpi_namespace_node *) obj_handle;
 
 	/*
 	 * Enable the GPE (SCIs should be disabled at this point)
@@ -625,7 +628,7 @@
 		return (status);
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %2.2X\n",
 		name, gpe_number));
 	return (AE_OK);
 }
@@ -805,15 +808,16 @@
 		return_VOID;
 	}
 
-	if (gpe_info.method_handle) {
+	if (gpe_info.method_node) {
 		/*
 		 * Invoke the GPE Method (_Lxx, _Exx):
 		 * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
 		 */
-		status = acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL);
+		status = acpi_ns_evaluate_by_handle (gpe_info.method_node, NULL, NULL);
 		if (ACPI_FAILURE (status)) {
-			ACPI_REPORT_ERROR (("%s while evaluating GPE%X method\n",
-				acpi_format_exception (status), gpe_number));
+			ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2.2X]\n",
+				acpi_format_exception (status),
+				gpe_info.method_node->name.ascii, gpe_number));
 		}
 	}
 
@@ -881,7 +885,7 @@
 	if (gpe_info->type & ACPI_EVENT_EDGE_TRIGGERED) {
 		status = acpi_hw_clear_gpe (gpe_number);
 		if (ACPI_FAILURE (status)) {
-			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%X]\n", gpe_number));
+			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%2.2X]\n", gpe_number));
 			return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
 		}
 	}
@@ -898,14 +902,14 @@
 
 		gpe_info->handler (gpe_info->context);
 	}
-	else if (gpe_info->method_handle) {
+	else if (gpe_info->method_node) {
 		/*
 		 * Disable GPE, so it doesn't keep firing before the method has a
 		 * chance to run.
 		 */
 		status = acpi_hw_disable_gpe (gpe_number);
 		if (ACPI_FAILURE (status)) {
-			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%X]\n", gpe_number));
+			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%2.2X]\n", gpe_number));
 			return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
 		}
 
@@ -915,13 +919,13 @@
 		if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
 				 acpi_ev_asynch_execute_gpe_method,
 				 ACPI_TO_POINTER (gpe_number)))) {
-			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%X], event is disabled\n", gpe_number));
+			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2.2X], event is disabled\n", gpe_number));
 		}
 	}
 	else {
 		/* No handler or method to run! */
 
-		ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: No handler or method for GPE[%X], disabling event\n", gpe_number));
+		ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: No handler or method for GPE[%2.2X], disabling event\n", gpe_number));
 
 		/*
 		 * Disable the GPE.  The GPE will remain disabled until the ACPI
@@ -929,7 +933,7 @@
 		 */
 		status = acpi_hw_disable_gpe (gpe_number);
 		if (ACPI_FAILURE (status)) {
-			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%X]\n", gpe_number));
+			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to disable GPE[%2.2X]\n", gpe_number));
 			return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
 		}
 	}
@@ -940,7 +944,7 @@
 	if (gpe_info->type & ACPI_EVENT_LEVEL_TRIGGERED) {
 		status = acpi_hw_clear_gpe (gpe_number);
 		if (ACPI_FAILURE (status)) {
-			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%X]\n", gpe_number));
+			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to clear GPE[%2.2X]\n", gpe_number));
 			return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
 		}
 	}
diff -Nru a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
--- a/drivers/acpi/events/evrgnini.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/acpi/events/evrgnini.c	Wed Nov 27 14:36:27 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: evrgnini- ACPI Address_space (Op_region) init
- *              $Revision: 63 $
+ *              $Revision: 64 $
  *
  *****************************************************************************/
 
@@ -268,6 +268,11 @@
 	if (ACPI_SUCCESS (status)) {
 		pci_id->bus = ACPI_LOWORD (temp);
 	}
+
+	/*
+	 * Complete this device's Pci_id
+	 */
+	acpi_os_derive_pci_id (node, region_obj->region.node, &pci_id);
 
 	*region_context = pci_id;
 	return_ACPI_STATUS (AE_OK);
diff -Nru a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h
--- a/drivers/acpi/include/acconfig.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/acpi/include/acconfig.h	Wed Nov 27 14:36:31 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acconfig.h - Global configuration constants
- *       $Revision: 118 $
+ *       $Revision: 119 $
  *
  *****************************************************************************/
 
@@ -54,7 +54,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20021115
+#define ACPI_CA_VERSION                 0x20021122
 
 /* Version of ACPI supported */
 
diff -Nru a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h
--- a/drivers/acpi/include/aclocal.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/acpi/include/aclocal.h	Wed Nov 27 14:36:31 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: aclocal.h - Internal data types used across the ACPI subsystem
- *       $Revision: 179 $
+ *       $Revision: 181 $
  *
  *****************************************************************************/
 
@@ -301,7 +301,6 @@
 
 typedef struct
 {
-	u8                      address_space_id;
 	acpi_generic_address    *block_address;
 	u16                     register_count;
 	u8                      block_base_number;
@@ -330,7 +329,7 @@
 
 typedef struct
 {
-	acpi_handle             method_handle;  /* Method handle for direct (fast) execution */
+	acpi_namespace_node     *method_node;   /* Method node for this GPE level */
 	acpi_gpe_handler        handler;        /* Address of handler, if any */
 	void                    *context;       /* Context to be passed to handler */
 	u8                      type;           /* Level or Edge */
diff -Nru a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h
--- a/drivers/acpi/include/acpiosxf.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/acpi/include/acpiosxf.h	Wed Nov 27 14:36:27 2002
@@ -246,6 +246,14 @@
 	acpi_integer            value,
 	u32                     width);
 
+/*
+ * Interim function needed for PCI IRQ routing
+ */
+void
+acpi_os_derive_pci_id(
+	acpi_handle	            rhandle,
+	acpi_handle             chandle,
+	acpi_pci_id	            **pci_id);
 
 /*
  * Miscellaneous
diff -Nru a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
--- a/drivers/acpi/namespace/nsxfobj.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/acpi/namespace/nsxfobj.c	Wed Nov 27 14:36:27 2002
@@ -141,7 +141,7 @@
 	*ret_handle =
 		acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_node (node));
 
-	/* Return exeption if parent is null */
+	/* Return exception if parent is null */
 
 	if (!acpi_ns_get_parent_node (node)) {
 		status = AE_NULL_ENTRY;
diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c
--- a/drivers/acpi/osl.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/acpi/osl.c	Wed Nov 27 14:36:31 2002
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <asm/io.h>
+#include "acpi_bus.h"
 #include "acpi.h"
 
 #ifdef CONFIG_ACPI_EFI
@@ -481,6 +482,44 @@
 						     pci_id->function),
 				     reg, size, value);
 	return (result ? AE_ERROR : AE_OK);
+}
+
+/* TODO: Rewrite this code!!! */
+void
+acpi_os_derive_pci_id (
+	acpi_handle     rhandle,        /* upper bound  */
+	acpi_handle     chandle,        /* current node */
+	acpi_pci_id     **id)
+{
+	acpi_handle     handle;
+	acpi_pci_id     *pci_id = *id;
+	acpi_status     status;
+	unsigned long   temp;
+	acpi_object_type type;
+	u8              tu8;
+
+	acpi_get_parent(chandle, &handle);
+	if (handle != rhandle) {
+		acpi_os_derive_pci_id(rhandle, handle, &pci_id);
+
+		status = acpi_get_type(handle, &type);
+		if ( (ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE) )
+			return;
+
+		status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp);
+		if (ACPI_SUCCESS(status)) {
+			pci_id->device  = ACPI_HIWORD (ACPI_LODWORD (temp));
+			pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp));
+
+			/* any nicer way to get bus number of bridge ? */
+			status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8);
+			if (ACPI_SUCCESS(status) && (tu8 & 0x7f) == 1) {
+				status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8);
+				if (ACPI_SUCCESS(status))
+					pci_id->bus = tu8;
+			}
+		}
+	}
 }
 
 #else /*!CONFIG_ACPI_PCI*/
diff -Nru a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
--- a/drivers/acpi/parser/psopcode.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/acpi/parser/psopcode.c	Wed Nov 27 14:36:28 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: psopcode - Parser/Interpreter opcode information table
- *              $Revision: 73 $
+ *              $Revision: 74 $
  *
  *****************************************************************************/
 
@@ -734,7 +734,7 @@
 acpi_ps_get_opcode_name (
 	u16                     opcode)
 {
-#ifdef ACPI_DISASSEMBLER
+#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
 
 	const acpi_opcode_info  *op;
 
diff -Nru a/drivers/acpi/power.c b/drivers/acpi/power.c
--- a/drivers/acpi/power.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/acpi/power.c	Wed Nov 27 14:36:30 2002
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/compatmac.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
@@ -48,6 +49,7 @@
 
 int acpi_power_add (struct acpi_device *device);
 int acpi_power_remove (struct acpi_device *device, int type);
+static int acpi_power_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_power_driver = {
 	.name =		ACPI_POWER_DRIVER_NAME,
@@ -71,6 +73,12 @@
 
 static struct list_head		acpi_power_resource_list;
 
+static struct file_operations acpi_power_fops = {
+	.open		= acpi_power_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 /* --------------------------------------------------------------------------
                              Power Resource Management
@@ -379,58 +387,45 @@
 
 struct proc_dir_entry		*acpi_power_dir = NULL;
 
-
-static int
-acpi_power_read_status (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_power_seq_show(struct seq_file *seq, void *offset)
 {
 	struct acpi_power_resource *resource = NULL;
-	char			*p = page;
-	int			len;
 
-	ACPI_FUNCTION_TRACE("acpi_power_read_status");
+	ACPI_FUNCTION_TRACE("acpi_power_seq_show");
 
-	if (!data || (off != 0))
-		goto end;
+	resource = (struct acpi_power_resource *)seq->private;
 
-	resource = (struct acpi_power_resource *) data;
+	if (!resource)
+		goto end;
 
-	p += sprintf(p, "state:                   ");
+	seq_puts(seq, "state:                   ");
 	switch (resource->state) {
 	case ACPI_POWER_RESOURCE_STATE_ON:
-		p += sprintf(p, "on\n");
+		seq_puts(seq, "on\n");
 		break;
 	case ACPI_POWER_RESOURCE_STATE_OFF:
-		p += sprintf(p, "off\n");
+		seq_puts(seq, "off\n");
 		break;
 	default:
-		p += sprintf(p, "unknown\n");
+		seq_puts(seq, "unknown\n");
 		break;
 	}
 
-	p += sprintf(p, "system level:            S%d\n",
-		resource->system_level);
-	p += sprintf(p, "order:                   %d\n",
-		resource->order);
-	p += sprintf(p, "reference count:         %d\n",
-		resource->references);
+	seq_printf(seq, "system level:            S%d\n"
+			"order:                   %d\n"
+			"reference count:         %d\n",
+			resource->system_level,
+			resource->order,
+			resource->references);
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
 }
 
+static int acpi_power_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_power_seq_show, PDE(inode)->data);
+}
 
 static int
 acpi_power_add_fs (
@@ -458,7 +453,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_POWER_FILE_STATUS));
 	else {
-		entry->read_proc = acpi_power_read_status;
+		entry->proc_fops = &acpi_power_fops;
 		entry->data = acpi_driver_data(device);
 	}
 
diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c
--- a/drivers/acpi/processor.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/acpi/processor.c	Wed Nov 27 14:36:31 2002
@@ -40,6 +40,7 @@
 #include <asm/delay.h>
 #include <linux/compatmac.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
@@ -90,6 +91,11 @@
 
 static int acpi_processor_add (struct acpi_device *device);
 static int acpi_processor_remove (struct acpi_device *device, int type);
+static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
+static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file);
+static int acpi_processor_power_open_fs(struct inode *inode, struct file *file);
+static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file);
+
 
 static struct acpi_driver acpi_processor_driver = {
 	.name =		ACPI_PROCESSOR_DRIVER_NAME,
@@ -224,6 +230,34 @@
 	}			piix4;
 };
 
+static struct file_operations acpi_processor_info_fops = {
+	.open 		= acpi_processor_info_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations acpi_processor_power_fops = {
+	.open 		= acpi_processor_power_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations acpi_processor_throttling_fops = {
+	.open 		= acpi_processor_throttling_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations acpi_processor_limit_fops = {
+	.open 		= acpi_processor_limit_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static struct acpi_processor	*processors[NR_CPUS];
 static struct acpi_processor_errata errata;
 static void (*pm_idle_save)(void) = NULL;
@@ -231,6 +265,13 @@
 #ifdef CONFIG_ACPI_PROCESSOR_PERF
 static unsigned int cpufreq_usage_count = 0;
 static struct cpufreq_driver *acpi_cpufreq_driver;
+static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
+static struct file_operations acpi_processor_perf_fops = {
+	.open 		= acpi_processor_perf_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 #endif
 
 
@@ -1884,174 +1925,132 @@
 
 struct proc_dir_entry		*acpi_processor_dir = NULL;
 
-static int
-acpi_processor_read_info (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_processor	*pr = (struct acpi_processor *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
 
-	ACPI_FUNCTION_TRACE("acpi_processor_read_info");
+	ACPI_FUNCTION_TRACE("acpi_processor_info_seq_show");
 
-	if (!pr || (off != 0))
+	if (!pr)
 		goto end;
 
-	p += sprintf(p, "processor id:            %d\n",
-		pr->id);
-
-	p += sprintf(p, "acpi id:                 %d\n",
-		pr->acpi_id);
-
-	p += sprintf(p, "bus mastering control:   %s\n",
-		pr->flags.bm_control ? "yes" : "no");
-
-	p += sprintf(p, "power management:        %s\n",
-		pr->flags.power ? "yes" : "no");
-
-	p += sprintf(p, "throttling control:      %s\n",
-		pr->flags.throttling ? "yes" : "no");
-
-	p += sprintf(p, "performance management:  %s\n",
-		pr->flags.performance ? "yes" : "no");
-
-	p += sprintf(p, "limit interface:         %s\n",
-		pr->flags.limit ? "yes" : "no");
+	seq_printf(seq, "processor id:            %d\n"
+			"acpi id:                 %d\n"
+			"bus mastering control:   %s\n"
+			"power management:        %s\n"
+			"throttling control:      %s\n"
+			"performance management:  %s\n"
+			"limit interface:         %s\n",
+			pr->id,
+			pr->acpi_id,
+			pr->flags.bm_control ? "yes" : "no",
+			pr->flags.power ? "yes" : "no",
+			pr->flags.throttling ? "yes" : "no",
+			pr->flags.performance ? "yes" : "no",
+			pr->flags.limit ? "yes" : "no");
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
 }
 
+static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_processor_info_seq_show,
+						PDE(inode)->data);
+}
 
-static int
-acpi_processor_read_power (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_processor	*pr = (struct acpi_processor *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
 	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_processor_read_power");
+	ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show");
 
-	if (!pr || (off != 0))
+	if (!pr)
 		goto end;
 
-	p += sprintf(p, "active state:            C%d\n",
-		pr->power.state);
-
-	p += sprintf(p, "default state:           C%d\n",
-		pr->power.default_state);
+	seq_printf(seq, "active state:            C%d\n"
+			"default state:           C%d\n"
+			"bus master activity:     %08x\n",
+			pr->power.state,
+			pr->power.default_state,
+			pr->power.bm_activity);
 
-	p += sprintf(p, "bus master activity:     %08x\n",
-		pr->power.bm_activity);
+	seq_puts(seq, "states:\n");
 
-	p += sprintf(p, "states:\n");
-
-	for (i=1; i<ACPI_C_STATE_COUNT; i++) {
-
-		p += sprintf(p, "   %cC%d:                  ", 
+	for (i = 1; i < ACPI_C_STATE_COUNT; i++) {
+		seq_printf(seq, "   %cC%d:                  ", 
 			(i == pr->power.state?'*':' '), i);
 
 		if (!pr->power.states[i].valid) {
-			p += sprintf(p, "<not supported>\n");
+			seq_puts(seq, "<not supported>\n");
 			continue;
 		}
 
 		if (pr->power.states[i].promotion.state)
-			p += sprintf(p, "promotion[C%d] ",
+			seq_printf(seq, "promotion[C%d] ",
 				pr->power.states[i].promotion.state);
 		else
-			p += sprintf(p, "promotion[--] ");
+			seq_puts(seq, "promotion[--] ");
 
 		if (pr->power.states[i].demotion.state)
-			p += sprintf(p, "demotion[C%d] ",
+			seq_printf(seq, "demotion[C%d] ",
 				pr->power.states[i].demotion.state);
 		else
-			p += sprintf(p, "demotion[--] ");
+			seq_puts(seq, "demotion[--] ");
 
-		p += sprintf(p, "latency[%03d] usage[%08d]\n",
+		seq_printf(seq, "latency[%03d] usage[%08d]\n",
 			pr->power.states[i].latency,
 			pr->power.states[i].usage);
 	}
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
+	return 0;
+}
 
-	return_VALUE(len);
+static int acpi_processor_power_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_processor_power_seq_show,
+						PDE(inode)->data);
 }
 
 #ifdef CONFIG_ACPI_PROCESSOR_PERF
-static int
-acpi_processor_read_performance (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_processor	*pr = (struct acpi_processor *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
 	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_processor_read_performance");
+	ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
 
-	if (!pr || (off != 0))
+	if (!pr)
 		goto end;
 
 	if (!pr->flags.performance) {
-		p += sprintf(p, "<not supported>\n");
+		seq_puts(seq, "<not supported>\n");
 		goto end;
 	}
 
-	p += sprintf(p, "state count:             %d\n",
-		pr->performance.state_count);
-
-	p += sprintf(p, "active state:            P%d\n",
-		pr->performance.state);
-
-	p += sprintf(p, "states:\n");
-
-	for (i=0; i<pr->performance.state_count; i++)
-		p += sprintf(p, "   %cP%d:                  %d MHz, %d mW, %d uS\n",
+	seq_printf(seq, "state count:             %d\n"
+			"active state:            P%d\n",
+			pr->performance.state_count,
+			pr->performance.state);
+
+	seq_puts(seq, "states:\n");
+	for (i = 0; i < pr->performance.state_count; i++)
+		seq_printf(seq, "   %cP%d:                  %d MHz, %d mW, %d uS\n",
 			(i == pr->performance.state?'*':' '), i,
 			(u32) pr->performance.states[i].core_frequency,
 			(u32) pr->performance.states[i].power,
 			(u32) pr->performance.states[i].transition_latency);
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
+	return 0;
+}
 
-	return_VALUE(len);
+static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_processor_perf_seq_show,
+						PDE(inode)->data);
 }
 
 static int
@@ -2091,63 +2090,49 @@
 }
 #endif
 
-
-static int
-acpi_processor_read_throttling (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_processor	*pr = (struct acpi_processor *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
 	int			i = 0;
 	int                     result = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_processor_read_throttling");
+	ACPI_FUNCTION_TRACE("acpi_processor_throttling_seq_show");
 
-	if (!pr || (off != 0))
+	if (!pr)
 		goto end;
 
 	if (!(pr->throttling.state_count > 0)) {
-		p += sprintf(p, "<not supported>\n");
+		seq_puts(seq, "<not supported>\n");
 		goto end;
 	}
 
 	result = acpi_processor_get_throttling(pr);
 
 	if (result) {
-		p += sprintf(p, "Could not determine current throttling state.\n");
+		seq_puts(seq, "Could not determine current throttling state.\n");
 		goto end;
 	}
 
-	p += sprintf(p, "state count:             %d\n",
-		pr->throttling.state_count);
-
-	p += sprintf(p, "active state:            T%d\n",
-		pr->throttling.state);
-
-	p += sprintf(p, "states:\n");
-
-	for (i=0; i<pr->throttling.state_count; i++)
-		p += sprintf(p, "   %cT%d:                  %02d%%\n",
+	seq_printf(seq, "state count:             %d\n"
+			"active state:            T%d\n",
+			pr->throttling.state_count,
+			pr->throttling.state);
+
+	seq_puts(seq, "states:\n");
+	for (i = 0; i < pr->throttling.state_count; i++)
+		seq_printf(seq, "   %cT%d:                  %02d%%\n",
 			(i == pr->throttling.state?'*':' '), i,
 			(pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0));
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
 }
 
+static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_processor_throttling_seq_show,
+						PDE(inode)->data);
+}
 
 static int
 acpi_processor_write_throttling (
@@ -2178,53 +2163,38 @@
 	return_VALUE(count);
 }
 
-
-static int
-acpi_processor_read_limit (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_processor	*pr = (struct acpi_processor *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_processor	*pr = (struct acpi_processor *)seq->private;
 
-	ACPI_FUNCTION_TRACE("acpi_processor_read_limit");
+	ACPI_FUNCTION_TRACE("acpi_processor_limit_seq_show");
 
-	if (!pr || (off != 0))
+	if (!pr)
 		goto end;
 
 	if (!pr->flags.limit) {
-		p += sprintf(p, "<not supported>\n");
+		seq_puts(seq, "<not supported>\n");
 		goto end;
 	}
 
-	p += sprintf(p, "active limit:            P%d:T%d\n",
-		pr->limit.state.px, pr->limit.state.tx);
-
-	p += sprintf(p, "platform limit:          P%d:T0\n",
-		pr->flags.performance?pr->performance.platform_limit:0);
-
-	p += sprintf(p, "user limit:              P%d:T%d\n",
-		pr->limit.user.px, pr->limit.user.tx);
-
-	p += sprintf(p, "thermal limit:           P%d:T%d\n",
-		pr->limit.thermal.px, pr->limit.thermal.tx);
+	seq_printf(seq, "active limit:            P%d:T%d\n"
+			"platform limit:          P%d:T0\n"
+			"user limit:              P%d:T%d\n"
+			"thermal limit:           P%d:T%d\n",
+			pr->limit.state.px, pr->limit.state.tx,
+			pr->flags.performance?pr->performance.platform_limit:0,
+			pr->limit.user.px, pr->limit.user.tx,
+			pr->limit.thermal.px, pr->limit.thermal.tx);
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
 }
 
+static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_processor_limit_seq_show,
+						PDE(inode)->data);
+}
 
 static int
 acpi_processor_write_limit (
@@ -2304,7 +2274,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_PROCESSOR_FILE_INFO));
 	else {
-		entry->read_proc = acpi_processor_read_info;
+		entry->proc_fops = &acpi_processor_info_fops;
 		entry->data = acpi_driver_data(device);
 	}
 
@@ -2316,7 +2286,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_PROCESSOR_FILE_POWER));
 	else {
-		entry->read_proc = acpi_processor_read_power;
+		entry->proc_fops = &acpi_processor_power_fops;
 		entry->data = acpi_driver_data(device);
 	}
 
@@ -2329,7 +2299,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_PROCESSOR_FILE_PERFORMANCE));
 	else {
-		entry->read_proc = acpi_processor_read_performance;
+		entry->proc_fops = &acpi_processor_perf_fops;
 		entry->write_proc = acpi_processor_write_performance;
 		entry->data = acpi_driver_data(device);
 	}
@@ -2343,7 +2313,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_PROCESSOR_FILE_THROTTLING));
 	else {
-		entry->read_proc = acpi_processor_read_throttling;
+		entry->proc_fops = &acpi_processor_throttling_fops;
 		entry->write_proc = acpi_processor_write_throttling;
 		entry->data = acpi_driver_data(device);
 	}
@@ -2356,7 +2326,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_PROCESSOR_FILE_LIMIT));
 	else {
-		entry->read_proc = acpi_processor_read_limit;
+		entry->proc_fops = &acpi_processor_limit_fops;
 		entry->write_proc = acpi_processor_write_limit;
 		entry->data = acpi_driver_data(device);
 	}
diff -Nru a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
--- a/drivers/acpi/sleep.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/acpi/sleep.c	Wed Nov 27 14:36:27 2002
@@ -15,6 +15,7 @@
 #include <linux/pm.h>
 #include <linux/device.h>
 #include <linux/suspend.h>
+#include <linux/seq_file.h>
 
 #include <asm/uaccess.h>
 #include <asm/acpi.h>
@@ -32,8 +33,25 @@
 #define ACPI_SYSTEM_FILE_SLEEP		"sleep"
 #define ACPI_SYSTEM_FILE_ALARM		"alarm"
 
+static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file);
+static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file);
+
 static u8 sleep_states[ACPI_S_STATE_COUNT];
 
+static struct file_operations acpi_system_sleep_fops = {
+	.open		= acpi_system_sleep_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations acpi_system_alarm_fops = {
+	.open		= acpi_system_alarm_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static void
 acpi_power_off (void)
 {
@@ -271,43 +289,26 @@
 	return status;
 }
 
-
-static int
-acpi_system_read_sleep (
-        char                    *page,
-        char                    **start,
-        off_t                   off,
-        int                     count,
-        int                     *eof,
-        void                    *data)
+static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
 {
-	char			*p = page;
-	int			size;
 	int			i;
 
-	ACPI_FUNCTION_TRACE("acpi_system_read_sleep");
-
-	if (off != 0)
-		goto end;
+	ACPI_FUNCTION_TRACE("acpi_system_sleep_seq_show");
 
 	for (i = 0; i <= ACPI_STATE_S5; i++) {
 		if (sleep_states[i])
-			p += sprintf(p,"S%d ", i);
+			seq_printf(seq,"S%d ", i);
 	}
 
-	p += sprintf(p, "\n");
-
-end:
-	size = (p - page);
-	if (size <= off+count) *eof = 1;
-	*start = page + off;
-	size -= off;
-	if (size>count) size = count;
-	if (size<0) size = 0;
+	seq_puts(seq, "\n");
 
-	return_VALUE(size);
+	return 0;
 }
 
+static int acpi_system_sleep_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data);
+}
 
 static int
 acpi_system_write_sleep (
@@ -349,25 +350,12 @@
 	return_VALUE(count);
 }
 
-
-static int
-acpi_system_read_alarm (
-	char                    *page,
-	char                    **start,
-	off_t                   off,
-	int                     count,
-	int                     *eof,
-	void                    *context)
+static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
 {
-	char			*p = page;
-	int			size = 0;
 	u32			sec, min, hr;
 	u32			day, mo, yr;
 
-	ACPI_FUNCTION_TRACE("acpi_system_read_alarm");
-
-	if (off != 0)
-		goto end;
+	ACPI_FUNCTION_TRACE("acpi_system_alarm_seq_show");
 
 	spin_lock(&rtc_lock);
 
@@ -427,21 +415,19 @@
 	yr += 2000;
 #endif
 
-	p += sprintf(p,"%4.4u-", yr);
-	p += (mo > 12)  ? sprintf(p, "**-")  : sprintf(p, "%2.2u-", mo);
-	p += (day > 31) ? sprintf(p, "** ")  : sprintf(p, "%2.2u ", day);
-	p += (hr > 23)  ? sprintf(p, "**:")  : sprintf(p, "%2.2u:", hr);
-	p += (min > 59) ? sprintf(p, "**:")  : sprintf(p, "%2.2u:", min);
-	p += (sec > 59) ? sprintf(p, "**\n") : sprintf(p, "%2.2u\n", sec);
-
- end:
-	size = p - page;
-	if (size < count) *eof = 1;
-	else if (size > count) size = count;
-	if (size < 0) size = 0;
-	*start = page;
+	seq_printf(seq,"%4.4u-", yr);
+	(mo > 12)  ? seq_puts(seq, "**-")  : seq_printf(seq, "%2.2u-", mo);
+	(day > 31) ? seq_puts(seq, "** ")  : seq_printf(seq, "%2.2u ", day);
+	(hr > 23)  ? seq_puts(seq, "**:")  : seq_printf(seq, "%2.2u:", hr);
+	(min > 59) ? seq_puts(seq, "**:")  : seq_printf(seq, "%2.2u:", min);
+	(sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec);
 
-	return_VALUE(size);
+	return 0;
+}
+
+static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_system_alarm_seq_show, PDE(inode)->data);
 }
 
 
@@ -687,7 +673,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_SYSTEM_FILE_SLEEP));
 	else {
-		entry->read_proc = acpi_system_read_sleep;
+		entry->proc_fops = &acpi_system_sleep_fops;
 		entry->write_proc = acpi_system_write_sleep;
 	}
 
@@ -699,7 +685,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_SYSTEM_FILE_ALARM));
 	else {
-		entry->read_proc = acpi_system_read_alarm;
+		entry->proc_fops = &acpi_system_alarm_fops;
 		entry->write_proc = acpi_system_write_alarm;
 	}
 
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/acpi/thermal.c	Wed Nov 27 14:36:31 2002
@@ -39,6 +39,7 @@
 #include <linux/proc_fs.h>
 #include <linux/sched.h>
 #include <linux/kmod.h>
+#include <linux/seq_file.h>
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
@@ -79,6 +80,11 @@
 
 static int acpi_thermal_add (struct acpi_device *device);
 static int acpi_thermal_remove (struct acpi_device *device, int type);
+static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
+static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
+static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
+static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
+static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_thermal_driver = {
 	.name =		ACPI_THERMAL_DRIVER_NAME,
@@ -157,6 +163,40 @@
 	struct timer_list	timer;
 };
 
+static struct file_operations acpi_thermal_state_fops = {
+	.open		= acpi_thermal_state_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations acpi_thermal_temp_fops = {
+	.open		= acpi_thermal_temp_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations acpi_thermal_trip_fops = {
+	.open		= acpi_thermal_trip_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations acpi_thermal_cooling_fops = {
+	.open		= acpi_thermal_cooling_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations acpi_thermal_polling_fops = {
+	.open		= acpi_thermal_polling_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 /* --------------------------------------------------------------------------
                              Thermal Zone Management
@@ -720,154 +760,119 @@
 
 struct proc_dir_entry		*acpi_thermal_dir = NULL;
 
-
-static int
-acpi_thermal_read_state (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_thermal	*tz = (struct acpi_thermal *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_thermal	*tz = (struct acpi_thermal *)seq->private;
 
-	ACPI_FUNCTION_TRACE("acpi_thermal_read_state");
+	ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show");
 
-	if (!tz || (off != 0))
+	if (!tz)
 		goto end;
 
-	p += sprintf(p, "state:                   ");
+	seq_puts(seq, "state:                   ");
 
 	if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active)
-		p += sprintf(p, "ok\n");
+		seq_puts(seq, "ok\n");
 	else {
 		if (tz->state.critical)
-			p += sprintf(p, "critical ");
+			seq_puts(seq, "critical ");
 		if (tz->state.hot)
-			p += sprintf(p, "hot ");
+			seq_puts(seq, "hot ");
 		if (tz->state.passive)
-			p += sprintf(p, "passive ");
+			seq_puts(seq, "passive ");
 		if (tz->state.active)
-			p += sprintf(p, "active[%d]", tz->state.active_index);
-		p += sprintf(p, "\n");
+			seq_printf(seq, "active[%d]", tz->state.active_index);
+		seq_puts(seq, "\n");
 	}
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
+	return 0;
+}
 
-	return_VALUE(len);
+static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
 }
 
 
-static int
-acpi_thermal_read_temperature (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
 {
 	int			result = 0;
-	struct acpi_thermal	*tz = (struct acpi_thermal *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_thermal	*tz = (struct acpi_thermal *)seq->private;
 
-	ACPI_FUNCTION_TRACE("acpi_thermal_read_temperature");
+	ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show");
 
-	if (!tz || (off != 0))
+	if (!tz)
 		goto end;
 
 	result = acpi_thermal_get_temperature(tz);
 	if (result)
 		goto end;
 
-	p += sprintf(p, "temperature:             %ld C\n", 
+	seq_printf(seq, "temperature:             %ld C\n", 
 		KELVIN_TO_CELSIUS(tz->temperature));
-	
+
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
+	return 0;
+}
 
-	return_VALUE(len);
+static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
 }
 
 
-static int
-acpi_thermal_read_trip_points (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_thermal	*tz = (struct acpi_thermal *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_thermal	*tz = (struct acpi_thermal *)seq->private;
 	int			i = 0;
 	int			j = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_thermal_read_trip_points");
+	ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show");
 
-	if (!tz || (off != 0))
+	if (!tz)
 		goto end;
 
 	if (tz->trips.critical.flags.valid)
-		p += sprintf(p, "critical (S5):           %ld C\n",
+		seq_printf(seq, "critical (S5):           %ld C\n",
 			KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
 
 	if (tz->trips.hot.flags.valid)
-		p += sprintf(p, "hot (S4):                %ld C\n",
+		seq_printf(seq, "hot (S4):                %ld C\n",
 			KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
 
 	if (tz->trips.passive.flags.valid) {
-		p += sprintf(p, "passive:                 %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
+		seq_printf(seq, "passive:                 %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
 			KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
 			tz->trips.passive.tc1,
 			tz->trips.passive.tc2, 
 			tz->trips.passive.tsp);
 		for (j=0; j<tz->trips.passive.devices.count; j++) {
 
-			p += sprintf(p, "0x%p ", tz->trips.passive.devices.handles[j]);
+			seq_printf(seq, "0x%p ", tz->trips.passive.devices.handles[j]);
 		}
-		p += sprintf(p, "\n");
+		seq_puts(seq, "\n");
 	}
 
-	for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
+	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
 		if (!(tz->trips.active[i].flags.valid))
 			break;
-		p += sprintf(p, "active[%d]:               %ld C: devices=",
+		seq_printf(seq, "active[%d]:               %ld C: devices=",
 			i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
-		for (j=0; j<tz->trips.active[i].devices.count; j++) 
-			p += sprintf(p, "0x%p ",
+		for (j = 0; j < tz->trips.active[i].devices.count; j++) 
+			seq_printf(seq, "0x%p ",
 				tz->trips.active[i].devices.handles[j]);
-		p += sprintf(p, "\n");
+		seq_puts(seq, "\n");
 	}
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
 }
 
+static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
+}
 
 static int
 acpi_thermal_write_trip_points (
@@ -909,43 +914,32 @@
 }
 
 
-static int
-acpi_thermal_read_cooling_mode (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_thermal	*tz = (struct acpi_thermal *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_thermal	*tz = (struct acpi_thermal *)seq->private;
 
-	ACPI_FUNCTION_TRACE("acpi_thermal_read_cooling_mode");
+	ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show");
 
-	if (!tz || (off != 0))
+	if (!tz)
 		goto end;
 
 	if (!tz->flags.cooling_mode) {
-		p += sprintf(p, "<not supported>\n");
+		seq_puts(seq, "<not supported>\n");
 		goto end;
 	}
 
-	p += sprintf(p, "cooling mode:            %s\n",
+	seq_printf(seq, "cooling mode:            %s\n",
 		tz->cooling_mode?"passive":"active");
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
 }
 
+static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_thermal_cooling_seq_show,
+							PDE(inode)->data);
+}
 
 static int
 acpi_thermal_write_cooling_mode (
@@ -980,43 +974,32 @@
 }
 
 
-static int
-acpi_thermal_read_polling (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
+static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
 {
-	struct acpi_thermal	*tz = (struct acpi_thermal *) data;
-	char			*p = page;
-	int			len = 0;
+	struct acpi_thermal	*tz = (struct acpi_thermal *)seq->private;
 
-	ACPI_FUNCTION_TRACE("acpi_thermal_read_polling");
+	ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show");
 
-	if (!tz || (off != 0))
+	if (!tz)
 		goto end;
 
 	if (!tz->polling_frequency) {
-		p += sprintf(p, "<polling disabled>\n");
+		seq_puts(seq, "<polling disabled>\n");
 		goto end;
 	}
 
-	p += sprintf(p, "polling frequency:       %lu seconds\n",
+	seq_printf(seq, "polling frequency:       %lu seconds\n",
 		(tz->polling_frequency / 10));
 
 end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-
-	return_VALUE(len);
+	return 0;
 }
 
+static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_thermal_polling_seq_show,
+							PDE(inode)->data);
+}
 
 static int
 acpi_thermal_write_polling (
@@ -1075,7 +1058,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_THERMAL_FILE_STATE));
 	else {
-		entry->read_proc = acpi_thermal_read_state;
+		entry->proc_fops = &acpi_thermal_state_fops;
 		entry->data = acpi_driver_data(device);
 	}
 
@@ -1087,7 +1070,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_THERMAL_FILE_TEMPERATURE));
 	else {
-		entry->read_proc = acpi_thermal_read_temperature;
+		entry->proc_fops = &acpi_thermal_temp_fops;
 		entry->data = acpi_driver_data(device);
 	}
 
@@ -1099,7 +1082,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_THERMAL_FILE_POLLING_FREQ));
 	else {
-		entry->read_proc = acpi_thermal_read_trip_points;
+		entry->proc_fops = &acpi_thermal_trip_fops;
 		entry->write_proc = acpi_thermal_write_trip_points;
 		entry->data = acpi_driver_data(device);
 	}
@@ -1112,7 +1095,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_THERMAL_FILE_COOLING_MODE));
 	else {
-		entry->read_proc = acpi_thermal_read_cooling_mode;
+		entry->proc_fops = &acpi_thermal_cooling_fops;
 		entry->write_proc = acpi_thermal_write_cooling_mode;
 		entry->data = acpi_driver_data(device);
 	}
@@ -1125,7 +1108,7 @@
 			"Unable to create '%s' fs entry\n",
 			ACPI_THERMAL_FILE_POLLING_FREQ));
 	else {
-		entry->read_proc = acpi_thermal_read_polling;
+		entry->proc_fops = &acpi_thermal_polling_fops;
 		entry->write_proc = acpi_thermal_write_polling;
 		entry->data = acpi_driver_data(device);
 	}
diff -Nru a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
--- a/drivers/acpi/toshiba_acpi.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/acpi/toshiba_acpi.c	Wed Nov 27 14:36:27 2002
@@ -41,6 +41,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/version.h>
 
 #include <acconfig.h>
@@ -100,6 +101,47 @@
 #define HCI_VIDEO_OUT_CRT		0x2
 #define HCI_VIDEO_OUT_TV		0x4
 
+static int toshiba_lcd_open_fs(struct inode *inode, struct file *file);
+static int toshiba_video_open_fs(struct inode *inode, struct file *file);
+static int toshiba_fan_open_fs(struct inode *inode, struct file *file);
+static int toshiba_keys_open_fs(struct inode *inode, struct file *file);
+static int toshiba_version_open_fs(struct inode *inode, struct file *file);
+
+static struct file_operations toshiba_lcd_fops = {
+	.open		= toshiba_lcd_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations toshiba_video_fops = {
+	.open		= toshiba_video_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations toshiba_fan_fops = {
+	.open		= toshiba_fan_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations toshiba_keys_fops = {
+	.open		= toshiba_keys_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct file_operations toshiba_version_fops = {
+	.open		= toshiba_version_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 /* utility
  */
 
@@ -126,22 +168,6 @@
 	return result;
 }
 
-/* This is the common code at the end of every proc read handler.  I don't
- * understand it yet.
- */
-static int
-end_proc_read(const char* p, char* page, off_t off, int count,
-	char** start, int* eof)
-{
-	int len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-	return len;
-}
-
 /* acpi interface wrappers
  */
 
@@ -259,29 +285,27 @@
 /* proc file handlers
  */
 
-static int
-proc_read_lcd(char* page, char** start, off_t off, int count, int* eof,
-	void* context)
+static int toshiba_lcd_seq_show(struct seq_file *seq, void *offset)
 {
-	char* p = page;
 	u32 hci_result;
 	u32 value;
 
-	if (off != 0) goto end;
-
 	hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
 	if (hci_result == HCI_SUCCESS) {
 		value = value >> HCI_LCD_BRIGHTNESS_SHIFT;
-		p += sprintf(p, "brightness:              %d\n", value);
-		p += sprintf(p, "brightness_levels:       %d\n",
-			HCI_LCD_BRIGHTNESS_LEVELS);
-	} else {
-		p += sprintf(p, "ERROR\n");
-		goto end;
-	}
+		seq_printf(seq, "brightness:              %d\n"
+				"brightness_levels:       %d\n",
+				value,
+				HCI_LCD_BRIGHTNESS_LEVELS);
+	} else
+		seq_puts(seq, "ERROR\n");
 
-end:
-	return end_proc_read(p, page, off, count, start, eof);
+	return 0;
+}
+
+static int toshiba_lcd_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, toshiba_lcd_seq_show, NULL);
 }
 
 static int
@@ -306,31 +330,31 @@
 	return count;
 }
 
-static int
-proc_read_video(char* page, char** start, off_t off, int count, int* eof,
-	void* context)
+static int toshiba_video_seq_show(struct seq_file *seq, void *offset)
 {
-	char* p = page;
 	u32 hci_result;
 	u32 value;
 
-	if (off != 0) goto end;
-
 	hci_read1(HCI_VIDEO_OUT, &value, &hci_result);
 	if (hci_result == HCI_SUCCESS) {
 		int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
 		int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
 		int is_tv  = (value & HCI_VIDEO_OUT_TV ) ? 1 : 0;
-		p += sprintf(p, "lcd_out:                 %d\n", is_lcd);
-		p += sprintf(p, "crt_out:                 %d\n", is_crt);
-		p += sprintf(p, "tv_out:                  %d\n", is_tv);
-	} else {
-		p += sprintf(p, "ERROR\n");
-		goto end;
-	}
+		seq_printf(seq, "lcd_out:                 %d\n"
+				"crt_out:                 %d\n"
+				"tv_out:                  %d\n",
+				is_lcd,
+				is_crt,
+				is_tv);
+	} else
+		seq_puts(seq, "ERROR\n");
 
-end:
-	return end_proc_read(p, page, off, count, start, eof);
+	return 0;
+}
+
+static int toshiba_video_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, toshiba_video_seq_show, NULL);
 }
 
 static int
@@ -376,27 +400,26 @@
 	return count;
 }
 
-static int
-proc_read_fan(char* page, char** start, off_t off, int count, int* eof,
-	void* context)
+static int toshiba_fan_seq_show(struct seq_file *seq, void *offset)
 {
-	char* p = page;
 	u32 hci_result;
 	u32 value;
 
-	if (off != 0) goto end;
-
 	hci_read1(HCI_FAN, &value, &hci_result);
 	if (hci_result == HCI_SUCCESS) {
-		p += sprintf(p, "running:                 %d\n", (value > 0));
-		p += sprintf(p, "force_on:                %d\n", force_fan);
-	} else {
-		p += sprintf(p, "ERROR\n");
-		goto end;
-	}
+		seq_printf(seq, "running:                 %d\n"
+				"force_on:                %d\n",
+				(value > 0),
+				force_fan);
+	} else
+		seq_puts(seq, "ERROR\n");
 
-end:
-	return end_proc_read(p, page, off, count, start, eof);
+	return 0;
+}
+
+static int toshiba_fan_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, toshiba_fan_seq_show, NULL);
 }
 
 static int
@@ -420,16 +443,11 @@
 	return count;
 }
 
-static int
-proc_read_keys(char* page, char** start, off_t off, int count, int* eof,
-	void* context)
+static int toshiba_keys_seq_show(struct seq_file *seq, void *offset)
 {
-	char* p = page;
 	u32 hci_result;
 	u32 value;
 
-	if (off != 0) goto end;
-
 	if (!key_event_valid) {
 		hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
 		if (hci_result == HCI_SUCCESS) {
@@ -438,16 +456,23 @@
 		} else if (hci_result == HCI_EMPTY) {
 			/* better luck next time */
 		} else {
-			p += sprintf(p, "ERROR\n");
+			seq_puts(seq, "ERROR\n");
 			goto end;
 		}
 	}
 
-	p += sprintf(p, "hotkey_ready:            %d\n", key_event_valid);
-	p += sprintf(p, "hotkey:                  0x%04x\n", last_key_event);
+	seq_printf(seq, "hotkey_ready:            %d\n"
+			"hotkey:                  0x%04x\n",
+			key_event_valid,
+			last_key_event);
 
 end:
-	return end_proc_read(p, page, off, count, start, eof);
+	return 0;
+}
+
+static int toshiba_keys_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, toshiba_keys_seq_show, NULL);
 }
 
 static int
@@ -466,20 +491,19 @@
 	return count;
 }
 
-static int
-proc_read_version(char* page, char** start, off_t off, int count, int* eof,
-	void* context)
+static int toshiba_version_seq_show(struct seq_file *seq, void *offset)
 {
-	char* p = page;
+	seq_printf(seq, "driver:                  %s\n"
+			"proc_interface:          %d\n",
+			TOSHIBA_ACPI_VERSION,
+			PROC_INTERFACE_VERSION);
 
-	if (off != 0) goto end;
-
-	p += sprintf(p, "driver:                  %s\n", TOSHIBA_ACPI_VERSION);
-	p += sprintf(p, "proc_interface:          %d\n",
-		PROC_INTERFACE_VERSION);
+	return 0;
+}
 
-end:
-	return end_proc_read(p, page, off, count, start, eof);
+static int toshiba_version_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, toshiba_version_seq_show, NULL);
 }
 
 /* proc and module init
@@ -490,24 +514,38 @@
 {
 	struct proc_dir_entry* proc;
 
-	proc = create_proc_read_entry(PROC_LCD, S_IFREG | S_IRUGO | S_IWUSR,
-		toshiba_proc_dir, proc_read_lcd, 0);
-	if (proc) proc->write_proc = proc_write_lcd;
-
-	proc = create_proc_read_entry(PROC_VIDEO, S_IFREG | S_IRUGO | S_IWUSR,
-		toshiba_proc_dir, proc_read_video, 0);
-	if (proc) proc->write_proc = proc_write_video;
-
-	proc = create_proc_read_entry(PROC_FAN, S_IFREG | S_IRUGO | S_IWUSR,
-		toshiba_proc_dir, proc_read_fan, 0);
-	if (proc) proc->write_proc = proc_write_fan;
-
-	proc = create_proc_read_entry(PROC_KEYS, S_IFREG | S_IRUGO | S_IWUSR,
-		toshiba_proc_dir, proc_read_keys, 0);
-	if (proc) proc->write_proc = proc_write_keys;
+	proc = create_proc_entry(PROC_LCD, S_IFREG | S_IRUGO | S_IWUSR,
+		toshiba_proc_dir);
+	if (proc) {
+		proc->proc_fops = &toshiba_lcd_fops;
+		proc->write_proc = proc_write_lcd;
+	}
+
+	proc = create_proc_entry(PROC_VIDEO, S_IFREG | S_IRUGO | S_IWUSR,
+		toshiba_proc_dir);
+	if (proc) {
+		proc->proc_fops = &toshiba_video_fops;
+		proc->write_proc = proc_write_video;
+	}
+
+	proc = create_proc_entry(PROC_FAN, S_IFREG | S_IRUGO | S_IWUSR,
+		toshiba_proc_dir);
+	if (proc) {
+		proc->proc_fops = &toshiba_fan_fops;
+		proc->write_proc = proc_write_fan;
+	}
+
+	proc = create_proc_entry(PROC_KEYS, S_IFREG | S_IRUGO | S_IWUSR,
+		toshiba_proc_dir);
+	if (proc) {
+		proc->proc_fops = &toshiba_keys_fops;
+		proc->write_proc = proc_write_keys;
+	}
 
-	proc = create_proc_read_entry(PROC_VERSION, S_IFREG | S_IRUGO | S_IWUSR,
-		toshiba_proc_dir, proc_read_version, 0);
+	proc = create_proc_entry(PROC_VERSION, S_IFREG | S_IRUGO | S_IWUSR,
+		toshiba_proc_dir);
+	if (proc)
+		proc->proc_fops = &toshiba_version_fops;
 
 	return(AE_OK);
 }
diff -Nru a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
--- a/drivers/acpi/utilities/utcopy.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/acpi/utilities/utcopy.c	Wed Nov 27 14:36:30 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: utcopy - Internal to external object translation utilities
- *              $Revision: 105 $
+ *              $Revision: 106 $
  *
  *****************************************************************************/
 
@@ -419,7 +419,8 @@
 
 	case ACPI_TYPE_STRING:
 
-		internal_object->string.pointer = ACPI_MEM_CALLOCATE ((ACPI_SIZE) external_object->string.length + 1);
+		internal_object->string.pointer =
+			ACPI_MEM_CALLOCATE ((ACPI_SIZE) external_object->string.length + 1);
 		if (!internal_object->string.pointer) {
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
@@ -434,7 +435,8 @@
 
 	case ACPI_TYPE_BUFFER:
 
-		internal_object->buffer.pointer = ACPI_MEM_CALLOCATE (external_object->buffer.length);
+		internal_object->buffer.pointer =
+			ACPI_MEM_CALLOCATE (external_object->buffer.length);
 		if (!internal_object->buffer.pointer) {
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
@@ -471,10 +473,10 @@
  * FUNCTION:    Acpi_ut_copy_epackage_to_ipackage
  *
  * PARAMETERS:  *Internal_object   - Pointer to the object we are returning
- *              *Buffer         - Where the object is returned
- *              *Space_used     - Where the length of the object is returned
+ *              *Buffer            - Where the object is returned
+ *              *Space_used        - Where the length of the object is returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: This function is called to place a package object in a user
  *              buffer.  A package object by definition contains other objects.
@@ -607,7 +609,8 @@
 
 	/* Copy the entire source object over the destination object*/
 
-	ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc, sizeof (acpi_operand_object));
+	ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc,
+			  sizeof (acpi_operand_object));
 
 	/* Restore the saved fields */
 
@@ -687,26 +690,36 @@
 			   &state->pkg.dest_object->package.elements[this_index];
 
 	switch (object_type) {
-	case 0:
+	case ACPI_COPY_TYPE_SIMPLE:
 
-		/*
-		 * This is a simple object, just copy it
-		 */
-		target_object = acpi_ut_create_internal_object (ACPI_GET_OBJECT_TYPE (source_object));
-		if (!target_object) {
-			return (AE_NO_MEMORY);
-		}
+		/* A null source object indicates a (legal) null package element */
 
-		status = acpi_ut_copy_simple_object (source_object, target_object);
-		if (ACPI_FAILURE (status)) {
-			return (status);
+		if (source_object) {
+			/*
+			 * This is a simple object, just copy it
+			 */
+			target_object = acpi_ut_create_internal_object (
+					   ACPI_GET_OBJECT_TYPE (source_object));
+			if (!target_object) {
+				return (AE_NO_MEMORY);
+			}
+
+			status = acpi_ut_copy_simple_object (source_object, target_object);
+			if (ACPI_FAILURE (status)) {
+				return (status);
+			}
+
+			*this_target_ptr = target_object;
 		}
+		else {
+			/* Pass through a null element */
 
-		*this_target_ptr = target_object;
+			*this_target_ptr = NULL;
+		}
 		break;
 
 
-	case 1:
+	case ACPI_COPY_TYPE_PACKAGE:
 
 		/*
 		 * This object is a package - go down another nesting level
@@ -719,6 +732,17 @@
 
 		target_object->package.count = source_object->package.count;
 		target_object->common.flags = source_object->common.flags;
+
+		/*
+		 * Create the object array
+		 */
+		target_object->package.elements =
+			ACPI_MEM_CALLOCATE (((ACPI_SIZE) source_object->package.count + 1) *
+					 sizeof (void *));
+		if (!target_object->package.elements) {
+			ACPI_MEM_FREE (target_object);
+			return (AE_NO_MEMORY);
+		}
 
 		/*
 		 * Pass the new package object back to the package walk routine
diff -Nru a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
--- a/drivers/acpi/utilities/utmisc.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/acpi/utilities/utmisc.c	Wed Nov 27 14:36:27 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: utmisc - common utility procedures
- *              $Revision: 86 $
+ *              $Revision: 87 $
  *
  ******************************************************************************/
 
@@ -475,7 +475,6 @@
 		string++;
 	}
 
-
 	return (src_string);
 }
 
@@ -575,7 +574,6 @@
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-
 	if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) {
 		status = acpi_os_create_semaphore (1, 1,
 				  &acpi_gbl_acpi_mutex_info[mutex_id].mutex);
@@ -613,7 +611,6 @@
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-
 	status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex);
 
 	acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL;
@@ -651,7 +648,6 @@
 		return (AE_BAD_PARAMETER);
 	}
 
-
 	this_thread_id = acpi_os_get_thread_id ();
 
 	/*
@@ -679,7 +675,6 @@
 		}
 	}
 
-
 	ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
 			 "Thread %X attempting to acquire Mutex [%s]\n",
 			 this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
@@ -693,7 +688,6 @@
 		acpi_gbl_acpi_mutex_info[mutex_id].use_count++;
 		acpi_gbl_acpi_mutex_info[mutex_id].owner_id = this_thread_id;
 	}
-
 	else {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not acquire Mutex [%s] %s\n",
 				 this_thread_id, acpi_ut_get_mutex_name (mutex_id),
@@ -737,7 +731,6 @@
 		return (AE_BAD_PARAMETER);
 	}
 
-
 	/*
 	 * Mutex must be acquired in order to release it!
 	 */
@@ -749,7 +742,6 @@
 		return (AE_NOT_ACQUIRED);
 	}
 
-
 	/*
 	 * Deadlock prevention.  Check if this thread owns any mutexes of value
 	 * greater than this one.  If so, the thread has violated the mutex
@@ -770,7 +762,6 @@
 		}
 	}
 
-
 	/* Mark unlocked FIRST */
 
 	acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;
@@ -828,7 +819,6 @@
 		return (AE_NO_MEMORY);
 	}
 
-
 	acpi_ut_push_generic_state (state_list, state);
 	return (AE_OK);
 }
@@ -866,7 +856,6 @@
 		return (AE_NO_MEMORY);
 	}
 
-
 	acpi_ut_push_generic_state (state_list, state);
 	return (AE_OK);
 }
@@ -1129,7 +1118,6 @@
 		return_PTR (NULL);
 	}
 
-
 	/* Init fields specific to the control struct */
 
 	state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
@@ -1224,6 +1212,8 @@
 	}
 
 	while (state) {
+		/* Get one element of the package */
+
 		this_index    = state->pkg.index;
 		this_source_obj = (acpi_operand_object *)
 				  state->pkg.source_object->package.elements[this_index];
@@ -1323,6 +1313,7 @@
 {
 	u32                     i;
 	signed char             sum = 0;
+
 
 	for (i = 0; i < length; i++) {
 		sum = (signed char) (sum + buffer[i]);
diff -Nru a/drivers/base/base.h b/drivers/base/base.h
--- a/drivers/base/base.h	Wed Nov 27 14:36:29 2002
+++ b/drivers/base/base.h	Wed Nov 27 14:36:29 2002
@@ -34,7 +34,7 @@
 {
 	return 0;
 }
-static int class_hotplug(struct device *dev, const char *action)
+static inline int class_hotplug(struct device *dev, const char *action)
 {
 	return 0;
 }
diff -Nru a/drivers/base/hotplug.c b/drivers/base/hotplug.c
--- a/drivers/base/hotplug.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/base/hotplug.c	Wed Nov 27 14:36:27 2002
@@ -35,6 +35,8 @@
 #define BUFFER_SIZE	1024	/* should be enough memory for the env */
 #define NUM_ENVP	32	/* number of env pointers */
 
+static char prefix [] = "devices";	/* /sys/devices/... */
+
 static int do_hotplug (struct device *dev, char *argv1, const char *action,
 			int (* hotplug) (struct device *, char **, int, char *, int))
 {
@@ -72,7 +74,7 @@
 	}
 
 	dev_length = get_devpath_length (dev);
-	dev_length += strlen("root");
+	dev_length += strlen(prefix);
 	dev_path = kmalloc (dev_length, GFP_KERNEL);
 	if (!dev_path) {
 		kfree (buffer);
@@ -80,7 +82,7 @@
 		return -ENOMEM;
 	}
 	memset (dev_path, 0x00, dev_length);
-	strcpy (dev_path, "root");
+	strcpy (dev_path, prefix);
 	fill_devpath (dev, dev_path, dev_length);
 
 	argv [0] = hotplug_path;
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/block/DAC960.c	Wed Nov 27 14:36:31 2002
@@ -19,8 +19,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.4.11"
-#define DAC960_DriverDate			"11 October 2001"
+#define DAC960_DriverVersion			"2.5.47"
+#define DAC960_DriverDate			"14 November 2002"
 
 
 #include <linux/version.h>
@@ -56,16 +56,6 @@
 static int
   DAC960_ControllerCount =			0;
 
-
-/*
-  DAC960_ActiveControllerCount is the number of active DAC960 Controllers
-  detected.
-*/
-
-static int
-  DAC960_ActiveControllerCount =		0;
-
-
 /*
   DAC960_Controllers is an array of pointers to the DAC960 Controller
   structures.
@@ -82,11 +72,11 @@
 */
 
 static struct block_device_operations DAC960_BlockDeviceOperations = {
-	.owner		= THIS_MODULE,
-	.open		= DAC960_Open,
-	.release	= DAC960_Release,
-	.ioctl		= DAC960_IOCTL,
-	.revalidate_disk= DAC960_revalidate,
+	.owner		=THIS_MODULE,
+	.open		=DAC960_Open,
+	.release	=DAC960_Release,
+	.ioctl		=DAC960_IOCTL,
+	.revalidate_disk=DAC960_revalidate,
 };
 
 
@@ -99,14 +89,6 @@
 
 
 /*
-  DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver.
-*/
-
-static NotifierBlock_T
-  DAC960_NotifierBlock =    { DAC960_Notifier, NULL, 0 };
-
-
-/*
   DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name,
   Copyright Notice, and Electronic Mail Address.
 */
@@ -144,6 +126,54 @@
   return false;
 }
 
+/*
+  init_dma_loaf() and slice_dma_loaf() are helper functions for
+  aggregating the dma-mapped memory for a well-known collection of
+  data structures that are of different lengths.
+
+  These routines don't guarantee any alignment.  The caller must
+  include any space needed for alignment in the sizes of the structures
+  that are passed in.
+ */
+
+static boolean init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf,
+								 size_t len)
+{
+	void *cpu_addr;
+	dma_addr_t dma_handle;
+
+	cpu_addr = pci_alloc_consistent(dev, len, &dma_handle);
+	if (cpu_addr == NULL)
+		return false;
+	
+	loaf->cpu_free = loaf->cpu_base = cpu_addr;
+	loaf->dma_free =loaf->dma_base = dma_handle;
+	loaf->length = len;
+	memset(cpu_addr, 0, len);
+	return true;
+}
+
+static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len,
+					dma_addr_t *dma_handle)
+{
+	void *cpu_end = loaf->cpu_free + len;
+	void *cpu_addr = loaf->cpu_free;
+
+	if (cpu_end > loaf->cpu_base + loaf->length)
+		BUG();
+	*dma_handle = loaf->dma_free;
+	loaf->cpu_free = cpu_end;
+	loaf->dma_free += len;
+	return cpu_addr;
+}
+
+static void free_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf_handle)
+{
+	if (loaf_handle->cpu_base != NULL)
+		pci_free_consistent(dev, loaf_handle->length,
+			loaf_handle->cpu_base, loaf_handle->dma_base);
+}
+
 
 /*
   DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary
@@ -156,15 +186,42 @@
   int CommandAllocationLength, CommandAllocationGroupSize;
   int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount;
   void *AllocationPointer = NULL;
+  void *ScatterGatherCPU = NULL;
+  dma_addr_t ScatterGatherDMA;
+  struct pci_pool *ScatterGatherPool;
+  void *RequestSenseCPU = NULL;
+  dma_addr_t RequestSenseDMA;
+  struct pci_pool *RequestSensePool = NULL;
+
   if (Controller->FirmwareType == DAC960_V1_Controller)
     {
       CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker);
       CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize;
+      ScatterGatherPool = pci_pool_create("DAC960_V1_ScatterGather",
+		Controller->PCIDevice,
+	DAC960_V1_ScatterGatherLimit * sizeof(DAC960_V1_ScatterGatherSegment_T),
+	sizeof(DAC960_V1_ScatterGatherSegment_T), 0);
+      if (ScatterGatherPool == NULL)
+	    return DAC960_Failure(Controller,
+			"AUXILIARY STRUCTURE CREATION (SG)");
+      Controller->ScatterGatherPool = ScatterGatherPool;
     }
   else
     {
       CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker);
       CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize;
+      ScatterGatherPool = pci_pool_create("DAC960_V2_ScatterGather",
+		Controller->PCIDevice,
+	DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T),
+	sizeof(DAC960_V2_ScatterGatherSegment_T), 0);
+      RequestSensePool = pci_pool_create("DAC960_V2_RequestSense",
+		Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T),
+		sizeof(int), 0);
+      if (ScatterGatherPool == NULL || RequestSensePool == NULL)
+	    return DAC960_Failure(Controller,
+			"AUXILIARY STRUCTURE CREATION (SG)");
+      Controller->ScatterGatherPool = ScatterGatherPool;
+      Controller->V2.RequestSensePool = RequestSensePool;
     }
   Controller->CommandAllocationGroupSize = CommandAllocationGroupSize;
   Controller->FreeCommands = NULL;
@@ -176,16 +233,17 @@
       if (--CommandsRemaining <= 0)
 	{
 	  CommandsRemaining =
-	    Controller->DriverQueueDepth - CommandIdentifier + 1;
+		Controller->DriverQueueDepth - CommandIdentifier + 1;
 	  if (CommandsRemaining > CommandAllocationGroupSize)
-	    CommandsRemaining = CommandAllocationGroupSize;
+		CommandsRemaining = CommandAllocationGroupSize;
 	  CommandGroupByteCount =
-	    CommandsRemaining * CommandAllocationLength;
+		CommandsRemaining * CommandAllocationLength;
 	  AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC);
 	  if (AllocationPointer == NULL)
-	    return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION");
+		return DAC960_Failure(Controller,
+					"AUXILIARY STRUCTURE CREATION");
 	  memset(AllocationPointer, 0, CommandGroupByteCount);
-	}
+	 }
       Command = (DAC960_Command_T *) AllocationPointer;
       AllocationPointer += CommandAllocationLength;
       Command->CommandIdentifier = CommandIdentifier;
@@ -193,6 +251,33 @@
       Command->Next = Controller->FreeCommands;
       Controller->FreeCommands = Command;
       Controller->Commands[CommandIdentifier-1] = Command;
+      ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, SLAB_ATOMIC,
+							&ScatterGatherDMA);
+      if (ScatterGatherCPU == NULL)
+	  return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION");
+
+      if (RequestSensePool != NULL) {
+  	  RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC,
+						&RequestSenseDMA);
+  	  if (RequestSenseCPU == NULL) {
+                pci_pool_free(ScatterGatherPool, ScatterGatherCPU,
+                                ScatterGatherDMA);
+    		return DAC960_Failure(Controller,
+					"AUXILIARY STRUCTURE CREATION");
+	  }
+        }
+     if (Controller->FirmwareType == DAC960_V1_Controller) {
+	Command->V1.ScatterGatherList =
+		(DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU;
+	Command->V1.ScatterGatherListDMA = ScatterGatherDMA;
+      } else {
+	Command->V2.ScatterGatherList =
+		(DAC960_V2_ScatterGatherSegment_T *)ScatterGatherCPU;
+	Command->V2.ScatterGatherListDMA = ScatterGatherDMA;
+	Command->V2.RequestSense =
+				(DAC960_SCSI_RequestSense_T *)RequestSenseCPU;
+	Command->V2.RequestSenseDMA = RequestSenseDMA;
+      }
     }
   return true;
 }
@@ -206,29 +291,80 @@
 static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller)
 {
   int i;
+  struct pci_pool *ScatterGatherPool = Controller->ScatterGatherPool;
+  struct pci_pool *RequestSensePool = NULL;
+  void *ScatterGatherCPU;
+  dma_addr_t ScatterGatherDMA;
+  void *RequestSenseCPU;
+  dma_addr_t RequestSenseDMA;
+  DAC960_Command_T *CommandGroup = NULL;
+  
+
+  if (Controller->FirmwareType == DAC960_V2_Controller)
+        RequestSensePool = Controller->V2.RequestSensePool;
+
   Controller->FreeCommands = NULL;
   for (i = 0; i < Controller->DriverQueueDepth; i++)
     {
       DAC960_Command_T *Command = Controller->Commands[i];
-      if (Command != NULL &&
-	  (Command->CommandIdentifier
-	   % Controller->CommandAllocationGroupSize) == 1)
-	kfree(Command);
+
+      if (Command == NULL)
+	  continue;
+
+      if (Controller->FirmwareType == DAC960_V1_Controller) {
+	  ScatterGatherCPU = (void *)Command->V1.ScatterGatherList;
+	  ScatterGatherDMA = Command->V1.ScatterGatherListDMA;
+	  RequestSenseCPU = NULL;
+	  RequestSenseDMA = (dma_addr_t)0;
+      } else {
+          ScatterGatherCPU = (void *)Command->V2.ScatterGatherList;
+	  ScatterGatherDMA = Command->V2.ScatterGatherListDMA;
+	  RequestSenseCPU = (void *)Command->V2.RequestSense;
+	  RequestSenseDMA = Command->V2.RequestSenseDMA;
+      }
+      if (ScatterGatherCPU != NULL)
+          pci_pool_free(ScatterGatherPool, ScatterGatherCPU, ScatterGatherDMA);
+      if (RequestSenseCPU != NULL)
+          pci_pool_free(RequestSensePool, RequestSenseCPU, RequestSenseDMA);
+
+      if ((Command->CommandIdentifier
+	   % Controller->CommandAllocationGroupSize) == 1) {
+	   /*
+	    * We can't free the group of commands until all of the
+	    * request sense and scatter gather dma structures are free.
+            * Remember the beginning of the group, but don't free it
+	    * until we've reached the beginning of the next group.
+	    */
+	   if (CommandGroup != NULL)
+		kfree(CommandGroup);
+	    CommandGroup = Command;
+      }
       Controller->Commands[i] = NULL;
     }
+  if (CommandGroup != NULL)
+      kfree(CommandGroup);
+
   if (Controller->CombinedStatusBuffer != NULL)
     {
       kfree(Controller->CombinedStatusBuffer);
       Controller->CombinedStatusBuffer = NULL;
       Controller->CurrentStatusBuffer = NULL;
     }
+
+  if (ScatterGatherPool != NULL)
+  	pci_pool_destroy(ScatterGatherPool);
   if (Controller->FirmwareType == DAC960_V1_Controller) return;
+
+  if (RequestSensePool != NULL)
+	pci_pool_destroy(RequestSensePool);
+
   for (i = 0; i < DAC960_MaxLogicalDrives; i++)
     if (Controller->V2.LogicalDeviceInformation[i] != NULL)
       {
 	kfree(Controller->V2.LogicalDeviceInformation[i]);
 	Controller->V2.LogicalDeviceInformation[i] = NULL;
       }
+
   for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++)
     {
       if (Controller->V2.PhysicalDeviceInformation[i] != NULL)
@@ -297,6 +433,8 @@
 static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
+
+  Command->Request = NULL;
   Command->Next = Controller->FreeCommands;
   Controller->FreeCommands = Command;
 }
@@ -308,9 +446,9 @@
 
 static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
 {
-  spin_unlock_irq(Controller->RequestQueue.queue_lock);
+  spin_unlock_irq(&Controller->queue_lock);
   __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands);
-  spin_lock_irq(Controller->RequestQueue.queue_lock);
+  spin_lock_irq(&Controller->queue_lock);
 }
 
 
@@ -557,7 +695,7 @@
 
 static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
 				      DAC960_V1_CommandOpcode_T CommandOpcode,
-				      void *DataPointer)
+				      dma_addr_t DataDMA)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
@@ -565,7 +703,7 @@
   DAC960_V1_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
   CommandMailbox->Type3.CommandOpcode = CommandOpcode;
-  CommandMailbox->Type3.BusAddress = Virtual_to_Bus32(DataPointer);
+  CommandMailbox->Type3.BusAddress = DataDMA;
   DAC960_ExecuteCommand(Command);
   CommandStatus = Command->V1.CommandStatus;
   DAC960_DeallocateCommand(Command);
@@ -582,7 +720,7 @@
 static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
 				       DAC960_V1_CommandOpcode_T CommandOpcode,
 				       unsigned char CommandOpcode2,
-				       void *DataPointer)
+				       dma_addr_t DataDMA)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
@@ -591,7 +729,7 @@
   Command->CommandType = DAC960_ImmediateCommand;
   CommandMailbox->Type3B.CommandOpcode = CommandOpcode;
   CommandMailbox->Type3B.CommandOpcode2 = CommandOpcode2;
-  CommandMailbox->Type3B.BusAddress = Virtual_to_Bus32(DataPointer);
+  CommandMailbox->Type3B.BusAddress = DataDMA;
   DAC960_ExecuteCommand(Command);
   CommandStatus = Command->V1.CommandStatus;
   DAC960_DeallocateCommand(Command);
@@ -609,7 +747,7 @@
 				       DAC960_V1_CommandOpcode_T CommandOpcode,
 				       unsigned char Channel,
 				       unsigned char TargetID,
-				       void *DataPointer)
+				       dma_addr_t DataDMA)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
@@ -619,7 +757,7 @@
   CommandMailbox->Type3D.CommandOpcode = CommandOpcode;
   CommandMailbox->Type3D.Channel = Channel;
   CommandMailbox->Type3D.TargetID = TargetID;
-  CommandMailbox->Type3D.BusAddress = Virtual_to_Bus32(DataPointer);
+  CommandMailbox->Type3D.BusAddress = DataDMA;
   DAC960_ExecuteCommand(Command);
   CommandStatus = Command->V1.CommandStatus;
   DAC960_DeallocateCommand(Command);
@@ -631,12 +769,11 @@
   DAC960_V2_GeneralInfo executes a DAC960 V2 Firmware General Information
   Reading IOCTL Command and waits for completion.  It returns true on success
   and false on failure.
+
+  Return data in The controller's HealthStatusBuffer, which is dma-able memory
 */
 
-static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller,
-				     DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode,
-				     void *DataPointer,
-				     unsigned int DataByteCount)
+static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
@@ -648,12 +785,12 @@
 			.DataTransferControllerToHost = true;
   CommandMailbox->Common.CommandControlBits
 			.NoAutoRequestSense = true;
-  CommandMailbox->Common.DataTransferSize = DataByteCount;
-  CommandMailbox->Common.IOCTL_Opcode = IOCTL_Opcode;
+  CommandMailbox->Common.DataTransferSize = sizeof(DAC960_V2_HealthStatusBuffer_T);
+  CommandMailbox->Common.IOCTL_Opcode = DAC960_V2_GetHealthStatus;
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentDataPointer =
-    Virtual_to_Bus64(DataPointer);
+    Controller->V2.HealthStatusBufferDMA;
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentByteCount =
@@ -669,12 +806,12 @@
   DAC960_V2_ControllerInfo executes a DAC960 V2 Firmware Controller
   Information Reading IOCTL Command and waits for completion.  It returns
   true on success and false on failure.
+
+  Data is returned in the controller's V2.NewControllerInformation dma-able
+  memory buffer.
 */
 
-static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller,
-					DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode,
-					void *DataPointer,
-					unsigned int DataByteCount)
+static boolean DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
@@ -686,13 +823,13 @@
 				.DataTransferControllerToHost = true;
   CommandMailbox->ControllerInfo.CommandControlBits
 				.NoAutoRequestSense = true;
-  CommandMailbox->ControllerInfo.DataTransferSize = DataByteCount;
+  CommandMailbox->ControllerInfo.DataTransferSize = sizeof(DAC960_V2_ControllerInfo_T);
   CommandMailbox->ControllerInfo.ControllerNumber = 0;
-  CommandMailbox->ControllerInfo.IOCTL_Opcode = IOCTL_Opcode;
+  CommandMailbox->ControllerInfo.IOCTL_Opcode = DAC960_V2_GetControllerInfo;
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentDataPointer =
-    Virtual_to_Bus64(DataPointer);
+    	Controller->V2.NewControllerInformationDMA;
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentByteCount =
@@ -708,34 +845,34 @@
   DAC960_V2_LogicalDeviceInfo executes a DAC960 V2 Firmware Controller Logical
   Device Information Reading IOCTL Command and waits for completion.  It
   returns true on success and false on failure.
+
+  Data is returned in the controller's V2.NewLogicalDeviceInformation
 */
 
-static boolean DAC960_V2_LogicalDeviceInfo(DAC960_Controller_T *Controller,
-					   DAC960_V2_IOCTL_Opcode_T
-					     IOCTL_Opcode,
-					   unsigned short
-					     LogicalDeviceNumber,
-					   void *DataPointer,
-					   unsigned int DataByteCount)
+static boolean DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller,
+					   unsigned short LogicalDeviceNumber)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandStatus_T CommandStatus;
+
   DAC960_V2_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
-  CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
+  CommandMailbox->LogicalDeviceInfo.CommandOpcode =
+				DAC960_V2_IOCTL;
   CommandMailbox->LogicalDeviceInfo.CommandControlBits
 				   .DataTransferControllerToHost = true;
   CommandMailbox->LogicalDeviceInfo.CommandControlBits
 				   .NoAutoRequestSense = true;
-  CommandMailbox->LogicalDeviceInfo.DataTransferSize = DataByteCount;
+  CommandMailbox->LogicalDeviceInfo.DataTransferSize = 
+				sizeof(DAC960_V2_LogicalDeviceInfo_T);
   CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber =
     LogicalDeviceNumber;
-  CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode;
+  CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = DAC960_V2_GetLogicalDeviceInfoValid;
   CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 				   .ScatterGatherSegments[0]
 				   .SegmentDataPointer =
-    Virtual_to_Bus64(DataPointer);
+    	Controller->V2.NewLogicalDeviceInformationDMA;
   CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 				   .ScatterGatherSegments[0]
 				   .SegmentByteCount =
@@ -748,23 +885,30 @@
 
 
 /*
-  DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller Physical
-  Device Information Reading IOCTL Command and waits for completion.  It
+  DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller "Read
+  Physical Device Information" IOCTL Command and waits for completion.  It
   returns true on success and false on failure.
+
+  The Channel, TargetID, LogicalUnit arguments should be 0 the first time
+  this function is called for a given controller.  This will return data
+  for the "first" device on that controller.  The returned data includes a
+  Channel, TargetID, LogicalUnit that can be passed in to this routine to
+  get data for the NEXT device on that controller.
+
+  Data is stored in the controller's V2.NewPhysicalDeviceInfo dma-able
+  memory buffer.
+
 */
 
-static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller,
-					    DAC960_V2_IOCTL_Opcode_T
-					      IOCTL_Opcode,
+static boolean DAC960_V2_NewPhysicalDeviceInfo(DAC960_Controller_T *Controller,
 					    unsigned char Channel,
 					    unsigned char TargetID,
-					    unsigned char LogicalUnit,
-					    void *DataPointer,
-					    unsigned int DataByteCount)
+					    unsigned char LogicalUnit)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandStatus_T CommandStatus;
+
   DAC960_V2_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
   CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
@@ -772,15 +916,17 @@
 				    .DataTransferControllerToHost = true;
   CommandMailbox->PhysicalDeviceInfo.CommandControlBits
 				    .NoAutoRequestSense = true;
-  CommandMailbox->PhysicalDeviceInfo.DataTransferSize = DataByteCount;
+  CommandMailbox->PhysicalDeviceInfo.DataTransferSize =
+				sizeof(DAC960_V2_PhysicalDeviceInfo_T);
   CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = LogicalUnit;
   CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID;
   CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel;
-  CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode;
+  CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode =
+					DAC960_V2_GetPhysicalDeviceInfoValid;
   CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 				    .ScatterGatherSegments[0]
 				    .SegmentDataPointer =
-    Virtual_to_Bus64(DataPointer);
+    					Controller->V2.NewPhysicalDeviceInformationDMA;
   CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 				    .ScatterGatherSegments[0]
 				    .SegmentByteCount =
@@ -792,6 +938,75 @@
 }
 
 
+static void DAC960_V2_ConstructNewUnitSerialNumber(
+	DAC960_Controller_T *Controller,
+	DAC960_V2_CommandMailbox_T *CommandMailbox, int Channel, int TargetID,
+	int LogicalUnit)
+{
+      CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru;
+      CommandMailbox->SCSI_10.CommandControlBits
+			     .DataTransferControllerToHost = true;
+      CommandMailbox->SCSI_10.CommandControlBits
+			     .NoAutoRequestSense = true;
+      CommandMailbox->SCSI_10.DataTransferSize =
+	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+      CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit;
+      CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID;
+      CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel;
+      CommandMailbox->SCSI_10.CDBLength = 6;
+      CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */
+      CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */
+      CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */
+      CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */
+      CommandMailbox->SCSI_10.SCSI_CDB[4] =
+	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+      CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */
+      CommandMailbox->SCSI_10.DataTransferMemoryAddress
+			     .ScatterGatherSegments[0]
+			     .SegmentDataPointer =
+		Controller->V2.NewInquiryUnitSerialNumberDMA;
+      CommandMailbox->SCSI_10.DataTransferMemoryAddress
+			     .ScatterGatherSegments[0]
+			     .SegmentByteCount =
+		CommandMailbox->SCSI_10.DataTransferSize;
+}
+
+
+/*
+  DAC960_V2_NewUnitSerialNumber executes an SCSI pass-through
+  Inquiry command to a SCSI device identified by Channel number,
+  Target id, Logical Unit Number.  This function Waits for completion
+  of the command.
+
+  The return data includes Unit Serial Number information for the
+  specified device.
+
+  Data is stored in the controller's V2.NewPhysicalDeviceInfo dma-able
+  memory buffer.
+*/
+
+static boolean DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Controller,
+			int Channel, int TargetID, int LogicalUnit)
+{
+      DAC960_Command_T *Command;
+      DAC960_V2_CommandMailbox_T *CommandMailbox;
+      DAC960_V2_CommandStatus_T CommandStatus;
+
+      Command = DAC960_AllocateCommand(Controller);
+      CommandMailbox = &Command->V2.CommandMailbox;
+      DAC960_V2_ClearCommand(Command);
+      Command->CommandType = DAC960_ImmediateCommand;
+
+      DAC960_V2_ConstructNewUnitSerialNumber(Controller, CommandMailbox,
+			Channel, TargetID, LogicalUnit);
+
+      DAC960_ExecuteCommand(Command);
+      CommandStatus = Command->V2.CommandStatus;
+      DAC960_DeallocateCommand(Command);
+      return (CommandStatus == DAC960_V2_NormalCompletion);
+}
+
+
 /*
   DAC960_V2_DeviceOperation executes a DAC960 V2 Firmware Controller Device
   Operation IOCTL Command and waits for completion.  It returns true on
@@ -825,84 +1040,144 @@
 /*
   DAC960_V1_EnableMemoryMailboxInterface enables the Memory Mailbox Interface
   for DAC960 V1 Firmware Controllers.
+
+  PD and P controller types have no memory mailbox, but still need the
+  other dma mapped memory.
 */
 
 static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_HardwareType_T hw_type = Controller->HardwareType;
+  PCI_Device_T	*PCI_Device = Controller->PCIDevice;
+  struct dma_loaf *DmaPages = &Controller->DmaPages;
+  size_t DmaPagesSize;
+  size_t CommandMailboxesSize;
+  size_t StatusMailboxesSize;
+
   DAC960_V1_CommandMailbox_T *CommandMailboxesMemory;
+  dma_addr_t CommandMailboxesMemoryDMA;
+
   DAC960_V1_StatusMailbox_T *StatusMailboxesMemory;
+  dma_addr_t StatusMailboxesMemoryDMA;
+
   DAC960_V1_CommandMailbox_T CommandMailbox;
   DAC960_V1_CommandStatus_T CommandStatus;
-  unsigned long MemoryMailboxPagesAddress;
-  unsigned long MemoryMailboxPagesOrder;
-  unsigned long MemoryMailboxPagesSize;
-  void *SavedMemoryMailboxesAddress = NULL;
-  short NextCommandMailboxIndex = 0;
-  short NextStatusMailboxIndex = 0;
-  int TimeoutCounter = 1000000, i;
-  MemoryMailboxPagesOrder = 0;
-  MemoryMailboxPagesSize =
-    DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T) +
-    DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T);
-  while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder)
-    MemoryMailboxPagesOrder++;
-  if (Controller->HardwareType == DAC960_LA_Controller)
-    DAC960_LA_RestoreMemoryMailboxInfo(Controller,
-				       &SavedMemoryMailboxesAddress,
-				       &NextCommandMailboxIndex,
-				       &NextStatusMailboxIndex);
-  else DAC960_PG_RestoreMemoryMailboxInfo(Controller,
-					  &SavedMemoryMailboxesAddress,
-					  &NextCommandMailboxIndex,
-					  &NextStatusMailboxIndex);
-  if (SavedMemoryMailboxesAddress == NULL)
-    {
-      MemoryMailboxPagesAddress =
-	__get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder);
-      Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress;
-      CommandMailboxesMemory =
-	(DAC960_V1_CommandMailbox_T *) MemoryMailboxPagesAddress;
-    }
-  else CommandMailboxesMemory = SavedMemoryMailboxesAddress;
-  if (CommandMailboxesMemory == NULL) return false;
-  Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder;
-  memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize);
+  int TimeoutCounter;
+  int i;
+
+  
+  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V1_PciDmaMask))
+	return DAC960_Failure(Controller, "DMA mask out of range");
+
+  if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) {
+    CommandMailboxesSize =  0;
+    StatusMailboxesSize = 0;
+  } else {
+    CommandMailboxesSize =  DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T);
+    StatusMailboxesSize = DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T);
+  }
+  DmaPagesSize = CommandMailboxesSize + StatusMailboxesSize + 
+	sizeof(DAC960_V1_DCDB_T) + sizeof(DAC960_V1_Enquiry_T) +
+	sizeof(DAC960_V1_ErrorTable_T) + sizeof(DAC960_V1_EventLogEntry_T) +
+	sizeof(DAC960_V1_RebuildProgress_T) +
+	sizeof(DAC960_V1_LogicalDriveInformationArray_T) +
+	sizeof(DAC960_V1_BackgroundInitializationStatus_T) +
+	sizeof(DAC960_V1_DeviceState_T) + sizeof(DAC960_SCSI_Inquiry_T) +
+	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+
+  if (!init_dma_loaf(PCI_Device, DmaPages, DmaPagesSize))
+	return false;
+
+
+  if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) 
+	goto skip_mailboxes;
+
+  CommandMailboxesMemory = slice_dma_loaf(DmaPages,
+                CommandMailboxesSize, &CommandMailboxesMemoryDMA);
+  
+  /* These are the base addresses for the command memory mailbox array */
   Controller->V1.FirstCommandMailbox = CommandMailboxesMemory;
+  Controller->V1.FirstCommandMailboxDMA = CommandMailboxesMemoryDMA;
+
   CommandMailboxesMemory += DAC960_V1_CommandMailboxCount - 1;
   Controller->V1.LastCommandMailbox = CommandMailboxesMemory;
-  Controller->V1.NextCommandMailbox =
-    &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex];
-  if (--NextCommandMailboxIndex < 0)
-    NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1;
-  Controller->V1.PreviousCommandMailbox1 =
-    &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex];
-  if (--NextCommandMailboxIndex < 0)
-    NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1;
+  Controller->V1.NextCommandMailbox = Controller->V1.FirstCommandMailbox;
+  Controller->V1.PreviousCommandMailbox1 = Controller->V1.LastCommandMailbox;
   Controller->V1.PreviousCommandMailbox2 =
-    &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex];
-  StatusMailboxesMemory =
-    (DAC960_V1_StatusMailbox_T *) (CommandMailboxesMemory + 1);
+	  				Controller->V1.LastCommandMailbox - 1;
+
+  /* These are the base addresses for the status memory mailbox array */
+  StatusMailboxesMemory = slice_dma_loaf(DmaPages,
+                StatusMailboxesSize, &StatusMailboxesMemoryDMA);
+
   Controller->V1.FirstStatusMailbox = StatusMailboxesMemory;
+  Controller->V1.FirstStatusMailboxDMA = StatusMailboxesMemoryDMA;
   StatusMailboxesMemory += DAC960_V1_StatusMailboxCount - 1;
   Controller->V1.LastStatusMailbox = StatusMailboxesMemory;
-  Controller->V1.NextStatusMailbox =
-    &Controller->V1.FirstStatusMailbox[NextStatusMailboxIndex];
-  if (SavedMemoryMailboxesAddress != NULL) return true;
+  Controller->V1.NextStatusMailbox = Controller->V1.FirstStatusMailbox;
+
+skip_mailboxes:
+  Controller->V1.MonitoringDCDB = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_DCDB_T),
+                &Controller->V1.MonitoringDCDB_DMA);
+
+  Controller->V1.NewEnquiry = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_Enquiry_T),
+                &Controller->V1.NewEnquiryDMA);
+
+  Controller->V1.NewErrorTable = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_ErrorTable_T),
+                &Controller->V1.NewErrorTableDMA);
+
+  Controller->V1.EventLogEntry = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_EventLogEntry_T),
+                &Controller->V1.EventLogEntryDMA);
+
+  Controller->V1.RebuildProgress = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_RebuildProgress_T),
+                &Controller->V1.RebuildProgressDMA);
+
+  Controller->V1.NewLogicalDriveInformation = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_LogicalDriveInformationArray_T),
+                &Controller->V1.NewLogicalDriveInformationDMA);
+
+  Controller->V1.BackgroundInitializationStatus = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_BackgroundInitializationStatus_T),
+                &Controller->V1.BackgroundInitializationStatusDMA);
+
+  Controller->V1.NewDeviceState = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_DeviceState_T),
+                &Controller->V1.NewDeviceStateDMA);
+
+  Controller->V1.NewInquiryStandardData = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_SCSI_Inquiry_T),
+                &Controller->V1.NewInquiryStandardDataDMA);
+
+  Controller->V1.NewInquiryUnitSerialNumber = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
+                &Controller->V1.NewInquiryUnitSerialNumberDMA);
+
+  if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller))
+	return true;
+ 
   /* Enable the Memory Mailbox Interface. */
   Controller->V1.DualModeMemoryMailboxInterface = true;
   CommandMailbox.TypeX.CommandOpcode = 0x2B;
   CommandMailbox.TypeX.CommandIdentifier = 0;
   CommandMailbox.TypeX.CommandOpcode2 = 0x14;
   CommandMailbox.TypeX.CommandMailboxesBusAddress =
-    Virtual_to_Bus32(Controller->V1.FirstCommandMailbox);
+    				Controller->V1.FirstCommandMailboxDMA;
   CommandMailbox.TypeX.StatusMailboxesBusAddress =
-    Virtual_to_Bus32(Controller->V1.FirstStatusMailbox);
+    				Controller->V1.FirstStatusMailboxDMA;
+#define TIMEOUT_COUNT 1000000
+
   for (i = 0; i < 2; i++)
     switch (Controller->HardwareType)
       {
       case DAC960_LA_Controller:
+	TimeoutCounter = TIMEOUT_COUNT;
 	while (--TimeoutCounter >= 0)
 	  {
 	    if (!DAC960_LA_HardwareMailboxFullP(ControllerBaseAddress))
@@ -912,6 +1187,7 @@
 	if (TimeoutCounter < 0) return false;
 	DAC960_LA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
 	DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress);
+	TimeoutCounter = TIMEOUT_COUNT;
 	while (--TimeoutCounter >= 0)
 	  {
 	    if (DAC960_LA_HardwareMailboxStatusAvailableP(
@@ -928,6 +1204,7 @@
 	CommandMailbox.TypeX.CommandOpcode2 = 0x10;
 	break;
       case DAC960_PG_Controller:
+	TimeoutCounter = TIMEOUT_COUNT;
 	while (--TimeoutCounter >= 0)
 	  {
 	    if (!DAC960_PG_HardwareMailboxFullP(ControllerBaseAddress))
@@ -937,6 +1214,8 @@
 	if (TimeoutCounter < 0) return false;
 	DAC960_PG_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
 	DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress);
+
+	TimeoutCounter = TIMEOUT_COUNT;
 	while (--TimeoutCounter >= 0)
 	  {
 	    if (DAC960_PG_HardwareMailboxStatusAvailableP(
@@ -953,6 +1232,7 @@
 	CommandMailbox.TypeX.CommandOpcode2 = 0x10;
 	break;
       default:
+        DAC960_Failure(Controller, "Unknown Controller Type\n");
 	break;
       }
   return false;
@@ -962,75 +1242,146 @@
 /*
   DAC960_V2_EnableMemoryMailboxInterface enables the Memory Mailbox Interface
   for DAC960 V2 Firmware Controllers.
+
+  Aggregate the space needed for the controller's memory mailbox and
+  the other data structures that will be targets of dma transfers with
+  the controller.  Allocate a dma-mapped region of memory to hold these
+  structures.  Then, save CPU pointers and dma_addr_t values to reference
+  the structures that are contained in that region.
 */
 
 static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
+  PCI_Device_T	*PCI_Device = Controller->PCIDevice;
+  struct dma_loaf *DmaPages = &Controller->DmaPages;
+  size_t DmaPagesSize;
+  size_t CommandMailboxesSize;
+  size_t StatusMailboxesSize;
+
   DAC960_V2_CommandMailbox_T *CommandMailboxesMemory;
+  dma_addr_t CommandMailboxesMemoryDMA;
+
   DAC960_V2_StatusMailbox_T *StatusMailboxesMemory;
-  DAC960_V2_CommandMailbox_T CommandMailbox;
-  DAC960_V2_CommandStatus_T CommandStatus = 0;
-  unsigned long MemoryMailboxPagesAddress;
-  unsigned long MemoryMailboxPagesOrder;
-  unsigned long MemoryMailboxPagesSize;
-  MemoryMailboxPagesOrder = 0;
-  MemoryMailboxPagesSize =
-    DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T) +
-    DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T) +
-    sizeof(DAC960_V2_HealthStatusBuffer_T);
-  while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder)
-    MemoryMailboxPagesOrder++;
-  MemoryMailboxPagesAddress =
-    __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder);
-  Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress;
-  CommandMailboxesMemory =
-    (DAC960_V2_CommandMailbox_T *) MemoryMailboxPagesAddress;
-  if (CommandMailboxesMemory == NULL) return false;
-  Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder;
-  memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize);
+  dma_addr_t StatusMailboxesMemoryDMA;
+
+  DAC960_V2_CommandMailbox_T *CommandMailbox;
+  dma_addr_t	CommandMailboxDMA;
+  DAC960_V2_CommandStatus_T CommandStatus;
+
+  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V2_PciDmaMask))
+	return DAC960_Failure(Controller, "DMA mask out of range");
+
+  /* This is a temporary dma mapping, used only in the scope of this function */
+  CommandMailbox =
+	  (DAC960_V2_CommandMailbox_T *)pci_alloc_consistent( PCI_Device,
+		sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA);
+  if (CommandMailbox == NULL)
+	  return false;
+
+  CommandMailboxesSize = DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T);
+  StatusMailboxesSize = DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T);
+  DmaPagesSize =
+    CommandMailboxesSize + StatusMailboxesSize +
+    sizeof(DAC960_V2_HealthStatusBuffer_T) +
+    sizeof(DAC960_V2_ControllerInfo_T) +
+    sizeof(DAC960_V2_LogicalDeviceInfo_T) +
+    sizeof(DAC960_V2_PhysicalDeviceInfo_T) +
+    sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T) +
+    sizeof(DAC960_V2_Event_T) +
+    sizeof(DAC960_V2_PhysicalToLogicalDevice_T);
+
+  if (!init_dma_loaf(PCI_Device, DmaPages, DmaPagesSize)) {
+  	pci_free_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T),
+					CommandMailbox, CommandMailboxDMA);
+	return false;
+  }
+
+  CommandMailboxesMemory = slice_dma_loaf(DmaPages,
+		CommandMailboxesSize, &CommandMailboxesMemoryDMA);
+
+  /* These are the base addresses for the command memory mailbox array */
   Controller->V2.FirstCommandMailbox = CommandMailboxesMemory;
+  Controller->V2.FirstCommandMailboxDMA = CommandMailboxesMemoryDMA;
+
   CommandMailboxesMemory += DAC960_V2_CommandMailboxCount - 1;
   Controller->V2.LastCommandMailbox = CommandMailboxesMemory;
   Controller->V2.NextCommandMailbox = Controller->V2.FirstCommandMailbox;
   Controller->V2.PreviousCommandMailbox1 = Controller->V2.LastCommandMailbox;
   Controller->V2.PreviousCommandMailbox2 =
-    Controller->V2.LastCommandMailbox - 1;
-  StatusMailboxesMemory =
-    (DAC960_V2_StatusMailbox_T *) (CommandMailboxesMemory + 1);
+    					Controller->V2.LastCommandMailbox - 1;
+
+  /* These are the base addresses for the status memory mailbox array */
+  StatusMailboxesMemory = slice_dma_loaf(DmaPages,
+		StatusMailboxesSize, &StatusMailboxesMemoryDMA);
+
   Controller->V2.FirstStatusMailbox = StatusMailboxesMemory;
+  Controller->V2.FirstStatusMailboxDMA = StatusMailboxesMemoryDMA;
   StatusMailboxesMemory += DAC960_V2_StatusMailboxCount - 1;
   Controller->V2.LastStatusMailbox = StatusMailboxesMemory;
   Controller->V2.NextStatusMailbox = Controller->V2.FirstStatusMailbox;
-  Controller->V2.HealthStatusBuffer =
-    (DAC960_V2_HealthStatusBuffer_T *) (StatusMailboxesMemory + 1);
-  /* Enable the Memory Mailbox Interface. */
-  memset(&CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T));
-  CommandMailbox.SetMemoryMailbox.CommandIdentifier = 1;
-  CommandMailbox.SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL;
-  CommandMailbox.SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true;
-  CommandMailbox.SetMemoryMailbox.FirstCommandMailboxSizeKB =
+
+  Controller->V2.HealthStatusBuffer = slice_dma_loaf(DmaPages,
+		sizeof(DAC960_V2_HealthStatusBuffer_T),
+		&Controller->V2.HealthStatusBufferDMA);
+
+  Controller->V2.NewControllerInformation = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_ControllerInfo_T), 
+                &Controller->V2.NewControllerInformationDMA);
+
+  Controller->V2.NewLogicalDeviceInformation =  slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_LogicalDeviceInfo_T),
+                &Controller->V2.NewLogicalDeviceInformationDMA);
+
+  Controller->V2.NewPhysicalDeviceInformation = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_PhysicalDeviceInfo_T),
+                &Controller->V2.NewPhysicalDeviceInformationDMA);
+
+  Controller->V2.NewInquiryUnitSerialNumber = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
+                &Controller->V2.NewInquiryUnitSerialNumberDMA);
+
+  Controller->V2.Event = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_Event_T),
+                &Controller->V2.EventDMA);
+
+  Controller->V2.PhysicalToLogicalDevice = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_PhysicalToLogicalDevice_T),
+                &Controller->V2.PhysicalToLogicalDeviceDMA);
+
+  /*
+    Enable the Memory Mailbox Interface.
+    
+    I don't know why we can't just use one of the memory mailboxes
+    we just allocated to do this, instead of using this temporary one.
+    Try this change later.
+  */
+  memset(CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T));
+  CommandMailbox->SetMemoryMailbox.CommandIdentifier = 1;
+  CommandMailbox->SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL;
+  CommandMailbox->SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true;
+  CommandMailbox->SetMemoryMailbox.FirstCommandMailboxSizeKB =
     (DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T)) >> 10;
-  CommandMailbox.SetMemoryMailbox.FirstStatusMailboxSizeKB =
+  CommandMailbox->SetMemoryMailbox.FirstStatusMailboxSizeKB =
     (DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T)) >> 10;
-  CommandMailbox.SetMemoryMailbox.SecondCommandMailboxSizeKB = 0;
-  CommandMailbox.SetMemoryMailbox.SecondStatusMailboxSizeKB = 0;
-  CommandMailbox.SetMemoryMailbox.RequestSenseSize = 0;
-  CommandMailbox.SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox;
-  CommandMailbox.SetMemoryMailbox.HealthStatusBufferSizeKB = 1;
-  CommandMailbox.SetMemoryMailbox.HealthStatusBufferBusAddress =
-    Virtual_to_Bus64(Controller->V2.HealthStatusBuffer);
-  CommandMailbox.SetMemoryMailbox.FirstCommandMailboxBusAddress =
-    Virtual_to_Bus64(Controller->V2.FirstCommandMailbox);
-  CommandMailbox.SetMemoryMailbox.FirstStatusMailboxBusAddress =
-    Virtual_to_Bus64(Controller->V2.FirstStatusMailbox);
+  CommandMailbox->SetMemoryMailbox.SecondCommandMailboxSizeKB = 0;
+  CommandMailbox->SetMemoryMailbox.SecondStatusMailboxSizeKB = 0;
+  CommandMailbox->SetMemoryMailbox.RequestSenseSize = 0;
+  CommandMailbox->SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox;
+  CommandMailbox->SetMemoryMailbox.HealthStatusBufferSizeKB = 1;
+  CommandMailbox->SetMemoryMailbox.HealthStatusBufferBusAddress =
+    					Controller->V2.HealthStatusBufferDMA;
+  CommandMailbox->SetMemoryMailbox.FirstCommandMailboxBusAddress =
+    					Controller->V2.FirstCommandMailboxDMA;
+  CommandMailbox->SetMemoryMailbox.FirstStatusMailboxBusAddress =
+    					Controller->V2.FirstStatusMailboxDMA;
   switch (Controller->HardwareType)
     {
     case DAC960_BA_Controller:
       while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress))
 	udelay(1);
-      DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+      DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA);
       DAC960_BA_HardwareMailboxNewCommand(ControllerBaseAddress);
       while (!DAC960_BA_HardwareMailboxStatusAvailableP(ControllerBaseAddress))
 	udelay(1);
@@ -1041,7 +1392,7 @@
     case DAC960_LP_Controller:
       while (DAC960_LP_HardwareMailboxFullP(ControllerBaseAddress))
 	udelay(1);
-      DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+      DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA);
       DAC960_LP_HardwareMailboxNewCommand(ControllerBaseAddress);
       while (!DAC960_LP_HardwareMailboxStatusAvailableP(ControllerBaseAddress))
 	udelay(1);
@@ -1050,8 +1401,12 @@
       DAC960_LP_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
       break;
     default:
+      DAC960_Failure(Controller, "Unknown Controller Type\n");
+      CommandStatus = DAC960_V2_AbormalCompletion;
       break;
     }
+  pci_free_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T),
+					CommandMailbox, CommandMailboxDMA);
   return (CommandStatus == DAC960_V2_NormalCompletion);
 }
 
@@ -1064,33 +1419,65 @@
 static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
 						     *Controller)
 {
-  DAC960_V1_Enquiry2_T Enquiry2;
-  DAC960_V1_Config2_T Config2;
+  DAC960_V1_Enquiry2_T *Enquiry2;
+  dma_addr_t Enquiry2DMA;
+  DAC960_V1_Config2_T *Config2;
+  dma_addr_t Config2DMA;
   int LogicalDriveNumber, Channel, TargetID;
+  struct dma_loaf local_dma;
+
+  if (!init_dma_loaf(Controller->PCIDevice, &local_dma,
+		sizeof(DAC960_V1_Enquiry2_T) + sizeof(DAC960_V1_Config2_T)))
+	return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION");
+
+  Enquiry2 = slice_dma_loaf(&local_dma, sizeof(DAC960_V1_Enquiry2_T), &Enquiry2DMA);
+  Config2 = slice_dma_loaf(&local_dma, sizeof(DAC960_V1_Config2_T), &Config2DMA);
+
   if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry,
-			      &Controller->V1.Enquiry))
+			      Controller->V1.NewEnquiryDMA)) {
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
     return DAC960_Failure(Controller, "ENQUIRY");
-  if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, &Enquiry2))
+  }
+  memcpy(&Controller->V1.Enquiry, Controller->V1.NewEnquiry,
+						sizeof(DAC960_V1_Enquiry_T));
+
+  if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, Enquiry2DMA)) {
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
     return DAC960_Failure(Controller, "ENQUIRY2");
-  if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, &Config2))
+  }
+
+  if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, Config2DMA)) {
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
     return DAC960_Failure(Controller, "READ CONFIG2");
+  }
+
   if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_GetLogicalDriveInformation,
-			      &Controller->V1.LogicalDriveInformation))
+			      Controller->V1.NewLogicalDriveInformationDMA)) {
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
     return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION");
-  for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++)
-    for (TargetID = 0; TargetID < Enquiry2.MaxTargets; TargetID++)
+  }
+  memcpy(&Controller->V1.LogicalDriveInformation,
+		Controller->V1.NewLogicalDriveInformation,
+		sizeof(DAC960_V1_LogicalDriveInformationArray_T));
+
+  for (Channel = 0; Channel < Enquiry2->ActualChannels; Channel++)
+    for (TargetID = 0; TargetID < Enquiry2->MaxTargets; TargetID++) {
       if (!DAC960_V1_ExecuteType3D(Controller, DAC960_V1_GetDeviceState,
 				   Channel, TargetID,
-				   &Controller->V1.DeviceState
-						   [Channel][TargetID]))
-	return DAC960_Failure(Controller, "GET DEVICE STATE");
+				   Controller->V1.NewDeviceStateDMA)) {
+    		free_dma_loaf(Controller->PCIDevice, &local_dma);
+		return DAC960_Failure(Controller, "GET DEVICE STATE");
+	}
+	memcpy(&Controller->V1.DeviceState[Channel][TargetID],
+		Controller->V1.NewDeviceState, sizeof(DAC960_V1_DeviceState_T));
+     }
   /*
     Initialize the Controller Model Name and Full Model Name fields.
   */
-  switch (Enquiry2.HardwareID.SubModel)
+  switch (Enquiry2->HardwareID.SubModel)
     {
     case DAC960_V1_P_PD_PU:
-      if (Enquiry2.SCSICapability.BusSpeed == DAC960_V1_Ultra)
+      if (Enquiry2->SCSICapability.BusSpeed == DAC960_V1_Ultra)
 	strcpy(Controller->ModelName, "DAC960PU");
       else strcpy(Controller->ModelName, "DAC960PD");
       break;
@@ -1122,6 +1509,7 @@
       strcpy(Controller->ModelName, "DAC1164P");
       break;
     default:
+      free_dma_loaf(Controller->PCIDevice, &local_dma);
       return DAC960_Failure(Controller, "MODEL VERIFICATION");
     }
   strcpy(Controller->FullModelName, "Mylex ");
@@ -1135,18 +1523,18 @@
     DAC960PU/PD/PL	    3.51 and above
     DAC960PU/PD/PL/P	    2.73 and above
   */
-  if (Enquiry2.FirmwareID.MajorVersion == 0)
+  if (Enquiry2->FirmwareID.MajorVersion == 0)
     {
-      Enquiry2.FirmwareID.MajorVersion =
+      Enquiry2->FirmwareID.MajorVersion =
 	Controller->V1.Enquiry.MajorFirmwareVersion;
-      Enquiry2.FirmwareID.MinorVersion =
+      Enquiry2->FirmwareID.MinorVersion =
 	Controller->V1.Enquiry.MinorFirmwareVersion;
-      Enquiry2.FirmwareID.FirmwareType = '0';
-      Enquiry2.FirmwareID.TurnID = 0;
+      Enquiry2->FirmwareID.FirmwareType = '0';
+      Enquiry2->FirmwareID.TurnID = 0;
     }
   sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
-	  Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
-	  Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
+	  Enquiry2->FirmwareID.MajorVersion, Enquiry2->FirmwareID.MinorVersion,
+	  Enquiry2->FirmwareID.FirmwareType, Enquiry2->FirmwareID.TurnID);
   if (!((Controller->FirmwareVersion[0] == '5' &&
 	 strcmp(Controller->FirmwareVersion, "5.06") >= 0) ||
 	(Controller->FirmwareVersion[0] == '4' &&
@@ -1159,17 +1547,18 @@
       DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
       DAC960_Error("Firmware Version = '%s'\n", Controller,
 		   Controller->FirmwareVersion);
+      free_dma_loaf(Controller->PCIDevice, &local_dma);
       return false;
     }
   /*
     Initialize the Controller Channels, Targets, Memory Size, and SAF-TE
     Enclosure Management Enabled fields.
   */
-  Controller->Channels = Enquiry2.ActualChannels;
-  Controller->Targets = Enquiry2.MaxTargets;
-  Controller->MemorySize = Enquiry2.MemorySize >> 20;
+  Controller->Channels = Enquiry2->ActualChannels;
+  Controller->Targets = Enquiry2->MaxTargets;
+  Controller->MemorySize = Enquiry2->MemorySize >> 20;
   Controller->V1.SAFTE_EnclosureManagementEnabled =
-    (Enquiry2.FaultManagementType == DAC960_V1_SAFTE);
+    (Enquiry2->FaultManagementType == DAC960_V1_SAFTE);
   /*
     Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive
     Count, Maximum Blocks per Command, Controller Scatter/Gather Limit, and
@@ -1183,8 +1572,8 @@
     Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth;
   Controller->LogicalDriveCount =
     Controller->V1.Enquiry.NumberOfLogicalDrives;
-  Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand;
-  Controller->ControllerScatterGatherLimit = Enquiry2.MaxScatterGatherEntries;
+  Controller->MaxBlocksPerCommand = Enquiry2->MaxBlocksPerCommand;
+  Controller->ControllerScatterGatherLimit = Enquiry2->MaxScatterGatherEntries;
   Controller->DriverScatterGatherLimit =
     Controller->ControllerScatterGatherLimit;
   if (Controller->DriverScatterGatherLimit > DAC960_V1_ScatterGatherLimit)
@@ -1192,11 +1581,11 @@
   /*
     Initialize the Stripe Size, Segment Size, and Geometry Translation.
   */
-  Controller->V1.StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor
+  Controller->V1.StripeSize = Config2->BlocksPerStripe * Config2->BlockFactor
 			      >> (10 - DAC960_BlockSizeBits);
-  Controller->V1.SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor
+  Controller->V1.SegmentSize = Config2->BlocksPerCacheLine * Config2->BlockFactor
 			       >> (10 - DAC960_BlockSizeBits);
-  switch (Config2.DriveGeometry)
+  switch (Config2->DriveGeometry)
     {
     case DAC960_V1_Geometry_128_32:
       Controller->V1.GeometryTranslationHeads = 128;
@@ -1207,6 +1596,7 @@
       Controller->V1.GeometryTranslationSectors = 63;
       break;
     default:
+      free_dma_loaf(Controller->PCIDevice, &local_dma);
       return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
     }
   /*
@@ -1220,8 +1610,11 @@
       Controller->V1.BackgroundInitializationStatusSupported = true;
       DAC960_V1_ExecuteType3B(Controller,
 			      DAC960_V1_BackgroundInitializationControl, 0x20,
-			      &Controller->
-			       V1.LastBackgroundInitializationStatus);
+			      Controller->
+			       V1.BackgroundInitializationStatusDMA);
+      memcpy(&Controller->V1.LastBackgroundInitializationStatus,
+		Controller->V1.BackgroundInitializationStatus,
+		sizeof(DAC960_V1_BackgroundInitializationStatus_T));
     }
   /*
     Initialize the Logical Drive Initially Accessible flag.
@@ -1234,6 +1627,7 @@
 	DAC960_V1_LogicalDrive_Offline)
       Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true;
   Controller->V1.LastRebuildStatus = DAC960_V1_NoRebuildOrCheckInProgress;
+  free_dma_loaf(Controller->PCIDevice, &local_dma);
   return true;
 }
 
@@ -1247,17 +1641,20 @@
 						     *Controller)
 {
   DAC960_V2_ControllerInfo_T *ControllerInfo =
-    &Controller->V2.ControllerInformation;
+    		&Controller->V2.ControllerInformation;
   unsigned short LogicalDeviceNumber = 0;
   int ModelNameLength;
-  if (!DAC960_V2_ControllerInfo(Controller, DAC960_V2_GetControllerInfo,
-				ControllerInfo,
-				sizeof(DAC960_V2_ControllerInfo_T)))
+
+  /* Get data into dma-able area, then copy into permanant location */
+  if (!DAC960_V2_NewControllerInfo(Controller))
     return DAC960_Failure(Controller, "GET CONTROLLER INFO");
-  if (!DAC960_V2_GeneralInfo(Controller, DAC960_V2_GetHealthStatus,
-			     Controller->V2.HealthStatusBuffer,
-			     sizeof(DAC960_V2_HealthStatusBuffer_T)))
+  memcpy(ControllerInfo, Controller->V2.NewControllerInformation,
+			sizeof(DAC960_V2_ControllerInfo_T));
+	 
+  
+  if (!DAC960_V2_GeneralInfo(Controller))
     return DAC960_Failure(Controller, "GET HEALTH STATUS");
+
   /*
     Initialize the Controller Model Name and Full Model Name fields.
   */
@@ -1325,14 +1722,11 @@
   while (true)
     {
       DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo =
-	&Controller->V2.NewLogicalDeviceInformation;
+	Controller->V2.NewLogicalDeviceInformation;
       DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo;
       DAC960_V2_PhysicalDevice_T PhysicalDevice;
-      if (!DAC960_V2_LogicalDeviceInfo(Controller,
-				       DAC960_V2_GetLogicalDeviceInfoValid,
-				       LogicalDeviceNumber,
-				       NewLogicalDeviceInfo,
-				       sizeof(DAC960_V2_LogicalDeviceInfo_T)))
+
+      if (!DAC960_V2_NewLogicalDeviceInfo(Controller, LogicalDeviceNumber))
 	break;
       LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber;
       if (LogicalDeviceNumber > DAC960_MaxLogicalDrives)
@@ -1421,26 +1815,61 @@
 static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
 						 *Controller)
 {
-  DAC960_V1_DCDB_T DCDBs[DAC960_V1_MaxChannels], *DCDB;
-  Completion_T Completions[DAC960_V1_MaxChannels], *Completion;
+  struct dma_loaf local_dma;
+
+  dma_addr_t DCDBs_dma[DAC960_V1_MaxChannels];
+  DAC960_V1_DCDB_T *DCDBs_cpu[DAC960_V1_MaxChannels];
+
+  dma_addr_t SCSI_Inquiry_dma[DAC960_V1_MaxChannels];
+  DAC960_SCSI_Inquiry_T *SCSI_Inquiry_cpu[DAC960_V1_MaxChannels];
+
+  dma_addr_t SCSI_NewInquiryUnitSerialNumberDMA[DAC960_V1_MaxChannels];
+  DAC960_SCSI_Inquiry_UnitSerialNumber_T *SCSI_NewInquiryUnitSerialNumberCPU[DAC960_V1_MaxChannels];
+
+  Completion_T Completions[DAC960_V1_MaxChannels];
   unsigned long ProcessorFlags;
   int Channel, TargetID;
+
+  if (!init_dma_loaf(Controller->PCIDevice, &local_dma, 
+		DAC960_V1_MaxChannels*(sizeof(DAC960_V1_DCDB_T) +
+			sizeof(DAC960_SCSI_Inquiry_T) +
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T))))
+     return DAC960_Failure(Controller,
+                        "DMA ALLOCATION FAILED IN ReadDeviceConfiguration"); 
+   
+  for (Channel = 0; Channel < Controller->Channels; Channel++) {
+	DCDBs_cpu[Channel] = slice_dma_loaf(&local_dma,
+			sizeof(DAC960_V1_DCDB_T), DCDBs_dma + Channel);
+	SCSI_Inquiry_cpu[Channel] = slice_dma_loaf(&local_dma,
+			sizeof(DAC960_SCSI_Inquiry_T),
+			SCSI_Inquiry_dma + Channel);
+	SCSI_NewInquiryUnitSerialNumberCPU[Channel] = slice_dma_loaf(&local_dma,
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
+			SCSI_NewInquiryUnitSerialNumberDMA + Channel);
+  }
+		
   for (TargetID = 0; TargetID < Controller->Targets; TargetID++)
     {
+      /*
+       * For each channel, submit a probe for a device on that channel.
+       * The timeout interval for a device that is present is 10 seconds.
+       * With this approach, the timeout periods can elapse in parallel
+       * on each channel.
+       */
       for (Channel = 0; Channel < Controller->Channels; Channel++)
 	{
+	  dma_addr_t NewInquiryStandardDataDMA = SCSI_Inquiry_dma[Channel];
+  	  DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel];
+  	  dma_addr_t DCDB_dma = DCDBs_dma[Channel];
 	  DAC960_Command_T *Command = Controller->Commands[Channel];
-	  DAC960_SCSI_Inquiry_T *InquiryStandardData =
-	    &Controller->V1.InquiryStandardData[Channel][TargetID];
-	  InquiryStandardData->PeripheralDeviceType = 0x1F;
-	  Completion = &Completions[Channel];
+          Completion_T *Completion = &Completions[Channel];
+
 	  init_completion(Completion);
-	  DCDB = &DCDBs[Channel];
 	  DAC960_V1_ClearCommand(Command);
 	  Command->CommandType = DAC960_ImmediateCommand;
 	  Command->Completion = Completion;
 	  Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
-	  Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus32(DCDB);
+	  Command->V1.CommandMailbox.Type3.BusAddress = DCDB_dma;
 	  DCDB->Channel = Channel;
 	  DCDB->TargetID = TargetID;
 	  DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -1449,7 +1878,7 @@
 	  DCDB->NoAutomaticRequestSense = false;
 	  DCDB->DisconnectPermitted = true;
 	  DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
-	  DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData);
+	  DCDB->BusAddress = NewInquiryStandardDataDMA;
 	  DCDB->CDBLength = 6;
 	  DCDB->TransferLengthHigh4 = 0;
 	  DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -1463,20 +1892,39 @@
 	  DAC960_QueueCommand(Command);
 	  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	}
+      /*
+       * Wait for the problems submitted in the previous loop
+       * to complete.  On the probes that are successful, 
+       * get the serial number of the device that was found.
+       */
       for (Channel = 0; Channel < Controller->Channels; Channel++)
 	{
-	  DAC960_Command_T *Command = Controller->Commands[Channel];
+	  DAC960_SCSI_Inquiry_T *InquiryStandardData =
+	    &Controller->V1.InquiryStandardData[Channel][TargetID];
+	  DAC960_SCSI_Inquiry_T *NewInquiryStandardData = SCSI_Inquiry_cpu[Channel];
+	  dma_addr_t NewInquiryUnitSerialNumberDMA =
+			SCSI_NewInquiryUnitSerialNumberDMA[Channel];
+	  DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber =
+	    		SCSI_NewInquiryUnitSerialNumberCPU[Channel];
 	  DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
 	    &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID];
-	  InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
-	  Completion = &Completions[Channel];
+	  DAC960_Command_T *Command = Controller->Commands[Channel];
+  	  DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel];
+          Completion_T *Completion = &Completions[Channel];
+
 	  wait_for_completion(Completion);
-	  if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion)
+
+	  if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) {
+	    memset(InquiryStandardData, 0, sizeof(DAC960_SCSI_Inquiry_T));
+	    InquiryStandardData->PeripheralDeviceType = 0x1F;
 	    continue;
+	  } else
+	    memcpy(InquiryStandardData, NewInquiryStandardData, sizeof(DAC960_SCSI_Inquiry_T));
+	
+	  /* Preserve Channel and TargetID values from the previous loop */
 	  Command->Completion = Completion;
-	  DCDB = &DCDBs[Channel];
 	  DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	  DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber);
+	  DCDB->BusAddress = NewInquiryUnitSerialNumberDMA;
 	  DCDB->SenseLength = sizeof(DCDB->SenseData);
 	  DCDB->CDB[0] = 0x12; /* INQUIRY */
 	  DCDB->CDB[1] = 1; /* EVPD = 1 */
@@ -1488,8 +1936,17 @@
 	  DAC960_QueueCommand(Command);
 	  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	  wait_for_completion(Completion);
+
+	  if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) {
+	  	memset(InquiryUnitSerialNumber, 0,
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+	  	InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+	  } else
+	  	memcpy(InquiryUnitSerialNumber, NewInquiryUnitSerialNumber,
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
 	}
     }
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
   return true;
 }
 
@@ -1506,74 +1963,55 @@
 {
   unsigned char Channel = 0, TargetID = 0, LogicalUnit = 0;
   unsigned short PhysicalDeviceIndex = 0;
+
   while (true)
     {
       DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo =
-	&Controller->V2.NewPhysicalDeviceInformation;
+		Controller->V2.NewPhysicalDeviceInformation;
       DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo;
+      DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber =
+		Controller->V2.NewInquiryUnitSerialNumber;
       DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber;
-      DAC960_Command_T *Command;
-      DAC960_V2_CommandMailbox_T *CommandMailbox;
-      if (!DAC960_V2_PhysicalDeviceInfo(Controller,
-					DAC960_V2_GetPhysicalDeviceInfoValid,
-					Channel,
-					TargetID,
-					LogicalUnit,
-					NewPhysicalDeviceInfo,
-					sizeof(DAC960_V2_PhysicalDeviceInfo_T)))
+
+      if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit))
 	  break;
-      Channel = NewPhysicalDeviceInfo->Channel;
-      TargetID = NewPhysicalDeviceInfo->TargetID;
-      LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit;
+
       PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *)
-	kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
+		kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
       if (PhysicalDeviceInfo == NULL)
-	return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION");
+		return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION");
       Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] =
-	PhysicalDeviceInfo;
+		PhysicalDeviceInfo;
       memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo,
-	     sizeof(DAC960_V2_PhysicalDeviceInfo_T));
+		sizeof(DAC960_V2_PhysicalDeviceInfo_T));
+
       InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *)
 	kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC);
-      if (InquiryUnitSerialNumber == NULL)
+      if (InquiryUnitSerialNumber == NULL) {
+	kfree(PhysicalDeviceInfo);
 	return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION");
+      }
       Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex] =
-	InquiryUnitSerialNumber;
-      memset(InquiryUnitSerialNumber, 0,
-	     sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
-      InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
-      Command = DAC960_AllocateCommand(Controller);
-      CommandMailbox = &Command->V2.CommandMailbox;
-      DAC960_V2_ClearCommand(Command);
-      Command->CommandType = DAC960_ImmediateCommand;
-      CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru;
-      CommandMailbox->SCSI_10.CommandControlBits
-			     .DataTransferControllerToHost = true;
-      CommandMailbox->SCSI_10.CommandControlBits
-			     .NoAutoRequestSense = true;
-      CommandMailbox->SCSI_10.DataTransferSize =
-	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-      CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit;
-      CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID;
-      CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel;
-      CommandMailbox->SCSI_10.CDBLength = 6;
-      CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */
-      CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */
-      CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */
-      CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */
-      CommandMailbox->SCSI_10.SCSI_CDB[4] =
-	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-      CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */
-      CommandMailbox->SCSI_10.DataTransferMemoryAddress
-			     .ScatterGatherSegments[0]
-			     .SegmentDataPointer =
-	Virtual_to_Bus64(InquiryUnitSerialNumber);
-      CommandMailbox->SCSI_10.DataTransferMemoryAddress
-			     .ScatterGatherSegments[0]
-			     .SegmentByteCount =
-	CommandMailbox->SCSI_10.DataTransferSize;
-      DAC960_ExecuteCommand(Command);
-      DAC960_DeallocateCommand(Command);
+		InquiryUnitSerialNumber;
+
+      Channel = NewPhysicalDeviceInfo->Channel;
+      TargetID = NewPhysicalDeviceInfo->TargetID;
+      LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit;
+
+      /*
+	 Some devices do NOT have Unit Serial Numbers.
+	 This command fails for them.  But, we still want to
+	 remember those devices are there.  Construct a
+	 UnitSerialNumber structure for the failure case.
+      */
+      if (!DAC960_V2_NewInquiryUnitSerialNumber(Controller, Channel, TargetID, LogicalUnit)) {
+      	memset(InquiryUnitSerialNumber, 0,
+             sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+     	InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+      } else
+      	memcpy(InquiryUnitSerialNumber, NewInquiryUnitSerialNumber,
+		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+
       PhysicalDeviceIndex++;
       LogicalUnit++;
     }
@@ -1947,12 +2385,12 @@
     Initialize the I/O Request Queue.
   */
   RequestQueue = &Controller->RequestQueue;
-  Controller->queue_lock = SPIN_LOCK_UNLOCKED;
   blk_init_queue(RequestQueue, DAC960_RequestFunction, &Controller->queue_lock);
   RequestQueue->queuedata = Controller;
   blk_queue_max_hw_segments(RequestQueue,
 			    Controller->DriverScatterGatherLimit);
-  blk_queue_max_phys_segments(RequestQueue, ~0);
+  blk_queue_max_phys_segments(RequestQueue,
+		 	    Controller->DriverScatterGatherLimit);
   blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
 
   for (n = 0; n < DAC960_MaxLogicalDrives; n++) {
@@ -1978,8 +2416,10 @@
 {
   int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
   int disk;
+
   for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++)
 	  del_gendisk(Controller->disks[disk]);
+
   /*
     Unregister the Block Device Major Number for this DAC960 Controller.
   */
@@ -2082,159 +2522,155 @@
 
 
 /*
-  DAC960_DetectControllers detects Mylex DAC960/AcceleRAID/eXtremeRAID
+ * DAC960_DetectCleanup releases the resources that were allocated
+ * during DAC960_DetectController().  DAC960_DetectController can
+ * has several internal failure points, so not ALL resources may 
+ * have been allocated.  It's important to free only
+ * resources that HAVE been allocated.  The code below always
+ * tests that the resource has been allocated before attempting to
+ * free it.
+ */
+static void DAC960_DetectCleanup(DAC960_Controller_T *Controller)
+{
+  int i;
+
+  /* Free the memory mailbox, status, and related structures */
+  free_dma_loaf(Controller->PCIDevice, &Controller->DmaPages);
+  if (Controller->MemoryMappedAddress) {
+  	switch(Controller->HardwareType)
+  	{
+		case DAC960_BA_Controller:
+			DAC960_BA_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_LP_Controller:
+			DAC960_LP_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_LA_Controller:
+			DAC960_LA_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_PG_Controller:
+			DAC960_PG_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_PD_Controller:
+			DAC960_PD_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_P_Controller:
+			DAC960_PD_DisableInterrupts(Controller->BaseAddress);
+			break;
+  	}
+  	iounmap(Controller->MemoryMappedAddress);
+  }
+  if (Controller->IRQ_Channel)
+  	free_irq(Controller->IRQ_Channel, Controller);
+  if (Controller->IO_Address)
+	release_region(Controller->IO_Address, 0x80);
+  pci_disable_device(Controller->PCIDevice);
+  for (i = 0; (i < DAC960_MaxLogicalDrives) && Controller->disks[i]; i++)
+       put_disk(Controller->disks[i]);
+  DAC960_Controllers[Controller->ControllerNumber] = NULL;
+  kfree(Controller);
+}
+
+
+/*
+  DAC960_DetectController detects Mylex DAC960/AcceleRAID/eXtremeRAID
   PCI RAID Controllers by interrogating the PCI Configuration Space for
   Controller Type.
 */
 
-static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
-{
-  void (*InterruptHandler)(int, void *, Registers_T *) = NULL;
+static DAC960_Controller_T * 
+DAC960_DetectController(PCI_Device_T *PCI_Device,
+					const struct pci_device_id *entry)
+{
+  struct DAC960_privdata *privdata = (struct DAC960_privdata *)entry->driver_data;
+  void (*InterruptHandler)(int, void *, Registers_T *) = privdata->InterruptHandler;
+  unsigned int MemoryWindowSize = privdata->MemoryWindowSize;
   DAC960_Controller_T *Controller = NULL;
-  DAC960_FirmwareType_T FirmwareType = 0;
-  unsigned short VendorID = 0, DeviceID = 0;
-  unsigned int MemoryWindowSize = 0;
-  PCI_Device_T *PCI_Device = NULL;
+  unsigned char DeviceFunction = PCI_Device->devfn;
+  unsigned char ErrorStatus, Parameter0, Parameter1;
+  unsigned int IRQ_Channel = PCI_Device->irq;
+  void *BaseAddress;
   int i;
-  switch (HardwareType)
-    {
-    case DAC960_BA_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_BA;
-      FirmwareType = DAC960_V2_Controller;
-      InterruptHandler = DAC960_BA_InterruptHandler;
-      MemoryWindowSize = DAC960_BA_RegisterWindowSize;
-      break;
-    case DAC960_LP_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_LP;
-      FirmwareType = DAC960_LP_Controller;
-      InterruptHandler = DAC960_LP_InterruptHandler;
-      MemoryWindowSize = DAC960_LP_RegisterWindowSize;
-      break;
-    case DAC960_LA_Controller:
-      VendorID = PCI_VENDOR_ID_DEC;
-      DeviceID = PCI_DEVICE_ID_DEC_21285;
-      FirmwareType = DAC960_V1_Controller;
-      InterruptHandler = DAC960_LA_InterruptHandler;
-      MemoryWindowSize = DAC960_LA_RegisterWindowSize;
-      break;
-    case DAC960_PG_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PG;
-      FirmwareType = DAC960_V1_Controller;
-      InterruptHandler = DAC960_PG_InterruptHandler;
-      MemoryWindowSize = DAC960_PG_RegisterWindowSize;
-      break;
-    case DAC960_PD_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PD;
-      FirmwareType = DAC960_V1_Controller;
-      InterruptHandler = DAC960_PD_InterruptHandler;
-      MemoryWindowSize = DAC960_PD_RegisterWindowSize;
-      break;
-    case DAC960_P_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_P;
-      FirmwareType = DAC960_V1_Controller;
-      InterruptHandler = DAC960_P_InterruptHandler;
-      MemoryWindowSize = DAC960_PD_RegisterWindowSize;
-      break;
-    }
-  while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
-    {
-      DAC960_IO_Address_T IO_Address = 0;
-      DAC960_PCI_Address_T PCI_Address = 0;
-      unsigned char Bus = PCI_Device->bus->number;
-      unsigned char DeviceFunction = PCI_Device->devfn;
-      unsigned char Device = DeviceFunction >> 3;
-      unsigned char Function = DeviceFunction & 0x7;
-      unsigned char ErrorStatus, Parameter0, Parameter1;
-      unsigned int IRQ_Channel = PCI_Device->irq;
-      void *BaseAddress;
-      Controller = NULL;
-      if (pci_enable_device(PCI_Device) != 0) continue;
-      switch (HardwareType)
-	{
+
+  Controller = (DAC960_Controller_T *)
+	kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
+  if (Controller == NULL) {
+	DAC960_Error("Unable to allocate Controller structure for "
+                       "Controller at\n", NULL);
+	return NULL;
+  }
+  memset(Controller, 0, sizeof(DAC960_Controller_T));
+  Controller->ControllerNumber = DAC960_ControllerCount;
+  DAC960_Controllers[DAC960_ControllerCount++] = Controller;
+  Controller->Bus = PCI_Device->bus->number;
+  Controller->FirmwareType = privdata->FirmwareType;
+  Controller->HardwareType = privdata->HardwareType;
+  Controller->Device = DeviceFunction >> 3;
+  Controller->Function = DeviceFunction & 0x7;
+  Controller->PCIDevice = PCI_Device;
+  strcpy(Controller->FullModelName, "DAC960");
+
+  if (pci_enable_device(PCI_Device))  {
+        kfree(Controller);
+	goto Failure;
+  }
+
+  switch (Controller->HardwareType)
+  {
 	case DAC960_BA_Controller:
-	  PCI_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
 	case DAC960_LP_Controller:
-	  PCI_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
 	case DAC960_LA_Controller:
-	  if (!(PCI_Device->subsystem_vendor == PCI_VENDOR_ID_MYLEX &&
-		PCI_Device->subsystem_device == PCI_DEVICE_ID_MYLEX_DAC960_LA))
-	    continue;
-	  PCI_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
 	case DAC960_PG_Controller:
-	  PCI_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
 	case DAC960_PD_Controller:
-	  IO_Address = pci_resource_start(PCI_Device, 0);
-	  PCI_Address = pci_resource_start(PCI_Device, 1);
+	  Controller->IO_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 1);
 	  break;
 	case DAC960_P_Controller:
-	  IO_Address = pci_resource_start(PCI_Device, 0);
-	  PCI_Address = pci_resource_start(PCI_Device, 1);
+	  Controller->IO_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 1);
 	  break;
-	}
-      if (DAC960_ControllerCount == DAC960_MaxControllers)
-	{
-	  DAC960_Error("More than %d DAC960 Controllers detected - "
-		       "ignoring from Controller at\n",
-		       NULL, DAC960_MaxControllers);
-	  goto Failure;
-	}
-      Controller = (DAC960_Controller_T *)
-	kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
-      if (Controller == NULL)
-	{
-	  DAC960_Error("Unable to allocate Controller structure for "
-		       "Controller at\n", NULL);
-	  goto Failure;
-	}
-      memset(Controller, 0, sizeof(DAC960_Controller_T));
-      for (i = 0; i < DAC960_MaxLogicalDrives; i++) {
-		Controller->disks[i] = alloc_disk(1<<DAC960_MaxPartitionsBits);
-		if (!Controller->disks[i])
-			goto Enomem;
-		Controller->disks[i]->private_data = (void*)i;
-		Controller->disks[i]->queue = &Controller->RequestQueue;
-      }
-      Controller->ControllerNumber = DAC960_ControllerCount;
-      init_waitqueue_head(&Controller->CommandWaitQueue);
-      init_waitqueue_head(&Controller->HealthStatusWaitQueue);
-      DAC960_Controllers[DAC960_ControllerCount++] = Controller;
-      DAC960_AnnounceDriver(Controller);
-      Controller->FirmwareType = FirmwareType;
-      Controller->HardwareType = HardwareType;
-      Controller->IO_Address = IO_Address;
-      Controller->PCI_Address = PCI_Address;
-      Controller->Bus = Bus;
-      Controller->Device = Device;
-      Controller->Function = Function;
-      /*
-	Map the Controller Register Window.
-      */
-      if (MemoryWindowSize < PAGE_SIZE)
+  }
+
+  pci_set_drvdata(PCI_Device, (void *)((int)Controller->ControllerNumber));
+  for (i = 0; i < DAC960_MaxLogicalDrives; i++) {
+	Controller->disks[i] = alloc_disk(1<<DAC960_MaxPartitionsBits);
+	if (!Controller->disks[i])
+		goto Failure;
+	Controller->disks[i]->private_data = (void *)i;
+	Controller->disks[i]->queue = &Controller->RequestQueue;
+  }
+  init_waitqueue_head(&Controller->CommandWaitQueue);
+  init_waitqueue_head(&Controller->HealthStatusWaitQueue);
+  Controller->queue_lock = SPIN_LOCK_UNLOCKED; 
+  DAC960_AnnounceDriver(Controller);
+  /*
+    Map the Controller Register Window.
+  */
+ if (MemoryWindowSize < PAGE_SIZE)
 	MemoryWindowSize = PAGE_SIZE;
-      Controller->MemoryMappedAddress =
-	ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize);
-      Controller->BaseAddress =
-	Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK);
-      if (Controller->MemoryMappedAddress == NULL)
-	{
+  Controller->MemoryMappedAddress =
+	ioremap_nocache(Controller->PCI_Address & PAGE_MASK, MemoryWindowSize);
+  Controller->BaseAddress =
+	Controller->MemoryMappedAddress + (Controller->PCI_Address & ~PAGE_MASK);
+  if (Controller->MemoryMappedAddress == NULL)
+  {
 	  DAC960_Error("Unable to map Controller Register Window for "
 		       "Controller at\n", Controller);
 	  goto Failure;
-	}
-      BaseAddress = Controller->BaseAddress;
-      switch (HardwareType)
-	{
+  }
+  BaseAddress = Controller->BaseAddress;
+  switch (Controller->HardwareType)
+  {
 	case DAC960_BA_Controller:
-	  DAC960_BA_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_BA_DisableInterrupts(BaseAddress);
 	  DAC960_BA_AcknowledgeHardwareMailboxStatus(BaseAddress);
 	  udelay(1000);
 	  while (DAC960_BA_InitializationInProgressP(BaseAddress))
@@ -2252,7 +2688,7 @@
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_BA_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_BA_EnableInterrupts(BaseAddress);
 	  Controller->QueueCommand = DAC960_BA_QueueCommand;
 	  Controller->ReadControllerConfiguration =
 	    DAC960_V2_ReadControllerConfiguration;
@@ -2264,7 +2700,7 @@
 	    DAC960_V2_QueueReadWriteCommand;
 	  break;
 	case DAC960_LP_Controller:
-	  DAC960_LP_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_LP_DisableInterrupts(BaseAddress);
 	  DAC960_LP_AcknowledgeHardwareMailboxStatus(BaseAddress);
 	  udelay(1000);
 	  while (DAC960_LP_InitializationInProgressP(BaseAddress))
@@ -2282,7 +2718,7 @@
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_LP_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_LP_EnableInterrupts(BaseAddress);
 	  Controller->QueueCommand = DAC960_LP_QueueCommand;
 	  Controller->ReadControllerConfiguration =
 	    DAC960_V2_ReadControllerConfiguration;
@@ -2294,7 +2730,7 @@
 	    DAC960_V2_QueueReadWriteCommand;
 	  break;
 	case DAC960_LA_Controller:
-	  DAC960_LA_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_LA_DisableInterrupts(BaseAddress);
 	  DAC960_LA_AcknowledgeHardwareMailboxStatus(BaseAddress);
 	  udelay(1000);
 	  while (DAC960_LA_InitializationInProgressP(BaseAddress))
@@ -2312,7 +2748,7 @@
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_LA_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_LA_EnableInterrupts(BaseAddress);
 	  if (Controller->V1.DualModeMemoryMailboxInterface)
 	    Controller->QueueCommand = DAC960_LA_QueueCommandDualMode;
 	  else Controller->QueueCommand = DAC960_LA_QueueCommandSingleMode;
@@ -2326,7 +2762,7 @@
 	    DAC960_V1_QueueReadWriteCommand;
 	  break;
 	case DAC960_PG_Controller:
-	  DAC960_PG_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_PG_DisableInterrupts(BaseAddress);
 	  DAC960_PG_AcknowledgeHardwareMailboxStatus(BaseAddress);
 	  udelay(1000);
 	  while (DAC960_PG_InitializationInProgressP(BaseAddress))
@@ -2344,7 +2780,7 @@
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_PG_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_PG_EnableInterrupts(BaseAddress);
 	  if (Controller->V1.DualModeMemoryMailboxInterface)
 	    Controller->QueueCommand = DAC960_PG_QueueCommandDualMode;
 	  else Controller->QueueCommand = DAC960_PG_QueueCommandSingleMode;
@@ -2373,10 +2809,16 @@
 					    &Parameter0, &Parameter1) &&
 		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
 					   Parameter0, Parameter1))
-		goto Failure1;
+		goto Failure;
 	      udelay(10);
 	    }
-	  DAC960_PD_EnableInterrupts(Controller->BaseAddress);
+	  if (!DAC960_V1_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to allocate DMA mapped memory "
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_PD_EnableInterrupts(BaseAddress);
 	  Controller->QueueCommand = DAC960_PD_QueueCommand;
 	  Controller->ReadControllerConfiguration =
 	    DAC960_V1_ReadControllerConfiguration;
@@ -2403,10 +2845,16 @@
 					    &Parameter0, &Parameter1) &&
 		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
 					   Parameter0, Parameter1))
-		goto Failure1;
+		goto Failure;
 	      udelay(10);
 	    }
-	  DAC960_PD_EnableInterrupts(Controller->BaseAddress);
+	  if (!DAC960_V1_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to allocate DMA mapped memory"
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_PD_EnableInterrupts(BaseAddress);
 	  Controller->QueueCommand = DAC960_P_QueueCommand;
 	  Controller->ReadControllerConfiguration =
 	    DAC960_V1_ReadControllerConfiguration;
@@ -2417,107 +2865,47 @@
 	  Controller->QueueReadWriteCommand =
 	    DAC960_V1_QueueReadWriteCommand;
 	  break;
-	}
-      /*
-	Acquire shared access to the IRQ Channel.
-      */
-      if (IRQ_Channel == 0)
-	{
-	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure1;
-	}
-      strcpy(Controller->FullModelName, "DAC960");
-      if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ,
+  }
+  /*
+     Acquire shared access to the IRQ Channel.
+  */
+  if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ,
 		      Controller->FullModelName, Controller) < 0)
-	{
-	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure1;
-	}
-      Controller->IRQ_Channel = IRQ_Channel;
-      DAC960_ActiveControllerCount++;
-      Controller->InitialCommand.CommandIdentifier = 1;
-      Controller->InitialCommand.Controller = Controller;
-      Controller->Commands[0] = &Controller->InitialCommand;
-      Controller->FreeCommands = &Controller->InitialCommand;
-      Controller->ControllerDetectionSuccessful = true;
-      continue;
-    Failure1:
-      if (Controller->IO_Address) release_region(Controller->IO_Address, 0x80);
-    Failure:
-      if (IO_Address == 0)
+  {
+	DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
+		       Controller, Controller->IRQ_Channel);
+	goto Failure;
+  }
+  Controller->IRQ_Channel = IRQ_Channel;
+  Controller->InitialCommand.CommandIdentifier = 1;
+  Controller->InitialCommand.Controller = Controller;
+  Controller->Commands[0] = &Controller->InitialCommand;
+  Controller->FreeCommands = &Controller->InitialCommand;
+  return Controller;
+      
+Failure:
+  if (Controller->IO_Address == 0)
 	DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
 		     "PCI Address 0x%X\n", Controller,
-		     Bus, Device, Function, PCI_Address);
-      else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
+		     Controller->Bus, Controller->Device,
+		     Controller->Function, Controller->PCI_Address);
+  else
+	DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
 			"0x%X PCI Address 0x%X\n", Controller,
-			Bus, Device, Function, IO_Address, PCI_Address);
-      if (Controller == NULL) break;
-      if (Controller->MemoryMappedAddress != NULL)
-	iounmap(Controller->MemoryMappedAddress);
-      if (Controller->IRQ_Channel > 0)
-	free_irq(IRQ_Channel, Controller);
-    }
-    return;
-Enomem:
-      while (i--)
-	put_disk(Controller->disks[i]);
-      kfree(Controller);
-      goto Failure;
-}
-
-
-/*
-  DAC960_SortControllers sorts the Controllers by PCI Bus and Device Number.
-*/
-
-static void DAC960_SortControllers(void)
-{
-  int ControllerNumber, LastInterchange, Bound, j;
-  LastInterchange = DAC960_ControllerCount-1;
-  while (LastInterchange > 0)
-    {
-      Bound = LastInterchange;
-      LastInterchange = 0;
-      for (j = 0; j < Bound; j++)
-	{
-	  DAC960_Controller_T *Controller1 = DAC960_Controllers[j];
-	  DAC960_Controller_T *Controller2 = DAC960_Controllers[j+1];
-	  if (Controller1->Bus > Controller2->Bus ||
-	      (Controller1->Bus == Controller2->Bus &&
-	       (Controller1->Device > Controller2->Device)))
-	    {
-	      Controller2->ControllerNumber = j;
-	      DAC960_Controllers[j] = Controller2;
-	      Controller1->ControllerNumber = j+1;
-	      DAC960_Controllers[j+1] = Controller1;
-	      LastInterchange = j;
-	    }
-	}
-    }
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      if (!Controller->ControllerDetectionSuccessful)
-	{
-	  int i;
-	  DAC960_Controllers[ControllerNumber] = NULL;
-	  for (i = 0; i < DAC960_MaxLogicalDrives; i++)
-		put_disk(Controller->disks[i]);
-	  kfree(Controller);
-	}
-    }
+			Controller->Bus, Controller->Device,
+			Controller->Function, Controller->IO_Address,
+			Controller->PCI_Address);
+  DAC960_DetectCleanup(Controller);
+  DAC960_ControllerCount--;
+  return NULL;
 }
 
-
 /*
   DAC960_InitializeController initializes Controller.
 */
 
-static void DAC960_InitializeController(DAC960_Controller_T *Controller)
+static boolean 
+DAC960_InitializeController(DAC960_Controller_T *Controller)
 {
   if (DAC960_ReadControllerConfiguration(Controller) &&
       DAC960_ReportControllerConfiguration(Controller) &&
@@ -2536,8 +2924,9 @@
       Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction;
       add_timer(&Controller->MonitoringTimer);
       Controller->ControllerInitialized = true;
+      return true;
     }
-  else DAC960_FinalizeController(Controller);
+  return false;
 }
 
 
@@ -2547,35 +2936,38 @@
 
 static void DAC960_FinalizeController(DAC960_Controller_T *Controller)
 {
-  int i;
   if (Controller->ControllerInitialized)
     {
-      del_timer(&Controller->MonitoringTimer);
+      unsigned long ProcessorFlags;
+
+      /*
+       * Acquiring and releasing lock here eliminates
+       * a very low probability race.
+       *
+       * The code below allocates controller command structures
+       * from the free list without holding the controller lock.
+       * This is safe assuming there is no other activity on
+       * the controller at the time.
+       * 
+       * But, there might be a monitoring command still
+       * in progress.  Setting the Shutdown flag while holding
+       * the lock ensures that there is no monitoring command
+       * in the interrupt handler currently, and any monitoring
+       * commands that complete from this time on will NOT return
+       * their command structure to the free list.
+       */
+      DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+      Controller->ShutdownMonitoringTimer = 1;
+      DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+      del_timer_sync(&Controller->MonitoringTimer);
       if (Controller->FirmwareType == DAC960_V1_Controller)
 	{
 	  DAC960_Notice("Flushing Cache...", Controller);
-	  DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, NULL);
+	  DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, 0);
 	  DAC960_Notice("done\n", Controller);
-	  switch (Controller->HardwareType)
-	    {
-	    case DAC960_LA_Controller:
-	      if (Controller->V1.DualModeMemoryMailboxInterface)
-		free_pages(Controller->MemoryMailboxPagesAddress,
-			   Controller->MemoryMailboxPagesOrder);
-	      else DAC960_LA_SaveMemoryMailboxInfo(Controller);
-	      break;
-	    case DAC960_PG_Controller:
-	      if (Controller->V1.DualModeMemoryMailboxInterface)
-		free_pages(Controller->MemoryMailboxPagesAddress,
-			   Controller->MemoryMailboxPagesOrder);
-	      else DAC960_PG_SaveMemoryMailboxInfo(Controller);
-	      break;
-	    case DAC960_PD_Controller:
+
+	  if (Controller->HardwareType == DAC960_PD_Controller)
 	      release_region(Controller->IO_Address, 0x80);
-	      break;
-	    default:
-	      break;
-	    }
 	}
       else
 	{
@@ -2583,51 +2975,48 @@
 	  DAC960_V2_DeviceOperation(Controller, DAC960_V2_PauseDevice,
 				    DAC960_V2_RAID_Controller);
 	  DAC960_Notice("done\n", Controller);
-	  free_pages(Controller->MemoryMailboxPagesAddress,
-		     Controller->MemoryMailboxPagesOrder);
 	}
     }
-  free_irq(Controller->IRQ_Channel, Controller);
-  iounmap(Controller->MemoryMappedAddress);
   DAC960_UnregisterBlockDevice(Controller);
   DAC960_DestroyAuxiliaryStructures(Controller);
-  DAC960_Controllers[Controller->ControllerNumber] = NULL;
-  for (i = 0; i < DAC960_MaxLogicalDrives; i++)
-	put_disk(Controller->disks[i]);
-  kfree(Controller);
+  DAC960_DestroyProcEntries(Controller);
+  DAC960_DetectCleanup(Controller);
 }
 
 
 /*
-  DAC960_Initialize initializes the DAC960 Driver.
+  DAC960_Probe verifies controller's existence and
+  initializes the DAC960 Driver for that controller.
 */
 
-static int DAC960_Initialize(void)
+static int 
+DAC960_Probe(struct pci_dev *dev, const struct pci_device_id *entry)
 {
-  int ControllerNumber;
-  DAC960_DetectControllers(DAC960_BA_Controller);
-  DAC960_DetectControllers(DAC960_LP_Controller);
-  DAC960_DetectControllers(DAC960_LA_Controller);
-  DAC960_DetectControllers(DAC960_PG_Controller);
-  DAC960_DetectControllers(DAC960_PD_Controller);
-  DAC960_DetectControllers(DAC960_P_Controller);
-  DAC960_SortControllers();
-  if (DAC960_ActiveControllerCount == 0) return -ENODEV;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      int disk;
-      if (Controller == NULL) continue;
-      DAC960_InitializeController(Controller);
-      for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) {
-	set_capacity(Controller->disks[disk], disk_size(Controller, disk));
-	add_disk(Controller->disks[disk]);
-      }
-    }
-  DAC960_CreateProcEntries();
-  register_reboot_notifier(&DAC960_NotifierBlock);
+  int disk;
+  DAC960_Controller_T *Controller;
+
+  if (DAC960_ControllerCount == DAC960_MaxControllers)
+  {
+	DAC960_Error("More than %d DAC960 Controllers detected - "
+                       "ignoring from Controller at\n",
+                       NULL, DAC960_MaxControllers);
+	return -ENODEV;
+  }
+
+  Controller = DAC960_DetectController(dev, entry);
+  if (!Controller)
+	return -ENODEV;
+
+  if (!DAC960_InitializeController(Controller)) {
+  	DAC960_FinalizeController(Controller);
+	return -ENODEV;
+  }
+
+  for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) {
+        set_capacity(Controller->disks[disk], disk_size(Controller, disk));
+        add_disk(Controller->disks[disk]);
+  }
+  DAC960_CreateProcEntries(Controller);
   return 0;
 }
 
@@ -2636,32 +3025,12 @@
   DAC960_Finalize finalizes the DAC960 Driver.
 */
 
-static void DAC960_Finalize(void)
-{
-  int ControllerNumber;
-  if (DAC960_ActiveControllerCount == 0) return;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    if (DAC960_Controllers[ControllerNumber] != NULL)
-      DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]);
-  DAC960_DestroyProcEntries();
-  unregister_reboot_notifier(&DAC960_NotifierBlock);
-}
-
-
-/*
-  DAC960_Notifier is the notifier for the DAC960 Driver.
-*/
-
-static int DAC960_Notifier(NotifierBlock_T *NotifierBlock,
-			   unsigned long Event,
-			   void *Buffer)
+static void DAC960_Remove(PCI_Device_T *PCI_Device)
 {
-  if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
-    return NOTIFY_DONE;
-  DAC960_Finalize();
-  return NOTIFY_OK;
+  int Controller_Number = (int)pci_get_drvdata(PCI_Device);
+  DAC960_Controller_T *Controller = DAC960_Controllers[Controller_Number];
+  if (Controller != NULL)
+      DAC960_FinalizeController(Controller);
 }
 
 
@@ -2674,57 +3043,60 @@
 {
   DAC960_Controller_T *Controller = Command->Controller;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
+  DAC960_V1_ScatterGatherSegment_T *ScatterGatherList =
+					Command->V1.ScatterGatherList;
+  struct scatterlist *ScatterList = Command->V1.ScatterList;
+  int DmaDirection, SegCount;
+
   DAC960_V1_ClearCommand(Command);
-  if (Command->SegmentCount == 1)
+
+  if (Command->CommandType == DAC960_ReadCommand)
+        DmaDirection = PCI_DMA_FROMDEVICE;
+  else
+        DmaDirection = PCI_DMA_TODEVICE;
+
+  SegCount = blk_rq_map_sg(&Controller->RequestQueue, Command->Request,
+								ScatterList);
+  /* pci_map_sg MAY change the value of SegCount */
+  SegCount = pci_map_sg(Command->PciDevice, ScatterList, SegCount,
+								DmaDirection);
+  Command->SegmentCount = SegCount;
+
+  if (SegCount == 1)
     {
       if (Command->CommandType == DAC960_ReadCommand)
 	CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read;
-      else CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write;
+      else 
+        CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write;
+
       CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
       CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
       CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
       CommandMailbox->Type5.BusAddress =
-	Virtual_to_Bus32(Command->RequestBuffer);
+			(DAC960_BusAddress32_T)sg_dma_address(ScatterList);	
     }
   else
     {
-      DAC960_V1_ScatterGatherSegment_T
-	*ScatterGatherList = Command->V1.ScatterGatherList;
-      BufferHeader_T *BufferHeader = Command->BufferHeader;
-      char *LastDataEndPointer = NULL;
-      int SegmentNumber = 0;
+      int i;
+
       if (Command->CommandType == DAC960_ReadCommand)
 	CommandMailbox->Type5.CommandOpcode = DAC960_V1_ReadWithScatterGather;
       else
 	CommandMailbox->Type5.CommandOpcode = DAC960_V1_WriteWithScatterGather;
+
       CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
       CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
       CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
-      CommandMailbox->Type5.BusAddress = Virtual_to_Bus32(ScatterGatherList);
-      CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
-      while (BufferHeader != NULL)
-	{
-	  if (bio_data(BufferHeader) == LastDataEndPointer)
-	    {
-	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
-		BufferHeader->bi_size;
-	      LastDataEndPointer += BufferHeader->bi_size;
-	    }
-	  else
-	    {
-	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus32(bio_data(BufferHeader));
-	      ScatterGatherList[SegmentNumber].SegmentByteCount =
-		BufferHeader->bi_size;
-	      LastDataEndPointer = bio_data(BufferHeader) +
-		BufferHeader->bi_size;
-	      if (SegmentNumber++ > Controller->DriverScatterGatherLimit)
-		panic("DAC960: Scatter/Gather Segment Overflow\n");
-	    }
-	  BufferHeader = BufferHeader->bi_next;
-	}
-      if (SegmentNumber != Command->SegmentCount)
-	panic("DAC960: SegmentNumber != SegmentCount\n");
+      CommandMailbox->Type5.BusAddress = Command->V1.ScatterGatherListDMA;
+
+      CommandMailbox->Type5.ScatterGatherCount = SegCount;
+
+      for (i = 0; i < SegCount; i++, ScatterList++, ScatterGatherList++) {
+		ScatterGatherList->SegmentDataPointer =
+			(DAC960_BusAddress32_T)sg_dma_address(ScatterList);
+		ScatterGatherList->SegmentByteCount =
+			(DAC960_ByteCount32_T)sg_dma_len(ScatterList);
+      }
     }
   DAC960_QueueCommand(Command);
 }
@@ -2739,18 +3111,32 @@
 {
   DAC960_Controller_T *Controller = Command->Controller;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
+  struct scatterlist *ScatterList = Command->V2.ScatterList;
+  int DmaDirection, SegCount;
+
   DAC960_V2_ClearCommand(Command);
+
+  if (Command->CommandType == DAC960_ReadCommand)
+        DmaDirection = PCI_DMA_FROMDEVICE;
+  else
+        DmaDirection = PCI_DMA_TODEVICE;
+
+  SegCount = blk_rq_map_sg(&Controller->RequestQueue, Command->Request,
+								ScatterList);
+  /* pci_map_sg MAY change the value of SegCount */
+  SegCount = pci_map_sg(Command->PciDevice, ScatterList, SegCount,
+								DmaDirection);
+  Command->SegmentCount = SegCount;
+
   CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10;
   CommandMailbox->SCSI_10.CommandControlBits.DataTransferControllerToHost =
     (Command->CommandType == DAC960_ReadCommand);
   CommandMailbox->SCSI_10.DataTransferSize =
     Command->BlockCount << DAC960_BlockSizeBits;
-  CommandMailbox->SCSI_10.RequestSenseBusAddress =
-    Virtual_to_Bus64(&Command->V2.RequestSense);
+  CommandMailbox->SCSI_10.RequestSenseBusAddress = Command->V2.RequestSenseDMA;
   CommandMailbox->SCSI_10.PhysicalDevice =
     Controller->V2.LogicalDriveToVirtualDevice[Command->LogicalDriveNumber];
-  CommandMailbox->SCSI_10.RequestSenseSize =
-    sizeof(DAC960_SCSI_RequestSense_T);
+  CommandMailbox->SCSI_10.RequestSenseSize = sizeof(DAC960_SCSI_RequestSense_T);
   CommandMailbox->SCSI_10.CDBLength = 10;
   CommandMailbox->SCSI_10.SCSI_CDB[0] =
     (Command->CommandType == DAC960_ReadCommand ? 0x28 : 0x2A);
@@ -2760,12 +3146,13 @@
   CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber;
   CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8;
   CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount;
-  if (Command->SegmentCount == 1)
+
+  if (SegCount == 1)
     {
       CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			     .ScatterGatherSegments[0]
 			     .SegmentDataPointer =
-	Virtual_to_Bus64(Command->RequestBuffer);
+	(DAC960_BusAddress64_T)sg_dma_address(ScatterList);
       CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			     .ScatterGatherSegments[0]
 			     .SegmentByteCount =
@@ -2773,49 +3160,30 @@
     }
   else
     {
-      DAC960_V2_ScatterGatherSegment_T
-	*ScatterGatherList = Command->V2.ScatterGatherList;
-      BufferHeader_T *BufferHeader = Command->BufferHeader;
-      char *LastDataEndPointer = NULL;
-      int SegmentNumber = 0;
-      if (Command->SegmentCount > 2)
+      DAC960_V2_ScatterGatherSegment_T *ScatterGatherList;
+      int i;
+
+      if (SegCount > 2)
 	{
+          ScatterGatherList = Command->V2.ScatterGatherList;
 	  CommandMailbox->SCSI_10.CommandControlBits
 			 .AdditionalScatterGatherListMemory = true;
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-			 .ExtendedScatterGather.ScatterGatherList0Length =
-	    Command->SegmentCount;
+		.ExtendedScatterGather.ScatterGatherList0Length = SegCount;
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			 .ExtendedScatterGather.ScatterGatherList0Address =
-	    Virtual_to_Bus64(ScatterGatherList);
+	    Command->V2.ScatterGatherListDMA;
 	}
       else
-	ScatterGatherList =
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
+	ScatterGatherList = CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments;
-      while (BufferHeader != NULL)
-	{
-	  if (bio_data(BufferHeader) == LastDataEndPointer)
-	    {
-	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
-		BufferHeader->bi_size;
-	      LastDataEndPointer += BufferHeader->bi_size;
-	    }
-	  else
-	    {
-	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus64(bio_data(BufferHeader));
-	      ScatterGatherList[SegmentNumber].SegmentByteCount =
-		BufferHeader->bi_size;
-	      LastDataEndPointer = bio_data(BufferHeader) +
-		BufferHeader->bi_size;
-	      if (SegmentNumber++ > Controller->DriverScatterGatherLimit)
-		panic("DAC960: Scatter/Gather Segment Overflow\n");
-	    }
-	  BufferHeader = BufferHeader->bi_next;
-	}
-      if (SegmentNumber != Command->SegmentCount)
-	panic("DAC960: SegmentNumber != SegmentCount\n");
+
+      for (i = 0; i < SegCount; i++, ScatterList++, ScatterGatherList++) {
+		ScatterGatherList->SegmentDataPointer =
+			(DAC960_BusAddress64_T)sg_dma_address(ScatterList);
+		ScatterGatherList->SegmentByteCount =
+			(DAC960_ByteCount64_T)sg_dma_len(ScatterList);
+      }
     }
   DAC960_QueueCommand(Command);
 }
@@ -2832,32 +3200,36 @@
 				     boolean WaitForCommand)
 {
   RequestQueue_T *RequestQueue = &Controller->RequestQueue;
-  ListHead_T *RequestQueueHead;
   IO_Request_T *Request;
   DAC960_Command_T *Command;
-  if (RequestQueue == NULL) return false;
-  RequestQueueHead = &RequestQueue->queue_head;
-  while (true)
-    {
-      if (list_empty(RequestQueueHead)) return false;
+
+  if (!Controller->ControllerInitialized)
+     return false;
+
+  while (true) {
+      if (blk_queue_empty(RequestQueue))
+          return false;
+
       Request = elv_next_request(RequestQueue);
       Command = DAC960_AllocateCommand(Controller);
-      if (Command != NULL) break;
-      if (!WaitForCommand) return false;
+      if (Command != NULL)
+          break;
+
+      if (!WaitForCommand)
+          return false;
+
       DAC960_WaitForCommand(Controller);
-    }
-  if (Request->cmd == READ)
+  }
+  if (rq_data_dir(Request) == READ)
     Command->CommandType = DAC960_ReadCommand;
-  else Command->CommandType = DAC960_WriteCommand;
+  else
+    Command->CommandType = DAC960_WriteCommand;
   Command->Completion = Request->waiting;
   Command->LogicalDriveNumber = (int)Request->rq_disk->private_data;
   Command->BlockNumber = Request->sector;
   Command->BlockCount = Request->nr_sectors;
-  Command->SegmentCount = Request->nr_phys_segments;
-  Command->BufferHeader = Request->bio;
-  Command->RequestBuffer = Request->buffer;
+  Command->Request = Request;
   blkdev_dequeue_request(Request);
-  blk_put_request(Request);
   DAC960_QueueReadWriteCommand(Command);
   return true;
 }
@@ -2904,16 +3276,43 @@
   individual Buffer.
 */
 
-static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
+static inline void DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
 						 boolean SuccessfulIO)
 {
-  bio_endio(BufferHeader, BufferHeader->bi_size, SuccessfulIO ? 0 : -EIO);
-  blk_finished_io(bio_sectors(BufferHeader));
-}
+	DAC960_CommandType_T CommandType = Command->CommandType;
+	IO_Request_T *Request = Command->Request;
+	int DmaDirection, UpToDate;
+
+	UpToDate = 0;
+	if (SuccessfulIO)
+		UpToDate = 1;
+
+	/*
+	 * We could save DmaDirection in the command structure
+	 * and just reuse that information here.
+	 */
+	if (CommandType == DAC960_ReadCommand ||
+		CommandType == DAC960_ReadRetryCommand)
+		DmaDirection = PCI_DMA_FROMDEVICE;
+	else
+		DmaDirection = PCI_DMA_TODEVICE;
 
-static inline int DAC960_PartitionByCommand(DAC960_Command_T *Command)
-{
-	return (int)Command->BufferHeader->bi_bdev->bd_disk->private_data;
+	pci_unmap_sg(Command->PciDevice, Command->V1.ScatterList,
+		Command->SegmentCount, DmaDirection);
+	/*
+	 * BlockCount is redundant with nr_sectors in the request
+	 * structure.  Consider eliminating BlockCount from the
+	 * command structure now that Command includes a pointer to
+	 * the request.
+	 */
+	 while (end_that_request_first(Request, UpToDate, Command->BlockCount))
+		 ;
+ 	 end_that_request_last(Request);
+
+	if (Command->Completion) {
+		complete(Command->Completion);
+		Command->Completion = NULL;
+	}
 }
 
 /*
@@ -2966,13 +3365,6 @@
 	       Controller, Controller->ControllerNumber,
 	       Command->LogicalDriveNumber, Command->BlockNumber,
 	       Command->BlockNumber + Command->BlockCount - 1);
-  if (DAC960_PartitionByCommand(Command) > 0)
-    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
-		 Controller, Controller->ControllerNumber,
-		 Command->LogicalDriveNumber,
-		 DAC960_PartitionByCommand(Command),
-		 Command->BufferHeader->bi_sector,
-		 Command->BufferHeader->bi_sector + Command->BlockCount - 1);
 }
 
 
@@ -2988,129 +3380,60 @@
   DAC960_V1_CommandOpcode_T CommandOpcode =
     Command->V1.CommandMailbox.Common.CommandOpcode;
   DAC960_V1_CommandStatus_T CommandStatus = Command->V1.CommandStatus;
-  BufferHeader_T *BufferHeader = Command->BufferHeader;
+
   if (CommandType == DAC960_ReadCommand ||
       CommandType == DAC960_WriteCommand)
     {
       if (CommandStatus == DAC960_V1_NormalCompletion)
+
+		DAC960_ProcessCompletedRequest(Command, true);
+
+      else if (CommandStatus == DAC960_V1_IrrecoverableDataError ||
+		CommandStatus == DAC960_V1_BadDataEncountered)
 	{
+
 	  /*
-	    Perform completion processing for all buffers in this I/O Request.
-	  */
-	  while (BufferHeader != NULL)
-	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
-	      BufferHeader->bi_next = NULL;
-	      DAC960_ProcessCompletedBuffer(BufferHeader, true);
-	      BufferHeader = NextBufferHeader;
-	    }
-	  if (Command->Completion != NULL)
-	    {
-	      complete(Command->Completion);
-	      Command->Completion = NULL;
-	    }
-	  add_disk_randomness(Controller->disks[Command->LogicalDriveNumber]);
-	}
-      else if ((CommandStatus == DAC960_V1_IrrecoverableDataError ||
-		CommandStatus == DAC960_V1_BadDataEncountered) &&
-	       BufferHeader != NULL &&
-	       BufferHeader->bi_next != NULL)
-	{
-	  DAC960_V1_CommandMailbox_T *CommandMailbox =
-	    &Command->V1.CommandMailbox;
-	  if (CommandType == DAC960_ReadCommand)
-	    {
-	      Command->CommandType = DAC960_ReadRetryCommand;
-	      CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read;
-	    }
-	  else
-	    {
-	      Command->CommandType = DAC960_WriteRetryCommand;
-	      CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write;
-	    }
-	  Command->BlockCount = BufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
-	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus32(bio_data(BufferHeader));
-	  DAC960_QueueCommand(Command);
-	  return;
+	   * Finish this later.
+	   *
+	   * We should call "complete_that_request_first()"
+	   * to remove the first part of the request.  Then, if there
+	   * is still more I/O to be done, resubmit the request.
+	   *
+	   * We want to recalculate scatter/gather list,
+	   * and requeue the command.
+	   *
+	   * For now, print a message on the console, and clone
+	   * the code for "normal" completion.
+	   */
+	  printk("V1_ProcessCompletedCommand: I/O error on read/write\n");
+
+	  DAC960_ProcessCompletedRequest(Command, false);
 	}
       else
 	{
 	  if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline)
 	    DAC960_V1_ReadWriteError(Command);
-	  /*
-	    Perform completion processing for all buffers in this I/O Request.
-	  */
-	  while (BufferHeader != NULL)
-	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
-	      BufferHeader->bi_next = NULL;
-	      DAC960_ProcessCompletedBuffer(BufferHeader, false);
-	      BufferHeader = NextBufferHeader;
-	    }
-	  if (Command->Completion != NULL)
-	    {
-	      complete(Command->Completion);
-	      Command->Completion = NULL;
-	    }
+
+	  DAC960_ProcessCompletedRequest(Command, false);
 	}
     }
   else if (CommandType == DAC960_ReadRetryCommand ||
 	   CommandType == DAC960_WriteRetryCommand)
     {
-      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
-      BufferHeader->bi_next = NULL;
-      /*
-	Perform completion processing for this single buffer.
-      */
-      if (CommandStatus == DAC960_V1_NormalCompletion)
-	DAC960_ProcessCompletedBuffer(BufferHeader, true);
-      else
-	{
-	  if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline)
-	    DAC960_V1_ReadWriteError(Command);
-	  DAC960_ProcessCompletedBuffer(BufferHeader, false);
-	}
-      if (NextBufferHeader != NULL)
-	{
-	  DAC960_V1_CommandMailbox_T *CommandMailbox =
-	    &Command->V1.CommandMailbox;
-	  Command->BlockNumber +=
-	    BufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  Command->BlockCount =
-	    NextBufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  Command->BufferHeader = NextBufferHeader;
-	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
-	  CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
-	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus32(bio_data(NextBufferHeader));
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
+	/*
+	 * We're not doing retry commands yet.
+	 */
+	printk("DAC960_ProcessCompletedCommand: RetryCommand not done yet\n");
     }
-  else if (CommandType == DAC960_MonitoringCommand ||
-	   CommandOpcode == DAC960_V1_Enquiry ||
-	   CommandOpcode == DAC960_V1_GetRebuildProgress)
-    {
-      if (CommandType != DAC960_MonitoringCommand)
-	{
-	  if (CommandOpcode == DAC960_V1_Enquiry)
-	    memcpy(&Controller->V1.NewEnquiry,
-		   Bus32_to_Virtual(Command->V1.CommandMailbox
-					       .Type3.BusAddress),
-		   sizeof(DAC960_V1_Enquiry_T));
-	  else if (CommandOpcode == DAC960_V1_GetRebuildProgress)
-	    memcpy(&Controller->V1.RebuildProgress,
-		   Bus32_to_Virtual(Command->V1.CommandMailbox
-					       .Type3.BusAddress),
-		   sizeof(DAC960_V1_RebuildProgress_T));
-	}
-      if (CommandOpcode == DAC960_V1_Enquiry &&
-	  Controller->ControllerInitialized)
+
+  else if (CommandType == DAC960_MonitoringCommand)
+    {
+      if (Controller->ShutdownMonitoringTimer)
+	      return;
+      if (CommandOpcode == DAC960_V1_Enquiry)
 	{
 	  DAC960_V1_Enquiry_T *OldEnquiry = &Controller->V1.Enquiry;
-	  DAC960_V1_Enquiry_T *NewEnquiry = &Controller->V1.NewEnquiry;
+	  DAC960_V1_Enquiry_T *NewEnquiry = Controller->V1.NewEnquiry;
 	  unsigned int OldCriticalLogicalDriveCount =
 	    OldEnquiry->CriticalLogicalDriveCount;
 	  unsigned int NewCriticalLogicalDriveCount =
@@ -3220,17 +3543,7 @@
 	    (NewEnquiry->CriticalLogicalDriveCount > 0 ||
 	     NewEnquiry->OfflineLogicalDriveCount > 0 ||
 	     NewEnquiry->DeadDriveCount > 0);
-	  if (CommandType != DAC960_MonitoringCommand &&
-	      Controller->V1.RebuildFlagPending)
-	    {
-	      DAC960_V1_Enquiry_T *Enquiry = (DAC960_V1_Enquiry_T *)
-		Bus32_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress);
-	      Enquiry->RebuildFlag = Controller->V1.PendingRebuildFlag;
-	      Controller->V1.RebuildFlagPending = false;
-	    }
-	  else if (CommandType == DAC960_MonitoringCommand &&
-		   NewEnquiry->RebuildFlag >
-		   DAC960_V1_BackgroundCheckInProgress)
+	  if (NewEnquiry->RebuildFlag > DAC960_V1_BackgroundCheckInProgress)
 	    {
 	      Controller->V1.PendingRebuildFlag = NewEnquiry->RebuildFlag;
 	      Controller->V1.RebuildFlagPending = true;
@@ -3256,7 +3569,7 @@
 		 "killed due to SCSI phase sequence error",
 		 "killed due to unknown status" };
 	  DAC960_V1_EventLogEntry_T *EventLogEntry =
-	    &Controller->V1.EventLogEntry;
+	    	Controller->V1.EventLogEntry;
 	  if (EventLogEntry->SequenceNumber ==
 	      Controller->V1.OldEventLogSequenceNumber)
 	    {
@@ -3316,7 +3629,7 @@
       else if (CommandOpcode == DAC960_V1_GetErrorTable)
 	{
 	  DAC960_V1_ErrorTable_T *OldErrorTable = &Controller->V1.ErrorTable;
-	  DAC960_V1_ErrorTable_T *NewErrorTable = &Controller->V1.NewErrorTable;
+	  DAC960_V1_ErrorTable_T *NewErrorTable = Controller->V1.NewErrorTable;
 	  int Channel, TargetID;
 	  for (Channel = 0; Channel < Controller->Channels; Channel++)
 	    for (TargetID = 0; TargetID < Controller->Targets; TargetID++)
@@ -3342,7 +3655,7 @@
 				  NewErrorEntry->HardErrorCount,
 				  NewErrorEntry->MiscErrorCount);
 	      }
-	  memcpy(&Controller->V1.ErrorTable, &Controller->V1.NewErrorTable,
+	  memcpy(&Controller->V1.ErrorTable, Controller->V1.NewErrorTable,
 		 sizeof(DAC960_V1_ErrorTable_T));
 	}
       else if (CommandOpcode == DAC960_V1_GetDeviceState)
@@ -3351,7 +3664,7 @@
 	    &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel]
 				       [Controller->V1.DeviceStateTargetID];
 	  DAC960_V1_DeviceState_T *NewDeviceState =
-	    &Controller->V1.NewDeviceState;
+	    Controller->V1.NewDeviceState;
 	  if (NewDeviceState->DeviceState != OldDeviceState->DeviceState)
 	    DAC960_Critical("Physical Device %d:%d is now %s\n", Controller,
 			    Controller->V1.DeviceStateChannel,
@@ -3387,7 +3700,7 @@
 	      DAC960_V1_LogicalDriveInformation_T *OldLogicalDriveInformation =
 		&Controller->V1.LogicalDriveInformation[LogicalDriveNumber];
 	      DAC960_V1_LogicalDriveInformation_T *NewLogicalDriveInformation =
-		&Controller->V1.NewLogicalDriveInformation[LogicalDriveNumber];
+		&(*Controller->V1.NewLogicalDriveInformation)[LogicalDriveNumber];
 	      if (NewLogicalDriveInformation->LogicalDriveState !=
 		  OldLogicalDriveInformation->LogicalDriveState)
 		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
@@ -3412,17 +3725,17 @@
 				 ? "WRITE BACK" : "WRITE THRU"));
 	    }
 	  memcpy(&Controller->V1.LogicalDriveInformation,
-		 &Controller->V1.NewLogicalDriveInformation,
+		 Controller->V1.NewLogicalDriveInformation,
 		 sizeof(DAC960_V1_LogicalDriveInformationArray_T));
 	}
       else if (CommandOpcode == DAC960_V1_GetRebuildProgress)
 	{
 	  unsigned int LogicalDriveNumber =
-	    Controller->V1.RebuildProgress.LogicalDriveNumber;
+	    Controller->V1.RebuildProgress->LogicalDriveNumber;
 	  unsigned int LogicalDriveSize =
-	    Controller->V1.RebuildProgress.LogicalDriveSize;
+	    Controller->V1.RebuildProgress->LogicalDriveSize;
 	  unsigned int BlocksCompleted =
-	    LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks;
+	    LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks;
 	  if (CommandStatus == DAC960_V1_NoRebuildOrCheckInProgress &&
 	      Controller->V1.LastRebuildStatus == DAC960_V1_NormalCompletion)
 	    CommandStatus = DAC960_V1_RebuildSuccessful;
@@ -3479,11 +3792,11 @@
       else if (CommandOpcode == DAC960_V1_RebuildStat)
 	{
 	  unsigned int LogicalDriveNumber =
-	    Controller->V1.RebuildProgress.LogicalDriveNumber;
+	    Controller->V1.RebuildProgress->LogicalDriveNumber;
 	  unsigned int LogicalDriveSize =
-	    Controller->V1.RebuildProgress.LogicalDriveSize;
+	    Controller->V1.RebuildProgress->LogicalDriveSize;
 	  unsigned int BlocksCompleted =
-	    LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks;
+	    LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks;
 	  if (CommandStatus == DAC960_V1_NormalCompletion)
 	    {
 	      Controller->EphemeralProgressMessage = true;
@@ -3501,15 +3814,15 @@
       else if (CommandOpcode == DAC960_V1_BackgroundInitializationControl)
 	{
 	  unsigned int LogicalDriveNumber =
-	    Controller->V1.BackgroundInitializationStatus.LogicalDriveNumber;
+	    Controller->V1.BackgroundInitializationStatus->LogicalDriveNumber;
 	  unsigned int LogicalDriveSize =
-	    Controller->V1.BackgroundInitializationStatus.LogicalDriveSize;
+	    Controller->V1.BackgroundInitializationStatus->LogicalDriveSize;
 	  unsigned int BlocksCompleted =
-	    Controller->V1.BackgroundInitializationStatus.BlocksCompleted;
+	    Controller->V1.BackgroundInitializationStatus->BlocksCompleted;
 	  switch (CommandStatus)
 	    {
 	    case DAC960_V1_NormalCompletion:
-	      switch (Controller->V1.BackgroundInitializationStatus.Status)
+	      switch (Controller->V1.BackgroundInitializationStatus->Status)
 		{
 		case DAC960_V1_BackgroundInitializationInvalid:
 		  break;
@@ -3519,11 +3832,11 @@
 		  break;
 		case DAC960_V1_BackgroundInitializationInProgress:
 		  if (BlocksCompleted ==
-		      Controller->V1.LastBackgroundInitializationStatus
-				    .BlocksCompleted &&
+		      Controller->V1.LastBackgroundInitializationStatus.
+				BlocksCompleted &&
 		      LogicalDriveNumber ==
-		      Controller->V1.LastBackgroundInitializationStatus
-				    .LogicalDriveNumber)
+		      Controller->V1.LastBackgroundInitializationStatus.
+				LogicalDriveNumber)
 		    break;
 		  Controller->EphemeralProgressMessage = true;
 		  DAC960_Progress("Background Initialization in Progress: "
@@ -3546,32 +3859,84 @@
 		  break;
 		}
 	      memcpy(&Controller->V1.LastBackgroundInitializationStatus,
-		     &Controller->V1.BackgroundInitializationStatus,
+		     Controller->V1.BackgroundInitializationStatus,
 		     sizeof(DAC960_V1_BackgroundInitializationStatus_T));
 	      break;
 	    case DAC960_V1_BackgroundInitSuccessful:
-	      if (Controller->V1.BackgroundInitializationStatus.Status ==
+	      if (Controller->V1.BackgroundInitializationStatus->Status ==
 		  DAC960_V1_BackgroundInitializationInProgress)
 		DAC960_Progress("Background Initialization "
 				"Completed Successfully\n", Controller);
-	      Controller->V1.BackgroundInitializationStatus.Status =
+	      Controller->V1.BackgroundInitializationStatus->Status =
 		DAC960_V1_BackgroundInitializationInvalid;
 	      break;
 	    case DAC960_V1_BackgroundInitAborted:
-	      if (Controller->V1.BackgroundInitializationStatus.Status ==
+	      if (Controller->V1.BackgroundInitializationStatus->Status ==
 		  DAC960_V1_BackgroundInitializationInProgress)
 		DAC960_Progress("Background Initialization Aborted\n",
 				Controller);
-	      Controller->V1.BackgroundInitializationStatus.Status =
+	      Controller->V1.BackgroundInitializationStatus->Status =
 		DAC960_V1_BackgroundInitializationInvalid;
 	      break;
 	    case DAC960_V1_NoBackgroundInitInProgress:
 	      break;
 	    }
+	} 
+      else if (CommandOpcode == DAC960_V1_DCDB)
+	{
+	   /*
+	     This is a bit ugly.
+
+	     The InquiryStandardData and 
+	     the InquiryUntitSerialNumber information
+	     retrieval operations BOTH use the DAC960_V1_DCDB
+	     commands.  the test above can't distinguish between
+	     these two cases.
+
+	     Instead, we rely on the order of code later in this
+             function to ensure that DeviceInquiryInformation commands
+             are submitted before DeviceSerialNumber commands.
+	   */
+	   if (Controller->V1.NeedDeviceInquiryInformation)
+	     {
+	        DAC960_SCSI_Inquiry_T *InquiryStandardData =
+			&Controller->V1.InquiryStandardData
+				[Controller->V1.DeviceStateChannel]
+				[Controller->V1.DeviceStateTargetID];
+	        if (CommandStatus != DAC960_V1_NormalCompletion)
+		   {
+			memset(InquiryStandardData, 0,
+				sizeof(DAC960_SCSI_Inquiry_T));
+	      		InquiryStandardData->PeripheralDeviceType = 0x1F;
+		    }
+	         else
+			memcpy(InquiryStandardData, 
+				Controller->V1.NewInquiryStandardData,
+				sizeof(DAC960_SCSI_Inquiry_T));
+	         Controller->V1.NeedDeviceInquiryInformation = false;
+              }
+	   else if (Controller->V1.NeedDeviceSerialNumberInformation) 
+              {
+	        DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+		  &Controller->V1.InquiryUnitSerialNumber
+				[Controller->V1.DeviceStateChannel]
+				[Controller->V1.DeviceStateTargetID];
+	         if (CommandStatus != DAC960_V1_NormalCompletion)
+		   {
+			memset(InquiryUnitSerialNumber, 0,
+				sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+	      		InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+		    }
+	          else
+			memcpy(InquiryUnitSerialNumber, 
+				Controller->V1.NewInquiryUnitSerialNumber,
+				sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+	      Controller->V1.NeedDeviceSerialNumberInformation = false;
+	     }
 	}
-    }
-  if (CommandType == DAC960_MonitoringCommand)
-    {
+      /*
+        Begin submitting new monitoring commands.
+       */
       if (Controller->V1.NewEventLogSequenceNumber
 	  - Controller->V1.OldEventLogSequenceNumber > 0)
 	{
@@ -3583,7 +3948,7 @@
 	  Command->V1.CommandMailbox.Type3E.SequenceNumber =
 	    Controller->V1.OldEventLogSequenceNumber;
 	  Command->V1.CommandMailbox.Type3E.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.EventLogEntry);
+	    	Controller->V1.EventLogEntryDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3593,7 +3958,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetErrorTable;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.NewErrorTable);
+	    	Controller->V1.NewErrorTableDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3604,7 +3969,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetRebuildProgress;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
+	    Controller->V1.RebuildProgressDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3612,15 +3977,14 @@
 	{
 	  if (Controller->V1.NeedDeviceInquiryInformation)
 	    {
-	      DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB;
-	      DAC960_SCSI_Inquiry_T *InquiryStandardData =
-		&Controller->V1.InquiryStandardData
-				[Controller->V1.DeviceStateChannel]
-				[Controller->V1.DeviceStateTargetID];
-	      InquiryStandardData->PeripheralDeviceType = 0x1F;
+	      DAC960_V1_DCDB_T *DCDB = Controller->V1.MonitoringDCDB;
+	      dma_addr_t DCDB_DMA = Controller->V1.MonitoringDCDB_DMA;
+
+	      dma_addr_t NewInquiryStandardDataDMA =
+		Controller->V1.NewInquiryStandardDataDMA;
+
 	      Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
-	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus32(DCDB);
+	      Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA;
 	      DCDB->Channel = Controller->V1.DeviceStateChannel;
 	      DCDB->TargetID = Controller->V1.DeviceStateTargetID;
 	      DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -3629,7 +3993,7 @@
 	      DCDB->NoAutomaticRequestSense = false;
 	      DCDB->DisconnectPermitted = true;
 	      DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
-	      DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData);
+	      DCDB->BusAddress = NewInquiryStandardDataDMA;
 	      DCDB->CDBLength = 6;
 	      DCDB->TransferLengthHigh4 = 0;
 	      DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -3640,20 +4004,17 @@
 	      DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T);
 	      DCDB->CDB[5] = 0; /* Control */
 	      DAC960_QueueCommand(Command);
-	      Controller->V1.NeedDeviceInquiryInformation = false;
 	      return;
 	    }
 	  if (Controller->V1.NeedDeviceSerialNumberInformation)
 	    {
-	      DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB;
-	      DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
-		&Controller->V1.InquiryUnitSerialNumber
-				[Controller->V1.DeviceStateChannel]
-				[Controller->V1.DeviceStateTargetID];
-	      InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+	      DAC960_V1_DCDB_T *DCDB = Controller->V1.MonitoringDCDB;
+	      dma_addr_t DCDB_DMA = Controller->V1.MonitoringDCDB_DMA;
+	      dma_addr_t NewInquiryUnitSerialNumberDMA = 
+			Controller->V1.NewInquiryUnitSerialNumberDMA;
+
 	      Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
-	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus32(DCDB);
+	      Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA;
 	      DCDB->Channel = Controller->V1.DeviceStateChannel;
 	      DCDB->TargetID = Controller->V1.DeviceStateTargetID;
 	      DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -3663,7 +4024,7 @@
 	      DCDB->DisconnectPermitted = true;
 	      DCDB->TransferLength =
 		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	      DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber);
+	      DCDB->BusAddress = NewInquiryUnitSerialNumberDMA;
 	      DCDB->CDBLength = 6;
 	      DCDB->TransferLengthHigh4 = 0;
 	      DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -3674,7 +4035,6 @@
 	      DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
 	      DCDB->CDB[5] = 0; /* Control */
 	      DAC960_QueueCommand(Command);
-	      Controller->V1.NeedDeviceSerialNumberInformation = false;
 	      return;
 	    }
 	  if (Controller->V1.StartDeviceStateScan)
@@ -3690,7 +4050,7 @@
 	    }
 	  if (Controller->V1.DeviceStateChannel < Controller->Channels)
 	    {
-	      Controller->V1.NewDeviceState.DeviceState =
+	      Controller->V1.NewDeviceState->DeviceState =
 		DAC960_V1_Device_Dead;
 	      Command->V1.CommandMailbox.Type3D.CommandOpcode =
 		DAC960_V1_GetDeviceState;
@@ -3699,7 +4059,7 @@
 	      Command->V1.CommandMailbox.Type3D.TargetID =
 		Controller->V1.DeviceStateTargetID;
 	      Command->V1.CommandMailbox.Type3D.BusAddress =
-		Virtual_to_Bus32(&Controller->V1.NewDeviceState);
+		Controller->V1.NewDeviceStateDMA;
 	      DAC960_QueueCommand(Command);
 	      return;
 	    }
@@ -3711,7 +4071,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetLogicalDriveInformation;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.NewLogicalDriveInformation);
+	    Controller->V1.NewLogicalDriveInformationDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3721,7 +4081,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetRebuildProgress;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
+	    	Controller->V1.RebuildProgressDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3731,7 +4091,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_RebuildStat;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
+	    Controller->V1.RebuildProgressDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3742,14 +4102,14 @@
 	    DAC960_V1_BackgroundInitializationControl;
 	  Command->V1.CommandMailbox.Type3B.CommandOpcode2 = 0x20;
 	  Command->V1.CommandMailbox.Type3B.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.BackgroundInitializationStatus);
+	    Controller->V1.BackgroundInitializationStatusDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
       Controller->MonitoringTimerCount++;
       Controller->MonitoringTimer.expires =
 	jiffies + DAC960_MonitoringTimerInterval;
-      add_timer(&Controller->MonitoringTimer);
+      	add_timer(&Controller->MonitoringTimer);
     }
   if (CommandType == DAC960_ImmediateCommand)
     {
@@ -3825,18 +4185,11 @@
       break;
     }
   DAC960_Error("Error Condition %s on %s:\n", Controller,
-	       SenseErrors[Command->V2.RequestSense.SenseKey], CommandName);
+	       SenseErrors[Command->V2.RequestSense->SenseKey], CommandName);
   DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %u..%u\n",
 	       Controller, Controller->ControllerNumber,
 	       Command->LogicalDriveNumber, Command->BlockNumber,
 	       Command->BlockNumber + Command->BlockCount - 1);
-  if (DAC960_PartitionByCommand(Command) > 0)
-    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
-		 Controller, Controller->ControllerNumber,
-		 Command->LogicalDriveNumber,
-		 DAC960_PartitionByCommand(Command),
-		 Command->BufferHeader->bi_sector,
-		 Command->BufferHeader->bi_sector + Command->BlockCount - 1);
 }
 
 
@@ -4094,123 +4447,51 @@
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_IOCTL_Opcode_T CommandOpcode = CommandMailbox->Common.IOCTL_Opcode;
   DAC960_V2_CommandStatus_T CommandStatus = Command->V2.CommandStatus;
-  BufferHeader_T *BufferHeader = Command->BufferHeader;
+
   if (CommandType == DAC960_ReadCommand ||
       CommandType == DAC960_WriteCommand)
     {
       if (CommandStatus == DAC960_V2_NormalCompletion)
+
+		DAC960_ProcessCompletedRequest(Command, true);
+
+      else if (Command->V2.RequestSense->SenseKey == DAC960_SenseKey_MediumError)
 	{
+	  
 	  /*
-	    Perform completion processing for all buffers in this I/O Request.
-	  */
-	  while (BufferHeader != NULL)
-	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
-	      BufferHeader->bi_next = NULL;
-	      DAC960_ProcessCompletedBuffer(BufferHeader, true);
-	      BufferHeader = NextBufferHeader;
-	    }
-	  if (Command->Completion != NULL)
-	    {
-	      complete(Command->Completion);
-	      Command->Completion = NULL;
-	    }
-	  add_disk_randomness(Controller->disks[Command->LogicalDriveNumber]);
-	}
-      else if (Command->V2.RequestSense.SenseKey
-	       == DAC960_SenseKey_MediumError &&
-	       BufferHeader != NULL &&
-	       BufferHeader->bi_next != NULL)
-	{
-	  if (CommandType == DAC960_ReadCommand)
-	    Command->CommandType = DAC960_ReadRetryCommand;
-	  else Command->CommandType = DAC960_WriteRetryCommand;
-	  Command->BlockCount = BufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  CommandMailbox->SCSI_10.CommandControlBits
-				 .AdditionalScatterGatherListMemory = false;
-	  CommandMailbox->SCSI_10.DataTransferSize =
-	    Command->BlockCount << DAC960_BlockSizeBits;
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				 .ScatterGatherSegments[0].SegmentDataPointer =
-	    Virtual_to_Bus64(bio_data(BufferHeader));
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				 .ScatterGatherSegments[0].SegmentByteCount =
-	    CommandMailbox->SCSI_10.DataTransferSize;
-	  CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8;
-	  CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount;
-	  DAC960_QueueCommand(Command);
-	  return;
+	   * Don't know yet how to handle this case.  
+	   * See comments in DAC960_V1_ProcessCompletedCommand()
+	   *
+	   * For now, print a message on the console, and clone
+	   * the code for "normal" completion.
+	   */
+	  printk("V1_ProcessCompletedCommand: I/O error on read/write\n");
+
+	  DAC960_ProcessCompletedRequest(Command, false);
 	}
       else
 	{
-	  if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady)
+	  if (Command->V2.RequestSense->SenseKey != DAC960_SenseKey_NotReady)
 	    DAC960_V2_ReadWriteError(Command);
 	  /*
 	    Perform completion processing for all buffers in this I/O Request.
 	  */
-	  while (BufferHeader != NULL)
-	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
-	      BufferHeader->bi_next = NULL;
-	      DAC960_ProcessCompletedBuffer(BufferHeader, false);
-	      BufferHeader = NextBufferHeader;
-	    }
-	  if (Command->Completion != NULL)
-	    {
-	      complete(Command->Completion);
-	      Command->Completion = NULL;
-	    }
+          DAC960_ProcessCompletedRequest(Command, false);
 	}
     }
   else if (CommandType == DAC960_ReadRetryCommand ||
 	   CommandType == DAC960_WriteRetryCommand)
     {
-      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
-      BufferHeader->bi_next = NULL;
-      /*
-	Perform completion processing for this single buffer.
-      */
-      if (CommandStatus == DAC960_V2_NormalCompletion)
-	DAC960_ProcessCompletedBuffer(BufferHeader, true);
-      else
-	{
-	  if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady)
-	    DAC960_V2_ReadWriteError(Command);
-	  DAC960_ProcessCompletedBuffer(BufferHeader, false);
-	}
-      if (NextBufferHeader != NULL)
-	{
-	  Command->BlockNumber +=
-	    BufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  Command->BlockCount =
-	    NextBufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  Command->BufferHeader = NextBufferHeader;
-	  CommandMailbox->SCSI_10.DataTransferSize =
-	    Command->BlockCount << DAC960_BlockSizeBits;
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				 .ScatterGatherSegments[0]
-				 .SegmentDataPointer =
-	    Virtual_to_Bus64(bio_data(NextBufferHeader));
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				 .ScatterGatherSegments[0]
-				 .SegmentByteCount =
-	    CommandMailbox->SCSI_10.DataTransferSize;
-	  CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24;
-	  CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16;
-	  CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8;
-	  CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber;
-	  CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8;
-	  CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount;
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
+	printk("DAC960_V2_ProcessCompletedCommand: retries not coded yet\n");
     }
   else if (CommandType == DAC960_MonitoringCommand)
     {
+      if (Controller->ShutdownMonitoringTimer)
+	      return;
       if (CommandOpcode == DAC960_V2_GetControllerInfo)
 	{
 	  DAC960_V2_ControllerInfo_T *NewControllerInfo =
-	    &Controller->V2.NewControllerInformation;
+	    Controller->V2.NewControllerInformation;
 	  DAC960_V2_ControllerInfo_T *ControllerInfo =
 	    &Controller->V2.ControllerInformation;
 	  Controller->LogicalDriveCount =
@@ -4229,15 +4510,16 @@
 	}
       else if (CommandOpcode == DAC960_V2_GetEvent)
 	{
-	  if (CommandStatus == DAC960_V2_NormalCompletion)
-	    DAC960_V2_ReportEvent(Controller, &Controller->V2.Event);
+	  if (CommandStatus == DAC960_V2_NormalCompletion) {
+	    DAC960_V2_ReportEvent(Controller, Controller->V2.Event);
+	  }
 	  Controller->V2.NextEventSequenceNumber++;
 	}
       else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid &&
 	       CommandStatus == DAC960_V2_NormalCompletion)
 	{
 	  DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo =
-	    &Controller->V2.NewPhysicalDeviceInformation;
+	    Controller->V2.NewPhysicalDeviceInformation;
 	  unsigned int PhysicalDeviceIndex = Controller->V2.PhysicalDeviceIndex;
 	  DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo =
 	    Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex];
@@ -4448,7 +4730,7 @@
 	       CommandStatus == DAC960_V2_NormalCompletion)
 	{
 	  DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo =
-	    &Controller->V2.NewLogicalDeviceInformation;
+	    Controller->V2.NewLogicalDeviceInformation;
 	  unsigned short LogicalDeviceNumber =
 	    NewLogicalDeviceInfo->LogicalDeviceNumber;
 	  DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo =
@@ -4598,6 +4880,23 @@
 	    }
 	  Controller->V2.NeedLogicalDeviceInformation = false;
 	}
+      else if (CommandOpcode == DAC960_V2_SCSI_10_Passthru)
+        {
+	    DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+		Controller->V2.InquiryUnitSerialNumber[Controller->V2.PhysicalDeviceIndex - 1];
+
+	    if (CommandStatus != DAC960_V2_NormalCompletion) {
+		memset(InquiryUnitSerialNumber,
+			0, sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+		InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+	    } else
+	  	memcpy(InquiryUnitSerialNumber,
+			Controller->V2.NewInquiryUnitSerialNumber,
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+
+	     Controller->V2.NeedDeviceSerialNumberInformation = false;
+        }
+
       if (Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
 	  - Controller->V2.NextEventSequenceNumber > 0)
 	{
@@ -4613,7 +4912,7 @@
 	  CommandMailbox->GetEvent.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentDataPointer =
-	    Virtual_to_Bus64(&Controller->V2.Event);
+	    Controller->V2.EventDMA;
 	  CommandMailbox->GetEvent.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentByteCount =
@@ -4626,62 +4925,41 @@
 	  if (Controller->V2.NeedDeviceSerialNumberInformation)
 	    {
 	      DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
-		Controller->V2.InquiryUnitSerialNumber
-			       [Controller->V2.PhysicalDeviceIndex - 1];
+                Controller->V2.NewInquiryUnitSerialNumber;
 	      InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
-	      CommandMailbox->SCSI_10.CommandOpcode =
-		DAC960_V2_SCSI_10_Passthru;
-	      CommandMailbox->SCSI_10.DataTransferSize =
-		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	      CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit =
-		Controller->V2.NewPhysicalDeviceInformation.LogicalUnit - 1;
-	      CommandMailbox->SCSI_10.PhysicalDevice.TargetID =
-		Controller->V2.NewPhysicalDeviceInformation.TargetID;
-	      CommandMailbox->SCSI_10.PhysicalDevice.Channel =
-		Controller->V2.NewPhysicalDeviceInformation.Channel;
-	      CommandMailbox->SCSI_10.CDBLength = 6;
-	      CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */
-	      CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */
-	      CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */
-	      CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */
-	      CommandMailbox->SCSI_10.SCSI_CDB[4] =
-		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	      CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */
-	      CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				     .ScatterGatherSegments[0]
-				     .SegmentDataPointer =
-		Virtual_to_Bus64(InquiryUnitSerialNumber);
-	      CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				     .ScatterGatherSegments[0]
-				     .SegmentByteCount =
-		CommandMailbox->SCSI_10.DataTransferSize;
+
+	      DAC960_V2_ConstructNewUnitSerialNumber(Controller, CommandMailbox,
+			Controller->V2.NewPhysicalDeviceInformation->Channel,
+			Controller->V2.NewPhysicalDeviceInformation->TargetID,
+		Controller->V2.NewPhysicalDeviceInformation->LogicalUnit - 1);
+
+
 	      DAC960_QueueCommand(Command);
-	      Controller->V2.NeedDeviceSerialNumberInformation = false;
 	      return;
 	    }
 	  if (Controller->V2.StartPhysicalDeviceInformationScan)
 	    {
 	      Controller->V2.PhysicalDeviceIndex = 0;
-	      Controller->V2.NewPhysicalDeviceInformation.Channel = 0;
-	      Controller->V2.NewPhysicalDeviceInformation.TargetID = 0;
-	      Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0;
+	      Controller->V2.NewPhysicalDeviceInformation->Channel = 0;
+	      Controller->V2.NewPhysicalDeviceInformation->TargetID = 0;
+	      Controller->V2.NewPhysicalDeviceInformation->LogicalUnit = 0;
 	      Controller->V2.StartPhysicalDeviceInformationScan = false;
 	    }
 	  CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferSize =
 	    sizeof(DAC960_V2_PhysicalDeviceInfo_T);
 	  CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit =
-	    Controller->V2.NewPhysicalDeviceInformation.LogicalUnit;
+	    Controller->V2.NewPhysicalDeviceInformation->LogicalUnit;
 	  CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID =
-	    Controller->V2.NewPhysicalDeviceInformation.TargetID;
+	    Controller->V2.NewPhysicalDeviceInformation->TargetID;
 	  CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel =
-	    Controller->V2.NewPhysicalDeviceInformation.Channel;
+	    Controller->V2.NewPhysicalDeviceInformation->Channel;
 	  CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode =
 	    DAC960_V2_GetPhysicalDeviceInfoValid;
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 					    .ScatterGatherSegments[0]
 					    .SegmentDataPointer =
-	    Virtual_to_Bus64(&Controller->V2.NewPhysicalDeviceInformation);
+	    Controller->V2.NewPhysicalDeviceInformationDMA;
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 					    .ScatterGatherSegments[0]
 					    .SegmentByteCount =
@@ -4699,21 +4977,20 @@
 		   LogicalDriveNumber++)
 		Controller->V2.LogicalDriveFoundDuringScan
 			       [LogicalDriveNumber] = false;
-	      Controller->V2.NewLogicalDeviceInformation
-			    .LogicalDeviceNumber = 0;
+	      Controller->V2.NewLogicalDeviceInformation->LogicalDeviceNumber = 0;
 	      Controller->V2.StartLogicalDeviceInformationScan = false;
 	    }
 	  CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
 	  CommandMailbox->LogicalDeviceInfo.DataTransferSize =
 	    sizeof(DAC960_V2_LogicalDeviceInfo_T);
 	  CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber =
-	    Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber;
+	    Controller->V2.NewLogicalDeviceInformation->LogicalDeviceNumber;
 	  CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode =
 	    DAC960_V2_GetLogicalDeviceInfoValid;
 	  CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 					   .ScatterGatherSegments[0]
 					   .SegmentDataPointer =
-	    Virtual_to_Bus64(&Controller->V2.NewLogicalDeviceInformation);
+	    Controller->V2.NewLogicalDeviceInformationDMA;
 	  CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 					   .ScatterGatherSegments[0]
 					   .SegmentByteCount =
@@ -4724,7 +5001,7 @@
       Controller->MonitoringTimerCount++;
       Controller->MonitoringTimer.expires =
 	jiffies + DAC960_HealthStatusMonitoringInterval;
-      add_timer(&Controller->MonitoringTimer);
+      	add_timer(&Controller->MonitoringTimer);
     }
   if (CommandType == DAC960_ImmediateCommand)
     {
@@ -5002,6 +5279,10 @@
 /*
   DAC960_P_InterruptHandler handles hardware interrupts from DAC960 P Series
   Controllers.
+
+  Translations of DAC960_V1_Enquiry and DAC960_V1_GetDeviceState rely
+  on the data having been placed into DAC960_Controller_T, rather than
+  an arbitrary buffer.
 */
 
 static void DAC960_P_InterruptHandler(int IRQ_Channel,
@@ -5034,14 +5315,12 @@
 	{
 	case DAC960_V1_Enquiry_Old:
 	  Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Enquiry;
-	  DAC960_P_To_PD_TranslateEnquiry(
-	    Bus32_to_Virtual(CommandMailbox->Type3.BusAddress));
+	  DAC960_P_To_PD_TranslateEnquiry(Controller->V1.NewEnquiry);
 	  break;
 	case DAC960_V1_GetDeviceState_Old:
 	  Command->V1.CommandMailbox.Common.CommandOpcode =
-	    DAC960_V1_GetDeviceState;
-	  DAC960_P_To_PD_TranslateDeviceState(
-	    Bus32_to_Virtual(CommandMailbox->Type3.BusAddress));
+	    					DAC960_V1_GetDeviceState;
+	  DAC960_P_To_PD_TranslateDeviceState(Controller->V1.NewDeviceState);
 	  break;
 	case DAC960_V1_Read_Old:
 	  Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Read;
@@ -5090,8 +5369,7 @@
   DAC960_V1_ClearCommand(Command);
   Command->CommandType = DAC960_MonitoringCommand;
   CommandMailbox->Type3.CommandOpcode = DAC960_V1_Enquiry;
-  CommandMailbox->Type3.BusAddress =
-    Virtual_to_Bus32(&Controller->V1.NewEnquiry);
+  CommandMailbox->Type3.BusAddress = Controller->V1.NewEnquiryDMA;
   DAC960_QueueCommand(Command);
 }
 
@@ -5119,7 +5397,7 @@
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentDataPointer =
-    Virtual_to_Bus64(&Controller->V2.NewControllerInformation);
+    Controller->V2.NewControllerInformationDMA;
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentByteCount =
@@ -5198,7 +5476,7 @@
 	{
 	  Controller->MonitoringTimer.expires =
 	    jiffies + DAC960_HealthStatusMonitoringInterval;
-	  add_timer(&Controller->MonitoringTimer);
+	    add_timer(&Controller->MonitoringTimer);
 	  return;
 	}
       Controller->V2.StatusChangeCounter = StatusChangeCounter;
@@ -5225,6 +5503,7 @@
     }
 }
 
+
 /*
   DAC960_Open is the Device Open Function for the DAC960 Driver.
 */
@@ -5423,14 +5702,17 @@
 	DAC960_V1_CommandOpcode_T CommandOpcode;
 	DAC960_V1_CommandStatus_T CommandStatus;
 	DAC960_V1_DCDB_T DCDB;
+	DAC960_V1_DCDB_T *DCDB_IOBUF = NULL;
+	dma_addr_t	DCDB_IOBUFDMA;
 	ProcessorFlags_T ProcessorFlags;
 	int ControllerNumber, DataTransferLength;
 	unsigned char *DataTransferBuffer = NULL;
+	dma_addr_t DataTransferBufferDMA;
 	if (UserSpaceUserCommand == NULL) return -EINVAL;
 	if (copy_from_user(&UserCommand, UserSpaceUserCommand,
 				   sizeof(DAC960_V1_UserCommand_T))) {
 		ErrorCode = -EFAULT;
-		goto Failure1;
+		goto Failure1a;
 	}
 	ControllerNumber = UserCommand.ControllerNumber;
 	if (ControllerNumber < 0 ||
@@ -5447,7 +5729,7 @@
 	    if (copy_from_user(&DCDB, UserCommand.DCDB,
 			       sizeof(DAC960_V1_DCDB_T))) {
 		ErrorCode = -EFAULT;
-		goto Failure1;
+		goto Failure1a;
 	    }
 	    if (DCDB.Channel >= DAC960_V1_MaxChannels) return -EINVAL;
 	    if (!((DataTransferLength == 0 &&
@@ -5463,17 +5745,29 @@
 	    if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength)
 		!= abs(DataTransferLength))
 	      return -EINVAL;
+	    DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice,
+			sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA);
+	    if (DCDB_IOBUF == NULL)
+			return -ENOMEM;
 	  }
 	if (DataTransferLength > 0)
 	  {
-	    DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL);
-	    if (DataTransferBuffer == NULL) return -ENOMEM;
+	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+				DataTransferLength, &DataTransferBufferDMA);
+	    if (DataTransferBuffer == NULL) {
+		ErrorCode = -ENOMEM;
+		goto Failure1;
+	    }
 	    memset(DataTransferBuffer, 0, DataTransferLength);
 	  }
 	else if (DataTransferLength < 0)
 	  {
-	    DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL);
-	    if (DataTransferBuffer == NULL) return -ENOMEM;
+	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+				-DataTransferLength, &DataTransferBufferDMA);
+	    if (DataTransferBuffer == NULL) {
+		ErrorCode = -ENOMEM;
+		goto Failure1;
+	    }
 	    if (copy_from_user(DataTransferBuffer,
 			       UserCommand.DataTransferBuffer,
 			       -DataTransferLength)) {
@@ -5489,11 +5783,11 @@
 	    while (Controller->V1.DirectCommandActive[DCDB.Channel]
 						     [DCDB.TargetID])
 	      {
-		spin_unlock_irq(Controller->RequestQueue.queue_lock);
+		spin_unlock_irq(&Controller->queue_lock);
 		__wait_event(Controller->CommandWaitQueue,
 			     !Controller->V1.DirectCommandActive
 					     [DCDB.Channel][DCDB.TargetID]);
-		spin_lock_irq(Controller->RequestQueue.queue_lock);
+		spin_lock_irq(&Controller->queue_lock);
 	      }
 	    Controller->V1.DirectCommandActive[DCDB.Channel]
 					      [DCDB.TargetID] = true;
@@ -5502,9 +5796,9 @@
 	    Command->CommandType = DAC960_ImmediateCommand;
 	    memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox,
 		   sizeof(DAC960_V1_CommandMailbox_T));
-	    Command->V1.CommandMailbox.Type3.BusAddress =
-	      Virtual_to_Bus32(&DCDB);
-	    DCDB.BusAddress = Virtual_to_Bus32(DataTransferBuffer);
+	    Command->V1.CommandMailbox.Type3.BusAddress = DCDB_IOBUFDMA;
+	    DCDB.BusAddress = DataTransferBufferDMA;
+	    memcpy(DCDB_IOBUF, &DCDB, sizeof(DAC960_V1_DCDB_T));
 	  }
 	else
 	  {
@@ -5518,7 +5812,7 @@
 		   sizeof(DAC960_V1_CommandMailbox_T));
 	    if (DataTransferBuffer != NULL)
 	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus32(DataTransferBuffer);
+		DataTransferBufferDMA;
 	  }
 	DAC960_ExecuteCommand(Command);
 	CommandStatus = Command->V1.CommandStatus;
@@ -5528,15 +5822,20 @@
 	if (DataTransferLength > 0)
 	  {
 	    if (copy_to_user(UserCommand.DataTransferBuffer,
-			     DataTransferBuffer, DataTransferLength))
+			     DataTransferBuffer, DataTransferLength)) {
 		ErrorCode = -EFAULT;
 		goto Failure1;
+            }
 	  }
 	if (CommandOpcode == DAC960_V1_DCDB)
 	  {
+	    /*
+	      I don't believe Target or Channel in the DCDB_IOBUF
+	      should be any different from the contents of DCDB.
+	     */
 	    Controller->V1.DirectCommandActive[DCDB.Channel]
 					      [DCDB.TargetID] = false;
-	    if (copy_to_user(UserCommand.DCDB, &DCDB,
+	    if (copy_to_user(UserCommand.DCDB, DCDB_IOBUF,
 			     sizeof(DAC960_V1_DCDB_T))) {
 		ErrorCode = -EFAULT;
 		goto Failure1;
@@ -5545,7 +5844,12 @@
 	ErrorCode = CommandStatus;
       Failure1:
 	if (DataTransferBuffer != NULL)
-	  kfree(DataTransferBuffer);
+	  pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength),
+			DataTransferBuffer, DataTransferBufferDMA);
+	if (DCDB_IOBUF != NULL)
+	  pci_free_consistent(Controller->PCIDevice, sizeof(DAC960_V1_DCDB_T),
+			DCDB_IOBUF, DCDB_IOBUFDMA);
+      Failure1a:
 	return ErrorCode;
       }
     case DAC960_IOCTL_V2_EXECUTE_COMMAND:
@@ -5561,12 +5865,14 @@
 	int ControllerNumber, DataTransferLength;
 	int DataTransferResidue, RequestSenseLength;
 	unsigned char *DataTransferBuffer = NULL;
+	dma_addr_t DataTransferBufferDMA;
 	unsigned char *RequestSenseBuffer = NULL;
+	dma_addr_t RequestSenseBufferDMA;
 	if (UserSpaceUserCommand == NULL) return -EINVAL;
 	if (copy_from_user(&UserCommand, UserSpaceUserCommand,
 			   sizeof(DAC960_V2_UserCommand_T))) {
 		ErrorCode = -EFAULT;
-		goto Failure2;
+		goto Failure2a;
 	}
 	ControllerNumber = UserCommand.ControllerNumber;
 	if (ControllerNumber < 0 ||
@@ -5578,13 +5884,15 @@
 	DataTransferLength = UserCommand.DataTransferLength;
 	if (DataTransferLength > 0)
 	  {
-	    DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL);
+	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+				DataTransferLength, &DataTransferBufferDMA);
 	    if (DataTransferBuffer == NULL) return -ENOMEM;
 	    memset(DataTransferBuffer, 0, DataTransferLength);
 	  }
 	else if (DataTransferLength < 0)
 	  {
-	    DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL);
+	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+				-DataTransferLength, &DataTransferBufferDMA);
 	    if (DataTransferBuffer == NULL) return -ENOMEM;
 	    if (copy_from_user(DataTransferBuffer,
 			       UserCommand.DataTransferBuffer,
@@ -5596,7 +5904,8 @@
 	RequestSenseLength = UserCommand.RequestSenseLength;
 	if (RequestSenseLength > 0)
 	  {
-	    RequestSenseBuffer = kmalloc(RequestSenseLength, GFP_KERNEL);
+	    RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice,
+			RequestSenseLength, &RequestSenseBufferDMA);
 	    if (RequestSenseBuffer == NULL)
 	      {
 		ErrorCode = -ENOMEM;
@@ -5637,8 +5946,7 @@
 	      }
 	    CommandMailbox->Common.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
-				  .SegmentDataPointer =
-	      Virtual_to_Bus64(DataTransferBuffer);
+				  .SegmentDataPointer = DataTransferBufferDMA;
 	    CommandMailbox->Common.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentByteCount =
@@ -5650,7 +5958,7 @@
 				  .NoAutoRequestSense = false;
 	    CommandMailbox->Common.RequestSenseSize = RequestSenseLength;
 	    CommandMailbox->Common.RequestSenseBusAddress =
-	      Virtual_to_Bus64(RequestSenseBuffer);
+	      						RequestSenseBufferDMA;
 	  }
 	DAC960_ExecuteCommand(Command);
 	CommandStatus = Command->V2.CommandStatus;
@@ -5690,10 +5998,12 @@
 	  }
 	ErrorCode = CommandStatus;
       Failure2:
-	if (DataTransferBuffer != NULL)
-	  kfree(DataTransferBuffer);
+	  pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength),
+		DataTransferBuffer, DataTransferBufferDMA);
 	if (RequestSenseBuffer != NULL)
-	  kfree(RequestSenseBuffer);
+	  pci_free_consistent(Controller->PCIDevice, RequestSenseLength,
+		RequestSenseBuffer, RequestSenseBufferDMA);
+      Failure2a:
 	return ErrorCode;
       }
     case DAC960_IOCTL_V2_GET_HEALTH_STATUS:
@@ -5740,226 +6050,6 @@
 
 
 /*
-  DAC960_KernelIOCTL is the Kernel IOCTL Function for the DAC960 Driver.
-*/
-
-int DAC960_KernelIOCTL(unsigned int Request, void *Argument)
-{
-  switch (Request)
-    {
-    case DAC960_IOCTL_GET_CONTROLLER_COUNT:
-      return DAC960_ControllerCount;
-    case DAC960_IOCTL_GET_CONTROLLER_INFO:
-      {
-	DAC960_ControllerInfo_T *ControllerInfo =
-	  (DAC960_ControllerInfo_T *) Argument;
-	DAC960_Controller_T *Controller;
-	int ControllerNumber;
-	if (ControllerInfo == NULL) return -EINVAL;
-	ControllerNumber = ControllerInfo->ControllerNumber;
-	if (ControllerNumber < 0 ||
-	    ControllerNumber > DAC960_ControllerCount - 1)
-	  return -ENXIO;
-	Controller = DAC960_Controllers[ControllerNumber];
-	if (Controller == NULL) return -ENXIO;
-	memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
-	ControllerInfo->ControllerNumber = ControllerNumber;
-	ControllerInfo->FirmwareType = Controller->FirmwareType;
-	ControllerInfo->Channels = Controller->Channels;
-	ControllerInfo->Targets = Controller->Targets;
-	ControllerInfo->PCI_Bus = Controller->Bus;
-	ControllerInfo->PCI_Device = Controller->Device;
-	ControllerInfo->PCI_Function = Controller->Function;
-	ControllerInfo->IRQ_Channel = Controller->IRQ_Channel;
-	ControllerInfo->PCI_Address = Controller->PCI_Address;
-	strcpy(ControllerInfo->ModelName, Controller->ModelName);
-	strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion);
-	return 0;
-      }
-    case DAC960_IOCTL_V1_EXECUTE_COMMAND:
-      {
-	DAC960_V1_KernelCommand_T *KernelCommand =
-	  (DAC960_V1_KernelCommand_T *) Argument;
-	DAC960_Controller_T *Controller;
-	DAC960_Command_T *Command = NULL;
-	DAC960_V1_CommandOpcode_T CommandOpcode;
-	DAC960_V1_DCDB_T *DCDB = NULL;
-	ProcessorFlags_T ProcessorFlags;
-	int ControllerNumber, DataTransferLength;
-	unsigned char *DataTransferBuffer = NULL;
-	if (KernelCommand == NULL) return -EINVAL;
-	ControllerNumber = KernelCommand->ControllerNumber;
-	if (ControllerNumber < 0 ||
-	    ControllerNumber > DAC960_ControllerCount - 1)
-	  return -ENXIO;
-	Controller = DAC960_Controllers[ControllerNumber];
-	if (Controller == NULL) return -ENXIO;
-	if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL;
-	CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode;
-	DataTransferLength = KernelCommand->DataTransferLength;
-	DataTransferBuffer = KernelCommand->DataTransferBuffer;
-	if (CommandOpcode & 0x80) return -EINVAL;
-	if (CommandOpcode == DAC960_V1_DCDB)
-	  {
-	    DCDB = KernelCommand->DCDB;
-	    if (DCDB->Channel >= DAC960_V1_MaxChannels) return -EINVAL;
-	    if (!((DataTransferLength == 0 &&
-		   DCDB->Direction == DAC960_V1_DCDB_NoDataTransfer) ||
-		  (DataTransferLength > 0 &&
-		   DCDB->Direction
-		   == DAC960_V1_DCDB_DataTransferDeviceToSystem) ||
-		  (DataTransferLength < 0 &&
-		   DCDB->Direction
-		   == DAC960_V1_DCDB_DataTransferSystemToDevice)))
-	      return -EINVAL;
-	    if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength)
-		!= abs(DataTransferLength))
-	      return -EINVAL;
-	  }
-	if (DataTransferLength != 0 && DataTransferBuffer == NULL)
-	  return -EINVAL;
-	if (DataTransferLength > 0)
-	  memset(DataTransferBuffer, 0, DataTransferLength);
-	if (CommandOpcode == DAC960_V1_DCDB)
-	  {
-	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-	    if (!Controller->V1.DirectCommandActive[DCDB->Channel]
-						   [DCDB->TargetID])
-	      Command = DAC960_AllocateCommand(Controller);
-	    if (Command == NULL)
-	      {
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		return -EBUSY;
-	      }
-	    else Controller->V1.DirectCommandActive[DCDB->Channel]
-						   [DCDB->TargetID] = true;
-	    DAC960_V1_ClearCommand(Command);
-	    Command->CommandType = DAC960_QueuedCommand;
-	    memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox,
-		   sizeof(DAC960_V1_CommandMailbox_T));
-	    Command->V1.CommandMailbox.Type3.BusAddress =
-	      Virtual_to_Bus32(DCDB);
-	    Command->V1.KernelCommand = KernelCommand;
-	    DCDB->BusAddress = Virtual_to_Bus32(DataTransferBuffer);
-	    DAC960_QueueCommand(Command);
-	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-	  }
-	else
-	  {
-	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-	    Command = DAC960_AllocateCommand(Controller);
-	    if (Command == NULL)
-	      {
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		return -EBUSY;
-	      }
-	    DAC960_V1_ClearCommand(Command);
-	    Command->CommandType = DAC960_QueuedCommand;
-	    memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox,
-		   sizeof(DAC960_V1_CommandMailbox_T));
-	    if (DataTransferBuffer != NULL)
-	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus32(DataTransferBuffer);
-	    Command->V1.KernelCommand = KernelCommand;
-	    DAC960_QueueCommand(Command);
-	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-	  }
-	return 0;
-      }
-    case DAC960_IOCTL_V2_EXECUTE_COMMAND:
-      {
-	DAC960_V2_KernelCommand_T *KernelCommand =
-	  (DAC960_V2_KernelCommand_T *) Argument;
-	DAC960_Controller_T *Controller;
-	DAC960_Command_T *Command = NULL;
-	DAC960_V2_CommandMailbox_T *CommandMailbox;
-	ProcessorFlags_T ProcessorFlags;
-	int ControllerNumber, DataTransferLength, RequestSenseLength;
-	unsigned char *DataTransferBuffer = NULL;
-	unsigned char *RequestSenseBuffer = NULL;
-	if (KernelCommand == NULL) return -EINVAL;
-	ControllerNumber = KernelCommand->ControllerNumber;
-	if (ControllerNumber < 0 ||
-	    ControllerNumber > DAC960_ControllerCount - 1)
-	  return -ENXIO;
-	Controller = DAC960_Controllers[ControllerNumber];
-	if (Controller == NULL) return -ENXIO;
-	if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL;
-	DataTransferLength = KernelCommand->DataTransferLength;
-	RequestSenseLength = KernelCommand->RequestSenseLength;
-	DataTransferBuffer = KernelCommand->DataTransferBuffer;
-	RequestSenseBuffer = KernelCommand->RequestSenseBuffer;
-	if (DataTransferLength != 0 && DataTransferBuffer == NULL)
-	  return -EINVAL;
-	if (RequestSenseLength < 0)
-	  return -EINVAL;
-	if (RequestSenseLength > 0 && RequestSenseBuffer == NULL)
-	  return -EINVAL;
-	if (DataTransferLength > 0)
-	  memset(DataTransferBuffer, 0, DataTransferLength);
-	if (RequestSenseLength > 0)
-	  memset(RequestSenseBuffer, 0, RequestSenseLength);
-	DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-	Command = DAC960_AllocateCommand(Controller);
-	if (Command == NULL)
-	  {
-	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-	    return -EBUSY;
-	  }
-	DAC960_V2_ClearCommand(Command);
-	Command->CommandType = DAC960_QueuedCommand;
-	CommandMailbox = &Command->V2.CommandMailbox;
-	memcpy(CommandMailbox, &KernelCommand->CommandMailbox,
-	       sizeof(DAC960_V2_CommandMailbox_T));
-	CommandMailbox->Common.CommandControlBits
-			      .AdditionalScatterGatherListMemory = false;
-	CommandMailbox->Common.CommandControlBits
-			      .NoAutoRequestSense = true;
-	CommandMailbox->Common.DataTransferSize = 0;
-	CommandMailbox->Common.DataTransferPageNumber = 0;
-	memset(&CommandMailbox->Common.DataTransferMemoryAddress, 0,
-	       sizeof(DAC960_V2_DataTransferMemoryAddress_T));
-	if (DataTransferLength != 0)
-	  {
-	    if (DataTransferLength > 0)
-	      {
-		CommandMailbox->Common.CommandControlBits
-				      .DataTransferControllerToHost = true;
-		CommandMailbox->Common.DataTransferSize = DataTransferLength;
-	      }
-	    else
-	      {
-		CommandMailbox->Common.CommandControlBits
-				      .DataTransferControllerToHost = false;
-		CommandMailbox->Common.DataTransferSize = -DataTransferLength;
-	      }
-	    CommandMailbox->Common.DataTransferMemoryAddress
-				  .ScatterGatherSegments[0]
-				  .SegmentDataPointer =
-	      Virtual_to_Bus64(DataTransferBuffer);
-	    CommandMailbox->Common.DataTransferMemoryAddress
-				  .ScatterGatherSegments[0]
-				  .SegmentByteCount =
-	      CommandMailbox->Common.DataTransferSize;
-	  }
-	if (RequestSenseLength > 0)
-	  {
-	    CommandMailbox->Common.CommandControlBits
-				  .NoAutoRequestSense = false;
-	    CommandMailbox->Common.RequestSenseBusAddress =
-	      Virtual_to_Bus64(RequestSenseBuffer);
-	  }
-	Command->V2.KernelCommand = KernelCommand;
-	DAC960_QueueCommand(Command);
-	DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-	return 0;
-      }
-    }
-  return -EINVAL;
-}
-
-
-/*
   DAC960_CheckStatusBuffer verifies that there is room to hold ByteCount
   additional bytes in the Combined Status Buffer and grows the buffer if
   necessary.  It returns true if there is enough room and false otherwise.
@@ -6381,11 +6471,25 @@
   else if (strcmp(UserCommand, "cancel-rebuild") == 0 ||
 	   strcmp(UserCommand, "cancel-consistency-check") == 0)
     {
-      unsigned char OldRebuildRateConstant;
+      /*
+        the OldRebuildRateConstant is never actually used
+        once its value is retrieved from the controller.
+       */
+      unsigned char *OldRebuildRateConstant;
+      dma_addr_t OldRebuildRateConstantDMA;
+
+      OldRebuildRateConstant = pci_alloc_consistent( Controller->PCIDevice,
+		sizeof(char), &OldRebuildRateConstantDMA);
+      if (OldRebuildRateConstant == NULL) {
+         DAC960_UserCritical("Cancellation of Rebuild or "
+			     "Consistency Check Failed - "
+			     "Out of Memory",
+                             Controller);
+	 goto failure;
+      }
       CommandMailbox->Type3R.CommandOpcode = DAC960_V1_RebuildControl;
       CommandMailbox->Type3R.RebuildRateConstant = 0xFF;
-      CommandMailbox->Type3R.BusAddress =
-	Virtual_to_Bus32(&OldRebuildRateConstant);
+      CommandMailbox->Type3R.BusAddress = OldRebuildRateConstantDMA;
       DAC960_ExecuteCommand(Command);
       switch (Command->V1.CommandStatus)
 	{
@@ -6400,6 +6504,9 @@
 			      Controller, Command->V1.CommandStatus);
 	  break;
 	}
+failure:
+  	pci_free_consistent(Controller->PCIDevice, sizeof(char),
+		OldRebuildRateConstant, OldRebuildRateConstantDMA);
     }
   else DAC960_UserCritical("Illegal User Command: '%s'\n",
 			   Controller, UserCommand);
@@ -6423,10 +6530,12 @@
 						   *LogicalDeviceNumber)
 {
   DAC960_V2_CommandMailbox_T SavedCommandMailbox, *CommandMailbox;
-  DAC960_V2_PhysicalToLogicalDevice_T PhysicalToLogicalDevice;
+  DAC960_Controller_T *Controller =  Command->Controller;
+
   CommandMailbox = &Command->V2.CommandMailbox;
   memcpy(&SavedCommandMailbox, CommandMailbox,
 	 sizeof(DAC960_V2_CommandMailbox_T));
+
   CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
   CommandMailbox->PhysicalDeviceInfo.CommandControlBits
 				    .DataTransferControllerToHost = true;
@@ -6441,15 +6550,17 @@
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentDataPointer =
-    Virtual_to_Bus64(&PhysicalToLogicalDevice);
+    		Controller->V2.PhysicalToLogicalDeviceDMA;
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentByteCount =
-    CommandMailbox->Common.DataTransferSize;
+    		CommandMailbox->Common.DataTransferSize;
+
   DAC960_ExecuteCommand(Command);
+  *LogicalDeviceNumber = Controller->V2.PhysicalToLogicalDevice->LogicalDeviceNumber;
+
   memcpy(CommandMailbox, &SavedCommandMailbox,
 	 sizeof(DAC960_V2_CommandMailbox_T));
-  *LogicalDeviceNumber = PhysicalToLogicalDevice.LogicalDeviceNumber;
   return (Command->V2.CommandStatus == DAC960_V2_NormalCompletion);
 }
 
@@ -6635,16 +6746,20 @@
 	  CommandMailbox->ControllerInfo.ControllerNumber = 0;
 	  CommandMailbox->ControllerInfo.IOCTL_Opcode =
 	    DAC960_V2_GetControllerInfo;
+	  /*
+	   * How does this NOT race with the queued Monitoring
+	   * usage of this structure?
+	   */
 	  CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 					.ScatterGatherSegments[0]
 					.SegmentDataPointer =
-	    Virtual_to_Bus64(&Controller->V2.NewControllerInformation);
+	    Controller->V2.NewControllerInformationDMA;
 	  CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 					.ScatterGatherSegments[0]
 					.SegmentByteCount =
 	    CommandMailbox->ControllerInfo.DataTransferSize;
 	  DAC960_ExecuteCommand(Command);
-	  while (Controller->V2.NewControllerInformation.PhysicalScanActive)
+	  while (Controller->V2.NewControllerInformation->PhysicalScanActive)
 	    {
 	      DAC960_ExecuteCommand(Command);
 	      sleep_on_timeout(&Controller->CommandWaitQueue, HZ);
@@ -6817,22 +6932,19 @@
   DAC960 Driver.
 */
 
-static void DAC960_CreateProcEntries(void)
+static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller)
 {
-  PROC_DirectoryEntry_T *StatusProcEntry;
-  int ControllerNumber;
-  DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL);
-  StatusProcEntry = create_proc_read_entry("status", 0,
+	PROC_DirectoryEntry_T *StatusProcEntry;
+	PROC_DirectoryEntry_T *ControllerProcEntry;
+	PROC_DirectoryEntry_T *UserCommandProcEntry;
+
+	if (DAC960_ProcDirectoryEntry == NULL) {
+  		DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL);
+  		StatusProcEntry = create_proc_read_entry("status", 0,
 					   DAC960_ProcDirectoryEntry,
 					   DAC960_ProcReadStatus, NULL);
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      PROC_DirectoryEntry_T *ControllerProcEntry;
-      PROC_DirectoryEntry_T *UserCommandProcEntry;
-      if (Controller == NULL) continue;
+	}
+
       sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
       ControllerProcEntry = proc_mkdir(Controller->ControllerName,
 				       DAC960_ProcDirectoryEntry);
@@ -6846,7 +6958,6 @@
 			       Controller);
       UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand;
       Controller->ControllerProcEntry = ControllerProcEntry;
-    }
 }
 
 
@@ -6855,26 +6966,138 @@
   DAC960 Driver.
 */
 
-static void DAC960_DestroyProcEntries(void)
+static void DAC960_DestroyProcEntries(DAC960_Controller_T *Controller)
 {
-  int ControllerNumber;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      if (Controller == NULL) continue;
+      if (Controller->ControllerProcEntry == NULL)
+	      return;
       remove_proc_entry("initial_status", Controller->ControllerProcEntry);
       remove_proc_entry("current_status", Controller->ControllerProcEntry);
       remove_proc_entry("user_command", Controller->ControllerProcEntry);
       remove_proc_entry(Controller->ControllerName, DAC960_ProcDirectoryEntry);
-    }
-  remove_proc_entry("rd/status", NULL);
-  remove_proc_entry("rd", NULL);
+      Controller->ControllerProcEntry = NULL;
 }
 
+static struct DAC960_privdata DAC960_BA_privdata = {
+	.HardwareType =		DAC960_BA_Controller,
+	.FirmwareType 	=	DAC960_V2_Controller,
+	.InterruptHandler =	DAC960_BA_InterruptHandler,
+	.MemoryWindowSize =	DAC960_BA_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_LP_privdata = {
+	.HardwareType =		DAC960_LP_Controller,
+	.FirmwareType 	=	DAC960_LP_Controller,
+	.InterruptHandler =	DAC960_LP_InterruptHandler,
+	.MemoryWindowSize =	DAC960_LP_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_LA_privdata = {
+	.HardwareType =		DAC960_LA_Controller,
+	.FirmwareType 	=	DAC960_V1_Controller,
+	.InterruptHandler =	DAC960_LA_InterruptHandler,
+	.MemoryWindowSize =	DAC960_LA_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_PG_privdata = {
+	.HardwareType =		DAC960_PG_Controller,
+	.FirmwareType 	=	DAC960_V1_Controller,
+	.InterruptHandler =	DAC960_PG_InterruptHandler,
+	.MemoryWindowSize =	DAC960_PG_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_PD_privdata = {
+	.HardwareType =		DAC960_PD_Controller,
+	.FirmwareType 	=	DAC960_V1_Controller,
+	.InterruptHandler =	DAC960_PD_InterruptHandler,
+	.MemoryWindowSize =	DAC960_PD_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_P_privdata = {
+	.HardwareType =		DAC960_P_Controller,
+	.FirmwareType 	=	DAC960_V1_Controller,
+	.InterruptHandler =	DAC960_P_InterruptHandler,
+	.MemoryWindowSize =	DAC960_PD_RegisterWindowSize,
+};
+
+static struct pci_device_id DAC960_id_table[] = {
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_BA,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_BA_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_LP,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_LP_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_DEC,
+		.device		= PCI_DEVICE_ID_DEC_21285,
+		.subvendor	= PCI_VENDOR_ID_MYLEX,
+		.subdevice	= PCI_DEVICE_ID_MYLEX_DAC960_LA,
+		.driver_data	= (unsigned long) &DAC960_LA_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_PG,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_PG_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_PD,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_PD_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_P,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_P_privdata,
+	},
+	{0, },
+};
+
+MODULE_DEVICE_TABLE(pci, DAC960_id_table);
+
+static struct pci_driver DAC960_pci_driver = {
+	.name		= "DAC960",
+	.id_table	= DAC960_id_table,
+	.probe		= DAC960_Probe,
+	.remove		= DAC960_Remove,
+};
+
+static int DAC960_init_module(void)
+{
+	return pci_module_init(&DAC960_pci_driver);
+}
+
+static void DAC960_cleanup_module(void)
+{
+	int i;
+
+	for (i = 0; i < DAC960_ControllerCount; i++) {
+		DAC960_Controller_T *Controller = DAC960_Controllers[i];
+		if (Controller == NULL)
+			continue;
+		DAC960_FinalizeController(Controller);
+	}
+	if (DAC960_ProcDirectoryEntry != NULL) {
+  		remove_proc_entry("rd/status", NULL);
+  		remove_proc_entry("rd", NULL);
+	}
+	DAC960_ControllerCount = 0;
+	pci_unregister_driver(&DAC960_pci_driver);
+}
 
-module_init(DAC960_Initialize);
-module_exit(DAC960_Finalize);
+module_init(DAC960_init_module);
+module_exit(DAC960_cleanup_module);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h
--- a/drivers/block/DAC960.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/block/DAC960.h	Wed Nov 27 14:36:31 2002
@@ -60,6 +60,17 @@
 #define DAC960_V1_MaxPhysicalDevices		45
 #define DAC960_V2_MaxPhysicalDevices		272
 
+/*
+  Define the pci dma mask supported by DAC960 V1 and V2 Firmware Controlers
+
+  For now set the V2 mask to only 32 bits.  The controller IS capable
+  of doing 64 bit dma.  But I have yet to find out whether this needs to
+  be explicitely enabled in the controller, or of the controller adapts
+  automatically.
+ */
+
+#define DAC690_V1_PciDmaMask	0xffffffff
+#define DAC690_V2_PciDmaMask	0xffffffffffffffff
 
 /*
   Define a Boolean data type.
@@ -111,6 +122,20 @@
 
 
 /*
+  dma_loaf is used by helper routines to divide a region of
+  dma mapped memory into smaller pieces, where those pieces
+  are not of uniform size.
+ */
+
+struct dma_loaf {
+	void	*cpu_base;
+	dma_addr_t dma_base;
+	size_t  length;
+	void	*cpu_free;
+	dma_addr_t dma_free;
+};
+
+/*
   Define the SCSI INQUIRY Standard Data structure.
 */
 
@@ -2059,9 +2084,6 @@
 #define DAC960_LogicalDriveNumber(Device) \
   (minor(Device) >> DAC960_MaxPartitionsBits)
 
-#define DAC960_PartitionNumber(Device) \
-  (minor(Device) & (DAC960_MaxPartitions - 1))
-
 #define DAC960_MajorNumber(ControllerNumber) \
   (DAC960_MAJOR + (ControllerNumber))
 
@@ -2191,7 +2213,6 @@
   of the Linux Kernel and I/O Subsystem.
 */
 
-typedef struct bio BufferHeader_T;
 typedef struct file File_T;
 typedef struct block_device_operations BlockDeviceOperations_T;
 typedef struct completion Completion_T;
@@ -2200,7 +2221,6 @@
 typedef struct inode_operations InodeOperations_T;
 typedef kdev_t KernelDevice_T;
 typedef struct list_head ListHead_T;
-typedef struct notifier_block NotifierBlock_T;
 typedef struct pci_dev PCI_Device_T;
 typedef struct proc_dir_entry PROC_DirectoryEntry_T;
 typedef unsigned long ProcessorFlags_T;
@@ -2211,6 +2231,13 @@
 typedef struct timer_list Timer_T;
 typedef wait_queue_head_t WaitQueue_T;
 
+struct DAC960_privdata {
+	DAC960_HardwareType_T	HardwareType;
+	DAC960_FirmwareType_T	FirmwareType;
+	void (*InterruptHandler)(int, void *, Registers_T *);
+	unsigned int		MemoryWindowSize;
+};
+
 
 /*
   Define the DAC960 V1 Firmware Controller Status Mailbox structure.
@@ -2278,16 +2305,16 @@
   unsigned int BlockNumber;
   unsigned int BlockCount;
   unsigned int SegmentCount;
-  BufferHeader_T *BufferHeader;
-  void *RequestBuffer;
+  IO_Request_T *Request;
+  struct pci_dev *PciDevice;
   union {
     struct {
       DAC960_V1_CommandMailbox_T CommandMailbox;
       DAC960_V1_KernelCommand_T *KernelCommand;
       DAC960_V1_CommandStatus_T CommandStatus;
-      DAC960_V1_ScatterGatherSegment_T
-	ScatterGatherList[DAC960_V1_ScatterGatherLimit]
-	__attribute__ ((aligned (sizeof(DAC960_V1_ScatterGatherSegment_T))));
+      DAC960_V1_ScatterGatherSegment_T *ScatterGatherList;
+      dma_addr_t ScatterGatherListDMA;
+      struct scatterlist ScatterList[DAC960_V1_ScatterGatherLimit];
       unsigned int EndMarker[0];
     } V1;
     struct {
@@ -2296,11 +2323,11 @@
       DAC960_V2_CommandStatus_T CommandStatus;
       unsigned char RequestSenseLength;
       int DataTransferResidue;
-      DAC960_V2_ScatterGatherSegment_T
-	ScatterGatherList[DAC960_V2_ScatterGatherLimit]
-	__attribute__ ((aligned (sizeof(DAC960_V2_ScatterGatherSegment_T))));
-      DAC960_SCSI_RequestSense_T RequestSense
-	__attribute__ ((aligned (sizeof(int))));
+      DAC960_V2_ScatterGatherSegment_T *ScatterGatherList;
+      dma_addr_t ScatterGatherListDMA;
+      DAC960_SCSI_RequestSense_T *RequestSense;
+      dma_addr_t RequestSenseDMA;
+      struct scatterlist ScatterList[DAC960_V2_ScatterGatherLimit];
       unsigned int EndMarker[0];
     } V2;
   } FW;
@@ -2320,6 +2347,7 @@
   DAC960_HardwareType_T HardwareType;
   DAC960_IO_Address_T IO_Address;
   DAC960_PCI_Address_T PCI_Address;
+  PCI_Device_T  *PCIDevice;
   unsigned char ControllerNumber;
   unsigned char ControllerName[4];
   unsigned char ModelName[20];
@@ -2345,14 +2373,13 @@
   unsigned int CurrentStatusLength;
   unsigned int ProgressBufferLength;
   unsigned int UserStatusLength;
-  unsigned long MemoryMailboxPagesAddress;
-  unsigned long MemoryMailboxPagesOrder;
+  struct dma_loaf DmaPages;
   unsigned long MonitoringTimerCount;
   unsigned long PrimaryMonitoringTime;
   unsigned long SecondaryMonitoringTime;
+  unsigned long ShutdownMonitoringTimer;
   unsigned long LastProgressReportTime;
   unsigned long LastCurrentStatusTime;
-  boolean ControllerDetectionSuccessful;
   boolean ControllerInitialized;
   boolean MonitoringCommandDeferred;
   boolean EphemeralProgressMessage;
@@ -2361,6 +2388,7 @@
   boolean SuppressEnclosureMessages;
   Timer_T MonitoringTimer;
   struct gendisk *disks[DAC960_MaxLogicalDrives];
+  struct pci_pool *ScatterGatherPool;
   DAC960_Command_T *FreeCommands;
   unsigned char *CombinedStatusBuffer;
   unsigned char *CurrentStatusBuffer;
@@ -2404,36 +2432,63 @@
       boolean RebuildProgressFirst;
       boolean RebuildFlagPending;
       boolean RebuildStatusPending;
+
+      dma_addr_t	FirstCommandMailboxDMA;
       DAC960_V1_CommandMailbox_T *FirstCommandMailbox;
       DAC960_V1_CommandMailbox_T *LastCommandMailbox;
       DAC960_V1_CommandMailbox_T *NextCommandMailbox;
       DAC960_V1_CommandMailbox_T *PreviousCommandMailbox1;
       DAC960_V1_CommandMailbox_T *PreviousCommandMailbox2;
+
+      dma_addr_t	FirstStatusMailboxDMA;
       DAC960_V1_StatusMailbox_T *FirstStatusMailbox;
       DAC960_V1_StatusMailbox_T *LastStatusMailbox;
       DAC960_V1_StatusMailbox_T *NextStatusMailbox;
-      DAC960_V1_DCDB_T MonitoringDCDB;
+
+      DAC960_V1_DCDB_T *MonitoringDCDB;
+      dma_addr_t MonitoringDCDB_DMA;
+
       DAC960_V1_Enquiry_T Enquiry;
-      DAC960_V1_Enquiry_T NewEnquiry;
+      DAC960_V1_Enquiry_T *NewEnquiry;
+      dma_addr_t NewEnquiryDMA;
+
       DAC960_V1_ErrorTable_T ErrorTable;
-      DAC960_V1_ErrorTable_T NewErrorTable;
-      DAC960_V1_EventLogEntry_T EventLogEntry;
-      DAC960_V1_RebuildProgress_T RebuildProgress;
+      DAC960_V1_ErrorTable_T *NewErrorTable;
+      dma_addr_t NewErrorTableDMA;
+
+      DAC960_V1_EventLogEntry_T *EventLogEntry;
+      dma_addr_t EventLogEntryDMA;
+
+      DAC960_V1_RebuildProgress_T *RebuildProgress;
+      dma_addr_t RebuildProgressDMA;
       DAC960_V1_CommandStatus_T LastRebuildStatus;
       DAC960_V1_CommandStatus_T PendingRebuildStatus;
+
       DAC960_V1_LogicalDriveInformationArray_T LogicalDriveInformation;
-      DAC960_V1_LogicalDriveInformationArray_T NewLogicalDriveInformation;
+      DAC960_V1_LogicalDriveInformationArray_T *NewLogicalDriveInformation;
+      dma_addr_t NewLogicalDriveInformationDMA;
+
       DAC960_V1_BackgroundInitializationStatus_T
-        BackgroundInitializationStatus;
+        	*BackgroundInitializationStatus;
+      dma_addr_t BackgroundInitializationStatusDMA;
       DAC960_V1_BackgroundInitializationStatus_T
-        LastBackgroundInitializationStatus;
+        	LastBackgroundInitializationStatus;
+
       DAC960_V1_DeviceState_T
 	DeviceState[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
-      DAC960_V1_DeviceState_T NewDeviceState;
+      DAC960_V1_DeviceState_T *NewDeviceState;
+      dma_addr_t	NewDeviceStateDMA;
+
       DAC960_SCSI_Inquiry_T
 	InquiryStandardData[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
+      DAC960_SCSI_Inquiry_T *NewInquiryStandardData;
+      dma_addr_t NewInquiryStandardDataDMA;
+
       DAC960_SCSI_Inquiry_UnitSerialNumber_T
 	InquiryUnitSerialNumber[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
+      DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber;
+      dma_addr_t NewInquiryUnitSerialNumberDMA;
+
       int DeviceResetCount[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
       boolean DirectCommandActive[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
     } V1;
@@ -2446,28 +2501,50 @@
       boolean NeedDeviceSerialNumberInformation;
       boolean StartLogicalDeviceInformationScan;
       boolean StartPhysicalDeviceInformationScan;
+      struct pci_pool *RequestSensePool;
+
+      dma_addr_t	FirstCommandMailboxDMA;
       DAC960_V2_CommandMailbox_T *FirstCommandMailbox;
       DAC960_V2_CommandMailbox_T *LastCommandMailbox;
       DAC960_V2_CommandMailbox_T *NextCommandMailbox;
       DAC960_V2_CommandMailbox_T *PreviousCommandMailbox1;
       DAC960_V2_CommandMailbox_T *PreviousCommandMailbox2;
+
+      dma_addr_t	FirstStatusMailboxDMA;
       DAC960_V2_StatusMailbox_T *FirstStatusMailbox;
       DAC960_V2_StatusMailbox_T *LastStatusMailbox;
       DAC960_V2_StatusMailbox_T *NextStatusMailbox;
+
+      dma_addr_t	HealthStatusBufferDMA;
       DAC960_V2_HealthStatusBuffer_T *HealthStatusBuffer;
+
       DAC960_V2_ControllerInfo_T ControllerInformation;
-      DAC960_V2_ControllerInfo_T NewControllerInformation;
+      DAC960_V2_ControllerInfo_T *NewControllerInformation;
+      dma_addr_t	NewControllerInformationDMA;
+
       DAC960_V2_LogicalDeviceInfo_T
 	*LogicalDeviceInformation[DAC960_MaxLogicalDrives];
-      DAC960_V2_LogicalDeviceInfo_T NewLogicalDeviceInformation;
+      DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInformation;
+      dma_addr_t	 NewLogicalDeviceInformationDMA;
+
       DAC960_V2_PhysicalDeviceInfo_T
 	*PhysicalDeviceInformation[DAC960_V2_MaxPhysicalDevices];
-      DAC960_V2_PhysicalDeviceInfo_T NewPhysicalDeviceInformation;
+      DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInformation;
+      dma_addr_t	NewPhysicalDeviceInformationDMA;
+
+      DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber;
+      dma_addr_t	NewInquiryUnitSerialNumberDMA;
       DAC960_SCSI_Inquiry_UnitSerialNumber_T
 	*InquiryUnitSerialNumber[DAC960_V2_MaxPhysicalDevices];
+
+      DAC960_V2_Event_T *Event;
+      dma_addr_t EventDMA;
+
+      DAC960_V2_PhysicalToLogicalDevice_T *PhysicalToLogicalDevice;
+      dma_addr_t PhysicalToLogicalDeviceDMA;
+
       DAC960_V2_PhysicalDevice_T
 	LogicalDriveToVirtualDevice[DAC960_MaxLogicalDrives];
-      DAC960_V2_Event_T Event;
       boolean LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives];
     } V2;
   } FW;
@@ -2495,16 +2572,47 @@
 #define DAC960_QueueReadWriteCommand(Command) \
   (Controller->QueueReadWriteCommand)(Command)
 
+/*
+ * dma_addr_writeql is provided to write dma_addr_t types
+ * to a 64-bit pci address space register.  The controller
+ * will accept having the register written as two 32-bit
+ * values.
+ *
+ * In HIGHMEM kernels, dma_addr_t is a 64-bit value.
+ * without HIGHMEM,  dma_addr_t is a 32-bit value.
+ *
+ * The compiler should always fix up the assignment
+ * to u.wq appropriately, depending upon the size of
+ * dma_addr_t.
+ */
+static inline
+void dma_addr_writeql(dma_addr_t addr, void *write_address)
+{
+	union {
+		u64 wq;
+		uint wl[2];
+	} u;
+
+	u.wq = addr;
+
+	writel(u.wl[0], write_address);
+	writel(u.wl[1], write_address + 4);
+}
 
 /*
   DAC960_AcquireControllerLock acquires exclusive access to Controller.
+	Reference the queue_lock through the controller structure,
+	rather than through the request queue.  These macros are
+        used to mutex on the controller structure during initialization,
+	BEFORE the request queue is allocated and initialized in
+	DAC960_RegisterBlockDevice().
 */
 
 static inline
 void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
 				  ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags);
+  spin_lock_irqsave(&Controller->queue_lock, *ProcessorFlags);
 }
 
 
@@ -2516,7 +2624,7 @@
 void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
 				  ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(&Controller->queue_lock, *ProcessorFlags);
 }
 
 
@@ -2553,7 +2661,7 @@
 void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
 				    ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags);
+  spin_lock_irqsave(&Controller->queue_lock, *ProcessorFlags);
 }
 
 
@@ -2566,10 +2674,9 @@
 void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
 				    ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(&Controller->queue_lock, *ProcessorFlags);
 }
 
-#error I am a non-portable driver, please convert me to use the Documentation/DMA-mapping.txt interfaces
 
 /*
   Define the DAC960 BA Series Controller Interface Register Offsets.
@@ -2834,17 +2941,14 @@
   mb();
 }
 
+
 static inline
 void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress,
-				    DAC960_V2_CommandMailbox_T *CommandMailbox)
+				    dma_addr_t CommandMailboxDMA)
 {
-#ifdef __ia64__
-  writeq(Virtual_to_Bus64(CommandMailbox),
-	 ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset);
-#else
-  writel(Virtual_to_Bus32(CommandMailbox),
-	 ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset);
-#endif
+	dma_addr_writeql(CommandMailboxDMA,
+		ControllerBaseAddress +
+		DAC960_BA_CommandMailboxBusAddressOffset);
 }
 
 static inline DAC960_V2_CommandIdentifier_T
@@ -3142,15 +3246,11 @@
 
 static inline
 void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress,
-				    DAC960_V2_CommandMailbox_T *CommandMailbox)
+				    dma_addr_t CommandMailboxDMA)
 {
-#ifdef __ia64__
-  writeq(Virtual_to_Bus64(CommandMailbox),
-	 ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset);
-#else
-  writel(Virtual_to_Bus32(CommandMailbox),
-	 ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset);
-#endif
+	dma_addr_writeql(CommandMailboxDMA,
+		ControllerBaseAddress +
+		DAC960_LP_CommandMailboxBusAddressOffset);
 }
 
 static inline DAC960_V2_CommandIdentifier_T
@@ -3506,43 +3606,6 @@
   return true;
 }
 
-static inline
-void DAC960_LA_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
-{
-#ifdef __i386__
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0x743C485E,
-	 ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset);
-  writel((unsigned long) Controller->V1.FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset);
-  writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset);
-  writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox,
-	 ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset);
-#endif
-}
-
-static inline
-void DAC960_LA_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
-					void **MemoryMailboxAddress,
-					short *NextCommandMailboxIndex,
-					short *NextStatusMailboxIndex)
-{
-#ifdef __i386__
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  if (readl(ControllerBaseAddress
-	    + DAC960_LA_CommandOpcodeRegisterOffset) != 0x743C485E)
-    return;
-  *MemoryMailboxAddress =
-    (void *) readl(ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset);
-  *NextCommandMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset);
-  *NextStatusMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset);
-#endif
-}
-
-
 /*
   Define the DAC960 PG Series Controller Interface Register Offsets.
 */
@@ -3868,43 +3931,6 @@
   return true;
 }
 
-static inline
-void DAC960_PG_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
-{
-#ifdef __i386__
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0x743C485E,
-	 ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset);
-  writel((unsigned long) Controller->V1.FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset);
-  writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset);
-  writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox,
-	 ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset);
-#endif
-}
-
-static inline
-void DAC960_PG_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
-					void **MemoryMailboxAddress,
-					short *NextCommandMailboxIndex,
-					short *NextStatusMailboxIndex)
-{
-#ifdef __i386__
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  if (readl(ControllerBaseAddress
-	    + DAC960_PG_CommandOpcodeRegisterOffset) != 0x743C485E)
-    return;
-  *MemoryMailboxAddress =
-    (void *) readl(ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset);
-  *NextCommandMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset);
-  *NextStatusMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset);
-#endif
-}
-
-
 /*
   Define the DAC960 PD Series Controller Interface Register Offsets.
 */
@@ -4206,9 +4232,8 @@
 */
 
 static void DAC960_FinalizeController(DAC960_Controller_T *);
-static int DAC960_Notifier(NotifierBlock_T *, unsigned long, void *);
 static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *);
-static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *);
+static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); 
 static void DAC960_RequestFunction(RequestQueue_T *);
 static void DAC960_BA_InterruptHandler(int, void *, Registers_T *);
 static void DAC960_LP_InterruptHandler(int, void *, Registers_T *);
@@ -4225,7 +4250,7 @@
 static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
 static void DAC960_Message(DAC960_MessageLevel_T, unsigned char *,
 			   DAC960_Controller_T *, ...);
-static void DAC960_CreateProcEntries(void);
-static void DAC960_DestroyProcEntries(void);
+static void DAC960_CreateProcEntries(DAC960_Controller_T *);
+static void DAC960_DestroyProcEntries(DAC960_Controller_T *);
 
 #endif /* DAC960_DriverVersion */
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/block/ll_rw_blk.c	Wed Nov 27 14:36:27 2002
@@ -737,7 +737,7 @@
 }
 
 
-inline int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
+int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
 				   struct bio *nxt)
 {
 	if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
@@ -758,7 +758,7 @@
 	return 0;
 }
 
-inline int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
+int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
 				 struct bio *nxt)
 {
 	if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
@@ -956,6 +956,7 @@
  */
 void blk_plug_device(request_queue_t *q)
 {
+	WARN_ON(!irqs_disabled());
 	if (!blk_queue_plugged(q)) {
 		spin_lock(&blk_plug_lock);
 		list_add_tail(&q->plug_list, &blk_plug_list);
@@ -967,8 +968,9 @@
  * remove the queue from the plugged list, if present. called with
  * queue lock held and interrupts disabled.
  */
-inline int blk_remove_plug(request_queue_t *q)
+int blk_remove_plug(request_queue_t *q)
 {
+	WARN_ON(!irqs_disabled());
 	if (blk_queue_plugged(q)) {
 		spin_lock(&blk_plug_lock);
 		list_del_init(&q->plug_list);
@@ -1096,28 +1098,27 @@
 #define blk_plug_entry(entry) list_entry((entry), request_queue_t, plug_list)
 void blk_run_queues(void)
 {
-	struct list_head local_plug_list;
-
-	INIT_LIST_HEAD(&local_plug_list);
+	LIST_HEAD(local_plug_list);
 
 	spin_lock_irq(&blk_plug_lock);
 
 	/*
 	 * this will happen fairly often
 	 */
-	if (list_empty(&blk_plug_list)) {
-		spin_unlock_irq(&blk_plug_lock);
-		return;
-	}
+	if (list_empty(&blk_plug_list))
+		goto out;
 
 	list_splice_init(&blk_plug_list, &local_plug_list);
-	spin_unlock_irq(&blk_plug_lock);
 	
 	while (!list_empty(&local_plug_list)) {
 		request_queue_t *q = blk_plug_entry(local_plug_list.next);
 
+		spin_unlock_irq(&blk_plug_lock);
 		q->unplug_fn(q);
+		spin_lock_irq(&blk_plug_lock);
 	}
+out:
+	spin_unlock_irq(&blk_plug_lock);
 }
 
 static int __blk_cleanup_queue(struct request_list *list)
@@ -1958,7 +1959,7 @@
 	return 1;
 }
 
-inline void blk_recalc_rq_segments(struct request *rq)
+void blk_recalc_rq_segments(struct request *rq)
 {
 	struct bio *bio;
 	int nr_phys_segs, nr_hw_segs;
@@ -1981,7 +1982,7 @@
 	rq->nr_hw_segments = nr_hw_segs;
 }
 
-inline void blk_recalc_rq_sectors(struct request *rq, int nsect)
+void blk_recalc_rq_sectors(struct request *rq, int nsect)
 {
 	if (blk_fs_request(rq)) {
 		rq->hard_sector += nsect;
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/block/nbd.c	Wed Nov 27 14:36:28 2002
@@ -26,6 +26,8 @@
  *   reduce number of partial TCP segments sent. <steve@chygwyn.com>
  * 01-12-6 Fix deadlock condition by making queue locks independant of
  *   the transmit lock. <steve@chygwyn.com>
+ * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes.
+ *   <Paul.Clements@SteelEye.com> <James.Bottomley@SteelEye.com>
  *
  * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
  * why not: would need verify_area and friends, would share yet another 
@@ -89,10 +91,12 @@
 
 	oldfs = get_fs();
 	set_fs(get_ds());
-
+	/* Allow interception of SIGKILL only
+	 * Don't allow other signals to interrupt the transmission */
 	spin_lock_irqsave(&current->sig->siglock, flags);
 	oldset = current->blocked;
 	sigfillset(&current->blocked);
+	sigdelsetmask(&current->blocked, sigmask(SIGKILL));
 	recalc_sigpending();
 	spin_unlock_irqrestore(&current->sig->siglock, flags);
 
@@ -115,6 +119,17 @@
 		else
 			result = sock_recvmsg(sock, &msg, size, 0);
 
+		if (signal_pending(current)) {
+			siginfo_t info;
+			spin_lock_irqsave(&current->sig->siglock, flags);
+			printk(KERN_WARNING "NBD (pid %d: %s) got signal %d\n",
+				current->pid, current->comm, 
+				dequeue_signal(&current->blocked, &info));
+			spin_unlock_irqrestore(&current->sig->siglock, flags);
+			result = -EINTR;
+			break;
+		}
+
 		if (result <= 0) {
 #ifdef PARANOIA
 			printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.\n",
@@ -154,6 +169,10 @@
 
 	down(&lo->tx_lock);
 
+	if (!sock || !lo->sock) {
+		FAIL("Attempted sendmsg to closed socket\n");
+	}
+
 	result = nbd_xmit(1, sock, (char *) &request, sizeof(request), nbd_cmd(req) == NBD_CMD_WRITE ? MSG_MORE : 0);
 	if (result <= 0)
 		FAIL("Sendmsg failed for control.");
@@ -324,11 +343,31 @@
 		spin_unlock_irq(q->queue_lock);
 
 		spin_lock(&lo->queue_lock);
+
+		if (!lo->file) {
+			spin_unlock(&lo->queue_lock);
+			printk(KERN_ERR "nbd: failed between accept and semaphore, file lost\n");
+			req->errors++;
+			nbd_end_request(req);
+			spin_lock_irq(q->queue_lock);
+			continue;
+		}
+
 		list_add(&req->queuelist, &lo->queue_head);
 		spin_unlock(&lo->queue_lock);
 
 		nbd_send_req(lo, req);
 
+		if (req->errors) {
+			printk(KERN_ERR "nbd: nbd_send_req failed\n");
+			spin_lock(&lo->queue_lock);
+			list_del(&req->queuelist);
+			spin_unlock(&lo->queue_lock);
+			nbd_end_request(req);
+			spin_lock_irq(q->queue_lock);
+			continue;
+		}
+
 		spin_lock_irq(q->queue_lock);
 		continue;
 
@@ -371,12 +410,14 @@
 			printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n");
 			return -EBUSY;
 		}
-		spin_unlock(&lo->queue_lock);
 		file = lo->file;
-		if (!file)
+		if (!file) {
+			spin_unlock(&lo->queue_lock);
 			return -EINVAL;
+		}
 		lo->file = NULL;
 		lo->sock = NULL;
+		spin_unlock(&lo->queue_lock);
 		fput(file);
 		return 0;
 	case NBD_SET_SOCK:
@@ -420,6 +461,26 @@
 		if (!lo->file)
 			return -EINVAL;
 		nbd_do_it(lo);
+		/* on return tidy up in case we have a signal */
+		/* Forcibly shutdown the socket causing all listeners
+		 * to error
+		 *
+		 * FIXME: This code is duplicated from sys_shutdown, but
+		 * there should be a more generic interface rather than
+		 * calling socket ops directly here */
+		down(&lo->tx_lock);
+		printk(KERN_WARNING "nbd: shutting down socket\n");
+		lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN);
+		lo->sock = NULL;
+		up(&lo->tx_lock);
+		spin_lock(&lo->queue_lock);
+		file = lo->file;
+		lo->file = NULL;
+		spin_unlock(&lo->queue_lock);
+		nbd_clear_que(lo);
+		printk(KERN_WARNING "nbd: queue cleared\n");
+		if (file)
+			fput(file);
 		return lo->harderror;
 	case NBD_CLEAR_QUE:
 		nbd_clear_que(lo);
@@ -498,7 +559,7 @@
 		init_MUTEX(&nbd_dev[i].tx_lock);
 		nbd_dev[i].blksize = 1024;
 		nbd_dev[i].blksize_bits = 10;
-		nbd_dev[i].bytesize = 0x7ffffc00; /* 2GB */
+		nbd_dev[i].bytesize = ((u64)0x7ffffc00) << 10; /* 2TB */
 		disk->major = MAJOR_NR;
 		disk->first_minor = i;
 		disk->fops = &nbd_fops;
diff -Nru a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
--- a/drivers/block/scsi_ioctl.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/block/scsi_ioctl.c	Wed Nov 27 14:36:32 2002
@@ -7,7 +7,7 @@
  *
  * 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.
  *
@@ -16,26 +16,20 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
  *
  */
-#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/config.h>
-#include <linux/swap.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/cdrom.h>
 #include <linux/slab.h>
 #include <linux/bio.h>
+#include <asm/uaccess.h>
 
-#include "../scsi/scsi.h"
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
 
-#include <asm/uaccess.h>
 
 /* Command group 3 is reserved and should never be used.  */
 const unsigned char scsi_command_size[8] =
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Wed Nov 27 14:36:32 2002
+++ b/drivers/char/Makefile	Wed Nov 27 14:36:32 2002
@@ -77,7 +77,7 @@
 obj-$(CONFIG_NWFLASH) += nwflash.o
 obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
 
-obj-$(CONFIG_WATCHDOGS)	+= watchdog/
+obj-$(CONFIG_WATCHDOG)	+= watchdog/
 obj-$(CONFIG_MWAVE) += mwave/
 obj-$(CONFIG_AGP) += agp/
 obj-$(CONFIG_DRM) += drm/
diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
--- a/drivers/char/agp/agp.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/char/agp/agp.h	Wed Nov 27 14:36:30 2002
@@ -294,7 +294,14 @@
 #define I810_DRAM_ROW_0		0x00000001
 #define I810_DRAM_ROW_0_SDRAM	0x00000001
 
-
+/* Intel 7505 registers */
+#define INTEL_I7505_NAPBASELO	0x10
+#define INTEL_I7505_APSIZE	0x74
+#define INTEL_I7505_NCAPID	0x60
+#define INTEL_I7505_NISTAT	0x6c
+#define INTEL_I7505_ATTBASE	0x78
+#define INTEL_I7505_ERRSTS	0x42
+#define INTEL_I7505_AGPCTRL	0x70
 
 /* VIA register */
 #define VIA_APBASE	0x10
diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c
--- a/drivers/char/cyclades.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/char/cyclades.c	Wed Nov 27 14:36:28 2002
@@ -3434,8 +3434,8 @@
 		}
 #ifdef CY_DEBUG_DTR
 		printk("cyc:set_line_char dropping DTR\n");
-		printk("     status: 0x%x,
-		    0x%x\n", cy_readb(base_addr+(CyMSVR1<<index)),
+		printk("     status: 0x%x, 0x%x\n", 
+		    cy_readb(base_addr+(CyMSVR1<<index)),
 		    cy_readb(base_addr+(CyMSVR2<<index)));
 #endif
 	    }else{
diff -Nru a/drivers/char/ftape/lowlevel/ftape-init.h b/drivers/char/ftape/lowlevel/ftape-init.h
--- a/drivers/char/ftape/lowlevel/ftape-init.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/char/ftape/lowlevel/ftape-init.h	Wed Nov 27 14:36:28 2002
@@ -40,15 +40,4 @@
 #define QIC117_TAPE_MAJOR 27
 #endif
 
-/*      ftape-init.c defined global variables.
- */
-
-
-/*      ftape-init.c defined global functions not defined in ftape.h
- */
-#ifdef MODULE
-asmlinkage extern int  init_module   (void);
-asmlinkage extern void cleanup_module(void);
-#endif
-
 #endif
diff -Nru a/drivers/char/ftape/zftape/zftape-ctl.c b/drivers/char/ftape/zftape/zftape-ctl.c
--- a/drivers/char/ftape/zftape/zftape-ctl.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/char/ftape/zftape/zftape-ctl.c	Wed Nov 27 14:36:29 2002
@@ -648,50 +648,6 @@
 	TRACE_EXIT 0;
 }
 
-/*  decide when we should lock the module in memory, even when calling
- *  the release routine. This really is necessary for use with
- *  kerneld.
- *
- *  NOTE: we MUST NOT use zft_write_protected, because this includes
- *  the file access mode as well which has no meaning with our 
- *  asynchronous update scheme.
- *
- *  Ugly, ugly. We need to look the module if we changed the block size.
- *  How sad! Need persistent modules storage!
- *
- *  NOTE: I don't want to lock the module if the number of dma buffers 
- *  has been changed. It's enough! Stop the story! Give me persisitent
- *  module storage! Do it!
- */
-int zft_dirty(void)
-{
-	if (!ft_formatted || zft_offline) { 
-		/* cannot be dirty if not formatted or offline */
-		return 0;
-	}
-	if (zft_blk_sz != CONFIG_ZFT_DFLT_BLK_SZ) {
-		/* blocksize changed, must lock */
-		return 1;
-	}
-	if (zft_mt_compression != 0) {
-		/* compression mode with /dev/qft, must lock */
-		return 1;
-	}
-	if (!zft_header_read) {
-		/* tape is logical at BOT, no lock */
-		return 0;
-	}
-	if (!zft_tape_at_lbot(&zft_pos)) {
-		/* somewhere inside a volume, lock tape */
-		return 1;
-	}
-	if (zft_volume_table_changed || zft_header_changed) {
-		/* header segments dirty if tape not write protected */
-		return !(ft_write_protected || zft_old_ftape);
-	}
-	return 0;
-}
-
 /*      OPEN routine called by kernel-interface code
  *
  *      NOTE: this is also called by mt_reset() with dev_minor == -1
diff -Nru a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
--- a/drivers/char/ftape/zftape/zftape-init.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/char/ftape/zftape/zftape-init.c	Wed Nov 27 14:36:29 2002
@@ -314,7 +314,7 @@
 /*  Called by modules package when installing the driver or by kernel
  *  during the initialization phase
  */
-int __init zft_init(void)
+static int __init zft_init(void)
 {
 	int i;
 	TRACE_FUN(ft_t_flow);
@@ -392,27 +392,9 @@
 }
 
 
-#ifdef MODULE
-/* Called by modules package before trying to unload the module
- */
-static int can_unload(void)
-{
-	return (GET_USE_COUNT(THIS_MODULE)||zft_dirty()||test_bit(0,&busy_flag))?-EBUSY:0;
-}
-/* Called by modules package when installing the driver
- */
-int init_module(void)
-{
-	if (!mod_member_present(&__this_module, can_unload)) {
-		return -EBUSY;
-	}
-	__this_module.can_unload = can_unload;
-	return zft_init();
-}
-
 /* Called by modules package when removing the driver 
  */
-void cleanup_module(void)
+static void zft_exit(void)
 {
 	int i;
 	TRACE_FUN(ft_t_flow);
@@ -435,4 +417,5 @@
 	TRACE_EXIT;
 }
 
-#endif /* MODULE */
+module_init(zft_init);
+module_exit(zft_exit);
diff -Nru a/drivers/char/ftape/zftape/zftape-init.h b/drivers/char/ftape/zftape/zftape-init.h
--- a/drivers/char/ftape/zftape/zftape-init.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/char/ftape/zftape/zftape-init.h	Wed Nov 27 14:36:30 2002
@@ -73,13 +73,6 @@
 extern struct zft_cmpr_ops *zft_cmpr_unregister(void);
 extern int                  zft_cmpr_lock(int try_to_load);
 
-#ifdef MODULE
-
-asmlinkage extern int  init_module(void);
-asmlinkage extern void cleanup_module(void);
-
-#endif
-
 #endif
 
 
diff -Nru a/drivers/char/i810-tco.h b/drivers/char/i810-tco.h
--- a/drivers/char/i810-tco.h	Wed Nov 27 14:36:31 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,42 +0,0 @@
-/*
- *	i810-tco 0.05:	TCO timer driver for i8xx chipsets
- *
- *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
- *				http://www.kernelconcepts.de
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- *	
- *	Neither kernel concepts nor Nils Faerber admit liability nor provide
- *	warranty for any of this software. This material is provided
- *	"AS-IS" and at no charge.
- *
- *	(c) Copyright 2000	kernel concepts <nils@kernelconcepts.de>
- *				developed for
- *                              Jentro AG, Haar/Munich (Germany)
- *
- *	TCO timer driver for i8xx chipsets
- *	based on softdog.c by Alan Cox <alan@redhat.com>
- *
- *	For history and the complete list of supported I/O Controller Hub's
- *	see i810-tco.c
- */
-
-
-/*
- * Some address definitions for the i810 TCO
- */
-
-#define	TCOBASE		ACPIBASE + 0x60	/* TCO base address		*/
-#define TCO1_RLD	TCOBASE + 0x00	/* TCO Timer Reload and Current Value */
-#define TCO1_TMR	TCOBASE + 0x01	/* TCO Timer Initial Value	*/
-#define	TCO1_DAT_IN	TCOBASE + 0x02	/* TCO Data In Register		*/
-#define	TCO1_DAT_OUT	TCOBASE + 0x03	/* TCO Data Out Register	*/
-#define	TCO1_STS	TCOBASE + 0x04	/* TCO1 Status Register		*/
-#define	TCO2_STS	TCOBASE + 0x06	/* TCO2 Status Register		*/
-#define TCO1_CNT	TCOBASE + 0x08	/* TCO1 Control Register	*/
-#define TCO2_CNT	TCOBASE + 0x0a	/* TCO2 Control Register	*/
-
-#define	SMI_EN		ACPIBASE + 0x30	/* SMI Control and Enable Register */
diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c
--- a/drivers/char/ip2main.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/char/ip2main.c	Wed Nov 27 14:36:32 2002
@@ -253,10 +253,6 @@
 /***********************/
 
 /* Global module entry functions */
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-#endif
 
 /* Private (static) functions */
 static int  ip2_open(PTTY, struct file *);
diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c
--- a/drivers/char/keyboard.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/char/keyboard.c	Wed Nov 27 14:36:29 2002
@@ -681,8 +681,8 @@
 
 static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)
 {
-	static const char *pad_chars = "0123456789+-*/\015,.?()";
-	static const char *app_map = "pqrstuvwxylSRQMnnmPQ";
+	static const char *pad_chars = "0123456789+-*/\015,.?()#";
+	static const char *app_map = "pqrstuvwxylSRQMnnmPQS";
 
 	if (up_flag)
 		return;		/* no action, if this is a key release */
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/char/mem.c	Wed Nov 27 14:36:30 2002
@@ -697,9 +697,6 @@
 	lp_m68k_init();
 #endif
 	misc_init();
-#if CONFIG_QIC02_TAPE
-	qic02_tape_init();
-#endif
 #ifdef CONFIG_FTAPE
 	ftape_init();
 #endif
diff -Nru a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
--- a/drivers/char/rio/riocmd.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/char/rio/riocmd.c	Wed Nov 27 14:36:28 2002
@@ -462,8 +462,8 @@
 		rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", PacketP->len,PacketP->len );
 		rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", PacketP->control, PacketP->control);
 		rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", PacketP->csum, PacketP->csum );
-		rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, 
-					Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command );
+		rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, "
+					"Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command );
 		return TRUE;
 	}
 
diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c
--- a/drivers/char/rocket.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/char/rocket.c	Wed Nov 27 14:36:31 2002
@@ -1330,7 +1330,7 @@
 {
 	if (tty)
 		sprintf(buf, "%s%d", tty->driver.name,
-			MINOR(tty->device) - tty->driver.minor_start +
+			minor(tty->device) - tty->driver.minor_start +
 			tty->driver.name_base);
 	else
 		strcpy(buf, "NULL tty");
@@ -1794,6 +1794,10 @@
 		str = "8-port Modem";
 		max_num_aiops = 1;
 		break;
+	case 0x8:
+		str = "mysterious 8 port";
+		max_num_aiops = 1;
+		break;
 	default:
 		str = "(unknown/unsupported)";
 		max_num_aiops = 0;
@@ -1872,6 +1876,10 @@
 			PCI_DEVICE_ID_RP8M, i, &bus, &device_fn)) 
 			if(register_PCI(count+boards_found, bus, device_fn))
 				count++;
+		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
+			0x8, i, &bus, &device_fn)) 
+			if(register_PCI(count+boards_found, bus, device_fn))
+				count++;
 	}
 	return(count);
 }
@@ -2072,6 +2080,7 @@
 	if (retval < 0) {
 		printk("Couldn't install Rocketport callout driver "
 		       "(error %d)\n", -retval);
+		release_region(controller, 4);
 		return -1;
 	}
 
@@ -2079,6 +2088,7 @@
 	if (retval < 0) {
 		printk("Couldn't install tty Rocketport driver "
 		       "(error %d)\n", -retval);
+		release_region(controller, 4);
 		return -1;
 	}
 #ifdef ROCKET_DEBUG_OPEN
diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c
--- a/drivers/char/sx.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/char/sx.c	Wed Nov 27 14:36:29 2002
@@ -353,9 +353,11 @@
                               0xc8000, 0xd8000, 0xe8000};
 static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
                               0xc8000, 0xd8000, 0xe8000, 0xa0000};
+static int si1_probe_addrs[]= { 0xd0000};
 
 #define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
 #define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
+#define NR_SI1_ADDRS (sizeof(si1_probe_addrs)/sizeof (int))
 
 
 /* Set the mask to all-ones. This alas, only supports 32 interrupts. 
@@ -582,6 +584,8 @@
 		}
 	} else if (IS_EISA_BOARD(board)) {
 		outb(board->irq<<4, board->eisa_base+0xc02);
+	} else if (IS_SI1_BOARD(board)) {
+	        write_sx_byte (board, SI1_ISA_RESET,   0); // value does not matter
 	} else {
 		/* Gory details of the SI/ISA board */
 		write_sx_byte (board, SI2_ISA_RESET,    SI2_ISA_RESET_SET);
@@ -656,6 +660,9 @@
 	} else if (IS_EISA_BOARD(board)) {
 		write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
 		outb((board->irq<<4)|4, board->eisa_base+0xc02);
+	} else if (IS_SI1_BOARD(board)) {
+		write_sx_byte (board, SI1_ISA_RESET_CLEAR, 0);
+		write_sx_byte (board, SI1_ISA_INTCL, 0);
 	} else {
 		/* Don't bug me about the clear_set. 
 		   I haven't the foggiest idea what it's about -- REW */
@@ -681,6 +688,9 @@
 		                                 SX_CONF_HOSTIRQ);
 	} else if (IS_EISA_BOARD(board)) {
 		inb(board->eisa_base+0xc03);  
+	} else if (IS_SI1_BOARD(board)) {
+	       write_sx_byte (board, SI1_ISA_INTCL,0);
+	       write_sx_byte (board, SI1_ISA_INTCL_CLEAR,0);
 	} else {
 		switch (board->irq) {
 		case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break;
@@ -1690,6 +1700,7 @@
 		if (IS_SX_BOARD (board)) rc = SX_TYPE_SX;
 		if (IS_CF_BOARD (board)) rc = SX_TYPE_CF;
 		if (IS_SI_BOARD (board)) rc = SX_TYPE_SI;
+		if (IS_SI1_BOARD (board)) rc = SX_TYPE_SI;
 		if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI;
 		sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
 		break;
@@ -2184,13 +2195,20 @@
 	int i;
 
 	func_enter();
-	sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature %lx.\n", 
+	sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at %lx.\n", board->hw_base,
 	            board->base + SI2_ISA_ID_BASE);
 
 	if (sx_debug & SX_DEBUG_PROBE)
 		my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8);
 
 	if (!IS_EISA_BOARD(board)) {
+	  if( IS_SI1_BOARD(board) ) 
+	    {
+		for (i=0;i<8;i++) {
+		  write_sx_byte (board, SI2_ISA_ID_BASE+7-i,i); 
+
+		}
+	    }
 		for (i=0;i<8;i++) {
 			if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
 				return 0;
@@ -2198,6 +2216,23 @@
 		}
 	}
 
+	/* Now we're pretty much convinced that there is an SI board here, 
+	   but to prevent trouble, we'd better double check that we don't
+	   have an SI1 board when we're probing for an SI2 board.... */
+
+	write_sx_byte (board, SI2_ISA_ID_BASE,0x10); 
+	if ( IS_SI1_BOARD(board)) {
+		/* This should be an SI1 board, which has this
+		   location writable... */
+		if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+			return 0; 
+	} else {
+		/* This should be an SI2 board, which has the bottom
+		   3 bits non-writable... */
+		if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+			return 0; 
+	}
+
 	printheader ();
 
 	printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
@@ -2554,6 +2589,21 @@
 		board->base = (ulong) ioremap(board->hw_base, SI2_ISA_WINDOW_LEN);
 		board->flags &= ~SX_BOARD_TYPE;
 		board->flags |=  SI_ISA_BOARD;
+		board->irq = sx_irqmask ?-1:0;
+
+		if (probe_si (board)) {
+			found++;
+		} else {
+			my_iounmap (board->hw_base, board->base);
+		}
+	}
+	for (i=0;i<NR_SI1_ADDRS;i++) {
+		board = &boards[found];
+		board->hw_base = si1_probe_addrs[i];
+		board->base2 =
+		board->base = (ulong) ioremap(board->hw_base, SI1_ISA_WINDOW_LEN);
+		board->flags &= ~SX_BOARD_TYPE;
+		board->flags |=  SI1_ISA_BOARD;
 		board->irq = sx_irqmask ?-1:0;
 
 		if (probe_si (board)) {
diff -Nru a/drivers/char/sx.h b/drivers/char/sx.h
--- a/drivers/char/sx.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/char/sx.h	Wed Nov 27 14:36:28 2002
@@ -69,6 +69,7 @@
 #define SX_CFPCI_BOARD       0x00000008
 #define SX_CFISA_BOARD       0x00000010
 #define SI_EISA_BOARD        0x00000020
+#define SI1_ISA_BOARD        0x00000040
 
 #define SX_BOARD_PRESENT     0x00001000
 #define SX_BOARD_INITIALIZED 0x00002000
@@ -80,6 +81,7 @@
                                             SX_ISA_BOARD | SX_CFISA_BOARD))
 
 #define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
+#define IS_SI1_BOARD(board) (board->flags & SI1_ISA_BOARD)
 
 #define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD)
 
diff -Nru a/drivers/char/sxboards.h b/drivers/char/sxboards.h
--- a/drivers/char/sxboards.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/char/sxboards.h	Wed Nov 27 14:36:27 2002
@@ -46,12 +46,36 @@
 #define		CARD_BUS(type)		((type>>4)&0xF)
 #define		CARD_PHASE(type)	(type&0xF)
 
+#define		TYPE_SI1_ISA		CARD_TYPE(BUS_ISA,SI1_Z280)
 #define		TYPE_SI2_ISA		CARD_TYPE(BUS_ISA,SI2_Z280)
 #define		TYPE_SI2_EISA		CARD_TYPE(BUS_EISA,SI2_Z280)
 #define		TYPE_SI2_PCI		CARD_TYPE(BUS_PCI,SI2_Z280)
 
 #define		TYPE_SX_ISA		CARD_TYPE(BUS_ISA,SI3_T225)
 #define		TYPE_SX_PCI		CARD_TYPE(BUS_PCI,SI3_T225)
+/*****************************************************************************
+******************************                  ******************************
+******************************   Phase 1 Z280   ******************************
+******************************                  ******************************
+*****************************************************************************/
+
+/* ISA board details... */
+#define		SI1_ISA_WINDOW_LEN	0x10000		/* 64 Kbyte shared memory window */
+//#define 	SI1_ISA_MEMORY_LEN	0x8000		/* Usable memory  - unused define*/
+//#define		SI1_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
+//#define		SI1_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
+//#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
+//#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
+
+/* ISA board, register definitions... */
+//#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
+#define		SI1_ISA_RESET		0x8000		/* WRITE: Host Reset */
+#define		SI1_ISA_RESET_CLEAR	0xc000		/* WRITE: Host Reset clear*/
+#define		SI1_ISA_WAIT	        0x9000		/* WRITE: Host wait */
+#define		SI1_ISA_WAIT_CLEAR	0xd000		/* WRITE: Host wait clear */
+#define		SI1_ISA_INTCL        	0xa000		/* WRITE: Host Reset */
+#define		SI1_ISA_INTCL_CLEAR	0xe000		/* WRITE: Host Reset */
+
 
 /*****************************************************************************
 ******************************                  ******************************
diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c
--- a/drivers/char/synclink.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/char/synclink.c	Wed Nov 27 14:36:29 2002
@@ -875,22 +875,22 @@
  * Global linked list of SyncLink devices
  */
 struct mgsl_struct *mgsl_device_list;
-int mgsl_device_count;
+static int mgsl_device_count;
 
 /*
  * Set this param to non-zero to load eax with the
  * .text section address and breakpoint on module load.
  * This is useful for use with gdb and add-symbol-file command.
  */
-int break_on_load;
+static int break_on_load;
 
 /*
  * Driver major number, defaults to zero to get auto
  * assigned major number. May be forced as module parameter.
  */
-int ttymajor;
+static int ttymajor;
 
-int cuamajor;
+static int cuamajor;
 
 /*
  * Array of user specified options for ISA adapters.
diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
--- a/drivers/char/tpqic02.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/char/tpqic02.c	Wed Nov 27 14:36:30 2002
@@ -2759,9 +2759,7 @@
 	return 0;
 }				/* qic02_tape_init */
 
-#ifdef MODULE
-
-void cleanup_module(void)
+static void qic02_module_exit(void)
 {
 	unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME);
 	if (status_zombie == NO)
@@ -2777,7 +2775,7 @@
 	devfs_remove("tpqic150");
 }
 
-int init_module(void)
+static int qic02_module_init(void)
 {
 	int retval;
 	retval = qic02_tape_init();
@@ -2788,12 +2786,14 @@
 	if (!retval && qic02_tape_dynconf.ifc_type) {
 		retval = update_ifc_masks(qic02_tape_dynconf.ifc_type);
 		if (retval) {
-			cleanup_module();
+			qic02_module_exit();
 		}
 	}
 # endif
 	return retval;
 }
-#endif
 
 MODULE_LICENSE("GPL");
+
+module_init(qic02_module_init);
+module_exit(qic02_module_exit);
diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
--- a/drivers/char/watchdog/Makefile	Wed Nov 27 14:36:31 2002
+++ b/drivers/char/watchdog/Makefile	Wed Nov 27 14:36:31 2002
@@ -7,21 +7,21 @@
 # watchdog dies or is 'borrowed' for some reason the software watchdog
 # still gives you some cover.
 
-watchdog-$(CONFIG_PCWATCHDOG) += pcwd.o
-watchdog-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
-watchdog-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
-watchdog-$(CONFIG_IB700_WDT) += ib700wdt.o
-watchdog-$(CONFIG_MIXCOMWD) += mixcomwd.o
-watchdog-$(CONFIG_SCx200_WDT) += scx200_wdt.o
-watchdog-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
-watchdog-$(CONFIG_WDT) += wdt.o
-watchdog-$(CONFIG_WDTPCI) += wdt_pci.o
-watchdog-$(CONFIG_21285_WATCHDOG) += wdt285.o
-watchdog-$(CONFIG_977_WATCHDOG) += wdt977.o
-watchdog-$(CONFIG_I810_TCO) += i810-tco.o
-watchdog-$(CONFIG_MACHZ_WDT) += machzwd.o
-watchdog-$(CONFIG_SH_WDT) += shwdt.o
-watchdog-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
-watchdog-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+obj-$(CONFIG_PCWATCHDOG) += pcwd.o
+obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
+obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
+obj-$(CONFIG_IB700_WDT) += ib700wdt.o
+obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
+obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
+obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+obj-$(CONFIG_WDT) += wdt.o
+obj-$(CONFIG_WDTPCI) += wdt_pci.o
+obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
+obj-$(CONFIG_977_WATCHDOG) += wdt977.o
+obj-$(CONFIG_I810_TCO) += i810-tco.o
+obj-$(CONFIG_MACHZ_WDT) += machzwd.o
+obj-$(CONFIG_SH_WDT) += shwdt.o
+obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
+obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/char/watchdog/i810-tco.h b/drivers/char/watchdog/i810-tco.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/watchdog/i810-tco.h	Wed Nov 27 14:36:31 2002
@@ -0,0 +1,42 @@
+/*
+ *	i810-tco 0.05:	TCO timer driver for i8xx chipsets
+ *
+ *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
+ *				http://www.kernelconcepts.de
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *	
+ *	Neither kernel concepts nor Nils Faerber admit liability nor provide
+ *	warranty for any of this software. This material is provided
+ *	"AS-IS" and at no charge.
+ *
+ *	(c) Copyright 2000	kernel concepts <nils@kernelconcepts.de>
+ *				developed for
+ *                              Jentro AG, Haar/Munich (Germany)
+ *
+ *	TCO timer driver for i8xx chipsets
+ *	based on softdog.c by Alan Cox <alan@redhat.com>
+ *
+ *	For history and the complete list of supported I/O Controller Hub's
+ *	see i810-tco.c
+ */
+
+
+/*
+ * Some address definitions for the i810 TCO
+ */
+
+#define	TCOBASE		ACPIBASE + 0x60	/* TCO base address		*/
+#define TCO1_RLD	TCOBASE + 0x00	/* TCO Timer Reload and Current Value */
+#define TCO1_TMR	TCOBASE + 0x01	/* TCO Timer Initial Value	*/
+#define	TCO1_DAT_IN	TCOBASE + 0x02	/* TCO Data In Register		*/
+#define	TCO1_DAT_OUT	TCOBASE + 0x03	/* TCO Data Out Register	*/
+#define	TCO1_STS	TCOBASE + 0x04	/* TCO1 Status Register		*/
+#define	TCO2_STS	TCOBASE + 0x06	/* TCO2 Status Register		*/
+#define TCO1_CNT	TCOBASE + 0x08	/* TCO1 Control Register	*/
+#define TCO2_CNT	TCOBASE + 0x0a	/* TCO2 Control Register	*/
+
+#define	SMI_EN		ACPIBASE + 0x30	/* SMI Control and Enable Register */
diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
--- a/drivers/char/watchdog/sbc60xxwdt.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/char/watchdog/sbc60xxwdt.c	Wed Nov 27 14:36:31 2002
@@ -310,15 +310,16 @@
 
 	unregister_reboot_notifier(&wdt_notifier);
 	release_region(WDT_START,1);
-	release_region(WDT_STOP,1);
+//	release_region(WDT_STOP,1);
 }
 
 static int __init sbc60xxwdt_init(void)
 {
 	int rc = -EBUSY;
 
-	if (!request_region(WDT_STOP, 1, "SBC 60XX WDT"))
-		goto err_out;
+//	We cannot reserve 0x45 - the kernel already has!
+//	if (!request_region(WDT_STOP, 1, "SBC 60XX WDT"))
+//		goto err_out;
 	if (!request_region(WDT_START, 1, "SBC 60XX WDT"))
 		goto err_out_region1;
 
diff -Nru a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
--- a/drivers/char/watchdog/scx200_wdt.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/char/watchdog/scx200_wdt.c	Wed Nov 27 14:36:31 2002
@@ -245,13 +245,18 @@
 	sema_init(&open_semaphore, 1);
 
 	r = misc_register(&scx200_wdt_miscdev);
-	if (r)
+	if (r) {
+		release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+				SCx200_WDT_SIZE);
 		return r;
+	}
 
 	r = register_reboot_notifier(&scx200_wdt_notifier);
         if (r) {
                 printk(KERN_ERR NAME ": unable to register reboot notifier");
 		misc_deregister(&scx200_wdt_miscdev);
+		release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+				SCx200_WDT_SIZE);
                 return r;
         }
 
diff -Nru a/drivers/char/watchdog/wd501p.h b/drivers/char/watchdog/wd501p.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/watchdog/wd501p.h	Wed Nov 27 14:36:27 2002
@@ -0,0 +1,91 @@
+/*
+ *	Industrial Computer Source WDT500/501 driver for Linux 1.3.x
+ *
+ *	(c) Copyright 1995	CymruNET Ltd
+ *				Innovation Centre
+ *				Singleton Park
+ *				Swansea
+ *				Wales
+ *				UK
+ *				SA2 8PP
+ *
+ *	http://www.cymru.net
+ *
+ *	This driver is provided under the GNU General Public License, incorporated
+ *	herein by reference. The driver is provided without warranty or 
+ *	support.
+ *
+ *	Release 0.04.
+ *
+ */
+
+#include <linux/config.h>
+
+#define WDT_COUNT0		(io+0)
+#define WDT_COUNT1		(io+1)
+#define WDT_COUNT2		(io+2)
+#define WDT_CR			(io+3)
+#define WDT_SR			(io+4)	/* Start buzzer on PCI write */
+#define WDT_RT			(io+5)	/* Stop buzzer on PCI write */
+#define WDT_BUZZER		(io+6)	/* PCI only: rd=disable, wr=enable */
+#define WDT_DC			(io+7)
+
+/* The following are only on the PCI card, they're outside of I/O space on
+ * the ISA card: */
+#define WDT_CLOCK		(io+12)	/* COUNT2: rd=16.67MHz, wr=2.0833MHz */
+/* inverted opto isolated reset output: */
+#define WDT_OPTONOTRST		(io+13)	/* wr=enable, rd=disable */
+/* opto isolated reset output: */
+#define WDT_OPTORST		(io+14)	/* wr=enable, rd=disable */
+/* programmable outputs: */
+#define WDT_PROGOUT		(io+15)	/* wr=enable, rd=disable */
+
+#define WDC_SR_WCCR		1	/* Active low */
+#define WDC_SR_TGOOD		2
+#define WDC_SR_ISOI0		4
+#define WDC_SR_ISII1		8
+#define WDC_SR_FANGOOD		16
+#define WDC_SR_PSUOVER		32	/* Active low */
+#define WDC_SR_PSUUNDR		64	/* Active low */
+#define WDC_SR_IRQ		128	/* Active low */
+
+#ifndef WDT_IS_PCI
+
+/*
+ *	Feature Map 1 is the active high inputs not supported on your card.
+ *	Feature Map 2 is the active low inputs not supported on your card.
+ */
+ 
+#ifdef CONFIG_WDT_501		/* Full board */
+
+#ifdef CONFIG_WDT501_FAN	/* Full board, Fan has no tachometer */
+#define FEATUREMAP1		0
+#define WDT_OPTION_MASK		(WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT)
+#else
+#define FEATUREMAP1		WDC_SR_FANGOOD
+#define WDT_OPTION_MASK		(WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2)
+#endif
+
+#define FEATUREMAP2		0
+#endif
+
+#ifndef CONFIG_WDT_501
+#define CONFIG_WDT_500
+#endif
+
+#ifdef CONFIG_WDT_500		/* Minimal board */
+#define FEATUREMAP1		(WDC_SR_TGOOD|WDC_SR_FANGOOD)
+#define FEATUREMAP2		(WDC_SR_PSUOVER|WDC_SR_PSUUNDR)
+#define WDT_OPTION_MASK		(WDIOF_OVERHEAT)
+#endif
+
+#else
+
+#define FEATUREMAP1		(WDC_SR_TGOOD|WDC_SR_FANGOOD)
+#define FEATUREMAP2		(WDC_SR_PSUOVER|WDC_SR_PSUUNDR)
+#define WDT_OPTION_MASK		(WDIOF_OVERHEAT)
+#endif
+
+#ifndef FEATUREMAP1
+#error "Config option not set"
+#endif
diff -Nru a/drivers/char/wd501p.h b/drivers/char/wd501p.h
--- a/drivers/char/wd501p.h	Wed Nov 27 14:36:27 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,91 +0,0 @@
-/*
- *	Industrial Computer Source WDT500/501 driver for Linux 1.3.x
- *
- *	(c) Copyright 1995	CymruNET Ltd
- *				Innovation Centre
- *				Singleton Park
- *				Swansea
- *				Wales
- *				UK
- *				SA2 8PP
- *
- *	http://www.cymru.net
- *
- *	This driver is provided under the GNU General Public License, incorporated
- *	herein by reference. The driver is provided without warranty or 
- *	support.
- *
- *	Release 0.04.
- *
- */
-
-#include <linux/config.h>
-
-#define WDT_COUNT0		(io+0)
-#define WDT_COUNT1		(io+1)
-#define WDT_COUNT2		(io+2)
-#define WDT_CR			(io+3)
-#define WDT_SR			(io+4)	/* Start buzzer on PCI write */
-#define WDT_RT			(io+5)	/* Stop buzzer on PCI write */
-#define WDT_BUZZER		(io+6)	/* PCI only: rd=disable, wr=enable */
-#define WDT_DC			(io+7)
-
-/* The following are only on the PCI card, they're outside of I/O space on
- * the ISA card: */
-#define WDT_CLOCK		(io+12)	/* COUNT2: rd=16.67MHz, wr=2.0833MHz */
-/* inverted opto isolated reset output: */
-#define WDT_OPTONOTRST		(io+13)	/* wr=enable, rd=disable */
-/* opto isolated reset output: */
-#define WDT_OPTORST		(io+14)	/* wr=enable, rd=disable */
-/* programmable outputs: */
-#define WDT_PROGOUT		(io+15)	/* wr=enable, rd=disable */
-
-#define WDC_SR_WCCR		1	/* Active low */
-#define WDC_SR_TGOOD		2
-#define WDC_SR_ISOI0		4
-#define WDC_SR_ISII1		8
-#define WDC_SR_FANGOOD		16
-#define WDC_SR_PSUOVER		32	/* Active low */
-#define WDC_SR_PSUUNDR		64	/* Active low */
-#define WDC_SR_IRQ		128	/* Active low */
-
-#ifndef WDT_IS_PCI
-
-/*
- *	Feature Map 1 is the active high inputs not supported on your card.
- *	Feature Map 2 is the active low inputs not supported on your card.
- */
- 
-#ifdef CONFIG_WDT_501		/* Full board */
-
-#ifdef CONFIG_WDT501_FAN	/* Full board, Fan has no tachometer */
-#define FEATUREMAP1		0
-#define WDT_OPTION_MASK		(WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT)
-#else
-#define FEATUREMAP1		WDC_SR_FANGOOD
-#define WDT_OPTION_MASK		(WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2)
-#endif
-
-#define FEATUREMAP2		0
-#endif
-
-#ifndef CONFIG_WDT_501
-#define CONFIG_WDT_500
-#endif
-
-#ifdef CONFIG_WDT_500		/* Minimal board */
-#define FEATUREMAP1		(WDC_SR_TGOOD|WDC_SR_FANGOOD)
-#define FEATUREMAP2		(WDC_SR_PSUOVER|WDC_SR_PSUUNDR)
-#define WDT_OPTION_MASK		(WDIOF_OVERHEAT)
-#endif
-
-#else
-
-#define FEATUREMAP1		(WDC_SR_TGOOD|WDC_SR_FANGOOD)
-#define FEATUREMAP2		(WDC_SR_PSUOVER|WDC_SR_PSUUNDR)
-#define WDT_OPTION_MASK		(WDIOF_OVERHEAT)
-#endif
-
-#ifndef FEATUREMAP1
-#error "Config option not set"
-#endif
diff -Nru a/drivers/hotplug/cpqphp_nvram.c b/drivers/hotplug/cpqphp_nvram.c
--- a/drivers/hotplug/cpqphp_nvram.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/hotplug/cpqphp_nvram.c	Wed Nov 27 14:36:31 2002
@@ -177,12 +177,12 @@
 	
 	spin_lock_irqsave(&int15_lock, flags);
 	__asm__ (
-		"xorl   %%ebx,%%ebx
-		xorl    %%edx,%%edx
-		pushf
-		push    %%cs
-		cli
-		call    *%6"
+		"xorl   %%ebx,%%ebx\n" \
+		"xorl    %%edx,%%edx\n" \
+		"pushf\n" \
+		"push %%cs\n" \
+		"cli\n" \
+		"call *%6\n"
 		: "=c" (*buf_size), "=a" (ret_val)
 		: "a" (op), "c" (*buf_size), "S" (ev_name),
 		"D" (buffer), "m" (compaq_int15_entry_point)
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/i2c/i2c-dev.c	Wed Nov 27 14:36:31 2002
@@ -115,6 +115,9 @@
 
 	struct i2c_client *client = (struct i2c_client *)file->private_data;
 
+	if(count > 8192)
+		count = 8192;
+		
 	/* copy user space data to kernel space. */
 	tmp = kmalloc(count,GFP_KERNEL);
 	if (tmp==NULL)
@@ -143,6 +146,9 @@
 	struct inode *inode = file->f_dentry->d_inode;
 #endif /* DEBUG */
 
+	if(count > 8192)
+		count = 8192;
+		
 	/* copy user space data to kernel space. */
 	tmp = kmalloc(count,GFP_KERNEL);
 	if (tmp==NULL)
diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig
--- a/drivers/ide/Kconfig	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/Kconfig	Wed Nov 27 14:36:30 2002
@@ -467,17 +467,25 @@
 	  If you say Y here, you need to say Y to "Use DMA by default
 	  when available" as well.
 
+config BLK_DEV_CS5520
+	tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)"
+	depends on BLK_DEV_IDEDMA_PCI && EXPERIMENTAL
+	help
+	  Include support for PIO tuning an virtual DMA on the Cyrix MediaGX 
+	  5510/5520 chipset. This will automatically be detected and
+	  configured if found.
+
+	  It is safe to say Y to this question.
+
 config BLK_DEV_CS5530
-	tristate "Cyrix CS5530 MediaGX chipset support"
-	depends on BLK_DEV_IDEDMA_PCI
+	tristate "Cyrix/National Semiconductor CS5530 MediaGX chipset support"
+	depends on BLK_DEV_IDEDMA_PCIOA
 	help
 	  Include support for UDMA on the Cyrix MediaGX 5530 chipset. This
 	  will automatically be detected and configured if found.
 
 	  It is safe to say Y to this question.
 
-	  People with SCSI-only systems should say N here. If unsure, say Y.
-
 config BLK_DEV_HPT34X
 	tristate "HPT34X chipset support"
 	depends on BLK_DEV_IDEDMA_PCI
@@ -524,6 +532,13 @@
 	  ide-probe at boot. It is reported to support DVD II drives, by the
 	  manufacturer.
 
+config BLK_DEV_SC1200
+	tristate "National SCx200 chipset support"
+	depends on BLK_DEV_IDEDMA_PCI
+	help
+	  This driver adds support for the built in IDE on the National
+	  SCx200 series of embedded x86 "Geode" systems
+
 config BLK_DEV_PIIX
 	tristate "Intel PIIXn chipsets support"
 	depends on BLK_DEV_IDEDMA_PCI
@@ -616,6 +631,9 @@
 config BLK_DEV_SIIMAGE
 	tristate "Silicon Image chipset support"
 	depends on BLK_DEV_IDEDMA_PCI
+	help
+	  This driver adds PIO/(U)DMA support for the SI CMD680 and SII
+	  3112 (Serial ATA) chips.
 
 config BLK_DEV_SIS5513
 	tristate "SiS5513 chipset support"
diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile
--- a/drivers/ide/Makefile	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/Makefile	Wed Nov 27 14:36:30 2002
@@ -7,14 +7,14 @@
 # Note : at this point, these files are compiled on all systems.
 # In the future, some of these should be built conditionally.
 #
-export-objs := ide-iops.o ide-taskfile.o ide-proc.o ide.o ide-probe.o ide-dma.o ide-lib.o setup-pci.o
+export-objs := ide-iops.o ide-taskfile.o ide-proc.o ide.o ide-probe.o ide-dma.o ide-lib.o setup-pci.o ide-io.o
 
 # First come modules that register themselves with the core
 obj-$(CONFIG_BLK_DEV_IDEPCI)		+= pci/
 
 # Core IDE code - must come before legacy
 
-obj-$(CONFIG_BLK_DEV_IDE)		+= ide-probe.o ide-geometry.o ide-iops.o ide-taskfile.o ide.o ide-lib.o
+obj-$(CONFIG_BLK_DEV_IDE)		+= ide-io.o ide-probe.o ide-geometry.o ide-iops.o ide-taskfile.o ide.o ide-lib.o
 obj-$(CONFIG_BLK_DEV_IDEDISK)		+= ide-disk.o
 obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd.o
 obj-$(CONFIG_BLK_DEV_IDETAPE)		+= ide-tape.o
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/ide-cd.c	Wed Nov 27 14:36:30 2002
@@ -2965,10 +2965,8 @@
 
 	printk(", %dkB Cache", be16_to_cpu(cap.buffer_size));
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (drive->using_dma)
 		(void) HWIF(drive)->ide_dma_verbose(drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	printk("\n");
 
 	return nslots;
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/ide/ide-disk.c	Wed Nov 27 14:36:29 2002
@@ -1412,24 +1412,6 @@
 	return call_idedisk_standby(drive, 0);
 }
 
-static int call_idedisk_suspend (ide_drive_t *drive, int arg)
-{
-	ide_task_t args;
-	u8 suspend = (arg) ? WIN_SLEEPNOW2 : WIN_SLEEPNOW1;
-	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_COMMAND_OFFSET]	= suspend;
-	args.command_type			= ide_cmd_type_parser(&args);
-	return ide_raw_taskfile(drive, &args, NULL);
-}
-
-static int do_idedisk_suspend (ide_drive_t *drive)
-{
-	if (drive->suspend_reset)
-		return 1;
-
-	return call_idedisk_suspend(drive, 0);
-}
-
 #if 0
 static int call_idedisk_checkpower (ide_drive_t *drive, int arg)
 {
@@ -1456,13 +1438,6 @@
 }
 #endif
 
-static int do_idedisk_resume (ide_drive_t *drive)
-{
-	if (!drive->suspend_reset)
-		return 1;
-	return 0;
-}
-
 static int do_idedisk_flushcache (ide_drive_t *drive)
 {
 	ide_task_t args;
@@ -1561,6 +1536,39 @@
 #endif
 }
 
+static int idedisk_suspend(struct device *dev, u32 state, u32 level)
+{
+	ide_drive_t *drive = dev->driver_data;
+
+	printk("Suspending device %p\n", dev->driver_data);
+
+	/* I hope that every freeze operation from the upper levels have
+	 * already been done...
+	 */
+
+	if (level != SUSPEND_SAVE_STATE)
+		return 0;
+
+	/* set the drive to standby */
+	printk(KERN_INFO "suspending: %s ", drive->name);
+	do_idedisk_standby(drive);
+	drive->blocked = 1;
+
+	BUG_ON (HWGROUP(drive)->handler);
+	return 0;
+}
+
+static int idedisk_resume(struct device *dev, u32 level)
+{
+	ide_drive_t *drive = dev->driver_data;
+
+	if (level != RESUME_RESTORE_STATE)
+		return 0;
+	BUG_ON(!drive->blocked);
+	drive->blocked = 0;
+	return 0;
+}
+
 static void idedisk_setup (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
@@ -1641,10 +1649,8 @@
 
 	printk(", CHS=%d/%d/%d", 
 	       drive->bios_cyl, drive->bios_head, drive->bios_sect);
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (drive->using_dma)
 		(void) HWIF(drive)->ide_dma_verbose(drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	printk("\n");
 
 	drive->mult_count = 0;
@@ -1671,6 +1677,7 @@
 {
 	struct gendisk *g = drive->disk;
 
+	do_idedisk_standby(drive);
 	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
 		if (do_idedisk_flushcache(drive))
 			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
@@ -1696,9 +1703,6 @@
 	.supports_dma		= 1,
 	.supports_dsc_overlap	= 0,
 	.cleanup		= idedisk_cleanup,
-	.standby		= do_idedisk_standby,
-	.suspend		= do_idedisk_suspend,
-	.resume			= do_idedisk_resume,
 	.flushcache		= do_idedisk_flushcache,
 	.do_request		= do_rw_disk,
 	.sense			= idedisk_dump_status,
@@ -1709,6 +1713,10 @@
 	.proc			= idedisk_proc,
 	.attach			= idedisk_attach,
 	.drives			= LIST_HEAD_INIT(idedisk_driver.drives),
+	.gen_driver		= {
+		.suspend	= idedisk_suspend,
+		.resume		= idedisk_resume,
+	}
 };
 
 static int idedisk_open(struct inode *inode, struct file *filp)
@@ -1835,8 +1843,7 @@
 
 static int idedisk_init (void)
 {
-	ide_register_driver(&idedisk_driver);
-	return 0;
+	return ide_register_driver(&idedisk_driver);
 }
 
 module_init(idedisk_init);
diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/ide-dma.c	Wed Nov 27 14:36:30 2002
@@ -90,6 +90,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
+#define CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
 #ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
 
 struct drive_list_entry {
@@ -145,11 +146,20 @@
 
 };
 
-int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
+/**
+ *	in_drive_list	-	look for drive in black/white list
+ *	@id: drive identifier
+ *	@drive_table: list to inspect
+ *
+ *	Look for a drive in the blacklist and the whitelist tables
+ *	Returns 1 if the drive is found in the table.
+ */
+
+static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
 {
 	for ( ; drive_table->id_model ; drive_table++)
 		if ((!strcmp(drive_table->id_model, id->model)) &&
-		    ((!strstr(drive_table->id_firmware, id->fw_rev)) ||
+		    ((strstr(drive_table->id_firmware, id->fw_rev)) ||
 		     (!strcmp(drive_table->id_firmware, "ALL"))))
 			return 1;
 	return 0;
@@ -189,9 +199,14 @@
 
 #endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */
 
-/*
- * dma_intr() is the handler for disk read/write DMA interrupts
+/**
+ *	ide_dma_intr	-	IDE DMA interrupt handler
+ *	@drive: the drive the interrupt is for
+ *
+ *	Handle an interrupt completing a read/write DMA transfer on an 
+ *	IDE device
  */
+ 
 ide_startstop_t ide_dma_intr (ide_drive_t *drive)
 {
 	u8 stat = 0, dma_stat = 0;
@@ -205,7 +220,7 @@
 			DRIVER(drive)->end_request(drive, 1, rq->nr_sectors);
 			return ide_stopped;
 		}
-		printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
+		printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
 		       drive->name, dma_stat);
 	}
 	return DRIVER(drive)->error(drive, "dma_intr", stat);
@@ -213,6 +228,17 @@
 
 EXPORT_SYMBOL_GPL(ide_dma_intr);
 
+/**
+ *	ide_build_sglist	-	map IDE scatter gather for DMA I/O
+ *	@drive: the drive to build the DMA table for
+ *	@rq: the request holding the sg list
+ *
+ *	Perform the PCI mapping magic neccessary to access the source or
+ *	target buffers of a request via PCI DMA. The lower layers of the
+ *	kernel provide the neccessary cache management so that we can
+ *	operate in a portable fashion
+ */
+ 
 static int ide_build_sglist (ide_drive_t *drive, struct request *rq)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -232,6 +258,17 @@
 	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
 }
 
+/**
+ *	ide_raw_build_sglist	-	map IDE scatter gather for DMA
+ *	@drive: the drive to build the DMA table for
+ *	@rq: the request holding the sg list
+ *
+ *	Perform the PCI mapping magic neccessary to access the source or
+ *	target buffers of a taskfile request via PCI DMA. The lower layers 
+ *	of the  kernel provide the neccessary cache management so that we can
+ *	operate in a portable fashion
+ */
+ 
 static int ide_raw_build_sglist (ide_drive_t *drive, struct request *rq)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -246,6 +283,9 @@
 	else
 		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
 #if 1
+	if (sector_count > 256)
+		BUG();
+		
 	if (sector_count > 128) {
 		memset(&sg[nents], 0, sizeof(*sg));
 		sg[nents].page = virt_to_page(virt_addr);
@@ -279,11 +319,18 @@
 	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
 }
 
-/*
- * ide_build_dmatable() prepares a dma request.
- * Returns 0 if all went okay, returns 1 otherwise.
- * May also be invoked from trm290.c
+/**
+ *	ide_build_dmatable	-	build IDE DMA table
+ *
+ *	ide_build_dmatable() prepares a dma request. We map the command
+ *	to get the pci bus addresses of the buffers and then build up
+ *	the PRD table that the IDE layer wants to be fed. The code
+ *	knows about the 64K wrap bug in the CS5530.
+ *
+ *	Returns 0 if all went okay, returns 1 otherwise.
+ *	May also be invoked from trm290.c
  */
+ 
 int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
@@ -317,7 +364,7 @@
 
 		while (cur_len) {
 			if (count++ >= PRD_ENTRIES) {
-				printk("%s: DMA table too small\n", drive->name);
+				printk(KERN_ERR "%s: DMA table too small\n", drive->name);
 				goto use_pio_instead;
 			} else {
 				u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
@@ -335,7 +382,7 @@
 	 * So here we break the 64KB entry into two 32KB entries instead.
 	 */
 					if (count++ >= PRD_ENTRIES) {
-						printk("%s: DMA table too small\n", drive->name);
+						printk(KERN_ERR "%s: DMA table too small\n", drive->name);
 						goto use_pio_instead;
 					}
 					*table++ = cpu_to_le32(0x8000);
@@ -357,7 +404,7 @@
 			*--table |= cpu_to_le32(0x80000000);
 		return count;
 	}
-	printk("%s: empty DMA table?\n", drive->name);
+	printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
 use_pio_instead:
 	pci_unmap_sg(hwif->pci_dev,
 		     hwif->sg_table,
@@ -369,7 +416,17 @@
 
 EXPORT_SYMBOL_GPL(ide_build_dmatable);
 
-/* Teardown mappings after DMA has completed.  */
+/**
+ *	ide_destroy_dmatable	-	clean up DMA mapping
+ *	@drive: The drive to unmap
+ *
+ *	Teardown mappings after DMA has completed. This must be called
+ *	after the completion of each use of ide_build_dmatable and before
+ *	the next use of ide_build_dmatable. Failure to do so will cause
+ *	an oops as only one mapping can be live for each target at a given
+ *	time.
+ */
+ 
 void ide_destroy_dmatable (ide_drive_t *drive)
 {
 	struct pci_dev *dev = HWIF(drive)->pci_dev;
@@ -382,6 +439,17 @@
 
 EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
 
+/**
+ *	config_drive_for_dma	-	attempt to activate IDE DMA
+ *	@drive: the drive to place in DMA mode
+ *
+ *	If the drive supports at least mode 2 DMA or UDMA of any kind
+ *	then attempt to place it into DMA mode. Drives that are known to
+ *	support DMA but predate the DMA properties or that are known
+ *	to have DMA handling bugs are also set up appropriately based
+ *	on the good/bad drive lists.
+ */
+ 
 static int config_drive_for_dma (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
@@ -415,15 +483,25 @@
 	return hwif->ide_dma_off_quietly(drive);
 }
 
-/*
- * 1 dmaing, 2 error, 4 intr
+/**
+ *	dma_timer_expiry	-	handle a DMA timeout
+ *	@drive: Drive that timed out
+ *
+ *	An IDE DMA transfer timed out. In the event of an error we ask
+ *	the driver to resolve the problem, if a DMA transfer is still
+ *	in progress we continue to wait (arguably we need to add a 
+ *	secondary 'I dont care what the drive thinks' timeout here)
+ *	Finally if we have an interrupt but for some reason got the
+ *	timeout first we complete the I/O. This can occur if an 
+ *	interrupt is lost or due to bugs.
  */
+ 
 static int dma_timer_expiry (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	u8 dma_stat		= hwif->INB(hwif->dma_status);
 
-	printk("%s: dma_timer_expiry: dma status == 0x%02x\n",
+	printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
 		drive->name, dma_stat);
 
 	if ((dma_stat & 0x18) == 0x18)	/* BUSY Stupid Early Timer !! */
@@ -431,6 +509,8 @@
 
 	HWGROUP(drive)->expiry = NULL;	/* one free ride for now */
 
+	/* 1 dmaing, 2 error, 4 intr */
+	
 	if (dma_stat & 2) {	/* ERROR */
 		(void) hwif->ide_dma_end(drive);
 		return DRIVER(drive)->error(drive,
@@ -445,6 +525,14 @@
 	return 0;
 }
 
+/**
+ *	__ide_dma_host_off	-	Generic DMA kill
+ *	@drive: drive to control
+ *
+ *	Perform the generic IDE controller DMA off operation. This
+ *	works for most IDE bus mastering controllers
+ */
+
 int __ide_dma_host_off (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
@@ -457,6 +545,13 @@
 
 EXPORT_SYMBOL(__ide_dma_host_off);
 
+/**
+ *	__ide_dma_host_off_quietly	-	Generic DMA kill
+ *	@drive: drive to control
+ *
+ *	Turn off the current DMA on this IDE controller. 
+ */
+
 int __ide_dma_off_quietly (ide_drive_t *drive)
 {
 	drive->using_dma = 0;
@@ -473,14 +568,30 @@
 
 EXPORT_SYMBOL(__ide_dma_off_quietly);
 
+/**
+ *	__ide_dma_host_off	-	Generic DMA kill
+ *	@drive: drive to control
+ *
+ *	Turn off the current DMA on this IDE controller. Inform the
+ *	user that DMA has been disabled. 
+ */
+
 int __ide_dma_off (ide_drive_t *drive)
 {
-	printk("%s: DMA disabled\n", drive->name);
+	printk(KERN_INFO "%s: DMA disabled\n", drive->name);
 	return HWIF(drive)->ide_dma_off_quietly(drive);
 }
 
 EXPORT_SYMBOL(__ide_dma_off);
 
+/**
+ *	__ide_dma_host_on	-	Enable DMA on a host
+ *	@drive: drive to enable for DMA
+ *
+ *	Enable DMA on an IDE controller following generic bus mastering
+ *	IDE controller behaviour
+ */
+ 
 int __ide_dma_host_on (ide_drive_t *drive)
 {
 	if (drive->using_dma) {
@@ -496,6 +607,13 @@
 
 EXPORT_SYMBOL(__ide_dma_host_on);
 
+/**
+ *	__ide_dma_on		-	Enable DMA on a device
+ *	@drive: drive to enable DMA on
+ *
+ *	Enable IDE DMA for a device on this IDE controller.
+ */
+ 
 int __ide_dma_on (ide_drive_t *drive)
 {
 	drive->using_dma = 1;
@@ -512,6 +630,13 @@
 
 EXPORT_SYMBOL(__ide_dma_on);
 
+/**
+ *	__ide_dma_check		-	check DMA setup
+ *	@drive: drive to check
+ *
+ *	Don't use - due for extermination
+ */
+ 
 int __ide_dma_check (ide_drive_t *drive)
 {
 	return config_drive_for_dma(drive);
@@ -519,6 +644,21 @@
 
 EXPORT_SYMBOL(__ide_dma_check);
 
+/**
+ *	ide_start_dma	-	begin a DMA phase
+ *	@hwif: interface
+ *	@drive: target device
+ *	@reading: set if reading, clear if writing
+ *
+ *	Build an IDE DMA PRD (IDE speak for scatter gather table)
+ *	and then set up the DMA transfer registers for a device
+ *	that follows generic IDE PCI DMA behaviour. Controllers can
+ *	override this function if they need to
+ *
+ *	Returns 0 on success. If a PIO fallback is required then 1
+ *	is returned. 
+ */
+ 
 int ide_start_dma(ide_hwif_t *hwif, ide_drive_t *drive, int reading)
 {
 	struct request *rq = HWGROUP(drive)->rq;
@@ -566,6 +706,10 @@
 	ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
 
 	command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
+	
+	if (drive->vdma)
+		command = (lba48) ? WIN_READ_EXT: WIN_READ;
+		
 	if (rq->flags & REQ_DRIVE_TASKFILE) {
 		ide_task_t *args = rq->special;
 		command = args->tfRegister[IDE_COMMAND_OFFSET];
@@ -600,6 +744,9 @@
 	ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
 
 	command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
+	if (drive->vdma)
+		command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE;
+		
 	if (rq->flags & REQ_DRIVE_TASKFILE) {
 		ide_task_t *args = rq->special;
 		command = args->tfRegister[IDE_COMMAND_OFFSET];
@@ -791,9 +938,17 @@
 
 EXPORT_SYMBOL(__ide_dma_verbose);
 
+/**
+ *	__ide_dma_retune	-	default retune handler
+ *	@drive: drive to retune
+ *
+ *	Default behaviour when we decide to return the IDE DMA setup.
+ *	The default behaviour is "we don't"
+ */
+ 
 int __ide_dma_retune (ide_drive_t *drive)
 {
-	printk("%s: chipset supported call only\n", __FUNCTION__);
+	printk(KERN_WARNING "%s: chipset supported call only\n", __FUNCTION__);
 	return 1;
 }
 
@@ -809,7 +964,7 @@
 
 int __ide_dma_timeout (ide_drive_t *drive)
 {
-	printk("%s: timeout waiting for DMA\n", drive->name);
+	printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
 	if (HWIF(drive)->ide_dma_test_irq(drive))
 		return 0;
 
@@ -882,7 +1037,7 @@
 	if ((hwif->dmatable_cpu) && (hwif->sg_table))
 		return 0;
 
-	printk("%s: -- Error, unable to allocate%s%s table(s).\n",
+	printk(KERN_ERR "%s: -- Error, unable to allocate%s%s table(s).\n",
 		(hwif->dmatable_cpu == NULL) ? " CPU" : "",
 		(hwif->sg_table == NULL) ?  " SG DMA" : " DMA",
 		hwif->cds->name);
@@ -893,7 +1048,7 @@
 
 int ide_mmio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports)
 {
-	printk("    %s: MMIO-DMA at 0x%08lx-0x%08lx",
+	printk(KERN_INFO "    %s: MMIO-DMA at 0x%08lx-0x%08lx",
 		hwif->name, base, base + ports - 1);
 	if (check_mem_region(base, ports)) {
 		printk(" -- Error, MMIO ports already in use.\n");
@@ -905,7 +1060,11 @@
 		request_region(base+16, hwif->cds->extra, hwif->cds->name);
 		hwif->dma_extra = hwif->cds->extra;
 	}
-	hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
+	
+	if(hwif->mate)
+		hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
+	else
+		hwif->dma_master = base;
 	if (hwif->dma_base2) {
 		if (!check_mem_region(hwif->dma_base2, ports))
 			request_mem_region(hwif->dma_base2, ports, hwif->name);
@@ -915,7 +1074,7 @@
 
 int ide_iomio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports)
 {
-	printk("    %s: BM-DMA at 0x%04lx-0x%04lx",
+	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
 		hwif->name, base, base + ports - 1);
 	if (!request_region(base, ports, hwif->name)) {
 		printk(" -- Error, ports in use.\n");
@@ -926,7 +1085,11 @@
 		request_region(base+16, hwif->cds->extra, hwif->cds->name);
 		hwif->dma_extra = hwif->cds->extra;
 	}
-	hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
+	
+	if(hwif->mate)
+		hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
+	else
+		hwif->dma_master = base;
 	if (hwif->dma_base2) {
 		if (!request_region(hwif->dma_base2, ports, hwif->name))
 		{
diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
--- a/drivers/ide/ide-floppy.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/ide-floppy.c	Wed Nov 27 14:36:30 2002
@@ -115,6 +115,12 @@
 /* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
 #define IDEFLOPPY_DEBUG( fmt, args... )
 
+#ifndef IDEFLOPPY_DEBUG_LOG
+#define debug_log(fmt, args... ) do {} while(0)
+#else
+#define debug_log printk
+#endif
+
 
 /*
  *	Some drives require a longer irq timeout.
@@ -543,9 +549,7 @@
 	struct request *rq = HWGROUP(drive)->rq;
 	int error;
 
-#if IDEFLOPPY_DEBUG_LOG
-	printk(KERN_INFO "Reached idefloppy_end_request\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+	debug_log(KERN_INFO "Reached idefloppy_end_request\n");
 
 	switch (uptodate) {
 		case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
@@ -627,7 +631,6 @@
 	}
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
 {
 	struct request *rq = pc->rq;
@@ -636,7 +639,6 @@
 	while ((bio = rq->bio) != NULL)
 		idefloppy_do_end_request(drive, 1, 0);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /*
  *	idefloppy_queue_pc_head generates a new packet command request in front
@@ -682,25 +684,22 @@
 	floppy->ascq = result->ascq;
 	floppy->progress_indication = result->sksv[0] & 0x80 ?
 		(u16)get_unaligned((u16 *)(result->sksv+1)):0x10000;
-#if IDEFLOPPY_DEBUG_LOG
 	if (floppy->failed_pc)
-		printk(KERN_INFO "ide-floppy: pc = %x, sense key = %x, "
+		debug_log(KERN_INFO "ide-floppy: pc = %x, sense key = %x, "
 			"asc = %x, ascq = %x\n", floppy->failed_pc->c[0],
 			result->sense_key, result->asc, result->ascq);
 	else
-		printk(KERN_INFO "ide-floppy: sense key = %x, asc = %x, "
+		debug_log(KERN_INFO "ide-floppy: sense key = %x, asc = %x, "
 			"ascq = %x\n", result->sense_key,
 			result->asc, result->ascq);
-#endif /* IDEFLOPPY_DEBUG_LOG */
 }
 
 static void idefloppy_request_sense_callback (ide_drive_t *drive)
 {
 	idefloppy_floppy_t *floppy = drive->driver_data;
 
-#if IDEFLOPPY_DEBUG_LOG
-	printk(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+	debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
+	
 	if (!floppy->pc->error) {
 		idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer);
 		idefloppy_do_end_request(drive, 1, 0);
@@ -717,9 +716,7 @@
 {
 	idefloppy_floppy_t *floppy = drive->driver_data;
 	
-#if IDEFLOPPY_DEBUG_LOG
-	printk (KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+	debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
 
 	idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);
 }
@@ -781,12 +778,9 @@
 	struct request *rq = pc->rq;
 	unsigned int temp;
 
-#if IDEFLOPPY_DEBUG_LOG
-	printk(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",
+	debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",
 		__FUNCTION__);
-#endif /* IDEFLOPPY_DEBUG_LOG */	
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
 		if (HWIF(drive)->ide_dma_end(drive)) {
 			set_bit(PC_DMA_ERROR, &pc->flags);
@@ -794,30 +788,23 @@
 			pc->actually_transferred = pc->request_transfer;
 			idefloppy_update_buffers(drive, pc);
 		}
-#if IDEFLOPPY_DEBUG_LOG
-		printk (KERN_INFO "ide-floppy: DMA finished\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+		debug_log(KERN_INFO "ide-floppy: DMA finished\n");
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	/* Clear the interrupt */
 	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
 
 	if (!status.b.drq) {			/* No more interrupts */
-#if IDEFLOPPY_DEBUG_LOG
-		printk(KERN_INFO "Packet command completed, %d bytes "
+		debug_log(KERN_INFO "Packet command completed, %d bytes "
 			"transferred\n", pc->actually_transferred);
-#endif /* IDEFLOPPY_DEBUG_LOG */
 		clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
 
 		local_irq_enable();
 
 		if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {
 			/* Error detected */
-#if IDEFLOPPY_DEBUG_LOG
-			printk(KERN_INFO "ide-floppy: %s: I/O error\n",
+			debug_log(KERN_INFO "ide-floppy: %s: I/O error\n",
 				drive->name);
-#endif /* IDEFLOPPY_DEBUG_LOG */
 			rq->errors++;
 			if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
 				printk(KERN_ERR "ide-floppy: I/O error in "
@@ -836,14 +823,14 @@
 		pc->callback(drive);
 		return ide_stopped;
 	}
-#ifdef CONFIG_BLK_DEV_IDEDMA
+
 	if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
 		printk(KERN_ERR "ide-floppy: The floppy wants to issue "
 			"more interrupts in DMA mode\n");
 		(void) HWIF(drive)->ide_dma_off(drive);
 		return ide_do_reset(drive);
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+
 	/* Get the number of bytes to transfer */
 	bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG);
 	bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG);
@@ -879,11 +866,9 @@
 						NULL);
 				return ide_started;
 			}
-#if IDEFLOPPY_DEBUG_LOG
-			printk(KERN_NOTICE "ide-floppy: The floppy wants to "
+			debug_log(KERN_NOTICE "ide-floppy: The floppy wants to "
 				"send us more data than expected - "
 				"allowing transfer\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
 		}
 	}
 	if (test_bit(PC_WRITING, &pc->flags)) {
@@ -1047,9 +1032,8 @@
 		pc->callback(drive);
 		return ide_stopped;
 	}
-#if IDEFLOPPY_DEBUG_LOG
-	printk(KERN_INFO "Retry number - %d\n",pc->retries);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+
+	debug_log(KERN_INFO "Retry number - %d\n",pc->retries);
 
 	pc->retries++;
 	/* We haven't transferred any data yet */
@@ -1057,13 +1041,11 @@
 	pc->current_position = pc->buffer;
 	bcount.all = min(pc->request_transfer, 63 * 1024);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
 		(void) HWIF(drive)->ide_dma_off(drive);
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	feature.all = 0;
-#ifdef CONFIG_BLK_DEV_IDEDMA
+
 	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) {
 		if (test_bit(PC_WRITING, &pc->flags)) {
 			feature.b.dma = !HWIF(drive)->ide_dma_write(drive);
@@ -1071,7 +1053,6 @@
 			feature.b.dma = !HWIF(drive)->ide_dma_read(drive);
 		}
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	if (IDE_CONTROL_REG)
 		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
@@ -1081,12 +1062,10 @@
 	HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
 	HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (feature.b.dma) {	/* Begin DMA, if necessary */
 		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
 		(void) (HWIF(drive)->ide_dma_begin(drive));
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	/* Can we transfer the packet when we get the interrupt or wait? */
 	if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) {
@@ -1116,9 +1095,7 @@
 
 static void idefloppy_rw_callback (ide_drive_t *drive)
 {
-#if IDEFLOPPY_DEBUG_LOG	
-	printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+	debug_log(KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
 
 	idefloppy_do_end_request(drive, 1, 0);
 	return;
@@ -1126,10 +1103,8 @@
 
 static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent)
 {
-#if IDEFLOPPY_DEBUG_LOG
-	printk(KERN_INFO "ide-floppy: creating prevent removal command, "
+	debug_log(KERN_INFO "ide-floppy: creating prevent removal command, "
 		"prevent = %d\n", prevent);
-#endif /* IDEFLOPPY_DEBUG_LOG */
 
 	idefloppy_init_pc(pc);
 	pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD;
@@ -1212,11 +1187,9 @@
 	int blocks = rq->nr_sectors / floppy->bs_factor;
 	int cmd = rq_data_dir(rq);
 
-#if IDEFLOPPY_DEBUG_LOG
-	printk("create_rw1%d_cmd: block == %d, blocks == %d\n",
+	debug_log("create_rw1%d_cmd: block == %d, blocks == %d\n",
 		2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags),
 		block, blocks);
-#endif /* IDEFLOPPY_DEBUG_LOG */
 
 	idefloppy_init_pc(pc);
 	if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) {
@@ -1262,14 +1235,12 @@
 	idefloppy_pc_t *pc;
 	unsigned long block = (unsigned long)block_s;
 
-#if IDEFLOPPY_DEBUG_LOG
-	printk(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n",
+	debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n",
 			rq->rq_status, rq->rq_disk->disk_name,
 			rq->flags, rq->errors);
-	printk(KERN_INFO "sector: %ld, nr_sectors: %ld, "
-			"current_nr_sectors: %ld\n", (long)rq->sector,
+	debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
+			"current_nr_sectors: %d\n", (long)rq->sector,
 			rq->nr_sectors, rq->current_nr_sectors);
-#endif /* IDEFLOPPY_DEBUG_LOG */
 
 	if (rq->errors >= ERROR_MAX) {
 		if (floppy->failed_pc != NULL)
@@ -1473,10 +1444,10 @@
 		}
 		}
 		if (!i) {
-			IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n",
+			debug_log( "Descriptor 0 Code: %d\n",
 				descriptor->dc);
 		}
-		IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d "
+		debug_log( "Descriptor %d: %dkB, %d blocks, %d "
 			"sector size\n", i, blocks * length / 1024, blocks,
 			length);
 	}
@@ -1909,9 +1880,7 @@
 
 	drive->usage++;
 	
-#if IDEFLOPPY_DEBUG_LOG
-	printk(KERN_INFO "Reached idefloppy_open\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+	debug_log(KERN_INFO "Reached idefloppy_open\n");
 
 	if (drive->usage == 1) {
 		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
@@ -1958,9 +1927,7 @@
 	ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
 	idefloppy_pc_t pc;
 	
-#if IDEFLOPPY_DEBUG_LOG
-	printk (KERN_INFO "Reached idefloppy_release\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+	debug_log(KERN_INFO "Reached idefloppy_release\n");
 
 	if (drive->usage == 1) {
 		idefloppy_floppy_t *floppy = drive->driver_data;
diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/ide-io.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,1320 @@
+/*
+ *	IDE I/O functions
+ *
+ *	Basic PIO and command management functionality.
+ *
+ * This code was split off from ide.c. See ide.c for history and original
+ * copyrights.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * 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.
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open non patent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ */
+ 
+ 
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/genhd.h>
+#include <linux/blkpg.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/completion.h>
+#include <linux/reboot.h>
+#include <linux/cdrom.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/kmod.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+
+#include "ide_modes.h"
+
+#if (DISK_RECOVERY_TIME > 0)
+
+Error So the User Has To Fix the Compilation And Stop Hacking Port 0x43
+Does anyone ever use this anyway ??
+
+/*
+ * For really screwy hardware (hey, at least it *can* be used with Linux)
+ * we can enforce a minimum delay time between successive operations.
+ */
+static unsigned long read_timer (ide_hwif_t *hwif)
+{
+	unsigned long t, flags;
+	int i;
+	
+	/* FIXME this is completely unsafe! */
+	local_irq_save(flags);
+	t = jiffies * 11932;
+	outb_p(0, 0x43);
+	i = inb_p(0x40);
+	i |= inb_p(0x40) << 8;
+	local_irq_restore(flags);
+	return (t - i);
+}
+#endif /* DISK_RECOVERY_TIME */
+
+static inline void set_recovery_timer (ide_hwif_t *hwif)
+{
+#if (DISK_RECOVERY_TIME > 0)
+	hwif->last_time = read_timer(hwif);
+#endif /* DISK_RECOVERY_TIME */
+}
+
+/**
+ *	ide_end_request		-	complete an IDE I/O
+ *	@drive: IDE device for the I/O
+ *	@uptodate: 
+ *	@nr_sectors: number of sectors completed
+ *
+ *	This is our end_request wrapper function. We complete the I/O
+ *	update random number input and dequeue the request, which if
+ *	it was tagged may be out of order.
+ */
+ 
+int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
+{
+	struct request *rq;
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&ide_lock, flags);
+	rq = HWGROUP(drive)->rq;
+
+	BUG_ON(!(rq->flags & REQ_STARTED));
+
+	if (!nr_sectors)
+		nr_sectors = rq->hard_cur_sectors;
+
+	/*
+	 * decide whether to reenable DMA -- 3 is a random magic for now,
+	 * if we DMA timeout more than 3 times, just stay in PIO
+	 */
+	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
+		drive->state = 0;
+		HWGROUP(drive)->hwif->ide_dma_on(drive);
+	}
+
+	if (!end_that_request_first(rq, uptodate, nr_sectors)) {
+		add_disk_randomness(rq->rq_disk);
+		if (!blk_rq_tagged(rq))
+			blkdev_dequeue_request(rq);
+		else
+			blk_queue_end_tag(&drive->queue, rq);
+		HWGROUP(drive)->rq = NULL;
+		end_that_request_last(rq);
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&ide_lock, flags);
+	return ret;
+}
+
+EXPORT_SYMBOL(ide_end_request);
+
+/**
+ *	ide_end_drive_cmd	-	end an explicit drive command
+ *	@drive: command 
+ *	@stat: status bits
+ *	@err: error bits
+ *
+ *	Clean up after success/failure of an explicit drive command.
+ *	These get thrown onto the queue so they are synchronized with
+ *	real I/O operations on the drive.
+ *
+ *	In LBA48 mode we have to read the register set twice to get
+ *	all the extra information out.
+ */
+ 
+void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long flags;
+	struct request *rq;
+
+	spin_lock_irqsave(&ide_lock, flags);
+	rq = HWGROUP(drive)->rq;
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	if (rq->flags & REQ_DRIVE_CMD) {
+		u8 *args = (u8 *) rq->buffer;
+		if (rq->errors == 0)
+			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+
+		if (args) {
+			args[0] = stat;
+			args[1] = err;
+			args[2] = hwif->INB(IDE_NSECTOR_REG);
+		}
+	} else if (rq->flags & REQ_DRIVE_TASK) {
+		u8 *args = (u8 *) rq->buffer;
+		if (rq->errors == 0)
+			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+
+		if (args) {
+			args[0] = stat;
+			args[1] = err;
+			args[2] = hwif->INB(IDE_NSECTOR_REG);
+			args[3] = hwif->INB(IDE_SECTOR_REG);
+			args[4] = hwif->INB(IDE_LCYL_REG);
+			args[5] = hwif->INB(IDE_HCYL_REG);
+			args[6] = hwif->INB(IDE_SELECT_REG);
+		}
+	} else if (rq->flags & REQ_DRIVE_TASKFILE) {
+		ide_task_t *args = (ide_task_t *) rq->special;
+		if (rq->errors == 0)
+			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+			
+		if (args) {
+			if (args->tf_in_flags.b.data) {
+				u16 data				= hwif->INW(IDE_DATA_REG);
+				args->tfRegister[IDE_DATA_OFFSET]	= (data) & 0xFF;
+				args->hobRegister[IDE_DATA_OFFSET_HOB]	= (data >> 8) & 0xFF;
+			}
+			args->tfRegister[IDE_ERROR_OFFSET]   = err;
+			args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
+			args->tfRegister[IDE_SECTOR_OFFSET]  = hwif->INB(IDE_SECTOR_REG);
+			args->tfRegister[IDE_LCYL_OFFSET]    = hwif->INB(IDE_LCYL_REG);
+			args->tfRegister[IDE_HCYL_OFFSET]    = hwif->INB(IDE_HCYL_REG);
+			args->tfRegister[IDE_SELECT_OFFSET]  = hwif->INB(IDE_SELECT_REG);
+			args->tfRegister[IDE_STATUS_OFFSET]  = stat;
+
+			if (drive->addressing == 1) {
+				hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
+				args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG);
+				args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG);
+				args->hobRegister[IDE_SECTOR_OFFSET_HOB]  = hwif->INB(IDE_SECTOR_REG);
+				args->hobRegister[IDE_LCYL_OFFSET_HOB]    = hwif->INB(IDE_LCYL_REG);
+				args->hobRegister[IDE_HCYL_OFFSET_HOB]    = hwif->INB(IDE_HCYL_REG);
+			}
+		}
+	}
+
+	spin_lock_irqsave(&ide_lock, flags);
+	blkdev_dequeue_request(rq);
+	HWGROUP(drive)->rq = NULL;
+	end_that_request_last(rq);
+	spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+EXPORT_SYMBOL(ide_end_drive_cmd);
+
+/**
+ *	try_to_flush_leftover_data	-	flush junk
+ *	@drive: drive to flush
+ *
+ *	try_to_flush_leftover_data() is invoked in response to a drive
+ *	unexpectedly having its DRQ_STAT bit set.  As an alternative to
+ *	resetting the drive, this routine tries to clear the condition
+ *	by read a sector's worth of data from the drive.  Of course,
+ *	this may not help if the drive is *waiting* for data from *us*.
+ */
+void try_to_flush_leftover_data (ide_drive_t *drive)
+{
+	int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS;
+
+	if (drive->media != ide_disk)
+		return;
+	while (i > 0) {
+		u32 buffer[16];
+		u32 wcount = (i > 16) ? 16 : i;
+
+		i -= wcount;
+		HWIF(drive)->ata_input_data(drive, buffer, wcount);
+	}
+}
+
+EXPORT_SYMBOL(try_to_flush_leftover_data);
+
+/*
+ * FIXME Add an ATAPI error
+ */
+
+/**
+ *	ide_error	-	handle an error on the IDE
+ *	@drive: drive the error occurred on
+ *	@msg: message to report
+ *	@stat: status bits
+ *
+ *	ide_error() takes action based on the error returned by the drive.
+ *	For normal I/O that may well include retries. We deal with
+ *	both new-style (taskfile) and old style command handling here.
+ *	In the case of taskfile command handling there is work left to
+ *	do
+ */
+ 
+ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
+{
+	ide_hwif_t *hwif;
+	struct request *rq;
+	u8 err;
+
+	err = ide_dump_status(drive, msg, stat);
+	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+		return ide_stopped;
+
+	hwif = HWIF(drive);
+	/* retry only "normal" I/O: */
+	if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+		rq->errors = 1;
+		ide_end_drive_cmd(drive, stat, err);
+		return ide_stopped;
+	}
+	if (rq->flags & REQ_DRIVE_TASKFILE) {
+		rq->errors = 1;
+		ide_end_drive_cmd(drive, stat, err);
+//		ide_end_taskfile(drive, stat, err);
+		return ide_stopped;
+	}
+
+	if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
+		 /* other bits are useless when BUSY */
+		rq->errors |= ERROR_RESET;
+	} else {
+		if (drive->media != ide_disk)
+			goto media_out;
+
+		if (stat & ERR_STAT) {
+			/* err has different meaning on cdrom and tape */
+			if (err == ABRT_ERR) {
+				if (drive->select.b.lba &&
+				    (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY))
+					/* some newer drives don't
+					 * support WIN_SPECIFY
+					 */
+					return ide_stopped;
+			} else if ((err & BAD_CRC) == BAD_CRC) {
+				drive->crc_count++;
+				/* UDMA crc error -- just retry the operation */
+			} else if (err & (BBD_ERR | ECC_ERR)) {
+				/* retries won't help these */
+				rq->errors = ERROR_MAX;
+			} else if (err & TRK0_ERR) {
+				/* help it find track zero */
+				rq->errors |= ERROR_RECAL;
+			}
+		}
+media_out:
+		if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE)
+			try_to_flush_leftover_data(drive);
+	}
+	if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) {
+		/* force an abort */
+		hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
+	}
+	if (rq->errors >= ERROR_MAX) {
+		if (drive->driver != NULL)
+			DRIVER(drive)->end_request(drive, 0, 0);
+		else
+	 		ide_end_request(drive, 0, 0);
+	} else {
+		if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
+			++rq->errors;
+			return ide_do_reset(drive);
+		}
+		if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
+			drive->special.b.recalibrate = 1;
+		++rq->errors;
+	}
+	return ide_stopped;
+}
+
+EXPORT_SYMBOL(ide_error);
+
+/**
+ *	ide_cmd		-	issue a simple drive command
+ *	@drive: drive the command is for
+ *	@cmd: command byte
+ *	@nsect: sector byte
+ *	@handler: handler for the command completion
+ *
+ *	Issue a simple drive command with interrupts.
+ *	The drive must be selected beforehand.
+ */
+ 
+void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	if (HWGROUP(drive)->handler != NULL)
+		BUG();
+	ide_set_handler(drive, handler, WAIT_CMD, NULL);
+	if (IDE_CONTROL_REG)
+		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
+	SELECT_MASK(drive,0);
+	hwif->OUTB(nsect,IDE_NSECTOR_REG);
+	hwif->OUTB(cmd,IDE_COMMAND_REG);
+}
+
+EXPORT_SYMBOL(ide_cmd);
+
+/**
+ *	drive_cmd_intr		- 	drive command completion interrupt
+ *	@drive: drive the completion interrupt occurred on
+ *
+ *	drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
+ *	We do any neccessary daya reading and then wait for the drive to
+ *	go non busy. At that point we may read the error data and complete
+ *	the request
+ */
+ 
+ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
+{
+	struct request *rq = HWGROUP(drive)->rq;
+	ide_hwif_t *hwif = HWIF(drive);
+	u8 *args = (u8 *) rq->buffer;
+	u8 stat = hwif->INB(IDE_STATUS_REG);
+	int retries = 10;
+
+	local_irq_enable();
+	if ((stat & DRQ_STAT) && args && args[3]) {
+		u8 io_32bit = drive->io_32bit;
+		drive->io_32bit = 0;
+		hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
+		drive->io_32bit = io_32bit;
+		while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
+			udelay(100);
+	}
+
+	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+		return DRIVER(drive)->error(drive, "drive_cmd", stat);
+		/* calls ide_end_drive_cmd */
+	ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
+	return ide_stopped;
+}
+
+EXPORT_SYMBOL(drive_cmd_intr);
+
+/**
+ *	do_special		-	issue some special commands
+ *	@drive: drive the command is for
+ *
+ *	do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
+ *	commands to a drive.  It used to do much more, but has been scaled
+ *	back.
+ */
+
+ide_startstop_t do_special (ide_drive_t *drive)
+{
+	special_t *s = &drive->special;
+
+#ifdef DEBUG
+	printk("%s: do_special: 0x%02x\n", drive->name, s->all);
+#endif
+	if (s->b.set_tune) {
+		s->b.set_tune = 0;
+		if (HWIF(drive)->tuneproc != NULL)
+			HWIF(drive)->tuneproc(drive, drive->tune_req);
+	} else if (drive->driver != NULL) {
+		return DRIVER(drive)->special(drive);
+	} else if (s->all) {
+		printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, s->all);
+		s->all = 0;
+	}
+	return ide_stopped;
+}
+
+EXPORT_SYMBOL(do_special);
+
+/**
+ *	execute_drive_command	-	issue special drive command
+ *	@drive: the drive to issue th command on
+ *	@rq: the request structure holding the command
+ *
+ *	execute_drive_cmd() issues a special drive command,  usually 
+ *	initiated by ioctl() from the external hdparm program. The
+ *	command can be a drive command, drive task or taskfile 
+ *	operation. Weirdly you can call it with NULL to wait for
+ *	all commands to finish. Don't do this as that is due to change
+ */
+
+ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	if (rq->flags & REQ_DRIVE_TASKFILE) {
+ 		ide_task_t *args = rq->special;
+ 
+		if (!args)
+			goto done;
+ 
+		if (args->tf_out_flags.all != 0) 
+			return flagged_taskfile(drive, args);
+		return do_rw_taskfile(drive, args);
+	} else if (rq->flags & REQ_DRIVE_TASK) {
+		u8 *args = rq->buffer;
+		u8 sel;
+ 
+		if (!args)
+			goto done;
+#ifdef DEBUG
+ 		printk("%s: DRIVE_TASK_CMD ", drive->name);
+ 		printk("cmd=0x%02x ", args[0]);
+ 		printk("fr=0x%02x ", args[1]);
+ 		printk("ns=0x%02x ", args[2]);
+ 		printk("sc=0x%02x ", args[3]);
+ 		printk("lcyl=0x%02x ", args[4]);
+ 		printk("hcyl=0x%02x ", args[5]);
+ 		printk("sel=0x%02x\n", args[6]);
+#endif
+ 		hwif->OUTB(args[1], IDE_FEATURE_REG);
+ 		hwif->OUTB(args[3], IDE_SECTOR_REG);
+ 		hwif->OUTB(args[4], IDE_LCYL_REG);
+ 		hwif->OUTB(args[5], IDE_HCYL_REG);
+ 		sel = (args[6] & ~0x10);
+ 		if (drive->select.b.unit)
+ 			sel |= 0x10;
+ 		hwif->OUTB(sel, IDE_SELECT_REG);
+ 		ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
+ 		return ide_started;
+ 	} else if (rq->flags & REQ_DRIVE_CMD) {
+ 		u8 *args = rq->buffer;
+
+		if (!args)
+			goto done;
+#ifdef DEBUG
+ 		printk("%s: DRIVE_CMD ", drive->name);
+ 		printk("cmd=0x%02x ", args[0]);
+ 		printk("sc=0x%02x ", args[1]);
+ 		printk("fr=0x%02x ", args[2]);
+ 		printk("xx=0x%02x\n", args[3]);
+#endif
+ 		if (args[0] == WIN_SMART) {
+ 			hwif->OUTB(0x4f, IDE_LCYL_REG);
+ 			hwif->OUTB(0xc2, IDE_HCYL_REG);
+ 			hwif->OUTB(args[2],IDE_FEATURE_REG);
+ 			hwif->OUTB(args[1],IDE_SECTOR_REG);
+ 			ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
+ 			return ide_started;
+ 		}
+ 		hwif->OUTB(args[2],IDE_FEATURE_REG);
+ 		ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
+ 		return ide_started;
+ 	}
+
+done:
+ 	/*
+ 	 * NULL is actually a valid way of waiting for
+ 	 * all current requests to be flushed from the queue.
+ 	 */
+#ifdef DEBUG
+ 	printk("%s: DRIVE_CMD (null)\n", drive->name);
+#endif
+ 	ide_end_drive_cmd(drive,
+			hwif->INB(IDE_STATUS_REG),
+			hwif->INB(IDE_ERROR_REG));
+ 	return ide_stopped;
+}
+
+EXPORT_SYMBOL(execute_drive_cmd);
+
+/**
+ *	start_request	-	start of I/O and command issuing for IDE
+ *
+ *	start_request() initiates handling of a new I/O request. It
+ *	accepts commands and I/O (read/write) requests. It also does
+ *	the final remapping for weird stuff like EZDrive. Once 
+ *	device mapper can work sector level the EZDrive stuff can go away
+ *
+ *	FIXME: this function needs a rename
+ */
+ 
+ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
+{
+	ide_startstop_t startstop;
+	unsigned long block;
+
+	BUG_ON(!(rq->flags & REQ_STARTED));
+
+#ifdef DEBUG
+	printk("%s: start_request: current=0x%08lx\n",
+		HWIF(drive)->name, (unsigned long) rq);
+#endif
+
+	/* bail early if we've exceeded max_failures */
+	if (drive->max_failures && (drive->failures > drive->max_failures)) {
+		goto kill_rq;
+	}
+
+	/*
+	 * bail early if we've sent a device to sleep, however how to wake
+	 * this needs to be a masked flag.  FIXME for proper operations.
+	 */
+	if (drive->suspend_reset)
+		goto kill_rq;
+
+	block    = rq->sector;
+	if (blk_fs_request(rq) &&
+	    (drive->media == ide_disk || drive->media == ide_floppy)) {
+		block += drive->sect0;
+	}
+	/* Yecch - this will shift the entire interval,
+	   possibly killing some innocent following sector */
+	if (block == 0 && drive->remap_0_to_1 == 1)
+		block = 1;  /* redirect MBR access to EZ-Drive partn table */
+
+#if (DISK_RECOVERY_TIME > 0)
+	while ((read_timer() - HWIF(drive)->last_time) < DISK_RECOVERY_TIME);
+#endif
+
+	SELECT_DRIVE(drive);
+	if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
+		printk(KERN_ERR "%s: drive not ready for command\n", drive->name);
+		return startstop;
+	}
+	if (!drive->special.all) {
+		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK))
+			return execute_drive_cmd(drive, rq);
+		else if (rq->flags & REQ_DRIVE_TASKFILE)
+			return execute_drive_cmd(drive, rq);
+
+		if (drive->driver != NULL) {
+			return (DRIVER(drive)->do_request(drive, rq, block));
+		}
+		printk(KERN_ERR "%s: media type %d not supported\n", drive->name, drive->media);
+		goto kill_rq;
+	}
+	return do_special(drive);
+kill_rq:
+	if (drive->driver != NULL)
+		DRIVER(drive)->end_request(drive, 0, 0);
+	else
+		ide_end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
+EXPORT_SYMBOL(start_request);
+
+/**
+ *	restart_request		-	reissue an IDE request
+ *	@drive: drive for request
+ *	@rq: request to reissue
+ *
+ *	Reissue a request. See start_request for details and for
+ *	FIXME
+ */
+ 
+int restart_request (ide_drive_t *drive, struct request *rq)
+{
+	(void) start_request(drive, rq);
+	return 0;
+}
+
+EXPORT_SYMBOL(restart_request);
+
+/**
+ *	ide_stall_queue		-	pause an IDE device
+ *	@drive: drive to stall
+ *	@timeout: time to stall for (jiffies)
+ *
+ *	ide_stall_queue() can be used by a drive to give excess bandwidth back
+ *	to the hwgroup by sleeping for timeout jiffies.
+ */
+ 
+void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
+{
+	if (timeout > WAIT_WORSTCASE)
+		timeout = WAIT_WORSTCASE;
+	drive->sleep = timeout + jiffies;
+}
+
+EXPORT_SYMBOL(ide_stall_queue);
+
+#define WAKEUP(drive)	((drive)->service_start + 2 * (drive)->service_time)
+
+/**
+ *	choose_drive		-	select a drive to service
+ *	@hwgroup: hardware group to select on
+ *
+ *	choose_drive() selects the next drive which will be serviced.
+ *	This is neccessary because the IDE layer can't issue commands
+ *	to both drives on the same cable, unlike SCSI.
+ */
+ 
+static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
+{
+	ide_drive_t *drive, *best;
+
+repeat:	
+	best = NULL;
+	drive = hwgroup->drive;
+	do {
+		if (!blk_queue_empty(&drive->queue) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) {
+			if (!best
+			 || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
+			 || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
+			{
+				if (!blk_queue_plugged(&drive->queue))
+					best = drive;
+			}
+		}
+	} while ((drive = drive->next) != hwgroup->drive);
+	if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
+		long t = (signed long)(WAKEUP(best) - jiffies);
+		if (t >= WAIT_MIN_SLEEP) {
+		/*
+		 * We *may* have some time to spare, but first let's see if
+		 * someone can potentially benefit from our nice mood today..
+		 */
+			drive = best->next;
+			do {
+				if (!drive->sleep
+				/* FIXME: use time_before */
+				 && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
+				 && 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
+				{
+					ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP));
+					goto repeat;
+				}
+			} while ((drive = drive->next) != best);
+		}
+	}
+	return best;
+}
+
+/*
+ * Issue a new request to a drive from hwgroup
+ * Caller must have already done spin_lock_irqsave(&ide_lock, ..);
+ *
+ * A hwgroup is a serialized group of IDE interfaces.  Usually there is
+ * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
+ * may have both interfaces in a single hwgroup to "serialize" access.
+ * Or possibly multiple ISA interfaces can share a common IRQ by being grouped
+ * together into one hwgroup for serialized access.
+ *
+ * Note also that several hwgroups can end up sharing a single IRQ,
+ * possibly along with many other devices.  This is especially common in
+ * PCI-based systems with off-board IDE controller cards.
+ *
+ * The IDE driver uses the single global ide_lock spinlock to protect
+ * access to the request queues, and to protect the hwgroup->busy flag.
+ *
+ * The first thread into the driver for a particular hwgroup sets the
+ * hwgroup->busy flag to indicate that this hwgroup is now active,
+ * and then initiates processing of the top request from the request queue.
+ *
+ * Other threads attempting entry notice the busy setting, and will simply
+ * queue their new requests and exit immediately.  Note that hwgroup->busy
+ * remains set even when the driver is merely awaiting the next interrupt.
+ * Thus, the meaning is "this hwgroup is busy processing a request".
+ *
+ * When processing of a request completes, the completing thread or IRQ-handler
+ * will start the next request from the queue.  If no more work remains,
+ * the driver will clear the hwgroup->busy flag and exit.
+ *
+ * The ide_lock (spinlock) is used to protect all access to the
+ * hwgroup->busy flag, but is otherwise not needed for most processing in
+ * the driver.  This makes the driver much more friendlier to shared IRQs
+ * than previous designs, while remaining 100% (?) SMP safe and capable.
+ */
+/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back
+ *         into life on wakeup from machine sleep.
+ */ 
+void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
+{
+	ide_drive_t	*drive;
+	ide_hwif_t	*hwif;
+	struct request	*rq;
+	ide_startstop_t	startstop;
+
+	/* for atari only: POSSIBLY BROKEN HERE(?) */
+	ide_get_lock(&ide_intr_lock, ide_intr, hwgroup);
+
+	/* necessary paranoia: ensure IRQs are masked on local CPU */
+	local_irq_disable();
+
+	while (!hwgroup->busy) {
+		hwgroup->busy = 1;
+		drive = choose_drive(hwgroup);
+		if (drive == NULL) {
+			unsigned long sleep = 0;
+			hwgroup->rq = NULL;
+			drive = hwgroup->drive;
+			do {
+				if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
+					sleep = drive->sleep;
+			} while ((drive = drive->next) != hwgroup->drive);
+			if (sleep) {
+		/*
+		 * Take a short snooze, and then wake up this hwgroup again.
+		 * This gives other hwgroups on the same a chance to
+		 * play fairly with us, just in case there are big differences
+		 * in relative throughputs.. don't want to hog the cpu too much.
+		 */
+				if (time_before(sleep, jiffies + WAIT_MIN_SLEEP))
+					sleep = jiffies + WAIT_MIN_SLEEP;
+#if 1
+				if (timer_pending(&hwgroup->timer))
+					printk(KERN_CRIT "ide_set_handler: timer already active\n");
+#endif
+				/* so that ide_timer_expiry knows what to do */
+				hwgroup->sleeping = 1;
+				mod_timer(&hwgroup->timer, sleep);
+				/* we purposely leave hwgroup->busy==1
+				 * while sleeping */
+			} else {
+				/* Ugly, but how can we sleep for the lock
+				 * otherwise? perhaps from tq_disk?
+				 */
+
+				/* for atari only */
+				ide_release_lock(&ide_intr_lock);
+				hwgroup->busy = 0;
+			}
+
+			/* no more work for this hwgroup (for now) */
+			return;
+		}
+		hwif = HWIF(drive);
+		if (hwgroup->hwif->sharing_irq &&
+		    hwif != hwgroup->hwif &&
+		    hwif->io_ports[IDE_CONTROL_OFFSET]) {
+			/* set nIEN for previous hwif */
+			SELECT_INTERRUPT(drive);
+		}
+		hwgroup->hwif = hwif;
+		hwgroup->drive = drive;
+		drive->sleep = 0;
+		drive->service_start = jiffies;
+
+queue_next:
+		if (!ata_can_queue(drive)) {
+			if (!ata_pending_commands(drive))
+				hwgroup->busy = 0;
+
+			break;
+		}
+
+		if (blk_queue_plugged(&drive->queue)) {
+			if (drive->using_tcq)
+				break;
+
+			printk(KERN_ERR "ide: huh? queue was plugged!\n");
+			break;
+		}
+
+		/*
+		 * we know that the queue isn't empty, but this can happen
+		 * if the q->prep_rq_fn() decides to kill a request
+		 */
+		rq = elv_next_request(&drive->queue);
+		if (!rq) {
+			hwgroup->busy = !!ata_pending_commands(drive);
+			break;
+		}
+
+		if (!rq->bio && ata_pending_commands(drive))
+			break;
+
+		hwgroup->rq = rq;
+
+		/*
+		 * Some systems have trouble with IDE IRQs arriving while
+		 * the driver is still setting things up.  So, here we disable
+		 * the IRQ used by this interface while the request is being started.
+		 * This may look bad at first, but pretty much the same thing
+		 * happens anyway when any interrupt comes in, IDE or otherwise
+		 *  -- the kernel masks the IRQ while it is being handled.
+		 */
+		if (masked_irq && hwif->irq != masked_irq)
+			disable_irq_nosync(hwif->irq);
+		spin_unlock(&ide_lock);
+		local_irq_enable();
+			/* allow other IRQs while we start this request */
+		startstop = start_request(drive, rq);
+		spin_lock_irq(&ide_lock);
+		if (masked_irq && hwif->irq != masked_irq)
+			enable_irq(hwif->irq);
+		if (startstop == ide_released)
+			goto queue_next;
+		if (startstop == ide_stopped)
+			hwgroup->busy = 0;
+	}
+}
+
+EXPORT_SYMBOL(ide_do_request);
+
+/*
+ * Passes the stuff to ide_do_request
+ */
+void do_ide_request(request_queue_t *q)
+{
+	ide_do_request(q->queuedata, 0);
+}
+
+/*
+ * un-busy the hwgroup etc, and clear any pending DMA status. we want to
+ * retry the current request in pio mode instead of risking tossing it
+ * all away
+ */
+void ide_dma_timeout_retry(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct request *rq;
+
+	/*
+	 * end current dma transaction
+	 */
+	(void) hwif->ide_dma_end(drive);
+
+	/*
+	 * complain a little, later we might remove some of this verbosity
+	 */
+	printk(KERN_WARNING "%s: timeout waiting for DMA\n", drive->name);
+	(void) hwif->ide_dma_timeout(drive);
+
+	/*
+	 * disable dma for now, but remember that we did so because of
+	 * a timeout -- we'll reenable after we finish this next request
+	 * (or rather the first chunk of it) in pio.
+	 */
+	drive->retry_pio++;
+	drive->state = DMA_PIO_RETRY;
+	(void) hwif->ide_dma_off_quietly(drive);
+
+	/*
+	 * un-busy drive etc (hwgroup->busy is cleared on return) and
+	 * make sure request is sane
+	 */
+	rq = HWGROUP(drive)->rq;
+	HWGROUP(drive)->rq = NULL;
+
+	rq->errors = 0;
+	rq->sector = rq->bio->bi_sector;
+	rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
+	rq->hard_cur_sectors = rq->current_nr_sectors;
+	if (rq->bio)
+		rq->buffer = NULL;
+}
+
+EXPORT_SYMBOL(ide_dma_timeout_retry);
+
+/**
+ *	ide_timer_expiry	-	handle lack of an IDE interrupt
+ *	@data: timer callback magic (hwgroup)
+ *
+ *	An IDE command has timed out before the expected drive return
+ *	occurred. At this point we attempt to clean up the current
+ *	mess. If the current handler includes an expiry handler then
+ *	we invoke the expiry handler, and providing it is happy the
+ *	work is done. If that fails we apply generic recovery rules
+ *	invoking the handler and checking the drive DMA status. We
+ *	have an excessively incestuous relationship with the DMA
+ *	logic that wants cleaning up.
+ */
+ 
+void ide_timer_expiry (unsigned long data)
+{
+	ide_hwgroup_t	*hwgroup = (ide_hwgroup_t *) data;
+	ide_handler_t	*handler;
+	ide_expiry_t	*expiry;
+ 	unsigned long	flags;
+	unsigned long	wait;
+
+	spin_lock_irqsave(&ide_lock, flags);
+	del_timer(&hwgroup->timer);
+
+	if ((handler = hwgroup->handler) == NULL) {
+		/*
+		 * Either a marginal timeout occurred
+		 * (got the interrupt just as timer expired),
+		 * or we were "sleeping" to give other devices a chance.
+		 * Either way, we don't really want to complain about anything.
+		 */
+		if (hwgroup->sleeping) {
+			hwgroup->sleeping = 0;
+			hwgroup->busy = 0;
+		}
+	} else {
+		ide_drive_t *drive = hwgroup->drive;
+		if (!drive) {
+			printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n");
+			hwgroup->handler = NULL;
+		} else {
+			ide_hwif_t *hwif;
+			ide_startstop_t startstop = ide_stopped;
+			if (!hwgroup->busy) {
+				hwgroup->busy = 1;	/* paranoia */
+				printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name);
+			}
+			if ((expiry = hwgroup->expiry) != NULL) {
+				/* continue */
+				if ((wait = expiry(drive)) != 0) {
+					/* reset timer */
+					hwgroup->timer.expires  = jiffies + wait;
+					add_timer(&hwgroup->timer);
+					spin_unlock_irqrestore(&ide_lock, flags);
+					return;
+				}
+			}
+			hwgroup->handler = NULL;
+			/*
+			 * We need to simulate a real interrupt when invoking
+			 * the handler() function, which means we need to
+			 * globally mask the specific IRQ:
+			 */
+			spin_unlock(&ide_lock);
+			hwif  = HWIF(drive);
+#if DISABLE_IRQ_NOSYNC
+			disable_irq_nosync(hwif->irq);
+#else
+			/* disable_irq_nosync ?? */
+			disable_irq(hwif->irq);
+#endif /* DISABLE_IRQ_NOSYNC */
+			/* local CPU only,
+			 * as if we were handling an interrupt */
+			local_irq_disable();
+			if (hwgroup->poll_timeout != 0) {
+				startstop = handler(drive);
+			} else if (drive_is_ready(drive)) {
+				if (drive->waiting_for_dma)
+					(void) hwgroup->hwif->ide_dma_lostirq(drive);
+				(void)ide_ack_intr(hwif);
+				printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
+				startstop = handler(drive);
+			} else {
+				if (drive->waiting_for_dma) {
+					startstop = ide_stopped;
+					ide_dma_timeout_retry(drive);
+				} else
+					startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
+			}
+			set_recovery_timer(hwif);
+			drive->service_time = jiffies - drive->service_start;
+			enable_irq(hwif->irq);
+			spin_lock_irq(&ide_lock);
+			if (startstop == ide_stopped)
+				hwgroup->busy = 0;
+		}
+	}
+	ide_do_request(hwgroup, 0);
+	spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+EXPORT_SYMBOL(ide_timer_expiry);
+
+/**
+ *	unexpected_intr		-	handle an unexpected IDE interrupt
+ *	@irq: interrupt line
+ *	@hwgroup: hwgroup being processed
+ *
+ *	There's nothing really useful we can do with an unexpected interrupt,
+ *	other than reading the status register (to clear it), and logging it.
+ *	There should be no way that an irq can happen before we're ready for it,
+ *	so we needn't worry much about losing an "important" interrupt here.
+ *
+ *	On laptops (and "green" PCs), an unexpected interrupt occurs whenever
+ *	the drive enters "idle", "standby", or "sleep" mode, so if the status
+ *	looks "good", we just ignore the interrupt completely.
+ *
+ *	This routine assumes __cli() is in effect when called.
+ *
+ *	If an unexpected interrupt happens on irq15 while we are handling irq14
+ *	and if the two interfaces are "serialized" (CMD640), then it looks like
+ *	we could screw up by interfering with a new request being set up for 
+ *	irq15.
+ *
+ *	In reality, this is a non-issue.  The new command is not sent unless 
+ *	the drive is ready to accept one, in which case we know the drive is
+ *	not trying to interrupt us.  And ide_set_handler() is always invoked
+ *	before completing the issuance of any new drive command, so we will not
+ *	be accidentally invoked as a result of any valid command completion
+ *	interrupt.
+ *
+ *	Note that we must walk the entire hwgroup here. We know which hwif
+ *	is doing the current command, but we don't know which hwif burped
+ *	mysteriously.
+ */
+ 
+static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
+{
+	u8 stat;
+	ide_hwif_t *hwif = hwgroup->hwif;
+
+	/*
+	 * handle the unexpected interrupt
+	 */
+	do {
+		if (hwif->irq == irq) {
+			stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+			if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
+				/* Try to not flood the console with msgs */
+				static unsigned long last_msgtime, count;
+				++count;
+				if (time_after(jiffies, last_msgtime + HZ)) {
+					last_msgtime = jiffies;
+					printk(KERN_ERR "%s%s: unexpected interrupt, "
+						"status=0x%02x, count=%ld\n",
+						hwif->name,
+						(hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count);
+				}
+			}
+		}
+	} while ((hwif = hwif->next) != hwgroup->hwif);
+}
+
+/**
+ *	ide_intr	-	default IDE interrupt handler
+ *	@irq: interrupt number
+ *	@dev_id: hwif group
+ *	@regs: unused weirdness from the kernel irq layer
+ *
+ *	This is the default IRQ handler for the IDE layer. You should
+ *	not need to override it. If you do be aware it is subtle in
+ *	places
+ *
+ *	hwgroup->hwif is the interface in the group currently performing
+ *	a command. hwgroup->drive is the drive and hwgroup->handler is
+ *	the IRQ handler to call. As we issue a command the handlers
+ *	step through multiple states, reassigning the handler to the
+ *	next step in the process. Unlike a smart SCSI controller IDE
+ *	expects the main processor to sequence the various transfer
+ *	stages. We also manage a poll timer to catch up with most
+ *	timeout situations. There are still a few where the handlers
+ *	don't ever decide to give up.
+ *
+ *	The handler eventually returns ide_stopped to indicate the
+ *	request completed. At this point we issue the next request
+ *	on the hwgroup and the process begins again.
+ */
+ 
+void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long flags;
+	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
+	ide_hwif_t *hwif;
+	ide_drive_t *drive;
+	ide_handler_t *handler;
+	ide_startstop_t startstop;
+
+	spin_lock_irqsave(&ide_lock, flags);
+	hwif = hwgroup->hwif;
+
+	if (!ide_ack_intr(hwif)) {
+		spin_unlock_irqrestore(&ide_lock, flags);
+		return;
+	}
+
+	if ((handler = hwgroup->handler) == NULL ||
+	    hwgroup->poll_timeout != 0) {
+		/*
+		 * Not expecting an interrupt from this drive.
+		 * That means this could be:
+		 *	(1) an interrupt from another PCI device
+		 *	sharing the same PCI INT# as us.
+		 * or	(2) a drive just entered sleep or standby mode,
+		 *	and is interrupting to let us know.
+		 * or	(3) a spurious interrupt of unknown origin.
+		 *
+		 * For PCI, we cannot tell the difference,
+		 * so in that case we just ignore it and hope it goes away.
+		 *
+		 * FIXME: unexpected_intr should be hwif-> then we can
+		 * remove all the ifdef PCI crap
+		 */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+		if (hwif->pci_dev && !hwif->pci_dev->vendor)
+#endif	/* CONFIG_BLK_DEV_IDEPCI */
+		{
+			/*
+			 * Probably not a shared PCI interrupt,
+			 * so we can safely try to do something about it:
+			 */
+			unexpected_intr(irq, hwgroup);
+#ifdef CONFIG_BLK_DEV_IDEPCI
+		} else {
+			/*
+			 * Whack the status register, just in case
+			 * we have a leftover pending IRQ.
+			 */
+			(void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+		}
+		spin_unlock_irqrestore(&ide_lock, flags);
+		return;
+	}
+	drive = hwgroup->drive;
+	if (!drive) {
+		/*
+		 * This should NEVER happen, and there isn't much
+		 * we could do about it here.
+		 *
+		 * [Note - this can occur if the drive is hot unplugged]
+		 */
+		spin_unlock_irqrestore(&ide_lock, flags);
+		return;
+	}
+	if (!drive_is_ready(drive)) {
+		/*
+		 * This happens regularly when we share a PCI IRQ with
+		 * another device.  Unfortunately, it can also happen
+		 * with some buggy drives that trigger the IRQ before
+		 * their status register is up to date.  Hopefully we have
+		 * enough advance overhead that the latter isn't a problem.
+		 */
+		spin_unlock_irqrestore(&ide_lock, flags);
+		return;
+	}
+	if (!hwgroup->busy) {
+		hwgroup->busy = 1;	/* paranoia */
+		printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
+	}
+	hwgroup->handler = NULL;
+	del_timer(&hwgroup->timer);
+	spin_unlock(&ide_lock);
+
+	if (drive->unmask)
+		local_irq_enable();
+	/* service this interrupt, may set handler for next interrupt */
+	startstop = handler(drive);
+	spin_lock_irq(&ide_lock);
+
+	/*
+	 * Note that handler() may have set things up for another
+	 * interrupt to occur soon, but it cannot happen until
+	 * we exit from this routine, because it will be the
+	 * same irq as is currently being serviced here, and Linux
+	 * won't allow another of the same (on any CPU) until we return.
+	 */
+	set_recovery_timer(HWIF(drive));
+	drive->service_time = jiffies - drive->service_start;
+	if (startstop == ide_stopped) {
+		if (hwgroup->handler == NULL) {	/* paranoia */
+			hwgroup->busy = 0;
+			ide_do_request(hwgroup, hwif->irq);
+		} else {
+			printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler "
+				"on exit\n", drive->name);
+		}
+	}
+	spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+EXPORT_SYMBOL(ide_intr);
+
+/**
+ *	ide_init_drive_cmd	-	initialize a drive command request
+ *	@rq: request object
+ *
+ *	Initialize a request before we fill it in and send it down to
+ *	ide_do_drive_cmd. Commands must be set up by this function. Right
+ *	now it doesn't do a lot, but if that changes abusers will have a
+ *	nasty suprise.
+ */
+
+void ide_init_drive_cmd (struct request *rq)
+{
+	memset(rq, 0, sizeof(*rq));
+	rq->flags = REQ_DRIVE_CMD;
+}
+
+EXPORT_SYMBOL(ide_init_drive_cmd);
+
+/**
+ *	ide_do_drive_cmd	-	issue IDE special command
+ *	@drive: device to issue command
+ *	@rq: request to issue
+ *	@action: action for processing
+ *
+ *	This function issues a special IDE device request
+ *	onto the request queue.
+ *
+ *	If action is ide_wait, then the rq is queued at the end of the
+ *	request queue, and the function sleeps until it has been processed.
+ *	This is for use when invoked from an ioctl handler.
+ *
+ *	If action is ide_preempt, then the rq is queued at the head of
+ *	the request queue, displacing the currently-being-processed
+ *	request and this function returns immediately without waiting
+ *	for the new rq to be completed.  This is VERY DANGEROUS, and is
+ *	intended for careful use by the ATAPI tape/cdrom driver code.
+ *
+ *	If action is ide_next, then the rq is queued immediately after
+ *	the currently-being-processed-request (if any), and the function
+ *	returns without waiting for the new rq to be completed.  As above,
+ *	This is VERY DANGEROUS, and is intended for careful use by the
+ *	ATAPI tape/cdrom driver code.
+ *
+ *	If action is ide_end, then the rq is queued at the end of the
+ *	request queue, and the function returns immediately without waiting
+ *	for the new rq to be completed. This is again intended for careful
+ *	use by the ATAPI tape/cdrom driver code.
+ */
+ 
+int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
+{
+	unsigned long flags;
+	ide_hwgroup_t *hwgroup = HWGROUP(drive);
+	DECLARE_COMPLETION(wait);
+	int insert_end = 1, err;
+
+#ifdef CONFIG_BLK_DEV_PDC4030
+	/*
+	 *	FIXME: there should be a drive or hwif->special
+	 *	handler that points here by default, not hacks
+	 *	in the ide-io.c code
+	 */
+	if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
+		return -ENOSYS;  /* special drive cmds not supported */
+#endif
+	rq->errors = 0;
+	rq->rq_status = RQ_ACTIVE;
+
+	rq->rq_disk = drive->disk;
+
+	/*
+	 * we need to hold an extra reference to request for safe inspection
+	 * after completion
+	 */
+	if (action == ide_wait) {
+		rq->ref_count++;
+		rq->waiting = &wait;
+	}
+
+	spin_lock_irqsave(&ide_lock, flags);
+	if (action == ide_preempt) {
+		hwgroup->rq = NULL;
+		insert_end = 0;
+	}
+	__elv_add_request(&drive->queue, rq, insert_end, 0);
+	ide_do_request(hwgroup, 0);
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	err = 0;
+	if (action == ide_wait) {
+		wait_for_completion(&wait);
+		if (rq->errors)
+			err = -EIO;
+
+		blk_put_request(rq);
+	}
+
+	return err;
+}
+
+EXPORT_SYMBOL(ide_do_drive_cmd);
diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
--- a/drivers/ide/ide-iops.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/ide/ide-iops.c	Wed Nov 27 14:36:28 2002
@@ -57,14 +57,14 @@
 	insl(port, addr, count);
 }
 
-static void ide_outb (u8 addr, ide_ioreg_t port)
+static void ide_outb (u8 value, ide_ioreg_t port)
 {
-	outb(addr, port);
+	outb(value, port);
 }
 
-static void ide_outw (u16 addr, ide_ioreg_t port)
+static void ide_outw (u16 value, ide_ioreg_t port)
 {
-	outw(addr, port);
+	outw(value, port);
 }
 
 static void ide_outsw (ide_ioreg_t port, void *addr, u32 count)
@@ -72,14 +72,14 @@
 	outsw(port, addr, count);
 }
 
-static void ide_outl (u32 addr, ide_ioreg_t port)
+static void ide_outl (u32 value, ide_ioreg_t port)
 {
-	outl(addr, port);
+	outl(value, port);
 }
 
 static void ide_outsl (ide_ioreg_t port, void *addr, u32 count)
 {
-	return outsl(port, addr, count);
+	outsl(port, addr, count);
 }
 
 void default_hwif_iops (ide_hwif_t *hwif)
@@ -819,9 +819,9 @@
 //	while (HWGROUP(drive)->busy)
 //		ide_delay_50ms();
 
-#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
+#if !defined(CONFIG_DMA_NONPCI)
 	hwif->ide_dma_host_off(drive);
-#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
+#endif /* !(CONFIG_DMA_NONPCI) */
 
 	/*
 	 * Don't use ide_wait_cmd here - it will
@@ -887,12 +887,12 @@
 	drive->id->dma_mword &= ~0x0F00;
 	drive->id->dma_1word &= ~0x0F00;
 
-#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
+#if !defined(CONFIG_DMA_NONPCI)
 	if (speed >= XFER_SW_DMA_0)
 		hwif->ide_dma_host_on(drive);
 	else
 		hwif->ide_dma_off(drive);
-#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
+#endif /* !(CONFIG_DMA_NONPCI) */
 
 	switch(speed) {
 		case XFER_UDMA_7:   drive->id->dma_ultra |= 0x8080; break;
@@ -1057,8 +1057,7 @@
 {
 	if (drive->crc_count) {
 		(void) HWIF(drive)->ide_dma_off_quietly(drive);
-		if ((HWIF(drive)->speedproc) != NULL)
-			HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive));
+		ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));
 		if (drive->current_speed >= XFER_SW_DMA_0)
 			(void) HWIF(drive)->ide_dma_on(drive);
 	} else {
diff -Nru a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
--- a/drivers/ide/ide-lib.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/ide/ide-lib.c	Wed Nov 27 14:36:32 2002
@@ -300,7 +300,7 @@
 }
 
 /**
- *	ide_get_best_pio_mode	-	get PIO mode fro drive
+ *	ide_get_best_pio_mode	-	get PIO mode from drive
  *	@driver: drive to consider
  *	@mode_wanted: preferred mode
  *	@max_mode: highest allowed
@@ -387,6 +387,15 @@
 
 EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
 
+/**
+ *	ide_toggle_bounce	-	handle bounce buffering
+ *	@drive: drive to update
+ *	@on: on/off boolean
+ *
+ *	Enable or disable bounce buffering for the device. Drives move
+ *	between PIO and DMA and that changes the rules we need.
+ */
+ 
 void ide_toggle_bounce(ide_drive_t *drive, int on)
 {
 	u64 addr = BLK_BOUNCE_HIGH;	/* dma64_addr_t */
@@ -402,3 +411,28 @@
 }
 
 EXPORT_SYMBOL(ide_toggle_bounce);
+
+/**
+ *	ide_set_xfer_rate	-	set transfer rate
+ *	@drive: drive to set
+ *	@speed: speed to attempt to set
+ *	
+ *	General helper for setting the speed of an IDE device. This
+ *	function knows about user enforced limits from the configuration
+ *	which speedproc() does not.  High level drivers should never
+ *	invoke speedproc() directly.
+ */
+ 
+int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
+{
+#ifndef CONFIG_BLK_DEV_IDEDMA
+	rate = min(rate, (u8) XFER_PIO_4);
+#endif
+	if(HWIF(drive)->speedproc)
+		return HWIF(drive)->speedproc(drive, rate);
+	else
+		return -1;
+}
+
+EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
+
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/ide-probe.c	Wed Nov 27 14:36:30 2002
@@ -144,6 +144,7 @@
 	id->model[sizeof(id->model)-1] = '\0';
 	printk("%s: %s, ", drive->name, id->model);
 	drive->present = 1;
+	drive->dead = 0;
 
 	/*
 	 * Check for an ATAPI device
@@ -546,8 +547,24 @@
 	return 1;
 }
 
-#define hwif_check_region(addr, num) \
-	((hwif->mmio) ? check_mem_region((addr),(num)) : check_region((addr),(num)))
+static int hwif_check_region(ide_hwif_t *hwif, unsigned long addr, int num)
+{
+	int err;
+	
+	if(hwif->mmio)
+		err = check_mem_region(addr, num);
+	else
+		err = check_region(addr, num);
+		
+	if(err)
+	{
+		printk("%s: %s resource 0x%lX-0x%lX not free.\n",
+			hwif->name, hwif->mmio?"MMIO":"I/O", addr, addr+num-1);
+		mdelay(2000);
+	}
+	return err;
+}
+		
 
 static int hwif_check_regions (ide_hwif_t *hwif)
 {
@@ -556,14 +573,14 @@
 
 	if (hwif->mmio == 2)
 		return 0;
-	addr_errs  = hwif_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
+	addr_errs  = hwif_check_region(hwif, hwif->io_ports[IDE_DATA_OFFSET], 1);
 	for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-		addr_errs += hwif_check_region(hwif->io_ports[i], 1);
+		addr_errs += hwif_check_region(hwif, hwif->io_ports[i], 1);
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
-		addr_errs += hwif_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+		addr_errs += hwif_check_region(hwif, hwif->io_ports[IDE_CONTROL_OFFSET], 1);
 #if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
 	if (hwif->io_ports[IDE_IRQ_OFFSET])
-		addr_errs += hwif_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);
+		addr_errs += hwif_check_region(hwif, hwif->io_ports[IDE_IRQ_OFFSET], 1);
 #endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
 	/* If any errors are return, we drop the hwif interface. */
 	hwif->straight8 = 0;
@@ -629,7 +646,7 @@
 	}
 #endif
 
-	if ((hwif->chipset != ide_4drives || !hwif->mate->present) &&
+	if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) &&
 #if CONFIG_BLK_DEV_PDC4030
 	    (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
 #endif /* CONFIG_BLK_DEV_PDC4030 */
@@ -655,6 +672,13 @@
 	 * we'll install our IRQ driver much later...
 	 */
 	irqd = hwif->irq;
+	
+	if (irqd >= NR_IRQS)
+	{
+		printk(KERN_ERR "***WARNING***: Bogus interrupt reported. Probably a bug in the Linux ACPI\n");
+		printk(KERN_ERR "***WARNING***: Attempting to continue as best we can.\n");
+		irqd = 0;
+	}
 	if (irqd)
 		disable_irq(hwif->irq);
 
@@ -1058,6 +1082,7 @@
 			 "%s","IDE Drive");
 		drive->gendev.parent = &hwif->gendev;
 		drive->gendev.bus = &ide_bus_type;
+		drive->gendev.driver_data = drive;
 		sprintf (name, "ide/host%d/bus%d/target%d/lun%d",
 			(hwif->channel && hwif->mate) ?
 			hwif->mate->index : hwif->index,
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
--- a/drivers/ide/ide-tape.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/ide/ide-tape.c	Wed Nov 27 14:36:28 2002
@@ -1450,7 +1450,6 @@
 	}
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static void idetape_update_buffers (idetape_pc_t *pc)
 {
 	struct bio *bio = pc->bio;
@@ -1475,7 +1474,6 @@
 	}
 	pc->bio = bio;
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /*
  *	idetape_next_pc_storage returns a pointer to a place in which we can
@@ -1580,7 +1578,6 @@
 		ide_stall_queue(drive, HZ / 2);
 		return;
 	}
-#ifdef CONFIG_BLK_DEV_IDEDMA
 
 	/*
 	 *	Correct pc->actually_transferred by asking the tape.
@@ -1589,7 +1586,7 @@
 		pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned(&result->information));
 		idetape_update_buffers(pc);
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+
 	if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) {
 		pc->error = IDETAPE_ERROR_FILEMARK;
 		set_bit(PC_ABORT, &pc->flags);
@@ -1982,7 +1979,6 @@
 	/* Clear the interrupt */
 	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
 		if (HWIF(drive)->ide_dma_end(drive)) {
 			/*
@@ -2006,7 +2002,6 @@
 			printk(KERN_INFO "ide-tape: DMA finished\n");
 #endif /* IDETAPE_DEBUG_LOG */
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	/* No more interrupts */
 	if (!status.b.drq) {
@@ -2061,7 +2056,6 @@
 			tape->failed_pc = NULL;
 		return pc->callback(drive);	/* Command finished - Call the callback function */
 	}
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
 		printk(KERN_ERR "ide-tape: The tape wants to issue more "
 				"interrupts in DMA mode\n");
@@ -2069,7 +2063,6 @@
 		(void) HWIF(drive)->ide_dma_off(drive);
 		return ide_do_reset(drive);
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	bcount.b.high = IN_BYTE(IDE_BCOUNTH_REG);	/* Get the number of bytes to transfer */
 	bcount.b.low  = IN_BYTE(IDE_BCOUNTL_REG);	/* on this interrupt */
 	ireason.all   = IN_BYTE(IDE_IREASON_REG);
@@ -2264,7 +2257,6 @@
 	pc->current_position = pc->buffer;
 	bcount.all = pc->request_transfer;	/* Request to transfer the entire buffer at once */
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
 		printk(KERN_WARNING "ide-tape: DMA disabled, "
 				"reverting to PIO\n");
@@ -2276,7 +2268,6 @@
 		else
 			dma_ok = !HWIF(drive)->ide_dma_read(drive);
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
@@ -2284,12 +2275,10 @@
 	OUT_BYTE(bcount.b.high,     IDE_BCOUNTH_REG);
 	OUT_BYTE(bcount.b.low,      IDE_BCOUNTL_REG);
 	OUT_BYTE(drive->select.all, IDE_SELECT_REG);
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (dma_ok) {			/* Begin DMA, if necessary */
 		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
 		(void) (HWIF(drive)->ide_dma_begin(drive));
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
 		if (HWGROUP(drive)->handler != NULL)	/* paranoia check */
 			BUG();
diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
--- a/drivers/ide/ide-taskfile.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/ide/ide-taskfile.c	Wed Nov 27 14:36:27 2002
@@ -1068,7 +1068,6 @@
 		case DISABLE_SEAGATE:
 		case EXABYTE_ENABLE_NEST:
 			return &task_no_data_intr;
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case WIN_READDMA:
 	//	case WIN_READDMA_ONCE:
 		case WIN_IDENTIFY_DMA:
@@ -1080,7 +1079,6 @@
 		case WIN_WRITEDMA_QUEUED:
 		case WIN_WRITEDMA_EXT:
 		case WIN_WRITEDMA_QUEUED_EXT:
-#endif
 		case WIN_FORMAT:
 		case WIN_INIT:
 		case WIN_DEVICE_RESET:
@@ -1164,7 +1162,6 @@
 				default:
 					return IDE_DRIVE_TASK_NO_DATA;
 			}
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case WIN_READDMA:
 	//	case WIN_READDMA_ONCE:
 		case WIN_IDENTIFY_DMA:
@@ -1178,7 +1175,6 @@
 		case WIN_WRITEDMA_EXT:
 		case WIN_WRITEDMA_QUEUED_EXT:
 			return IDE_DRIVE_TASK_RAW_WRITE;
-#endif
 		case WIN_SETFEATURES:
 			switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
 				case SETFEATURES_EN_8BIT:
@@ -1669,8 +1665,7 @@
 
 	if (!err && xfer_rate) {
 		/* active-retuning-calls future */
-		if ((HWIF(drive)->speedproc) != NULL)
-			HWIF(drive)->speedproc(drive, xfer_rate);
+		ide_set_xfer_rate(drive, xfer_rate);
 		ide_driveid_update(drive);
 	}
 abort:
@@ -1724,8 +1719,7 @@
 
 	if (!err && xfer_rate) {
 		/* active-retuning-calls future */
-		if ((HWIF(drive)->speedproc) != NULL)
-			HWIF(drive)->speedproc(drive, xfer_rate);
+		ide_set_xfer_rate(driver, xfer_rate);
 		ide_driveid_update(drive);
 	}
 abort:
diff -Nru a/drivers/ide/ide-tcq.c b/drivers/ide/ide-tcq.c
--- a/drivers/ide/ide-tcq.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/ide/ide-tcq.c	Wed Nov 27 14:36:32 2002
@@ -148,14 +148,14 @@
 	ide_hwif_t *hwif = HWIF(drive);
 	unsigned long flags;
 
-	printk("ide_tcq_intr_timeout: timeout waiting for %s interrupt\n", hwgroup->rq ? "completion" : "service");
+	printk(KERN_ERR "ide_tcq_intr_timeout: timeout waiting for %s interrupt\n", hwgroup->rq ? "completion" : "service");
 
 	spin_lock_irqsave(&ide_lock, flags);
 
 	if (!hwgroup->busy)
-		printk("ide_tcq_intr_timeout: hwgroup not busy\n");
+		printk(KERN_ERR "ide_tcq_intr_timeout: hwgroup not busy\n");
 	if (hwgroup->handler == NULL)
-		printk("ide_tcq_intr_timeout: missing isr!\n");
+		printk(KERN_ERR "ide_tcq_intr_timeout: missing isr!\n");
 
 	hwgroup->busy = 1;
 	spin_unlock_irqrestore(&ide_lock, flags);
@@ -261,7 +261,7 @@
 	hwif->OUTB(WIN_QUEUED_SERVICE, IDE_COMMAND_REG);
 
 	if (ide_tcq_wait_altstat(drive, &stat, BUSY_STAT)) {
-		printk("ide_service: BUSY clear took too long\n");
+		printk(KERN_ERR "ide_service: BUSY clear took too long\n");
 		ide_dump_status(drive, "ide_service", stat);
 		ide_tcq_invalidate_queue(drive);
 		return ide_stopped;
@@ -284,7 +284,7 @@
 	feat = hwif->INB(IDE_NSECTOR_REG);
 	if (feat & REL) {
 		HWGROUP(drive)->rq = NULL;
-		printk("%s: release in service\n", drive->name);
+		printk(KERN_ERR "%s: release in service\n", drive->name);
 		return ide_stopped;
 	}
 
@@ -307,7 +307,7 @@
 		return HWIF(drive)->ide_dma_queued_start(drive);
 	}
 
-	printk("ide_service: missing request for tag %d\n", tag);
+	printk(KERN_ERR "ide_service: missing request for tag %d\n", tag);
 	spin_unlock_irqrestore(&ide_lock, flags);
 	return ide_stopped;
 }
@@ -347,14 +347,14 @@
 	 * must be end of I/O, check status and complete as necessary
 	 */
 	if (unlikely(!OK_STAT(stat, READY_STAT, drive->bad_wstat | DRQ_STAT))) {
-		printk("ide_dmaq_intr: %s: error status %x\n",drive->name,stat);
+		printk(KERN_ERR "ide_dmaq_intr: %s: error status %x\n",drive->name,stat);
 		ide_dump_status(drive, "ide_dmaq_complete", stat);
 		ide_tcq_invalidate_queue(drive);
 		return ide_stopped;
 	}
 
 	if (dma_stat)
-		printk("%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat);
+		printk(KERN_WARNING "%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat);
 
 	TCQ_PRINTK("ide_dmaq_complete: ending %p, tag %d\n", rq, rq->tag);
 	ide_end_request(drive, 1, rq->nr_sectors);
@@ -465,7 +465,7 @@
 	args->command_type = ide_cmd_type_parser(args);
 
 	if (ide_raw_taskfile(drive, args, NULL)) {
-		printk("%s: failed to enable write cache\n", drive->name);
+		printk(KERN_WARNING "%s: failed to enable write cache\n", drive->name);
 		goto err;
 	}
 
@@ -479,7 +479,7 @@
 	args->command_type = ide_cmd_type_parser(args);
 
 	if (ide_raw_taskfile(drive, args, NULL)) {
-		printk("%s: disabling release interrupt fail\n", drive->name);
+		printk(KERN_ERR "%s: disabling release interrupt fail\n", drive->name);
 		goto err;
 	}
 
@@ -493,7 +493,7 @@
 	args->command_type = ide_cmd_type_parser(args);
 
 	if (ide_raw_taskfile(drive, args, NULL)) {
-		printk("%s: enabling service interrupt fail\n", drive->name);
+		printk(KERN_ERR "%s: enabling service interrupt fail\n", drive->name);
 		goto err;
 	}
 #endif
@@ -518,7 +518,7 @@
 	 */
 	if (!on) {
 		if (drive->using_tcq)
-			printk("%s: TCQ disabled\n", drive->name);
+			printk(KERN_INFO "%s: TCQ disabled\n", drive->name);
 
 		drive->using_tcq = 0;
 		return 0;
@@ -541,7 +541,7 @@
 	ide_tcq_check_autopoll(drive);
 
 	if (depth != drive->queue_depth)
-		printk("%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth);
+		printk(KERN_INFO "%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth);
 
 	drive->using_tcq = 1;
 	return 0;
@@ -588,7 +588,7 @@
 		return 1;
 
 	if (ata_pending_commands(drive)) {
-		printk("ide-tcq; can't toggle tcq feature on busy drive\n");
+		printk(KERN_WARNING "ide-tcq; can't toggle tcq feature on busy drive\n");
 		return 1;
 	}
 
@@ -692,10 +692,10 @@
 	TCQ_PRINTK("ide_dma: setting up queued tag=%d\n", rq->tag);
 
 	if (!hwgroup->busy)
-		printk("queued_rw: hwgroup not busy\n");
+		printk(KERN_ERR "queued_rw: hwgroup not busy\n");
 
 	if (ide_tcq_wait_dataphase(drive)) {
-		printk("timeout waiting for data phase\n");
+		printk(KERN_WARNING "timeout waiting for data phase\n");
 		return ide_stopped;
 	}
 
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/ide/ide.c	Wed Nov 27 14:36:28 2002
@@ -222,37 +222,6 @@
 EXPORT_SYMBOL(idetape);
 EXPORT_SYMBOL(idescsi);
 
-#if (DISK_RECOVERY_TIME > 0)
-
-Error So the User Has To Fix the Compilation And Stop Hacking Port 0x43
-Does anyone ever use this anyway ??
-
-/*
- * For really screwy hardware (hey, at least it *can* be used with Linux)
- * we can enforce a minimum delay time between successive operations.
- */
-static unsigned long read_timer (ide_hwif_t *hwif)
-{
-	unsigned long t, flags;
-	int i;
-	
-	/* FIXME this is completely unsafe! */
-	local_irq_save(flags);
-	t = jiffies * 11932;
-	outb_p(0, 0x43);
-	i = inb_p(0x40);
-	i |= inb_p(0x40) << 8;
-	local_irq_restore(flags);
-	return (t - i);
-}
-#endif /* DISK_RECOVERY_TIME */
-
-static inline void set_recovery_timer (ide_hwif_t *hwif)
-{
-#if (DISK_RECOVERY_TIME > 0)
-	hwif->last_time = read_timer(hwif);
-#endif /* DISK_RECOVERY_TIME */
-}
 
 /*
  * Do not even *think* about calling this!
@@ -310,6 +279,7 @@
 		drive->max_failures		= IDE_DEFAULT_MAX_FAILURES;
 		drive->using_dma		= 0;
 		drive->is_flash			= 0;
+		drive->vdma			= 0;
 		INIT_LIST_HEAD(&drive->list);
 	}
 }
@@ -372,7 +342,7 @@
 			/* safe default value for VESA and PCI */
 			system_bus_speed = 50;
 		}
-		printk("ide: Assuming %dMHz system bus speed "
+		printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
 			"for PIO modes%s\n", system_bus_speed,
 			idebus_parameter ? "" : "; override with idebus=xx");
 	}
@@ -380,48 +350,6 @@
 }
 
 /*
- * This is our end_request replacement function.
- */
-int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
-{
-	struct request *rq;
-	unsigned long flags;
-	int ret = 1;
-
-	spin_lock_irqsave(&ide_lock, flags);
-	rq = HWGROUP(drive)->rq;
-
-	BUG_ON(!(rq->flags & REQ_STARTED));
-
-	if (!nr_sectors)
-		nr_sectors = rq->hard_cur_sectors;
-
-	/*
-	 * decide whether to reenable DMA -- 3 is a random magic for now,
-	 * if we DMA timeout more than 3 times, just stay in PIO
-	 */
-	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
-		drive->state = 0;
-		HWGROUP(drive)->hwif->ide_dma_on(drive);
-	}
-
-	if (!end_that_request_first(rq, uptodate, nr_sectors)) {
-		add_disk_randomness(rq->rq_disk);
-		if (!blk_rq_tagged(rq))
-			blkdev_dequeue_request(rq);
-		else
-			blk_queue_end_tag(&drive->queue, rq);
-		HWGROUP(drive)->rq = NULL;
-		end_that_request_last(rq);
-		ret = 0;
-	}
-	spin_unlock_irqrestore(&ide_lock, flags);
-	return ret;
-}
-
-EXPORT_SYMBOL(ide_end_request);
-
-/*
  * current_capacity() returns the capacity (in sectors) of a drive
  * according to its current geometry/LBA settings.
  */
@@ -444,82 +372,6 @@
 }
 
 /*
- * Clean up after success/failure of an explicit drive cmd
- */
-void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	unsigned long flags;
-	struct request *rq;
-
-	spin_lock_irqsave(&ide_lock, flags);
-	rq = HWGROUP(drive)->rq;
-	spin_unlock_irqrestore(&ide_lock, flags);
-
-	if (rq->flags & REQ_DRIVE_CMD) {
-		u8 *args = (u8 *) rq->buffer;
-		if (rq->errors == 0)
-			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-
-		if (args) {
-			args[0] = stat;
-			args[1] = err;
-			args[2] = hwif->INB(IDE_NSECTOR_REG);
-		}
-	} else if (rq->flags & REQ_DRIVE_TASK) {
-		u8 *args = (u8 *) rq->buffer;
-		if (rq->errors == 0)
-			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-
-		if (args) {
-			args[0] = stat;
-			args[1] = err;
-			args[2] = hwif->INB(IDE_NSECTOR_REG);
-			args[3] = hwif->INB(IDE_SECTOR_REG);
-			args[4] = hwif->INB(IDE_LCYL_REG);
-			args[5] = hwif->INB(IDE_HCYL_REG);
-			args[6] = hwif->INB(IDE_SELECT_REG);
-		}
-	} else if (rq->flags & REQ_DRIVE_TASKFILE) {
-		ide_task_t *args = (ide_task_t *) rq->special;
-		if (rq->errors == 0)
-			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-			
-		if (args) {
-			if (args->tf_in_flags.b.data) {
-				u16 data				= hwif->INW(IDE_DATA_REG);
-				args->tfRegister[IDE_DATA_OFFSET]	= (data) & 0xFF;
-				args->hobRegister[IDE_DATA_OFFSET_HOB]	= (data >> 8) & 0xFF;
-			}
-			args->tfRegister[IDE_ERROR_OFFSET]   = err;
-			args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
-			args->tfRegister[IDE_SECTOR_OFFSET]  = hwif->INB(IDE_SECTOR_REG);
-			args->tfRegister[IDE_LCYL_OFFSET]    = hwif->INB(IDE_LCYL_REG);
-			args->tfRegister[IDE_HCYL_OFFSET]    = hwif->INB(IDE_HCYL_REG);
-			args->tfRegister[IDE_SELECT_OFFSET]  = hwif->INB(IDE_SELECT_REG);
-			args->tfRegister[IDE_STATUS_OFFSET]  = stat;
-
-			if (drive->addressing == 1) {
-				hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
-				args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG);
-				args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG);
-				args->hobRegister[IDE_SECTOR_OFFSET_HOB]  = hwif->INB(IDE_SECTOR_REG);
-				args->hobRegister[IDE_LCYL_OFFSET_HOB]    = hwif->INB(IDE_LCYL_REG);
-				args->hobRegister[IDE_HCYL_OFFSET_HOB]    = hwif->INB(IDE_HCYL_REG);
-			}
-		}
-	}
-
-	spin_lock_irqsave(&ide_lock, flags);
-	blkdev_dequeue_request(rq);
-	HWGROUP(drive)->rq = NULL;
-	end_that_request_last(rq);
-	spin_unlock_irqrestore(&ide_lock, flags);
-}
-
-EXPORT_SYMBOL(ide_end_drive_cmd);
-
-/*
  * Error reporting, in human readable form (luxurious, but a memory hog).
  */
 u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
@@ -529,7 +381,7 @@
 	u8 err = 0;
 
 	local_irq_set(flags);
-	printk("%s: %s: status=0x%02x", drive->name, msg, stat);
+	printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat);
 #if FANCY_STATUS_DUMPS
 	printk(" { ");
 	if (stat & BUSY_STAT) {
@@ -602,967 +454,7 @@
 
 EXPORT_SYMBOL(ide_dump_status);
 
-/*
- * try_to_flush_leftover_data() is invoked in response to a drive
- * unexpectedly having its DRQ_STAT bit set.  As an alternative to
- * resetting the drive, this routine tries to clear the condition
- * by read a sector's worth of data from the drive.  Of course,
- * this may not help if the drive is *waiting* for data from *us*.
- */
-void try_to_flush_leftover_data (ide_drive_t *drive)
-{
-	int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS;
-
-	if (drive->media != ide_disk)
-		return;
-	while (i > 0) {
-		u32 buffer[16];
-		u32 wcount = (i > 16) ? 16 : i;
-
-		i -= wcount;
-		HWIF(drive)->ata_input_data(drive, buffer, wcount);
-	}
-}
-
-EXPORT_SYMBOL(try_to_flush_leftover_data);
-
-/*
- * FIXME Add an ATAPI error
- */
-
-/*
- * ide_error() takes action based on the error returned by the drive.
- */
-ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
-{
-	ide_hwif_t *hwif;
-	struct request *rq;
-	u8 err;
-
-	err = ide_dump_status(drive, msg, stat);
-	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
-		return ide_stopped;
-
-	hwif = HWIF(drive);
-	/* retry only "normal" I/O: */
-	if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
-		rq->errors = 1;
-		ide_end_drive_cmd(drive, stat, err);
-		return ide_stopped;
-	}
-	if (rq->flags & REQ_DRIVE_TASKFILE) {
-		rq->errors = 1;
-		ide_end_drive_cmd(drive, stat, err);
-//		ide_end_taskfile(drive, stat, err);
-		return ide_stopped;
-	}
-
-	if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
-		 /* other bits are useless when BUSY */
-		rq->errors |= ERROR_RESET;
-	} else {
-		if (drive->media != ide_disk)
-			goto media_out;
 
-		if (stat & ERR_STAT) {
-			/* err has different meaning on cdrom and tape */
-			if (err == ABRT_ERR) {
-				if (drive->select.b.lba &&
-				    (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY))
-					/* some newer drives don't
-					 * support WIN_SPECIFY
-					 */
-					return ide_stopped;
-			} else if ((err & BAD_CRC) == BAD_CRC) {
-				drive->crc_count++;
-				/* UDMA crc error -- just retry the operation */
-			} else if (err & (BBD_ERR | ECC_ERR)) {
-				/* retries won't help these */
-				rq->errors = ERROR_MAX;
-			} else if (err & TRK0_ERR) {
-				/* help it find track zero */
-				rq->errors |= ERROR_RECAL;
-			}
-		}
-media_out:
-		if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE)
-			try_to_flush_leftover_data(drive);
-	}
-	if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) {
-		/* force an abort */
-		hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
-	}
-	if (rq->errors >= ERROR_MAX) {
-		if (drive->driver != NULL)
-			DRIVER(drive)->end_request(drive, 0, 0);
-		else
-	 		ide_end_request(drive, 0, 0);
-	} else {
-		if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
-			++rq->errors;
-			return ide_do_reset(drive);
-		}
-		if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
-			drive->special.b.recalibrate = 1;
-		++rq->errors;
-	}
-	return ide_stopped;
-}
-
-EXPORT_SYMBOL(ide_error);
-
-/*
- * Issue a simple drive command
- * The drive must be selected beforehand.
- */
-void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
-	ide_set_handler(drive, handler, WAIT_CMD, NULL);
-	if (IDE_CONTROL_REG)
-		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
-	SELECT_MASK(drive,0);
-	hwif->OUTB(nsect,IDE_NSECTOR_REG);
-	hwif->OUTB(cmd,IDE_COMMAND_REG);
-}
-
-EXPORT_SYMBOL(ide_cmd);
-
-/*
- * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- */
-ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
-{
-	struct request *rq = HWGROUP(drive)->rq;
-	ide_hwif_t *hwif = HWIF(drive);
-	u8 *args = (u8 *) rq->buffer;
-	u8 stat = hwif->INB(IDE_STATUS_REG);
-	int retries = 10;
-
-	local_irq_enable();
-	if ((stat & DRQ_STAT) && args && args[3]) {
-		u8 io_32bit = drive->io_32bit;
-		drive->io_32bit = 0;
-		hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
-		drive->io_32bit = io_32bit;
-		while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
-			udelay(100);
-	}
-
-	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
-		return DRIVER(drive)->error(drive, "drive_cmd", stat);
-		/* calls ide_end_drive_cmd */
-	ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
-	return ide_stopped;
-}
-
-EXPORT_SYMBOL(drive_cmd_intr);
-
-/*
- * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
- * commands to a drive.  It used to do much more, but has been scaled back.
- */
-ide_startstop_t do_special (ide_drive_t *drive)
-{
-	special_t *s = &drive->special;
-
-#ifdef DEBUG
-	printk("%s: do_special: 0x%02x\n", drive->name, s->all);
-#endif
-	if (s->b.set_tune) {
-		s->b.set_tune = 0;
-		if (HWIF(drive)->tuneproc != NULL)
-			HWIF(drive)->tuneproc(drive, drive->tune_req);
-	} else if (drive->driver != NULL) {
-		return DRIVER(drive)->special(drive);
-	} else if (s->all) {
-		printk("%s: bad special flag: 0x%02x\n", drive->name, s->all);
-		s->all = 0;
-	}
-	return ide_stopped;
-}
-
-EXPORT_SYMBOL(do_special);
-
-/*
- * execute_drive_cmd() issues a special drive command,
- * usually initiated by ioctl() from the external hdparm program.
- */
-ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	if (rq->flags & REQ_DRIVE_TASKFILE) {
- 		ide_task_t *args = rq->special;
- 
-		if (!args)
-			goto done;
- 
-		if (args->tf_out_flags.all != 0) 
-			return flagged_taskfile(drive, args);
-		return do_rw_taskfile(drive, args);
-	} else if (rq->flags & REQ_DRIVE_TASK) {
-		u8 *args = rq->buffer;
-		u8 sel;
- 
-		if (!args)
-			goto done;
-#ifdef DEBUG
- 		printk("%s: DRIVE_TASK_CMD ", drive->name);
- 		printk("cmd=0x%02x ", args[0]);
- 		printk("fr=0x%02x ", args[1]);
- 		printk("ns=0x%02x ", args[2]);
- 		printk("sc=0x%02x ", args[3]);
- 		printk("lcyl=0x%02x ", args[4]);
- 		printk("hcyl=0x%02x ", args[5]);
- 		printk("sel=0x%02x\n", args[6]);
-#endif
- 		hwif->OUTB(args[1], IDE_FEATURE_REG);
- 		hwif->OUTB(args[3], IDE_SECTOR_REG);
- 		hwif->OUTB(args[4], IDE_LCYL_REG);
- 		hwif->OUTB(args[5], IDE_HCYL_REG);
- 		sel = (args[6] & ~0x10);
- 		if (drive->select.b.unit)
- 			sel |= 0x10;
- 		hwif->OUTB(sel, IDE_SELECT_REG);
- 		ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
- 		return ide_started;
- 	} else if (rq->flags & REQ_DRIVE_CMD) {
- 		u8 *args = rq->buffer;
-
-		if (!args)
-			goto done;
-#ifdef DEBUG
- 		printk("%s: DRIVE_CMD ", drive->name);
- 		printk("cmd=0x%02x ", args[0]);
- 		printk("sc=0x%02x ", args[1]);
- 		printk("fr=0x%02x ", args[2]);
- 		printk("xx=0x%02x\n", args[3]);
-#endif
- 		if (args[0] == WIN_SMART) {
- 			hwif->OUTB(0x4f, IDE_LCYL_REG);
- 			hwif->OUTB(0xc2, IDE_HCYL_REG);
- 			hwif->OUTB(args[2],IDE_FEATURE_REG);
- 			hwif->OUTB(args[1],IDE_SECTOR_REG);
- 			ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
- 			return ide_started;
- 		}
- 		hwif->OUTB(args[2],IDE_FEATURE_REG);
- 		ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
- 		return ide_started;
- 	}
-
-done:
- 	/*
- 	 * NULL is actually a valid way of waiting for
- 	 * all current requests to be flushed from the queue.
- 	 */
-#ifdef DEBUG
- 	printk("%s: DRIVE_CMD (null)\n", drive->name);
-#endif
- 	ide_end_drive_cmd(drive,
-			hwif->INB(IDE_STATUS_REG),
-			hwif->INB(IDE_ERROR_REG));
- 	return ide_stopped;
-}
-
-EXPORT_SYMBOL(execute_drive_cmd);
-
-/*
- * start_request() initiates handling of a new I/O request
- * needed to reverse the perverted changes anonymously made back
- * 2.3.99-pre6
- */
-ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
-{
-	ide_startstop_t startstop;
-	unsigned long block;
-
-	BUG_ON(!(rq->flags & REQ_STARTED));
-
-#ifdef DEBUG
-	printk("%s: start_request: current=0x%08lx\n",
-		HWIF(drive)->name, (unsigned long) rq);
-#endif
-
-	/* bail early if we've exceeded max_failures */
-	if (drive->max_failures && (drive->failures > drive->max_failures)) {
-		goto kill_rq;
-	}
-
-	/*
-	 * bail early if we've sent a device to sleep, however how to wake
-	 * this needs to be a masked flag.  FIXME for proper operations.
-	 */
-	if (drive->suspend_reset)
-		goto kill_rq;
-
-	block    = rq->sector;
-	if (blk_fs_request(rq) &&
-	    (drive->media == ide_disk || drive->media == ide_floppy)) {
-		block += drive->sect0;
-	}
-	/* Yecch - this will shift the entire interval,
-	   possibly killing some innocent following sector */
-	if (block == 0 && drive->remap_0_to_1 == 1)
-		block = 1;  /* redirect MBR access to EZ-Drive partn table */
-
-#if (DISK_RECOVERY_TIME > 0)
-	while ((read_timer() - HWIF(drive)->last_time) < DISK_RECOVERY_TIME);
-#endif
-
-	SELECT_DRIVE(drive);
-	if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
-		printk("%s: drive not ready for command\n", drive->name);
-		return startstop;
-	}
-	if (!drive->special.all) {
-		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK))
-			return execute_drive_cmd(drive, rq);
-		else if (rq->flags & REQ_DRIVE_TASKFILE)
-			return execute_drive_cmd(drive, rq);
-
-		if (drive->driver != NULL) {
-			return (DRIVER(drive)->do_request(drive, rq, block));
-		}
-		printk("%s: media type %d not supported\n", drive->name, drive->media);
-		goto kill_rq;
-	}
-	return do_special(drive);
-kill_rq:
-	if (drive->driver != NULL)
-		DRIVER(drive)->end_request(drive, 0, 0);
-	else
-		ide_end_request(drive, 0, 0);
-	return ide_stopped;
-}
-
-EXPORT_SYMBOL(start_request);
-
-int restart_request (ide_drive_t *drive, struct request *rq)
-{
-	(void) start_request(drive, rq);
-	return 0;
-}
-
-EXPORT_SYMBOL(restart_request);
-
-/*
- * ide_stall_queue() can be used by a drive to give excess bandwidth back
- * to the hwgroup by sleeping for timeout jiffies.
- */
-void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
-{
-	if (timeout > WAIT_WORSTCASE)
-		timeout = WAIT_WORSTCASE;
-	drive->sleep = timeout + jiffies;
-}
-
-EXPORT_SYMBOL(ide_stall_queue);
-
-#define WAKEUP(drive)	((drive)->service_start + 2 * (drive)->service_time)
-
-/*
- * choose_drive() selects the next drive which will be serviced.
- */
-static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
-{
-	ide_drive_t *drive, *best;
-
-repeat:	
-	best = NULL;
-	drive = hwgroup->drive;
-	do {
-		if (!blk_queue_empty(&drive->queue) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) {
-			if (!best
-			 || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
-			 || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
-			{
-				if (!blk_queue_plugged(&drive->queue))
-					best = drive;
-			}
-		}
-	} while ((drive = drive->next) != hwgroup->drive);
-	if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
-		long t = (signed long)(WAKEUP(best) - jiffies);
-		if (t >= WAIT_MIN_SLEEP) {
-		/*
-		 * We *may* have some time to spare, but first let's see if
-		 * someone can potentially benefit from our nice mood today..
-		 */
-			drive = best->next;
-			do {
-				if (!drive->sleep
-				 && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
-				 && 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
-				{
-					ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP));
-					goto repeat;
-				}
-			} while ((drive = drive->next) != best);
-		}
-	}
-	return best;
-}
-
-/*
- * Issue a new request to a drive from hwgroup
- * Caller must have already done spin_lock_irqsave(&ide_lock, ..);
- *
- * A hwgroup is a serialized group of IDE interfaces.  Usually there is
- * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
- * may have both interfaces in a single hwgroup to "serialize" access.
- * Or possibly multiple ISA interfaces can share a common IRQ by being grouped
- * together into one hwgroup for serialized access.
- *
- * Note also that several hwgroups can end up sharing a single IRQ,
- * possibly along with many other devices.  This is especially common in
- * PCI-based systems with off-board IDE controller cards.
- *
- * The IDE driver uses the single global ide_lock spinlock to protect
- * access to the request queues, and to protect the hwgroup->busy flag.
- *
- * The first thread into the driver for a particular hwgroup sets the
- * hwgroup->busy flag to indicate that this hwgroup is now active,
- * and then initiates processing of the top request from the request queue.
- *
- * Other threads attempting entry notice the busy setting, and will simply
- * queue their new requests and exit immediately.  Note that hwgroup->busy
- * remains set even when the driver is merely awaiting the next interrupt.
- * Thus, the meaning is "this hwgroup is busy processing a request".
- *
- * When processing of a request completes, the completing thread or IRQ-handler
- * will start the next request from the queue.  If no more work remains,
- * the driver will clear the hwgroup->busy flag and exit.
- *
- * The ide_lock (spinlock) is used to protect all access to the
- * hwgroup->busy flag, but is otherwise not needed for most processing in
- * the driver.  This makes the driver much more friendlier to shared IRQs
- * than previous designs, while remaining 100% (?) SMP safe and capable.
- */
-/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back
- *         into life on wakeup from machine sleep.
- */ 
-void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
-{
-	ide_drive_t	*drive;
-	ide_hwif_t	*hwif;
-	struct request	*rq;
-	ide_startstop_t	startstop;
-
-	/* for atari only: POSSIBLY BROKEN HERE(?) */
-	ide_get_lock(&ide_intr_lock, ide_intr, hwgroup);
-
-	/* necessary paranoia: ensure IRQs are masked on local CPU */
-	local_irq_disable();
-
-	while (!hwgroup->busy) {
-		hwgroup->busy = 1;
-		drive = choose_drive(hwgroup);
-		if (drive == NULL) {
-			unsigned long sleep = 0;
-			hwgroup->rq = NULL;
-			drive = hwgroup->drive;
-			do {
-				if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
-					sleep = drive->sleep;
-			} while ((drive = drive->next) != hwgroup->drive);
-			if (sleep) {
-		/*
-		 * Take a short snooze, and then wake up this hwgroup again.
-		 * This gives other hwgroups on the same a chance to
-		 * play fairly with us, just in case there are big differences
-		 * in relative throughputs.. don't want to hog the cpu too much.
-		 */
-				if (time_before(sleep, jiffies + WAIT_MIN_SLEEP))
-					sleep = jiffies + WAIT_MIN_SLEEP;
-#if 1
-				if (timer_pending(&hwgroup->timer))
-					printk("ide_set_handler: timer already active\n");
-#endif
-				/* so that ide_timer_expiry knows what to do */
-				hwgroup->sleeping = 1;
-				mod_timer(&hwgroup->timer, sleep);
-				/* we purposely leave hwgroup->busy==1
-				 * while sleeping */
-			} else {
-				/* Ugly, but how can we sleep for the lock
-				 * otherwise? perhaps from tq_disk?
-				 */
-
-				/* for atari only */
-				ide_release_lock(&ide_intr_lock);
-				hwgroup->busy = 0;
-			}
-
-			/* no more work for this hwgroup (for now) */
-			return;
-		}
-		hwif = HWIF(drive);
-		if (hwgroup->hwif->sharing_irq &&
-		    hwif != hwgroup->hwif &&
-		    hwif->io_ports[IDE_CONTROL_OFFSET]) {
-			/* set nIEN for previous hwif */
-			SELECT_INTERRUPT(drive);
-		}
-		hwgroup->hwif = hwif;
-		hwgroup->drive = drive;
-		drive->sleep = 0;
-		drive->service_start = jiffies;
-
-queue_next:
-		if (!ata_can_queue(drive)) {
-			if (!ata_pending_commands(drive))
-				hwgroup->busy = 0;
-
-			break;
-		}
-
-		if (blk_queue_plugged(&drive->queue)) {
-			if (drive->using_tcq)
-				break;
-
-			printk("ide: huh? queue was plugged!\n");
-			break;
-		}
-
-		/*
-		 * we know that the queue isn't empty, but this can happen
-		 * if the q->prep_rq_fn() decides to kill a request
-		 */
-		rq = elv_next_request(&drive->queue);
-		if (!rq) {
-			hwgroup->busy = !!ata_pending_commands(drive);
-			break;
-		}
-
-		if (!rq->bio && ata_pending_commands(drive))
-			break;
-
-		hwgroup->rq = rq;
-
-		/*
-		 * Some systems have trouble with IDE IRQs arriving while
-		 * the driver is still setting things up.  So, here we disable
-		 * the IRQ used by this interface while the request is being started.
-		 * This may look bad at first, but pretty much the same thing
-		 * happens anyway when any interrupt comes in, IDE or otherwise
-		 *  -- the kernel masks the IRQ while it is being handled.
-		 */
-		if (masked_irq && hwif->irq != masked_irq)
-			disable_irq_nosync(hwif->irq);
-		spin_unlock(&ide_lock);
-		local_irq_enable();
-			/* allow other IRQs while we start this request */
-		startstop = start_request(drive, rq);
-		spin_lock_irq(&ide_lock);
-		if (masked_irq && hwif->irq != masked_irq)
-			enable_irq(hwif->irq);
-		if (startstop == ide_released)
-			goto queue_next;
-		if (startstop == ide_stopped)
-			hwgroup->busy = 0;
-	}
-}
-
-EXPORT_SYMBOL(ide_do_request);
-
-/*
- * Passes the stuff to ide_do_request
- */
-void do_ide_request(request_queue_t *q)
-{
-	ide_do_request(q->queuedata, 0);
-}
-
-/*
- * un-busy the hwgroup etc, and clear any pending DMA status. we want to
- * retry the current request in pio mode instead of risking tossing it
- * all away
- */
-void ide_dma_timeout_retry(ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	struct request *rq;
-
-	/*
-	 * end current dma transaction
-	 */
-	(void) hwif->ide_dma_end(drive);
-
-	/*
-	 * complain a little, later we might remove some of this verbosity
-	 */
-	printk("%s: timeout waiting for DMA\n", drive->name);
-	(void) hwif->ide_dma_timeout(drive);
-
-	/*
-	 * disable dma for now, but remember that we did so because of
-	 * a timeout -- we'll reenable after we finish this next request
-	 * (or rather the first chunk of it) in pio.
-	 */
-	drive->retry_pio++;
-	drive->state = DMA_PIO_RETRY;
-	(void) hwif->ide_dma_off_quietly(drive);
-
-	/*
-	 * un-busy drive etc (hwgroup->busy is cleared on return) and
-	 * make sure request is sane
-	 */
-	rq = HWGROUP(drive)->rq;
-	HWGROUP(drive)->rq = NULL;
-
-	rq->errors = 0;
-	rq->sector = rq->bio->bi_sector;
-	rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
-	rq->hard_cur_sectors = rq->current_nr_sectors;
-	if (rq->bio)
-		rq->buffer = NULL;
-}
-
-EXPORT_SYMBOL(ide_dma_timeout_retry);
-
-/*
- * ide_timer_expiry() is our timeout function for all drive operations.
- * But note that it can also be invoked as a result of a "sleep" operation
- * triggered by the mod_timer() call in ide_do_request.
- */
-void ide_timer_expiry (unsigned long data)
-{
-	ide_hwgroup_t	*hwgroup = (ide_hwgroup_t *) data;
-	ide_handler_t	*handler;
-	ide_expiry_t	*expiry;
- 	unsigned long	flags;
-	unsigned long	wait;
-
-	spin_lock_irqsave(&ide_lock, flags);
-	del_timer(&hwgroup->timer);
-
-	if ((handler = hwgroup->handler) == NULL) {
-		/*
-		 * Either a marginal timeout occurred
-		 * (got the interrupt just as timer expired),
-		 * or we were "sleeping" to give other devices a chance.
-		 * Either way, we don't really want to complain about anything.
-		 */
-		if (hwgroup->sleeping) {
-			hwgroup->sleeping = 0;
-			hwgroup->busy = 0;
-		}
-	} else {
-		ide_drive_t *drive = hwgroup->drive;
-		if (!drive) {
-			printk("ide_timer_expiry: hwgroup->drive was NULL\n");
-			hwgroup->handler = NULL;
-		} else {
-			ide_hwif_t *hwif;
-			ide_startstop_t startstop = ide_stopped;
-			if (!hwgroup->busy) {
-				hwgroup->busy = 1;	/* paranoia */
-				printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name);
-			}
-			if ((expiry = hwgroup->expiry) != NULL) {
-				/* continue */
-				if ((wait = expiry(drive)) != 0) {
-					/* reset timer */
-					hwgroup->timer.expires  = jiffies + wait;
-					add_timer(&hwgroup->timer);
-					spin_unlock_irqrestore(&ide_lock, flags);
-					return;
-				}
-			}
-			hwgroup->handler = NULL;
-			/*
-			 * We need to simulate a real interrupt when invoking
-			 * the handler() function, which means we need to
-			 * globally mask the specific IRQ:
-			 */
-			spin_unlock(&ide_lock);
-			hwif  = HWIF(drive);
-#if DISABLE_IRQ_NOSYNC
-			disable_irq_nosync(hwif->irq);
-#else
-			/* disable_irq_nosync ?? */
-			disable_irq(hwif->irq);
-#endif /* DISABLE_IRQ_NOSYNC */
-			/* local CPU only,
-			 * as if we were handling an interrupt */
-			local_irq_disable();
-			if (hwgroup->poll_timeout != 0) {
-				startstop = handler(drive);
-			} else if (drive_is_ready(drive)) {
-				if (drive->waiting_for_dma)
-					(void) hwgroup->hwif->ide_dma_lostirq(drive);
-				(void)ide_ack_intr(hwif);
-				printk("%s: lost interrupt\n", drive->name);
-				startstop = handler(drive);
-			} else {
-				if (drive->waiting_for_dma) {
-					startstop = ide_stopped;
-					ide_dma_timeout_retry(drive);
-				} else
-					startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
-			}
-			set_recovery_timer(hwif);
-			drive->service_time = jiffies - drive->service_start;
-			enable_irq(hwif->irq);
-			spin_lock_irq(&ide_lock);
-			if (startstop == ide_stopped)
-				hwgroup->busy = 0;
-		}
-	}
-	ide_do_request(hwgroup, 0);
-	spin_unlock_irqrestore(&ide_lock, flags);
-}
-
-EXPORT_SYMBOL(ide_timer_expiry);
-
-/*
- * There's nothing really useful we can do with an unexpected interrupt,
- * other than reading the status register (to clear it), and logging it.
- * There should be no way that an irq can happen before we're ready for it,
- * so we needn't worry much about losing an "important" interrupt here.
- *
- * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
- * drive enters "idle", "standby", or "sleep" mode, so if the status looks
- * "good", we just ignore the interrupt completely.
- *
- * This routine assumes __cli() is in effect when called.
- *
- * If an unexpected interrupt happens on irq15 while we are handling irq14
- * and if the two interfaces are "serialized" (CMD640), then it looks like
- * we could screw up by interfering with a new request being set up for irq15.
- *
- * In reality, this is a non-issue.  The new command is not sent unless the
- * drive is ready to accept one, in which case we know the drive is not
- * trying to interrupt us.  And ide_set_handler() is always invoked before
- * completing the issuance of any new drive command, so we will not be
- * accidentally invoked as a result of any valid command completion interrupt.
- *
- */
-static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
-{
-	u8 stat;
-	ide_hwif_t *hwif = hwgroup->hwif;
-
-	/*
-	 * handle the unexpected interrupt
-	 */
-	do {
-		if (hwif->irq == irq) {
-			stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
-			if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
-				/* Try to not flood the console with msgs */
-				static unsigned long last_msgtime, count;
-				++count;
-				if (time_after(jiffies, last_msgtime + HZ)) {
-					last_msgtime = jiffies;
-					printk("%s%s: unexpected interrupt, "
-						"status=0x%02x, count=%ld\n",
-						hwif->name,
-						(hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count);
-				}
-			}
-		}
-	} while ((hwif = hwif->next) != hwgroup->hwif);
-}
-
-/*
- * entry point for all interrupts, caller does __cli() for us
- */
-void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
-	ide_hwif_t *hwif;
-	ide_drive_t *drive;
-	ide_handler_t *handler;
-	ide_startstop_t startstop;
-
-	spin_lock_irqsave(&ide_lock, flags);
-	hwif = hwgroup->hwif;
-
-	if (!ide_ack_intr(hwif)) {
-		spin_unlock_irqrestore(&ide_lock, flags);
-		return;
-	}
-
-	if ((handler = hwgroup->handler) == NULL ||
-	    hwgroup->poll_timeout != 0) {
-		/*
-		 * Not expecting an interrupt from this drive.
-		 * That means this could be:
-		 *	(1) an interrupt from another PCI device
-		 *	sharing the same PCI INT# as us.
-		 * or	(2) a drive just entered sleep or standby mode,
-		 *	and is interrupting to let us know.
-		 * or	(3) a spurious interrupt of unknown origin.
-		 *
-		 * For PCI, we cannot tell the difference,
-		 * so in that case we just ignore it and hope it goes away.
-		 */
-#ifdef CONFIG_BLK_DEV_IDEPCI
-		if (hwif->pci_dev && !hwif->pci_dev->vendor)
-#endif	/* CONFIG_BLK_DEV_IDEPCI */
-		{
-			/*
-			 * Probably not a shared PCI interrupt,
-			 * so we can safely try to do something about it:
-			 */
-			unexpected_intr(irq, hwgroup);
-#ifdef CONFIG_BLK_DEV_IDEPCI
-		} else {
-			/*
-			 * Whack the status register, just in case
-			 * we have a leftover pending IRQ.
-			 */
-			(void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
-#endif /* CONFIG_BLK_DEV_IDEPCI */
-		}
-		spin_unlock_irqrestore(&ide_lock, flags);
-		return;
-	}
-	drive = hwgroup->drive;
-	if (!drive) {
-		/*
-		 * This should NEVER happen, and there isn't much
-		 * we could do about it here.
-		 */
-		spin_unlock_irqrestore(&ide_lock, flags);
-		return;
-	}
-	if (!drive_is_ready(drive)) {
-		/*
-		 * This happens regularly when we share a PCI IRQ with
-		 * another device.  Unfortunately, it can also happen
-		 * with some buggy drives that trigger the IRQ before
-		 * their status register is up to date.  Hopefully we have
-		 * enough advance overhead that the latter isn't a problem.
-		 */
-		spin_unlock_irqrestore(&ide_lock, flags);
-		return;
-	}
-	if (!hwgroup->busy) {
-		hwgroup->busy = 1;	/* paranoia */
-		printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
-	}
-	hwgroup->handler = NULL;
-	del_timer(&hwgroup->timer);
-	spin_unlock(&ide_lock);
-
-	if (drive->unmask)
-		local_irq_enable();
-	/* service this interrupt, may set handler for next interrupt */
-	startstop = handler(drive);
-	spin_lock_irq(&ide_lock);
-
-	/*
-	 * Note that handler() may have set things up for another
-	 * interrupt to occur soon, but it cannot happen until
-	 * we exit from this routine, because it will be the
-	 * same irq as is currently being serviced here, and Linux
-	 * won't allow another of the same (on any CPU) until we return.
-	 */
-	set_recovery_timer(HWIF(drive));
-	drive->service_time = jiffies - drive->service_start;
-	if (startstop == ide_stopped) {
-		if (hwgroup->handler == NULL) {	/* paranoia */
-			hwgroup->busy = 0;
-			ide_do_request(hwgroup, hwif->irq);
-		} else {
-			printk("%s: ide_intr: huh? expected NULL handler "
-				"on exit\n", drive->name);
-		}
-	}
-	spin_unlock_irqrestore(&ide_lock, flags);
-}
-
-EXPORT_SYMBOL(ide_intr);
-
-/*
- * This function is intended to be used prior to invoking ide_do_drive_cmd().
- */
-void ide_init_drive_cmd (struct request *rq)
-{
-	memset(rq, 0, sizeof(*rq));
-	rq->flags = REQ_DRIVE_CMD;
-}
-
-EXPORT_SYMBOL(ide_init_drive_cmd);
-
-/*
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * If action is ide_wait, then the rq is queued at the end of the
- * request queue, and the function sleeps until it has been processed.
- * This is for use when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of
- * the request queue, displacing the currently-being-processed
- * request and this function returns immediately without waiting
- * for the new rq to be completed.  This is VERY DANGEROUS, and is
- * intended for careful use by the ATAPI tape/cdrom driver code.
- *
- * If action is ide_next, then the rq is queued immediately after
- * the currently-being-processed-request (if any), and the function
- * returns without waiting for the new rq to be completed.  As above,
- * This is VERY DANGEROUS, and is intended for careful use by the
- * ATAPI tape/cdrom driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the
- * request queue, and the function returns immediately without waiting
- * for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code.
- */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
-{
-	unsigned long flags;
-	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	DECLARE_COMPLETION(wait);
-	int insert_end = 1, err;
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-	if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
-		return -ENOSYS;  /* special drive cmds not supported */
-#endif
-	rq->errors = 0;
-	rq->rq_status = RQ_ACTIVE;
-
-	rq->rq_disk = drive->disk;
-
-	/*
-	 * we need to hold an extra reference to request for safe inspection
-	 * after completion
-	 */
-	if (action == ide_wait) {
-		rq->ref_count++;
-		rq->waiting = &wait;
-	}
-
-	spin_lock_irqsave(&ide_lock, flags);
-	if (action == ide_preempt) {
-		hwgroup->rq = NULL;
-		insert_end = 0;
-	}
-	__elv_add_request(&drive->queue, rq, insert_end, 0);
-	ide_do_request(hwgroup, 0);
-	spin_unlock_irqrestore(&ide_lock, flags);
-
-	err = 0;
-	if (action == ide_wait) {
-		wait_for_completion(&wait);
-		if (rq->errors)
-			err = -EIO;
-
-		blk_put_request(rq);
-	}
-
-	return err;
-}
-
-EXPORT_SYMBOL(ide_do_drive_cmd);
 
 void ide_probe_module (void)
 {
@@ -1632,11 +524,18 @@
 #define hwif_release_region(addr, num) \
 	((hwif->mmio) ? release_mem_region((addr),(num)) : release_region((addr),(num)))
 
-/*
- * Note that we only release the standard ports,
- * and do not even try to handle any extra ports
- * allocated for weird IDE interface chipsets.
+/**
+ *	hwif_unregister		-	free IDE resources
+ *
+ *	Note that we only release the standard ports,
+ *	and do not even try to handle any extra ports
+ *	allocated for weird IDE interface chipsets.
+ *
+ *	Note also that we don't yet handle mmio resources here. More
+ *	importantly our caller should be doing this so we need to 
+ *	restructure this as a helper function for drivers.
  */
+ 
 void hwif_unregister (ide_hwif_t *hwif)
 {
 	u32 i = 0;
@@ -1665,6 +564,28 @@
 
 extern void init_hwif_data(unsigned int index);
 
+/**
+ *	ide_unregister		-	free an ide interface
+ *	@index: index of interface (will change soon to a pointer)
+ *
+ *	Perform the final unregister of an IDE interface. At the moment
+ *	we don't refcount interfaces so this will also get split up.
+ *
+ *	Locking:
+ *	The caller must not hold the IDE locks
+ *	The drive present/vanishing is not yet properly locked
+ *	Take care with the callbacks. These have been split to avoid
+ *	deadlocking the IDE layer. The shutdown callback is called
+ *	before we take the lock and free resources. It is up to the
+ *	caller to be sure there is no pending I/O here, and that
+ *	the interfce will not be reopened (present/vanishing locking
+ *	isnt yet done btw). After we commit to the final kill we
+ *	call the cleanup callback with the ide locks held.
+ *
+ *	Unregister restores the hwif structures to the default state.
+ *	This is raving bonkers.
+ */
+ 
 void ide_unregister (unsigned int index)
 {
 	ide_drive_t *drive, *d;
@@ -1675,7 +596,8 @@
 	ide_hwif_t old_hwif;
 
 	if (index >= MAX_HWIFS)
-		return;
+		BUG();
+		
 	spin_lock_irqsave(&ide_lock, flags);
 	hwif = &ide_hwifs[index];
 	if (!hwif->present)
@@ -1686,12 +608,21 @@
 			continue;
 		if (drive->usage)
 			goto abort;
-		if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
+		if (drive->driver != NULL && DRIVER(drive)->shutdown(drive))
 			goto abort;
 	}
 	hwif->present = 0;
 	
 	spin_unlock_irqrestore(&ide_lock, flags);
+
+	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+		drive = &hwif->drives[unit];
+		if (!drive->present)
+			continue;
+		if (drive->driver != NULL)
+			DRIVER(drive)->cleanup(drive);
+	}
+	
 #ifdef CONFIG_PROC_FS
 	destroy_proc_ide_drives(hwif);
 #endif
@@ -1752,7 +683,7 @@
 	else
 		hwgroup->hwif = HWIF(hwgroup->drive);
 
-#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
+#if !defined(CONFIG_DMA_NONPCI)
 	if (hwif->dma_base) {
 		(void) ide_release_dma(hwif);
 
@@ -1764,7 +695,7 @@
 		hwif->dma_vendor3 = 0;
 		hwif->dma_prdtable = 0;
 	}
-#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
+#endif /* !(CONFIG_DMA_NONPCI) */
 
 	/*
 	 * Remove us from the kernel's knowledge
@@ -1894,11 +825,21 @@
 
 EXPORT_SYMBOL(ide_unregister);
 
-/*
- * Setup hw_regs_t structure described by parameters.  You
- * may set up the hw structure yourself OR use this routine to
- * do it for you.
+/**
+ *	ide_setup_ports 	-	set up IDE interface ports
+ *	@hw: register descriptions
+ *	@base: base register
+ *	@offsets: table of register offsets
+ *	@ctrl: control register
+ *	@ack_irq: IRQ ack
+ *	@irq: interrupt lie
+ *
+ *	Setup hw_regs_t structure described by parameters.  You
+ *	may set up the hw structure yourself OR use this routine to
+ *	do it for you. This is basically a helper
+ *
  */
+ 
 void ide_setup_ports (	hw_regs_t *hw,
 			ide_ioreg_t base, int *offsets,
 			ide_ioreg_t ctrl, ide_ioreg_t intr,
@@ -2004,6 +945,27 @@
 
 EXPORT_SYMBOL(ide_register);
 
+/**
+ *	ide_add_setting		-	attach an IDE setting
+ *	drive: drive the setting is for
+ *	name: name of setting
+ *	rw: set if writable
+ *	read_ioctl: read function
+ *	write_ioctl: write function
+ *	data_type: form expected
+ *	min: minimum
+ *	max: maximum
+ *	mul_factor: multiply by
+ *	div_factor: divide by
+ *	data: value
+ *	set: handling for setting
+ *
+ *	Add a setting to the IDE drive. Support automatic removal and allow
+ *	all the work to be done by plugged in handlers. This code is also
+ *	rather short on locking, but the current plan is to do the locking
+ *	internally to the function. 
+ */
+ 
 void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
 {
 	ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
@@ -2038,6 +1000,14 @@
 
 EXPORT_SYMBOL(ide_add_setting);
 
+/**
+ *	ide_remove_setting	-	remove an ioctl setting
+ *	@name:	name of the property
+ *
+ *	Remove a drive ioctl setting that was created by ide_add_setting.
+ *	Again this needs the locking fixed
+ */
+ 
 void ide_remove_setting (ide_drive_t *drive, char *name)
 {
 	ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting;
@@ -2053,6 +1023,16 @@
 
 EXPORT_SYMBOL(ide_remove_setting);
 
+/**
+ *	ide_find_setting_by_ioctl	-	find a setting handler by its command
+ *	@drive: drive to act for
+ *	@cmd: ioctl command code
+ *
+ *	Scan the drive handlers for an ioctl handler for this function.
+ *	The handlers vary by drive and sometimes by drive state. 
+ *	Needs locking fixes.
+ */
+ 
 static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd)
 {
 	ide_settings_t *setting = drive->settings;
@@ -2065,6 +1045,16 @@
 	return setting;
 }
 
+/**
+ *	ide_find_setting_by_name	-	find a setting handler by its name
+ *	@drive: drive to act for
+ *	@cmd: ioctl command code
+ *
+ *	Scan the drive handlers handler matching the name for this function.
+ *	The handlers vary by drive and sometimes by drive state. 
+ *	Needs locking fixes.
+ */
+ 
 ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name)
 {
 	ide_settings_t *setting = drive->settings;
@@ -2077,6 +1067,17 @@
 	return setting;
 }
 
+/**
+ *	auto_remove_settings	-	remove driver settings on a device
+ *	@drive: drive to clean
+ *
+ *	Called when we change the driver bindings for a device, for 
+ *	example if the device is hot plugged. We must scrub the driver
+ *	bindings that are thus no longer relevant to the device in case
+ *	it changes from say a CD-ROM to a disk
+ *	Needs locking fixes
+ */
+ 
 static void auto_remove_settings (ide_drive_t *drive)
 {
 	ide_settings_t *setting;
@@ -2128,7 +1129,7 @@
 		local_irq_set(lflags);
 		if (time_after(jiffies, timeout)) {
 			local_irq_restore(lflags);
-			printk("%s: channel busy\n", drive->name);
+			printk(KERN_ERR "%s: channel busy\n", drive->name);
 			return -EBUSY;
 		}
 		local_irq_restore(lflags);
@@ -2229,8 +1230,7 @@
 			SETFEATURES_XFER, 0, NULL);
 
 	if (!err && arg) {
-		if ((HWIF(drive)->speedproc) != NULL)
-			HWIF(drive)->speedproc(drive, (u8) arg);
+		ide_set_xfer_rate(drive, (u8) arg);
 		ide_driveid_update(drive);
 	}
 	return err;
@@ -2312,7 +1312,7 @@
  */
 int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
 {
-	if (!drive->present || drive->usage)
+	if (!drive->present || drive->usage || drive->dead)
 		goto abort;
 	if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
 		goto abort;
@@ -2487,7 +1487,7 @@
 #if 1
 			spin_lock_irqsave(&ide_lock, flags);
 			if ( HWGROUP(drive)->handler != NULL) {
-				printk("%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler);
+				printk(KERN_ERR "%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler);
 				(void) HWGROUP(drive)->handler(drive);
 //				HWGROUP(drive)->handler = NULL;
 				HWGROUP(drive)->expiry	= NULL;
@@ -2702,7 +1702,7 @@
 	    strncmp(s,"hd",2))		/* hdx= & hdxlun= */
 		return 0;
 
-	printk("ide_setup: %s", s);
+	printk(KERN_INFO "ide_setup: %s", s);
 	init_ide_data ();
 
 #ifdef CONFIG_BLK_DEV_IDEDOUBLER
@@ -3050,18 +2050,6 @@
 		swarm_ide_probe();
 	}
 #endif /* CONFIG_BLK_DEV_IDE_SWARM */
-#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
-	{
-		extern void icside_init(void);
-		icside_init();
-	}
-#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */
-#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
-	{
-		extern void rapide_init(void);
-		rapide_init();
-	}
-#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
 #ifdef CONFIG_BLK_DEV_GAYLE
 	{
 		extern void gayle_init(void);
@@ -3122,21 +2110,39 @@
 #endif
 }
 
-static int default_standby (ide_drive_t *drive)
-{
-	return 0;
-}
-
-static int default_suspend (ide_drive_t *drive)
+/*
+ *	Actually unregister the subdriver. Called with the
+ *	request lock dropped.
+ */
+ 
+static int default_cleanup (ide_drive_t *drive)
 {
-	return 0;
+	return ide_unregister_subdriver(drive);
 }
 
-static int default_resume (ide_drive_t *drive)
+/*
+ *	Check if we can unregister the subdriver. Called with the
+ *	request lock held.
+ */
+ 
+static int default_shutdown(ide_drive_t *drive)
 {
+	if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
+		return 1;
+	}
+	drive->dead = 1;
 	return 0;
 }
 
+/*
+ *	Default function to use for the cache flush operation. This
+ *	must be replaced for disk devices (see ATA specification
+ *	documents on cache flush and drive suspend rules)
+ *
+ *	If we have no device attached or the device is not writable
+ *	this handler is sufficient.
+ */
+ 
 static int default_flushcache (ide_drive_t *drive)
 {
 	return 0;
@@ -3193,9 +2199,8 @@
 {
 	ide_driver_t *d = drive->driver;
 
-	if (d->standby == NULL)		d->standby = default_standby;
-	if (d->suspend == NULL)		d->suspend = default_suspend;
-	if (d->resume == NULL)		d->resume = default_resume;
+	if (d->cleanup == NULL)		d->cleanup = default_cleanup;
+	if (d->shutdown == NULL)	d->shutdown = default_shutdown;
 	if (d->flushcache == NULL)	d->flushcache = default_flushcache;
 	if (d->do_request == NULL)	d->do_request = default_do_request;
 	if (d->end_request == NULL)	d->end_request = default_end_request;
@@ -3213,7 +2218,7 @@
 	
 	spin_lock_irqsave(&ide_lock, flags);
 	if (version != IDE_SUBDRIVER_VERSION || !drive->present ||
-	    drive->driver != NULL || drive->usage) {
+	    drive->driver != NULL || drive->usage || drive->dead) {
 		spin_unlock_irqrestore(&ide_lock, flags);
 		return 1;
 	}
@@ -3274,13 +2279,8 @@
 	ide_drive_t * drive = container_of(dev,ide_drive_t,gendev);
 	ide_driver_t * driver = drive->driver;
 
-	if (driver) {
-		if (driver->standby)
-			driver->standby(drive);
-		if (driver->cleanup)
-			driver->cleanup(drive);
-	}
-	
+	if (driver && driver->cleanup)
+		driver->cleanup(drive);
 	return 0;
 }
 
@@ -3321,7 +2321,7 @@
 	while(!list_empty(&driver->drives)) {
 		drive = list_entry(driver->drives.next, ide_drive_t, list);
 		if (driver->cleanup(drive)) {
-			printk("%s: cleanup_module() called while still busy\n", drive->name);
+			printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
 			BUG();
 		}
 		/* We must remove proc entries defined in this module.
@@ -3395,7 +2395,7 @@
  		if ((next = strchr(line,' ')) != NULL)
 			*next++ = 0;
 		if (!ide_setup(line))
-			printk ("Unknown option '%s'\n", line);
+			printk (KERN_INFO "Unknown option '%s'\n", line);
 	}
 }
 
@@ -3411,10 +2411,10 @@
 
 	for (index = 0; index < MAX_HWIFS; ++index) {
 		ide_unregister(index);
-#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
+#if !defined(CONFIG_DMA_NONPCI)
 		if (ide_hwifs[index].dma_base)
 			(void) ide_release_dma(&ide_hwifs[index]);
-#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */
+#endif /* !(CONFIG_DMA_NONPCI) */
 	}
 
 #ifdef CONFIG_PROC_FS
diff -Nru a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
--- a/drivers/ide/legacy/ide-cs.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/ide/legacy/ide-cs.c	Wed Nov 27 14:36:31 2002
@@ -411,6 +411,8 @@
     DEBUG(0, "ide_release(0x%p)\n", link);
 
     if (info->ndev) {
+	/* FIXME: if this fails we need to queue the cleanup somehow
+	   -- need to investigate the required PCMCIA magic */
 	ide_unregister(info->hd);
 	/* deal with brain dead IDE resource management */
 	request_region(link->io.BasePort1, link->io.NumPorts1,
diff -Nru a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
--- a/drivers/ide/pci/Makefile	Wed Nov 27 14:36:28 2002
+++ b/drivers/ide/pci/Makefile	Wed Nov 27 14:36:28 2002
@@ -5,7 +5,9 @@
 obj-$(CONFIG_BLK_DEV_AMD74XX)		+= amd74xx.o
 obj-$(CONFIG_BLK_DEV_CMD640)		+= cmd640.o
 obj-$(CONFIG_BLK_DEV_CMD64X)		+= cmd64x.o
+obj-$(CONFIG_BLK_DEV_CS5520)		+= cs5520.o
 obj-$(CONFIG_BLK_DEV_CS5530)		+= cs5530.o
+obj-$(CONFIG_BLK_DEV_SC1200)		+= sc1200.o
 obj-$(CONFIG_BLK_DEV_CY82C693)		+= cy82c693.o
 obj-$(CONFIG_BLK_DEV_HPT34X)		+= hpt34x.o
 obj-$(CONFIG_BLK_DEV_HPT366)		+= hpt366.o
diff -Nru a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
--- a/drivers/ide/pci/aec62xx.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/ide/pci/aec62xx.c	Wed Nov 27 14:36:31 2002
@@ -292,7 +292,6 @@
 	}
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
 	u8 speed = ide_dma_speed(drive, aec62xx_ratemask(drive));	
@@ -303,7 +302,6 @@
 	(void) aec62xx_tune_chipset(drive, speed);
 	return ide_dma_enable(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
 {
@@ -321,7 +319,6 @@
 	(void) aec62xx_tune_chipset(drive, speed);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
@@ -405,7 +402,6 @@
 #endif
 	return 0;
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static unsigned int __init init_chipset_aec62xx (struct pci_dev *dev, const char *name)
 {
@@ -457,7 +453,6 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_check	= &aec62xx_config_drive_xfer_rate;
 	hwif->ide_dma_lostirq	= &aec62xx_irq_timeout;
 	hwif->ide_dma_timeout	= &aec62xx_irq_timeout;
@@ -465,7 +460,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void __init init_dma_aec62xx (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h
--- a/drivers/ide/pci/aec62xx.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/pci/aec62xx.h	Wed Nov 27 14:36:30 2002
@@ -14,7 +14,6 @@
 };
 
 struct chipset_bus_clock_list_entry aec6xxx_33_base [] = {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	{	XFER_UDMA_6,	0x31,	0x07	},
 	{	XFER_UDMA_5,	0x31,	0x06	},
 	{	XFER_UDMA_4,	0x31,	0x05	},
@@ -26,7 +25,6 @@
 	{	XFER_MW_DMA_2,	0x31,	0x00	},
 	{	XFER_MW_DMA_1,	0x31,	0x00	},
 	{	XFER_MW_DMA_0,	0x0a,	0x00	},
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	{	XFER_PIO_4,	0x31,	0x00	},
 	{	XFER_PIO_3,	0x33,	0x00	},
 	{	XFER_PIO_2,	0x08,	0x00	},
@@ -36,7 +34,6 @@
 };
 
 struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	{	XFER_UDMA_6,	0x41,	0x06	},
 	{	XFER_UDMA_5,	0x41,	0x05	},
 	{	XFER_UDMA_4,	0x41,	0x04	},
@@ -48,7 +45,6 @@
 	{	XFER_MW_DMA_2,	0x41,	0x00	},
 	{	XFER_MW_DMA_1,	0x42,	0x00	},
 	{	XFER_MW_DMA_0,	0x7a,	0x00	},
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	{	XFER_PIO_4,	0x41,	0x00	},
 	{	XFER_PIO_3,	0x43,	0x00	},
 	{	XFER_PIO_2,	0x78,	0x00	},
diff -Nru a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
--- a/drivers/ide/pci/alim15x3.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/ide/pci/alim15x3.c	Wed Nov 27 14:36:29 2002
@@ -450,7 +450,6 @@
 
 		if (speed < XFER_SW_DMA_0)
 			ali15x3_tune_drive(drive, speed);
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	} else {
 		pci_read_config_byte(dev, m5229_udma, &tmpbyte);
 		tmpbyte &= (0x0f << ((1-unit) << 2));
@@ -464,12 +463,10 @@
 			tmpbyte |= 1;
 			pci_write_config_byte(dev, 0x4b, tmpbyte);
 		}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	}
 	return (ide_config_drive_speed(drive, speed));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 
 /**
  *	config_chipset_for_dma	-	set up DMA mode
@@ -562,7 +559,6 @@
 		return 1;	/* try PIO instead of DMA */
 	return __ide_dma_write(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /**
  *	init_chipset_ali15x3	-	Initialise an ALi IDE controller
@@ -756,7 +752,6 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
         if (m5229_revision >= 0x20) {
                 /*
                  * M1543C or newer for DMAing
@@ -770,7 +765,6 @@
 	}
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 /**
@@ -854,6 +848,12 @@
 static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	ide_pci_device_t *d = &ali15x3_chipsets[id->driver_data];
+	
+	if(pci_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_IGP, NULL))
+	{
+		printk(KERN_ERR "Warning: ATI Radeon IGP Northbridge is not supported by Linux\n");
+		return 1;
+	}
 #if defined(CONFIG_SPARC64)
 	d->init_hwif = init_hwif_common_ali15x3;
 #endif /* CONFIG_SPARC64 */
diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
--- a/drivers/ide/pci/amd74xx.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/ide/pci/amd74xx.c	Wed Nov 27 14:36:32 2002
@@ -148,7 +148,6 @@
 	pio_timing	&= ~(0x03 << drive->dn);
 
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_7:
 		case XFER_UDMA_6:
 			speed = XFER_UDMA_5;
@@ -194,7 +193,6 @@
 		case XFER_SW_DMA_0:
 			dma_pio_timing |= 0xA8;
 			break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:
 			dma_pio_timing |= 0x20;
 			break;
@@ -215,9 +213,7 @@
 
 	pio_timing |= (0x03 << drive->dn);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing);
 	pci_write_config_byte(dev, 0x4c, pio_timing);
 
@@ -230,7 +226,6 @@
 	(void) amd74xx_tune_chipset(drive, (XFER_PIO_0 + pio));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 /*
  * This allows the configuration of ide_pci chipset registers
  * for cards that learn about the drive's UDMA, DMA, PIO capabilities
@@ -290,14 +285,11 @@
 	}
 	return hwif->ide_dma_on(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static unsigned int __init init_chipset_amd74xx (struct pci_dev *dev, const char *name)
 {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (!amd74xx_swdma_check(dev))
 		printk("%s: disabling single-word DMA support (revision < C4)\n", name);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS)
 	if (!amd74xx_proc) {
@@ -348,11 +340,7 @@
 		default:
 			break;
 	}
-#ifdef CONFIG_AMD74XX_OVERRIDE
-	return(1);
-#else
 	return (unsigned int) ata66;
-#endif /* CONFIG_AMD74XX_OVERRIDE */
 }
 
 static void __init init_hwif_amd74xx (ide_hwif_t *hwif)
@@ -373,7 +361,6 @@
 	if (amd74xx_swdma_check(hwif->pci_dev))
 		hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (!(hwif->udma_four))
 		hwif->udma_four = ata66_amd74xx(hwif);
 	hwif->ide_dma_check = &amd74xx_config_drive_xfer_rate;
@@ -381,7 +368,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void __init init_dma_amd74xx (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
--- a/drivers/ide/pci/cmd640.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/ide/pci/cmd640.c	Wed Nov 27 14:36:31 2002
@@ -751,7 +751,7 @@
 	 */
 	put_cmd640_reg(0x5b, 0xbd);
 	if (get_cmd640_reg(0x5b) != 0xbd) {
-		printk("ide: cmd640 init failed: wrong value in reg 0x5b\n");
+		printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n");
 		return 0;
 	}
 	put_cmd640_reg(0x5b, 0);
@@ -836,7 +836,7 @@
 		cmd_hwif1->tuneproc = &cmd640_tune_drive;
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 	}
-	printk("%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
+	printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
 		cmd_hwif0->serialized ? "" : "not ", port2);
 
 	/*
diff -Nru a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
--- a/drivers/ide/pci/cmd64x.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/ide/pci/cmd64x.c	Wed Nov 27 14:36:31 2002
@@ -383,18 +383,15 @@
 
 static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	u8 unit			= (drive->select.b.unit & 0x01);
 	u8 regU = 0, pciU	= (hwif->channel) ? UDIDETCR1 : UDIDETCR0;
 	u8 regD = 0, pciD	= (hwif->channel) ? BMIDESR1 : BMIDESR0;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	u8 speed	= ide_rate_filter(cmd64x_ratemask(drive), xferspeed);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (speed > XFER_PIO_4) {
 		(void) pci_read_config_byte(dev, pciD, &regD);
 		(void) pci_read_config_byte(dev, pciU, &regU);
@@ -405,10 +402,8 @@
 		(void) pci_read_config_byte(dev, pciD, &regD);
 		(void) pci_read_config_byte(dev, pciU, &regU);
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_5:	regU |= (unit ? 0x0A : 0x05); break;
 		case XFER_UDMA_4:	regU |= (unit ? 0x4A : 0x15); break;
 		case XFER_UDMA_3:	regU |= (unit ? 0x8A : 0x25); break;
@@ -421,7 +416,6 @@
 		case XFER_SW_DMA_2:	regD |= (unit ? 0x40 : 0x10); break;
 		case XFER_SW_DMA_1:	regD |= (unit ? 0x80 : 0x20); break;
 		case XFER_SW_DMA_0:	regD |= (unit ? 0xC0 : 0x30); break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:	cmd64x_tuneproc(drive, 4); break;
 		case XFER_PIO_3:	cmd64x_tuneproc(drive, 3); break;
 		case XFER_PIO_2:	cmd64x_tuneproc(drive, 2); break;
@@ -432,29 +426,26 @@
 			return 1;
 	}
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (speed > XFER_PIO_4) {
 		(void) pci_write_config_byte(dev, pciU, regU);
 		regD |= (unit ? 0x40 : 0x20);
 		(void) pci_write_config_byte(dev, pciD, regD);
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	return (ide_config_drive_speed(drive, speed));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
 	u8 speed	= ide_dma_speed(drive, cmd64x_ratemask(drive));
 
-	config_chipset_for_pio(drive, (!(speed)));
+	config_chipset_for_pio(drive, !speed);
 
-	if ((!(speed)))
+	if (!speed)
 		return 0;
 
-	if (HWIF(drive)->speedproc(drive, speed))
-		return 0;
+	if(ide_set_xfer_rate(drive, speed))
+		return 0; 
 
 	if (!drive->init_speed)
 		drive->init_speed = speed;
@@ -593,7 +584,6 @@
 	/* verify good DMA status */
 	return (dma_stat & 7) != 4;
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static unsigned int __init init_chipset_cmd64x (struct pci_dev *dev, const char *name)
 {
@@ -732,7 +722,6 @@
 	if (dev->device == PCI_DEVICE_ID_CMD_648)
 		hwif->ultra_mask = 0x1f;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_check = &cmd64x_config_drive_for_dma;
 	if (!(hwif->udma_four))
 		hwif->udma_four = ata66_cmd64x(hwif);
@@ -755,7 +744,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void __init init_dma_cmd64x (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/pci/cs5520.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,323 @@
+/*
+ *	IDE tuning and bus mastering support for the CS5510/CS5520
+ *	chipsets
+ *
+ *	The CS5510/CS5520 are slightly unusual devices. Unlike the 
+ *	typical IDE controllers they do bus mastering with the drive in
+ *	PIO mode and smarter silicon.
+ *
+ *	The practical upshot of this is that we must always tune the
+ *	drive for the right PIO mode. We must also ignore all the blacklists
+ *	and the drive bus mastering DMA information.
+ *
+ *	*** This driver is strictly experimental ***
+ *
+ *	(c) Copyright Red Hat Inc 2002
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * 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.
+ *
+ * For the avoidance of doubt the "preferred form" of this code is one which
+ * is in an open non patent encumbered format. Where cryptographic key signing
+ * forms part of the process of creating an executable the information
+ * including keys needed to generate an equivalently functional executable
+ * are deemed to be part of the source code.
+ *
+ */
+ 
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+#include "cs5520.h"
+
+#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static u8 cs5520_proc = 0;
+static struct pci_dev *bmide_dev;
+
+static int cs5520_get_info(char *buffer, char **addr, off_t offset, int count)
+{
+	char *p = buffer;
+	unsigned long bmiba = pci_resource_start(bmide_dev, 2);
+	u8 c0 = 0, c1 = 0;
+	u16 reg16;
+	u32 reg32;
+
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
+	c0 = inb((unsigned short)bmiba + 0x02);
+	c1 = inb((unsigned short)bmiba + 0x0a);
+	
+	p += sprintf(p, "\nCyrix CS55x0 IDE\n");
+	p += sprintf(p, "--------------- Primary Channel "
+			"---------------- Secondary Channel "
+			"-------------\n");
+	p += sprintf(p, "                %sabled "
+			"                        %sabled\n",
+			(c0&0x80) ? "dis" : " en",
+			(c1&0x80) ? "dis" : " en");
+			
+	p += sprintf(p, "\n\nTimings: \n");
+	
+	pci_read_config_word(bmide_dev, 0x62, &reg16);
+	p += sprintf(p, "8bit CAT/CRT   : %04x\n", reg16);
+	pci_read_config_dword(bmide_dev, 0x64, &reg32);
+	p += sprintf(p, "16bit Primary  : %08x\n", reg32);
+	pci_read_config_dword(bmide_dev, 0x68, &reg32);
+	p += sprintf(p, "16bit Secondary: %08x\n", reg32);
+	
+	return p-buffer;
+}
+
+#endif
+
+struct pio_clocks
+{
+	int address;
+	int assert;
+	int recovery;
+};
+
+struct pio_clocks cs5520_pio_clocks[]={
+	{3, 6, 11},
+	{2, 5, 6},
+	{1, 4, 3},
+	{1, 3, 2},
+	{1, 2, 1}
+};
+
+static int cs5520_tune_chipset(ide_drive_t *drive, u8 xferspeed)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *pdev = hwif->pci_dev;
+	u8 speed = min((u8)XFER_PIO_4, xferspeed);
+	int pio = speed;
+	u8 reg;
+	int controller = drive->dn > 1 ? 1 : 0;
+	int error;
+	
+	switch(speed)
+	{
+		case XFER_PIO_4:
+		case XFER_PIO_3:
+		case XFER_PIO_2:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+			pio -= XFER_PIO_0;
+			break;
+		default:
+			pio = 0;
+			printk(KERN_ERR "cs55x0: bad ide timing.\n");
+	}
+	
+	printk("PIO clocking = %d\n", pio);
+	
+	/* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
+	
+	/* 8bit command timing for channel */
+	pci_write_config_byte(pdev, 0x62 + controller, 
+		(cs5520_pio_clocks[pio].recovery << 4) |
+		(cs5520_pio_clocks[pio].assert));
+		
+	/* FIXME: should these use address ? */
+	/* Data read timing */
+	pci_write_config_byte(pdev, 0x64 + 4*controller + (drive->dn&1),
+		(cs5520_pio_clocks[pio].recovery << 4) |
+		(cs5520_pio_clocks[pio].assert));
+	/* Write command timing */
+	pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1),
+		(cs5520_pio_clocks[pio].recovery << 4) |
+		(cs5520_pio_clocks[pio].assert));
+		
+	/* Set the DMA enable/disable flag */
+	reg = inb(hwif->dma_base + 0x02 + 8*controller);
+	reg |= 1<<((drive->dn&1)+5);
+	outb(reg, hwif->dma_base + 0x02 + 8*controller);
+		
+	error = ide_config_drive_speed(drive, speed);
+	/* ATAPI is harder so leave it for now */
+	if(!error && drive->media == ide_disk)
+		error = hwif->ide_dma_on(drive);
+}	
+	
+static void cs5520_tune_drive(ide_drive_t *drive, u8 pio)
+{
+	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	cs5520_tune_chipset(drive, (XFER_PIO_0 + pio));
+}
+
+static int cs5520_config_drive_xfer_rate(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+
+	/* Tune the drive for PIO modes up to PIO 4 */	
+	cs5520_tune_drive(drive, 4);
+	/* Then tell the core to use DMA operations */
+	return hwif->ide_dma_on(drive);
+}
+	
+	
+static unsigned int __devinit init_chipset_cs5520(struct pci_dev *dev, const char *name)
+{
+#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS)
+	if (!cs5520_proc) {
+		cs5520_proc = 1;
+		bmide_dev = dev;
+		ide_pci_register_host_proc(&cs5520_procs[0]);
+	}
+#endif /* DISPLAY_CS5520_TIMINGS && CONFIG_PROC_FS */
+	return 0;
+}
+
+/*
+ *	We provide a callback for our nonstandard DMA location
+ */
+
+static void __devinit cs5520_init_setup_dma(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *hwif)
+{
+	u32 bmide = pci_resource_start(dev, 2);	/* Not the usual 4 */
+	if(hwif->mate && hwif->mate->dma_base)	/* Second channel at primary + 8 */
+		bmide += 8;
+	ide_setup_dma(hwif, bmide, 8);
+}
+
+/*
+ *	We wrap the DMA activate to set the vdma flag. This is needed
+ *	so that the IDE DMA layer issues PIO not DMA commands over the
+ *	DMA channel
+ */
+ 
+static int cs5520_dma_on(ide_drive_t *drive)
+{
+	drive->vdma = 1;
+	return 0;
+}
+
+static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
+{
+	hwif->tuneproc = &cs5520_tune_drive;
+	hwif->speedproc = &cs5520_tune_chipset;
+	hwif->ide_dma_check = &cs5520_config_drive_xfer_rate;
+	hwif->ide_dma_on = &cs5520_dma_on;
+
+	if(!noautodma)
+		hwif->autodma = 1;
+	
+	if(!hwif->dma_base)
+	{
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+		return;
+	}
+	
+	hwif->atapi_dma = 0;
+	hwif->ultra_mask = 0;
+	hwif->swdma_mask = 0;
+	hwif->mwdma_mask = 0;
+	
+	hwif->drives[0].autodma = hwif->autodma;
+	hwif->drives[1].autodma = hwif->autodma;
+}
+		
+/*
+ *	The 5510/5520 are a bit weird. They don't quite set up the way
+ *	the PCI helper layer expects so we must do much of the set up 
+ *	work longhand.
+ */
+ 
+static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	ata_index_t index;
+	ide_pci_device_t *d = &cyrix_chipsets[id->driver_data];
+	
+	ide_setup_pci_noise(dev, d);	
+	
+	/* We must not grab the entire device, it has 'ISA' space in its
+	   BARS too and we will freak out other bits of the kernel */
+	if(pci_enable_device_bars(dev, 1<<2))
+	{
+		printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
+		return 1;
+	}
+	pci_set_master(dev);
+	pci_set_dma_mask(dev, 0xFFFFFFFF);
+	init_chipset_cs5520(dev, d->name);	
+	
+	index.all = 0xf0f0;
+
+	/*
+	 *	Now the chipset is configured we can let the core
+	 *	do all the device setup for us
+	 */
+	 	
+	ide_pci_setup_ports(dev, d, 1, 14, &index);
+
+	printk("Index.b %d %d\n", index.b.low, index.b.high);
+	mdelay(2000);
+	if((index.b.low & 0xf0) != 0xf0)
+		probe_hwif_init(&ide_hwifs[index.b.low]);
+	if((index.b.high & 0xf0) != 0xf0)
+		probe_hwif_init(&ide_hwifs[index.b.high]);
+		
+	return 0;
+}
+
+static struct pci_device_id cs5520_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ 0, },
+};
+
+static struct pci_driver driver = {
+	.name		= "CyrixIDE",
+	.id_table	= cs5520_pci_tbl,
+	.probe		= cs5520_init_one,
+};
+
+static int cs5520_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+static void cs5520_ide_exit(void)
+{
+	return ide_pci_unregister_driver(&driver);
+}
+
+module_init(cs5520_ide_init);
+module_exit(cs5520_ide_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("PCI driver module for Cyrix 5510/5520 IDE");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
+
diff -Nru a/drivers/ide/pci/cs5520.h b/drivers/ide/pci/cs5520.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/pci/cs5520.h	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,66 @@
+#ifndef CS5520_H
+#define CS5520_H
+
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#define DISPLAY_CS5520_TIMINGS
+
+#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static u8 cs5520_proc;
+
+static int cs5520_get_info(char *, char **, off_t, int);
+
+static ide_pci_host_proc_t cs5520_procs[] __initdata = {
+	{
+		name:		"cs5520",
+		set:		1,
+		get_info:	cs5520_get_info,
+		parent:		NULL,
+	},
+};
+#endif  /* defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+static unsigned int init_chipset_cs5520(struct pci_dev *, const char *);
+static void init_hwif_cs5520(ide_hwif_t *);
+static void cs5520_init_setup_dma(struct pci_dev *dev, struct ide_pci_device_s *d, ide_hwif_t *hwif);
+
+static ide_pci_device_t cyrix_chipsets[] __devinitdata = {
+	{
+		vendor:		PCI_VENDOR_ID_CYRIX,
+		device:		PCI_DEVICE_ID_CYRIX_5510,
+		name:		"Cyrix 5510",
+		init_chipset:	init_chipset_cs5520,
+		init_setup_dma: cs5520_init_setup_dma,
+		init_iops:	NULL,
+		init_hwif:	init_hwif_cs5520,
+		isa_ports:	1,
+		channels:	2,
+		autodma:	AUTODMA,
+		bootable:	ON_BOARD,
+		extra:		0,
+	},
+	{
+		vendor:		PCI_VENDOR_ID_CYRIX,
+		device:		PCI_DEVICE_ID_CYRIX_5520,
+		name:		"Cyrix 5520",
+		init_chipset:	init_chipset_cs5520,
+		init_setup_dma: cs5520_init_setup_dma,
+		init_iops:	NULL,
+		init_hwif:	init_hwif_cs5520,
+		isa_ports:	1,
+		channels:	2,
+		autodma:	AUTODMA,
+		bootable:	ON_BOARD,
+		extra:		0,
+	}
+};
+
+
+#endif /* CS5520_H */
+
+
diff -Nru a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
--- a/drivers/ide/pci/cs5530.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/ide/pci/cs5530.c	Wed Nov 27 14:36:28 2002
@@ -135,8 +135,6 @@
 	}
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
-
 /**
  *	cs5530_config_dma	-	select/set DMA and UDMA modes
  *	@drive: drive to tune
@@ -256,7 +254,6 @@
 	 */
 	return hwif->ide_dma_on(drive);	/* success */
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /**
  *	init_chipset_5530	-	set up 5530 bridge
@@ -396,13 +393,11 @@
 	hwif->ultra_mask = 0x07;
 	hwif->mwdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_check = &cs5530_config_dma;
 	if (!noautodma)
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 /**
diff -Nru a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
--- a/drivers/ide/pci/cy82c693.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/ide/pci/cy82c693.c	Wed Nov 27 14:36:28 2002
@@ -123,10 +123,10 @@
 	p_pclk->time_8 = (u8)clk1;
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 /*
  * set DMA mode a specific channel for CY82C693
  */
+
 static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
 {
 	u8 index = 0, data = 0;
@@ -213,7 +213,6 @@
 	}
         return __ide_dma_on(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /*
  * tune ide drive - set PIO mode
@@ -405,13 +404,11 @@
 	hwif->mwdma_mask = 0x04;
 	hwif->swdma_mask = 0x04;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_on = &cy82c693_ide_dma_on;
 	if (!noautodma)
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static __initdata ide_hwif_t *primary;
diff -Nru a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
--- a/drivers/ide/pci/generic.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/pci/generic.c	Wed Nov 27 14:36:30 2002
@@ -50,12 +50,10 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (!noautodma)
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void init_dma_generic (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
--- a/drivers/ide/pci/hpt34x.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/ide/pci/hpt34x.c	Wed Nov 27 14:36:29 2002
@@ -159,13 +159,13 @@
 	(void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 /*
  * This allows the configuration of ide_pci chipset registers
  * for cards that learn about the drive's UDMA, DMA, PIO capabilities
  * after the drive is reported by the OS.  Initally for designed for
  * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc.
  */
+
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
 	u8 speed = ide_dma_speed(drive, hpt34x_ratemask(drive));
@@ -224,7 +224,6 @@
 #endif /* CONFIG_HPT34X_AUTODMA */
 	return hwif->ide_dma_on(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /*
  * If the BIOS does not set the IO base addaress to XX00, 343 will fail.
@@ -306,13 +305,11 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_check = &hpt34x_config_drive_xfer_rate;
 	if (!noautodma)
 		hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void __init init_dma_hpt34x (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
--- a/drivers/ide/pci/hpt366.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/pci/hpt366.c	Wed Nov 27 14:36:30 2002
@@ -216,7 +216,6 @@
 
 static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
 {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	struct pci_dev *dev	= HWIF(drive)->pci_dev;
 	u8 mode			= hpt3xx_ratemask(drive);
 
@@ -264,9 +263,6 @@
 			break;
 	}
 	return speed;
-#else
-	return min(speed, (u8)XFER_PIO_4);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static int check_in_drive_lists (ide_drive_t *drive, const char **list)
@@ -297,7 +293,7 @@
 {
 	struct pci_dev *dev	= HWIF(drive)->pci_dev;
 	u8 speed		= hpt3xx_ratefilter(drive, xferspeed);
-//	u8 speed	= ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
+//	u8 speed		= ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
 	u8 regtime		= (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
 	u8 regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;
 	u8 drive_fast		= 0;
@@ -444,7 +440,6 @@
 	(void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 /*
  * This allows the configuration of ide_pci chipset registers
  * for cards that learn about the drive's UDMA, DMA, PIO capabilities
@@ -654,7 +649,6 @@
 		pci_write_config_byte(dev, mscreg, msc_stat|0x30);
 	return __ide_dma_end(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /*
  * Since SUN Cobalt is attempting to do this operation, I should disclose
@@ -1030,7 +1024,6 @@
 	hwif->ultra_mask = 0x7f;
 	hwif->mwdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (!(hwif->udma_four))
 		hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
 	hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
@@ -1053,7 +1046,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void __init init_dma_hpt366 (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/it8172.c b/drivers/ide/pci/it8172.c
--- a/drivers/ide/pci/it8172.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/ide/pci/it8172.c	Wed Nov 27 14:36:31 2002
@@ -151,7 +151,6 @@
      */
     
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_4:
 		case XFER_UDMA_2:	//u_speed = 2 << (drive->dn * 4); break;
 		case XFER_UDMA_5:
@@ -162,7 +161,6 @@
 		case XFER_MW_DMA_1:
 		case XFER_MW_DMA_0:
 		case XFER_SW_DMA_2:	break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:
 		case XFER_PIO_3:
 		case XFER_PIO_2:
@@ -183,7 +181,6 @@
 	return (ide_config_drive_speed(drive, speed));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int it8172_config_chipset_for_dma (ide_drive_t *drive)
 {
 	u8 speed = ide_dma_speed(drive, it8172_ratemask(drive));
@@ -239,7 +236,6 @@
 	}
 	return hwif->ide_dma_on(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static unsigned int __init init_chipset_it8172 (struct pci_dev *dev, const char *name)
 {
@@ -282,13 +278,11 @@
 	hwif->mwdma_mask = 0x06;
 	hwif->swdma_mask = 0x04;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_check = &it8172_config_drive_xfer_rate;
 	if (!noautodma)
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void __init init_dma_it8172 (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
--- a/drivers/ide/pci/ns87415.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/pci/ns87415.c	Wed Nov 27 14:36:30 2002
@@ -83,7 +83,6 @@
 	ns87415_prepare_drive (drive, drive->using_dma);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int ns87415_ide_dma_end (ide_drive_t *drive)
 {
 	ide_hwif_t      *hwif = HWIF(drive);
@@ -132,7 +131,6 @@
 		return HWIF(drive)->ide_dma_off_quietly(drive);
 	return __ide_dma_check(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static void __init init_hwif_ns87415 (ide_hwif_t *hwif)
 {
@@ -209,7 +207,6 @@
 	if (!hwif->dma_base)
 		return;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->OUTB(0x60, hwif->dma_status);
 	hwif->ide_dma_read = &ns87415_ide_dma_read;
 	hwif->ide_dma_write = &ns87415_ide_dma_write;
@@ -220,7 +217,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void __init init_dma_ns87415 (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/nvidia.c b/drivers/ide/pci/nvidia.c
--- a/drivers/ide/pci/nvidia.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/ide/pci/nvidia.c	Wed Nov 27 14:36:32 2002
@@ -38,7 +38,7 @@
 static int nforce_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	u32 bibma = pci_resource_start(bmide_dev, 4);
+	unsigned long bibma = pci_resource_start(bmide_dev, 4);
 	u8 c0 = 0, c1 = 0;
 
 	/*
@@ -109,7 +109,6 @@
 	pio_timing	&= ~(0x03 << drive->dn);
 
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_7:
 		case XFER_UDMA_6:
 			speed = XFER_UDMA_5;
@@ -155,7 +154,6 @@
 		case XFER_SW_DMA_0:
 			dma_pio_timing |= 0xA8;
 			break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:
 			dma_pio_timing |= 0x20;
 			break;
@@ -176,9 +174,7 @@
 
 	pio_timing |= (0x03 << drive->dn);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing);
 	pci_write_config_byte(dev, 0x5c, pio_timing);
 
@@ -191,7 +187,6 @@
 	(void) nforce_tune_chipset(drive, (XFER_PIO_0 + pio));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 /*
  * This allows the configuration of ide_pci chipset registers
  * for cards that learn about the drive's UDMA, DMA, PIO capabilities
@@ -251,9 +246,8 @@
 	}
 	return hwif->ide_dma_on(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
-unsigned int __init init_chipset_nforce (struct pci_dev *dev, const char *name)
+static unsigned int __init init_chipset_nforce (struct pci_dev *dev, const char *name)
 {
 #if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS)
 	if (!nforce_proc) {
@@ -318,7 +312,6 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (!(hwif->udma_four))
 		hwif->udma_four = ata66_nforce(hwif);
 	hwif->ide_dma_check = &nforce_config_drive_xfer_rate;
@@ -326,7 +319,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 /* FIXME - not needed */
diff -Nru a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
--- a/drivers/ide/pci/opti621.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/ide/pci/opti621.c	Wed Nov 27 14:36:29 2002
@@ -343,13 +343,10 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (!noautodma)
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
 }
 
 static void __init init_dma_opti621 (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
--- a/drivers/ide/pci/pdc202xx_new.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/ide/pci/pdc202xx_new.c	Wed Nov 27 14:36:31 2002
@@ -165,7 +165,6 @@
 			pci_read_config_byte(dev, (drive_pci), &AP);
 			pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
 		}
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	} else {
 		if ((BP & 0xF0) && (CP & 0x0F)) {
 			/* clear DMA modes of upper 842 bits of B Register */
@@ -177,7 +176,6 @@
 			pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F);
 			pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
 		}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	}
 
 	pci_read_config_byte(dev, (drive_pci), &AP);
@@ -185,7 +183,6 @@
 	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
 
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_6:	speed = XFER_UDMA_5;
 		case XFER_UDMA_5:
 		case XFER_UDMA_4:	TB = 0x20; TC = 0x01; break;
@@ -199,7 +196,6 @@
 		case XFER_SW_DMA_2:	TB = 0x60; TC = 0x05; break;
 		case XFER_SW_DMA_1:	TB = 0x80; TC = 0x06; break;
 		case XFER_SW_DMA_0:	TB = 0xC0; TC = 0x0B; break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:	TA = 0x01; TB = 0x04; break;
 		case XFER_PIO_3:	TA = 0x02; TB = 0x06; break;
 		case XFER_PIO_2:	TA = 0x03; TB = 0x08; break;
@@ -211,11 +207,9 @@
 	if (speed < XFER_SW_DMA_0) {
 		pci_write_config_byte(dev, (drive_pci), AP|TA);
 		pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	} else {
 		pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
 		pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	}
 
 #if PDC202XX_DECODE_REGISTER_INFO
@@ -243,28 +237,18 @@
 static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	u32 indexreg		= hwif->dma_vendor1;
 	u32 datareg		= hwif->dma_vendor3;
-#else /* !CONFIG_BLK_DEV_IDEDMA */
-	struct pci_dev *dev	= hwif->pci_dev;
-	u32 high_16		= pci_resource_start(dev, 4);
-	u32 indexreg		= high_16 + (hwif->channel ? 0x09 : 0x01);
-	u32 datareg		= (indexreg + 2);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	u8 thold		= 0x10;
 	u8 adj			= (drive->dn%2) ? 0x08 : 0x00;
 	u8 speed	= ide_rate_filter(pdcnew_ratemask(drive), xferspeed);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (speed == XFER_UDMA_2) {
 		hwif->OUTB((thold + adj), indexreg);
 		hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg);
 	}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	switch (speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_7:
 			speed = XFER_UDMA_6;
 		case XFER_UDMA_6:	set_ultra(0x1a, 0x01, 0xcb); break;
@@ -277,7 +261,6 @@
 		case XFER_MW_DMA_2:	set_ata2(0x69, 0x25); break;
 		case XFER_MW_DMA_1:	set_ata2(0x6b, 0x27); break;
 		case XFER_MW_DMA_0:	set_ata2(0xdf, 0x5f); break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:	set_pio(0x23, 0x09, 0x25); break;
 		case XFER_PIO_3:	set_pio(0x27, 0x0d, 0x35); break;
 		case XFER_PIO_2:	set_pio(0x23, 0x26, 0x64); break;
@@ -301,7 +284,7 @@
 {
 	u8 speed = 0;
 
-	pio = (pio == 5) ? 4 : pio;
+	if (pio == 5) pio = 4;
 	speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
         
 	return ((int) pdcnew_tune_chipset(drive, speed));
@@ -312,8 +295,6 @@
 	(void) config_chipset_for_pio(drive, pio);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
-
 static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif)
 {
 	hwif->OUTB(0x0b, hwif->dma_vendor1);
@@ -458,8 +439,6 @@
 	return __ide_dma_timeout(drive);
 }
 
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
 static void pdcnew_new_reset (ide_drive_t *drive)
 {
 	/*
@@ -471,12 +450,8 @@
 
 static void pdcnew_reset_host (ide_hwif_t *hwif)
 {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 //	unsigned long high_16	= hwif->dma_base - (8*(hwif->channel));
 	unsigned long high_16	= hwif->dma_master;
-#else /* !CONFIG_BLK_DEV_IDEDMA */
-	unsigned long high_16	= pci_resource_start(hwif->pci_dev, 4);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	u8 udma_speed_flag	= hwif->INB(high_16|0x001f);
 
 	hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f));
@@ -571,8 +546,6 @@
 	hwif->ultra_mask = 0x7f;
 	hwif->mwdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
-
 	hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
 	hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq;
 	hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout;
@@ -581,7 +554,6 @@
 	if (!noautodma)
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 #if PDC202_DEBUG_CABLE
 	printk("%s: %s-pin cable\n",
 		hwif->name, hwif->udma_four ? "80" : "40");
diff -Nru a/drivers/ide/pci/pdc202xx_new.h b/drivers/ide/pci/pdc202xx_new.h
--- a/drivers/ide/pci/pdc202xx_new.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/ide/pci/pdc202xx_new.h	Wed Nov 27 14:36:27 2002
@@ -26,41 +26,6 @@
 	NULL
 };
 
-static inline u8 *pdcnew_pio_verbose (u32 drive_pci)
-{
-	if ((drive_pci & 0x000ff000) == 0x000ff000) return("NOTSET");
-	if ((drive_pci & 0x00000401) == 0x00000401) return("PIO 4");
-	if ((drive_pci & 0x00000602) == 0x00000602) return("PIO 3");
-	if ((drive_pci & 0x00000803) == 0x00000803) return("PIO 2");
-	if ((drive_pci & 0x00000C05) == 0x00000C05) return("PIO 1");
-	if ((drive_pci & 0x00001309) == 0x00001309) return("PIO 0");
-	return("PIO ?");
-}
-
-static inline u8 *pdcnew_dma_verbose (u32 drive_pci)
-{
-	if ((drive_pci & 0x00036000) == 0x00036000) return("MWDMA 2");
-	if ((drive_pci & 0x00046000) == 0x00046000) return("MWDMA 1");
-	if ((drive_pci & 0x00056000) == 0x00056000) return("MWDMA 0");
-	if ((drive_pci & 0x00056000) == 0x00056000) return("SWDMA 2");
-	if ((drive_pci & 0x00068000) == 0x00068000) return("SWDMA 1");
-	if ((drive_pci & 0x000BC000) == 0x000BC000) return("SWDMA 0");
-	return("PIO---");
-}
-
-static inline u8 *pdcnew_ultra_verbose (u32 drive_pci, u16 slow_cable)
-{
-	if ((drive_pci & 0x000ff000) == 0x000ff000)
-		return("NOTSET");
-	if ((drive_pci & 0x00012000) == 0x00012000)
-		return((slow_cable) ? "UDMA 2" : "UDMA 4");
-	if ((drive_pci & 0x00024000) == 0x00024000)
-		return((slow_cable) ? "UDMA 1" : "UDMA 3");
-	if ((drive_pci & 0x00036000) == 0x00036000)
-		return("UDMA 0");
-	return(pdcnew_dma_verbose(drive_pci));
-}
-
 /* A Register */
 #define	SYNC_ERRDY_EN	0xC0
 
diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
--- a/drivers/ide/pci/pdc202xx_old.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/ide/pci/pdc202xx_old.c	Wed Nov 27 14:36:32 2002
@@ -264,7 +264,6 @@
 			pci_read_config_byte(dev, (drive_pci), &AP);
 			pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
 		}
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	} else {
 		if ((BP & 0xF0) && (CP & 0x0F)) {
 			/* clear DMA modes of upper 842 bits of B Register */
@@ -276,7 +275,6 @@
 			pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F);
 			pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
 		}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	}
 
 	pci_read_config_byte(dev, (drive_pci), &AP);
@@ -284,7 +282,6 @@
 	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
 
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_6:	speed = XFER_UDMA_5;
 		case XFER_UDMA_5:
 		case XFER_UDMA_4:	TB = 0x20; TC = 0x01; break;
@@ -298,7 +295,6 @@
 		case XFER_SW_DMA_2:	TB = 0x60; TC = 0x05; break;
 		case XFER_SW_DMA_1:	TB = 0x80; TC = 0x06; break;
 		case XFER_SW_DMA_0:	TB = 0xC0; TC = 0x0B; break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:	TA = 0x01; TB = 0x04; break;
 		case XFER_PIO_3:	TA = 0x02; TB = 0x06; break;
 		case XFER_PIO_2:	TA = 0x03; TB = 0x08; break;
@@ -310,11 +306,9 @@
 	if (speed < XFER_SW_DMA_0) {
 		pci_write_config_byte(dev, (drive_pci), AP|TA);
 		pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	} else {
 		pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
 		pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	}
 
 #if PDC202XX_DECODE_REGISTER_INFO
@@ -347,23 +341,16 @@
  * 180, 120,  90,  90,  90,  60,  30
  *  11,   5,   4,   3,   2,   1,   0
  */
-static int config_chipset_for_pio (ide_drive_t *drive, u8 pio)
+static void config_chipset_for_pio (ide_drive_t *drive, u8 pio)
 {
 	u8 speed = 0;
 
-	pio = (pio == 5) ? 4 : pio;
+	if (pio == 5) pio = 4;
 	speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
         
-	return ((int) pdc202xx_tune_chipset(drive, speed));
+	pdc202xx_tune_chipset(drive, speed);
 }
 
-static void pdc202xx_tune_drive (ide_drive_t *drive, u8 pio)
-{
-	(void) config_chipset_for_pio(drive, pio);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-
 static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
 {
 	u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
@@ -618,8 +605,6 @@
 	return __ide_dma_timeout(drive);
 }
 
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
 static void pdc202xx_reset_host (ide_hwif_t *hwif)
 {
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -692,12 +677,8 @@
 static int pdc202xx_tristate (ide_drive_t * drive, int state)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-#ifdef CONFIG_BLK_DEV_IDEDMA
 //	unsigned long high_16	= hwif->dma_base - (8*(hwif->channel));
 	unsigned long high_16	= hwif->dma_master;
-#else /* !CONFIG_BLK_DEV_IDEDMA */
-	unsigned long high_16	= pci_resource_start(hwif->pci_dev, 4);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	u8 sc1f			= hwif->INB(high_16|0x001f);
 
 	if (!hwif)
@@ -761,7 +742,7 @@
 static void __init init_hwif_pdc202xx (ide_hwif_t *hwif)
 {
 	hwif->autodma = 0;
-	hwif->tuneproc  = &pdc202xx_tune_drive;
+	hwif->tuneproc  = &config_chipset_for_pio;
 	hwif->quirkproc = &pdc202xx_quirkproc;
 
 	if (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20265)
@@ -783,8 +764,6 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
-
 	hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate;
 	hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq;
 	hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout;
@@ -800,7 +779,6 @@
 	if (!noautodma)
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 #if PDC202_DEBUG_CABLE
 	printk("%s: %s-pin cable\n",
 		hwif->name, hwif->udma_four ? "80" : "40");
diff -Nru a/drivers/ide/pci/pdcadma.c b/drivers/ide/pci/pdcadma.c
--- a/drivers/ide/pci/pdcadma.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/ide/pci/pdcadma.c	Wed Nov 27 14:36:31 2002
@@ -55,7 +55,6 @@
 }
 #endif  /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 /*
  * pdcadma_dma functions() initiates/aborts (U)DMA read/write
  * operations on a drive.
@@ -81,8 +80,6 @@
         int (*ide_dma_timeout)(ide_drive_t *drive);
 
 #endif
-
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static unsigned int __init init_chipset_pdcadma (struct pci_dev *dev, const char *name)
 {
diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
--- a/drivers/ide/pci/piix.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/ide/pci/piix.c	Wed Nov 27 14:36:27 2002
@@ -373,7 +373,7 @@
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
-	u8 speed	= ide_rate_filter(piix_ratemask(drive), xferspeed);
+	u8 speed		= ide_rate_filter(piix_ratemask(drive), xferspeed);
 	int a_speed		= 3 << (drive->dn * 4);
 	int u_flag		= 1 << drive->dn;
 	int v_flag		= 0x01 << drive->dn;
@@ -392,7 +392,6 @@
 	pci_read_config_byte(dev, 0x55, &reg55);
 
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_4:
 		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
 		case XFER_UDMA_5:
@@ -402,7 +401,6 @@
 		case XFER_MW_DMA_2:
 		case XFER_MW_DMA_1:
 		case XFER_SW_DMA_2:	break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:
 		case XFER_PIO_3:
 		case XFER_PIO_2:
@@ -444,8 +442,6 @@
 	return (ide_config_drive_speed(drive, speed));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
-
 /**
  *	piix_config_drive_for_dma	-	configure drive for DMA
  *	@drive: IDE drive to configure
@@ -518,7 +514,6 @@
 	}
 	return hwif->ide_dma_on(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /**
  *	init_chipset_piix	-	set up the PIIX chipset
@@ -570,10 +565,8 @@
  
 static void __init init_hwif_piix (ide_hwif_t *hwif)
 {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	u8 reg54h = 0, reg55h = 0, ata66 = 0;
 	u8 mask = hwif->channel ? 0xc0 : 0x30;
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
 
 #ifndef CONFIG_IA64
 	if (!hwif->irq)
@@ -599,7 +592,6 @@
 	hwif->mwdma_mask = 0x06;
 	hwif->swdma_mask = 0x04;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	switch(hwif->pci_dev->device) {
 		case PCI_DEVICE_ID_INTEL_82371MX:
 			hwif->mwdma_mask = 0x80;
@@ -630,7 +622,6 @@
 
 	hwif->drives[1].autodma = hwif->autodma;
 	hwif->drives[0].autodma = hwif->autodma;
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
 }
 
 /**
diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/pci/sc1200.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,593 @@
+/*
+ * linux/drivers/ide/sc1200.c		Version 0.9	24-Oct-2002
+ *
+ * Copyright (C) 2000-2002		Mark Lord <mlord@pobox.com>
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ * Development of this chipset driver was funded
+ * by the nice folks at National Semiconductor.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+#include "sc1200.h"
+
+#define DISPLAY_SC1200_TIMINGS
+
+#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static int sc1200_get_info(char *, char **, off_t, int);
+extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+static u8 sc1200_proc = 0;
+
+#define SC1200_REV_A	0x00
+#define SC1200_REV_B1	0x01
+#define SC1200_REV_B3	0x02
+#define SC1200_REV_C1	0x03
+#define SC1200_REV_D1	0x04
+
+#define PCI_CLK_33	0x00
+#define PCI_CLK_48	0x01
+#define PCI_CLK_66	0x02
+#define PCI_CLK_33A	0x03
+
+static unsigned short sc1200_get_pci_clock (void)
+{
+	unsigned char chip_id, silicon_revision;
+	unsigned int pci_clock;
+	/*
+	 * Check the silicon revision, as not all versions of the chip
+	 * have the register with the fast PCI bus timings.
+	 */
+	chip_id = inb (0x903c);
+	silicon_revision = inb (0x903d);
+
+	// Read the fast pci clock frequency
+	if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) {
+		pci_clock = PCI_CLK_33;
+	} else {
+		// check clock generator configuration (cfcc)
+		// the clock is in bits 8 and 9 of this word
+
+		pci_clock = inw (0x901e);
+		pci_clock >>= 8;
+		pci_clock &= 0x03;
+		if (pci_clock == PCI_CLK_33A)
+			pci_clock = PCI_CLK_33;
+	}
+	return pci_clock;
+}
+
+static struct pci_dev *bmide_dev;
+
+static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+	char *p = buffer;
+	u32 bibma = pci_resource_start(bmide_dev, 4);
+	u8  c0 = 0, c1 = 0;
+
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
+
+	c0 = inb_p((unsigned short)bibma + 0x02);
+	c1 = inb_p((unsigned short)bibma + 0x0a);
+
+	p += sprintf(p, "\n                               National SCx200 Chipset.\n");
+	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+	p += sprintf(p, "                %sabled                         %sabled\n",
+			(c0&0x80) ? "dis" : " en",
+			(c1&0x80) ? "dis" : " en");
+	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
+			(c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
+			(c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
+
+	p += sprintf(p, "UDMA\n");
+	p += sprintf(p, "DMA\n");
+	p += sprintf(p, "PIO\n");
+
+	return p-buffer;
+}
+#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/*
+ * Set a new transfer mode at the drive
+ */
+int sc1200_set_xfer_mode (ide_drive_t *drive, byte mode)
+{
+	printk("%s: sc1200_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode));
+	return ide_config_drive_speed(drive, mode);
+}
+
+/*
+ * Here are the standard PIO mode 0-4 timings for each "format".
+ * Format-0 uses fast data reg timings, with slower command reg timings.
+ * Format-1 uses fast timings for all registers, but won't work with all drives.
+ */
+static const unsigned int sc1200_pio_timings[4][5] =
+	{{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},	// format0  33Mhz
+	 {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010},	// format1, 33Mhz
+	 {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021},	// format1, 48Mhz
+	 {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}};	// format1, 66Mhz
+
+/*
+ * After chip reset, the PIO timings are set to 0x00009172, which is not valid.
+ */
+//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172)
+
+static int sc1200_autoselect_dma_mode (ide_drive_t *drive)
+{
+	int			udma_ok = 1, mode = 0;
+	ide_hwif_t		*hwif = HWIF(drive);
+	int			unit = drive->select.b.unit;
+	ide_drive_t		*mate = &hwif->drives[unit^1];
+	struct hd_driveid	*id = drive->id;
+
+	/*
+	 * The SC1200 specifies that two drives sharing a cable cannot
+	 * mix UDMA/MDMA.  It has to be one or the other, for the pair,
+	 * though different timings can still be chosen for each drive.
+	 * We could set the appropriate timing bits on the fly,
+	 * but that might be a bit confusing.  So, for now we statically
+	 * handle this requirement by looking at our mate drive to see
+	 * what it is capable of, before choosing a mode for our own drive.
+	 */
+	if (mate->present) {
+		struct hd_driveid *mateid = mate->id;
+		if (mateid && (mateid->capability & 1) && !hwif->ide_dma_bad_drive(mate)) {
+			if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+				udma_ok = 1;
+			else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+				udma_ok = 0;
+			else
+				udma_ok = 1;
+		}
+	}
+	/*
+	 * Now see what the current drive is capable of,
+	 * selecting UDMA only if the mate said it was ok.
+	 */
+	if (id && (id->capability & 1) && hwif->autodma && !hwif->ide_dma_bad_drive(drive)) {
+		if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
+			if      (id->dma_ultra & 4)
+				mode = XFER_UDMA_2;
+			else if (id->dma_ultra & 2)
+				mode = XFER_UDMA_1;
+			else if (id->dma_ultra & 1)
+				mode = XFER_UDMA_0;
+		}
+		if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
+			if      (id->dma_mword & 4)
+				mode = XFER_MW_DMA_2;
+			else if (id->dma_mword & 2)
+				mode = XFER_MW_DMA_1;
+			else if (id->dma_mword & 1)
+				mode = XFER_MW_DMA_0;
+		}
+	}
+	return mode;
+}
+
+/*
+ * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes
+ * for both the chipset and drive.
+ */
+static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
+{
+	ide_hwif_t		*hwif = HWIF(drive);
+	int			unit = drive->select.b.unit;
+	unsigned int		reg, timings;
+	unsigned short		pci_clock;
+	unsigned int		basereg = hwif->channel ? 0x50 : 0x40;
+
+	/*
+	 * Default to DMA-off in case we run into trouble here.
+	 */
+	hwif->ide_dma_off_quietly(drive);			/* turn off DMA while we fiddle */
+	outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
+
+	/*
+	 * Tell the drive to switch to the new mode; abort on failure.
+	 */
+	if (!mode || sc1200_set_xfer_mode(drive, mode)) {
+		printk("SC1200: set xfer mode failure\n");
+		return 1;	/* failure */
+	}
+
+	pci_clock = sc1200_get_pci_clock();
+
+	/*
+	 * Now tune the chipset to match the drive:
+	 *
+	 * Note that each DMA mode has several timings associated with it.
+	 * The correct timing depends on the fast PCI clock freq.
+	 */
+	timings = 0;
+	switch (mode) {
+		case XFER_UDMA_0:
+			switch (pci_clock) {
+				case PCI_CLK_33:	timings = 0x00921250;	break;
+				case PCI_CLK_48:	timings = 0x00932470;	break;
+				case PCI_CLK_66:	timings = 0x009436a1;	break;
+			}
+			break;
+		case XFER_UDMA_1:
+			switch (pci_clock) {
+				case PCI_CLK_33:	timings = 0x00911140;	break;
+				case PCI_CLK_48:	timings = 0x00922260;	break;
+				case PCI_CLK_66:	timings = 0x00933481;	break;
+			}
+			break;
+		case XFER_UDMA_2:
+			switch (pci_clock) {
+				case PCI_CLK_33:	timings = 0x00911030;	break;
+				case PCI_CLK_48:	timings = 0x00922140;	break;
+				case PCI_CLK_66:	timings = 0x00923261;	break;
+			}
+			break;
+		case XFER_MW_DMA_0:
+			switch (pci_clock) {
+				case PCI_CLK_33:	timings = 0x00077771;	break;
+				case PCI_CLK_48:	timings = 0x000bbbb2;	break;
+				case PCI_CLK_66:	timings = 0x000ffff3;	break;
+			}
+			break;
+		case XFER_MW_DMA_1:
+			switch (pci_clock) {
+				case PCI_CLK_33:	timings = 0x00012121;	break;
+				case PCI_CLK_48:	timings = 0x00024241;	break;
+				case PCI_CLK_66:	timings = 0x00035352;	break;
+			}
+			break;
+		case XFER_MW_DMA_2:
+			switch (pci_clock) {
+				case PCI_CLK_33:	timings = 0x00002020;	break;
+				case PCI_CLK_48:	timings = 0x00013131;	break;
+				case PCI_CLK_66:	timings = 0x00015151;	break;
+			}
+			break;
+	}
+
+	if (timings == 0) {
+		printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock);
+		return 1;	/* failure */
+	}
+
+	if (unit == 0) {			/* are we configuring drive0? */
+		pci_read_config_dword(hwif->pci_dev, basereg+4, &reg);
+		timings |= reg & 0x80000000;	/* preserve PIO format bit */
+		pci_write_config_dword(hwif->pci_dev, basereg+4, timings);
+	} else {
+		pci_write_config_dword(hwif->pci_dev, basereg+12, timings);
+	}
+
+	outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2);	/* set DMA_capable bit */
+
+	/*
+	 * Finally, turn DMA on in software, and exit.
+	 */
+	return hwif->ide_dma_on(drive);	/* success */
+}
+
+/*
+ * sc1200_config_dma() handles selection/setting of DMA/UDMA modes
+ * for both the chipset and drive.
+ */
+static int sc1200_config_dma (ide_drive_t *drive)
+{
+	return sc1200_config_dma2(drive, sc1200_autoselect_dma_mode(drive));
+}
+
+
+/*  Replacement for the standard ide_dma_end action in
+ *  dma_proc.
+ *
+ *  returns 1 on error, 0 otherwise
+ */
+int sc1200_ide_dma_end (ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long dma_base = hwif->dma_base;
+	byte dma_stat;
+
+	dma_stat = inb(dma_base+2);		/* get DMA status */
+
+	if (!(dma_stat & 4))
+		printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n",
+		  dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2));
+
+	outb(dma_stat|0x1b, dma_base+2);	/* clear the INTR & ERROR bits */
+	outb(inb(dma_base)&~1, dma_base);	/* !! DO THIS HERE !! stop DMA */
+
+	drive->waiting_for_dma = 0;
+	ide_destroy_dmatable(drive);		/* purge DMA mappings */
+
+	return (dma_stat & 7) != 4;		/* verify good DMA status */
+}
+
+/*
+ * sc1200_tuneproc() handles selection/setting of PIO modes
+ * for both the chipset and drive.
+ *
+ * All existing BIOSs for this chipset guarantee that all drives
+ * will have valid default PIO timings set up before we get here.
+ */
+static void sc1200_tuneproc (ide_drive_t *drive, byte pio)	/* mode=255 means "autotune" */
+{
+	ide_hwif_t	*hwif = HWIF(drive);
+	unsigned int	format;
+	static byte	modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
+	int		mode = -1;
+
+	switch (pio) {
+		case 200: mode = XFER_UDMA_0;	break;
+		case 201: mode = XFER_UDMA_1;	break;
+		case 202: mode = XFER_UDMA_2;	break;
+		case 100: mode = XFER_MW_DMA_0;	break;
+		case 101: mode = XFER_MW_DMA_1;	break;
+		case 102: mode = XFER_MW_DMA_2;	break;
+	}
+	if (mode != -1) {
+		printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
+		(void)sc1200_config_dma2(drive, mode);
+		return;
+	}
+
+	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio);
+	if (!sc1200_set_xfer_mode(drive, modes[pio])) {
+		unsigned int basereg = hwif->channel ? 0x50 : 0x40;
+		pci_read_config_dword (hwif->pci_dev, basereg+4, &format);
+		format = (format >> 31) & 1;
+		if (format)
+			format += sc1200_get_pci_clock();
+		pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]);
+ 	}
+}
+
+static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev)
+{
+	int	h;
+
+	for (h = 0; h < MAX_HWIFS; h++) {
+		ide_hwif_t *hwif = &ide_hwifs[h];
+		if (prev) {
+			if (hwif == prev)
+				prev = NULL;	// found previous, now look for next match
+		} else {
+			if (hwif && hwif->pci_dev == dev)
+				return hwif;	// found next match
+		}
+	}
+	return NULL;	// not found
+}
+
+typedef struct sc1200_saved_state_s {
+	__u32		regs[4];
+} sc1200_saved_state_t;
+
+static int sc1200_save_state (struct pci_dev *dev, u32 state)
+{
+	ide_hwif_t		*hwif = NULL;
+
+printk("SC1200: save_state(%u)\n", state);
+	if (state != 0)
+		return 0;	// we only save state when going from full power to less
+	//
+	// Loop over all interfaces that are part of this PCI device:
+	//
+	while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
+		sc1200_saved_state_t	*ss;
+		unsigned int		basereg, r;
+		//
+		// allocate a permanent save area, if not already allocated
+		//
+		ss = (sc1200_saved_state_t *)hwif->config_data;
+		if (ss == NULL) {
+			ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
+			if (ss == NULL)
+				return -ENOMEM;
+			(sc1200_saved_state_t *)hwif->config_data = ss;
+		}
+		ss = (sc1200_saved_state_t *)hwif->config_data;
+		//
+		// Save timing registers:  this may be unnecessary if BIOS also does it
+		//
+		basereg = hwif->channel ? 0x50 : 0x40;
+		for (r = 0; r < 4; ++r) {
+			pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]);
+		}
+	}
+	return 0;
+}
+
+static int sc1200_suspend (struct pci_dev *dev, u32 state)
+{
+	ide_hwif_t	*hwif = NULL;
+
+	printk("SC1200: suspend(%u)\n", state);
+	/* You don't need to iterate over disks -- sysfs should have done that for you already */ 
+
+	pci_disable_device(dev);
+	pci_set_power_state(dev,state);
+	dev->current_state = state;
+	return 0;
+}
+
+static int sc1200_resume (struct pci_dev *dev)
+{
+	ide_hwif_t	*hwif = NULL;
+
+printk("SC1200: resume\n");
+	pci_set_power_state(dev,0);	// bring chip back from sleep state
+	dev->current_state = 0;
+	pci_enable_device(dev);
+	//
+	// loop over all interfaces that are part of this pci device:
+	//
+	while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
+		unsigned int		basereg, r, d, format;
+		sc1200_saved_state_t	*ss = (sc1200_saved_state_t *)hwif->config_data;
+printk("%s: SC1200: resume\n", hwif->name);
+
+		//
+		// Restore timing registers:  this may be unnecessary if BIOS also does it
+		//
+		basereg = hwif->channel ? 0x50 : 0x40;
+		if (ss != NULL) {
+			for (r = 0; r < 4; ++r) {
+				pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]);
+			}
+		}
+		//
+		// Re-program drive PIO modes
+		//
+		pci_read_config_dword(hwif->pci_dev, basereg+4, &format);
+		format = (format >> 31) & 1;
+		if (format)
+			format += sc1200_get_pci_clock();
+		for (d = 0; d < 2; ++d) {
+			ide_drive_t *drive = &(hwif->drives[d]);
+			if (drive->present) {
+				unsigned int pio, timings;
+				pci_read_config_dword(hwif->pci_dev, basereg+(drive->select.b.unit << 3), &timings);
+				for (pio = 0; pio <= 4; ++pio) {
+					if (sc1200_pio_timings[format][pio] == timings)
+						break;
+				}
+				if (pio > 4)
+					pio = 255; /* autotune */
+				(void)sc1200_tuneproc(drive, pio);
+			}
+		}
+		//
+		// Re-program drive DMA modes
+		//
+		for (d = 0; d < MAX_DRIVES; ++d) {
+			ide_drive_t *drive = &(hwif->drives[d]);
+			if (drive->present && !hwif->ide_dma_bad_drive(drive)) {
+				int was_using_dma = drive->using_dma;
+				hwif->ide_dma_off_quietly(drive);
+				sc1200_config_dma(drive);
+				if (!was_using_dma && drive->using_dma) {
+					hwif->ide_dma_off_quietly(drive);
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+/*
+ * Initialize the sc1200 bridge for reliable IDE DMA operation.
+ */
+static unsigned int __init init_chipset_sc1200 (struct pci_dev *dev, const char *name)
+{
+#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
+	if (!bmide_dev) {
+		sc1200_proc = 1;
+		bmide_dev = dev;
+		ide_pci_register_host_proc(&sc1200_procs[0]);
+	}
+#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
+	return 0;
+}
+
+/*
+ * This gets invoked by the IDE driver once for each channel,
+ * and performs channel-specific pre-initialization before drive probing.
+ */
+static void __init init_hwif_sc1200 (ide_hwif_t *hwif)
+{
+	if (hwif->mate)
+		hwif->serialized = hwif->mate->serialized = 1;
+	hwif->autodma = 0;
+	if (hwif->dma_base) {
+		hwif->ide_dma_check = &sc1200_config_dma;
+		hwif->ide_dma_end   = &sc1200_ide_dma_end;
+        	if (!noautodma)
+                	hwif->autodma = 1;
+		hwif->tuneproc = &sc1200_tuneproc;
+	}
+        hwif->atapi_dma = 1;
+        hwif->ultra_mask = 0x07;
+        hwif->mwdma_mask = 0x07;
+
+        hwif->drives[0].autodma = hwif->autodma;
+        hwif->drives[1].autodma = hwif->autodma;
+}
+
+static void __init init_dma_sc1200 (ide_hwif_t *hwif, unsigned long dmabase)
+{
+	ide_setup_dma(hwif, dmabase, 8);
+}
+
+extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+
+static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	ide_pci_device_t *d = &sc1200_chipsets[id->driver_data];
+	if (dev->device != d->device)
+		BUG();
+	ide_setup_pci_device(dev, d);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static struct pci_device_id sc1200_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ 0, },
+};
+
+static struct pci_driver driver = {
+	.name		= "SC1200 IDE",
+	.id_table	= sc1200_pci_tbl,
+	.probe		= sc1200_init_one,
+	.save_state	= sc1200_save_state,
+	.suspend	= sc1200_suspend,
+	.resume		= sc1200_resume,
+};
+
+static int sc1200_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+static void sc1200_ide_exit(void)
+{
+	ide_pci_unregister_driver(&driver);
+}
+
+module_init(sc1200_ide_init);
+module_exit(sc1200_ide_exit);
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
diff -Nru a/drivers/ide/pci/sc1200.h b/drivers/ide/pci/sc1200.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/pci/sc1200.h	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,54 @@
+#ifndef SC1200_H
+#define SC1200_H
+
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#define DISPLAY_SC1200_TIMINGS
+
+#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static u8 sc1200_proc;
+
+static int sc1200_get_info(char *, char **, off_t, int);
+
+static ide_pci_host_proc_t sc1200_procs[] __initdata = {
+	{
+		name:		"sc1200",
+		set:		1,
+		get_info:	sc1200_get_info,
+		parent:		NULL,
+	},
+};
+#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
+
+static unsigned int init_chipset_sc1200(struct pci_dev *, const char *);
+static void init_hwif_sc1200(ide_hwif_t *);
+static void init_dma_sc1200(ide_hwif_t *, unsigned long);
+
+static ide_pci_device_t sc1200_chipsets[] __devinitdata = {
+	{	/* 0 */
+		vendor:		PCI_VENDOR_ID_NS,
+		device:		PCI_DEVICE_ID_NS_SCx200_IDE,
+		name:		"SC1200",
+		init_chipset:	init_chipset_sc1200,
+		init_iops:	NULL,
+		init_hwif:	init_hwif_sc1200,
+		init_dma:	init_dma_sc1200,
+		channels:	2,
+		autodma:	AUTODMA,
+		enablebits:	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+		bootable:	ON_BOARD,
+		extra:		0,
+	},{
+		vendor:		0,
+		device:		0,
+		channels:	0,
+		bootable:	EOL,
+	}
+};
+
+#endif /* SC1200_H */
diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
--- a/drivers/ide/pci/serverworks.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/ide/pci/serverworks.c	Wed Nov 27 14:36:27 2002
@@ -251,7 +251,7 @@
 
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
-	u8 speed	= ide_rate_filter(svwks_ratemask(drive), xferspeed);
+	u8 speed		= ide_rate_filter(svwks_ratemask(drive), xferspeed);
 	u8 pio			= ide_get_best_pio_mode(drive, 255, 5, NULL);
 	u8 unit			= (drive->select.b.unit & 0x01);
 	u8 csb5			= svwks_csb_check(dev);
@@ -259,6 +259,13 @@
 	u8 dma_timing		= 0, pio_timing = 0;
 	u16 csb5_pio		= 0;
 
+	/* If we are about to put a disk into UDMA mode we screwed up.
+	   Our code assumes we never _ever_ do this on an OSB4 */
+	   
+	if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 &&
+		drive->media == ide_disk && speed >= XFER_UDMA_0)
+			BUG();
+			
 	pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing);
 	pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing);
 	pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
@@ -331,7 +338,6 @@
 			csb5_pio   |= ((speed - XFER_PIO_0) << (4*drive->dn));
 			break;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_MW_DMA_2:
 		case XFER_MW_DMA_1:
 		case XFER_MW_DMA_0:
@@ -351,7 +357,6 @@
 			dma_timing   |= dma_modes[2];
 			ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
 			ultra_enable |= (0x01 << drive->dn);
-#endif
 		default:
 			break;
 	}
@@ -360,11 +365,9 @@
 	if (csb5)
 		pci_write_config_word(dev, 0x4A, csb5_pio);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing);
 	pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing);
 	pci_write_config_byte(dev, 0x54, ultra_enable);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	return (ide_config_drive_speed(drive, speed));
 }
@@ -412,7 +415,6 @@
 	(void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
 	u8 speed = ide_dma_speed(drive, svwks_ratemask(drive));
@@ -470,6 +472,12 @@
 
 static int svwks_ide_dma_end (ide_drive_t *drive)
 {
+	/*
+	 *	We never place the OSB4 into a UDMA mode with a disk
+	 *	medium, that means the UDMA "all my data is 4 byte shifted"
+	 *	problem cannot occur.
+	 */
+#if 0
 	ide_hwif_t *hwif	= HWIF(drive);
 	u8 dma_stat		= hwif->INB(hwif->dma_status);
 
@@ -483,9 +491,9 @@
 		while(1)
 			cpu_relax();
 	}
+#endif	
 	return __ide_dma_end(drive);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static unsigned int __init init_chipset_svwks (struct pci_dev *dev, const char *name)
 {
@@ -703,7 +711,6 @@
 		return;
 	}
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
 	if (hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
 		hwif->ide_dma_end = &svwks_ide_dma_end;
@@ -719,7 +726,6 @@
 	hwif->drives[1].autotune = (!(dma_stat & 0x40));
 //	hwif->drives[0].autodma = hwif->autodma;
 //	hwif->drives[1].autodma = hwif->autodma;
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
 }
 
 /*
diff -Nru a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
--- a/drivers/ide/pci/siimage.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/ide/pci/siimage.c	Wed Nov 27 14:36:29 2002
@@ -205,7 +205,6 @@
 			siimage_tuneproc(drive, (speed - XFER_PIO_0));
 			mode |= ((unit) ? 0x10 : 0x01);
 			break;
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_MW_DMA_2:
 		case XFER_MW_DMA_1:
 		case XFER_MW_DMA_0:
@@ -226,7 +225,6 @@
 			mode |= ((unit) ? 0x30 : 0x03);
 			config_siimage_chipset_for_pio(drive, 0);
 			break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		default:
 			return 1;
 	}
@@ -246,7 +244,6 @@
 	return (ide_config_drive_speed(drive, speed));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
 	u8 speed	= ide_dma_speed(drive, siimage_ratemask(drive));
@@ -256,7 +253,7 @@
 	if ((!(speed)))
 		return 0;
 
-	if (HWIF(drive)->speedproc(drive, speed))
+	if (ide_set_xfer_rate(drive, speed))
 		return 0;
 
 	if (!drive->init_speed)
@@ -392,7 +389,6 @@
 #endif
 	return temp;
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static int siimage_busproc (ide_drive_t * drive, int state)
 {
@@ -811,7 +807,6 @@
 	if (hwif->pci_dev->device != PCI_DEVICE_ID_SII_3112)
 		hwif->atapi_dma = 1;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_check = &siimage_config_drive_for_dma;
 	if (!(hwif->udma_four))
 		hwif->udma_four = ata66_siimage(hwif);
@@ -827,7 +822,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 static void __init init_dma_siimage (ide_hwif_t *hwif, unsigned long dmabase)
diff -Nru a/drivers/ide/pci/siimage.h b/drivers/ide/pci/siimage.h
--- a/drivers/ide/pci/siimage.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/pci/siimage.h	Wed Nov 27 14:36:30 2002
@@ -62,14 +62,14 @@
 //	while (count--) { *(u32 *)addr = readl(port); addr += 4; }
 }
 
-inline void sii_outb (u8 addr, u32 port)
+inline void sii_outb (u8 value, u32 port)
 {
-	writeb(addr, port);
+	writeb(value, port);
 }
 
-inline void sii_outw (u16 addr, u32 port)
+inline void sii_outw (u16 value, u32 port)
 {
-	writew(addr, port);
+	writew(value, port);
 }
 
 inline void sii_outsw (u32 port, void *addr, u32 count)
@@ -77,9 +77,9 @@
 	while (count--) { writew(*(u16 *)addr, port); addr += 2; }
 }
 
-inline void sii_outl (u32 addr, u32 port)
+inline void sii_outl (u32 value, u32 port)
 {
-	writel(addr, port);
+	writel(value, port);
 }
 
 inline void sii_outsl (u32 port, void *addr, u32 count)
diff -Nru a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
--- a/drivers/ide/pci/sis5513.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/ide/pci/sis5513.c	Wed Nov 27 14:36:30 2002
@@ -703,7 +703,6 @@
 
 	/* Config chip for mode */
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_6:
 		case XFER_UDMA_5:
 		case XFER_UDMA_4:
@@ -745,7 +744,6 @@
 		case XFER_SW_DMA_1:
 		case XFER_SW_DMA_0:
 			break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4));
 		case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3));
 		case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2));
@@ -764,7 +762,6 @@
 	(void) config_chipset_for_pio(drive, pio);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 /*
  * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four))
  */
@@ -835,8 +832,6 @@
 	return sis5513_config_drive_xfer_rate(drive);
 }
 
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
 /* Chip detection and general config */
 static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name)
 {
@@ -999,7 +994,6 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (!host_dev)
 		return;
 
@@ -1013,7 +1007,6 @@
 	}
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif
 	return;
 }
 
diff -Nru a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
--- a/drivers/ide/pci/trm290.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/ide/pci/trm290.c	Wed Nov 27 14:36:28 2002
@@ -176,7 +176,6 @@
 	trm290_prepare_drive(drive, drive->using_dma);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int trm290_ide_dma_write (ide_drive_t *drive /*, struct request *rq */)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
@@ -297,7 +296,6 @@
 	status = hwif->INW(hwif->dma_status);
 	return (status == 0x00ff);
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 /*
  * Invoked from ide-dma.c at boot time.
@@ -344,13 +342,11 @@
 
 	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->ide_dma_write = &trm290_ide_dma_write;
 	hwif->ide_dma_read = &trm290_ide_dma_read;
 	hwif->ide_dma_begin = &trm290_ide_dma_begin;
 	hwif->ide_dma_end = &trm290_ide_dma_end;
 	hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	hwif->selectproc = &trm290_selectproc;
 	hwif->autodma = 0;		/* play it safe for now */
diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
--- a/drivers/ide/pci/via82cxxx.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/ide/pci/via82cxxx.c	Wed Nov 27 14:36:27 2002
@@ -383,8 +383,6 @@
 	via_set_drive(drive, XFER_PIO_0 + MIN(pio, 5));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
-
 /**
  *	via82cxxx_ide_dma_check		-	set up for DMA if possible
  *	@drive: IDE drive to set up
@@ -411,8 +409,6 @@
 	return HWIF(drive)->ide_dma_off_quietly(drive);
 }
 
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
 /**
  *	init_chipset_via82cxxx	-	initialization handler
  *	@dev: PCI device
@@ -608,7 +604,6 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (!(hwif->udma_four))
 		hwif->udma_four = ((via_enabled & via_80w) >> hwif->channel) & 1;
 	hwif->ide_dma_check = &via82cxxx_ide_dma_check;
@@ -616,7 +611,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 /**
diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
--- a/drivers/ide/setup-pci.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/ide/setup-pci.c	Wed Nov 27 14:36:29 2002
@@ -10,6 +10,7 @@
  *	Split the set up function into multiple functions
  *	Use pci_set_master
  *	Fix misreporting of I/O v MMIO problems
+ *	Initial fixups for simplex devices
  */
 
 /*
@@ -42,6 +43,8 @@
  *	based on io_base port if possible. Return the matching hwif,
  *	or a new hwif. If we find an error (clashing, out of devices, etc)
  *	return NULL
+ *
+ *	FIXME: we need to handle mmio matches here too
  */
 
 static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name)
@@ -144,34 +147,9 @@
 			return -EOPNOTSUPP;
 		}
 	}
-
-#if 0
-	/*
-	 * At this point we have enabled the device, but may previously
-	 * have done a BAR4 enable alone. We should be prepared to assign
-	 * resources here.
-	 */
-	
-	/*
-	 * Setup base registers for IDE command/control
-	 * spaces for each interface:
-	 */
-	for (reg = 0; reg < 4; reg++) {
-		struct resource *res = dev->resource + reg;
-		if ((res->flags & IORESOURCE_IO) == 0)
-			continue;
-		if (!res->start) {
-			if(pci_assign_resource(dev, reg)) {
-				printk(KERN_ERR "%s: Missing I/O address #%d\n", name, reg);
-				return -ENXIO;
-			}
-		}
-	}
-#endif
 	return 0;
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 #ifdef CONFIG_BLK_DEV_IDEDMA_FORCED
 /*
  * Long lost data from 2.0.34 that is now in 2.0.39
@@ -192,9 +170,6 @@
  *	Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
  *	If need be we set up the DMA base. Where a device has a partner that
  *	is already in DMA mode we check and enforce IDE simplex rules.
- *
- *	FIXME: currently we are sometimes enforicng simplex when it is not
- *	needed. We fail the safe way but why is it occurring ??
  */
 
 static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif)
@@ -274,7 +249,14 @@
 				simplex_stat = hwif->INB(dma_base + 2);
 				if (simplex_stat & 0x80) {
 					/* simplex device? */
-					
+#if 0					
+/*
+ *	At this point we haven't probed the drives so we can't make the
+ *	appropriate decision. Really we should defer this problem
+ *	until we tune the drive then try to grab DMA ownership if we want
+ *	to be the DMA end. This has to be become dynamic to handle hot
+ *	plug.
+ */
 					/* Don't enable DMA on a simplex channel with no drives */
 					if (!hwif->drives[0].present && !hwif->drives[1].present)
 					{
@@ -283,7 +265,9 @@
 						dma_base = 0;
 					}
 					/* If our other channel has DMA then we cannot */
-					else if(hwif->mate && hwif->mate->dma_base) 
+					else 
+#endif					
+					if(hwif->mate && hwif->mate->dma_base) 
 					{
 						printk(KERN_INFO "%s: simplex device: "
 							"DMA disabled\n",
@@ -295,9 +279,8 @@
 	}
 	return dma_base;
 }
-#endif	/* CONFIG_BLK_DEV_IDEDMA */
 
-static void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d)
+void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d)
 {
 	if ((d->vendor != dev->vendor) && (d->device != dev->device)) {
 		printk(KERN_INFO "%s: unknown IDE controller at PCI slot "
@@ -309,6 +292,9 @@
 	}
 }
 
+EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
+
+
 /**
  *	ide_pci_enable	-	do PCI enables
  *	@dev: PCI device
@@ -414,8 +400,7 @@
 			"<andre@linux-ide.org>.\n", d->name);
 	return -EINVAL;
 }
-	
-		
+
 /**
  *	ide_hwif_configure	-	configure an IDE interface
  *	@dev: PCI device holding interface
@@ -434,16 +419,19 @@
 	unsigned long ctl = 0, base = 0;
 	ide_hwif_t *hwif;
 
-	/*  Possibly we should fail if these checks report true */
-	ide_pci_check_iomem(dev, d, 2*port);
-	ide_pci_check_iomem(dev, d, 2*port+1);
+	if(!d->isa_ports)
+	{
+		/*  Possibly we should fail if these checks report true */
+		ide_pci_check_iomem(dev, d, 2*port);
+		ide_pci_check_iomem(dev, d, 2*port+1);
  
-	ctl  = pci_resource_start(dev, 2*port+1);
-	base = pci_resource_start(dev, 2*port);
-	if ((ctl && !base) || (base && !ctl)) {
-		printk(KERN_ERR "%s: inconsistent baseregs (BIOS) "
-			"for port %d, skipping\n", d->name, port);
-		return NULL;
+		ctl  = pci_resource_start(dev, 2*port+1);
+		base = pci_resource_start(dev, 2*port);
+		if ((ctl && !base) || (base && !ctl)) {
+			printk(KERN_ERR "%s: inconsistent baseregs (BIOS) "
+				"for port %d, skipping\n", d->name, port);
+			return NULL;
+		}
 	}
 	if (!ctl)
 	{
@@ -500,8 +488,9 @@
  			 * Set up BM-DMA capability
 			 * (PnP BIOS should have done this)
  			 */
-			if ((d->device != PCI_DEVICE_ID_CYRIX_5530_IDE)
-			    && (d->vendor != PCI_VENDOR_ID_CYRIX)) {
+			if (!((d->device == PCI_DEVICE_ID_CYRIX_5530_IDE && d->vendor == PCI_VENDOR_ID_CYRIX)
+			    ||(d->device == PCI_DEVICE_ID_NS_SCx200_IDE && d->vendor == PCI_VENDOR_ID_NS)))
+			{
 				/*
 				 * default DMA off if we had to
 				 * configure it here
@@ -575,75 +564,33 @@
 	return ret;
 }
 
-/*
- * ide_setup_pci_device() looks at the primary/secondary interfaces
- * on a PCI IDE device and, if they are enabled, prepares the IDE driver
- * for use with them.  This generic code works for most PCI chipsets.
- *
- * One thing that is not standardized is the location of the
- * primary/secondary interface "enable/disable" bits.  For chipsets that
- * we "know" about, this information is in the ide_pci_device_t struct;
- * for all other chipsets, we just assume both interfaces are enabled.
+/**
+ *	ide_pci_setup_ports	-	configure ports/devices on PCI IDE
+ *	@dev: PCI device
+ *	@d: IDE pci device info
+ *	@autodma: Should we enable DMA
+ *	@pciirq: IRQ line
+ *	@index: ata index to update
+ *
+ *	Scan the interfaces attached to this device and do any
+ *	neccessary per port setup. Attach the devices and ask the
+ *	generic DMA layer to do its work for us.
+ *
+ *	Normally called automaticall from do_ide_pci_setup_device,
+ *	but is also used directly as a helper function by some controllers
+ *	where the chipset setup is not the default PCI IDE one.
  */
-static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy)
+ 
+void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int autodma, int pciirq, ata_index_t *index)
 {
-	u32 port, at_least_one_hwif_enabled = 0, autodma = 0;
-	int pciirq = 0;
-	int tried_config = 0;
-	int drive0_tune, drive1_tune;
-	ata_index_t index;
-	u8 tmp = 0;
+	int port;
+	int at_least_one_hwif_enabled = 0;
 	ide_hwif_t *hwif, *mate = NULL;
 	static int secondpdc = 0;
+	int drive0_tune, drive1_tune;
+	u8 tmp;
 
-	index.all = 0xf0f0;
-
-	if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0)
-		return index;
-
-	/*
-	 * Can we trust the reported IRQ?
-	 */
-	pciirq = dev->irq;
-	
-	if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
-		if (noisy)
-			printk(KERN_INFO "%s: not 100%% native mode: "
-				"will probe irqs later\n", d->name);
-		/*
-		 * This allows offboard ide-pci cards the enable a BIOS,
-		 * verify interrupt settings of split-mirror pci-config
-		 * space, place chipset into init-mode, and/or preserve
-		 * an interrupt if the card is not native ide support.
-		 */
-		pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : 0;
-	} else if (tried_config) {
-		if (noisy)
-			printk(KERN_INFO "%s: will probe irqs later\n", d->name);
-		pciirq = 0;
-	} else if (!pciirq) {
-		if (noisy)
-			printk(KERN_WARNING "%s: bad irq (%d): will probe later\n",
-				d->name, pciirq);
-		pciirq = 0;
-	} else {
-		if (d->init_chipset)
-		{
-			if(d->init_chipset(dev, d->name) < 0)
-				return index;
-		}
-		if (noisy)
-#ifdef __sparc__
-			printk(KERN_INFO "%s: 100%% native mode on irq %s\n",
-			       d->name, __irq_itoa(pciirq));
-#else
-			printk(KERN_INFO "%s: 100%% native mode on irq %d\n",
-				d->name, pciirq);
-#endif
-	}
-	
-	if(pciirq < 0)		/* Error not an IRQ */
-		return index;
+	index->all = 0xf0f0;
 
 	/*
 	 * Set up the IDE ports
@@ -671,7 +618,7 @@
 controller_ok:
 
 		if (d->channels	<= port)
-			return index;
+			break;
 	
 		if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL)
 			continue;
@@ -680,25 +627,27 @@
 		hwif->gendev.parent = &dev->dev;
 
 		if (hwif->channel) {
-			index.b.high = hwif->index;
+			index->b.high = hwif->index;
 		} else {
-			index.b.low = hwif->index;
+			index->b.low = hwif->index;
 		}
 
 		
 		if (d->init_iops)
 			d->init_iops(hwif);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		if (d->autodma == NODMA)
 			goto bypass_legacy_dma;
 		if (d->autodma == NOAUTODMA)
 			autodma = 0;
 		if (autodma)
 			hwif->autodma = 1;
-		ide_hwif_setup_dma(dev, d, hwif);
+			
+		if(d->init_setup_dma)
+			d->init_setup_dma(dev, d, hwif);
+		else
+			ide_hwif_setup_dma(dev, d, hwif);
 bypass_legacy_dma:
-#endif	/* CONFIG_BLK_DEV_IDEDMA */
 
 		drive0_tune = hwif->drives[0].autotune;
 		drive1_tune = hwif->drives[1].autotune;
@@ -708,7 +657,13 @@
 			 * for each enabled hwif
 			 */
 			d->init_hwif(hwif);
-		
+
+		/*
+		 *	This is in the wrong place. The driver may
+		 *	do set up based on the autotune value and this
+		 *	will then trash it. Torben please move it and
+		 *	propogate the fixes into the drivers
+		 */		
 		if (drive0_tune == IDE_TUNE_BIOS) /* biostimings */
 			hwif->drives[0].autotune = IDE_TUNE_BIOS;
 		if (drive1_tune == IDE_TUNE_BIOS)
@@ -719,6 +674,76 @@
 	}
 	if (!at_least_one_hwif_enabled)
 		printk(KERN_INFO "%s: neither IDE port enabled (BIOS)\n", d->name);
+}
+
+EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
+
+/*
+ * ide_setup_pci_device() looks at the primary/secondary interfaces
+ * on a PCI IDE device and, if they are enabled, prepares the IDE driver
+ * for use with them.  This generic code works for most PCI chipsets.
+ *
+ * One thing that is not standardized is the location of the
+ * primary/secondary interface "enable/disable" bits.  For chipsets that
+ * we "know" about, this information is in the ide_pci_device_t struct;
+ * for all other chipsets, we just assume both interfaces are enabled.
+ */
+static ata_index_t do_ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d, u8 noisy)
+{
+	int autodma = 0;
+	int pciirq = 0;
+	int tried_config = 0;
+	ata_index_t index = { .b = { .low = 0xff, .high = 0xff } };
+
+	if((autodma = ide_setup_pci_controller(dev, d, noisy, &tried_config)) < 0)
+		return index;
+
+	/*
+	 * Can we trust the reported IRQ?
+	 */
+	pciirq = dev->irq;
+	
+	if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
+		if (noisy)
+			printk(KERN_INFO "%s: not 100%% native mode: "
+				"will probe irqs later\n", d->name);
+		/*
+		 * This allows offboard ide-pci cards the enable a BIOS,
+		 * verify interrupt settings of split-mirror pci-config
+		 * space, place chipset into init-mode, and/or preserve
+		 * an interrupt if the card is not native ide support.
+		 */
+		pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : 0;
+	} else if (tried_config) {
+		if (noisy)
+			printk(KERN_INFO "%s: will probe irqs later\n", d->name);
+		pciirq = 0;
+	} else if (!pciirq) {
+		if (noisy)
+			printk(KERN_WARNING "%s: bad irq (%d): will probe later\n",
+				d->name, pciirq);
+		pciirq = 0;
+	} else {
+		if (d->init_chipset)
+		{
+			if(d->init_chipset(dev, d->name) < 0)
+				return index;
+		}
+		if (noisy)
+#ifdef __sparc__
+			printk(KERN_INFO "%s: 100%% native mode on irq %s\n",
+			       d->name, __irq_itoa(pciirq));
+#else
+			printk(KERN_INFO "%s: 100%% native mode on irq %d\n",
+				d->name, pciirq);
+#endif
+	}
+	
+	if(pciirq < 0)		/* Error not an IRQ */
+		return index;
+
+	ide_pci_setup_ports(dev, d, autodma, pciirq, &index);
+
 	return index;
 }
 
diff -Nru a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
--- a/drivers/input/gameport/fm801-gp.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/input/gameport/fm801-gp.c	Wed Nov 27 14:36:30 2002
@@ -116,7 +116,7 @@
 	gameport_register_port(&gp->gameport);
 
 	printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n",
-		pci->name, pci->slot_name, gp->gameport.speed);
+		pci->dev.name, pci->slot_name, gp->gameport.speed);
 
 	return 0;
 }
diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
--- a/drivers/input/gameport/ns558.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/input/gameport/ns558.c	Wed Nov 27 14:36:31 2002
@@ -236,7 +236,7 @@
 	port->gameport.id.version = 0x100;
 
 	sprintf(port->phys, "isapnp%d.%d/gameport0", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-	sprintf(port->name, "%s", dev->name[0] ? dev->name : "NS558 PnP Gameport");
+	sprintf(port->name, "%s", dev->dev.name[0] ? dev->dev.name : "NS558 PnP Gameport");
 
 	gameport_register_port(&port->gameport);
 
diff -Nru a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c
--- a/drivers/input/gameport/vortex.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/input/gameport/vortex.c	Wed Nov 27 14:36:31 2002
@@ -127,7 +127,7 @@
 	vortex->gameport.cooked_read = vortex_cooked_read;
 	vortex->gameport.open = vortex_open;
 
-	vortex->gameport.name = dev->name;
+	vortex->gameport.name = dev->dev.name;
 	vortex->gameport.phys = vortex->phys;
 	vortex->gameport.id.bustype = BUS_PCI;
 	vortex->gameport.id.vendor = dev->vendor;
@@ -146,7 +146,7 @@
 	gameport_register_port(&vortex->gameport);
 	
 	printk(KERN_INFO "gameport: %s at pci%s speed %d kHz\n",
-		dev->name, dev->slot_name, vortex->gameport.speed);
+		dev->dev.name, dev->slot_name, vortex->gameport.speed);
 
 	return 0;
 }
diff -Nru a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c
--- a/drivers/isdn/act2000/module.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/act2000/module.c	Wed Nov 27 14:36:31 2002
@@ -398,12 +398,6 @@
 				break;
 			chan->l2prot = (c->arg >> 8);
 			return 0;
-		case ISDN_CMD_GETL2:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
-				return -ENODEV;
-			if (!(chan = find_channel(card, c->arg & 0x0f)))
-				break;
-			return chan->l2prot;
 		case ISDN_CMD_SETL3:
 			if (!card->flags & ACT2000_FLAGS_RUNNING)
 				return -ENODEV;
@@ -415,33 +409,6 @@
 				break;
 			chan->l3prot = (c->arg >> 8);
 			return 0;
-		case ISDN_CMD_GETL3:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
-				return -ENODEV;
-			if (!(chan = find_channel(card, c->arg & 0x0f)))
-				break;
-			return chan->l3prot;
-		case ISDN_CMD_GETEAZ:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
-				return -ENODEV;
-			printk(KERN_DEBUG "act2000 CMD_GETEAZ not implemented\n");
-			return 0;
-		case ISDN_CMD_SETSIL:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
-				return -ENODEV;
-			printk(KERN_DEBUG "act2000 CMD_SETSIL not implemented\n");
-			return 0;
-		case ISDN_CMD_GETSIL:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
-				return -ENODEV;
-			printk(KERN_DEBUG "act2000 CMD_GETSIL not implemented\n");
-			return 0;
-		case ISDN_CMD_LOCK:
-			MOD_INC_USE_COUNT;
-			return 0;
-		case ISDN_CMD_UNLOCK:
-			MOD_DEC_USE_COUNT;
-			return 0;
         }
 	
         return -EINVAL;
@@ -620,6 +587,7 @@
 	INIT_WORK(&card->rcv_tq, (void *) (void *) actcapi_dispatch, card);
 	INIT_WORK(&card->poll_tq, (void *) (void *) act2000_receive, card);
 	init_timer(&card->ptimer);
+	SET_MODULE_OWNER(&card->interface);
         card->interface.channels = ACT2000_BCH;
         card->interface.maxbufsize = 4000;
         card->interface.command = if_command;
diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
--- a/drivers/isdn/capi/capi.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/capi/capi.c	Wed Nov 27 14:36:32 2002
@@ -1289,9 +1289,7 @@
 	
 	memset(drv, 0, sizeof(struct tty_driver));
 	drv->magic = TTY_DRIVER_MAGIC;
-#if (LINUX_VERSION_CODE > 0x20100)
 	drv->driver_name = "capi_nc";
-#endif
 	drv->name = "capi/%d";
 	drv->major = capi_ttymajor;
 	drv->minor_start = 0;
@@ -1323,15 +1321,11 @@
 	drv->stop = capinc_tty_stop;
 	drv->start = capinc_tty_start;
 	drv->hangup = capinc_tty_hangup;
-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	drv->break_ctl = capinc_tty_break_ctl;
-#endif
 	drv->flush_buffer = capinc_tty_flush_buffer;
 	drv->set_ldisc = capinc_tty_set_ldisc;
-#if (LINUX_VERSION_CODE >= 131343)
 	drv->send_xchar = capinc_tty_send_xchar;
 	drv->read_proc = capinc_tty_read_proc;
-#endif
 	if (tty_register_driver(drv)) {
 		printk(KERN_ERR "Couldn't register capi_nc driver\n");
 		return -1;
diff -Nru a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
--- a/drivers/isdn/capi/capidrv.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/capi/capidrv.c	Wed Nov 27 14:36:30 2002
@@ -1787,45 +1787,6 @@
 		bchan->msn[0] = 0;
 		return 0;
 
-	case ISDN_CMD_LOCK:
-		if (debugmode > 1)
-			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg);
-		MOD_INC_USE_COUNT;
-		break;
-
-	case ISDN_CMD_UNLOCK:
-		if (debugmode > 1)
-			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",
-					card->contrnr, c->arg);
-		MOD_DEC_USE_COUNT;
-		break;
-
-/* never called */
-	case ISDN_CMD_GETL2:
-		if (debugmode)
-			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n",
-					card->contrnr);
-		return -ENODEV;
-	case ISDN_CMD_GETL3:
-		if (debugmode)
-			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n",
-					card->contrnr);
-		return -ENODEV;
-	case ISDN_CMD_GETEAZ:
-		if (debugmode)
-			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n",
-					card->contrnr);
-		return -ENODEV;
-	case ISDN_CMD_SETSIL:
-		if (debugmode)
-			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n",
-					card->contrnr);
-		return -ENODEV;
-	case ISDN_CMD_GETSIL:
-		if (debugmode)
-			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n",
-					card->contrnr);
-		return -ENODEV;
 	default:
 		printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",
 					card->contrnr, c->command);
diff -Nru a/drivers/isdn/eicon/divas.h b/drivers/isdn/eicon/divas.h
--- a/drivers/isdn/eicon/divas.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/eicon/divas.h	Wed Nov 27 14:36:31 2002
@@ -103,8 +103,7 @@
 	int		card_id;	/* unique id assigned to this card */
 	int		card_type;	/* use DIA_CARD_TYPE_xxx above */
 	int		bus_type;	/* use DIA_BUS_TYPE_xxx above */
-	int		bus_num;	/* bus number (instance number of bus type) */
-	int		func_num;	/* adapter function number (PCI register) */
+	struct pci_dev *pdev;
 	int		slot;		/* slot number in bus */
 	unsigned char	irq;		/* IRQ number */
     int     reset_base; /* Reset register  for I/O mapped cards */
diff -Nru a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c
--- a/drivers/isdn/eicon/eicon_mod.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/eicon/eicon_mod.c	Wed Nov 27 14:36:27 2002
@@ -529,12 +529,6 @@
 				break;
 			chan->l2prot = (c->arg >> 8);
 			return 0;
-		case ISDN_CMD_GETL2:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			if (!(chan = find_channel(card, c->arg & 0x1f)))
-				break;
-			return chan->l2prot;
 		case ISDN_CMD_SETL3:
 			if (!card->flags & EICON_FLAGS_RUNNING)
 				return -ENODEV;
@@ -548,33 +542,6 @@
 			}
 #endif
 			return 0;
-		case ISDN_CMD_GETL3:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			if (!(chan = find_channel(card, c->arg & 0x1f)))
-				break;
-			return chan->l3prot;
-		case ISDN_CMD_GETEAZ:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n");
-			return 0;
-		case ISDN_CMD_SETSIL:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n");
-			return 0;
-		case ISDN_CMD_GETSIL:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n");
-			return 0;
-		case ISDN_CMD_LOCK:
-			MOD_INC_USE_COUNT;
-			return 0;
-		case ISDN_CMD_UNLOCK:
-			MOD_DEC_USE_COUNT;
-			return 0;
 #ifdef CONFIG_ISDN_TTY_FAX
 		case ISDN_CMD_FAXCMD:
 			if (!card->flags & EICON_FLAGS_RUNNING)
@@ -877,6 +844,7 @@
 		tasklet_init(&card->snd_tq, eicon_transmit, (unsigned long)card);
 		tasklet_init(&card->rcv_tq, eicon_rcv_dispatch, (unsigned long)card);
 		tasklet_init(&card->ack_tq, eicon_ack_dispatch, (unsigned long)card);
+		SET_MODULE_OWNER(&card->interface);
 		card->interface.maxbufsize = 4000;
 		card->interface.command = if_command;
 		card->interface.writebuf_skb = if_sendbuf;
diff -Nru a/drivers/isdn/eicon/lincfg.c b/drivers/isdn/eicon/lincfg.c
--- a/drivers/isdn/eicon/lincfg.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/eicon/lincfg.c	Wed Nov 27 14:36:30 2002
@@ -42,310 +42,182 @@
 
 int DivasCardsDiscover(void)
 {
+	struct pci_dev *pdev = NULL;
 	word wNumCards = 0, wDeviceIndex = 0;
-	byte byBus, byFunc;
-	word wPCIConsultation, PCItmp;
+	word PCItmp;
 	dword j, i;
 	unsigned int PCIserial;
 	dia_card_t Card;
 	byte *b;
 	
-	while (wDeviceIndex < 10)
-	{
-		wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, 
-				PCI_DEVICE_ID_EICON_MAESTRAQ, 
-				wDeviceIndex, 
-				&byBus, &byFunc);
-
-		if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
-		{
-
-			dword dwRAM, dwDivasIOBase, dwCFG, dwCTL; 			
-			byte byIRQ;
-			
-			printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n");
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2,(unsigned int *) &dwRAM);
-			dwRAM &= 0xFFC00000;
-			
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1,(unsigned int *) &dwDivasIOBase);
-			dwDivasIOBase &= 0xFFFFFF00;
-			
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0,(unsigned int *) &dwCFG);
-			dwCFG &= 0xFFFFFF00;
-			
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_3,(unsigned int *) &dwCTL);
-			dwCTL &= 0xFFFFE000;
-			
-
-			pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
-			/* Retrieve the serial number */
-
-			pcibios_write_config_word(byBus,byFunc,0x4E,0x00FC);
-
-			for (j=0, PCItmp=0; j<10000 && !PCItmp; j++)
-			{
-				pcibios_read_config_word(byBus,byFunc,0x4E, &PCItmp);
-				PCItmp &= 0x8000;  // extract done flag
-			}
-
-			pcibios_read_config_dword(byBus,byFunc,0x50, &PCIserial);
-
+	while ((pdev = pci_find_device(PCI_VENDOR_ID_EICON, 
+				      PCI_DEVICE_ID_EICON_MAESTRAQ, 
+				      pdev))) {
+		dword dwRAM, dwDivasIOBase, dwCFG, dwCTL;
+			
+		printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n");
+
+		dwRAM = pci_resource_start(pdev, 2);
+		dwDivasIOBase = pci_resource_start(pdev, 1);
+		dwCFG = pci_resource_start(pdev, 0);
+		dwCTL = pci_resource_start(pdev, 3);
+
+		/* Retrieve the serial number */
+		pci_write_config_word(pdev, 0x4E, 0x00FC);
+		for (j=0, PCItmp=0; j<10000 && !PCItmp; j++) {
+			pci_read_config_word(pdev, 0x4E, &PCItmp);
+			PCItmp &= 0x8000;  // extract done flag
+		}
+		pci_read_config_dword(pdev, 0x50, &PCIserial);
 		
-			Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000);
-			Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000);
-			Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100);
-			Card.io_base=dwDivasIOBase;
-
-			Card.irq = byIRQ;
-			
-			Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q;
-			Card.bus_type = DIA_BUS_TYPE_PCI;
-	
-			FPGA_Done = 0;
-
-			/* Create four virtual card structures as we want to treat 
-			   the 4Bri card as 4 Bri cards*/
-			for(i=0;i<4;i++)
-			{
-
-				b=Card.memory[DIVAS_RAM_MEMORY];
-				b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1); 
-				DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET));
-				Card.memory[DIVAS_RAM_MEMORY]=b;
+		Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000);
+		Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000);
+		Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100);
+		Card.io_base=dwDivasIOBase;
+
+		Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q;
+		Card.bus_type = DIA_BUS_TYPE_PCI;
+		Card.pdev = pdev;
+		Card.irq = pdev->irq;
+			
+		FPGA_Done = 0;
+
+		/* Create four virtual card structures as we want to treat 
+		   the 4Bri card as 4 Bri cards*/
+		for(i=0;i<4;i++) {
+			b=Card.memory[DIVAS_RAM_MEMORY];
+			b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1); 
+			DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET));
+			Card.memory[DIVAS_RAM_MEMORY]=b;
  
-				b = Card.memory[DIVAS_RAM_MEMORY];
-				b += MQ_SM_OFFSET;
-				Card.memory[DIVAS_SHARED_MEMORY] = b;
-
-				Card.bus_num = byBus;
-				Card.func_num = byFunc;
-				Card.slot = -1;
-
-			
-				/* Fill in Name */
-				Card.name[0] = 'D';
-				Card.name[1] = 'I';
-				Card.name[2] = 'V';
-				Card.name[3] = 'A';
-				Card.name[4] = 'S';
-				Card.name[5] = 'Q';
-				Card.name[6] = '0' + i;
-				Card.name[7] = '\0';
-
-				Card.serial = PCIserial;
-
-			 	Card.card_id = wNumCards;
-
- 				if (DivasCardNew(&Card) != 0)
-				{
-					// Force for loop to terminate
-					i = 4;
-					continue;
-				}
-				wNumCards++;
-
-			}//for
-		}
-		wDeviceIndex++;
-	}
-
-	wDeviceIndex = 0;
+			b = Card.memory[DIVAS_RAM_MEMORY];
+			b += MQ_SM_OFFSET;
+			Card.memory[DIVAS_SHARED_MEMORY] = b;
 
-	while (wDeviceIndex < 10)
-	{
-		wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, 
-				PCI_DEVICE_ID_EICON_MAESTRA, 
-				wDeviceIndex, 
-				&byBus, &byFunc);
-
-		if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
-		{
-			dword dwPLXIOBase, dwDivasIOBase;
-			byte byIRQ;
-
-			printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n");
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
-			dwPLXIOBase &= 0xFFFFFF80;
+			Card.slot = -1;
 
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
-			dwDivasIOBase &= 0xFFFFFFFC;
+			sprintf(Card.name, "DIVASQ%ld", i);
 
-			pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
+			Card.serial = PCIserial;
 
 			Card.card_id = wNumCards;
-			Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
-			Card.bus_type = DIA_BUS_TYPE_PCI;
-			Card.irq = byIRQ;
-			Card.reset_base = dwPLXIOBase;
-			Card.io_base = dwDivasIOBase;
-			Card.bus_num = byBus;
-			Card.func_num = byFunc;
-			Card.slot = -1;
-			Card.name[0] = 'D';
-			Card.name[1] = 'I';
-			Card.name[2] = 'V';
-			Card.name[3] = 'A';
-			Card.name[4] = 'S';
-			Card.name[5] = 'B';
-			Card.name[6] = '\0';
-
-			if (check_region(Card.io_base, 0x20))
-			{
-				printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
-				wDeviceIndex++;
-				continue;
-			}
-
-			if (check_region(Card.reset_base, 0x80))
-			{
-				printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
-				wDeviceIndex++;
-				continue;
-			}
 
-			if (DivasCardNew(&Card) != 0)
-			{
-				wDeviceIndex++;
-				continue;
+			if (DivasCardNew(&Card) != 0) {
+				break;
 			}
 			wNumCards++;
-		}
 
-		wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, 
-				PCI_DEVICE_ID_EICON_MAESTRAQ_U, 
-				wDeviceIndex, 
-				&byBus, &byFunc);
-
-		if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
-		{
-			dword dwPLXIOBase, dwDivasIOBase;
-			byte byIRQ;
+		}
+	}
 
-			printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n");
+	pdev = NULL;
+	while ((pdev = pci_find_device(PCI_VENDOR_ID_EICON, 
+				      PCI_DEVICE_ID_EICON_MAESTRA, 
+				      pdev))) {
+		dword dwPLXIOBase, dwDivasIOBase;
+
+		printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n");
+		dwPLXIOBase = pci_resource_start(pdev, 1);
+		dwDivasIOBase = pci_resource_start(pdev, 2);
+		
+		Card.card_id = wNumCards;
+		Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
+		Card.bus_type = DIA_BUS_TYPE_PCI;
+		Card.pdev = pdev;
+		Card.irq = pdev->irq;
+		Card.reset_base = dwPLXIOBase;
+		Card.io_base = dwDivasIOBase;
+		Card.slot = -1;
+		strcpy(Card.name, "DIVASB");
 
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
-			dwPLXIOBase &= 0xFFFFFF80;
+		if (check_region(Card.io_base, 0x20)) {
+			printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
+		}
 
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
-			dwDivasIOBase &= 0xFFFFFFFC;
+		if (check_region(Card.reset_base, 0x80)) {
+			printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
+			continue;
+		}
+		
+		if (DivasCardNew(&Card) != 0) {
+			continue;
+		}
+		wNumCards++;
+	}
 
-			pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
+	pdev = NULL;
+	while ((pdev = pci_find_device(PCI_VENDOR_ID_EICON, 
+				      PCI_DEVICE_ID_EICON_MAESTRAQ_U, 
+				      pdev))) {
+		dword dwPLXIOBase, dwDivasIOBase;
 
-			Card.card_id = wNumCards;
-			Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
-			Card.bus_type = DIA_BUS_TYPE_PCI;
-			Card.irq = byIRQ;
-			Card.reset_base = dwPLXIOBase;
-			Card.io_base = dwDivasIOBase;
-			Card.bus_num = byBus;
-			Card.func_num = byFunc;
-			Card.slot = -1;
-			Card.name[0] = 'D';
-			Card.name[1] = 'I';
-			Card.name[2] = 'V';
-			Card.name[3] = 'A';
-			Card.name[4] = 'S';
-			Card.name[5] = 'B';
-			Card.name[6] = '\0';
-
-			if (check_region(Card.io_base, 0x20))
-			{
-				printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);	
-				wDeviceIndex++;
-				continue;
-			}
+		printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n");
 
-			if (check_region(Card.reset_base, 0x80))
-			{
-				printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
-				wDeviceIndex++;
-				continue;
-			}
+		dwPLXIOBase = pci_resource_start(pdev, 1);
+		dwDivasIOBase = pci_resource_start(pdev, 2);
+		
+		Card.card_id = wNumCards;
+		Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
+		Card.bus_type = DIA_BUS_TYPE_PCI;
+		Card.pdev = pdev;
+		Card.irq = pdev->irq;
+		Card.reset_base = dwPLXIOBase;
+		Card.io_base = dwDivasIOBase;
+		Card.slot = -1;
+		strcpy(Card.name, "DIVASB");
+
+		if (check_region(Card.io_base, 0x20)) {
+			printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);	
+			continue;
+		}
 
-			if (DivasCardNew(&Card) != 0)
-			{
-				wDeviceIndex++;
-				continue;
-			}
-			wNumCards++;
+		if (check_region(Card.reset_base, 0x80)) {
+			printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
+			continue;
 		}
 
-		wDeviceIndex++;
+		if (DivasCardNew(&Card) != 0) {
+			continue;
+		}
+		wNumCards++;
 	}
 
 	wDeviceIndex = 0;
 
-	while (wDeviceIndex < 10)
-	{
-		wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON, 
-				PCI_DEVICE_ID_EICON_MAESTRAP, 
-				wDeviceIndex, 
-				&byBus, &byFunc);
-
-		if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
-		{
-			dword dwRAM, dwREG, dwCFG;
-			byte byIRQ;
+	pdev = NULL;
+	while ((pdev = pci_find_device(PCI_VENDOR_ID_EICON, 
+				      PCI_DEVICE_ID_EICON_MAESTRAQ_U, 
+				      pdev))) {
+		dword dwRAM, dwREG, dwCFG;
 
-			printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n");
-
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0, (unsigned int *) &dwRAM);
-			dwRAM &= 0xFFFFF000;
-
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwREG);
-			dwREG &= 0xFFFFF000;
-			
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_4, (unsigned int *) &dwCFG);
-			dwCFG &= 0xFFFFF000;
-
-			pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
-
-			Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000);
-			Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000);
-			Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000);
-			Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET;
-
-/*			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
-			dwPLXIOBase &= 0xFFFFFFFc;
-
-			pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
-			dwDivasIOBase &= 0xFFFFFF80;
-
-			pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
-*/
-			Card.card_id = wNumCards;
-			Card.card_type = DIA_CARD_TYPE_DIVA_SERVER;
-			Card.bus_type = DIA_BUS_TYPE_PCI;
-			Card.irq = byIRQ;
-/*			Card.reset_base = dwPLXIOBase;
-			Card.io_base = dwDivasIOBase;*/
-			Card.bus_num = byBus;
-			Card.func_num = byFunc;
-			Card.slot = -1;
-			Card.name[0] = 'D';
-			Card.name[1] = 'I';
-			Card.name[2] = 'V';
-			Card.name[3] = 'A';
-			Card.name[4] = 'S';
-			Card.name[5] = 'P';
-			Card.name[6] = '\0';
-
-			if (DivasCardNew(&Card) != 0)
-			{
-				wDeviceIndex++;
-				continue;
-			}
-			wNumCards++;
+		printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n");
+		
+		dwRAM = pci_resource_start(pdev, 0);
+		dwREG = pci_resource_start(pdev, 2);
+		dwCFG = pci_resource_start(pdev, 4);
+		
+		Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000);
+		Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000);
+		Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000);
+		Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET;
+		
+		Card.card_id = wNumCards;
+		Card.card_type = DIA_CARD_TYPE_DIVA_SERVER;
+		Card.bus_type = DIA_BUS_TYPE_PCI;
+		Card.pdev = pdev;
+		Card.irq = pdev->irq;
+		Card.slot = -1;
+		strcpy(Card.name, "DIVASP");
+		if (DivasCardNew(&Card) != 0) {
+			continue;
 		}
-
-		wDeviceIndex++;
+		wNumCards++;
 	}
 
 
 	printk(KERN_INFO "Divas: %d cards detected\n", wNumCards);
 
-	if(wNumCards == 0)
-	{
+	if(wNumCards == 0) {
 		return -1;
 	}
 
@@ -357,8 +229,7 @@
 
 	Divas_major = register_chrdev(0, "Divas", &Divas_fops);
 
-	if (Divas_major < 0)
-	{
+	if (Divas_major < 0) {
 		printk(KERN_WARNING "Divas: Unable to register character driver\n");
 		return -1;
 	}
diff -Nru a/drivers/isdn/eicon/linio.c b/drivers/isdn/eicon/linio.c
--- a/drivers/isdn/eicon/linio.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/eicon/linio.c	Wed Nov 27 14:36:28 2002
@@ -13,6 +13,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -67,8 +68,7 @@
 	switch (cfg->bus_type)
 	{
 	case DIA_BUS_TYPE_PCI:
-		c->bus_num = cfg->bus_num;
-		c->func_num = cfg->func_num;
+		c->pdev = cfg->pdev;
 		c->io_base = cfg->io_base;
 		c->reset_base = cfg->reset_base;
 		c->card_type    = cfg->card_type;
@@ -625,16 +625,15 @@
 
 void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
 {
-	switch (size)
-	{
+	switch (size) {
 	case sizeof(byte):
-		pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
+		pci_write_config_byte(card->pdev, offset, * (byte *) value);
 		break;
 	case sizeof(word):
-		pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
+		pci_write_config_word(card->pdev, offset, * (word *) value);
 		break;
 	case sizeof(dword):
-		pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
+		pci_write_config_dword(card->pdev, offset, * (dword *) value);
 		break;
 	default:
 		printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
@@ -643,16 +642,15 @@
 
 void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
 {
-	switch (size)
-	{
+	switch (size) {
 	case sizeof(byte):
-		pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
+		pci_read_config_byte(card->pdev, offset, (byte *) value);
 		break;
 	case sizeof(word):
-		pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
+		pci_read_config_word(card->pdev, offset, (word *) value);
 		break;
 	case sizeof(dword):
-		pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
+		pci_read_config_dword(card->pdev, offset, (unsigned int *) value);
 		break;
 	default:
 		printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
diff -Nru a/drivers/isdn/eicon/uxio.h b/drivers/isdn/eicon/uxio.h
--- a/drivers/isdn/eicon/uxio.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/eicon/uxio.h	Wed Nov 27 14:36:27 2002
@@ -28,8 +28,7 @@
 	int		reset_base;
 	int		card_type;
 	byte		*mapped;
-	int		bus_num;
-	int		func_num;
+	struct pci_dev  *pdev;
 	int		slot;
 	int		irq;
 	byte		*pDRAM;
diff -Nru a/drivers/isdn/hardware/eicon/i4lididrv.c b/drivers/isdn/hardware/eicon/i4lididrv.c
--- a/drivers/isdn/hardware/eicon/i4lididrv.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hardware/eicon/i4lididrv.c	Wed Nov 27 14:36:32 2002
@@ -589,12 +589,6 @@
 			chan->l2prot = (c->arg >> 8);
                         memcpy(chan->a_para, c->parm.aux.para, sizeof(chan->a_para));
 			return 0;
-		case ISDN_CMD_GETL2:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			if (!(chan = find_channel(card, c->arg & 0x1f)))
-				break;
-			return chan->l2prot;
 		case ISDN_CMD_SETL3:
 			if (!card->flags & EICON_FLAGS_RUNNING)
 				return -ENODEV;
@@ -608,33 +602,6 @@
 			}
 #endif
 			return 0;
-		case ISDN_CMD_GETL3:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			if (!(chan = find_channel(card, c->arg & 0x1f)))
-				break;
-			return chan->l3prot;
-		case ISDN_CMD_GETEAZ:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			eicon_log(card, 1, "%s: CMD_GETEAZ not implemented\n", DRIVERLNAME);
-			return 0;
-		case ISDN_CMD_SETSIL:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			eicon_log(card, 1, "%s: CMD_SETSIL not implemented\n",DRIVERLNAME);
-			return 0;
-		case ISDN_CMD_GETSIL:
-			if (!card->flags & EICON_FLAGS_RUNNING)
-				return -ENODEV;
-			eicon_log(card, 1, "%s: CMD_GETSIL not implemented\n", DRIVERLNAME);
-			return 0;
-		case ISDN_CMD_LOCK:
-			MOD_INC_USE_COUNT;
-			return 0;
-		case ISDN_CMD_UNLOCK:
-			MOD_DEC_USE_COUNT;
-			return 0;
 #ifdef CONFIG_ISDN_TTY_FAX
 		case ISDN_CMD_FAXCMD:
 			if (!card->flags & EICON_FLAGS_RUNNING)
@@ -961,6 +928,7 @@
 	skb_queue_head_init(&card->sackq);
 	skb_queue_head_init(&card->statq);
 	card->statq_entries = 0;
+	SET_MODULE_OWNER(&card->interface);
 	card->interface.maxbufsize = 4000;
 	card->interface.command = if_command;
 	card->interface.writebuf_skb = if_sendbuf;
diff -Nru a/drivers/isdn/hardware/eicon/mi_pc.h b/drivers/isdn/hardware/eicon/mi_pc.h
--- a/drivers/isdn/hardware/eicon/mi_pc.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/hardware/eicon/mi_pc.h	Wed Nov 27 14:36:30 2002
@@ -65,7 +65,7 @@
 #define _MP_LED1         0x04        /* 1 = on      */
 #define _MP_DSP_RESET    0x02        /* active lo   */
 #define _MP_RISC_RESET   0x81        /* active hi, bit 7 for compatibility with old boards */
-/* CPU exeption context structure in MP shared ram after trap */
+/* CPU exception context structure in MP shared ram after trap */
 typedef struct mp_xcptcontext_s MP_XCPTC;
 struct mp_xcptcontext_s {
     dword       sr;
diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c
--- a/drivers/isdn/hisax/amd7930.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/isdn/hisax/amd7930.c	Wed Nov 27 14:36:29 2002
@@ -115,14 +115,7 @@
 		dev_kfree_skb(bcs->hw.amd7930.tx_skb);
 		bcs->hw.amd7930.tx_skb = NULL;
 	}
-
-	if ((skb = skb_dequeue(&bcs->squeue))) {
-		Bchan_fill_fifo(bcs, skb);
-	} else {
-		clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		bcs->event |= 1 << B_XMTBUFREADY;
-		schedule_work(&bcs->work);
-	}
+	xmit_ready_b(bcs);
 }
 
 static void
diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
--- a/drivers/isdn/hisax/amd7930_fn.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/amd7930_fn.c	Wed Nov 27 14:36:31 2002
@@ -268,18 +268,6 @@
 }
 
 
-void
-Amd7930_sched_event(struct IsdnCardState *cs, int event) // ok
-{
-
-	if (cs->debug & L1_DEB_ISAC) {
-		debugl1(cs, "AMD7930: sched_event 0x%X", event);
-        }
-
-        test_and_set_bit(event, &cs->event);
-	schedule_work(&cs->work);
-}
-
 static void
 Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag)
 {
@@ -339,7 +327,7 @@
                                 /* throw damaged packets away, reset recieve-buffer, indicate RX */
 				ptr = cs->rcvbuf;
 				cs->rcvidx = 0;
-				Amd7930_sched_event(cs, D_RCVBUFREADY);
+				sched_d_event(cs, D_RCVBUFREADY);
 			}
                 }
 		/* Packet to long, overflow */
@@ -455,7 +443,7 @@
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				Amd7930_sched_event(cs, D_CLEARBUSY);
+				sched_d_event(cs, D_CLEARBUSY);
                         /* restart frame */
                         if (cs->tx_skb) {
 				skb_push(cs->tx_skb, cs->tx_cnt);
@@ -473,7 +461,7 @@
 		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 			del_timer(&cs->dbusytimer);
 		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			Amd7930_sched_event(cs, D_CLEARBUSY);
+			sched_d_event(cs, D_CLEARBUSY);
                 /* restart TX-Frame */
                 if (cs->tx_skb) {
 			skb_push(cs->tx_skb, cs->tx_cnt);
@@ -494,7 +482,7 @@
                 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 			del_timer(&cs->dbusytimer);
 		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			Amd7930_sched_event(cs, D_CLEARBUSY);
+			sched_d_event(cs, D_CLEARBUSY);
 		if (cs->tx_skb) {
 			if (cs->tx_skb->len)
 				Amd7930_fill_Dfifo(cs);
@@ -523,7 +511,7 @@
                 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 			del_timer(&cs->dbusytimer);
 		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			Amd7930_sched_event(cs, D_CLEARBUSY);
+			sched_d_event(cs, D_CLEARBUSY);
 
                 if (cs->tx_skb) {
         		if (cs->debug & L1_DEB_ISAC)
@@ -541,7 +529,7 @@
 			Amd7930_fill_Dfifo(cs);
 		}
                 else
-			Amd7930_sched_event(cs, D_XMTBUFREADY);
+			sched_d_event(cs, D_XMTBUFREADY);
 		/* AMD interrupts on */
                 AmdIrqOn(cs);
         }
@@ -556,7 +544,7 @@
 
 		cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
 
-		Amd7930_sched_event(cs, D_L1STATECHANGE);
+		sched_d_event(cs, D_L1STATECHANGE);
 		/* AMD interrupts on */
                 AmdIrqOn(cs);
 	}
@@ -662,7 +650,7 @@
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				Amd7930_sched_event(cs, D_CLEARBUSY);
+				sched_d_event(cs, D_CLEARBUSY);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
--- a/drivers/isdn/hisax/asuscom.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hisax/asuscom.c	Wed Nov 27 14:36:32 2002
@@ -172,10 +172,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
 
-	if (!cs) {
-		printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
 	if (val)
@@ -202,6 +199,7 @@
 	writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0);
 	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0);
 	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 static void
@@ -295,7 +293,7 @@
 			return(0);
 		case CARD_INIT:
 			cs->debug |= L1_DEB_IPAC;
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
--- a/drivers/isdn/hisax/avm_a1.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/avm_a1.c	Wed Nov 27 14:36:27 2002
@@ -106,10 +106,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val, sval;
 
-	if (!cs) {
-		printk(KERN_WARNING "AVM A1: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	while (((sval = bytein(cs->hw.avm.cfg_reg)) & 0xf) != 0x7) {
 		if (!(sval & AVM_A1_STAT_TIMER)) {
 			byteout(cs->hw.avm.cfg_reg, 0x1E);
@@ -133,6 +130,7 @@
 	writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
 	writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
 	writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 inline static void
@@ -163,10 +161,9 @@
 			release_ioregs(cs, 0x3f);
 			return(0);
 		case CARD_INIT:
-			inithscxisac(cs, 1);
 			byteout(cs->hw.avm.cfg_reg, 0x16);
 			byteout(cs->hw.avm.cfg_reg, 0x1E);
-			inithscxisac(cs, 2);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
--- a/drivers/isdn/hisax/avm_a1p.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/hisax/avm_a1p.c	Wed Nov 27 14:36:30 2002
@@ -179,10 +179,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val, sval;
 
-	if (!cs) {
-		printk(KERN_WARNING "AVM A1 PCMCIA: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
 		if (cs->debug & L1_DEB_INTSTAT)
 			debugl1(cs, "avm IntStatus %x", sval);
@@ -203,6 +200,7 @@
 	WriteISAC(cs, ISAC_MASK, 0x00);
 	WriteHSCX(cs, 0, HSCX_MASK, 0x00);
 	WriteHSCX(cs, 1, HSCX_MASK, 0x00);
+	spin_unlock(&cs->lock);
 }
 
 static int
@@ -224,10 +222,7 @@
 
 		case CARD_INIT:
 			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			inithscxisac(cs, 1);
-			inithscxisac(cs, 2);
+			inithscxisac(cs);
 			return 0;
 
 		case CARD_TEST:
diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
--- a/drivers/isdn/hisax/avm_pci.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/avm_pci.c	Wed Nov 27 14:36:28 2002
@@ -191,13 +191,6 @@
 		return(NULL);
 }
 
-void inline
-hdlc_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
 void
 write_ctrl(struct BCState *bcs, int which) {
 
@@ -252,7 +245,7 @@
 			bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
 			write_ctrl(bcs, 1);
 			bcs->hw.hdlc.ctrl.sr.cmd = 0;
-			hdlc_sched_event(bcs, B_XMTBUFREADY);
+			sched_b_event(bcs, B_XMTBUFREADY);
 			break;
 		case (L1_MODE_HDLC):
 			bcs->mode = mode;
@@ -263,7 +256,7 @@
 			bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
 			write_ctrl(bcs, 1);
 			bcs->hw.hdlc.ctrl.sr.cmd = 0;
-			hdlc_sched_event(bcs, B_XMTBUFREADY);
+			sched_b_event(bcs, B_XMTBUFREADY);
 			break;
 	}
 }
@@ -323,35 +316,24 @@
 hdlc_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int count, cnt =0;
+	int count, more, cnt =0;
 	int fifo_size = 32;
-	u_char *p;
-	u_int *ptr;
+	unsigned char *p;
+	unsigned int *ptr;
 
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "hdlc_fill_fifo");
-	if (!bcs->tx_skb)
-		return;
-	if (bcs->tx_skb->len <= 0)
+	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
+	if (!p)
 		return;
 
-	bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
-	if (bcs->tx_skb->len > fifo_size) {
-		count = fifo_size;
-	} else {
-		count = bcs->tx_skb->len;
-		if (bcs->mode != L1_MODE_TRANS)
-			bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
-	}
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
-	ptr = (u_int *) p = bcs->tx_skb->data;
-	skb_pull(bcs->tx_skb, count);
-	bcs->tx_cnt -= count;
-	bcs->hw.hdlc.count += count;
+	if (more)
+		bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
+	else
+		bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
+
 	bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count);
 	write_ctrl(bcs, 3);  /* sets the correct index too */
 	if (cs->subtyp == AVM_FRITZ_PCI) {
+		ptr = (unsigned int *) p;
 		while (cnt<count) {
 #ifdef __powerpc__
 #ifdef CONFIG_APUS
@@ -370,34 +352,28 @@
 			cnt++;
 		}
 	}
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		if (cs->subtyp == AVM_FRITZ_PNP)
-			p = (u_char *) ptr;
-		t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', count);
-		QuickHex(t, p, count);
-		debugl1(cs, bcs->blog);
-	}
 }
 
 static void
-fill_hdlc(struct BCState *bcs)
+reset_xmit(struct BCState *bcs)
 {
-	unsigned long flags;
-	spin_lock_irqsave(&avm_pci_lock, flags);
+	bcs->hw.hdlc.ctrl.sr.xml = 0;
+	bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
+	write_ctrl(bcs, 1);
+	bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
+	write_ctrl(bcs, 1);
 	hdlc_fill_fifo(bcs);
-	spin_unlock_irqrestore(&avm_pci_lock, flags);
 }
 
 static inline void
-HDLC_irq(struct BCState *bcs, u_int stat) {
+HDLC_irq(struct BCState *bcs, u_int stat)
+{
 	int len;
 	struct sk_buff *skb;
 
 	if (bcs->cs->debug & L1_DEB_HSCX)
 		debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
+
 	if (stat & HDLC_INT_RPR) {
 		if (stat & HDLC_STAT_RDO) {
 			if (bcs->cs->debug & L1_DEB_HSCX)
@@ -425,7 +401,7 @@
 						skb_queue_tail(&bcs->rqueue, skb);
 					}
 					bcs->hw.hdlc.rcvidx = 0;
-					hdlc_sched_event(bcs, B_RCVBUFREADY);
+					sched_b_event(bcs, B_RCVBUFREADY);
 				} else {
 					if (bcs->cs->debug & L1_DEB_HSCX)
 						debugl1(bcs->cs, "invalid frame");
@@ -437,46 +413,9 @@
 		}
 	}
 	if (stat & HDLC_INT_XDU) {
-		/* Here we lost an TX interrupt, so
-		 * restart transmitting the whole frame.
-		 */
-		if (bcs->tx_skb) {
-			skb_push(bcs->tx_skb, bcs->hw.hdlc.count);
-			bcs->tx_cnt += bcs->hw.hdlc.count;
-			bcs->hw.hdlc.count = 0;
-//			hdlc_sched_event(bcs, B_XMTBUFREADY);
-			if (bcs->cs->debug & L1_DEB_WARN)
-				debugl1(bcs->cs, "ch%d XDU", bcs->channel);
-		} else if (bcs->cs->debug & L1_DEB_WARN)
-			debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel);
-		bcs->hw.hdlc.ctrl.sr.xml = 0;
-		bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
-		write_ctrl(bcs, 1);
-		bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
-		write_ctrl(bcs, 1);
-		hdlc_fill_fifo(bcs);
+		xmit_xdu_b(bcs, reset_xmit);
 	} else if (stat & HDLC_INT_XPR) {
-		if (bcs->tx_skb) {
-			if (bcs->tx_skb->len) {
-				hdlc_fill_fifo(bcs);
-				return;
-			} else {
-				if (bcs->st->lli.l1writewakeup &&
-					(PACKET_NOACK != bcs->tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count);
-				dev_kfree_skb_irq(bcs->tx_skb);
-				bcs->hw.hdlc.count = 0;
-				bcs->tx_skb = NULL;
-			}
-		}
-		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-			bcs->hw.hdlc.count = 0;
-			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
-			hdlc_fill_fifo(bcs);
-		} else {
-			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-			hdlc_sched_event(bcs, B_XMTBUFREADY);
-		}
+		xmit_xpr_b(bcs);
 	}
 }
 
@@ -484,10 +423,9 @@
 HDLC_irq_main(struct IsdnCardState *cs)
 {
 	u_int stat;
-	long  flags;
 	struct BCState *bcs;
 
-	spin_lock_irqsave(&avm_pci_lock, flags);
+	spin_lock(&cs->lock);
 	if (cs->subtyp == AVM_FRITZ_PCI) {
 		stat = ReadHDLCPCI(cs, 0, HDLC_STATUS);
 	} else {
@@ -516,45 +454,23 @@
 		} else
 			HDLC_irq(bcs, stat);
 	}
-	spin_unlock_irqrestore(&avm_pci_lock, flags);
+	spin_unlock(&cs->lock);
 }
 
 void
 hdlc_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	unsigned long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			spin_lock_irqsave(&avm_pci_lock, flags);
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				spin_unlock_irqrestore(&avm_pci_lock, flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				st->l1.bcs->hw.hdlc.count = 0;
-				spin_unlock_irqrestore(&avm_pci_lock, flags);
-				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n");
-				break;
-			}
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->hw.hdlc.count = 0;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
@@ -639,7 +555,7 @@
 }
 
 void __init
-clear_pending_hdlc_ints(struct IsdnCardState *cs)
+inithdlc(struct IsdnCardState *cs)
 {
 	u_int val;
 
@@ -666,11 +582,7 @@
 		val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3);
 		debugl1(cs, "HDLC 2 VIN %x", val);
 	}
-}
 
-void __init
-inithdlc(struct IsdnCardState *cs)
-{
 	cs->bcs[0].BC_SetStack = setstack_hdlc;
 	cs->bcs[1].BC_SetStack = setstack_hdlc;
 	cs->bcs[0].BC_Close = close_hdlcstate;
@@ -731,17 +643,12 @@
 			release_region(cs->hw.avm.cfg_reg, 32);
 			return(0);
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
 			initisac(cs);
-			clear_pending_hdlc_ints(cs);
 			inithdlc(cs);
 			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
 				cs->hw.avm.cfg_reg + 2);
-			WriteISAC(cs, ISAC_MASK, 0);
 			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
 				AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
-			/* RESET Receiver and Transmitter */
-			WriteISAC(cs, ISAC_CMDR, 0x41);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -880,7 +787,7 @@
 	cs->writeisac = &WriteISAC;
 	cs->readisacfifo = &ReadISACfifo;
 	cs->writeisacfifo = &WriteISACfifo;
-	cs->BC_Send_Data = &fill_hdlc;
+	cs->BC_Send_Data = &hdlc_fill_fifo;
 	cs->cardmsg = &AVM_card_msg;
 	cs->irq_func = &avm_pcipnp_interrupt;
 	ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
--- a/drivers/isdn/hisax/bkm_a4t.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/isdn/hisax/bkm_a4t.c	Wed Nov 27 14:36:29 2002
@@ -139,10 +139,7 @@
 	u_char val = 0;
 	I20_REGISTER_FILE *pI20_Regs;
 
-	if (!cs) {
-		printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
 
 	/* ISDN interrupt pending? */
@@ -169,6 +166,7 @@
 		/* Reenable ISDN interrupt */
 		pI20_Regs->i20IntCtrl |= intISDN;
 	}
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -243,8 +241,6 @@
 			release_io_bkm(cs);
 			return (0);
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_jade_ints(cs);
 			initisac(cs);
 			initjade(cs);
 			/* Enable ints */
diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
--- a/drivers/isdn/hisax/bkm_a8.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/bkm_a8.c	Wed Nov 27 14:36:31 2002
@@ -153,13 +153,10 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char ista, val, icnt = 5;
 
-	if (!cs) {
-		printk(KERN_WARNING "HiSax: Scitel Quadro: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
 	if (!(ista & 0x3f)) /* not this IPAC */
-		return;
+		goto unlock;
       Start_IPAC:
 	if (cs->debug & L1_DEB_IPAC)
 		debugl1(cs, "IPAC ISTA %02X", ista);
@@ -196,6 +193,8 @@
 		       sct_quadro_subtypes[cs->subtyp]);
 	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF);
 	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0);
+ unlock:
+	spin_unlock(&cs->lock);
 }
 
 
@@ -251,7 +250,7 @@
 		case CARD_INIT:
 			cs->debug |= L1_DEB_IPAC;
 			set_ipac_active(cs, 1);
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			/* Enable ints */
 			enable_bkm_int(cs, 1);
 			return (0);
diff -Nru a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
--- a/drivers/isdn/hisax/callc.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/hisax/callc.c	Wed Nov 27 14:36:30 2002
@@ -29,8 +29,6 @@
 
 extern struct IsdnCard cards[];
 extern int nrcards;
-extern void HiSax_mod_dec_use_count(struct IsdnCardState *cs);
-extern void HiSax_mod_inc_use_count(struct IsdnCardState *cs);
 
 static int init_b_st(struct Channel *chanp, int incoming);
 static void release_b_st(struct Channel *chanp);
@@ -1068,7 +1066,6 @@
 	setstack_isdnl2(st, tmp);
 	setstack_l3dc(st, chanp);
 	st->lli.userdata = chanp;
-	st->lli.l2writewakeup = NULL;
 	st->lli.l3l4 = dchan_l3l4;
 
 	return 0;
@@ -1186,13 +1183,30 @@
 }
 
 static void
+ll_writewakeup(struct Channel *chanp, struct sk_buff *skb)
+{
+	isdn_ctrl ic;
+
+	if (skb->pkt_type != PACKET_NOACK) {
+		if (chanp->debug & 0x800)
+			link_debug(chanp, 0, "llwakeup: %d", skb->truesize);
+		ic.driver = chanp->cs->myid;
+		ic.command = ISDN_STAT_BSENT;
+		ic.arg = chanp->chan;
+		ic.parm.length = skb->truesize;
+		chanp->cs->iif.statcallb(&ic);
+	}
+	dev_kfree_skb(skb);
+}
+
+static void
 lldata_handler(struct PStack *st, int pr, void *arg)
 {
 	struct Channel *chanp = (struct Channel *) st->lli.userdata;
 	struct sk_buff *skb = arg;
 
 	switch (pr) {
-		case (DL_DATA  | INDICATION):
+		case (DL_DATA | INDICATION):
 			if (chanp->data_open) {
 				if (chanp->debug & 0x800)
 					link_debug(chanp, 0, "lldata: %d", skb->len);
@@ -1202,6 +1216,9 @@
 				dev_kfree_skb(skb);
 			}
 			break;
+		case (DL_DATA | CONFIRM):
+			ll_writewakeup(chanp, skb);
+			break;
 		case (DL_ESTABLISH | INDICATION):
 		case (DL_ESTABLISH | CONFIRM):
 			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
@@ -1234,6 +1251,9 @@
 				dev_kfree_skb(skb);
 			}
 			break;
+		case (PH_DATA | CONFIRM):
+			ll_writewakeup(chanp, skb);
+			break;
 		case (PH_ACTIVATE | INDICATION):
 		case (PH_ACTIVATE | CONFIRM):
 			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
@@ -1249,21 +1269,6 @@
 	}
 }
 
-static void
-ll_writewakeup(struct PStack *st, int len)
-{
-	struct Channel *chanp = st->lli.userdata;
-	isdn_ctrl ic;
-
-	if (chanp->debug & 0x800)
-		link_debug(chanp, 0, "llwakeup: %d", len);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_BSENT;
-	ic.arg = chanp->chan;
-	ic.parm.length = len;
-	chanp->cs->iif.statcallb(&ic);
-}
-
 static int
 init_b_st(struct Channel *chanp, int incoming)
 {
@@ -1314,8 +1319,6 @@
 			setstack_l3bc(st, chanp);
 			st->l3.l2l3 = lldata_handler;
 			st->lli.userdata = chanp;
-			st->lli.l1writewakeup = NULL;
-			st->lli.l2writewakeup = ll_writewakeup;
 			st->l2.l2m.debug = chanp->debug & 16;
 			st->l2.debug = chanp->debug & 64;
 			break;
@@ -1326,7 +1329,6 @@
 		case (ISDN_PROTO_L2_FAX):
 			st->l2.l1l2 = lltrans_handler;
 			st->lli.userdata = chanp;
-			st->lli.l1writewakeup = ll_writewakeup;
 			setstack_transl2(st);
 			setstack_l3bc(st, chanp);
 			break;
@@ -1584,22 +1586,6 @@
 					break;
 			}
 			break;
-		case (ISDN_CMD_LOCK):
-			HiSax_mod_inc_use_count(csta);
-#ifdef MODULE
-			if (csta->channel[0].debug & 0x400)
-				HiSax_putstatus(csta, "   LOCK ", "modcnt %lx",
-					MOD_USE_COUNT);
-#endif				/* MODULE */
-			break;
-		case (ISDN_CMD_UNLOCK):
-			HiSax_mod_dec_use_count(csta);
-#ifdef MODULE
-			if (csta->channel[0].debug & 0x400)
-				HiSax_putstatus(csta, " UNLOCK ", "modcnt %lx",
-					MOD_USE_COUNT);
-#endif				/* MODULE */
-			break;
 		case (ISDN_CMD_IOCTL):
 			switch (ic->arg) {
 				case (0):
@@ -1623,14 +1609,6 @@
 					printk(KERN_DEBUG "HiSax: delay card %d set to %d ms\n",
 						csta->cardnr + 1, num);
 					break;
-				case (3):
-					for (i = 0; i < *(unsigned int *) ic->parm.num; i++)
-						HiSax_mod_dec_use_count(NULL);
-					break;
-				case (4):
-					for (i = 0; i < *(unsigned int *) ic->parm.num; i++)
-						HiSax_mod_inc_use_count(NULL);
-					break;
 				case (5):	/* set card in leased mode */
 					num = *(unsigned int *) ic->parm.num;
 					if ((num <1) || (num > 2)) {
@@ -1693,12 +1671,6 @@
 					}
 					L4L3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
 					break;
-#ifdef MODULE
-				case (55):
-					MOD_USE_COUNT = 0;
-					HiSax_mod_inc_use_count(NULL);
-					break;
-#endif				/* MODULE */
 				case (11):
 					num = csta->debug & DEB_DLOG_HEX;
 					csta->debug = *(unsigned int *) ic->parm.num;
diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
--- a/drivers/isdn/hisax/config.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/config.c	Wed Nov 27 14:36:31 2002
@@ -942,6 +942,8 @@
 	cs->status_write = cs->status_buf;
 	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
 	cs->typ = card->typ;
+	spin_lock_init(&cs->lock);
+	SET_MODULE_OWNER(&cs->iif);
 	strcpy(cs->iif.id, id);
 	cs->iif.channels = 2;
 	cs->iif.maxbufsize = MAX_DATA_SIZE;
@@ -1769,6 +1771,7 @@
 	hisax_d_if->cs = cs;
 	cs->hw.hisax_d_if = hisax_d_if;
 	cs->cardmsg = hisax_cardmsg;
+	cs->iif.owner = hisax_d_if->owner; // FIXME should be done before registering
 	INIT_WORK(&cs->work, hisax_bh, cs);
 	cs->channel[0].d_st->l1.l2l1 = hisax_d_l2l1;
 	for (i = 0; i < 2; i++) {
@@ -1795,12 +1798,6 @@
 
 #include "isdnl1.h"
 
-static void hisax_sched_event(struct IsdnCardState *cs, int event)
-{
-	cs->event |= 1 << event;
-	schedule_work(&cs->work);
-}
-
 static void hisax_bh(void *data)
 {
 	struct IsdnCardState *cs = data;
@@ -1822,12 +1819,6 @@
 	}
 }
 
-static void hisax_b_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
 static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg)
 {
 	struct hisax_if *ifc = (struct hisax_if *) d_if;
@@ -1850,15 +1841,15 @@
 	switch (pr) {
 	case PH_ACTIVATE | INDICATION:
 		set_bit(0, &d_if->ph_state);
-		hisax_sched_event(cs, D_L1STATECHANGE);
+		sched_d_event(cs, D_L1STATECHANGE);
 		break;
 	case PH_DEACTIVATE | INDICATION:
 		clear_bit(0, &d_if->ph_state);
-		hisax_sched_event(cs, D_L1STATECHANGE);
+		sched_d_event(cs, D_L1STATECHANGE);
 		break;
 	case PH_DATA | INDICATION:
 		skb_queue_tail(&cs->rq, arg);
-		hisax_sched_event(cs, D_RCVBUFREADY);
+		sched_d_event(cs, D_RCVBUFREADY);
 		break;
 	case PH_DATA | CONFIRM:
 		skb = skb_dequeue(&cs->sq);
@@ -1876,7 +1867,7 @@
 		break;
 	case PH_DATA_E | INDICATION:
 		skb_queue_tail(&d_if->erq, arg);
-		hisax_sched_event(cs, E_RCVBUFREADY);
+		sched_d_event(cs, E_RCVBUFREADY);
 		break;
 	default:
 		printk("pr %#x\n", pr);
@@ -1904,12 +1895,12 @@
 		break;
 	case PH_DATA | INDICATION:
 		skb_queue_tail(&bcs->rqueue, arg);
-		hisax_b_sched_event(bcs, B_RCVBUFREADY);
+		sched_b_event(bcs, B_RCVBUFREADY);
 		break;
 	case PH_DATA | CONFIRM:
-		bcs->tx_cnt -= (int) arg;
-		if (bcs->st->lli.l1writewakeup)
-			bcs->st->lli.l1writewakeup(bcs->st, (int) arg);
+		skb = arg;
+		bcs->tx_cnt -= skb->truesize;
+		xmit_complete_b(bcs);
 		skb = skb_dequeue(&bcs->squeue);
 		if (skb) {
 			B_L2L1(b_if, PH_DATA | REQUEST, skb);
@@ -2050,33 +2041,6 @@
 						skb->len);
 		}
 		dev_kfree_skb_any(skb);
-	}
-}
-
-void HiSax_mod_dec_use_count(struct IsdnCardState *cs)
-{
-	struct module *mod;
-
-	if (cs && cs->cardmsg == hisax_cardmsg) {
-		mod = cs->hw.hisax_d_if->owner;
-		if (mod)
-			__MOD_DEC_USE_COUNT(mod);
-	} else {
-		MOD_DEC_USE_COUNT;
-	}
-}
-
-void HiSax_mod_inc_use_count(struct IsdnCardState *cs)
-{
-	struct module *mod;
-
-	if (cs && cs->cardmsg == hisax_cardmsg) {
-		mod = cs->hw.hisax_d_if->owner;
-		if (mod)
-		// hope we do win the race...
-			try_inc_mod_count(mod);
-	} else {
-		MOD_INC_USE_COUNT;
 	}
 }
 
diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
--- a/drivers/isdn/hisax/diva.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hisax/diva.c	Wed Nov 27 14:36:32 2002
@@ -307,10 +307,7 @@
 	u_char val, sval;
 	int cnt=5;
 
-	if (!cs) {
-		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) {
 		val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40);
 		if (val)
@@ -328,6 +325,7 @@
 	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
 	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
 	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 static void
@@ -456,46 +454,19 @@
 Memhscx_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int more, count, cnt;
+	int more, count;
 	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
-	u_char *ptr,*p;
-	unsigned long flags;
+	unsigned char *p;
 
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "hscx_fill_fifo");
-
-	if (!bcs->tx_skb)
-		return;
-	if (bcs->tx_skb->len <= 0)
+	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
+	if (!p)
 		return;
 
-	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
-	if (bcs->tx_skb->len > fifo_size) {
-		more = !0;
-		count = fifo_size;
-	} else
-		count = bcs->tx_skb->len;
-	cnt = count;
 	MemwaitforXFW(cs, bcs->hw.hscx.hscx);
-	spin_lock_irqsave(&diva_lock, flags);
-	p = ptr = bcs->tx_skb->data;
-	skb_pull(bcs->tx_skb, count);
-	bcs->tx_cnt -= count;
-	bcs->hw.hscx.count += count;
-	while(cnt--)
+	while (count--)
 		memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0,
 			*p++);
 	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
-	spin_unlock_irqrestore(&diva_lock, flags);
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
-			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
 }
 
 static inline void
@@ -542,7 +513,7 @@
 			}
 		}
 		bcs->hw.hscx.rcvidx = 0;
-		hscx_sched_event(bcs, B_RCVBUFREADY);
+		sched_b_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		Memhscx_empty_fifo(bcs, fifo_size);
@@ -555,34 +526,20 @@
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
 			bcs->hw.hscx.rcvidx = 0;
-			hscx_sched_event(bcs, B_RCVBUFREADY);
+			sched_b_event(bcs, B_RCVBUFREADY);
 		}
 	}
-	if (val & 0x10) {	/* XPR */
-		if (bcs->tx_skb) {
-			if (bcs->tx_skb->len) {
-				Memhscx_fill_fifo(bcs);
-				return;
-			} else {
-				if (bcs->st->lli.l1writewakeup &&
-					(PACKET_NOACK != bcs->tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				dev_kfree_skb_irq(bcs->tx_skb);
-				bcs->hw.hscx.count = 0; 
-				bcs->tx_skb = NULL;
-			}
-		}
-		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-			bcs->hw.hscx.count = 0;
-			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
-			Memhscx_fill_fifo(bcs);
-		} else {
-			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-			hscx_sched_event(bcs, B_XMTBUFREADY);
-		}
+	if (val & 0x10) {
+		xmit_xpr_b(bcs);/* XPR */
 	}
 }
 
+static void
+Memhscx_reset_xmit(struct BCState *bcs)
+{
+	MemWriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01);
+}
+
 static inline void
 Memhscx_int_main(struct IsdnCardState *cs, u_char val)
 {
@@ -594,23 +551,10 @@
 		bcs = cs->bcs + 1;
 		exval = MemReadHSCX(cs, 1, HSCX_EXIR);
 		if (exval & 0x40) {
-			if (bcs->mode == 1)
-				Memhscx_fill_fifo(bcs);
-			else {
-				/* Here we lost an TX interrupt, so
-				   * restart transmitting the whole frame.
-				 */
-				if (bcs->tx_skb) {
-					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
-					bcs->tx_cnt += bcs->hw.hscx.count;
-					bcs->hw.hscx.count = 0;
-				}
-				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
-			}
-		} else if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX B EXIR %x", exval);
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "HSCX B EXIR %x", exval);
+			xmit_xdu_b(bcs, Memhscx_reset_xmit);
+		}
 	}
 	if (val & 0xf8) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -621,23 +565,10 @@
 		bcs = cs->bcs;
 		exval = MemReadHSCX(cs, 0, HSCX_EXIR);
 		if (exval & 0x40) {
-			if (bcs->mode == L1_MODE_TRANS)
-				Memhscx_fill_fifo(bcs);
-			else {
-				/* Here we lost an TX interrupt, so
-				   * restart transmitting the whole frame.
-				 */
-				if (bcs->tx_skb) {
-					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
-					bcs->tx_cnt += bcs->hw.hscx.count;
-					bcs->hw.hscx.count = 0;
-				}
-				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
-			}
-		} else if (cs->debug & L1_DEB_HSCX)
-			debugl1(cs, "HSCX A EXIR %x", exval);
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "HSCX A EXIR %x", exval);
+			xmit_xdu_b(bcs, Memhscx_reset_xmit);
+		}
 	}
 	if (val & 0x04) {	// ICA
 		exval = MemReadHSCX(cs, 0, HSCX_ISTA);
@@ -714,7 +645,7 @@
 	cfg = (u_char *) cs->hw.diva.pci_cfg;
 	val = *cfg;
 	if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ
-  interrupt_ipacx(cs);      // handler for chip
+	interrupt_ipacx(cs);      // handler for chip
 	*cfg = PITA_INT0_STATUS;  // Reset PLX interrupt
 }
 
@@ -860,7 +791,7 @@
 				ireg = (unsigned int *)cs->hw.diva.pci_cfg;
 				*ireg = PITA_INT0_ENABLE;
 			}
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -1163,7 +1094,7 @@
 		cs->writeisacfifo = &MemWriteISACfifo_IPACX;
 		cs->BC_Read_Reg  = &MemReadHSCX_IPACX;
 		cs->BC_Write_Reg = &MemWriteHSCX_IPACX;
-		cs->BC_Send_Data = 0; // function located in ipacx module
+		cs->BC_Send_Data = &ipacx_fill_fifo;
 		cs->irq_func = &diva_irq_ipacx_pci;
 		printk(KERN_INFO "Diva: IPACX Design Id: %x\n", 
             MemReadISAC_IPACX(cs, IPACX_ID) &0x3F);
diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
--- a/drivers/isdn/hisax/elsa.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/elsa.c	Wed Nov 27 14:36:28 2002
@@ -308,15 +308,12 @@
 	u_char val;
 	int icnt=5;
 
-	if (!cs) {
-		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
 	/* The card tends to generate interrupts while being removed
 	   causing us to just crash the kernel. bad. */
 		printk(KERN_WARNING "Elsa: card not available!\n");
-		return;
+		goto unlock;
 	}
 #if ARCOFI_USE
 	if (cs->hw.elsa.MFlag) {
@@ -378,6 +375,8 @@
 	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0);
 	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0);
 	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0);
+ unlock:
+	spin_unlock(&cs->lock);
 }
 
 static void
@@ -679,7 +678,6 @@
 			return(0);
 		case CARD_INIT:
 			cs->debug |= L1_DEB_IPAC;
-			inithscxisac(cs, 1);
 			if ((cs->subtyp == ELSA_QS1000) ||
 			    (cs->subtyp == ELSA_QS3000))
 			{
@@ -687,7 +685,7 @@
 			}
 			if (cs->hw.elsa.trig)
 				byteout(cs->hw.elsa.trig, 0xff);
-			inithscxisac(cs, 2);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			if ((cs->subtyp == ELSA_PCMCIA) ||
diff -Nru a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
--- a/drivers/isdn/hisax/elsa_ser.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/elsa_ser.c	Wed Nov 27 14:36:28 2002
@@ -292,30 +292,10 @@
 	return(ret);
 }
 
-inline void
-modem_fill(struct BCState *bcs) {
-		
-	if (bcs->tx_skb) {
-		if (bcs->tx_skb->len) {
-			write_modem(bcs);
-			return;
-		} else {
-			if (bcs->st->lli.l1writewakeup &&
-				(PACKET_NOACK != bcs->tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st,
-						bcs->hw.hscx.count);
-			dev_kfree_skb_any(bcs->tx_skb);
-			bcs->tx_skb = NULL;
-		}
-	}
-	if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-		bcs->hw.hscx.count = 0;
-		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
-		write_modem(bcs);
-	} else {
-		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		hscx_sched_event(bcs, B_XMTBUFREADY);
-	}
+static void
+modem_fill(struct BCState *bcs)
+{
+	xmit_xpr_b(bcs);
 }
 
 static inline void receive_chars(struct IsdnCardState *cs,
@@ -349,7 +329,7 @@
 				cs->hw.elsa.rcvcnt);
 			skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb);
 		}
-		hscx_sched_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
+		sched_b_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
 	} else {
 		char tmp[128];
 		char *t = tmp;
@@ -580,7 +560,7 @@
 		} else {
 			st->l1.bcs->tx_skb = skb;
 			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->hw.hscx.count = 0;
+			st->l1.bcs->count = 0;
 			spin_unlock_irqrestore(&elsa_ser_lock, flags);
 			write_modem(st->l1.bcs);
 		}
@@ -613,6 +593,7 @@
 			if (open_hscxstate(st->l1.hardware, bcs))
 				return (-1);
 			st->l1.l2l1 = hscx_l2l1;
+			// bcs->cs->BC_Send_Data = hscx_fill_fifo;
 			break;
 		case L1_MODE_MODEM:
 			bcs->mode = L1_MODE_MODEM;
@@ -628,6 +609,7 @@
 			bcs->tx_cnt = 0;
 			bcs->cs->hw.elsa.bcs = bcs;
 			st->l1.l2l1 = modem_l2l1;
+			bcs->cs->BC_Send_Data = modem_fill;
 			break;
 	}
 	st->l1.bcs = bcs;
diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
--- a/drivers/isdn/hisax/enternow_pci.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/enternow_pci.c	Wed Nov 27 14:36:31 2002
@@ -75,7 +75,6 @@
 
 
 const char *enternow_pci_rev = "$Revision: 1.1.2.1 $";
-static spinlock_t enternow_pci_lock = SPIN_LOCK_UNLOCKED;
 
 /* *************************** I/O-Interface functions ************************************* */
 
@@ -231,13 +230,8 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	BYTE sval, ir;
-	unsigned long flags;
 
-
-	if (!cs) {
-		printk(KERN_WARNING "enter:now PCI: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 
 	sval = InByte(cs->hw.njet.base + NETJET_IRQSTAT1);
 
@@ -251,7 +245,6 @@
 	/* DMA-Interrupt: B-channel-stuff */
 	/* set bits in sval to indicate which page is free */
 
-	spin_lock_irqsave(&enternow_pci_lock, flags);
 	/* set bits in sval to indicate which page is free */
 	if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
 		inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
@@ -265,14 +258,8 @@
 		sval = sval | 0x02;
 	else	/* the 1st read page is free */
 		sval = sval | 0x01;
-	if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */
-	{
-		if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-			spin_unlock_irqrestore(&enternow_pci_lock, flags);
-			return;
-		}
+	if (sval != cs->hw.njet.last_is0) { /* we have a DMA interrupt */
 		cs->hw.njet.irqstat0 = sval;
-		spin_unlock_irqrestore(&enternow_pci_lock, flags);
 		if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) !=
 			(cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
 			/* we have a read dma int */
@@ -281,9 +268,8 @@
 			(cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE))
 			/* we have a write dma int */
 			write_tiger(cs);
-		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	} else
-		spin_unlock_irqrestore(&enternow_pci_lock, flags);
+	}
+	spin_unlock(&cs->lock);
 }
 
 
@@ -296,7 +282,6 @@
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	unsigned long flags;
 
 #if CONFIG_PCI
 #ifdef __BIG_ENDIAN
@@ -306,7 +291,6 @@
 	printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_ENTERNOW)
 		return(0);
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
 	for ( ;; )
 	{
@@ -343,9 +327,6 @@
 		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
 		cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
 
-		save_flags(flags);
-		sti();
-
 		/* Reset an */
 		cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
 		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
@@ -359,8 +340,6 @@
 
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		restore_flags(flags);
 
 		cs->hw.njet.auxd = 0x00; // war 0xc0
 		cs->hw.njet.dmactrl = 0;
diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
--- a/drivers/isdn/hisax/gazel.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/hisax/gazel.c	Wed Nov 27 14:36:30 2002
@@ -259,10 +259,7 @@
 	u_char valisac, valhscx;
 	int count = 0;
 
-	if (!cs) {
-		printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	do {
 		valhscx = ReadHSCX(cs, 1, HSCX_ISTA);
 		if (valhscx)
@@ -279,6 +276,7 @@
 	WriteISAC(cs, ISAC_MASK, 0x0);
 	WriteHSCX(cs, 0, HSCX_MASK, 0x0);
 	WriteHSCX(cs, 1, HSCX_MASK, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 
@@ -421,7 +419,7 @@
 			release_io_gazel(cs);
 			return (0);
 		case CARD_INIT:
-			inithscxisac(cs, 1);
+			inithscxisac(cs);
 			if ((cs->subtyp==R647)||(cs->subtyp==R685)) {
 				int i;
 				for (i=0;i<(2+MAX_WAITING_CALLS);i++) {
diff -Nru a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
--- a/drivers/isdn/hisax/hfc_2bds0.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/hfc_2bds0.c	Wed Nov 27 14:36:27 2002
@@ -106,15 +106,11 @@
 static inline int
 WaitNoBusy(struct IsdnCardState *cs)
 {
-	long flags;
 	int to = 130;
 
 	while ((ReadReg(cs, HFCD_STATUS, HFCD_STATUS) & HFCD_BUSY) && to) {
-		save_flags(flags);
-		sti();
 		udelay(1);
 		to--;
-		restore_flags(flags);
 	}
 	if (!to) 
 		printk(KERN_WARNING "HiSax: WaitNoBusy timeout\n");
@@ -125,13 +121,10 @@
 SelFiFo(struct IsdnCardState *cs, u_char FiFo)
 {
 	u_char cip;
-	long flags;
-
 
 	if (cs->hw.hfcD.fifo == FiFo)
 		return(1);
-	save_flags(flags);
-	cli();
+
 	switch(FiFo) {
 		case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1;
 			break;
@@ -146,16 +139,13 @@
 		case 5: cip = HFCD_FIFO | HFCD_Z1 | HFCD_REC;
 			break;
 		default:
-			restore_flags(flags);
 			debugl1(cs, "SelFiFo Error");
 			return(0);
 	}
 	cs->hw.hfcD.fifo = FiFo;
 	WaitNoBusy(cs);
 	cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0);
-	sti();
 	WaitForBusy(cs);
-	restore_flags(flags);
 	return(2);
 }
 static int
@@ -198,13 +188,6 @@
 	return (val);
 }
 
-static void
-hfc_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
 static struct sk_buff
 *hfc_empty_fifo(struct BCState *bcs, int count)
 {
@@ -213,22 +196,18 @@
 	struct IsdnCardState *cs = bcs->cs;
 	int idx;
 	int chksum;
-	long flags;
 	u_char stat, cip;
 	
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfc_empty_fifo");
 	idx = 0;
-	save_flags(flags);
 	if (count > HSCX_BUFMAX + 3) {
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "hfc_empty_fifo: incoming packet too large");
 		cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
 		while (idx++ < count) {
-			cli();
 			WaitNoBusy(cs);
 			ReadReg(cs, HFCD_DATA_NODEB, cip);
-			sti();
 		}
 		skb = NULL;
 	} else if (count < 4) {
@@ -238,7 +217,6 @@
 #ifdef ERROR_STATISTIC
 		bcs->err_inv++;
 #endif
-		cli();
 		while ((idx++ < count) && WaitNoBusy(cs))
 			ReadReg(cs, HFCD_DATA_NODEB, cip);
 		skb = NULL;
@@ -248,31 +226,25 @@
 		ptr = skb_put(skb, count - 3);
 		idx = 0;
 		cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
-		cli();
 		while (idx < (count - 3)) {
-			cli();
 			if (!WaitNoBusy(cs))
 				break;
 			*ptr = ReadReg(cs,  HFCD_DATA_NODEB, cip);
-			sti();
 			ptr++;
 			idx++;
 		}
 		if (idx != count - 3) {
-			sti();
 			debugl1(cs, "RFIFO BUSY error");
 			printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
 			dev_kfree_skb_irq(skb);
 			skb = NULL;
 		} else {
-			cli();
 			WaitNoBusy(cs);
 			chksum = (ReadReg(cs, HFCD_DATA, cip) << 8);
 			WaitNoBusy(cs);
 			chksum += ReadReg(cs, HFCD_DATA, cip);
 			WaitNoBusy(cs);
 			stat = ReadReg(cs, HFCD_DATA, cip);
-			sti();
 			if (cs->debug & L1_DEB_HSCX)
 				debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
 					bcs->channel, chksum, stat);
@@ -286,15 +258,11 @@
 			}
 		}
 	}
-	sti();
 	WaitForBusy(cs);
-	cli();
 	WaitNoBusy(cs);
 	stat = ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F2_INC |
 		HFCB_REC | HFCB_CHANNEL(bcs->channel));
-	sti();
 	WaitForBusy(cs);
-	restore_flags(flags);
 	return (skb);
 }
 
@@ -302,7 +270,6 @@
 hfc_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	long flags;
 	int idx, fcnt;
 	int count;
 	u_char cip;
@@ -311,8 +278,6 @@
 		return;
 	if (bcs->tx_skb->len <= 0)
 		return;
-	save_flags(flags);
-	cli();
 	SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel)); 
 	cip = HFCB_FIFO | HFCB_F1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel);
 	WaitNoBusy(cs);
@@ -322,7 +287,6 @@
 	WaitNoBusy(cs);
 	bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip);
 	bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
-	sti();
  	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
 			bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
@@ -333,7 +297,6 @@
 	if (fcnt > 30) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfc_fill_fifo more as 30 frames");
-		restore_flags(flags);
 		return;
 	}
 	count = GetFreeFifoBytes_B(bcs);
@@ -344,77 +307,45 @@
 	if (count < bcs->tx_skb->len) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfc_fill_fifo no fifo mem");
-		restore_flags(flags);
 		return;
 	}
 	cip = HFCB_FIFO | HFCB_FIFO_IN | HFCB_SEND | HFCB_CHANNEL(bcs->channel);
 	idx = 0;
-	cli();
 	WaitForBusy(cs);
 	WaitNoBusy(cs);
 	WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
 	while (idx < bcs->tx_skb->len) {
-		cli();
 		if (!WaitNoBusy(cs))
 			break;
 		WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]);
-		sti();
 		idx++;
 	}
 	if (idx != bcs->tx_skb->len) {
-		sti();
 		debugl1(cs, "FIFO Send BUSY error");
 		printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
 	} else {
 		bcs->tx_cnt -= bcs->tx_skb->len;
-		if (bcs->st->lli.l1writewakeup &&
-			(PACKET_NOACK != bcs->tx_skb->pkt_type))
-			bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
-		dev_kfree_skb_any(bcs->tx_skb);
-		bcs->tx_skb = NULL;
+		xmit_complete_b(bcs);
 	}
 	WaitForBusy(cs);
-	cli();
 	WaitNoBusy(cs);
 	ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F1_INC | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
-	sti();
 	WaitForBusy(cs);
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	restore_flags(flags);
 	return;
 }
 
-static void
-hfc_send_data(struct BCState *bcs)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	
-	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		hfc_fill_fifo(bcs);
-		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	} else
-		debugl1(cs,"send_data %d blocked", bcs->channel);
-}
-
 void
 main_rec_2bds0(struct BCState *bcs)
 {
-	long flags;
 	struct IsdnCardState *cs = bcs->cs;
 	int z1, z2, rcnt;
 	u_char f1, f2, cip;
 	int receive, count = 5;
 	struct sk_buff *skb;
 
-	save_flags(flags);
     Begin:
 	count--;
-	cli();
-	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		debugl1(cs,"rec_data %d blocked", bcs->channel);
-		restore_flags(flags);
-		return;
-	}
 	SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel));
 	cip = HFCB_FIFO | HFCB_F1 | HFCB_REC | HFCB_CHANNEL(bcs->channel);
 	WaitNoBusy(cs);
@@ -422,15 +353,12 @@
 	cip = HFCB_FIFO | HFCB_F2 | HFCB_REC | HFCB_CHANNEL(bcs->channel);
 	WaitNoBusy(cs);
 	f2 = ReadReg(cs, HFCD_DATA, cip);
-	sti();
 	if (f1 != f2) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
 				bcs->channel, f1, f2);
-		cli();
 		z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
 		z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
-		sti();
 		rcnt = z1 - z2;
 		if (rcnt < 0)
 			rcnt += cs->hw.hfcD.bfifosize;
@@ -439,10 +367,8 @@
 			debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
 				bcs->channel, z1, z2, rcnt);
 		if ((skb = hfc_empty_fifo(bcs, rcnt))) {
-			cli();
 			skb_queue_tail(&bcs->rqueue, skb);
-			sti();
-			hfc_sched_event(bcs, B_RCVBUFREADY);
+			sched_b_event(bcs, B_RCVBUFREADY);
 		}
 		rcnt = f1 -f2;
 		if (rcnt<0)
@@ -453,10 +379,8 @@
 			receive = 0;
 	} else
 		receive = 0;
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;	
-	restore_flags(flags);
 	return;
 }
 
@@ -512,40 +436,16 @@
 hfc_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			save_flags(flags);
-			cli();
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				restore_flags(flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-/*				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-*/				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-				restore_flags(flags);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
-				break;
-			}
-			save_flags(flags);
-			cli();
-/*			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-*/			st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			restore_flags(flags);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
@@ -642,18 +542,10 @@
 		DChannel_proc_xmt(cs);
 }
 
-void
-sched_event_D(struct IsdnCardState *cs, int event)
-{
-	test_and_set_bit(event, &cs->event);
-	schedule_work(&cs->work);
-}
-
 static
 int receive_dmsg(struct IsdnCardState *cs)
 {
 	struct sk_buff *skb;
-	long flags;
 	int idx;
 	int rcnt, z1, z2;
 	u_char stat, cip, f1, f2;
@@ -661,13 +553,6 @@
 	int count=5;
 	u_char *ptr;
 
-	save_flags(flags);
-	cli();
-	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		debugl1(cs, "rec_dmsg blocked");
-		restore_flags(flags);
-		return(1);
-	}
 	SelFiFo(cs, 4 | HFCD_REC);
 	cip = HFCD_FIFO | HFCD_F1 | HFCD_REC;
 	WaitNoBusy(cs);
@@ -685,39 +570,32 @@
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
 				f1, f2, z1, z2, rcnt);
-		sti();
 		idx = 0;
 		cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC;
 		if (rcnt > MAX_DFRAME_LEN + 3) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "empty_fifo d: incoming packet too large");
 			while (idx < rcnt) {
-				cli();
 				if (!(WaitNoBusy(cs)))
 					break;
 				ReadReg(cs, HFCD_DATA_NODEB, cip);
-				sti();
 				idx++;
 			}
 		} else if (rcnt < 4) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "empty_fifo d: incoming packet too small");
-			cli();
 			while ((idx++ < rcnt) && WaitNoBusy(cs))
 				ReadReg(cs, HFCD_DATA_NODEB, cip);
 		} else if ((skb = dev_alloc_skb(rcnt - 3))) {
 			ptr = skb_put(skb, rcnt - 3);
 			while (idx < (rcnt - 3)) {
-				cli();
 				if (!(WaitNoBusy(cs)))
 					break;
 				*ptr = ReadReg(cs, HFCD_DATA_NODEB, cip);
-				sti();
 				idx++;
 				ptr++;
 			}
 			if (idx != (rcnt - 3)) {
-				sti();
 				debugl1(cs, "RFIFO D BUSY error");
 				printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n");
 				dev_kfree_skb_irq(skb);
@@ -726,14 +604,12 @@
 				cs->err_rx++;
 #endif
 			} else {
-				cli();
 				WaitNoBusy(cs);
 				chksum = (ReadReg(cs, HFCD_DATA, cip) << 8);
 				WaitNoBusy(cs);
 				chksum += ReadReg(cs, HFCD_DATA, cip);
 				WaitNoBusy(cs);
 				stat = ReadReg(cs, HFCD_DATA, cip);
-				sti();
 				if (cs->debug & L1_DEB_ISAC)
 					debugl1(cs, "empty_dfifo chksum %x stat %x",
 						chksum, stat);
@@ -746,33 +622,26 @@
 #endif
 				} else {
 					skb_queue_tail(&cs->rq, skb);
-					sched_event_D(cs, D_RCVBUFREADY);
+					sched_d_event(cs, D_RCVBUFREADY);
 				}
 			}
 		} else
 			printk(KERN_WARNING "HFC: D receive out of memory\n");
-		sti();
 		WaitForBusy(cs);
 		cip = HFCD_FIFO | HFCD_F2_INC | HFCD_REC;
-		cli();
 		WaitNoBusy(cs);
 		stat = ReadReg(cs, HFCD_DATA, cip);
-		sti();
 		WaitForBusy(cs);
 		cip = HFCD_FIFO | HFCD_F2 | HFCD_REC;
-		cli();
 		WaitNoBusy(cs);
 		f2 = cs->readisac(cs, cip) & 0xf;
 	}
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	restore_flags(flags);
 	return(1);
 } 
 
 static void
 hfc_fill_dfifo(struct IsdnCardState *cs)
 {
-	long flags;
 	int idx, fcnt;
 	int count;
 	u_char cip;
@@ -782,8 +651,6 @@
 	if (cs->tx_skb->len <= 0)
 		return;
 
-	save_flags(flags);
-	cli();
 	SelFiFo(cs, 4 | HFCD_SEND);
 	cip = HFCD_FIFO | HFCD_F1 | HFCD_SEND;
 	WaitNoBusy(cs);
@@ -792,7 +659,6 @@
 	cip = HFCD_FIFO | HFCD_F2 | HFCD_SEND;
 	cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf;
 	cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND);
-	sti();
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
 			cs->hw.hfcD.f1, cs->hw.hfcD.f2,
@@ -803,7 +669,6 @@
 	if (fcnt > 14) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfc_fill_Dfifo more as 14 frames");
-		restore_flags(flags);
 		return;
 	}
 	count = GetFreeFifoBytes_D(cs);
@@ -813,37 +678,29 @@
 	if (count < cs->tx_skb->len) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "hfc_fill_Dfifo no fifo mem");
-		restore_flags(flags);
 		return;
 	}
 	cip = HFCD_FIFO | HFCD_FIFO_IN | HFCD_SEND;
 	idx = 0;
-	cli();
 	WaitForBusy(cs);
 	WaitNoBusy(cs);
 	WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx++]);
 	while (idx < cs->tx_skb->len) {
-		cli();
 		if (!(WaitNoBusy(cs)))
 			break;
 		WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx]);
-		sti();
 		idx++;
 	}
 	if (idx != cs->tx_skb->len) {
-		sti();
 		debugl1(cs, "DFIFO Send BUSY error");
 		printk(KERN_WARNING "HFC S DFIFO channel BUSY Error\n");
 	}
 	WaitForBusy(cs);
-	cli();
 	WaitNoBusy(cs);
 	ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND);
 	dev_kfree_skb_any(cs->tx_skb);
 	cs->tx_skb = NULL;
-	sti();
 	WaitForBusy(cs);
-	restore_flags(flags);
 	return;
 }
 
@@ -864,12 +721,10 @@
        	u_char exval;
        	struct BCState *bcs;
 	int count=15;
-	long flags;
 
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFCD irq %x %s", val,
-			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
-			"locked" : "unlocked");
+		debugl1(cs, "HFCD irq %x", val);
+
 	val &= cs->hw.hfcD.int_m1;
 	if (val & 0x40) { /* TE state machine irq */
 		exval = cs->readisac(cs, HFCD_STATES) & 0xf;
@@ -877,17 +732,10 @@
 			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state,
 				exval);
 		cs->dc.hfcd.ph_state = exval;
-		sched_event_D(cs, D_L1STATECHANGE);
+		sched_d_event(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
 	while (val) {
-		save_flags(flags);
-		cli();
-		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-			cs->hw.hfcD.int_s1 |= val;
-			restore_flags(flags);
-			return;
-		}
 		if (cs->hw.hfcD.int_s1 & 0x18) {
 			exval = val;
 			val =  cs->hw.hfcD.int_s1;
@@ -912,23 +760,7 @@
 				if (cs->debug)
 					debugl1(cs, "hfcd spurious 0x01 IRQ");
 			} else {
-				if (bcs->tx_skb) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfc_fill_fifo(bcs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else
-						debugl1(cs,"fill_data %d blocked", bcs->channel);
-				} else {
-					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-							hfc_fill_fifo(bcs);
-							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else
-							debugl1(cs,"fill_data %d blocked", bcs->channel);
-					} else {
-						hfc_sched_event(bcs, B_XMTBUFREADY);
-					}
-				}
+				xmit_xpr_b(bcs);
 			}
 		}
 		if (val & 0x02) {
@@ -936,60 +768,15 @@
 				if (cs->debug)
 					debugl1(cs, "hfcd spurious 0x02 IRQ");
 			} else {
-				if (bcs->tx_skb) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfc_fill_fifo(bcs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else
-						debugl1(cs,"fill_data %d blocked", bcs->channel);
-				} else {
-					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-							hfc_fill_fifo(bcs);
-							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else
-							debugl1(cs,"fill_data %d blocked", bcs->channel);
-					} else {
-						hfc_sched_event(bcs, B_XMTBUFREADY);
-					}
-				}
+				xmit_xpr_b(bcs);
 			}
 		}
 		if (val & 0x20) {	/* receive dframe */
 			receive_dmsg(cs);
 		}
 		if (val & 0x04) {	/* dframe transmitted */
-			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-				del_timer(&cs->dbusytimer);
-			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				sched_event_D(cs, D_CLEARBUSY);
-			if (cs->tx_skb) {
-				if (cs->tx_skb->len) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfc_fill_dfifo(cs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else {
-						debugl1(cs, "hfc_fill_dfifo irq blocked");
-					}
-					goto afterXPR;
-				} else {
-					dev_kfree_skb_irq(cs->tx_skb);
-					cs->tx_cnt = 0;
-					cs->tx_skb = NULL;
-				}
-			}
-			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
-				cs->tx_cnt = 0;
-				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-					hfc_fill_dfifo(cs);
-					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-				} else {
-					debugl1(cs, "hfc_fill_dfifo irq blocked");
-				}
-			} else
-				sched_event_D(cs, D_XMTBUFREADY);
+			xmit_xpr_d(cs);
 		}
-      afterXPR:
 		if (cs->hw.hfcD.int_s1 && count--) {
 			val = cs->hw.hfcD.int_s1;
 			cs->hw.hfcD.int_s1 = 0;
@@ -997,7 +784,6 @@
 				debugl1(cs, "HFCD irq %x loop %d", val, 15-count);
 		} else
 			val = 0;
-		restore_flags(flags);
 	}
 }
 
@@ -1009,64 +795,13 @@
 	
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-					hfc_fill_dfifo(cs);
-					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-				} else
-					debugl1(cs, "hfc_fill_dfifo blocked");
-
-			}
+			xmit_data_req_d(cs, skb);
 			break;
-		case (PH_PULL | INDICATION):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-				hfc_fill_dfifo(cs);
-				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-			} else
-				debugl1(cs, "hfc_fill_dfifo blocked");
+		case (PH_PULL |INDICATION):
+			xmit_pull_ind_d(cs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_d(st);
 			break;
 		case (HW_RESET | REQUEST):
 			cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */
@@ -1135,7 +870,8 @@
 		cs->bcs[0].hw.hfc.send = init_send_hfcd(32);
 	if (!cs->bcs[1].hw.hfc.send)
 		cs->bcs[1].hw.hfc.send = init_send_hfcd(32);
-	cs->BC_Send_Data = &hfc_send_data;
+	cs->BC_Send_Data = hfc_fill_fifo;
+	cs->DC_Send_Data = hfc_fill_dfifo;
 	cs->bcs[0].BC_SetStack = setstack_2b;
 	cs->bcs[1].BC_SetStack = setstack_2b;
 	cs->bcs[0].BC_Close = close_2bs0;
diff -Nru a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
--- a/drivers/isdn/hisax/hfc_2bs0.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/hfc_2bs0.c	Wed Nov 27 14:36:27 2002
@@ -21,18 +21,14 @@
 WaitForBusy(struct IsdnCardState *cs)
 {
 	int to = 130;
-	long flags;
 	u_char val;
 
-	save_flags(flags);
-	cli();
 	while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) {
 		val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 |
 				      (cs->hw.hfc.cip & 3));
 		udelay(1);
 		to--;
 	}
-	restore_flags(flags);
 	if (!to) {
 		printk(KERN_WARNING "HiSax: waitforBusy timeout\n");
 		return (0);
@@ -82,26 +78,17 @@
 	return (val);
 }
 
-void
-hfc_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
 static void
 hfc_clear_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	long flags;
 	int idx, cnt;
 	int rcnt, z1, z2;
 	u_char cip, f1, f2;
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfc_clear_fifo");
-	save_flags(flags);
-	cli();
+
 	cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
 	if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
 		cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
@@ -148,7 +135,6 @@
 		z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
 		z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
 	}
-	restore_flags(flags);
 	return;
 }
 
@@ -251,7 +237,6 @@
 hfc_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	long flags;
 	int idx, fcnt;
 	int count;
 	int z1, z2;
@@ -262,8 +247,6 @@
 	if (bcs->tx_skb->len <= 0)
 		return;
 
-	save_flags(flags);
-	cli();
 	cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel);
 	if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
 	  cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip);
@@ -286,7 +269,6 @@
 	  if (fcnt > 30) {
 	    if (cs->debug & L1_DEB_HSCX)
 	      debugl1(cs, "hfc_fill_fifo more as 30 frames");
-	    restore_flags(flags);
 	    return;
 	  }
 	  count = GetFreeFifoBytes(bcs);
@@ -306,7 +288,6 @@
 	if (count < bcs->tx_skb->len) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfc_fill_fifo no fifo mem");
-		restore_flags(flags);
 		return;
 	}
 	cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
@@ -321,34 +302,28 @@
 		bcs->tx_cnt -= count;
 		if (PACKET_NOACK == bcs->tx_skb->pkt_type)
 			count = -1;
-		dev_kfree_skb_any(bcs->tx_skb);
-		bcs->tx_skb = NULL;
+
+		xmit_complete_b(bcs);
 		if (bcs->mode != L1_MODE_TRANS) {
 		  WaitForBusy(cs);
 		  WaitNoBusy(cs);
 		  cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
 		}
-		if (bcs->st->lli.l1writewakeup && (count >= 0))
-			bcs->st->lli.l1writewakeup(bcs->st, count);
 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	}
-	restore_flags(flags);
 	return;
 }
 
 void
 main_irq_hfc(struct BCState *bcs)
 {
-	long flags;
 	struct IsdnCardState *cs = bcs->cs;
 	int z1, z2, rcnt;
 	u_char f1, f2, cip;
 	int receive, transmit, count = 5;
 	struct sk_buff *skb;
 
-	save_flags(flags);
       Begin:
-	cli();
 	count--;
 	cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel);
 	if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) {
@@ -381,17 +356,14 @@
 			if (cs->debug & L1_DEB_HSCX)
 				debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
 					bcs->channel, z1, z2, rcnt);
-			/*              sti(); */
 			if ((skb = hfc_empty_fifo(bcs, rcnt))) {
 				skb_queue_tail(&bcs->rqueue, skb);
-				hfc_sched_event(bcs, B_RCVBUFREADY);
+				sched_b_event(bcs, B_RCVBUFREADY);
 			}
 		}
 		receive = 1;
 	}
-	restore_flags(flags);
 	udelay(1);
-	cli();
 	if (bcs->tx_skb) {
 		transmit = 1;
 		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
@@ -407,10 +379,9 @@
 				transmit = 0;
 		} else {
 			transmit = 0;
-			hfc_sched_event(bcs, B_XMTBUFREADY);
+			sched_b_event(bcs, B_XMTBUFREADY);
 		}
 	}
-	restore_flags(flags);
 	if ((receive || transmit) && count)
 		goto Begin;
 	return;
@@ -474,40 +445,16 @@
 hfc_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			save_flags(flags);
-			cli();
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				restore_flags(flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-				restore_flags(flags);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
-				break;
-			}
-			save_flags(flags);
-			cli();
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			restore_flags(flags);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
--- a/drivers/isdn/hisax/hfc_pci.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/isdn/hisax/hfc_pci.c	Wed Nov 27 14:36:29 2002
@@ -73,21 +73,15 @@
 void
 release_io_hfcpci(struct IsdnCardState *cs)
 {
-	unsigned long flags;
-
 	printk(KERN_INFO "HiSax: release hfcpci at %p\n",
 		cs->hw.hfcpci.pci_io);
-	save_flags(flags);
-	cli();
 	cs->hw.hfcpci.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
-	restore_flags(flags);
 	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);	/* Reset On */
-	sti();
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
 	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
-	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0);	/* disable memory mapped ports + busmaster */
+	pci_disable_device(cs->hw.hfcpci.pdev);
 	del_timer(&cs->hw.hfcpci.timer);
 	iounmap(cs->hw.hfcpci.pci_io);
 	pci_free_consistent(cs->hw.hfcpci.pdev, 32768, cs->hw.hfcpci.fifos, cs->hw.hfcpci.fifos_dma);
@@ -100,18 +94,13 @@
 static void
 reset_hfcpci(struct IsdnCardState *cs)
 {
-	long flags;
-
-	save_flags(flags);
-	cli();
-	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
+	pci_disable_device(cs->hw.hfcpci.pdev);
 	cs->hw.hfcpci.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
 
 	printk(KERN_INFO "HFC_PCI: resetting card\n");
-	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER);	/* enable memory ports + busmaster */
+	pci_set_master(cs->hw.hfcpci.pdev);
 	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);	/* Reset On */
-	sti();
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
 	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
@@ -170,7 +159,6 @@
 	cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
 	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
 	if (Read_hfc(cs, HFCPCI_INT_S2));
-	restore_flags(flags);
 }
 
 /***************************************************/
@@ -186,27 +174,6 @@
  */
 }
 
-
-/*********************************/
-/* schedule a new D-channel task */
-/*********************************/
-static void
-sched_event_D_pci(struct IsdnCardState *cs, int event)
-{
-	test_and_set_bit(event, &cs->event);
-	schedule_work(&cs->work);
-}
-
-/*********************************/
-/* schedule a new b_channel task */
-/*********************************/
-static void
-hfcpci_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
 /************************************************/
 /* select a b-channel entry matching and active */
 /************************************************/
@@ -285,12 +252,9 @@
 	u_char *ptr, *ptr1, new_f2;
 	struct sk_buff *skb;
 	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
 	int total, maxlen, new_z2;
 	z_type *zp;
 
-	save_flags(flags);
-	sti();
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfcpci_empty_fifo");
 	zp = &bz->za[bz->f2];	/* point to Z-Regs */
@@ -333,7 +297,6 @@
 		bz->f2 = new_f2;	/* next buffer */
 
 	}
-	restore_flags(flags);
 	return (skb);
 }
 
@@ -353,10 +316,6 @@
 	z_type *zp;
 
 	df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx;
-	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		debugl1(cs, "rec_dmsg blocked");
-		return (1);
-	}
 	while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
 		zp = &df->za[df->f2 & D_FREG_MASK];
 		rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2);
@@ -399,11 +358,10 @@
 			df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((le16_to_cpu(zp->z2) + total) & (D_FIFO_SIZE - 1));
 
 			skb_queue_tail(&cs->rq, skb);
-			sched_event_D_pci(cs, D_RCVBUFREADY);
+			sched_d_event(cs, D_RCVBUFREADY);
 		} else
 			printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
 	}
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	return (1);
 }
 
@@ -451,10 +409,8 @@
 			ptr1 = bdata;	/* start of buffer */
 			memcpy(ptr, ptr1, fcnt);	/* rest */
 		}
-		cli();
 		skb_queue_tail(&bcs->rqueue, skb);
-		sti();
-		hfcpci_sched_event(bcs, B_RCVBUFREADY);
+		sched_b_event(bcs, B_RCVBUFREADY);
 	}
 
 	*z2r = cpu_to_le16(new_z2);		/* new position */
@@ -467,7 +423,6 @@
 void
 main_rec_hfcpci(struct BCState *bcs)
 {
-	long flags;
 	struct IsdnCardState *cs = bcs->cs;
 	int rcnt, real_fifo;
 	int receive, count = 5;
@@ -476,8 +431,6 @@
 	u_char *bdata;
 	z_type *zp;
 
-
-	save_flags(flags);
 	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
 		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
 		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
@@ -489,13 +442,6 @@
 	}
       Begin:
 	count--;
-	cli();
-	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		debugl1(cs, "rec_data %d blocked", bcs->channel);
-		restore_flags(flags);
-		return;
-	}
-	sti();
 	if (bz->f1 != bz->f2) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)",
@@ -510,10 +456,8 @@
 			debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)",
 				bcs->channel, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt);
 		if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) {
-			cli();
 			skb_queue_tail(&bcs->rqueue, skb);
-			sti();
-			hfcpci_sched_event(bcs, B_RCVBUFREADY);
+			sched_b_event(bcs, B_RCVBUFREADY);
 		}
 		rcnt = bz->f1 - bz->f2;
 		if (rcnt < 0)
@@ -531,10 +475,9 @@
 		receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
 	else
 		receive = 0;
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+
 	if (count && receive)
 		goto Begin;
-	restore_flags(flags);
 	return;
 }
 
@@ -544,7 +487,6 @@
 static void
 hfcpci_fill_dfifo(struct IsdnCardState *cs)
 {
-	long flags;
 	int fcnt;
 	int count, new_z1, maxlen;
 	dfifo_type *df;
@@ -601,12 +543,9 @@
 		src += maxlen;	/* new position */
 		memcpy(dst, src, count);
 	}
-	save_flags(flags);
-	cli();
 	df->za[new_f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1);	/* for next buffer */
 	df->za[df->f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1);	/* new pos actual buffer */
 	df->f1 = new_f1;	/* next frame */
-	restore_flags(flags);
 
 	dev_kfree_skb_any(cs->tx_skb);
 	cs->tx_skb = NULL;
@@ -620,7 +559,6 @@
 hfcpci_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
 	int maxlen, fcnt;
 	int count, new_z1;
 	bzfifo_type *bz;
@@ -633,9 +571,6 @@
 	if (bcs->tx_skb->len <= 0)
 		return;
 
-	save_flags(flags);
-	sti();
-
 	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
 		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
 		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b2;
@@ -684,12 +619,9 @@
 					bcs->channel, bcs->tx_skb->len);
 
 			dev_kfree_skb_any(bcs->tx_skb);
-			cli();
 			bcs->tx_skb = skb_dequeue(&bcs->squeue);	/* fetch next data */
-			sti();
 		}
 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		restore_flags(flags);
 		return;
 	}
 	if (cs->debug & L1_DEB_HSCX)
@@ -703,7 +635,6 @@
 	if (fcnt > (MAX_B_FRAMES - 1)) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfcpci_fill_Bfifo more as 14 frames");
-		restore_flags(flags);
 		return;
 	}
 	/* now determine free bytes in FIFO buffer */
@@ -719,7 +650,6 @@
 	if (count < bcs->tx_skb->len) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfcpci_fill_fifo no fifo mem");
-		restore_flags(flags);
 		return;
 	}
 	count = bcs->tx_skb->len;	/* get frame len */
@@ -742,17 +672,11 @@
 		memcpy(dst, src, count);
 	}
 	bcs->tx_cnt -= bcs->tx_skb->len;
-	if (bcs->st->lli.l1writewakeup &&
-	    (PACKET_NOACK != bcs->tx_skb->pkt_type))
-		bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+	xmit_complete_b(bcs);
 
-	cli();
 	bz->za[new_f1].z1 = cpu_to_le16(new_z1);	/* for next buffer */
 	bz->f1 = new_f1;	/* next frame */
-	restore_flags(flags);
 
-	dev_kfree_skb_any(bcs->tx_skb);
-	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	return;
 }
@@ -798,13 +722,10 @@
 static int
 hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
 {
-	unsigned long flags;
 	int i = *(unsigned int *) ic->parm.num;
 
 	if ((ic->arg == 98) &&
 	    (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) {
-		save_flags(flags);
-		cli();
 		Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */
 		Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0);	/* HFC ST G0 */
 		udelay(10);
@@ -818,7 +739,6 @@
 		cs->hw.hfcpci.nt_mode = 1;
 		cs->hw.hfcpci.nt_timer = 0;
 		cs->stlist->l1.l2l1 = dch_nt_l2l1;
-		restore_flags(flags);
 		debugl1(cs, "NT mode activated");
 		return (0);
 	}
@@ -826,8 +746,6 @@
 	    (cs->hw.hfcpci.nt_mode) || (ic->arg != 12))
 		return (-EINVAL);
 
-	save_flags(flags);
-	cli();
 	if (i) {
 		cs->logecho = 1;
 		cs->hw.hfcpci.trm |= 0x20;	/* enable echo chan */
@@ -850,7 +768,6 @@
 	Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
 	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-	restore_flags(flags);
 	return (0);
 }				/* hfcpci_auxcmd */
 
@@ -860,7 +777,6 @@
 static void
 receive_emsg(struct IsdnCardState *cs)
 {
-	long flags;
 	int rcnt;
 	int receive, count = 5;
 	bzfifo_type *bz;
@@ -870,18 +786,10 @@
 	int total, maxlen, new_z2;
 	u_char e_buffer[256];
 
-	save_flags(flags);
 	bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
 	bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
       Begin:
 	count--;
-	cli();
-	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		debugl1(cs, "echo_rec_data blocked");
-		restore_flags(flags);
-		return;
-	}
-	sti();
 	if (bz->f1 != bz->f2) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)",
@@ -953,10 +861,8 @@
 			receive = 0;
 	} else
 		receive = 0;
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;
-	restore_flags(flags);
 	return;
 }				/* receive_emsg */
 
@@ -970,7 +876,6 @@
 	u_char exval;
 	struct BCState *bcs;
 	int count = 15;
-	long flags;
 	u_char val, stat;
 
 	if (!cs) {
@@ -988,9 +893,7 @@
 		return;
 
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFC-PCI irq %x %s", val,
-			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
-			"locked" : "unlocked");
+		debugl1(cs, "HFC-PCI irq %x", val);
 	val &= cs->hw.hfcpci.int_m1;
 	if (val & 0x40) {	/* state machine irq */
 		exval = Read_hfc(cs, HFCPCI_STATES) & 0xf;
@@ -998,25 +901,18 @@
 			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state,
 				exval);
 		cs->dc.hfcpci.ph_state = exval;
-		sched_event_D_pci(cs, D_L1STATECHANGE);
+		sched_d_event(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
 	if (val & 0x80) {	/* timer irq */
 		if (cs->hw.hfcpci.nt_mode) {
 			if ((--cs->hw.hfcpci.nt_timer) < 0)
-				sched_event_D_pci(cs, D_L1STATECHANGE);
+				sched_d_event(cs, D_L1STATECHANGE);
 		}
 		val &= ~0x80;
 		Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
 	}
 	while (val) {
-		save_flags(flags);
-		cli();
-		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-			cs->hw.hfcpci.int_s1 |= val;
-			restore_flags(flags);
-			return;
-		}
 		if (cs->hw.hfcpci.int_s1 & 0x18) {
 			exval = val;
 			val = cs->hw.hfcpci.int_s1;
@@ -1043,23 +939,7 @@
 				if (cs->debug)
 					debugl1(cs, "hfcpci spurious 0x01 IRQ");
 			} else {
-				if (bcs->tx_skb) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfcpci_fill_fifo(bcs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else
-						debugl1(cs, "fill_data %d blocked", bcs->channel);
-				} else {
-					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-							hfcpci_fill_fifo(bcs);
-							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else
-							debugl1(cs, "fill_data %d blocked", bcs->channel);
-					} else {
-						hfcpci_sched_event(bcs, B_XMTBUFREADY);
-					}
-				}
+				xmit_xpr_b(bcs);
 			}
 		}
 		if (val & 0x02) {
@@ -1067,60 +947,15 @@
 				if (cs->debug)
 					debugl1(cs, "hfcpci spurious 0x02 IRQ");
 			} else {
-				if (bcs->tx_skb) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfcpci_fill_fifo(bcs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else
-						debugl1(cs, "fill_data %d blocked", bcs->channel);
-				} else {
-					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-							hfcpci_fill_fifo(bcs);
-							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else
-							debugl1(cs, "fill_data %d blocked", bcs->channel);
-					} else {
-						hfcpci_sched_event(bcs, B_XMTBUFREADY);
-					}
-				}
+				xmit_xpr_b(bcs);
 			}
 		}
 		if (val & 0x20) {	/* receive dframe */
 			receive_dmsg(cs);
 		}
 		if (val & 0x04) {	/* dframe transmitted */
-			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-				del_timer(&cs->dbusytimer);
-			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				sched_event_D_pci(cs, D_CLEARBUSY);
-			if (cs->tx_skb) {
-				if (cs->tx_skb->len) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfcpci_fill_dfifo(cs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else {
-						debugl1(cs, "hfcpci_fill_dfifo irq blocked");
-					}
-					goto afterXPR;
-				} else {
-					dev_kfree_skb_irq(cs->tx_skb);
-					cs->tx_cnt = 0;
-					cs->tx_skb = NULL;
-				}
-			}
-			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
-				cs->tx_cnt = 0;
-				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-					hfcpci_fill_dfifo(cs);
-					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-				} else {
-					debugl1(cs, "hfcpci_fill_dfifo irq blocked");
-				}
-			} else
-				sched_event_D_pci(cs, D_XMTBUFREADY);
+			xmit_xpr_d(cs);
 		}
-	      afterXPR:
 		if (cs->hw.hfcpci.int_s1 && count--) {
 			val = cs->hw.hfcpci.int_s1;
 			cs->hw.hfcpci.int_s1 = 0;
@@ -1128,7 +963,6 @@
 				debugl1(cs, "HFC-PCI irq %x loop %d", val, 15 - count);
 		} else
 			val = 0;
-		restore_flags(flags);
 	}
 }
 
@@ -1148,68 +982,16 @@
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
-	unsigned long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-					hfcpci_fill_dfifo(cs);
-					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-				} else
-					debugl1(cs, "hfcpci_fill_dfifo blocked");
-
-			}
+			xmit_data_req_d(cs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-				hfcpci_fill_dfifo(cs);
-				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-			} else
-				debugl1(cs, "hfcpci_fill_dfifo blocked");
+			xmit_pull_ind_d(cs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_d(st);
 			break;
 		case (HW_RESET | REQUEST):
 			Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3);	/* HFC ST 3 */
@@ -1236,21 +1018,15 @@
 				case (1):
 					Write_hfc(cs, HFCPCI_B1_SSL, 0x80);	/* tx slot */
 					Write_hfc(cs, HFCPCI_B1_RSL, 0x80);	/* rx slot */
-					save_flags(flags);
-					cli();
 					cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~7) | 1;
 					Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
-					restore_flags(flags);
 					break;
 
 				case (2):
 					Write_hfc(cs, HFCPCI_B2_SSL, 0x81);	/* tx slot */
 					Write_hfc(cs, HFCPCI_B2_RSL, 0x81);	/* rx slot */
-					save_flags(flags);
-					cli();
 					cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~0x38) | 0x08;
 					Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
-					restore_flags(flags);
 					break;
 
 				default:
@@ -1258,11 +1034,8 @@
 						debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg);
 					return;
 			}
-			save_flags(flags);
-			cli();
 			cs->hw.hfcpci.trm |= 0x80;	/* enable IOM-loop */
 			Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
-			restore_flags(flags);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -1280,21 +1053,6 @@
 	st->l1.l1hw = HFCPCI_l1hw;
 }
 
-/**************************************/
-/* send B-channel data if not blocked */
-/**************************************/
-static void
-hfcpci_send_data(struct BCState *bcs)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		hfcpci_fill_fifo(bcs);
-		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	} else
-		debugl1(cs, "send_data %d blocked", bcs->channel);
-}
-
 /***************************************************************/
 /* activate/deactivate hardware for selected channels and mode */
 /***************************************************************/
@@ -1302,7 +1060,6 @@
 mode_hfcpci(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
 	int fifo2;
 
 	if (cs->debug & L1_DEB_HSCX)
@@ -1311,8 +1068,6 @@
 	bcs->mode = mode;
 	bcs->channel = bc;
 	fifo2 = bc;
-	save_flags(flags);
-	cli();
 	if (cs->chanlimit > 1) {
 		cs->hw.hfcpci.bswapped = 0;	/* B1 and B2 normal mode */
 		cs->hw.hfcpci.sctrl_e &= ~0x80;
@@ -1417,7 +1172,6 @@
 	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
 	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
 	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
-	restore_flags(flags);
 }
 
 /******************************/
@@ -1427,40 +1181,16 @@
 hfcpci_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			save_flags(flags);
-			cli();
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				restore_flags(flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-/*                              test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
- */ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-				restore_flags(flags);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
-				break;
-			}
-			save_flags(flags);
-			cli();
-/*                      test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
- */ st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			restore_flags(flags);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
@@ -1538,7 +1268,6 @@
 hfcpci_bh(void *data)
 {
 	struct IsdnCardState *cs = data;
-	unsigned long flags;
 /*      struct PStack *stptr;
  */
 	if (!cs)
@@ -1566,8 +1295,6 @@
 		} else {
 			switch (cs->dc.hfcpci.ph_state) {
 				case (2):
-					save_flags(flags);
-					cli();
 					if (cs->hw.hfcpci.nt_timer < 0) {
 						cs->hw.hfcpci.nt_timer = 0;
 						cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
@@ -1589,17 +1316,13 @@
 						cs->hw.hfcpci.nt_timer = NT_T1_COUNT;
 						Write_hfc(cs, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3);	/* allow G2 -> G3 transition */
 					}
-					restore_flags(flags);
 					break;
 				case (1):
 				case (3):
 				case (4):
-					save_flags(flags);
-					cli();
 					cs->hw.hfcpci.nt_timer = 0;
 					cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
 					Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-					restore_flags(flags);
 					break;
 				default:
 					break;
@@ -1624,7 +1347,8 @@
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
 	INIT_WORK(&cs->work, hfcpci_bh, cs);
-	cs->BC_Send_Data = &hfcpci_send_data;
+	cs->BC_Send_Data = hfcpci_fill_fifo;
+	cs->DC_Send_Data = hfcpci_fill_dfifo;
 	cs->bcs[0].BC_SetStack = setstack_2b;
 	cs->bcs[1].BC_SetStack = setstack_2b;
 	cs->bcs[0].BC_Close = close_hfcpci;
@@ -1641,8 +1365,6 @@
 static int
 hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	long flags;
-
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "HFCPCI: card_msg %x", mt);
 	switch (mt) {
@@ -1654,8 +1376,6 @@
 			return (0);
 		case CARD_INIT:
 			inithfcpci(cs);
-			save_flags(flags);
-			sti();
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
 			/* now switch timer interrupt off */
@@ -1663,7 +1383,6 @@
 			Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
 			/* reinit mode reg */
 			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
-			restore_flags(flags);
 			return (0);
 		case CARD_TEST:
 			return (0);
@@ -1712,8 +1431,6 @@
 		if (tmp_hfcpci) {
 			i--;
 			dev_hfcpci = tmp_hfcpci;	/* old device */
-			cs->hw.hfcpci.pci_bus = dev_hfcpci->bus->number;
-			cs->hw.hfcpci.pci_device_fn = dev_hfcpci->devfn;
 			cs->irq = dev_hfcpci->irq;
 			cs->hw.hfcpci.pdev = tmp_hfcpci;
 			if (!cs->irq) {
@@ -1731,16 +1448,13 @@
 			return (0);
 		}
 		/* Allocate memory for FIFOS */
-		/* Because the HFC-PCI needs a 32K physical alignment, we */
-		/* need to allocate the double mem and align the address */
 		cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma);
 		if (!cs->hw.hfcpci.fifos) {
 			printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
 			return 0;
 		}
-		pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
-					cs->hw.hfcpci.pci_device_fn, 0x80,
-					(u_int)cs->hw.hfcpci.fifos_dma);
+		pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80,
+				       (u_int)cs->hw.hfcpci.fifos_dma);
 		cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
 		printk(KERN_INFO
 		       "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
@@ -1749,7 +1463,6 @@
 		       (u_int) cs->hw.hfcpci.fifos_dma,
 		       cs->irq, HZ);
 		printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID));
-		pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
 		cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
 		cs->hw.hfcpci.int_m1 = 0;
 		Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
--- a/drivers/isdn/hisax/hfc_sx.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/hfc_sx.c	Wed Nov 27 14:36:27 2002
@@ -61,25 +61,19 @@
 /******************************/
 static inline void
 Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val)
-{       unsigned long flags;
+{
 
-        save_flags(flags);
-	cli();
         byteout(cs->hw.hfcsx.base+1, regnum);
 	byteout(cs->hw.hfcsx.base, val);
-	restore_flags(flags);
 } 
 
 static inline u_char
 Read_hfc(struct IsdnCardState *cs, u_char regnum)
-{       unsigned long flags;
+{
         u_char ret; 
 
-        save_flags(flags);
-	cli();
         byteout(cs->hw.hfcsx.base+1, regnum);
 	ret = bytein(cs->hw.hfcsx.base);
-	restore_flags(flags);
 	return(ret);
 } 
 
@@ -89,20 +83,16 @@
 /**************************************************/
 static void
 fifo_select(struct IsdnCardState *cs, u_char fifo)
-{       unsigned long flags;
-
+{
         if (fifo == cs->hw.hfcsx.last_fifo) 
 	  return; /* still valid */
 
-	save_flags(flags);
-	cli();
         byteout(cs->hw.hfcsx.base+1, HFCSX_FIF_SEL);
 	byteout(cs->hw.hfcsx.base, fifo);
 	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
 	udelay(4);
 	byteout(cs->hw.hfcsx.base, fifo);
 	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
-	restore_flags(flags);
 }
 
 /******************************************/
@@ -111,16 +101,12 @@
 /******************************************/
 static void
 reset_fifo(struct IsdnCardState *cs, u_char fifo)
-{       unsigned long flags;
-
-        save_flags(flags); 
-	cli();
+{
 	fifo_select(cs, fifo); /* first select the fifo */
 	byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM);
 	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.cirm | 0x80); /* reset cmd */
 	udelay(1);
 	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
-	restore_flags(flags);
 } 
 
 
@@ -325,15 +311,9 @@
 void
 release_io_hfcsx(struct IsdnCardState *cs)
 {
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
 	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
-	restore_flags(flags);
 	Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET);	/* Reset On */
-	sti();
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
 	Write_hfc(cs, HFCSX_CIRM, 0);	/* Reset Off */
@@ -370,17 +350,12 @@
 static void
 reset_hfcsx(struct IsdnCardState *cs)
 {
-	long flags;
-
-	save_flags(flags);
-	cli();
 	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
 
 	printk(KERN_INFO "HFC_SX: resetting card\n");
 	while (1) {
 	  Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */
-	  sti();
 	  set_current_state(TASK_UNINTERRUPTIBLE);
 	  schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
 	  Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */
@@ -440,7 +415,6 @@
 	cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE;
 	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
 	if (Read_hfc(cs, HFCSX_INT_S2));
-	restore_flags(flags);
 }
 
 /***************************************************/
@@ -457,26 +431,6 @@
 }
 
 
-/*********************************/
-/* schedule a new D-channel task */
-/*********************************/
-static void
-sched_event_D_sx(struct IsdnCardState *cs, int event)
-{
-	test_and_set_bit(event, &cs->event);
-	schedule_work(&cs->work);
-}
-
-/*********************************/
-/* schedule a new b_channel task */
-/*********************************/
-static void
-hfcsx_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
 /************************************************/
 /* select a b-channel entry matching and active */
 /************************************************/
@@ -495,27 +449,20 @@
 /*******************************/
 /* D-channel receive procedure */
 /*******************************/
-static
-int
+static int
 receive_dmsg(struct IsdnCardState *cs)
 {
 	struct sk_buff *skb;
 	int count = 5;
 
-	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		debugl1(cs, "rec_dmsg blocked");
-		return (1);
-	}
-
 	do {
 	  skb = read_fifo(cs, HFCSX_SEL_D_RX, 0);
 	  if (skb) {
 	    skb_queue_tail(&cs->rq, skb);
-	    sched_event_D_sx(cs, D_RCVBUFREADY);
+	    sched_d_event(cs, D_RCVBUFREADY);
 	  }
 	} while (--count && skb);
 
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	return (1);
 }
 
@@ -525,38 +472,24 @@
 void
 main_rec_hfcsx(struct BCState *bcs)
 {
-	long flags;
 	struct IsdnCardState *cs = bcs->cs;
 	int count = 5;
 	struct sk_buff *skb;
 
-	save_flags(flags);
-	  
       Begin:
 	count--;
-	cli();
-	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		debugl1(cs, "rec_data %d blocked", bcs->channel);
-		restore_flags(flags);
-		return;
-	}
-	sti();
 	skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? 
 			HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX,
 			(bcs->mode == L1_MODE_TRANS) ? 
 			HFCSX_BTRANS_THRESHOLD : 0);
 
 	if (skb) {
-	  cli();
 	  skb_queue_tail(&bcs->rqueue, skb);
-	  sti();
-	  hfcsx_sched_event(bcs, B_RCVBUFREADY);
+	  sched_b_event(bcs, B_RCVBUFREADY);
 	}
 
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && skb)
 		goto Begin;
-	restore_flags(flags);
 	return;
 }
 
@@ -575,7 +508,6 @@
 	  dev_kfree_skb_any(cs->tx_skb);
 	  cs->tx_skb = NULL;
 	}
-	return;
 }
 
 /**************************/
@@ -585,34 +517,22 @@
 hfcsx_fill_fifo(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
 
 	if (!bcs->tx_skb)
 		return;
 	if (bcs->tx_skb->len <= 0)
 		return;
 
-	save_flags(flags);
-	sti();
-
 	if (write_fifo(cs, bcs->tx_skb, 
 		       ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? 
 		       HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX,
 		       (bcs->mode == L1_MODE_TRANS) ? 
 		       HFCSX_BTRANS_THRESHOLD : 0)) {
 
-	  bcs->tx_cnt -= bcs->tx_skb->len;
-	  if (bcs->st->lli.l1writewakeup &&
-	      (PACKET_NOACK != bcs->tx_skb->pkt_type))
-	    bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
-	  dev_kfree_skb_any(bcs->tx_skb);
-	  bcs->tx_skb = NULL;
-	  test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		bcs->tx_cnt -= bcs->tx_skb->len;
+		xmit_complete_b(bcs);
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	}
-
-	cli();
-	restore_flags(flags);
-	return;
 }
 
 /**********************************************/
@@ -656,13 +576,10 @@
 static int
 hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
 {
-	unsigned long flags;
 	int i = *(unsigned int *) ic->parm.num;
 
 	if ((ic->arg == 98) &&
 	    (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) {
-		save_flags(flags);
-		cli();
 		Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0);	/* HFC ST G0 */
 		udelay(10);
 		cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT;
@@ -675,7 +592,6 @@
 		cs->hw.hfcsx.nt_mode = 1;
 		cs->hw.hfcsx.nt_timer = 0;
 		cs->stlist->l1.l2l1 = dch_nt_l2l1;
-		restore_flags(flags);
 		debugl1(cs, "NT mode activated");
 		return (0);
 	}
@@ -683,8 +599,6 @@
 	    (cs->hw.hfcsx.nt_mode) || (ic->arg != 12))
 		return (-EINVAL);
 
-	save_flags(flags);
-	cli();
 	if (i) {
 		cs->logecho = 1;
 		cs->hw.hfcsx.trm |= 0x20;	/* enable echo chan */
@@ -705,7 +619,6 @@
 	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
 	Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
 	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-	restore_flags(flags);
 	return (0);
 }				/* hfcsx_auxcmd */
 
@@ -715,21 +628,10 @@
 static void
 receive_emsg(struct IsdnCardState *cs)
 {
-	unsigned long flags;
 	int count = 5;
 	u_char *ptr;
 	struct sk_buff *skb;
 
-
-	save_flags(flags);
-	cli();
-	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		debugl1(cs, "echo_rec_data blocked");
-		restore_flags(flags);
-		return;
-	}
-	sti();
-
 	do {
 	  skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0);
 	  if (skb) {
@@ -752,10 +654,6 @@
 	    dev_kfree_skb_any(skb);
 	  }
 	} while (--count && skb);
-
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	restore_flags(flags);
-	return;
 }				/* receive_emsg */
 
 
@@ -769,7 +667,6 @@
 	u_char exval;
 	struct BCState *bcs;
 	int count = 15;
-	long flags;
 	u_char val, stat;
 
 	if (!cs) {
@@ -787,9 +684,7 @@
 		return;
 
 	if (cs->debug & L1_DEB_ISAC)
-		debugl1(cs, "HFC-SX irq %x %s", val,
-			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
-			"locked" : "unlocked");
+		debugl1(cs, "HFC-SX irq %x", val);
 	val &= cs->hw.hfcsx.int_m1;
 	if (val & 0x40) {	/* state machine irq */
 		exval = Read_hfc(cs, HFCSX_STATES) & 0xf;
@@ -797,25 +692,18 @@
 			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state,
 				exval);
 		cs->dc.hfcsx.ph_state = exval;
-		sched_event_D_sx(cs, D_L1STATECHANGE);
+		sched_d_event(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
 	if (val & 0x80) {	/* timer irq */
 		if (cs->hw.hfcsx.nt_mode) {
 			if ((--cs->hw.hfcsx.nt_timer) < 0)
-				sched_event_D_sx(cs, D_L1STATECHANGE);
+				sched_d_event(cs, D_L1STATECHANGE);
 		}
 		val &= ~0x80;
 		Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
 	}
 	while (val) {
-		save_flags(flags);
-		cli();
-		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-			cs->hw.hfcsx.int_s1 |= val;
-			restore_flags(flags);
-			return;
-		}
 		if (cs->hw.hfcsx.int_s1 & 0x18) {
 			exval = val;
 			val = cs->hw.hfcsx.int_s1;
@@ -842,23 +730,7 @@
 				if (cs->debug)
 					debugl1(cs, "hfcsx spurious 0x01 IRQ");
 			} else {
-				if (bcs->tx_skb) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfcsx_fill_fifo(bcs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else
-						debugl1(cs, "fill_data %d blocked", bcs->channel);
-				} else {
-					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-							hfcsx_fill_fifo(bcs);
-							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else
-							debugl1(cs, "fill_data %d blocked", bcs->channel);
-					} else {
-						hfcsx_sched_event(bcs, B_XMTBUFREADY);
-					}
-				}
+				xmit_xpr_b(bcs);
 			}
 		}
 		if (val & 0x02) {
@@ -866,60 +738,15 @@
 				if (cs->debug)
 					debugl1(cs, "hfcsx spurious 0x02 IRQ");
 			} else {
-				if (bcs->tx_skb) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfcsx_fill_fifo(bcs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else
-						debugl1(cs, "fill_data %d blocked", bcs->channel);
-				} else {
-					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-							hfcsx_fill_fifo(bcs);
-							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else
-							debugl1(cs, "fill_data %d blocked", bcs->channel);
-					} else {
-						hfcsx_sched_event(bcs, B_XMTBUFREADY);
-					}
-				}
+				xmit_xpr_b(bcs);
 			}
 		}
 		if (val & 0x20) {	/* receive dframe */
 			receive_dmsg(cs);
 		}
 		if (val & 0x04) {	/* dframe transmitted */
-			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-				del_timer(&cs->dbusytimer);
-			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				sched_event_D_sx(cs, D_CLEARBUSY);
-			if (cs->tx_skb) {
-				if (cs->tx_skb->len) {
-					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-						hfcsx_fill_dfifo(cs);
-						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else {
-						debugl1(cs, "hfcsx_fill_dfifo irq blocked");
-					}
-					goto afterXPR;
-				} else {
-					dev_kfree_skb_irq(cs->tx_skb);
-					cs->tx_cnt = 0;
-					cs->tx_skb = NULL;
-				}
-			}
-			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
-				cs->tx_cnt = 0;
-				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-					hfcsx_fill_dfifo(cs);
-					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-				} else {
-					debugl1(cs, "hfcsx_fill_dfifo irq blocked");
-				}
-			} else
-				sched_event_D_sx(cs, D_XMTBUFREADY);
+			xmit_xpr_d(cs);
 		}
-	      afterXPR:
 		if (cs->hw.hfcsx.int_s1 && count--) {
 			val = cs->hw.hfcsx.int_s1;
 			cs->hw.hfcsx.int_s1 = 0;
@@ -927,7 +754,6 @@
 				debugl1(cs, "HFC-SX irq %x loop %d", val, 15 - count);
 		} else
 			val = 0;
-		restore_flags(flags);
 	}
 }
 
@@ -947,68 +773,16 @@
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
-	unsigned long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-				        hfcsx_fill_dfifo(cs); 
-					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-				} else
-					debugl1(cs, "hfcsx_fill_dfifo blocked");
-
-			}
+			xmit_data_req_d(cs, skb);
 			break;
-		case (PH_PULL | INDICATION):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-				hfcsx_fill_dfifo(cs); 
-				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-			} else
-				debugl1(cs, "hfcsx_fill_dfifo blocked");
+		case (PH_PULL |INDICATION):
+			xmit_pull_ind_d(cs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_d(st);
 			break;
 		case (HW_RESET | REQUEST):
 			Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3);	/* HFC ST 3 */
@@ -1035,21 +809,15 @@
 				case (1):
 					Write_hfc(cs, HFCSX_B1_SSL, 0x80);	/* tx slot */
 					Write_hfc(cs, HFCSX_B1_RSL, 0x80);	/* rx slot */
-					save_flags(flags);
-					cli();
 					cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1;
 					Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
-					restore_flags(flags);
 					break;
 
 				case (2):
 					Write_hfc(cs, HFCSX_B2_SSL, 0x81);	/* tx slot */
 					Write_hfc(cs, HFCSX_B2_RSL, 0x81);	/* rx slot */
-					save_flags(flags);
-					cli();
 					cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08;
 					Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
-					restore_flags(flags);
 					break;
 
 				default:
@@ -1057,11 +825,8 @@
 						debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg);
 					return;
 			}
-			save_flags(flags);
-			cli();
 			cs->hw.hfcsx.trm |= 0x80;	/* enable IOM-loop */
 			Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
-			restore_flags(flags);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -1079,21 +844,6 @@
 	st->l1.l1hw = HFCSX_l1hw;
 }
 
-/**************************************/
-/* send B-channel data if not blocked */
-/**************************************/
-static void
-hfcsx_send_data(struct BCState *bcs)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-	  hfcsx_fill_fifo(bcs);
-		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	} else
-		debugl1(cs, "send_data %d blocked", bcs->channel);
-}
-
 /***************************************************************/
 /* activate/deactivate hardware for selected channels and mode */
 /***************************************************************/
@@ -1101,7 +851,6 @@
 mode_hfcsx(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
 	int fifo2;
 
 	if (cs->debug & L1_DEB_HSCX)
@@ -1110,8 +859,6 @@
 	bcs->mode = mode;
 	bcs->channel = bc;
 	fifo2 = bc;
-	save_flags(flags);
-	cli();
 	if (cs->chanlimit > 1) {
 		cs->hw.hfcsx.bswapped = 0;	/* B1 and B2 normal mode */
 		cs->hw.hfcsx.sctrl_e &= ~0x80;
@@ -1205,7 +952,6 @@
 	  reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX);
 	  reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX);
 	}
-	restore_flags(flags);
 }
 
 /******************************/
@@ -1215,40 +961,16 @@
 hfcsx_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			save_flags(flags);
-			cli();
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				restore_flags(flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-/*                              test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
- */ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-				restore_flags(flags);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
-				break;
-			}
-			save_flags(flags);
-			cli();
-/*                      test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
- */ st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			restore_flags(flags);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
@@ -1326,11 +1048,7 @@
 hfcsx_bh(void *data)
 {
 	struct IsdnCardState *cs = data;
-	unsigned long flags;
-/*      struct PStack *stptr;
- */
-	if (!cs)
-		return;
+
 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
 		if (!cs->hw.hfcsx.nt_mode)
 			switch (cs->dc.hfcsx.ph_state) {
@@ -1354,8 +1072,6 @@
 		} else {
 			switch (cs->dc.hfcsx.ph_state) {
 				case (2):
-					save_flags(flags);
-					cli();
 					if (cs->hw.hfcsx.nt_timer < 0) {
 						cs->hw.hfcsx.nt_timer = 0;
 						cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
@@ -1377,17 +1093,13 @@
 						cs->hw.hfcsx.nt_timer = NT_T1_COUNT;
 						Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3);	/* allow G2 -> G3 transition */
 					}
-					restore_flags(flags);
 					break;
 				case (1):
 				case (3):
 				case (4):
-					save_flags(flags);
-					cli();
 					cs->hw.hfcsx.nt_timer = 0;
 					cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
 					Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-					restore_flags(flags);
 					break;
 				default:
 					break;
@@ -1412,7 +1124,8 @@
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
 	INIT_WORK(&cs->work, hfcsx_bh, cs);
-	cs->BC_Send_Data = &hfcsx_send_data;
+	cs->BC_Send_Data = hfcsx_fill_fifo;
+	cs->DC_Send_Data = hfcsx_fill_dfifo;
 	cs->bcs[0].BC_SetStack = setstack_2b;
 	cs->bcs[1].BC_SetStack = setstack_2b;
 	cs->bcs[0].BC_Close = close_hfcsx;
@@ -1429,8 +1142,6 @@
 static int
 hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	long flags;
-
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "HFCSX: card_msg %x", mt);
 	switch (mt) {
@@ -1442,8 +1153,6 @@
 			return (0);
 		case CARD_INIT:
 			inithfcsx(cs);
-			save_flags(flags);
-			sti();
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
 			/* now switch timer interrupt off */
@@ -1451,7 +1160,6 @@
 			Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
 			/* reinit mode reg */
 			Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
-			restore_flags(flags);
 			return (0);
 		case CARD_TEST:
 			return (0);
@@ -1476,7 +1184,6 @@
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	unsigned long flags;
 
 	strcpy(tmp, hfcsx_revision);
 	printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
@@ -1560,16 +1267,12 @@
 		  release_region(cs->hw.hfcsx.base, 2);
 		  return(0);
 		}  
-		save_flags(flags);
-		cli();
 		if (!(cs->hw.hfcsx.extra = (void *)
 		      kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
-		  restore_flags(flags);
 		  release_region(cs->hw.hfcsx.base, 2);
 		  printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
 		  return(0);
 		}
-		restore_flags(flags);
 
 		printk(KERN_INFO
 		       "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
--- a/drivers/isdn/hisax/hisax.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/hisax.h	Wed Nov 27 14:36:31 2002
@@ -278,8 +278,6 @@
 struct LLInterface {
 	void (*l3l4) (struct PStack *, int, void *);
 	void *userdata;
-	void (*l1writewakeup) (struct PStack *, int);
-	void (*l2writewakeup) (struct PStack *, int);
 };
 
 
@@ -353,7 +351,6 @@
 struct hscx_hw {
 	int hscx;
 	int rcvidx;
-	int count;              /* Current skb sent count */
 	u_char *rcvbuf;         /* B-Channel receive Buffer */
 	u_char tsaxr0;
 	u_char tsaxr1;
@@ -362,7 +359,6 @@
 struct w6692B_hw {
 	int bchan;
 	int rcvidx;
-	int count;              /* Current skb sent count */
 	u_char *rcvbuf;         /* B-Channel receive Buffer */
 };
 
@@ -378,7 +374,6 @@
 struct isar_hw {
 	int dpath;
 	int rcvidx;
-	int txcnt;
 	int mml;
 	u_char state;
 	u_char cmd;
@@ -413,7 +408,6 @@
 	} ctrl;
 	u_int stat;
 	int rcvidx;
-	int count;              /* Current skb sent count */
 	u_char *rcvbuf;         /* B-Channel receive Buffer */
 };
 
@@ -489,8 +483,9 @@
 	struct IsdnCardState *cs;
 	int tx_cnt;		/* B-Channel transmit counter */
 	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
-	struct sk_buff_head rqueue;	/* B-Channel receive Queue */
-	struct sk_buff_head squeue;	/* B-Channel send Queue */
+	struct sk_buff_head rqueue;	/* B-Channel receive queue */
+	struct sk_buff_head squeue;	/* B-Channel send queue */
+	struct sk_buff_head cmpl_queue;	/* B-Channel send complete queue */
 	struct PStack *st;
 	u_char *blog;
 	u_char *conmsg;
@@ -505,6 +500,7 @@
 	int err_rdo;
 	int err_inv;
 #endif
+	int count;
 	union {
 		struct hscx_hw hscx;
 		struct hdlc_hw hdlc;
@@ -685,8 +681,6 @@
         unsigned char bswapped;
         unsigned char nt_mode;
         int nt_timer;
-	unsigned char pci_bus;
-        unsigned char pci_device_fn;
         unsigned char *pci_io; /* start of PCI IO memory */
         void *fifos; /* FIFO memory */ 
         dma_addr_t fifos_dma;
@@ -872,7 +866,6 @@
 #define FLG_TWO_DCHAN		4
 #define FLG_L1_DBUSY		5
 #define FLG_DBUSY_TIMER 	6
-#define FLG_LOCK_ATOMIC 	7
 #define FLG_ARCOFI_TIMER	8
 #define FLG_ARCOFI_ERROR	9
 #define FLG_HW_L1_UINT		10
@@ -881,6 +874,7 @@
 struct IsdnCardState {
 	unsigned char typ;
 	unsigned char subtyp;
+	spinlock_t lock;
 	int protocol;
 	unsigned int irq;
 	unsigned long irq_flags;
@@ -930,6 +924,7 @@
 	void   (*BC_Send_Data) (struct BCState *);
 	int    (*cardmsg) (struct IsdnCardState *, int, void *);
 	void   (*setstack_d) (struct PStack *, struct IsdnCardState *);
+	void   (*DC_Send_Data) (struct IsdnCardState *);
 	void   (*DC_Close) (struct IsdnCardState *);
 	void   (*irq_func) (int, void *, struct pt_regs *);
 	int    (*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
@@ -1408,4 +1403,3 @@
 {
 	st->l3.l4l3(st, pr, arg);
 }
-
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	Wed Nov 27 14:36:31 2002
@@ -528,8 +528,7 @@
 	}
 	bcs->tx_cnt = 0;
 	bcs->tx_skb = NULL;
-	B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
-	dev_kfree_skb_irq(skb);
+	B_L1L2(bcs, PH_DATA | CONFIRM, skb);
 }
 
 static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.c b/drivers/isdn/hisax/hisax_hfcpci.c
--- a/drivers/isdn/hisax/hisax_hfcpci.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/hisax_hfcpci.c	Wed Nov 27 14:36:28 2002
@@ -1294,8 +1294,7 @@
 	}
 
 	bcs->tx_skb = NULL;
-	B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
-	dev_kfree_skb_irq(skb);
+	B_L1L2(bcs, PH_DATA | CONFIRM, skb);
 }
 
 // ----------------------------------------------------------------------
diff -Nru a/drivers/isdn/hisax/hisax_hscx.c b/drivers/isdn/hisax/hisax_hscx.c
--- a/drivers/isdn/hisax/hisax_hscx.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/hisax_hscx.c	Wed Nov 27 14:36:28 2002
@@ -226,8 +226,7 @@
 	}
 	hscx->tx_cnt = 0;
 	hscx->tx_skb = NULL;
-	B_L1L2(hscx, PH_DATA | CONFIRM, (void *) skb->truesize);
-	dev_kfree_skb_irq(skb);
+	B_L1L2(hscx, PH_DATA | CONFIRM, skb);
 }
 
 static inline void hscx_exi_interrupt(struct hscx *hscx)
diff -Nru a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
--- a/drivers/isdn/hisax/hscx.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/hscx.c	Wed Nov 27 14:36:27 2002
@@ -92,49 +92,19 @@
 }
 
 void
-hscx_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
-void
 hscx_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			save_flags(flags);
-			cli();
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				restore_flags(flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				st->l1.bcs->hw.hscx.count = 0;
-				restore_flags(flags);
-				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
-				break;
-			}
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->hw.hscx.count = 0;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
@@ -168,6 +138,7 @@
 		}
 		skb_queue_purge(&bcs->rqueue);
 		skb_queue_purge(&bcs->squeue);
+		skb_queue_purge(&bcs->cmpl_queue);
 		if (bcs->tx_skb) {
 			dev_kfree_skb_any(bcs->tx_skb);
 			bcs->tx_skb = NULL;
@@ -196,6 +167,7 @@
 		}
 		skb_queue_head_init(&bcs->rqueue);
 		skb_queue_head_init(&bcs->squeue);
+		skb_queue_head_init(&bcs->cmpl_queue);
 	}
 	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
@@ -220,10 +192,21 @@
 }
 
 void __init
-clear_pending_hscx_ints(struct IsdnCardState *cs)
+inithscx(struct IsdnCardState *cs)
 {
 	int val, eval;
 
+	cs->bcs[0].BC_SetStack = setstack_hscx;
+	cs->bcs[1].BC_SetStack = setstack_hscx;
+	cs->bcs[0].BC_Close = close_hscxstate;
+	cs->bcs[1].BC_Close = close_hscxstate;
+	cs->bcs[0].hw.hscx.hscx = 0;
+	cs->bcs[1].hw.hscx.hscx = 1;
+	cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
+	cs->bcs[0].hw.hscx.tsaxr1 = 3;
+	cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
+	cs->bcs[1].hw.hscx.tsaxr1 = 3;
+
 	val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
 	debugl1(cs, "HSCX B ISTA %x", val);
 	if (val & 0x01) {
@@ -243,40 +226,18 @@
 	/* disable all IRQ */
 	cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
 	cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
-}
 
-void __init
-inithscx(struct IsdnCardState *cs)
-{
-	cs->bcs[0].BC_SetStack = setstack_hscx;
-	cs->bcs[1].BC_SetStack = setstack_hscx;
-	cs->bcs[0].BC_Close = close_hscxstate;
-	cs->bcs[1].BC_Close = close_hscxstate;
-	cs->bcs[0].hw.hscx.hscx = 0;
-	cs->bcs[1].hw.hscx.hscx = 1;
-	cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
-	cs->bcs[0].hw.hscx.tsaxr1 = 3;
-	cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
-	cs->bcs[1].hw.hscx.tsaxr1 = 3;
 	modehscx(cs->bcs, 0, 0);
 	modehscx(cs->bcs + 1, 0, 0);
+
+	/* Reenable all IRQ */
+	cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
+	cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
 }
 
 void __init
-inithscxisac(struct IsdnCardState *cs, int part)
+inithscxisac(struct IsdnCardState *cs)
 {
-	if (part & 1) {
-		clear_pending_isac_ints(cs);
-		clear_pending_hscx_ints(cs);
-		initisac(cs);
-		inithscx(cs);
-	}
-	if (part & 2) {
-		/* Reenable all IRQ */
-		cs->writeisac(cs, ISAC_MASK, 0);
-		cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
-		cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
-		/* RESET Receiver and Transmitter */
-		cs->writeisac(cs, ISAC_CMDR, 0x41);
-	}
+	initisac(cs);
+	inithscx(cs);
 }
diff -Nru a/drivers/isdn/hisax/hscx.h b/drivers/isdn/hisax/hscx.h
--- a/drivers/isdn/hisax/hscx.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/hscx.h	Wed Nov 27 14:36:31 2002
@@ -35,8 +35,5 @@
 #define HSCX_MASK 0x20
 
 extern int HscxVersion(struct IsdnCardState *cs, char *s);
-extern void hscx_sched_event(struct BCState *bcs, int event);
 extern void modehscx(struct BCState *bcs, int mode, int bc);
-extern void clear_pending_hscx_ints(struct IsdnCardState *cs);
-extern void inithscx(struct IsdnCardState *cs);
-extern void inithscxisac(struct IsdnCardState *cs, int part);
+extern void inithscxisac(struct IsdnCardState *cs);
diff -Nru a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
--- a/drivers/isdn/hisax/hscx_irq.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hisax/hscx_irq.c	Wed Nov 27 14:36:32 2002
@@ -43,23 +43,16 @@
 static inline void
 WriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
 {
-	long flags;
-
-	save_flags(flags);
-	cli();
 	waitforCEC(cs, hscx);
 	WRITEHSCX(cs, hscx, HSCX_CMDR, data);
-	restore_flags(flags);
 }
 
 
-
 static void
 hscx_empty_fifo(struct BCState *bcs, int count)
 {
 	u_char *ptr;
 	struct IsdnCardState *cs = bcs->cs;
-	long flags;
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hscx_empty_fifo");
@@ -73,11 +66,8 @@
 	}
 	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
 	bcs->hw.hscx.rcvidx += count;
-	save_flags(flags);
-	cli();
 	READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
 	WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
-	restore_flags(flags);
 	if (cs->debug & L1_DEB_HSCX_FIFO) {
 		char *t = bcs->blog;
 
@@ -95,8 +85,6 @@
 	int more, count;
 	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
 	u_char *ptr;
-	long flags;
-
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hscx_fill_fifo");
@@ -114,15 +102,12 @@
 		count = bcs->tx_skb->len;
 
 	waitforXFW(cs, bcs->hw.hscx.hscx);
-	save_flags(flags);
-	cli();
 	ptr = bcs->tx_skb->data;
 	skb_pull(bcs->tx_skb, count);
 	bcs->tx_cnt -= count;
-	bcs->hw.hscx.count += count;
+	bcs->count += count;
 	WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
 	WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
-	restore_flags(flags);
 	if (cs->debug & L1_DEB_HSCX_FIFO) {
 		char *t = bcs->blog;
 
@@ -189,7 +174,7 @@
 			}
 		}
 		bcs->hw.hscx.rcvidx = 0;
-		hscx_sched_event(bcs, B_RCVBUFREADY);
+		sched_b_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		hscx_empty_fifo(bcs, fifo_size);
@@ -202,34 +187,20 @@
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
 			bcs->hw.hscx.rcvidx = 0;
-			hscx_sched_event(bcs, B_RCVBUFREADY);
+			sched_b_event(bcs, B_RCVBUFREADY);
 		}
 	}
-	if (val & 0x10) {	/* XPR */
-		if (bcs->tx_skb) {
-			if (bcs->tx_skb->len) {
-				hscx_fill_fifo(bcs);
-				return;
-			} else {
-				if (bcs->st->lli.l1writewakeup &&
-					(PACKET_NOACK != bcs->tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				dev_kfree_skb_irq(bcs->tx_skb);
-				bcs->hw.hscx.count = 0; 
-				bcs->tx_skb = NULL;
-			}
-		}
-		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-			bcs->hw.hscx.count = 0;
-			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
-			hscx_fill_fifo(bcs);
-		} else {
-			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-			hscx_sched_event(bcs, B_XMTBUFREADY);
-		}
+	if (val & 0x10) {
+		xmit_xpr_b(bcs);
 	}
 }
 
+static void
+reset_xmit(struct BCState *bcs)
+{
+	WriteHSCXCMDR(bcs->cs, bcs->hw.hscx.hscx, 0x01);
+}
+
 static inline void
 hscx_int_main(struct IsdnCardState *cs, u_char val)
 {
@@ -237,30 +208,15 @@
 	u_char exval;
 	struct BCState *bcs;
 
+	spin_lock(&cs->lock);
 	if (val & 0x01) {
 		bcs = cs->bcs + 1;
 		exval = READHSCX(cs, 1, HSCX_EXIR);
-		if (exval & 0x40) {
-			if (bcs->mode == 1)
-				hscx_fill_fifo(bcs);
-			else {
-#ifdef ERROR_STATISTIC
-				bcs->err_tx++;
-#endif
-				/* Here we lost an TX interrupt, so
-				   * restart transmitting the whole frame.
-				 */
-				if (bcs->tx_skb) {
-					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
-					bcs->tx_cnt += bcs->hw.hscx.count;
-					bcs->hw.hscx.count = 0;
-				}
-				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
-			}
-		} else if (cs->debug & L1_DEB_HSCX)
+		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "HSCX B EXIR %x", exval);
+		if (exval & 0x40) {
+			xmit_xdu_b(bcs, reset_xmit);
+		}
 	}
 	if (val & 0xf8) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -270,27 +226,11 @@
 	if (val & 0x02) {
 		bcs = cs->bcs;
 		exval = READHSCX(cs, 0, HSCX_EXIR);
-		if (exval & 0x40) {
-			if (bcs->mode == L1_MODE_TRANS)
-				hscx_fill_fifo(bcs);
-			else {
-				/* Here we lost an TX interrupt, so
-				   * restart transmitting the whole frame.
-				 */
-#ifdef ERROR_STATISTIC
-				bcs->err_tx++;
-#endif
-				if (bcs->tx_skb) {
-					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
-					bcs->tx_cnt += bcs->hw.hscx.count;
-					bcs->hw.hscx.count = 0;
-				}
-				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
-			}
-		} else if (cs->debug & L1_DEB_HSCX)
+		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "HSCX A EXIR %x", exval);
+		if (exval & 0x40) {
+			xmit_xdu_b(bcs, reset_xmit);
+		}
 	}
 	if (val & 0x04) {
 		exval = READHSCX(cs, 0, HSCX_ISTA);
@@ -298,4 +238,5 @@
 			debugl1(cs, "HSCX A interrupt %x", exval);
 		hscx_interrupt(cs, exval, 0);
 	}
+	spin_unlock(&cs->lock);
 }
diff -Nru a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
--- a/drivers/isdn/hisax/icc.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/icc.c	Wed Nov 27 14:36:27 2002
@@ -146,29 +146,15 @@
 icc_fill_fifo(struct IsdnCardState *cs)
 {
 	int count, more;
-	u_char *ptr;
+	unsigned char *p;
 	unsigned long flags;
 
-	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
-		debugl1(cs, "icc_fill_fifo");
-
-	if (!cs->tx_skb)
-		return;
-
-	count = cs->tx_skb->len;
-	if (count <= 0)
+	p = xmit_fill_fifo_d(cs, 32, &count, &more);
+	if (!p)
 		return;
 
-	more = 0;
-	if (count > 32) {
-		more = !0;
-		count = 32;
-	}
 	spin_lock_irqsave(&icc_lock, flags);
-	ptr = cs->tx_skb->data;
-	skb_pull(cs->tx_skb, count);
-	cs->tx_cnt += count;
-	cs->writeisacfifo(cs, ptr, count);
+	cs->writeisacfifo(cs, p, count);
 	cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa);
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 		debugl1(cs, "icc_fill_fifo dbusytimer running");
@@ -178,20 +164,6 @@
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
 	spin_unlock_irqrestore(&icc_lock, flags);
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "icc_fill_fifo cnt %d", count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
-	}
-}
-
-void
-icc_sched_event(struct IsdnCardState *cs, int event)
-{
-	test_and_set_bit(event, &cs->event);
-	schedule_work(&cs->work);
 }
 
 void
@@ -240,7 +212,7 @@
 			spin_unlock_irqrestore(&icc_lock, flags);
 		}
 		cs->rcvidx = 0;
-		icc_sched_event(cs, D_RCVBUFREADY);
+		sched_d_event(cs, D_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		icc_empty_fifo(cs, 32);
@@ -251,27 +223,8 @@
 			debugl1(cs, "ICC RSC interrupt");
 	}
 	if (val & 0x10) {	/* XPR */
-		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-			del_timer(&cs->dbusytimer);
-		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			icc_sched_event(cs, D_CLEARBUSY);
-		if (cs->tx_skb) {
-			if (cs->tx_skb->len) {
-				icc_fill_fifo(cs);
-				goto afterXPR;
-			} else {
-				dev_kfree_skb_irq(cs->tx_skb);
-				cs->tx_cnt = 0;
-				cs->tx_skb = NULL;
-			}
-		}
-		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
-			cs->tx_cnt = 0;
-			icc_fill_fifo(cs);
-		} else
-			icc_sched_event(cs, D_XMTBUFREADY);
+		xmit_xpr_d(cs);
 	}
-      afterXPR:
 	if (val & 0x04) {	/* CISQ */
 		exval = cs->readisac(cs, ICC_CIR0);
 		if (cs->debug & L1_DEB_ISAC)
@@ -280,7 +233,7 @@
 			cs->dc.icc.ph_state = (exval >> 2) & 0xf;
 			if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state);
-			icc_sched_event(cs, D_L1STATECHANGE);
+			sched_d_event(cs, D_L1STATECHANGE);
 		}
 		if (exval & 1) {
 			exval = cs->readisac(cs, ICC_CIR1);
@@ -302,23 +255,7 @@
 			printk(KERN_WARNING "HiSax: ICC XMR\n");
 		}
 		if (exval & 0x40) {  /* XDU */
-			debugl1(cs, "ICC XDU");
-			printk(KERN_WARNING "HiSax: ICC XDU\n");
-#ifdef ERROR_STATISTIC
-			cs->err_tx++;
-#endif
-			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-				del_timer(&cs->dbusytimer);
-			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				icc_sched_event(cs, D_CLEARBUSY);
-			if (cs->tx_skb) { /* Restart frame */
-				skb_push(cs->tx_skb, cs->tx_cnt);
-				cs->tx_cnt = 0;
-				icc_fill_fifo(cs);
-			} else {
-				printk(KERN_WARNING "HiSax: ICC XDU no skb\n");
-				debugl1(cs, "ICC XDU no skb");
-			}
+			xmit_xdu_d(cs, NULL);
 		}
 		if (exval & 0x04) {  /* MOS */
 			v1 = cs->readisac(cs, ICC_MOSR);
@@ -388,14 +325,14 @@
 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 				cs->dc.icc.mocr |= 0x0a;
 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
-				icc_sched_event(cs, D_RX_MON0);
+				sched_d_event(cs, D_RX_MON0);
 			}
 			if (v1 & 0x40) {
 				cs->dc.icc.mocr &= 0x0f;
 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 				cs->dc.icc.mocr |= 0xa0;
 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
-				icc_sched_event(cs, D_RX_MON1);
+				sched_d_event(cs, D_RX_MON1);
 			}
 			if (v1 & 0x02) {
 				if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && 
@@ -407,11 +344,11 @@
 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 					if (cs->dc.icc.mon_txc &&
 						(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
-						icc_sched_event(cs, D_TX_MON0);
+						sched_d_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
 				if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
-					icc_sched_event(cs, D_TX_MON0);
+					sched_d_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
 				cs->writeisac(cs, ICC_MOX0,
@@ -430,11 +367,11 @@
 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
 					if (cs->dc.icc.mon_txc &&
 						(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
-						icc_sched_event(cs, D_TX_MON1);
+						sched_d_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
 				if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
-					icc_sched_event(cs, D_TX_MON1);
+					sched_d_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
 				cs->writeisac(cs, ICC_MOX1,
@@ -457,55 +394,13 @@
 
 	switch (pr) {
 		case (PH_DATA |REQUEST):
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				icc_fill_fifo(cs);
-			}
+			xmit_data_req_d(cs, skb);
 			break;
 		case (PH_PULL |INDICATION):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			icc_fill_fifo(cs);
+			xmit_pull_ind_d(cs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_d(st);
 			break;
 		case (HW_RESET | REQUEST):
 			if ((cs->dc.icc.ph_state == ICC_IND_EI1) ||
@@ -557,7 +452,7 @@
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				icc_sched_event(cs, D_CLEARBUSY);
+				sched_d_event(cs, D_CLEARBUSY);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -623,15 +518,37 @@
 void __init
 initicc(struct IsdnCardState *cs)
 {
+	int val, eval;
+
 	INIT_WORK(&cs->work, icc_bh, cs);
 	cs->setstack_d = setstack_icc;
+	cs->DC_Send_Data = icc_fill_fifo;
 	cs->DC_Close = DC_Close_icc;
 	cs->dc.icc.mon_tx = NULL;
 	cs->dc.icc.mon_rx = NULL;
 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
-  	cs->writeisac(cs, ICC_MASK, 0xff);
+
+	val = cs->readisac(cs, ICC_STAR);
+	debugl1(cs, "ICC STAR %x", val);
+	val = cs->readisac(cs, ICC_MODE);
+	debugl1(cs, "ICC MODE %x", val);
+	val = cs->readisac(cs, ICC_ADF2);
+	debugl1(cs, "ICC ADF2 %x", val);
+	val = cs->readisac(cs, ICC_ISTA);
+	debugl1(cs, "ICC ISTA %x", val);
+	if (val & 0x01) {
+		eval = cs->readisac(cs, ICC_EXIR);
+		debugl1(cs, "ICC EXIR %x", eval);
+	}
+	val = cs->readisac(cs, ICC_CIR0);
+	debugl1(cs, "ICC CIR0 %x", val);
+	cs->dc.icc.ph_state = (val >> 2) & 0xf;
+	sched_d_event(cs, D_L1STATECHANGE);
+	/* Disable all IRQ */
+	cs->writeisac(cs, ICC_MASK, 0xFF);
+
   	cs->dc.icc.mocr = 0xaa;
 	if (test_bit(HW_IOM1, &cs->HW_Flags)) {
 		/* IOM 1 Mode */
@@ -655,29 +572,4 @@
 	ph_command(cs, ICC_CMD_RES);
 	cs->writeisac(cs, ICC_MASK, 0x0);
 	ph_command(cs, ICC_CMD_DI);
-}
-
-void __init
-clear_pending_icc_ints(struct IsdnCardState *cs)
-{
-	int val, eval;
-
-	val = cs->readisac(cs, ICC_STAR);
-	debugl1(cs, "ICC STAR %x", val);
-	val = cs->readisac(cs, ICC_MODE);
-	debugl1(cs, "ICC MODE %x", val);
-	val = cs->readisac(cs, ICC_ADF2);
-	debugl1(cs, "ICC ADF2 %x", val);
-	val = cs->readisac(cs, ICC_ISTA);
-	debugl1(cs, "ICC ISTA %x", val);
-	if (val & 0x01) {
-		eval = cs->readisac(cs, ICC_EXIR);
-		debugl1(cs, "ICC EXIR %x", eval);
-	}
-	val = cs->readisac(cs, ICC_CIR0);
-	debugl1(cs, "ICC CIR0 %x", val);
-	cs->dc.icc.ph_state = (val >> 2) & 0xf;
-	icc_sched_event(cs, D_L1STATECHANGE);
-	/* Disable all IRQ */
-	cs->writeisac(cs, ICC_MASK, 0xFF);
 }
diff -Nru a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h
--- a/drivers/isdn/hisax/icc.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/icc.h	Wed Nov 27 14:36:31 2002
@@ -68,4 +68,3 @@
 extern void ICCVersion(struct IsdnCardState *cs, char *s);
 extern void initicc(struct IsdnCardState *cs);
 extern void icc_interrupt(struct IsdnCardState *cs, u_char val);
-extern void clear_pending_icc_ints(struct IsdnCardState *cs);
diff -Nru a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
--- a/drivers/isdn/hisax/ipacx.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/hisax/ipacx.c	Wed Nov 27 14:36:30 2002
@@ -23,7 +23,6 @@
 #define MAX_DFRAME_LEN_L1 300
 #define B_FIFO_SIZE       64
 #define D_FIFO_SIZE       32
-static spinlock_t ipacx_lock = SPIN_LOCK_UNLOCKED;
 
 // ipacx interrupt mask values    
 #define _MASK_IMASK     0x2E  // global mask
@@ -39,16 +38,13 @@
 static void dbusy_timer_handler(struct IsdnCardState *cs);
 static void ipacx_new_ph(struct IsdnCardState *cs);
 static void dch_bh(void *data);
-static void dch_sched_event(struct IsdnCardState *cs, int event);
 static void dch_empty_fifo(struct IsdnCardState *cs, int count);
 static void dch_fill_fifo(struct IsdnCardState *cs);
 static inline void dch_int(struct IsdnCardState *cs);
 static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs);
 static void __devinit dch_init(struct IsdnCardState *cs);
 static void bch_l2l1(struct PStack *st, int pr, void *arg);
-static void bch_sched_event(struct BCState *bcs, int event);
 static void bch_empty_fifo(struct BCState *bcs, int count);
-static void bch_fill_fifo(struct BCState *bcs);
 static void bch_int(struct IsdnCardState *cs, u_char hscx);
 static void bch_mode(struct BCState *bcs, int mode, int bc);
 static void bch_close_state(struct BCState *bcs);
@@ -79,8 +75,8 @@
 
 	event = cs->readisac(cs, IPACX_CIR0) >> 4;
 	if (cs->debug &L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event);
-  cs->dc.isac.ph_state = event;
-  dch_sched_event(cs, D_L1STATECHANGE);
+	cs->dc.isac.ph_state = event;
+	sched_d_event(cs, D_L1STATECHANGE);
 }
 
 //==========================================================
@@ -99,51 +95,14 @@
 
 	switch (pr) {
 		case (PH_DATA |REQUEST):
-			if (cs->debug &DEB_DLOG_HEX)     LogFrame(cs, skb->data, skb->len);
-			if (cs->debug &DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0);
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG
-				if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG
-				if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				dch_fill_fifo(cs);
-			}
+			xmit_data_req_d(cs, skb);
 			break;
-      
 		case (PH_PULL |INDICATION):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if (cs->debug & DEB_DLOG_HEX)     LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0);
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG
-			if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			dch_fill_fifo(cs);
+			xmit_pull_ind_d(cs, skb);
 			break;
-      
 		case (PH_PULL | REQUEST):
-#ifdef L2FRAME_DEBUG
-			if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l2.l1l2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_d(st);
 			break;
-
 		case (HW_RESET | REQUEST):
 		case (HW_ENABLE | REQUEST):
 			ph_command(cs, IPACX_CMD_TIM);
@@ -300,22 +259,11 @@
 }
 
 //----------------------------------------------------------
-// proceed with bottom half handler dch_bh()
-//----------------------------------------------------------
-static void
-dch_sched_event(struct IsdnCardState *cs, int event)
-{
-	set_bit(event, &cs->event);
-	schedule_work(&cs->work);
-}
-
-//----------------------------------------------------------
 // Fill buffer from receive FIFO
 //----------------------------------------------------------
 static void 
 dch_empty_fifo(struct IsdnCardState *cs, int count)
 {
-	unsigned long flags;
 	u_char *ptr;
 
 	if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
@@ -333,10 +281,8 @@
 	ptr = cs->rcvbuf + cs->rcvidx;
 	cs->rcvidx += count;
   
-	spin_lock_irqsave(&ipacx_lock, flags);
 	cs->readisacfifo(cs, ptr, count);
 	cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC
-	spin_unlock_irqrestore(&ipacx_lock, flags);
   
 	if (cs->debug &L1_DEB_ISAC_FIFO) {
 		char *t = cs->dlog;
@@ -353,29 +299,20 @@
 static void 
 dch_fill_fifo(struct IsdnCardState *cs)
 {
-	unsigned long flags;
-	int count;
-	u_char cmd, *ptr;
+	int count, more;
+	unsigned char cmd, *p;
 
-	if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO))
-		debugl1(cs, "dch_fill_fifo()");
-    
-	if (!cs->tx_skb) return;
-	count = cs->tx_skb->len;
-	if (count <= 0) return;
+	p = xmit_fill_fifo_d(cs, 32, &count, &more);
+	if (!p)
+		return;
 
-	if (count > D_FIFO_SIZE) {
-		count = D_FIFO_SIZE;
+	if (more) {
 		cmd   = 0x08; // XTF
 	} else {
 		cmd   = 0x0A; // XTF | XME
 	}
   
-	spin_lock_irqsave(&ipacx_lock, flags);
-	ptr = cs->tx_skb->data;
-	skb_pull(cs->tx_skb, count);
-	cs->tx_cnt += count;
-	cs->writeisacfifo(cs, ptr, count);
+	cs->writeisacfifo(cs, p, count);
 	cs->writeisac(cs, IPACX_CMDRD, cmd);
   
   // set timeout for transmission contol
@@ -386,15 +323,6 @@
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
-	spin_unlock_irqrestore(&ipacx_lock, flags);
-  
-	if (cs->debug &L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "dch_fill_fifo() cnt %d", count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
-	}
 }
 
 //----------------------------------------------------------
@@ -405,7 +333,6 @@
 {
 	struct sk_buff *skb;
 	u_char istad, rstad;
-	unsigned long flags;
 	int count;
 
 	istad = cs->readisac(cs, IPACX_ISTAD);
@@ -429,7 +356,6 @@
 			count &= D_FIFO_SIZE-1;
 			if (count == 0) count = D_FIFO_SIZE;
 			dch_empty_fifo(cs, count);
-			spin_lock_irqsave(&ipacx_lock, flags);
 			if ((count = cs->rcvidx) > 0) {
 	      cs->rcvidx = 0;
 				if (!(skb = dev_alloc_skb(count)))
@@ -439,10 +365,9 @@
 					skb_queue_tail(&cs->rq, skb);
 				}
 			}
-			spin_unlock_irqrestore(&ipacx_lock, flags);
     }
 	  cs->rcvidx = 0;
-		dch_sched_event(cs, D_RCVBUFREADY);
+		sched_d_event(cs, D_RCVBUFREADY);
 	}
 
 	if (istad &0x40) {  // RPF
@@ -454,43 +379,13 @@
 	  cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES
 	}
   
-  if (istad &0x10) {  // XPR
-		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-			del_timer(&cs->dbusytimer);
-		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			dch_sched_event(cs, D_CLEARBUSY);
-    if (cs->tx_skb) {
-      if (cs->tx_skb->len) {
-        dch_fill_fifo(cs);
-        goto afterXPR;
-      }
-      else {
-        dev_kfree_skb_irq(cs->tx_skb);
-        cs->tx_skb = NULL;
-        cs->tx_cnt = 0;
-      }
-    }
-    if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
-      cs->tx_cnt = 0;
-      dch_fill_fifo(cs);
-    } 
-    else {
-      dch_sched_event(cs, D_XMTBUFREADY);
-    }  
-  }  
-  afterXPR:
+	if (istad &0x10) {  // XPR
+		xmit_xpr_d(cs);
+	}  
 
 	if (istad &0x0C) {  // XDU or XMR
-		if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): XDU");
-	  if (cs->tx_skb) {
-	    skb_push(cs->tx_skb, cs->tx_cnt); // retransmit
-	    cs->tx_cnt = 0;
-			dch_fill_fifo(cs);
-		} else {
-			printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
-			debugl1(cs, "ISAC XDU no skb");
-		}
-  }
+		xmit_xdu_d(cs, NULL);
+	}
 }
 
 //----------------------------------------------------------
@@ -510,7 +405,7 @@
 
 	INIT_WORK(&cs->work, dch_bh, cs);
 	cs->setstack_d      = dch_setstack;
-  
+	cs->DC_Send_Data = dch_fill_fifo;
 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
@@ -533,38 +428,16 @@
 bch_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	unsigned long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			spin_lock_irqsave(&ipacx_lock, flags);
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				spin_unlock_irqrestore(&ipacx_lock, flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-				set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				st->l1.bcs->hw.hscx.count = 0;
-				spin_unlock_irqrestore(&ipacx_lock, flags);
-        bch_fill_fifo(st->l1.bcs);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n");
-				break;
-			}
-			set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->hw.hscx.count = 0;
-      bch_fill_fifo(st->l1.bcs);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l2.l1l2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
@@ -584,16 +457,6 @@
 }
 
 //----------------------------------------------------------
-// proceed with bottom half handler BChannel_bh()
-//----------------------------------------------------------
-static void
-bch_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
-//----------------------------------------------------------
 // Read B channel fifo to receive buffer
 //----------------------------------------------------------
 static void
@@ -601,7 +464,6 @@
 {
 	u_char *ptr, hscx;
 	struct IsdnCardState *cs;
-	unsigned long flags;
 	int cnt;
 
 	cs = bcs->cs;
@@ -619,7 +481,6 @@
 	}
   
   // Read data uninterruptible
-	spin_lock_irqsave(&ipacx_lock, flags);
 	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
 	cnt = count;
 	while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB); 
@@ -627,7 +488,6 @@
   
 	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
 	bcs->hw.hscx.rcvidx += count;
-	spin_unlock_irqrestore(&ipacx_lock, flags);
   
 	if (cs->debug &L1_DEB_HSCX_FIFO) {
 		char *t = bcs->blog;
@@ -641,52 +501,34 @@
 //----------------------------------------------------------
 // Fill buffer to transmit FIFO
 //----------------------------------------------------------
-static void
-bch_fill_fifo(struct BCState *bcs)
+void
+ipacx_fill_fifo(struct BCState *bcs)
 {
-	struct IsdnCardState *cs;
-	int more, count, cnt;
-	u_char *ptr, *p, hscx;
-	unsigned long flags;
+	struct IsdnCardState *cs = bcs->cs;
+	int more, count;
+	unsigned char hscx = bcs->hw.hscx.hscx;
+	unsigned char *p;
 
-	cs = bcs->cs;
-	if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO))
-		debugl1(cs, "bch_fill_fifo()");
+	p = xmit_fill_fifo_b(bcs, B_FIFO_SIZE, &count, &more);
+	if (!p)
+		return;
 
-	if (!bcs->tx_skb)           return;
-	if (bcs->tx_skb->len <= 0)  return;
+	while (count--)
+		cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); 
 
-	hscx = bcs->hw.hscx.hscx;
-	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
-	if (bcs->tx_skb->len > B_FIFO_SIZE) {
-		more  = 1;
-		count = B_FIFO_SIZE;
-	} else {
-		count = bcs->tx_skb->len;
-	}  
-	cnt = count;
-    
-	spin_lock_irqsave(&ipacx_lock, flags);
-	p = ptr = bcs->tx_skb->data;
-	skb_pull(bcs->tx_skb, count);
-	bcs->tx_cnt -= count;
-	bcs->hw.hscx.count += count;
-	while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); 
 	cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a));
-	spin_unlock_irqrestore(&ipacx_lock, flags);
-  
-	if (cs->debug &L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
 }
 
 //----------------------------------------------------------
 // B channel interrupt handler
 //----------------------------------------------------------
+
+static void
+reset_xmit(struct BCState *bcs)
+{
+	bcs->cs->BC_Write_Reg(bcs->cs, bcs->hw.hscx.hscx, IPACX_CMDRB, 0x01);  // XRES
+}
+
 static void
 bch_int(struct IsdnCardState *cs, u_char hscx)
 {
@@ -730,7 +572,7 @@
 			}
 		}
 		bcs->hw.hscx.rcvidx = 0;
-		bch_sched_event(bcs, B_RCVBUFREADY);
+		sched_b_event(bcs, B_RCVBUFREADY);
 	}
   
 	if (istab &0x40) {	// RPF
@@ -745,57 +587,22 @@
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
 			bcs->hw.hscx.rcvidx = 0;
-			bch_sched_event(bcs, B_RCVBUFREADY);
+			sched_b_event(bcs, B_RCVBUFREADY);
 		}
 	}
   
 	if (istab &0x20) {	// RFO
 		if (cs->debug &L1_DEB_WARN) 
-      debugl1(cs, "bch_int() B-%d: RFO error", hscx);
-	  cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40);  // RRES
+			debugl1(cs, "bch_int() B-%d: RFO error", hscx);
+		cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40);  // RRES
 	}
 
 	if (istab &0x10) {	// XPR
-		if (bcs->tx_skb) {
-			if (bcs->tx_skb->len) {
-		    bch_fill_fifo(bcs);
-        goto afterXPR;
-      }
-      else {
-				if (bcs->st->lli.l1writewakeup &&
-					  (PACKET_NOACK != bcs->tx_skb->pkt_type)) {    
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-        }  
-			  dev_kfree_skb_irq(bcs->tx_skb);
-			  bcs->hw.hscx.count = 0; 
-			  bcs->tx_skb = NULL;
-      }
-    }    
-    if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-      bcs->hw.hscx.count = 0;
-      set_bit(BC_FLG_BUSY, &bcs->Flag);
-      bch_fill_fifo(bcs);
-    } else {
-      clear_bit(BC_FLG_BUSY, &bcs->Flag);
-      bch_sched_event(bcs, B_XMTBUFREADY);
-    }
-  }
-  afterXPR:
+		xmit_xpr_b(bcs);
+	}
 
 	if (istab &0x04) {	// XDU
-    if (bcs->mode == L1_MODE_TRANS) {
-			bch_fill_fifo(bcs);
-    }  
-    else {
-      if (bcs->tx_skb) {  // restart transmitting the whole frame
-        skb_push(bcs->tx_skb, bcs->hw.hscx.count);
-        bcs->tx_cnt += bcs->hw.hscx.count;
-        bcs->hw.hscx.count = 0;
-      }
-	    cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01);  // XRES
-      if (cs->debug &L1_DEB_WARN)
-        debugl1(cs, "bch_int() B-%d XDU error", hscx);
-    }
+		xmit_xdu_b(bcs, reset_xmit);
 	}
 }
 
@@ -942,13 +749,15 @@
 interrupt_ipacx(struct IsdnCardState *cs)
 {
 	u_char ista;
-  
+	
+	spin_lock(&cs->lock);
 	while ((ista = cs->readisac(cs, IPACX_ISTA))) {
 		if (ista &0x80) bch_int(cs, 0); // B channel interrupts
 		if (ista &0x40) bch_int(cs, 1);
 		if (ista &0x01) dch_int(cs);    // D channel
 		if (ista &0x10) cic_int(cs);    // Layer 1 state
 	}  
+	spin_unlock(&cs->lock);
 }
 
 //----------------------------------------------------------
diff -Nru a/drivers/isdn/hisax/ipacx.h b/drivers/isdn/hisax/ipacx.h
--- a/drivers/isdn/hisax/ipacx.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/ipacx.h	Wed Nov 27 14:36:27 2002
@@ -157,5 +157,6 @@
 
 extern void init_ipacx(struct IsdnCardState *cs, int part);
 extern void interrupt_ipacx(struct IsdnCardState *cs);
+extern void ipacx_fill_fifo(struct BCState *bcs);
 
 #endif
diff -Nru a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
--- a/drivers/isdn/hisax/isac.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/isac.c	Wed Nov 27 14:36:28 2002
@@ -22,7 +22,6 @@
 
 #define DBUSY_TIMER_VALUE 80
 #define ARCOFI_USE 1
-static spinlock_t isac_lock = SPIN_LOCK_UNLOCKED;
 
 static char *ISACVer[] __devinitdata =
 {"2086/2186 V1.1", "2085 B1", "2085 B2",
@@ -118,7 +117,6 @@
 isac_empty_fifo(struct IsdnCardState *cs, int count)
 {
 	u_char *ptr;
-	unsigned long flags;
 
 	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
 		debugl1(cs, "isac_empty_fifo");
@@ -133,10 +131,8 @@
 	}
 	ptr = cs->rcvbuf + cs->rcvidx;
 	cs->rcvidx += count;
-	spin_lock_irqsave(&isac_lock, flags);
 	cs->readisacfifo(cs, ptr, count);
 	cs->writeisac(cs, ISAC_CMDR, 0x80);
-	spin_unlock_irqrestore(&isac_lock, flags);
 	if (cs->debug & L1_DEB_ISAC_FIFO) {
 		char *t = cs->dlog;
 
@@ -150,29 +146,13 @@
 isac_fill_fifo(struct IsdnCardState *cs)
 {
 	int count, more;
-	u_char *ptr;
-	unsigned long flags;
-
-	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
-		debugl1(cs, "isac_fill_fifo");
-
-	if (!cs->tx_skb)
-		return;
+	unsigned char *p;
 
-	count = cs->tx_skb->len;
-	if (count <= 0)
+	p = xmit_fill_fifo_d(cs, 32, &count, &more);
+	if (!p)
 		return;
 
-	more = 0;
-	if (count > 32) {
-		more = !0;
-		count = 32;
-	}
-	spin_lock_irqsave(&isac_lock, flags);
-	ptr = cs->tx_skb->data;
-	skb_pull(cs->tx_skb, count);
-	cs->tx_cnt += count;
-	cs->writeisacfifo(cs, ptr, count);
+	cs->writeisacfifo(cs, p, count);
 	cs->writeisac(cs, ISAC_CMDR, more ? 0x8 : 0xa);
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 		debugl1(cs, "isac_fill_fifo dbusytimer running");
@@ -181,21 +161,6 @@
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
-	spin_unlock_irqrestore(&isac_lock, flags);
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "isac_fill_fifo cnt %d", count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
-	}
-}
-
-void
-isac_sched_event(struct IsdnCardState *cs, int event)
-{
-	test_and_set_bit(event, &cs->event);
-	schedule_work(&cs->work);
 }
 
 void
@@ -204,7 +169,6 @@
 	u_char exval, v1;
 	struct sk_buff *skb;
 	unsigned int count;
-	unsigned long flags;
 
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "ISAC interrupt %x", val);
@@ -231,7 +195,6 @@
 			if (count == 0)
 				count = 32;
 			isac_empty_fifo(cs, count);
-			spin_lock_irqsave(&isac_lock, flags);
 			if ((count = cs->rcvidx) > 0) {
 				cs->rcvidx = 0;
 				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
@@ -241,10 +204,9 @@
 					skb_queue_tail(&cs->rq, skb);
 				}
 			}
-			spin_unlock_irqrestore(&isac_lock, flags);
 		}
 		cs->rcvidx = 0;
-		isac_sched_event(cs, D_RCVBUFREADY);
+		sched_d_event(cs, D_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		isac_empty_fifo(cs, 32);
@@ -255,27 +217,8 @@
 			debugl1(cs, "ISAC RSC interrupt");
 	}
 	if (val & 0x10) {	/* XPR */
-		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-			del_timer(&cs->dbusytimer);
-		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			isac_sched_event(cs, D_CLEARBUSY);
-		if (cs->tx_skb) {
-			if (cs->tx_skb->len) {
-				isac_fill_fifo(cs);
-				goto afterXPR;
-			} else {
-				dev_kfree_skb_irq(cs->tx_skb);
-				cs->tx_cnt = 0;
-				cs->tx_skb = NULL;
-			}
-		}
-		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
-			cs->tx_cnt = 0;
-			isac_fill_fifo(cs);
-		} else
-			isac_sched_event(cs, D_XMTBUFREADY);
+		xmit_xpr_d(cs);
 	}
-      afterXPR:
 	if (val & 0x04) {	/* CISQ */
 		exval = cs->readisac(cs, ISAC_CIR0);
 		if (cs->debug & L1_DEB_ISAC)
@@ -284,7 +227,7 @@
 			cs->dc.isac.ph_state = (exval >> 2) & 0xf;
 			if (cs->debug & L1_DEB_ISAC)
 				debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state);
-			isac_sched_event(cs, D_L1STATECHANGE);
+			sched_d_event(cs, D_L1STATECHANGE);
 		}
 		if (exval & 1) {
 			exval = cs->readisac(cs, ISAC_CIR1);
@@ -306,23 +249,7 @@
 			printk(KERN_WARNING "HiSax: ISAC XMR\n");
 		}
 		if (exval & 0x40) {  /* XDU */
-			debugl1(cs, "ISAC XDU");
-			printk(KERN_WARNING "HiSax: ISAC XDU\n");
-#ifdef ERROR_STATISTIC
-			cs->err_tx++;
-#endif
-			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-				del_timer(&cs->dbusytimer);
-			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				isac_sched_event(cs, D_CLEARBUSY);
-			if (cs->tx_skb) { /* Restart frame */
-				skb_push(cs->tx_skb, cs->tx_cnt);
-				cs->tx_cnt = 0;
-				isac_fill_fifo(cs);
-			} else {
-				printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
-				debugl1(cs, "ISAC XDU no skb");
-			}
+			xmit_xdu_d(cs, NULL);
 		}
 		if (exval & 0x04) {  /* MOS */
 			v1 = cs->readisac(cs, ISAC_MOSR);
@@ -392,14 +319,14 @@
 				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				cs->dc.isac.mocr |= 0x0a;
 				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
-				isac_sched_event(cs, D_RX_MON0);
+				sched_d_event(cs, D_RX_MON0);
 			}
 			if (v1 & 0x40) {
 				cs->dc.isac.mocr &= 0x0f;
 				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				cs->dc.isac.mocr |= 0xa0;
 				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
-				isac_sched_event(cs, D_RX_MON1);
+				sched_d_event(cs, D_RX_MON1);
 			}
 			if (v1 & 0x02) {
 				if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && 
@@ -411,11 +338,11 @@
 					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 					if (cs->dc.isac.mon_txc &&
 						(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
-						isac_sched_event(cs, D_TX_MON0);
+						sched_d_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
 				if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
-					isac_sched_event(cs, D_TX_MON0);
+					sched_d_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
 				cs->writeisac(cs, ISAC_MOX0,
@@ -434,11 +361,11 @@
 					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 					if (cs->dc.isac.mon_txc &&
 						(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
-						isac_sched_event(cs, D_TX_MON1);
+						sched_d_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
 				if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
-					isac_sched_event(cs, D_TX_MON1);
+					sched_d_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
 				cs->writeisac(cs, ISAC_MOX1,
@@ -461,55 +388,13 @@
 
 	switch (pr) {
 		case (PH_DATA |REQUEST):
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				isac_fill_fifo(cs);
-			}
+			xmit_data_req_d(cs, skb);
 			break;
 		case (PH_PULL |INDICATION):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			isac_fill_fifo(cs);
+			xmit_pull_ind_d(cs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_d(st);
 			break;
 		case (HW_RESET | REQUEST):
 			if ((cs->dc.isac.ph_state == ISAC_IND_EI) ||
@@ -559,7 +444,7 @@
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				isac_sched_event(cs, D_CLEARBUSY);
+				sched_d_event(cs, D_CLEARBUSY);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -625,8 +510,26 @@
 void __devinit
 initisac(struct IsdnCardState *cs)
 {
+	int val, eval;
+
+	val = cs->readisac(cs, ISAC_STAR);
+	debugl1(cs, "ISAC STAR %x", val);
+	val = cs->readisac(cs, ISAC_MODE);
+	debugl1(cs, "ISAC MODE %x", val);
+	val = cs->readisac(cs, ISAC_ADF2);
+	debugl1(cs, "ISAC ADF2 %x", val);
+	val = cs->readisac(cs, ISAC_ISTA);
+	debugl1(cs, "ISAC ISTA %x", val);
+	if (val & 0x01) {
+		eval = cs->readisac(cs, ISAC_EXIR);
+		debugl1(cs, "ISAC EXIR %x", eval);
+	}
+	/* Disable all IRQ */
+	cs->writeisac(cs, ISAC_MASK, 0xFF);
+
 	INIT_WORK(&cs->work, isac_bh, cs);
 	cs->setstack_d = setstack_isac;
+	cs->DC_Send_Data = isac_fill_fifo;
 	cs->DC_Close = DC_Close_isac;
 	cs->dc.isac.mon_tx = NULL;
 	cs->dc.isac.mon_rx = NULL;
@@ -656,29 +559,12 @@
 	}
 	ph_command(cs, ISAC_CMD_RS);
 	cs->writeisac(cs, ISAC_MASK, 0x0);
-}
 
-void __devinit
-clear_pending_isac_ints(struct IsdnCardState *cs)
-{
-	int val, eval;
-
-	val = cs->readisac(cs, ISAC_STAR);
-	debugl1(cs, "ISAC STAR %x", val);
-	val = cs->readisac(cs, ISAC_MODE);
-	debugl1(cs, "ISAC MODE %x", val);
-	val = cs->readisac(cs, ISAC_ADF2);
-	debugl1(cs, "ISAC ADF2 %x", val);
-	val = cs->readisac(cs, ISAC_ISTA);
-	debugl1(cs, "ISAC ISTA %x", val);
-	if (val & 0x01) {
-		eval = cs->readisac(cs, ISAC_EXIR);
-		debugl1(cs, "ISAC EXIR %x", eval);
-	}
 	val = cs->readisac(cs, ISAC_CIR0);
 	debugl1(cs, "ISAC CIR0 %x", val);
 	cs->dc.isac.ph_state = (val >> 2) & 0xf;
-	isac_sched_event(cs, D_L1STATECHANGE);
-	/* Disable all IRQ */
-	cs->writeisac(cs, ISAC_MASK, 0xFF);
+	sched_d_event(cs, D_L1STATECHANGE);
+
+	/* RESET Receiver and Transmitter */
+	cs->writeisac(cs, ISAC_CMDR, 0x41);
 }
diff -Nru a/drivers/isdn/hisax/isac.h b/drivers/isdn/hisax/isac.h
--- a/drivers/isdn/hisax/isac.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hisax/isac.h	Wed Nov 27 14:36:32 2002
@@ -66,4 +66,3 @@
 extern void ISACVersion(struct IsdnCardState *cs, char *s);
 extern void initisac(struct IsdnCardState *cs);
 extern void isac_interrupt(struct IsdnCardState *cs, u_char val);
-extern void clear_pending_isac_ints(struct IsdnCardState *cs);
diff -Nru a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
--- a/drivers/isdn/hisax/isar.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/hisax/isar.c	Wed Nov 27 14:36:30 2002
@@ -190,7 +190,6 @@
 	u_short sadr, left, *sp;
 	u_char *p = buf;
 	u_char *msg, *tmpmsg, *mp, tmp[64];
-	unsigned long flags;
 	struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
 	
 	struct {u_short sadr;
@@ -344,7 +343,6 @@
 	/* NORMAL mode entered */
 	/* Enable IRQs of ISAR */
 	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA);
-	spin_lock_irqsave(&isar_lock, flags);
 	cnt = 1000; /* max 1s */
 	while ((!ireg->bstat) && cnt) {
 		udelay(1000);
@@ -352,7 +350,7 @@
 	}
 	if (!cnt) {
 		printk(KERN_ERR"isar no general status event received\n");
-		ret = 1;goto reterrflg;
+		ret = 1;goto reterror;
 	} else {
 		printk(KERN_DEBUG"isar general status event %x\n",
 			ireg->bstat);
@@ -364,7 +362,7 @@
 	ireg->iis = 0;
 	if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
 		printk(KERN_ERR"isar sendmsg self tst failed\n");
-		ret = 1;goto reterrflg;
+		ret = 1;goto reterror;
 	}
 	cnt = 10000; /* max 100 ms */
 	while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
@@ -374,7 +372,7 @@
 	udelay(1000);
 	if (!cnt) {
 		printk(KERN_ERR"isar no self tst response\n");
-		ret = 1;goto reterrflg;
+		ret = 1;goto reterror;
 	}
 	if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1)
 		&& (ireg->par[0] == 0)) {
@@ -382,12 +380,12 @@
 	} else {
 		printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n",
 			ireg->cmsb, ireg->clsb, ireg->par[0]);
-		ret = 1;goto reterrflg;
+		ret = 1;goto reterror;
 	}
 	ireg->iis = 0;
 	if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
 		printk(KERN_ERR"isar RQST SVN failed\n");
-		ret = 1;goto reterrflg;
+		ret = 1;goto reterror;
 	}
 	cnt = 30000; /* max 300 ms */
 	while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
@@ -397,7 +395,7 @@
 	udelay(1000);
 	if (!cnt) {
 		printk(KERN_ERR"isar no SVN response\n");
-		ret = 1;goto reterrflg;
+		ret = 1;goto reterror;
 	} else {
 		if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1))
 			printk(KERN_DEBUG"isar software version %#x\n",
@@ -405,14 +403,12 @@
 		else {
 			printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n",
 				ireg->cmsb, ireg->clsb, cnt);
-			ret = 1;goto reterrflg;
+			ret = 1;goto reterror;
 		}
 	}
 	cs->debug = debug;
 	isar_setup(cs);
 	ret = 0;
-reterrflg:
-	spin_unlock_irqrestore(&isar_lock, flags);
 reterror:
 	cs->debug = debug;
 	if (ret)
@@ -424,9 +420,6 @@
 }
 
 extern void BChannel_bh(struct BCState *);
-#define B_LL_NOCARRIER	8
-#define B_LL_CONNECT	9
-#define B_LL_OK		10
 
 static void
 isar_bh(void *data)
@@ -442,13 +435,6 @@
 		ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK);
 }
 
-static void
-isar_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
 static inline void
 send_DLE_ETX(struct BCState *bcs)
 {
@@ -458,7 +444,7 @@
 	if ((skb = dev_alloc_skb(2))) {
 		memcpy(skb_put(skb, 2), dleetx, 2);
 		skb_queue_tail(&bcs->rqueue, skb);
-		isar_sched_event(bcs, B_RCVBUFREADY);
+		sched_b_event(bcs, B_RCVBUFREADY);
 	} else {
 		printk(KERN_WARNING "HiSax: skb out of memory\n");
 	}
@@ -510,7 +496,7 @@
 		if ((skb = dev_alloc_skb(ireg->clsb))) {
 			rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb));
 			skb_queue_tail(&bcs->rqueue, skb);
-			isar_sched_event(bcs, B_RCVBUFREADY);
+			sched_b_event(bcs, B_RCVBUFREADY);
 		} else {
 			printk(KERN_WARNING "HiSax: skb out of memory\n");
 			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
@@ -551,7 +537,7 @@
 					memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2),
 						bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2);
 					skb_queue_tail(&bcs->rqueue, skb);
-					isar_sched_event(bcs, B_RCVBUFREADY);
+					sched_b_event(bcs, B_RCVBUFREADY);
 				}
 				bcs->hw.isar.rcvidx = 0;
 			}
@@ -576,7 +562,7 @@
 				insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx),
 					bcs->hw.isar.rcvbuf, ireg->clsb);
 				skb_queue_tail(&bcs->rqueue, skb);
-				isar_sched_event(bcs, B_RCVBUFREADY);
+				sched_b_event(bcs, B_RCVBUFREADY);
 				if (ireg->cmsb & SART_NMD) { /* ABORT */
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "isar_rcv_frame: no more data");
@@ -587,7 +573,7 @@
 						ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
 						0, NULL);
 					bcs->hw.isar.state = STFAX_ESCAPE;
-					isar_sched_event(bcs, B_LL_NOCARRIER);
+					sched_b_event(bcs, B_LL_NOCARRIER);
 				}
 			} else {
 				printk(KERN_WARNING "HiSax: skb out of memory\n");
@@ -635,9 +621,9 @@
 						bcs->hw.isar.rcvbuf,
 						bcs->hw.isar.rcvidx);
 					skb_queue_tail(&bcs->rqueue, skb);
-					isar_sched_event(bcs, B_RCVBUFREADY);
+					sched_b_event(bcs, B_RCVBUFREADY);
 					send_DLE_ETX(bcs);
-					isar_sched_event(bcs, B_LL_OK);
+					sched_b_event(bcs, B_LL_OK);
 				}
 				bcs->hw.isar.rcvidx = 0;
 			}
@@ -651,7 +637,7 @@
 			sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
 				ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
 			bcs->hw.isar.state = STFAX_ESCAPE;
-			isar_sched_event(bcs, B_LL_NOCARRIER);
+			sched_b_event(bcs, B_LL_NOCARRIER);
 		}
 		break;
 	default:
@@ -668,7 +654,6 @@
 	int count;
 	u_char msb;
 	u_char *ptr;
-	unsigned long flags;
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "isar_fill_fifo");
@@ -686,9 +671,8 @@
 		count = bcs->tx_skb->len;
 		msb = HDLC_FED;
 	}
-	spin_lock_irqsave(&isar_lock, flags);
 	ptr = bcs->tx_skb->data;
-	if (!bcs->hw.isar.txcnt) {
+	if (!bcs->count) {
 		msb |= HDLC_FST;
 		if ((bcs->mode == L1_MODE_FAX) &&
 			(bcs->hw.isar.cmd == PCTRL_CMD_FTH)) {
@@ -702,7 +686,7 @@
 	}
 	skb_pull(bcs->tx_skb, count);
 	bcs->tx_cnt -= count;
-	bcs->hw.isar.txcnt += count;
+	bcs->count += count;
 	switch (bcs->mode) {
 		case L1_MODE_NULL:
 			printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
@@ -737,7 +721,6 @@
 			printk(KERN_ERR"isar_fill_fifo mode(%x) error\n", bcs->mode);
 			break;
 	}
-	spin_unlock_irqrestore(&isar_lock, flags);
 }
 
 inline
@@ -760,9 +743,7 @@
 			isar_fill_fifo(bcs);
 			return;
 		} else {
-			if (bcs->st->lli.l1writewakeup &&
-				(PACKET_NOACK != bcs->tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt);
+			xmit_complete_b(bcs);
 			if (bcs->mode == L1_MODE_FAX) {
 				if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
 					if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
@@ -775,13 +756,11 @@
 					}
 				}
 			}
-			dev_kfree_skb_any(bcs->tx_skb);
-			bcs->hw.isar.txcnt = 0; 
-			bcs->tx_skb = NULL;
+			bcs->count = 0; 
 		}
 	}
 	if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-		bcs->hw.isar.txcnt = 0;
+		bcs->count = 0;
 		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 		isar_fill_fifo(bcs);
 	} else {
@@ -794,11 +773,11 @@
 				}
 				test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag);
 			} else {
-				isar_sched_event(bcs, B_LL_CONNECT);
+				sched_b_event(bcs, B_LL_CONNECT);
 			}
 		}
 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		isar_sched_event(bcs, B_XMTBUFREADY);
+		sched_b_event(bcs, B_XMTBUFREADY);
 	}
 }
 
@@ -1057,7 +1036,7 @@
 						&bcs->Flag);
 					add_timer(&bcs->hw.isar.ftimer);
 				} else {
-					isar_sched_event(bcs, B_LL_CONNECT);
+					sched_b_event(bcs, B_LL_CONNECT);
 				}
 			} else {
 				if (cs->debug & L1_DEB_WARN)
@@ -1102,10 +1081,10 @@
 				}
 			} else if (bcs->hw.isar.state == STFAX_ACTIV) {
 				if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) {
-					isar_sched_event(bcs, B_LL_OK);
+					sched_b_event(bcs, B_LL_OK);
 				} else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) {
 					send_DLE_ETX(bcs);
-					isar_sched_event(bcs, B_LL_NOCARRIER);
+					sched_b_event(bcs, B_LL_NOCARRIER);
 				} else {
 					ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
 				}
@@ -1161,11 +1140,9 @@
 void
 isar_int_main(struct IsdnCardState *cs)
 {
-	unsigned long flags;
 	struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
 	struct BCState *bcs;
 
-	spin_lock_irqsave(&isar_lock, flags);
 	get_irq_infos(cs, ireg);
 	switch (ireg->iis & ISAR_IIS_MSCMSD) {
 		case ISAR_IIS_RDATA:
@@ -1251,7 +1228,6 @@
 					ireg->iis, ireg->cmsb, ireg->clsb);
 			break;
 	}
-	spin_unlock_irqrestore(&isar_lock, flags);
 }
 
 static void
@@ -1261,7 +1237,7 @@
 			bcs->Flag);
 	test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag);
 	if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) {
-		isar_sched_event(bcs, B_LL_CONNECT);
+		sched_b_event(bcs, B_LL_CONNECT);
 	}
 }
 
@@ -1565,42 +1541,16 @@
 isar_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	unsigned long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			spin_lock_irqsave(&isar_lock, flags);
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				spin_unlock_irqrestore(&isar_lock, flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
-					debugl1(st->l1.bcs->cs, "DRQ set BC_FLG_BUSY");
-				st->l1.bcs->hw.isar.txcnt = 0;
-				spin_unlock_irqrestore(&isar_lock, flags);
-				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n");
-				break;
-			}
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
-				debugl1(st->l1.bcs->cs, "PUI set BC_FLG_BUSY");
-			st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->hw.isar.txcnt = 0;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
--- a/drivers/isdn/hisax/isdnl1.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/isdnl1.c	Wed Nov 27 14:36:28 2002
@@ -298,6 +298,16 @@
 	}
 }
 
+static void
+BChannel_proc_cmpl(struct BCState *bcs)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&bcs->cmpl_queue))) {
+		L1L2(bcs->st, PH_DATA | CONFIRM, skb);
+	}
+}
+
 void
 BChannel_bh(void *data)
 {
@@ -307,6 +317,8 @@
 		BChannel_proc_rcv(bcs);
 	if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event))
 		BChannel_proc_xmt(bcs);
+	if (test_and_clear_bit(B_CMPLREADY, &bcs->event))
+		BChannel_proc_cmpl(bcs);
 }
 
 void
diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
--- a/drivers/isdn/hisax/isdnl1.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/isdnl1.h	Wed Nov 27 14:36:31 2002
@@ -17,8 +17,13 @@
 #define D_TX_MON1	7
 #define E_RCVBUFREADY	8
 
-#define B_RCVBUFREADY 0
-#define B_XMTBUFREADY 1
+#define B_RCVBUFREADY   0
+#define B_XMTBUFREADY   1
+#define B_CMPLREADY     2
+
+#define B_LL_NOCARRIER	8
+#define B_LL_CONNECT	9
+#define B_LL_OK		10
 
 extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
 extern void DChannel_proc_xmt(struct IsdnCardState *cs);
@@ -29,3 +34,376 @@
 #ifdef L2FRAME_DEBUG
 extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
 #endif
+
+static inline void
+sched_b_event(struct BCState *bcs, int event)
+{
+	set_bit(event, &bcs->event);
+	schedule_work(&bcs->work);
+}
+
+static inline void
+sched_d_event(struct IsdnCardState *cs, int event)
+{
+	set_bit(event, &cs->event);
+	schedule_work(&cs->work);
+}
+
+/* called with the card lock held */
+static inline void
+xmit_complete_b(struct BCState *bcs)
+{
+	skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb);
+	sched_b_event(bcs, B_CMPLREADY);
+	bcs->tx_skb = NULL;
+}
+
+/* called with the card lock held */
+static inline void
+xmit_complete_d(struct IsdnCardState *cs)
+{
+	dev_kfree_skb_irq(cs->tx_skb);
+	cs->tx_skb = NULL;
+}
+
+/* called with the card lock held */
+static inline void
+xmit_ready_b(struct BCState *bcs)
+{
+	bcs->tx_skb = skb_dequeue(&bcs->squeue);
+	if (bcs->tx_skb) {
+		bcs->count = 0;
+		set_bit(BC_FLG_BUSY, &bcs->Flag);
+		bcs->cs->BC_Send_Data(bcs);
+	} else {
+		clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		sched_b_event(bcs, B_XMTBUFREADY);
+	}
+}
+
+/* called with the card lock held */
+static inline void
+xmit_ready_d(struct IsdnCardState *cs)
+{
+	cs->tx_skb = skb_dequeue(&cs->sq);
+	if (cs->tx_skb) {
+		cs->tx_cnt = 0;
+		cs->DC_Send_Data(cs);
+	} else {
+		sched_d_event(cs, D_XMTBUFREADY);
+	}
+}
+
+static inline void
+xmit_data_req_b(struct BCState *bcs, struct sk_buff *skb)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	if (bcs->tx_skb) {
+		skb_queue_tail(&bcs->squeue, skb);
+	} else {
+		set_bit(BC_FLG_BUSY, &bcs->Flag);
+		bcs->tx_skb = skb;
+		bcs->count = 0;
+		bcs->cs->BC_Send_Data(bcs);
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
+}
+
+static inline void
+xmit_data_req_d(struct IsdnCardState *cs, struct sk_buff *skb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	if (cs->debug & DEB_DLOG_HEX)
+		LogFrame(cs, skb->data, skb->len);
+	if (cs->debug & DEB_DLOG_VERBOSE)
+		dlogframe(cs, skb, 0);
+	if (cs->tx_skb) {
+		skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG
+		if (cs->debug & L1_DEB_LAPD)
+			Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+	} else {
+		cs->tx_skb = skb;
+		cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG
+		if (cs->debug & L1_DEB_LAPD)
+			Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+		cs->DC_Send_Data(cs);
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
+}
+
+static inline void
+xmit_pull_ind_b(struct BCState *bcs, struct sk_buff *skb)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	if (bcs->tx_skb) {
+		WARN_ON(1);
+	} else {
+		set_bit(BC_FLG_BUSY, &bcs->Flag);
+		bcs->tx_skb = skb;
+		bcs->count = 0;
+		bcs->cs->BC_Send_Data(bcs);
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
+}
+
+static inline void
+xmit_pull_ind_d(struct IsdnCardState *cs, struct sk_buff *skb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	if (cs->tx_skb) {
+		WARN_ON(1);
+	} else {
+		if (cs->debug & DEB_DLOG_HEX)
+			LogFrame(cs, skb->data, skb->len);
+		if (cs->debug & DEB_DLOG_VERBOSE)
+			dlogframe(cs, skb, 0);
+#ifdef L2FRAME_DEBUG
+		if (cs->debug & L1_DEB_LAPD)
+			Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+		cs->tx_skb = skb;
+		cs->tx_cnt = 0;
+		cs->DC_Send_Data(cs);
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
+}
+
+/* If busy, the PH_PULL | CONFIRM scheduling is handled under
+ * the card lock by xmit_ready_b() above, so no race */
+static inline void
+xmit_pull_req_b(struct PStack *st)
+{
+	struct BCState *bcs = st->l1.bcs;
+	struct IsdnCardState *cs = bcs->cs;
+	unsigned long flags;
+	int busy = 0;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	if (bcs->tx_skb) {
+		set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+		busy = 1;
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
+	if (!busy)
+		L1L2(st, PH_PULL | CONFIRM, NULL);
+}
+
+/* If busy, the PH_PULL | CONFIRM scheduling is handled under
+ * the card lock by xmit_ready_d() above, so no race */
+static inline void
+xmit_pull_req_d(struct PStack *st)
+{
+	struct IsdnCardState *cs = st->l1.hardware;
+	unsigned long flags;
+	int busy = 0;
+
+#ifdef L2FRAME_DEBUG
+	if (cs->debug & L1_DEB_LAPD)
+		debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+	spin_lock_irqsave(&cs->lock, flags);
+	if (cs->tx_skb) {
+		set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+		busy = 1;
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
+	if (!busy)
+		L1L2(st, PH_PULL | CONFIRM, NULL);
+}
+
+/* called with the card lock held */
+static inline void
+xmit_restart_b(struct BCState *bcs)
+{
+#ifdef ERROR_STATISTIC
+	bcs->err_tx++;
+#endif
+	if (!bcs->tx_skb) {
+		WARN_ON(1);
+		return;
+	}
+	skb_push(bcs->tx_skb, bcs->count);
+	bcs->tx_cnt += bcs->count;
+	bcs->count = 0;
+}
+
+/* called with the card lock held */
+static inline void
+xmit_restart_d(struct IsdnCardState *cs)
+{
+#ifdef ERROR_STATISTIC
+	cs->err_tx++;
+#endif
+	if (!cs->tx_skb) {
+		WARN_ON(1);
+		return;
+	}
+	skb_push(cs->tx_skb, cs->tx_cnt);
+	cs->tx_cnt = 0;
+}
+
+/* Useful for HSCX/ISAC work-alike's */
+/* ---------------------------------------------------------------------- */
+
+/* XPR - transmit pool ready */
+/* called with the card lock held */
+static inline void
+xmit_xpr_b(struct BCState *bcs)
+{
+	/* current frame? */
+	if (bcs->tx_skb) {
+		/* last frame not done yet? */
+		if (bcs->tx_skb->len) {
+			bcs->cs->BC_Send_Data(bcs);
+			return;
+		}
+		xmit_complete_b(bcs);
+		bcs->count = 0;
+	}
+	xmit_ready_b(bcs);
+}
+
+/* XPR - transmit pool ready */
+/* called with the card lock held */
+static inline void
+xmit_xpr_d(struct IsdnCardState *cs)
+{
+	if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+		del_timer(&cs->dbusytimer);
+	if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+		sched_d_event(cs, D_CLEARBUSY);
+	/* current frame? */
+	if (cs->tx_skb) {
+		/* last frame not done yet? */
+		if (cs->tx_skb->len) {
+			cs->DC_Send_Data(cs);
+			return;
+		}
+		xmit_complete_d(cs);
+		cs->tx_cnt = 0;
+	}
+	xmit_ready_d(cs);
+}
+
+/* XDU - transmit data underrun */
+/* called with the card lock held */
+static inline void
+xmit_xdu_b(struct BCState *bcs, void (*reset_xmit)(struct BCState *bcs))
+{
+	struct IsdnCardState *cs = bcs->cs;
+
+	if (cs->debug & L1_DEB_WARN)
+		debugl1(cs, "HSCX %c EXIR XDU", 'A' + bcs->channel);
+
+	if (bcs->mode == L1_MODE_TRANS) {
+		cs->BC_Send_Data(bcs);
+	} else {
+		xmit_restart_b(bcs);
+		reset_xmit(bcs);
+	}
+}
+
+/* XDU - transmit data underrun */
+/* called with the card lock held */
+static inline void
+xmit_xdu_d(struct IsdnCardState *cs, void (*reset_xmit)(struct IsdnCardState *cs))
+{
+	printk(KERN_WARNING "HiSax: D XDU\n");
+	if (cs->debug & L1_DEB_WARN)
+		debugl1(cs, "D XDU");
+
+	if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+		del_timer(&cs->dbusytimer);
+	if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+		sched_d_event(cs, D_CLEARBUSY);
+
+	xmit_restart_d(cs);
+	if (reset_xmit)
+		reset_xmit(cs);
+}
+
+static inline unsigned char *
+xmit_fill_fifo_b(struct BCState *bcs, int fifo_size, int *count, int *more)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	unsigned char *p;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, __FUNCTION__);
+
+	if (!bcs->tx_skb || bcs->tx_skb->len <= 0) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	*more = (bcs->mode == L1_MODE_TRANS);
+	if (bcs->tx_skb->len > fifo_size) {
+		*more = 1;
+		*count = fifo_size;
+	} else {
+		*count = bcs->tx_skb->len;
+	}
+	p = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, *count);
+	bcs->tx_cnt -= *count;
+	bcs->count += *count;
+
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "%s %c cnt %d", __FUNCTION__,
+			     bcs->hw.hscx.hscx ? 'B' : 'A', *count);
+		QuickHex(t, p, *count);
+		debugl1(cs, bcs->blog);
+	}
+	return p;
+}
+
+static inline unsigned char *
+xmit_fill_fifo_d(struct IsdnCardState *cs, int fifo_size, int *count, int *more)
+{
+	unsigned char *p;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, __FUNCTION__);
+
+	if (!cs->tx_skb || cs->tx_skb->len <= 0) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	*more = 0;
+	if (cs->tx_skb->len > fifo_size) {
+		*more = 1;
+		*count = fifo_size;
+	} else {
+		*count = cs->tx_skb->len;
+	}
+
+	p = cs->tx_skb->data;
+	skb_pull(cs->tx_skb, *count);
+	cs->tx_cnt += *count;
+
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "%s cnt %d", __FUNCTION__, *count);
+		QuickHex(t, p, *count);
+		debugl1(cs, cs->dlog);
+	}
+	return p;
+}
diff -Nru a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
--- a/drivers/isdn/hisax/isdnl2.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/isdnl2.c	Wed Nov 27 14:36:28 2002
@@ -403,7 +403,7 @@
 setva(struct PStack *st, unsigned int nr)
 {
 	struct Layer2 *l2 = &st->l2;
-	int len;
+	struct sk_buff *skb;
 
 	while (l2->va != nr) {
 		(l2->va)++;
@@ -411,14 +411,11 @@
 			l2->va %= 128;
 		else
 			l2->va %= 8;
-		len = l2->windowar[l2->sow]->len;
-		if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
-			len = -1;
-		dev_kfree_skb(l2->windowar[l2->sow]);
+		skb = l2->windowar[l2->sow];
 		l2->windowar[l2->sow] = NULL;
 		l2->sow = (l2->sow + 1) % l2->window;
-		if (st->lli.l2writewakeup && (len >=0))
-			st->lli.l2writewakeup(st, len);
+		
+		L2L3(st, DL_DATA | CONFIRM, skb);
 	}
 }
 
@@ -1685,6 +1682,9 @@
 			}
 			if (ret)
 				FreeSkb(skb);
+			break;
+		case (PH_DATA | CONFIRM):
+			dev_kfree_skb(skb);
 			break;
 		case (PH_PULL | CONFIRM):
 			FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
--- a/drivers/isdn/hisax/isurf.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/hisax/isurf.c	Wed Nov 27 14:36:30 2002
@@ -89,11 +89,7 @@
 	u_char val;
 	int cnt = 5;
 
-	if (!cs) {
-		printk(KERN_WARNING "ISurf: Spurious interrupt!\n");
-		return;
-	}
-
+	spin_lock(&cs->lock);
 	val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
       Start_ISAR:
 	if (val & ISAR_IRQSTA)
@@ -121,6 +117,7 @@
 	writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb();
 	writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb();
 	writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -155,14 +152,9 @@
 			release_io_isurf(cs);
 			return(0);
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
 			writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb();
 			initisac(cs);
 			initisar(cs);
-			/* Reenable ISAC IRQ */
-			cs->writeisac(cs, ISAC_MASK, 0);
-			/* RESET Receiver and Transmitter */
-			cs->writeisac(cs, ISAC_CMDR, 0x41);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -180,8 +172,6 @@
 			reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET |
 				ISURF_ARCOFI_RESET);
 			initisac(cs);
-			cs->writeisac(cs, ISAC_MASK, 0);
-			cs->writeisac(cs, ISAC_CMDR, 0x41);
 		}
 		return(ret);
 	}
diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
--- a/drivers/isdn/hisax/ix1_micro.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hisax/ix1_micro.c	Wed Nov 27 14:36:32 2002
@@ -141,10 +141,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
 
-	if (!cs) {
-		printk(KERN_WARNING "IX1: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
 	if (val)
@@ -171,6 +168,7 @@
 	writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0);
 	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0);
 	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0);
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -205,7 +203,7 @@
 			release_io_ix1micro(cs);
 			return(0);
 		case CARD_INIT:
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
--- a/drivers/isdn/hisax/jade.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/jade.c	Wed Nov 27 14:36:28 2002
@@ -134,49 +134,20 @@
 	cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00);
 }
 
-void
-jade_sched_event(struct BCState *bcs, int event)
-{
-    bcs->event |= 1 << event;
-    schedule_work(&bcs->work);
-}
-
 static void
 jade_l2l1(struct PStack *st, int pr, void *arg)
 {
     struct sk_buff *skb = arg;
-    unsigned long flags;
 
     switch (pr) {
 	case (PH_DATA | REQUEST):
-		spin_lock_irqsave(&jade_lock, flags);
-		if (st->l1.bcs->tx_skb) {
-			skb_queue_tail(&st->l1.bcs->squeue, skb);
-			spin_unlock_irqrestore(&jade_lock, flags);
-		} else {
-			st->l1.bcs->tx_skb = skb;
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->hw.hscx.count = 0;
-			spin_unlock_irqrestore(&jade_lock, flags);
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-		}
+		xmit_data_req_b(st->l1.bcs, skb);
 		break;
 	case (PH_PULL | INDICATION):
-		if (st->l1.bcs->tx_skb) {
-			printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n");
-			break;
-		}
-		test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-		st->l1.bcs->tx_skb = skb;
-		st->l1.bcs->hw.hscx.count = 0;
-		st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+		xmit_pull_ind_b(st->l1.bcs, skb);
 		break;
 	case (PH_PULL | REQUEST):
-		if (!st->l1.bcs->tx_skb) {
-		    test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-		    L1L2(st, PH_PULL | CONFIRM, NULL);
-		} else
-		    test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+		xmit_pull_req_b(st);
 		break;
 	case (PH_ACTIVATE | REQUEST):
 		test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
@@ -263,40 +234,32 @@
 }
 
 void __init
-clear_pending_jade_ints(struct IsdnCardState *cs)
+initjade(struct IsdnCardState *cs)
 {
 	int val;
-	char tmp[64];
+
+	cs->bcs[0].BC_SetStack = setstack_jade;
+	cs->bcs[1].BC_SetStack = setstack_jade;
+	cs->bcs[0].BC_Close = close_jadestate;
+	cs->bcs[1].BC_Close = close_jadestate;
+	cs->bcs[0].hw.hscx.hscx = 0;
+	cs->bcs[1].hw.hscx.hscx = 1;
 
 	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00);
 	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
 
 	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR);
-	sprintf(tmp, "jade B ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "jade B ISTA %x", val);
 	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR);
-	sprintf(tmp, "jade A ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "jade A ISTA %x", val);
 	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR);
-	sprintf(tmp, "jade B STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "jade B STAR %x", val);
 	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR);
-	sprintf(tmp, "jade A STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "jade A STAR %x", val);
+
 	/* Unmask ints */
 	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8);
 	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
-}
-
-void __init
-initjade(struct IsdnCardState *cs)
-{
-	cs->bcs[0].BC_SetStack = setstack_jade;
-	cs->bcs[1].BC_SetStack = setstack_jade;
-	cs->bcs[0].BC_Close = close_jadestate;
-	cs->bcs[1].BC_Close = close_jadestate;
-	cs->bcs[0].hw.hscx.hscx = 0;
-	cs->bcs[1].hw.hscx.hscx = 1;
 
 	/* Stop DSP audio tx/rx */
 	jade_write_indirect(cs, 0x11, 0x0f);
diff -Nru a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h
--- a/drivers/isdn/hisax/jade.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/jade.h	Wed Nov 27 14:36:28 2002
@@ -130,7 +130,6 @@
 extern int JadeVersion(struct IsdnCardState *cs, char *s);
 extern void jade_sched_event(struct BCState *bcs, int event);
 extern void modejade(struct BCState *bcs, int mode, int bc);
-extern void clear_pending_jade_ints(struct IsdnCardState *cs);
 extern void initjade(struct IsdnCardState *cs);
 
 #endif	/* __JADE_H__ */
diff -Nru a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
--- a/drivers/isdn/hisax/jade_irq.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/jade_irq.c	Wed Nov 27 14:36:27 2002
@@ -49,7 +49,6 @@
 {
 	u_char *ptr;
 	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "jade_empty_fifo");
@@ -63,10 +62,8 @@
 	}
 	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
 	bcs->hw.hscx.rcvidx += count;
-	spin_lock_irqsave(&jade_irq_lock, flags);
 	READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
 	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
-	spin_unlock_irqrestore(&jade_irq_lock, flags);
 	if (cs->debug & L1_DEB_HSCX_FIFO) {
 		char *t = bcs->blog;
 
@@ -83,41 +80,17 @@
 	struct IsdnCardState *cs = bcs->cs;
 	int more, count;
 	int fifo_size = 32;
-	u_char *ptr;
-	unsigned long flags;
+	int hscx = bcs->hw.hscx.hscx;
+	unsigned char *p;
 
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "jade_fill_fifo");
-
-	if (!bcs->tx_skb)
-		return;
-	if (bcs->tx_skb->len <= 0)
+	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
+	if (!p)
 		return;
 
-	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
-	if (bcs->tx_skb->len > fifo_size) {
-		more = !0;
-		count = fifo_size;
-	} else
-		count = bcs->tx_skb->len;
-
-	waitforXFW(cs, bcs->hw.hscx.hscx);
-	spin_lock_irqsave(&jade_irq_lock, flags);
-	ptr = bcs->tx_skb->data;
-	skb_pull(bcs->tx_skb, count);
-	bcs->tx_cnt -= count;
-	bcs->hw.hscx.count += count;
-	WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
-	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
-	spin_unlock_irqrestore(&jade_irq_lock, flags);
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
-
-		t += sprintf(t, "jade_fill_fifo %c cnt %d",
-			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
+	waitforXFW(cs, hscx);
+	WRITEJADEFIFO(cs, hscx, p, count);
+	WriteJADECMDR(cs, hscx, jade_HDLC_XCMD,
+		      more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
 }
 
 
@@ -164,7 +137,7 @@
 			}
 		}
 		bcs->hw.hscx.rcvidx = 0;
-		jade_sched_event(bcs, B_RCVBUFREADY);
+		sched_b_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & 0x40) {	/* RPF */
 		jade_empty_fifo(bcs, fifo_size);
@@ -177,34 +150,20 @@
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
 			bcs->hw.hscx.rcvidx = 0;
-			jade_sched_event(bcs, B_RCVBUFREADY);
+			sched_b_event(bcs, B_RCVBUFREADY);
 		}
 	}
 	if (val & 0x10) {	/* XPR */
-		if (bcs->tx_skb) {
-			if (bcs->tx_skb->len) {
-				jade_fill_fifo(bcs);
-				return;
-			} else {
-				if (bcs->st->lli.l1writewakeup &&
-					(PACKET_NOACK != bcs->tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				dev_kfree_skb_irq(bcs->tx_skb);
-				bcs->hw.hscx.count = 0;
-				bcs->tx_skb = NULL;
-			}
-		}
-		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-			bcs->hw.hscx.count = 0;
-			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
-			jade_fill_fifo(bcs);
-		} else {
-			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-			jade_sched_event(bcs, B_XMTBUFREADY);
-		}
+		xmit_xpr_b(bcs);
 	}
 }
 
+static void
+reset_xmit(struct BCState *bcs)
+{
+	WriteJADECMDR(bcs->cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
+}
+
 static inline void
 jade_int_main(struct IsdnCardState *cs, u_char val, int jade)
 {
@@ -216,23 +175,7 @@
 		val &= ~jadeISR_RFO;
 	}
 	if (val & jadeISR_XDU) {
-		/* relevant in HDLC mode only */
-		/* don't reset XPR here */
-		if (bcs->mode == 1)
-			jade_fill_fifo(bcs);
-		else {
-			/* Here we lost an TX interrupt, so
-			   * restart transmitting the whole frame.
-			 */
-			if (bcs->tx_skb) {
-			   	skb_push(bcs->tx_skb, bcs->hw.hscx.count);
-				bcs->tx_cnt += bcs->hw.hscx.count;
-				bcs->hw.hscx.count = 0;
-			}
-			WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
-			if (cs->debug & L1_DEB_WARN)
-				debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val);
-		}
+		xmit_xdu_b(bcs, reset_xmit);
 	}
 	if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
 		if (cs->debug & L1_DEB_HSCX)
diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
--- a/drivers/isdn/hisax/mic.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/mic.c	Wed Nov 27 14:36:31 2002
@@ -137,10 +137,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
 
-	if (!cs) {
-		printk(KERN_WARNING "mic: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
 	if (val)
@@ -167,6 +164,7 @@
 	writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0);
 	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0);
 	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -188,8 +186,7 @@
 			release_io_mic(cs);
 			return(0);
 		case CARD_INIT:
-			inithscx(cs); /* /RTSA := ISAC RST */
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
--- a/drivers/isdn/hisax/netjet.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/netjet.c	Wed Nov 27 14:36:28 2002
@@ -432,8 +432,7 @@
 		memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count);
 		skb_queue_tail(&bcs->rqueue, skb);
 	}
-	bcs->event |= 1 << B_RCVBUFREADY;
-	schedule_work(&bcs->work);
+	sched_b_event(bcs, B_RCVBUFREADY);
 	
 	if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME)
 		printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec");
@@ -760,11 +759,7 @@
 			if (!bcs->tx_skb) {
 				debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
 			} else {
-				if (bcs->st->lli.l1writewakeup &&
-					(PACKET_NOACK != bcs->tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
-				dev_kfree_skb_any(bcs->tx_skb);
-				bcs->tx_skb = NULL;
+				xmit_complete_b(bcs);
 			}
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 			bcs->hw.tiger.free = cnt - s_cnt;
@@ -788,8 +783,7 @@
 						debugl1(bcs->cs, "tiger write_raw: fill rest %d",
 							cnt - s_cnt);
 				}
-				bcs->event |= 1 << B_XMTBUFREADY;
-				schedule_work(&bcs->work);
+				sched_b_event(bcs, B_XMTBUFREADY);
 			}
 		}
 	} else if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
@@ -838,36 +832,16 @@
 tiger_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	unsigned long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			spin_lock_irqsave(&netjet_lock, flags);
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				spin_unlock_irqrestore(&netjet_lock, flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-				spin_unlock_irqrestore(&netjet_lock, flags);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n");
-				break;
-			}
-			spin_lock_irqsave(&netjet_lock, flags);
-			st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			spin_unlock_irqrestore(&netjet_lock, flags);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
--- a/drivers/isdn/hisax/niccy.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/isdn/hisax/niccy.c	Wed Nov 27 14:36:29 2002
@@ -147,11 +147,8 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
-
-	if (!cs) {
-		printk(KERN_WARNING "Niccy: Spurious interrupt!\n");
-		return;
-	}
+	
+	spin_lock(&cs->lock);
 	if (cs->subtyp == NICCY_PCI) {
 		int ival;
 		ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
@@ -185,6 +182,7 @@
 	writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0);
 	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0);
 	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0);
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -214,7 +212,7 @@
 		val |= PCI_IRQ_ENABLE;
 		outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
 	}
-	inithscxisac(cs, 3);
+	inithscxisac(cs);
 }
 
 static int
diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
--- a/drivers/isdn/hisax/nj_s.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/nj_s.c	Wed Nov 27 14:36:28 2002
@@ -16,7 +16,6 @@
 #include "netjet.h"
 
 const char *NETjet_S_revision = "$Revision: 2.7.6.6 $";
-static spinlock_t nj_s_lock = SPIN_LOCK_UNLOCKED;
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
 {
@@ -32,12 +31,8 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val, sval;
-	unsigned long flags;
 
-	if (!cs) {
-		printk(KERN_WARNING "NETjet-S: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) &
 		NETJET_ISACIRQ)) {
 		val = NETjet_ReadIC(cs, ISAC_ISTA);
@@ -49,7 +44,6 @@
 			NETjet_WriteIC(cs, ISAC_MASK, 0x0);
 		}
 	}
-	spin_lock_irqsave(&nj_s_lock, flags);
 	/* start new code 13/07/00 GE */
 	/* set bits in sval to indicate which page is free */
 	if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
@@ -66,12 +60,7 @@
 		sval = sval | 0x01;	
 	if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */
 	{
-		if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-			spin_unlock_irqrestore(&nj_s_lock, flags);
-			return;
-		}
 		cs->hw.njet.irqstat0 = sval;
-		spin_unlock_irqrestore(&nj_s_lock, flags);
 		if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != 
 			(cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
 			/* we have a read dma int */
@@ -81,10 +70,7 @@
 			/* we have a write dma int */
 			write_tiger(cs);
 		/* end new code 13/07/00 GE */
-		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	} else
-		spin_unlock_irqrestore(&nj_s_lock, flags);
-
+	}
 /*	if (!testcnt--) {
 		cs->hw.njet.dmactrl = 0;
 		byteout(cs->hw.njet.base + NETJET_DMACTRL,
@@ -92,15 +78,12 @@
 		byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
 	}
 */
+	spin_unlock(&cs->lock);
 }
 
 static void
 reset_netjet_s(struct IsdnCardState *cs)
 {
-	long flags;
-
-	save_flags(flags);
-	sti();
 	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
 	set_current_state(TASK_UNINTERRUPTIBLE);
@@ -110,7 +93,6 @@
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	restore_flags(flags);
 	cs->hw.njet.auxd = 0;
 	cs->hw.njet.dmactrl = 0;
 	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
@@ -130,10 +112,7 @@
 			return(0);
 		case CARD_INIT:
 			inittiger(cs);
-			clear_pending_isac_ints(cs);
 			initisac(cs);
-			/* Reenable all IRQ */
-			cs->writeisac(cs, ISAC_MASK, 0);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -149,7 +128,6 @@
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	unsigned long flags;
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
@@ -158,7 +136,6 @@
 	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_NETJET_S)
 		return(0);
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
 #if CONFIG_PCI
 
@@ -200,9 +177,6 @@
 		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
 		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
 
-		save_flags(flags);
-		sti();
-
 		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
 
@@ -214,8 +188,6 @@
 
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		restore_flags(flags);
 
 		cs->hw.njet.auxd = 0xC0;
 		cs->hw.njet.dmactrl = 0;
diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
--- a/drivers/isdn/hisax/nj_u.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/nj_u.c	Wed Nov 27 14:36:28 2002
@@ -16,7 +16,6 @@
 #include "netjet.h"
 
 const char *NETjet_U_revision = "$Revision: 2.8.6.6 $";
-static spinlock_t nj_u_lock = SPIN_LOCK_UNLOCKED;
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
 {
@@ -32,12 +31,8 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val, sval;
-	unsigned long flags;
 
-	if (!cs) {
-		printk(KERN_WARNING "NETspider-U: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) &
 		NETJET_ISACIRQ)) {
 		val = NETjet_ReadIC(cs, ICC_ISTA);
@@ -49,7 +44,6 @@
 			NETjet_WriteIC(cs, ICC_MASK, 0x0);
 		}
 	}
-	spin_lock_irqsave(&nj_u_lock, flags);
 	/* start new code 13/07/00 GE */
 	/* set bits in sval to indicate which page is free */
 	if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
@@ -66,12 +60,7 @@
 		sval = sval | 0x01;	
 	if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */
 	{
-		if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-			spin_unlock_irqrestore(&nj_u_lock, flags);
-			return;
-		}
 		cs->hw.njet.irqstat0 = sval;
-		spin_unlock_irqrestore(&nj_u_lock, flags);
 		if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != 
 			(cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
 			/* we have a read dma int */
@@ -81,10 +70,7 @@
 			/* we have a write dma int */
 			write_tiger(cs);
 		/* end new code 13/07/00 GE */
-		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	} else
-		spin_unlock_irqrestore(&nj_u_lock, flags);
-
+	}
 /*	if (!testcnt--) {
 		cs->hw.njet.dmactrl = 0;
 		byteout(cs->hw.njet.base + NETJET_DMACTRL,
@@ -92,15 +78,12 @@
 		byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
 	}
 */
+	spin_unlock(&cs->lock);
 }
 
 static void
 reset_netjet_u(struct IsdnCardState *cs)
 {
-	long flags;
-
-	save_flags(flags);
-	sti();
 	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
 	set_current_state(TASK_UNINTERRUPTIBLE);
@@ -110,7 +93,7 @@
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	restore_flags(flags);
+
 	cs->hw.njet.auxd = 0xC0;
 	cs->hw.njet.dmactrl = 0;
 	byteout(cs->hw.njet.auxa, 0);
@@ -131,7 +114,6 @@
 			return(0);
 		case CARD_INIT:
 			inittiger(cs);
-			clear_pending_icc_ints(cs);
 			initicc(cs);
 			/* Reenable all IRQ */
 			cs->writeisac(cs, ICC_MASK, 0);
@@ -150,7 +132,6 @@
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	long flags;
 #if CONFIG_PCI
 #endif
 #ifdef __BIG_ENDIAN
@@ -160,7 +141,6 @@
 	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_NETJET_U)
 		return(0);
-	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
 #if CONFIG_PCI
 
@@ -194,8 +174,6 @@
 		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
 		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
 
-		save_flags(flags);
-		sti();
 		cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
 
@@ -207,8 +185,6 @@
 
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		restore_flags(flags);
 
 		cs->hw.njet.auxd = 0xC0;
 		cs->hw.njet.dmactrl = 0;
diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
--- a/drivers/isdn/hisax/s0box.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/s0box.c	Wed Nov 27 14:36:27 2002
@@ -156,10 +156,7 @@
 	u_char val;
 	int count = 0;
 
-	if (!cs) {
-		printk(KERN_WARNING "Teles: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
       Start_HSCX:
 	if (val)
@@ -189,6 +186,7 @@
 	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
 	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
 	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -207,7 +205,7 @@
 			release_io_s0box(cs);
 			break;
 		case CARD_INIT:
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			break;
 		case CARD_TEST:
 			break;
diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
--- a/drivers/isdn/hisax/saphir.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/hisax/saphir.c	Wed Nov 27 14:36:27 2002
@@ -133,10 +133,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
 
-	if (!cs) {
-		printk(KERN_WARNING "saphir: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
 	if (val)
@@ -168,6 +165,7 @@
 	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
 	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
 	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
+	spin_unlock(&cs->lock);
 }
 
 static void
@@ -235,7 +233,7 @@
 			release_io_saphir(cs);
 			return(0);
 		case CARD_INIT:
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
--- a/drivers/isdn/hisax/sedlbauer.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hisax/sedlbauer.c	Wed Nov 27 14:36:32 2002
@@ -369,11 +369,7 @@
 	u_char val;
 	int cnt = 5;
 
-	if (!cs) {
-		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
-		return;
-	}
-
+	spin_lock(&cs->lock);
 	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
       Start_ISAR:
 	if (val & ISAR_IRQSTA)
@@ -402,6 +398,7 @@
 	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
 	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
 	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -479,17 +476,12 @@
 			return(0);
 		case CARD_INIT:
 			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-				clear_pending_isac_ints(cs);
 				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
 					ISAR_IRQBIT, 0);
 				initisac(cs);
 				initisar(cs);
-				/* Reenable all IRQ */
-				cs->writeisac(cs, ISAC_MASK, 0);
-				/* RESET Receiver and Transmitter */
-				cs->writeisac(cs, ISAC_CMDR, 0x41);
 			} else {
-				inithscxisac(cs, 3);
+				inithscxisac(cs);
 			}
 			return(0);
 		case CARD_TEST:
diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
--- a/drivers/isdn/hisax/sportster.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/hisax/sportster.c	Wed Nov 27 14:36:28 2002
@@ -104,10 +104,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
 
-	if (!cs) {
-		printk(KERN_WARNING "Sportster: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = READHSCX(cs, 1, HSCX_ISTA);
       Start_HSCX:
 	if (val)
@@ -130,6 +127,7 @@
 	}
 	/* get a new irq impulse if there any pending */
 	bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1);
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -168,10 +166,9 @@
 			release_io_sportster(cs);
 			return(0);
 		case CARD_INIT:
-			inithscxisac(cs, 1);
+			inithscxisac(cs);
 			cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
 			byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
-			inithscxisac(cs, 2);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
--- a/drivers/isdn/hisax/st5481_b.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/isdn/hisax/st5481_b.c	Wed Nov 27 14:36:29 2002
@@ -82,12 +82,7 @@
 			if (!skb->len) {
 				// Frame sent
 				b_out->tx_skb = NULL;
-				B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
-				dev_kfree_skb_any(skb);
-				
-/* 				if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */
-/* 					st5481B_sched_event(bcs, B_XMTBUFREADY); */
-/* 				} */
+				B_L1L2(bcs, PH_DATA | CONFIRM, skb);
 			}
 		} else {
 			if (bcs->mode == L1_MODE_TRANS) {
diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
--- a/drivers/isdn/hisax/teleint.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hisax/teleint.c	Wed Nov 27 14:36:32 2002
@@ -172,10 +172,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
 
-	if (!cs) {
-		printk(KERN_WARNING "TeleInt: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
       Start_ISAC:
 	if (val)
@@ -188,6 +185,7 @@
 	}
 	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
 	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 static void
@@ -242,11 +240,7 @@
 			return(0);
 		case CARD_INIT:
 			inithfc(cs);
-			clear_pending_isac_ints(cs);
 			initisac(cs);
-			/* Reenable all IRQ */
-			cs->writeisac(cs, ISAC_MASK, 0);
-			cs->writeisac(cs, ISAC_CMDR, 0x41);
 			cs->hw.hfc.timer.expires = jiffies + 1;
 			add_timer(&cs->hw.hfc.timer);
 			return(0);
diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
--- a/drivers/isdn/hisax/teles0.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/isdn/hisax/teles0.c	Wed Nov 27 14:36:30 2002
@@ -150,10 +150,7 @@
 	u_char val;
 	int count = 0;
 
-	if (!cs) {
-		printk(KERN_WARNING "Teles0: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
       Start_HSCX:
 	if (val)
@@ -181,6 +178,7 @@
 	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
 	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
 	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -251,7 +249,7 @@
 			release_io_teles0(cs);
 			return(0);
 		case CARD_INIT:
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
--- a/drivers/isdn/hisax/teles3.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/hisax/teles3.c	Wed Nov 27 14:36:32 2002
@@ -108,10 +108,7 @@
 	u_char val;
 	int count = 0;
 
-	if (!cs) {
-		printk(KERN_WARNING "Teles: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
       Start_HSCX:
 	if (val)
@@ -141,6 +138,7 @@
 	writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0);
 	writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
 	writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 inline static void
@@ -238,7 +236,7 @@
 			release_io_teles3(cs);
 			return(0);
 		case CARD_INIT:
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
--- a/drivers/isdn/hisax/telespci.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/telespci.c	Wed Nov 27 14:36:31 2002
@@ -233,10 +233,7 @@
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
 
-	if (!cs) {
-		printk(KERN_WARNING "TelesPCI: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
 	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
 	if (val)
 		hscx_int_main(cs, val);
@@ -252,6 +249,7 @@
 	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
 	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
 	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
+	spin_unlock(&cs->lock);
 }
 
 void
@@ -270,7 +268,7 @@
 			release_io_telespci(cs);
 			return(0);
 		case CARD_INIT:
-			inithscxisac(cs, 3);
+			inithscxisac(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
--- a/drivers/isdn/hisax/w6692.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/hisax/w6692.c	Wed Nov 27 14:36:31 2002
@@ -43,8 +43,6 @@
 
 const char *w6692_revision = "$Revision: 1.12.6.6 $";
 
-static spinlock_t w6692_lock = SPIN_LOCK_UNLOCKED;
-
 #define DBUSY_TIMER_VALUE 80
 
 static char *W6692Ver[] __initdata =
@@ -134,25 +132,10 @@
  */
 }
 
-void
-W6692_sched_event(struct IsdnCardState *cs, int event)
-{
-	test_and_set_bit(event, &cs->event);
-	schedule_work(&cs->work);
-}
-
-static void
-W6692B_sched_event(struct BCState *bcs, int event)
-{
-	bcs->event |= 1 << event;
-	schedule_work(&bcs->work);
-}
-
 static void
 W6692_empty_fifo(struct IsdnCardState *cs, int count)
 {
 	u_char *ptr;
-	unsigned long flags;
 
 	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
 		debugl1(cs, "W6692_empty_fifo");
@@ -167,10 +150,8 @@
 	}
 	ptr = cs->rcvbuf + cs->rcvidx;
 	cs->rcvidx += count;
-	spin_lock_irqsave(&w6692_lock, flags);
 	cs->readW6692fifo(cs, ptr, count);
 	cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
-	spin_unlock_irqrestore(&w6692_lock, flags);
 	if (cs->debug & L1_DEB_ISAC_FIFO) {
 		char *t = cs->dlog;
 
@@ -184,31 +165,14 @@
 W6692_fill_fifo(struct IsdnCardState *cs)
 {
 	int count, more;
-	u_char *ptr;
-	unsigned long flags;
+	unsigned char *p;
 
-	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
-		debugl1(cs, "W6692_fill_fifo");
-
-	if (!cs->tx_skb)
+	p = xmit_fill_fifo_d(cs, W_D_FIFO_THRESH, &count, &more);
+	if (!p)
 		return;
 
-	count = cs->tx_skb->len;
-	if (count <= 0)
-		return;
-
-	more = 0;
-	if (count > W_D_FIFO_THRESH) {
-		more = !0;
-		count = W_D_FIFO_THRESH;
-	}
-	spin_lock_irqsave(&w6692_lock, flags);
-	ptr = cs->tx_skb->data;
-	skb_pull(cs->tx_skb, count);
-	cs->tx_cnt += count;
-	cs->writeW6692fifo(cs, ptr, count);
+	cs->writeW6692fifo(cs, p, count);
 	cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME));
-	spin_unlock_irqrestore(&w6692_lock , flags);
 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
 		debugl1(cs, "W6692_fill_fifo dbusytimer running");
 		del_timer(&cs->dbusytimer);
@@ -216,13 +180,6 @@
 	init_timer(&cs->dbusytimer);
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
 	add_timer(&cs->dbusytimer);
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char *t = cs->dlog;
-
-		t += sprintf(t, "W6692_fill_fifo cnt %d", count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, cs->dlog);
-	}
 }
 
 static void
@@ -230,7 +187,6 @@
 {
 	u_char *ptr;
 	struct IsdnCardState *cs = bcs->cs;
-	unsigned long flags;
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "W6692B_empty_fifo");
@@ -244,10 +200,8 @@
 	}
 	ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx;
 	bcs->hw.w6692.rcvidx += count;
-	spin_lock_irqsave(&w6692_lock, flags);
 	READW6692BFIFO(cs, bcs->channel, ptr, count);
 	cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
-	spin_unlock_irqrestore(&w6692_lock , flags);
 	if (cs->debug & L1_DEB_HSCX_FIFO) {
 		char *t = bcs->blog;
 
@@ -263,41 +217,21 @@
 {
 	struct IsdnCardState *cs = bcs->cs;
 	int more, count;
-	u_char *ptr;
-	unsigned long flags;
-
-
-	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
-		debugl1(cs, "W6692B_fill_fifo");
+	unsigned char *p;
 
-	if (!bcs->tx_skb)
-		return;
-	if (bcs->tx_skb->len <= 0)
+	p = xmit_fill_fifo_b(bcs, W_B_FIFO_THRESH, &count, &more);
+	if (!p)
 		return;
 
-	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
-	if (bcs->tx_skb->len > W_B_FIFO_THRESH) {
-		more = !0;
-		count = W_B_FIFO_THRESH;
-	} else
-		count = bcs->tx_skb->len;
-
-	spin_lock_irqsave(&w6692_lock, flags);
-	ptr = bcs->tx_skb->data;
-	skb_pull(bcs->tx_skb, count);
-	bcs->tx_cnt -= count;
-	bcs->hw.w6692.count += count;
-	WRITEW6692BFIFO(cs, bcs->channel, ptr, count);
+	WRITEW6692BFIFO(cs, bcs->channel, p, count);
 	cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME));
-	spin_unlock_irqrestore(&w6692_lock , flags);
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char *t = bcs->blog;
+}
 
-		t += sprintf(t, "W6692B_fill_fifo %c cnt %d",
-			     bcs->channel + '1', count);
-		QuickHex(t, ptr, count);
-		debugl1(cs, bcs->blog);
-	}
+static void
+reset_xmit(struct BCState *bcs)
+{
+	bcs->cs->BC_Write_Reg(bcs->cs, bcs->channel, W_B_CMDR,
+			      W_B_CMDR_XRST | W_B_CMDR_RACT);
 }
 
 static void
@@ -345,7 +279,7 @@
 			}
 		}
 		bcs->hw.w6692.rcvidx = 0;
-		W6692B_sched_event(bcs, B_RCVBUFREADY);
+		sched_b_event(bcs, B_RCVBUFREADY);
 	}
 	if (val & W_B_EXI_RMR) {	/* RMR */
 		W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
@@ -358,48 +292,14 @@
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
 			bcs->hw.w6692.rcvidx = 0;
-			W6692B_sched_event(bcs, B_RCVBUFREADY);
+			sched_b_event(bcs, B_RCVBUFREADY);
 		}
 	}
 	if (val & W_B_EXI_XFR) {	/* XFR */
-		if (bcs->tx_skb) {
-			if (bcs->tx_skb->len) {
-				W6692B_fill_fifo(bcs);
-				return;
-			} else {
-				if (bcs->st->lli.l1writewakeup &&
-				 (PACKET_NOACK != bcs->tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.w6692.count);
-				dev_kfree_skb_irq(bcs->tx_skb);
-				bcs->hw.w6692.count = 0;
-				bcs->tx_skb = NULL;
-			}
-		}
-		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
-			bcs->hw.w6692.count = 0;
-			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
-			W6692B_fill_fifo(bcs);
-		} else {
-			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-			W6692B_sched_event(bcs, B_XMTBUFREADY);
-		}
+		xmit_xpr_b(bcs);
 	}
 	if (val & W_B_EXI_XDUN) {	/* XDUN */
-		if (bcs->mode == 1)
-			W6692B_fill_fifo(bcs);
-		else {
-			/* Here we lost an TX interrupt, so
-			   * restart transmitting the whole frame.
-			 */
-			if (bcs->tx_skb) {
-				skb_push(bcs->tx_skb, bcs->hw.w6692.count);
-				bcs->tx_cnt += bcs->hw.w6692.count;
-				bcs->hw.w6692.count = 0;
-			}
-			cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
-			if (cs->debug & L1_DEB_WARN)
-				debugl1(cs, "W6692 B EXIR %x Lost TX", val);
-		}
+		xmit_xdu_b(bcs, reset_xmit);
 	}
 }
 
@@ -410,13 +310,10 @@
 	u_char val, exval, v1;
 	struct sk_buff *skb;
 	unsigned int count;
-	unsigned long flags;
 	int icnt = 5;
 
-	if (!cs) {
-		printk(KERN_WARNING "W6692: Spurious interrupt!\n");
-		return;
-	}
+	spin_lock(&cs->lock);
+
 	val = cs->readW6692(cs, W_ISTA);
 
       StartW6692:
@@ -441,7 +338,6 @@
 			if (count == 0)
 				count = W_D_FIFO_THRESH;
 			W6692_empty_fifo(cs, count);
-			spin_lock_irqsave(&w6692_lock, flags);
 			if ((count = cs->rcvidx) > 0) {
 				cs->rcvidx = 0;
 				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
@@ -451,36 +347,16 @@
 					skb_queue_tail(&cs->rq, skb);
 				}
 			}
-			spin_unlock_irqrestore(&w6692_lock , flags);
 		}
 		cs->rcvidx = 0;
-		W6692_sched_event(cs, D_RCVBUFREADY);
+		sched_d_event(cs, D_RCVBUFREADY);
 	}
 	if (val & W_INT_D_RMR) {	/* RMR */
 		W6692_empty_fifo(cs, W_D_FIFO_THRESH);
 	}
 	if (val & W_INT_D_XFR) {	/* XFR */
-		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-			del_timer(&cs->dbusytimer);
-		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			W6692_sched_event(cs, D_CLEARBUSY);
-		if (cs->tx_skb) {
-			if (cs->tx_skb->len) {
-				W6692_fill_fifo(cs);
-				goto afterXFR;
-			} else {
-				dev_kfree_skb_irq(cs->tx_skb);
-				cs->tx_cnt = 0;
-				cs->tx_skb = NULL;
-			}
-		}
-		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
-			cs->tx_cnt = 0;
-			W6692_fill_fifo(cs);
-		} else
-			W6692_sched_event(cs, D_XMTBUFREADY);
+		xmit_xpr_d(cs);
 	}
-      afterXFR:
 	if (val & (W_INT_XINT0 | W_INT_XINT1)) {	/* XINT0/1 - never */
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "W6692 spurious XINT!");
@@ -490,21 +366,7 @@
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "W6692 D_EXIR %02x", exval);
 		if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) {	/* Transmit underrun/collision */
-			debugl1(cs, "W6692 D-chan underrun/collision");
-			printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n");
-			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
-				del_timer(&cs->dbusytimer);
-			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				W6692_sched_event(cs, D_CLEARBUSY);
-			if (cs->tx_skb) {	/* Restart frame */
-				skb_push(cs->tx_skb, cs->tx_cnt);
-				cs->tx_cnt = 0;
-				W6692_fill_fifo(cs);
-			} else {
-				printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n");
-				debugl1(cs, "W6692 XDUN/XCOL no skb");
-				cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);
-			}
+			xmit_xdu_d(cs, NULL);
 		}
 		if (exval & W_D_EXI_RDOV) {	/* RDOV */
 			debugl1(cs, "W6692 D-channel RDOV");
@@ -527,7 +389,7 @@
 				cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK;
 				if (cs->debug & L1_DEB_ISAC)
 					debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state);
-				W6692_sched_event(cs, D_L1STATECHANGE);
+				sched_d_event(cs, D_L1STATECHANGE);
 			}
 			if (v1 & W_CIR_SCC) {
 				v1 = cs->readW6692(cs, W_SQR);
@@ -558,6 +420,7 @@
 		printk(KERN_WARNING "W6692 IRQ LOOP\n");
 		cs->writeW6692(cs, W_IMASK, 0xff);
 	}
+	spin_unlock(&cs->lock);
 }
 
 static void
@@ -569,55 +432,13 @@
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				W6692_fill_fifo(cs);
-			}
+			xmit_data_req_d(cs, skb);
 			break;
-		case (PH_PULL | INDICATION):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if (cs->debug & DEB_DLOG_HEX)
-				LogFrame(cs, skb->data, skb->len);
-			if (cs->debug & DEB_DLOG_VERBOSE)
-				dlogframe(cs, skb, 0);
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			W6692_fill_fifo(cs);
+		case (PH_PULL |INDICATION):
+			xmit_pull_ind_d(cs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_d(st);
 			break;
 		case (HW_RESET | REQUEST):
 			if ((cs->dc.w6692.ph_state == W_L1IND_DRD))
@@ -652,7 +473,7 @@
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-				W6692_sched_event(cs, D_CLEARBUSY);
+				sched_d_event(cs, D_CLEARBUSY);
 			break;
 		default:
 			if (cs->debug & L1_DEB_WARN)
@@ -743,38 +564,16 @@
 W6692_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
-	unsigned long flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
-			spin_lock_irqsave(&w6692_lock, flags);
-			if (st->l1.bcs->tx_skb) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-				spin_unlock_irqrestore(&w6692_lock , flags);
-			} else {
-				st->l1.bcs->tx_skb = skb;
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				st->l1.bcs->hw.w6692.count = 0;
-				spin_unlock_irqrestore(&w6692_lock , flags);
-				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
-			}
+			xmit_data_req_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | INDICATION):
-			if (st->l1.bcs->tx_skb) {
-				printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n");
-				break;
-			}
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->tx_skb = skb;
-			st->l1.bcs->hw.w6692.count = 0;
-			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			xmit_pull_ind_b(st->l1.bcs, skb);
 			break;
 		case (PH_PULL | REQUEST):
-			if (!st->l1.bcs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				L1L2(st, PH_PULL | CONFIRM, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			xmit_pull_req_b(st);
 			break;
 		case (PH_ACTIVATE | REQUEST):
 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
@@ -1072,6 +871,7 @@
 	cs->BC_Read_Reg = &ReadW6692B;
 	cs->BC_Write_Reg = &WriteW6692B;
 	cs->BC_Send_Data = &W6692B_fill_fifo;
+	cs->DC_Send_Data = &W6692_fill_fifo;
 	cs->cardmsg = &w6692_card_msg;
 	cs->irq_func = &W6692_interrupt;
 	cs->irq_flags |= SA_SHIRQ;
diff -Nru a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
--- a/drivers/isdn/i4l/isdn_common.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/i4l/isdn_common.c	Wed Nov 27 14:36:28 2002
@@ -42,7 +42,46 @@
 
 /* ====================================================================== */
 
-static struct isdn_slot slots[ISDN_MAX_CHANNELS]; 
+/* Description of hardware-level-driver */
+struct isdn_driver {
+	int                 di;
+	char                id[20];
+	atomic_t            refcnt;
+	unsigned long       flags;            /* Misc driver Flags           */
+	unsigned long       features;
+	int                 channels;         /* Number of channels          */
+	wait_queue_head_t   st_waitq;         /* Wait-Queue for status-reads */
+	int                 maxbufsize;       /* Maximum Buffersize supported*/
+	int                 stavail;          /* Chars avail on Status-device*/
+	isdn_if            *interface;        /* Interface to driver         */
+	char                msn2eaz[10][ISDN_MSNLEN];  /*  MSN->EAZ          */
+	spinlock_t          lock;
+	struct isdn_slot   *slots; 
+	struct fsm_inst     fi;
+} driver;
+
+static void drv_destroy(struct isdn_driver *drv);
+
+static inline struct isdn_driver *
+get_drv(struct isdn_driver *drv)
+{
+	printk("get_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), 
+	       atomic_read(&drv->refcnt) + 1); 
+	atomic_inc(&drv->refcnt);
+	return drv;
+}
+
+static inline void
+put_drv(struct isdn_driver *drv)
+{
+	printk("put_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt),
+	       atomic_read(&drv->refcnt) - 1); 
+	if (atomic_dec_and_test(&drv->refcnt)) {
+		drv_destroy(drv);
+	}
+}
+
+/* ====================================================================== */
 
 static struct fsm slot_fsm;
 static void slot_debug(struct fsm_inst *fi, char *fmt, ...);
@@ -338,6 +377,7 @@
 	slot->ibytes = 0;
 	slot->obytes = 0;
 	slot->usage = ISDN_USAGE_NONE;
+	put_drv(slot->drv);
 	isdn_info_update();
 	return 0;
 }
@@ -396,7 +436,7 @@
 	char *p = buf;
 
 	va_start(args, fmt);
-	p += sprintf(p, "slot %d(%d:%d): ", slot-slots, slot->di, slot->ch);
+	p += sprintf(p, "slot (%d:%d): ", slot->di, slot->ch);
 	p += vsprintf(p, fmt, args);
 	va_end(args);
 	printk(KERN_DEBUG "%s\n", buf);
@@ -422,23 +462,6 @@
 
 #define DRV_FLAG_REJBUS  1
 
-/* Description of hardware-level-driver */
-struct isdn_driver {
-	int                 di;
-	char                id[20];
-	atomic_t            refcnt;
-	unsigned long       flags;            /* Misc driver Flags           */
-	unsigned long       features;
-	int                 locks;            /* Number of locks             */
-	int                 channels;         /* Number of channels          */
-	wait_queue_head_t   st_waitq;         /* Wait-Queue for status-reads */
-	int                 maxbufsize;       /* Maximum Buffersize supported*/
-	int                 stavail;          /* Chars avail on Status-device*/
-	isdn_if            *interface;        /* Interface to driver         */
-	char                msn2eaz[10][ISDN_MSNLEN];  /*  MSN->EAZ          */
-	struct fsm_inst     fi;
-} driver;
-
 static int __drv_command(struct isdn_driver *drv, isdn_ctrl *cmd);
 
 static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
@@ -469,7 +492,7 @@
 
  out:
 	if (retval > 0)
-		slots->obytes += retval;
+		slot->obytes += retval;
 
 	return retval;
 }
@@ -504,28 +527,10 @@
 static void
 drv_destroy(struct isdn_driver *drv)
 {
+	kfree(drv->slots);
 	kfree(drv);
 }
 
-static inline struct isdn_driver *
-get_drv(struct isdn_driver *drv)
-{
-	printk("get_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), 
-	       atomic_read(&drv->refcnt) + 1); 
-	atomic_inc(&drv->refcnt);
-	return drv;
-}
-
-static inline void
-put_drv(struct isdn_driver *drv)
-{
-	printk("put_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt),
-	       atomic_read(&drv->refcnt) - 1); 
-	if (atomic_dec_and_test(&drv->refcnt)) {
-		drv_destroy(drv);
-	}
-}
-
 static struct isdn_driver *
 get_drv_by_nr(int di)
 {
@@ -577,10 +582,9 @@
 /*
  * driver state machine
  */
-static int  isdn_add_channels(struct isdn_driver *, int, int, int);
+static int  isdn_add_channels(struct isdn_driver *, int);
 static void isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb);
 static int  isdn_status_callback(isdn_ctrl * c);
-static int  isdn_dc2minor(int di, int ch);
 
 static void isdn_v110_add_features(struct isdn_driver *drv);
 
@@ -623,30 +627,12 @@
 {
 	struct isdn_driver *drv = fi->userdata;
 	unsigned long flags;
-	int i;
 
 	spin_lock_irqsave(&drivers_lock, flags);
 	drivers[drv->di] = NULL;
 	spin_unlock_irqrestore(&drivers_lock, flags);
 	put_drv(drv);
 
-	while (drv->locks > 0) {
-		isdn_ctrl cmd;
-		cmd.driver = drv->di;
-		cmd.arg = 0;
-		cmd.command = ISDN_CMD_UNLOCK;
-		__drv_command(drv, &cmd);
-		drv->locks--;
-	}
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		if (slots[i].di == drv->di) {
- 			slots[i].di = -1;
- 			slots[i].drv = NULL;
-			slots[i].ch = -1;
-			slots[i].usage &= ~ISDN_USAGE_DISABLED;
-			isdn_unregister_devfs(i);
-		}
-	}
 	dev->channels -= drv->channels;
 
 	isdn_info_update();
@@ -654,16 +640,6 @@
 }
 
 static int
-drv_stat_addch(struct fsm_inst *fi, int pr, void *arg)
-{
-	struct isdn_driver *drv = fi->userdata;
-	isdn_ctrl *c = arg;
-
-	isdn_add_channels(drv, c->driver, c->arg, 1);
-	isdn_info_update();
-}
-
-static int
 drv_stat_stavail(struct fsm_inst *fi, int pr, void *arg)
 {
 	struct isdn_driver *drv = fi->userdata;
@@ -681,13 +657,9 @@
 {
 	struct isdn_driver *drv = fi->userdata;
 	isdn_ctrl *c = arg;
-	int sl = isdn_dc2minor(drv->di, c->arg & 0xff);
+	int ch = c->arg & 0xff;
 
-	if (sl < 0) {
-		isdn_BUG();
-		return 1;
-	}
-	return fsm_event(&slots[sl].fi, pr, arg);
+	return fsm_event(&drv->slots[ch].fi, pr, arg);
 }
 
 static struct fsm_node drv_fn_tbl[] = {
@@ -695,7 +667,6 @@
 
 	{ ST_DRV_LOADED,  EV_STAT_RUN,     drv_stat_run     },
 	{ ST_DRV_LOADED,  EV_STAT_STAVAIL, drv_stat_stavail },
-	{ ST_DRV_LOADED,  EV_STAT_ADDCH,   drv_stat_addch   },
 	{ ST_DRV_LOADED,  EV_STAT_UNLOAD,  drv_stat_unload  },
 
 	{ ST_DRV_RUNNING, EV_STAT_STOP,    drv_stat_stop    },
@@ -745,7 +716,6 @@
 isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb)
 {
 	struct isdn_driver *drv;
-	int sl;
 
 	drv = get_drv_by_nr(di);
 	if (!drv) {
@@ -759,12 +729,7 @@
 		isdn_BUG();
 		goto out;
 	}
-	sl = isdn_dc2minor(di, ch);
-	if (sl < 0) {
-		isdn_BUG();
-		goto out;
-	}
-	if (fsm_event(&slots[sl].fi, EV_DATA_IND, skb))
+	if (fsm_event(&drv->slots[ch].fi, EV_DATA_IND, skb))
 		dev_kfree_skb(skb);
  out:
 	put_drv(drv);
@@ -942,6 +907,8 @@
 	memset(drv, 0, sizeof(*drv));
 
 	atomic_set(&drv->refcnt, 0);
+	spin_lock_init(&drv->lock);
+	init_waitqueue_head(&drv->st_waitq);
 	drv->fi.fsm = &drv_fsm;
 	drv->fi.state = ST_DRV_NULL;
 	drv->fi.debug = 1;
@@ -963,7 +930,7 @@
 		goto fail_unlock;
 
 	strcpy(drv->id, iif->id);
-	if (isdn_add_channels(drv, drvidx, iif->channels, 0))
+	if (isdn_add_channels(drv, iif->channels))
 		goto fail_unlock;
 
 	drv->di = drvidx;
@@ -993,23 +960,14 @@
 static void
 isdn_lock_driver(struct isdn_driver *drv)
 {
-	isdn_ctrl cmd;
-
-	cmd.driver = drv->di;
-	cmd.arg = 0;
-	cmd.command = ISDN_CMD_LOCK;
-	__drv_command(drv, &cmd);
+	// FIXME don't ignore return value
+	try_module_get(drv->interface->owner);
 }
 
 static void
 isdn_unlock_driver(struct isdn_driver *drv)
 {
-	isdn_ctrl cmd;
-
-	cmd.driver = drv->di;
-	cmd.arg = 0;
-	cmd.command = ISDN_CMD_UNLOCK;
-	__drv_command(drv, &cmd);
+	module_put(drv->interface->owner);
 }
 
 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
@@ -1121,24 +1079,10 @@
 }
 
 static int
-isdn_dc2minor(int di, int ch)
-{
-	int i;
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-		if (slots[i].ch == ch && slots[i].di == di)
-			return i;
-	return -1;
-}
-
-static int
 __drv_command(struct isdn_driver *drv, isdn_ctrl *c)
 {
 #ifdef ISDN_DEBUG_COMMAND
 	switch (c->command) {
-	case ISDN_CMD_LOCK: 
-		printk(KERN_DEBUG "ISDN_CMD_LOCK %d/%ld\n", c->driver, c->arg & 0xff); break;
-	case ISDN_CMD_UNLOCK: 
-		printk(KERN_DEBUG "ISDN_CMD_UNLOCK %d/%ld\n", c->driver, c->arg & 0xff); break;
 	case ISDN_CMD_SETL2: 
 		printk(KERN_DEBUG "ISDN_CMD_SETL2 %d/%ld\n", c->driver, c->arg & 0xff); break;
 	case ISDN_CMD_SETL3: 
@@ -1177,19 +1121,14 @@
 #include <linux/isdn/capicmd.h>
 
 int
-isdn_capi_rec_hl_msg(capi_msg *cm) {
-	
-	int di;
-	int ch;
-	
-	di = (cm->adr.Controller & 0x7f) -1;
-	ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
+isdn_capi_rec_hl_msg(capi_msg *cm)
+{
 	switch(cm->Command) {
-		case CAPI_FACILITY:
-			/* in the moment only handled in tty */
-			return(isdn_tty_capi_facility(cm));
-		default:
-			return(-1);
+	case CAPI_FACILITY:
+		/* in the moment only handled in tty */
+		return isdn_tty_capi_facility(cm);
+	default:
+		return -1;
 	}
 }
 
@@ -1206,64 +1145,112 @@
 	return v;
 }
 
-static __inline int
-isdn_minor2drv(int minor)
+static struct isdn_slot *
+get_slot_by_minor(int minor)
 {
-	return slots[minor].di;
+	int di, ch;
+	struct isdn_driver *drv;
+
+	for (di = 0; di < ISDN_MAX_CHANNELS; di++) {
+		drv = get_drv_by_nr(di);
+		if (!drv)
+			continue;
+
+		for (ch = 0; ch < drv->channels; ch++) {
+			if (minor-- == 0)
+				goto found;
+		}
+		put_drv(drv);
+	}
+	return NULL;
+
+ found:
+	return drv->slots + ch;
 }
 
-static __inline int
-isdn_minor2chan(int minor)
+static inline void
+put_slot(struct isdn_slot *slot)
 {
-	return slots[minor].ch;
+	put_drv(slot->drv);
 }
 
 static char *
 isdn_statstr(void)
 {
 	static char istatbuf[2048];
+	struct isdn_slot *slot;
 	char *p;
 	int i;
 
 	sprintf(istatbuf, "idmap:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		sprintf(p, "%s ", (slots[i].di < 0) ? "-" : isdn_drv_drvid(slots[i].di));
+		slot = get_slot_by_minor(i);
+		if (slot) {
+			sprintf(p, "%s ", slot->drv->id);
+			put_slot(slot);
+		} else {
+			sprintf(p, "- ");
+		}
 		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\nchmap:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		sprintf(p, "%d ", slots[i].ch);
+		slot = get_slot_by_minor(i);
+		if (slot) {
+			sprintf(p, "%d ", slot->ch);
+			put_slot(slot);
+		} else {
+			sprintf(p, "-1 ");
+		}
 		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\ndrmap:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		sprintf(p, "%d ", slots[i].di);
-		p = istatbuf + strlen(istatbuf);
+		slot = get_slot_by_minor(i);
+		if (slot) {
+			sprintf(p, "%d ", slot->di);
+			put_slot(slot);
+		} else {
+			sprintf(p, "-1 ");
+		}
 	}
 	sprintf(p, "\nusage:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		sprintf(p, "%d ", slots[i].usage);
+		slot = get_slot_by_minor(i);
+		if (slot) {
+			sprintf(p, "%d ", slot->usage);
+			put_slot(slot);
+		} else {
+			sprintf(p, "0 ");
+		}
 		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\nflags:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
-		if (drivers[i]) {
+		slot = get_slot_by_minor(i);
+		if (slot) {
 			sprintf(p, "0 ");
-			p = istatbuf + strlen(istatbuf);
+			put_slot(slot);
 		} else {
 			sprintf(p, "? ");
-			p = istatbuf + strlen(istatbuf);
 		}
+		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\nphone:\t");
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		sprintf(p, "%s ", slots[i].num);
+		slot = get_slot_by_minor(i);
+		if (slot) {
+			sprintf(p, "%s ", slot->num);
+			put_slot(slot);
+		} else {
+			sprintf(p, " ");
+		}
 		p = istatbuf + strlen(istatbuf);
 	}
 	sprintf(p, "\n");
@@ -1392,7 +1379,9 @@
 static int
 isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
 {
+	static unsigned long zero_ul = 0UL;
 	int ret;
+	struct isdn_slot *slot;
 
 	switch (cmd) {
 	case IIOCGETDVR:
@@ -1407,8 +1396,15 @@
 					       sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
 				return ret;
 			for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-				put_user(slots[i].ibytes, p++);
-				put_user(slots[i].obytes, p++);
+				slot = get_slot_by_minor(i);
+				if (slot) {
+					put_user(slot->ibytes, p++);
+					put_user(slot->obytes, p++);
+					put_slot(slot);
+				} else {
+					put_user(zero_ul, p++);
+					put_user(zero_ul, p++);
+				}
 			}
 			return 0;
 		} else
@@ -1441,29 +1437,27 @@
 isdn_ctrl_open(struct inode *ino, struct file *file)
 {
 	unsigned int minor = minor(ino->i_rdev);
-	int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-	struct isdn_driver *drv;
+	struct isdn_slot *slot = get_slot_by_minor(minor - ISDN_MINOR_CTRL);
 
-	drv = get_drv_by_nr(drvidx);
-	if (!drv)
+	if (!slot)
 		return -ENODEV;
 
-	isdn_lock_driver(drv);
+	isdn_lock_driver(slot->drv);
+	file->private_data = slot;
 
-	file->private_data = drv;
 	return 0;
 }
 
 static int
 isdn_ctrl_release(struct inode *ino, struct file *file)
 {
-	struct isdn_driver *drv = file->private_data;
+	struct isdn_slot *slot = file->private_data;
 
 	if (dev->profd == current)
 		dev->profd = NULL;
 
-	isdn_unlock_driver(drv);
-	put_drv(drv);
+	isdn_unlock_driver(slot->drv);
+	put_slot(slot);
 
 	return 0;
 }
@@ -1471,24 +1465,22 @@
 static ssize_t
 isdn_ctrl_read(struct file *file, char *buf, size_t count, loff_t * off)
 {
-	struct isdn_driver *drv = file->private_data;
-	unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
+	struct isdn_slot *slot = file->private_data;
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int len = 0;
 
-
 	if (off != &file->f_pos)
 		return -ESPIPE;
 
-	if (!drv->interface->readstat) {
+	if (!slot->drv->interface->readstat) {
 		isdn_BUG();
 		return 0;
 	}
- 	add_wait_queue(&drv->st_waitq, &wait);
+ 	add_wait_queue(&slot->drv->st_waitq, &wait);
 	for (;;) {
 		spin_lock_irqsave(&stat_lock, flags);
-		len = drv->stavail;
+		len = slot->drv->stavail;
 		spin_unlock_irqrestore(&stat_lock, flags);
 		if (len > 0)
 			break;
@@ -1503,7 +1495,7 @@
 		schedule();
 	}
 	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&drv->st_waitq, &wait);
+	remove_wait_queue(&slot->drv->st_waitq, &wait);
 	
 	if (len < 0)
 		return len;
@@ -1511,15 +1503,15 @@
 	if (count > len)
 		count = len;
 		
-	len = drv->interface->readstat(buf, count, 1, drv->di,
-				       isdn_minor2chan(minor));
+	len = slot->drv->interface->readstat(buf, count, 1, slot->di, 
+					     slot->ch);
 
 	spin_lock_irqsave(&stat_lock, flags);
 	if (len) {
-		drv->stavail -= len;
+		slot->drv->stavail -= len;
 	} else {
 		isdn_BUG();
-		drv->stavail = 0;
+		slot->drv->stavail = 0;
 	}
 	spin_unlock_irqrestore(&stat_lock, flags);
 
@@ -1530,20 +1522,19 @@
 static ssize_t
 isdn_ctrl_write(struct file *file, const char *buf, size_t count, loff_t *off)
 {
-	struct isdn_driver *drv = file->private_data;
-	unsigned int minor = minor(file->f_dentry->d_inode->i_rdev);
+	struct isdn_slot *slot = file->private_data;
 	int retval;
 
-	if (off != &file->f_pos)
-		return -ESPIPE;
-
-	if (!drv->interface->writecmd) {
+	if (off != &file->f_pos) {
+		retval = -ESPIPE;
+		goto out;
+	}
+	if (!slot->drv->interface->writecmd) {
 		retval = -EINVAL;
 		goto out;
 	}
-	retval = drv->interface->
-		writecmd(buf, count, 1, drv->di, 
-			 isdn_minor2chan(minor - ISDN_MINOR_CTRL));
+	retval = slot->drv->interface->writecmd(buf, count, 1, slot->di, 
+						slot->ch);
 
  out:
 	return retval;
@@ -1552,12 +1543,12 @@
 static unsigned int
 isdn_ctrl_poll(struct file *file, poll_table *wait)
 {
-	struct isdn_driver *drv = file->private_data;
+	struct isdn_slot *slot = file->private_data;
 	unsigned int mask = 0;
 
-	poll_wait(file, &drv->st_waitq, wait);
+	poll_wait(file, &slot->drv->st_waitq, wait);
 	mask = POLLOUT | POLLWRNORM;
-	if (drv->stavail)
+	if (slot->drv->stavail)
 		mask |= POLLIN | POLLRDNORM;
 
 	return mask;
@@ -1869,46 +1860,61 @@
 isdn_get_free_slot(int usage, int l2_proto, int l3_proto,
 		   int pre_dev, int pre_chan, char *msn)
 {
+	struct isdn_driver *drv;
 	struct isdn_slot *slot;
-	int i;
+	int di, ch;
 	unsigned long flags;
 	unsigned long features;
 
-	save_flags(flags);
-	cli();
 	features = ((1 << l2_proto) | (0x10000 << l3_proto));
 
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		slot = &slots[i];
-
-		if (!slot->drv || slot->drv->fi.state != ST_DRV_RUNNING)
-			continue;
-		
-		if (!USG_NONE(slots[i].usage))
-			continue;
-		
-		if (slots[i].usage & ISDN_USAGE_DISABLED)
+	for (di = 0; di < ISDN_MAX_DRIVERS; di++) {
+		if (pre_dev >= 0 && pre_dev != di)
 			continue;
 
-		if (slots[i].di == -1)
+		drv = get_drv_by_nr(di);
+		if (!drv)
 			continue;
 
-		if (strcmp(isdn_map_eaz2msn(msn, slot->di), "-") == 0)
-			continue;
+		if (drv->fi.state != ST_DRV_RUNNING)
+			goto put;
 
-		if (!(drivers[slot->di]->features & features) == features)
-			continue;
+		if ((drv->features & features) != features)
+			goto put;
+
+		spin_lock_irqsave(&drv->lock, flags);
+		for (ch = 0; ch < drv->channels; ch++) {
+			if (pre_chan >= 0 && pre_chan != ch)
+				continue;
+
+			slot = &drv->slots[ch];
+
+			if (!USG_NONE(slot->usage))
+				continue;
+
+			if (slot->usage & ISDN_USAGE_DISABLED)
+				continue;
 
-		if (pre_dev < 0 || pre_chan < 0 ||
-		    (pre_dev == slot->di && pre_chan == slot->ch)) {
-			slot->usage = usage;
-			isdn_info_update();
-			fsm_event(&slot->fi, EV_SLOT_BIND, NULL);
-			return slot;
+			if (strcmp(isdn_map_eaz2msn(msn, drv->di), "-") == 0)
+				continue;
+
+			goto found;
+			
 		}
+		spin_unlock_irqrestore(&drv->lock, flags);
+
+	put:
+		put_drv(drv);
 	}
-	restore_flags(flags);
 	return NULL;
+
+ found:
+	slot->usage = usage;
+	spin_unlock_irqrestore(&drv->lock, flags);
+
+	isdn_info_update();
+	fsm_event(&slot->fi, EV_SLOT_BIND, NULL);
+	return slot;
 }
 
 /*
@@ -1930,38 +1936,38 @@
 }
 
 static int
-isdn_add_channels(struct isdn_driver *d, int drvidx, int n, int adding)
+isdn_add_channels(struct isdn_driver *drv, int n)
 {
-	int j, k, m;
-	ulong flags;
-
-	init_waitqueue_head(&d->st_waitq);
-
-       	if (n < 1) return 0;
+	struct isdn_slot *slot;
+	int ch;
 
-	m = (adding) ? d->channels + n : n;
+       	if (n < 1)
+		return 0;
 
 	if (dev->channels + n > ISDN_MAX_CHANNELS) {
 		printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
 		       ISDN_MAX_CHANNELS);
-		return -1;
+		return -EBUSY;
 	}
 	dev->channels += n;
-	save_flags(flags);
-	cli();
-	for (j = d->channels; j < m; j++) {
-		for (k = 0; k < ISDN_MAX_CHANNELS; k++) {
-			if (slots[k].ch < 0) {
-				slots[k].ch = j;
-				slots[k].di = drvidx;
-				slots[k].drv = d;
-				isdn_register_devfs(k);
-				break;
-			}
-		}
+	drv->slots = kmalloc(sizeof(struct isdn_slot) * n, GFP_KERNEL);
+	if (!drv->slots)
+		return -ENOMEM;
+	
+	for (ch = 0; ch < n; ch++) {
+		slot = drv->slots + ch;
+
+		slot->ch = ch;
+		slot->di = drv->di;
+		slot->drv = drv;
+		strcpy(slot->num, "???");
+		slot->fi.fsm = &slot_fsm;
+		slot->fi.state = ST_SLOT_NULL;
+		slot->fi.debug = 1;
+		slot->fi.userdata = slot;
+		slot->fi.printdebug = slot_debug;
 	}
-	restore_flags(flags);
-	d->channels = m;
+	drv->channels = n;
 	return 0;
 }
 
@@ -2242,7 +2248,6 @@
  */
 static int __init isdn_init(void)
 {
-	int i;
 	int retval;
 
 	retval = fsm_new(&slot_fsm);
@@ -2261,16 +2266,7 @@
 	memset(dev, 0, sizeof(*dev));
 	init_MUTEX(&dev->sem);
 	init_waitqueue_head(&dev->info_waitq);
-	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-		slots[i].di = -1;
-		slots[i].ch = -1;
-		strcpy(slots[i].num, "???");
-		slots[i].fi.fsm = &slot_fsm;
-		slots[i].fi.state = ST_SLOT_NULL;
-		slots[i].fi.debug = 1;
-		slots[i].fi.userdata = slots + i;
-		slots[i].fi.printdebug = slot_debug;
-	}
+
 	retval = register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops);
 	if (retval) {
 		printk(KERN_WARNING "isdn: Could not register control devices\n");
diff -Nru a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
--- a/drivers/isdn/icn/icn.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/isdn/icn/icn.c	Wed Nov 27 14:36:32 2002
@@ -1441,42 +1441,10 @@
 				card->l2_proto[a & 255] = (a >> 8);
 			}
 			break;
-		case ISDN_CMD_GETL2:
-			if (!card->flags & ICN_FLAGS_RUNNING)
-				return -ENODEV;
-			if ((c->arg & 255) < ICN_BCH)
-				return card->l2_proto[c->arg & 255];
-			else
-				return -ENODEV;
 		case ISDN_CMD_SETL3:
 			if (!card->flags & ICN_FLAGS_RUNNING)
 				return -ENODEV;
 			return 0;
-		case ISDN_CMD_GETL3:
-			if (!card->flags & ICN_FLAGS_RUNNING)
-				return -ENODEV;
-			if ((c->arg & 255) < ICN_BCH)
-				return ISDN_PROTO_L3_TRANS;
-			else
-				return -ENODEV;
-		case ISDN_CMD_GETEAZ:
-			if (!card->flags & ICN_FLAGS_RUNNING)
-				return -ENODEV;
-			break;
-		case ISDN_CMD_SETSIL:
-			if (!card->flags & ICN_FLAGS_RUNNING)
-				return -ENODEV;
-			break;
-		case ISDN_CMD_GETSIL:
-			if (!card->flags & ICN_FLAGS_RUNNING)
-				return -ENODEV;
-			break;
-		case ISDN_CMD_LOCK:
-			MOD_INC_USE_COUNT;
-			break;
-		case ISDN_CMD_UNLOCK:
-			MOD_DEC_USE_COUNT;
-			break;
 		default:
 			return -EINVAL;
 	}
@@ -1577,6 +1545,7 @@
 	}
 	memset((char *) card, 0, sizeof(icn_card));
 	card->port = port;
+	SET_MODULE_OWNER(&card->interface);
 	card->interface.hl_hdrlen = 1;
 	card->interface.channels = ICN_BCH;
 	card->interface.maxbufsize = 4000;
diff -Nru a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
--- a/drivers/isdn/isdnloop/isdnloop.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/isdn/isdnloop/isdnloop.c	Wed Nov 27 14:36:27 2002
@@ -1345,42 +1345,10 @@
 					card->l2_proto[a & 255] = (a >> 8);
 				}
 				break;
-		case ISDN_CMD_GETL2:
-				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
-					return -ENODEV;
-				if ((c->arg & 255) < ISDNLOOP_BCH)
-					return card->l2_proto[c->arg & 255];
-				else
-					return -ENODEV;
 		case ISDN_CMD_SETL3:
 				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
 					return -ENODEV;
 				return 0;
-		case ISDN_CMD_GETL3:
-				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
-					return -ENODEV;
-				if ((c->arg & 255) < ISDNLOOP_BCH)
-					return ISDN_PROTO_L3_TRANS;
-				else
-					return -ENODEV;
-		case ISDN_CMD_GETEAZ:
-				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
-					return -ENODEV;
-				break;
-		case ISDN_CMD_SETSIL:
-				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
-					return -ENODEV;
-				break;
-		case ISDN_CMD_GETSIL:
-				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
-					return -ENODEV;
-				break;
-		case ISDN_CMD_LOCK:
-				MOD_INC_USE_COUNT;
-				break;
-		case ISDN_CMD_UNLOCK:
-				MOD_DEC_USE_COUNT;
-				break;
 		default:
 				return -EINVAL;
 			}
@@ -1482,6 +1450,7 @@
 		return (isdnloop_card *) 0;
 	}
 	memset((char *) card, 0, sizeof(isdnloop_card));
+	SET_MODULE_OWNER(&card->interface);
 	card->interface.channels = ISDNLOOP_BCH;
 	card->interface.hl_hdrlen  = 1; /* scratch area for storing ack flag*/ 
 	card->interface.maxbufsize = 4000;
diff -Nru a/drivers/isdn/pcbit/capi.h b/drivers/isdn/pcbit/capi.h
--- a/drivers/isdn/pcbit/capi.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/pcbit/capi.h	Wed Nov 27 14:36:31 2002
@@ -63,8 +63,7 @@
 extern int capi_decode_debug_188(u_char *hdr, ushort hdrlen);
 #endif
 
-extern __inline__ 
-struct pcbit_chan * 
+static inline struct pcbit_chan * 
 capi_channel(struct pcbit_dev *dev, struct sk_buff *skb)
 {
 	ushort callref;
diff -Nru a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
--- a/drivers/isdn/pcbit/drv.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/pcbit/drv.c	Wed Nov 27 14:36:31 2002
@@ -171,9 +171,10 @@
 
 	dev->dev_if = dev_if;
 
-	dev_if->channels = 2;
-
+	SET_MODULE_OWNER(dev_if);
 
+	dev_if->channels = 2;
+	
 	dev_if->features = (ISDN_FEATURE_P_EURO  | ISDN_FEATURE_L3_TRANS | 
 			    ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS );
 
@@ -276,15 +277,6 @@
 	case ISDN_CMD_SETL2:
 		chan->proto = (ctl->arg >> 8);
 		break;
-	case ISDN_CMD_GETL2:
-		return chan->proto;
-		break;
-	case ISDN_CMD_LOCK:
-		MOD_INC_USE_COUNT;
-		break;
-	case ISDN_CMD_UNLOCK:
-		MOD_DEC_USE_COUNT;
-		break;
 	case ISDN_CMD_CLREAZ:
 		pcbit_clear_msn(dev);
 		break;
@@ -294,14 +286,6 @@
 	case ISDN_CMD_SETL3:
 		if ((ctl->arg >> 8) != ISDN_PROTO_L3_TRANS)
 			printk(KERN_DEBUG "L3 protocol unknown\n");
-		break;
-	case ISDN_CMD_GETL3:
-		return ISDN_PROTO_L3_TRANS;
-		break;
-	case ISDN_CMD_GETEAZ:
-	case ISDN_CMD_SETSIL:
-	case ISDN_CMD_GETSIL:
-		printk(KERN_DEBUG "pcbit_command: code %d not implemented yet\n", ctl->command);
 		break;
 	default:
 		printk(KERN_DEBUG "pcbit_command: unknown command\n");
diff -Nru a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
--- a/drivers/isdn/sc/command.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/sc/command.c	Wed Nov 27 14:36:28 2002
@@ -27,15 +27,8 @@
 int answer(int card, unsigned long channel);
 int clreaz(int card, unsigned long channel);
 int seteaz(int card, unsigned long channel, char *);
-int geteaz(int card, unsigned long channel, char *);
-int setsil(int card, unsigned long channel, char *);
-int getsil(int card, unsigned long channel, char *);
 int setl2(int card, unsigned long arg);
-int getl2(int card, unsigned long arg);
 int setl3(int card, unsigned long arg);
-int getl3(int card, unsigned long arg);
-int lock(void);
-int unlock(void);
 int acceptb(int card, unsigned long channel);
 
 extern int cinst;
@@ -63,17 +56,17 @@
 			    "ISDN_CMD_HANGUP",
 			    "ISDN_CMD_CLREAZ",
 			    "ISDN_CMD_SETEAZ",
-			    "ISDN_CMD_GETEAZ",
-			    "ISDN_CMD_SETSIL",
-			    "ISDN_CMD_GETSIL",
+			    NULL,
+			    NULL,
+			    NULL,
 			    "ISDN_CMD_SETL2",
-			    "ISDN_CMD_GETL2",
+			    NULL,
 			    "ISDN_CMD_SETL3",
-			    "ISDN_CMD_GETL3",
-			    "ISDN_CMD_LOCK",
-			    "ISDN_CMD_UNLOCK",
-			    "ISDN_CMD_SUSPEND",
-			    "ISDN_CMD_RESUME" };
+			    NULL,
+			    NULL,
+			    NULL,
+			    NULL,
+			    NULL, };
 
 /*
  * Translates ISDN4Linux protocol codes to strings for debug messages
@@ -144,24 +137,10 @@
 		return clreaz(card, cmd->arg);
 	case ISDN_CMD_SETEAZ:
 		return seteaz(card, cmd->arg, cmd->parm.num);
-	case ISDN_CMD_GETEAZ:
-		return geteaz(card, cmd->arg, cmd->parm.num);
-	case ISDN_CMD_SETSIL:
-		return setsil(card, cmd->arg, cmd->parm.num);
-	case ISDN_CMD_GETSIL:
-		return getsil(card, cmd->arg, cmd->parm.num);
 	case ISDN_CMD_SETL2:
 		return setl2(card, cmd->arg);
-	case ISDN_CMD_GETL2:
-		return getl2(card, cmd->arg);
 	case ISDN_CMD_SETL3:
 		return setl3(card, cmd->arg);
-	case ISDN_CMD_GETL3:
-		return getl3(card, cmd->arg);
-	case ISDN_CMD_LOCK:
-		return lock();
-	case ISDN_CMD_UNLOCK:
-		return unlock();
 	default:
 		return -EINVAL;
 	}
@@ -358,23 +337,6 @@
 }
 
 /*
- * Get the layer 2 protocol
- */
-int getl2(int card, unsigned long channel) {
-
-	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return -ENODEV;
-	}
-
-	pr_debug("%s: Level 2 protocol for channel %d reported as %s\n",
-		adapter[card]->devicename, channel+1,
-		l2protos[adapter[card]->channel[channel].l2_proto]);
-
-	return adapter[card]->channel[channel].l2_proto;
-}
-
-/*
  * Set the layer 3 protocol
  */
 int setl3(int card, unsigned long channel) 
@@ -392,23 +354,6 @@
 	return 0;
 }
 
-/*
- * Get the layer 3 protocol
- */
-int getl3(int card, unsigned long arg) 
-{
-	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return -ENODEV;
-	}
-
-	pr_debug("%s: Level 3 protocol for channel %d reported as %s\n",
-			adapter[card]->devicename, arg+1,
-			l3protos[adapter[card]->channel[arg].l3_proto]);
-	return adapter[card]->channel[arg].l3_proto;
-}
-
-
 int acceptb(int card, unsigned long channel)
 {
 	if(!IS_VALID_CARD(card)) {
@@ -454,61 +399,6 @@
 	pr_debug("%s: EAZ list for channel %d set to: %s\n",
 		adapter[card]->devicename, arg+1,
 		adapter[card]->channel[arg].eazlist);
-	return 0;
-}
-
-int geteaz(int card, unsigned long arg, char *num)
-{
-	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return -ENODEV;
-	}
-
-	strcpy(num, adapter[card]->channel[arg].eazlist);
-	pr_debug("%s: EAZ List for channel %d reported: %s\n",
-		adapter[card]->devicename, arg+1,
-		adapter[card]->channel[arg].eazlist);
-	return 0;
-}
-
-int setsil(int card, unsigned long arg, char *num)
-{
-	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return -ENODEV;
-	}
-
-	strcpy(adapter[card]->channel[arg].sillist, num);
-	pr_debug("%s: Service Indicators for channel %d set: %s\n",
-		adapter[card]->devicename, arg+1,
-		adapter[card]->channel[arg].sillist);
-	return 0;
-}
-
-int getsil(int card, unsigned long arg, char *num)
-{
-	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return -ENODEV;
-	}
-
-	strcpy(num, adapter[card]->channel[arg].sillist);
-	pr_debug("%s: SIL for channel %d reported: %s\n",
-		adapter[card]->devicename, arg+1,
-		adapter[card]->channel[arg].sillist);
-	return 0;
-}
-
-
-int lock()
-{
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-int unlock()
-{
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
diff -Nru a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
--- a/drivers/isdn/sc/init.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/sc/init.c	Wed Nov 27 14:36:31 2002
@@ -6,6 +6,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include "includes.h"
 #include "hardware.h"
 #include "card.h"
@@ -286,6 +287,7 @@
 		}
 		memset(interface, 0, sizeof(isdn_if));
 
+		SET_MODULE_OWNER(interface);
 		interface->hl_hdrlen = 0;
 		interface->channels = channels;
 		interface->maxbufsize = BUFFER_SIZE;
diff -Nru a/drivers/isdn/tpam/tpam_commands.c b/drivers/isdn/tpam/tpam_commands.c
--- a/drivers/isdn/tpam/tpam_commands.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/isdn/tpam/tpam_commands.c	Wed Nov 27 14:36:28 2002
@@ -27,7 +27,6 @@
 static int tpam_command_ioctl_loopmode(tpam_card *, u8);
 static int tpam_command_dial(tpam_card *, u32, u8 *);
 static int tpam_command_setl2(tpam_card *, u32, u8);
-static int tpam_command_getl2(tpam_card *, u32);
 static int tpam_command_acceptd(tpam_card *, u32);
 static int tpam_command_acceptb(tpam_card *, u32);
 static int tpam_command_hangup(tpam_card *, u32);
@@ -93,14 +92,6 @@
 		case ISDN_CMD_SETL2:
 			return tpam_command_setl2(card, c->arg & 0xff, 
 						  c->arg >> 8);
-		case ISDN_CMD_GETL2:
-			return tpam_command_getl2(card, c->arg);
-		case ISDN_CMD_LOCK:
-			MOD_INC_USE_COUNT;
-			return 0;
-		case ISDN_CMD_UNLOCK:
-			MOD_DEC_USE_COUNT;
-			return 0;
 		case ISDN_CMD_PROCEED:
 			return tpam_command_proceed(card, c->arg);
 		default:
@@ -368,30 +359,6 @@
 			return -EINVAL;
 	}
 	return 0;
-}
-
-/*
- * Return the level2 protocol (modem or HDLC).
- *
- * 	card: the board
- * 	channel: the channel number
- *
- * Return: ISDN_PROTO_L2_HDLC/MODEM if OK, <0 if error.
- */
-static int tpam_command_getl2(tpam_card *card, u32 channel) {
-
-	dprintk("TurboPAM(tpam_command_getl2): card=%d, channel=%lu\n",
-		card->id, (unsigned long)channel);
-	
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	/* return the current mode */
-	if (card->channels[channel].realhdlc)
-		return ISDN_PROTO_L2_HDLC;
-	else
-		return ISDN_PROTO_L2_MODEM;
 }
 
 /*
diff -Nru a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c
--- a/drivers/isdn/tpam/tpam_main.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/isdn/tpam/tpam_main.c	Wed Nov 27 14:36:31 2002
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
 
 #include <linux/init.h>
 #include <asm/io.h>
@@ -131,6 +132,7 @@
 	copy_to_pam_dword(card, (void *)0x01840070, 0x00000010);
 
 	/* fill the ISDN link layer structure */
+	SET_MODULE_OWNER(&card->interface);
 	card->interface.channels = TPAM_NBCHANNEL;
 	card->interface.maxbufsize = TPAM_MAXBUFSIZE;
 	card->interface.features = 
diff -Nru a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
--- a/drivers/macintosh/via-pmu.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/macintosh/via-pmu.c	Wed Nov 27 14:36:31 2002
@@ -2605,7 +2605,7 @@
 			disable_kernel_backlight--;
 			spin_unlock_irqrestore(&pmu_lock, flags);
 		}
-#endif defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
+#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
 		kfree(pp);
 	}
 	unlock_kernel();
diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
--- a/drivers/md/dm-ioctl.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/md/dm-ioctl.c	Wed Nov 27 14:36:28 2002
@@ -8,7 +8,6 @@
 
 #include <linux/module.h>
 #include <linux/vmalloc.h>
-#include <linux/compatmac.h>
 #include <linux/miscdevice.h>
 #include <linux/dm-ioctl.h>
 #include <linux/init.h>
@@ -16,6 +15,8 @@
 #include <linux/blk.h>
 #include <linux/slab.h>
 
+#include <asm/uaccess.h>
+
 #define DM_DRIVER_EMAIL "dm@uk.sistina.com"
 
 /*-----------------------------------------------------------------
@@ -177,6 +178,7 @@
 static int register_with_devfs(struct hash_cell *hc)
 {
 	struct gendisk *disk = dm_disk(hc->md);
+
 	hc->devfs_entry =
 	    devfs_register(_dev_dir, hc->name, DEVFS_FL_CURRENT_OWNER,
 			   disk->major, disk->first_minor,
@@ -459,11 +461,11 @@
 	if (!bdev)
 		return -ENXIO;
 
-	if (disk->policy)
-		param->flags |= DM_READONLY_FLAG;
-
 	param->open_count = bdev->bd_openers;
 	bdput(bdev);
+
+	if (disk->policy)
+		param->flags |= DM_READONLY_FLAG;
 
 	table = dm_get_table(md);
 	param->target_count = dm_table_get_num_targets(table);
diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c
--- a/drivers/md/dm-table.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/md/dm-table.c	Wed Nov 27 14:36:32 2002
@@ -146,6 +146,25 @@
 	return 0;
 }
 
+static void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size)
+{
+	unsigned long size;
+	void *addr;
+
+	/*
+	 * Check that we're not going to overflow.
+	 */
+	if (nmemb > (ULONG_MAX / elem_size))
+		return NULL;
+
+	size = nmemb * elem_size;
+	addr = vmalloc(size);
+	if (addr)
+		memset(addr, 0, size);
+
+	return addr;
+}
+
 /*
  * highs, and targets are managed as dynamic arrays during a
  * table load.
@@ -159,9 +178,8 @@
 	/*
 	 * Allocate both the target array and offset array at once.
 	 */
-	n_highs = (sector_t *) vcalloc(sizeof(struct dm_target) +
-				       sizeof(sector_t),
-				       num);
+	n_highs = (sector_t *) dm_vcalloc(sizeof(struct dm_target) +
+					  sizeof(sector_t), num);
 	if (!n_highs)
 		return -ENOMEM;
 
@@ -624,7 +642,7 @@
 		total += t->counts[i];
 	}
 
-	indexes = (sector_t *) vcalloc(total, (unsigned long) NODE_SIZE);
+	indexes = (sector_t *) dm_vcalloc(total, (unsigned long) NODE_SIZE);
 	if (!indexes)
 		return -ENOMEM;
 
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/md/dm.c	Wed Nov 27 14:36:31 2002
@@ -15,7 +15,7 @@
 #include <linux/slab.h>
 
 static const char *_name = DM_NAME;
-#define MAX_DEVICES 256
+#define MAX_DEVICES (1 << KDEV_MINOR_BITS)
 #define SECTOR_SHIFT 9
 
 static int major = 0;
@@ -41,8 +41,6 @@
 
 struct mapped_device {
 	struct rw_semaphore lock;
-
-	kdev_t kdev;
 	atomic_t holders;
 
 	unsigned long flags;
@@ -485,13 +483,25 @@
 	return 0;
 }
 
+/*-----------------------------------------------------------------
+ * A bitset is used to keep track of allocated minor numbers.
+ *---------------------------------------------------------------*/
+static spinlock_t _minor_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long _minor_bits[MAX_DEVICES / BITS_PER_LONG];
+
+static void free_minor(int minor)
+{
+	spin_lock(&_minor_lock);
+	clear_bit(minor, _minor_bits);
+	spin_unlock(&_minor_lock);
+}
+
 /*
  * See if the device with a specific minor # is free.
  */
-static int specific_dev(int minor, struct mapped_device *md)
+static int specific_minor(int minor)
 {
-	struct gendisk *disk;
-	int part;
+	int r = -EBUSY;
 
 	if (minor >= MAX_DEVICES) {
 		DMWARN("request for a mapped_device beyond MAX_DEVICES (%d)",
@@ -499,26 +509,27 @@
 		return -EINVAL;
 	}
 
-	disk = get_gendisk(MKDEV(_major, minor), &part);
-	if (disk) {
-		put_disk(disk);
-		return -EBUSY;
-	}
+	spin_lock(&_minor_lock);
+	if (!test_and_set_bit(minor, _minor_bits))
+		r = minor;
+	spin_unlock(&_minor_lock);
 
-	return minor;
+	return r;
 }
 
-static int any_old_dev(struct mapped_device *md)
+static int next_free_minor(void)
 {
-	int i;
+	int minor, r = -EBUSY;
 
-	for (i = 0; i < MAX_DEVICES; i++)
-		if (specific_dev(i, md) >= 0) {
-			DMWARN("allocating minor = %d", i);
-			return i;
-		}
+	spin_lock(&_minor_lock);
+	minor = find_first_zero_bit(_minor_bits, MAX_DEVICES);
+	if (minor != MAX_DEVICES) {
+		set_bit(minor, _minor_bits);
+		r = minor;
+	}
+	spin_unlock(&_minor_lock);
 
-	return -EBUSY;
+	return r;
 }
 
 /*
@@ -534,15 +545,15 @@
 	}
 
 	/* get a minor number for the dev */
-	minor = (minor < 0) ? any_old_dev(md) : specific_dev(minor, md);
+	minor = (minor < 0) ? next_free_minor() : specific_minor(minor);
 	if (minor < 0) {
 		kfree(md);
 		return NULL;
 	}
 
+	DMWARN("allocating minor %d.", minor);
 	memset(md, 0, sizeof(*md));
 	init_rwsem(&md->lock);
-	md->kdev = mk_kdev(_major, minor);
 	atomic_set(&md->holders, 1);
 
 	md->queue.queuedata = md;
@@ -550,6 +561,7 @@
 
 	md->disk = alloc_disk(1);
 	if (!md->disk) {
+		free_minor(md->disk->first_minor);
 		kfree(md);
 		return NULL;
 	}
@@ -569,6 +581,7 @@
 
 static void free_dev(struct mapped_device *md)
 {
+	free_minor(md->disk->first_minor);
 	del_gendisk(md->disk);
 	put_disk(md->disk);
 	kfree(md);
@@ -749,6 +762,10 @@
 	return 0;
 }
 
+/*
+ * The gendisk is only valid as long as you have a reference
+ * count on 'md'.
+ */
 struct gendisk *dm_disk(struct mapped_device *md)
 {
 	return md->disk;
diff -Nru a/drivers/media/dvb/av7110/Makefile b/drivers/media/dvb/av7110/Makefile
--- a/drivers/media/dvb/av7110/Makefile	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/dvb/av7110/Makefile	Wed Nov 27 14:36:31 2002
@@ -6,5 +6,7 @@
 
 obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
 
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
+
 include $(TOPDIR)/Rules.make 
 
diff -Nru a/drivers/media/dvb/av7110/av7110.c b/drivers/media/dvb/av7110/av7110.c
--- a/drivers/media/dvb/av7110/av7110.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/media/dvb/av7110/av7110.c	Wed Nov 27 14:36:27 2002
@@ -89,7 +89,7 @@
 static void SetMode(av7110_t *av7110, int mode);
 
 void pes_to_ts(u8 const *buf, long int length, u16 pid, p2t_t *p);
-void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, dvb_demux_feed_t *feed);
+void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, struct dvb_demux_feed *feed);
 
 static u32 vidmem	= 0;
 static u32 vidlow	= 0;
@@ -392,9 +392,9 @@
 
 
 static int
-record_cb(pes2ts_t *p2t, u8 *buf, size_t len)
+record_cb(dvb_filter_pes2ts_t *p2t, u8 *buf, size_t len)
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) p2t->priv;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) p2t->priv;
 
         if (!(dvbdmxfeed->ts_type & TS_PACKET)) 
                 return 0;
@@ -404,13 +404,13 @@
                 return dvbdmxfeed->cb.ts(buf, len, 0, 0, 
                                          &dvbdmxfeed->feed.ts, DMX_OK); 
         else
-                return pes2ts(p2t, buf, len);
+                return dvb_filter_pes2ts(p2t, buf, len);
 }
 
 static int 
-pes2ts_cb(void *priv, unsigned char *data)
+dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) priv;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) priv;
         
         dvbdmxfeed->cb.ts(data, 188, 0, 0,
                           &dvbdmxfeed->feed.ts,
@@ -420,9 +420,9 @@
 
 static int 
 AV_StartRecord(av7110_t *av7110, int av,
-               dvb_demux_feed_t *dvbdmxfeed)
+               struct dvb_demux_feed *dvbdmxfeed)
 {
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
   
         if (av7110->playing||(av7110->rec_mode&av))
                 return -EBUSY;
@@ -432,20 +432,30 @@
 
         switch (av7110->rec_mode) {
         case RP_AUDIO:
-                pes2ts_init(&av7110->p2t[0], dvbdmx->pesfilter[0]->pid,
-                            pes2ts_cb, (void *)dvbdmx->pesfilter[0]);
+                dvb_filter_pes2ts_init (&av7110->p2t[0],
+					dvbdmx->pesfilter[0]->pid,
+					dvb_filter_pes2ts_cb,
+					(void *)dvbdmx->pesfilter[0]);
                 outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
                 break;
+
         case RP_VIDEO:
-                pes2ts_init(&av7110->p2t[1], dvbdmx->pesfilter[1]->pid,
-                            pes2ts_cb, (void *)dvbdmx->pesfilter[1]);
+                dvb_filter_pes2ts_init (&av7110->p2t[1],
+					dvbdmx->pesfilter[1]->pid,
+					dvb_filter_pes2ts_cb,
+					(void *)dvbdmx->pesfilter[1]);
                 outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
                 break;
+
         case RP_AV:
-                pes2ts_init(&av7110->p2t[0], dvbdmx->pesfilter[0]->pid,
-                            pes2ts_cb, (void *)dvbdmx->pesfilter[0]);
-                pes2ts_init(&av7110->p2t[1], dvbdmx->pesfilter[1]->pid,
-                            pes2ts_cb, (void *)dvbdmx->pesfilter[1]);
+                dvb_filter_pes2ts_init (&av7110->p2t[0],
+					dvbdmx->pesfilter[0]->pid,
+					dvb_filter_pes2ts_cb,
+					(void *)dvbdmx->pesfilter[0]);
+                dvb_filter_pes2ts_init (&av7110->p2t[1],
+					dvbdmx->pesfilter[1]->pid,
+					dvb_filter_pes2ts_cb,
+					(void *)dvbdmx->pesfilter[1]);
                 outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0);
                 break;
         }
@@ -463,8 +473,8 @@
         outcom(av7110, COMTYPE_REC_PLAY, __Stop, 0);
 
         if (av7110->playing == RP_NONE) {
-                reset_ipack(&av7110->ipack[0]);
-                reset_ipack(&av7110->ipack[1]);
+                dvb_filter_ipack_reset(&av7110->ipack[0]);
+                dvb_filter_ipack_reset(&av7110->ipack[1]);
         }
 
         av7110->playing|=av;
@@ -814,7 +824,7 @@
 static inline int
 DvbDmxFilterCallback(u8 * buffer1, size_t buffer1_len,
                      u8 * buffer2, size_t buffer2_len,
-                     dvb_demux_filter_t *dvbdmxfilter,
+                     struct dvb_demux_filter *dvbdmxfilter,
                      dmx_success_t success,
                      av7110_t *av7110)
 {
@@ -896,7 +906,7 @@
 
         // FIXME: use bottom half or tasklet
         if (av7110->feeding && mem[0]==0x47)
-                DvbDmxSWFilterPackets(&av7110->demux, mem, 512);
+                dvb_dmx_swfilter_packets(&av7110->demux, mem, 512);
 }
 #else
 static
@@ -922,7 +932,7 @@
         } else {
                 if (av7110->ttbp>1000*188 && av7110->ttbp<1024*188) {
                         if (av7110->feeding)
-                                DvbDmxSWFilterPackets(&av7110->demux, 
+                                dvb_dmx_swfilter_packets(&av7110->demux, 
                                                       mem+av7110->ttbp,
                                                       1024- av7110->ttbp / 188);
                 }
@@ -937,7 +947,7 @@
 
         // FIXME: use bottom half or tasklet
         if (av7110->feeding && mem[0]==0x47)
-                DvbDmxSWFilterPackets(&av7110->demux, mem, num);
+                dvb_dmx_swfilter_packets(&av7110->demux, mem, num);
 }
 #endif
 
@@ -1001,7 +1011,7 @@
         switch (type&0xff) {
 
         case DATA_TS_RECORD:
-                DvbDmxSWFilterPackets(&av7110->demux, 
+                dvb_dmx_swfilter_packets(&av7110->demux, 
                                       (const u8 *)av7110->debi_virt, 
                                       av7110->debilen/188);
                 spin_lock(&av7110->debilock);
@@ -2008,8 +2018,8 @@
         av7110->arm_app=(buf[6] << 16) + buf[7];
         av7110->avtype=(buf[8] << 16) + buf[9];
 
-        printk ("av7110 (%d): AV711%d - firm %08x, rtsl %08x, vid %08x, app %08x\n", 
-		av7110->saa->dvb_adapter->num, av7110->avtype, av7110->arm_fw, 
+        printk ("DVB: AV711%d(%d) - firm %08x, rtsl %08x, vid %08x, app %08x\n",
+		av7110->avtype, av7110->saa->dvb_adapter->num, av7110->arm_fw, 
                 av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
 
         return;
@@ -2483,9 +2493,12 @@
                 if (umem) {
                         if (copy_from_user(av7110->kbuf[type], buf, n)) 
                                 return -EFAULT;
-                        instant_repack(av7110->kbuf[type], n, &av7110->ipack[type]);
-                } else
-                        instant_repack((u8 *)buf, n, &av7110->ipack[type]);
+                        dvb_filter_instant_repack(av7110->kbuf[type], n,
+						  &av7110->ipack[type]);
+                } else {
+                        dvb_filter_instant_repack((u8 *)buf, n,
+						  &av7110->ipack[type]);
+		}
                 todo -= n;
                 buf += n;
         }
@@ -2517,7 +2530,8 @@
                         n=IPACKS*2;
                 if (copy_from_user(av7110->kbuf[type], buf, n)) 
                         return -EFAULT;
-                instant_repack(av7110->kbuf[type], n, &av7110->ipack[type]);
+                dvb_filter_instant_repack(av7110->kbuf[type], n,
+					  &av7110->ipack[type]);
 //                        memcpy(dvb->kbuf[type], buf, n); 
                 todo -= n;
                 buf += n;
@@ -2525,7 +2539,7 @@
 	return count-todo;
 }
 
-void init_p2t(p2t_t *p, dvb_demux_feed_t *feed)
+void init_p2t(p2t_t *p, struct dvb_demux_feed *feed)
 {
 	memset(p->pes,0,TS_SIZE);
 	p->counter = 0;
@@ -2721,7 +2735,7 @@
 
 
 void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, 
-            dvb_demux_feed_t *feed)
+            struct dvb_demux_feed *feed)
 {
   
 	int l, pes_start;
@@ -3104,7 +3118,7 @@
 
 static unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         unsigned int mask=0;
 
@@ -3124,24 +3138,24 @@
 
 
 static struct file_operations dvb_fops = {
-	ioctl:         dvb_ioctl,
-	mmap:          dvb_mmap,
-	llseek:        no_llseek    
+	.ioctl		= dvb_ioctl,
+	.mmap		= dvb_mmap,
+	.llseek		= no_llseek    
 };
 
 
 /* template for video_device-structure */
 static struct video_device dvb_template = {
-	owner:		THIS_MODULE,
-	name:	        "DVB Board",
-	type:	        VID_TYPE_TUNER		|
+	.owner		= THIS_MODULE,
+	.name		= "DVB Board",
+	.type		= VID_TYPE_TUNER	|
         	        VID_TYPE_CAPTURE	|
 	                VID_TYPE_OVERLAY	|
         	        VID_TYPE_CLIPPING	|
                 	VID_TYPE_FRAMERAM	|
 	                VID_TYPE_SCALES,
-	hardware:       VID_HARDWARE_SAA7146,
-	fops:		&dvb_fops
+	.hardware	= VID_HARDWARE_SAA7146,
+	.fops		= &dvb_fops
 };
 
 
@@ -3182,9 +3196,9 @@
  ******************************************************************************/
 
 static int 
-StartHWFilter(dvb_demux_filter_t *dvbdmxfilter)
+StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 {
-        dvb_demux_feed_t *dvbdmxfeed=dvbdmxfilter->feed;
+        struct dvb_demux_feed *dvbdmxfeed=dvbdmxfilter->feed;
         av7110_t *av7110=(av7110_t *) dvbdmxfeed->demux->priv;
         u16 buf[20];
         int ret, i;
@@ -3220,7 +3234,7 @@
 }
 
 static int 
-StopHWFilter(dvb_demux_filter_t *dvbdmxfilter)
+StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 {
         av7110_t *av7110=(av7110_t *) dvbdmxfilter->feed->demux->priv;
         u16 buf[3];
@@ -3252,9 +3266,9 @@
 
 
 static int 
-dvb_write_to_decoder(dvb_demux_feed_t *dvbdmxfeed, u8 *buf, size_t count)
+dvb_write_to_decoder(struct dvb_demux_feed *dvbdmxfeed, u8 *buf, size_t count)
 {
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
         av7110_t *av7110=(av7110_t *) dvbdmx->priv;
         ipack *ipack=&av7110->ipack[dvbdmxfeed->pes_type];
 
@@ -3277,7 +3291,7 @@
                 return -1;
         }
         if (buf[1]&0x40)
-                send_ipack_rest(ipack);
+                dvb_filter_ipack_flush(ipack);
 
         if (buf[3]&0x20) {  // adaptation field?
                 count-=buf[4]+1;
@@ -3287,14 +3301,15 @@
                 }
         }
         
-        instant_repack(buf+4, count-4, &av7110->ipack[dvbdmxfeed->pes_type]);
+        dvb_filter_instant_repack(buf+4, count-4,
+				  &av7110->ipack[dvbdmxfeed->pes_type]);
         return 0;
 }
 
 static void
-dvb_feed_start_pid(dvb_demux_feed_t *dvbdmxfeed)
+dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
 {
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
         av7110_t *av7110=(av7110_t *) dvbdmx->priv;
         u16 *pid=dvbdmx->pids, npids[5];
         int i;
@@ -3329,9 +3344,9 @@
 }
 
 static void
-dvb_feed_stop_pid(dvb_demux_feed_t *dvbdmxfeed)
+dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
 {
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
         av7110_t *av7110=(av7110_t *) dvbdmx->priv;
         u16 *pid=dvbdmx->pids, npids[5];
         int i;
@@ -3365,9 +3380,9 @@
 }
 
 static int 
-dvb_start_feed(dvb_demux_feed_t *dvbdmxfeed)
+dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
         av7110_t *av7110=(av7110_t *) dvbdmx->priv;
 
         if (!dvbdmx->dmx.frontend)
@@ -3425,9 +3440,9 @@
 
 
 static int 
-dvb_stop_feed(dvb_demux_feed_t *dvbdmxfeed)
+dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
         av7110_t *av7110=(av7110_t *) dvbdmx->priv;
 
         if (av7110->saa->card_type>=DVB_CARD_TT_BUDGET) 
@@ -3468,8 +3483,8 @@
 static void 
 restart_feeds(av7110_t *av7110)
 {
-        dvb_demux_t *dvbdmx=&av7110->demux;
-        dvb_demux_feed_t *feed;
+        struct dvb_demux *dvbdmx=&av7110->demux;
+        struct dvb_demux_feed *feed;
         int mode;
         int i;
 
@@ -3660,7 +3675,7 @@
 static int 
 dvb_ca_open(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         int err=dvb_generic_open(inode, file);
 
@@ -3673,7 +3688,7 @@
 static unsigned 
 int dvb_ca_poll(struct file *file, poll_table *wait)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
 
         unsigned int mask=0;
@@ -3702,7 +3717,7 @@
 dvb_ca_ioctl(struct inode *inode, struct file *file, 
              unsigned int cmd, void *parg)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         unsigned long arg=(unsigned long) parg;
 
@@ -3716,7 +3731,7 @@
                 
         case CA_GET_CAP:
         {
-                ca_cap_t cap;
+                ca_caps_t cap;
                 
                 cap.slot_num=2;
 #ifdef NEW_CI
@@ -3788,7 +3803,7 @@
 dvb_ca_write(struct file *file, const char *buf, 
              size_t count, loff_t *ppos)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         
         return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos);
@@ -3797,7 +3812,7 @@
 static ssize_t 
 dvb_ca_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
 
         return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos);
@@ -3812,7 +3827,7 @@
 
 static unsigned int dvb_video_poll(struct file *file, poll_table *wait)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         unsigned int mask=0;
 
@@ -3834,7 +3849,7 @@
 dvb_video_write(struct file *file, const char *buf, 
                 size_t count, loff_t *ppos)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
 
         if (av7110->videostate.stream_source!=VIDEO_SOURCE_MEMORY) 
@@ -3847,7 +3862,7 @@
 dvb_audio_write(struct file *file, const char *buf, 
                 size_t count, loff_t *ppos)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
 
         if (av7110->audiostate.stream_source!=AUDIO_SOURCE_MEMORY) {
@@ -3876,7 +3891,7 @@
 	for (i=0; i<n; i++) 
                 dvb_play(av7110, buf, len, 0, 1, 1);
 
-	send_ipack_rest(&av7110->ipack[1]);
+	dvb_filter_ipack_flush(&av7110->ipack[1]);
 }
 
 
@@ -3884,7 +3899,7 @@
 dvb_video_ioctl(struct inode *inode, struct file *file,
             unsigned int cmd, void *parg)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         unsigned long arg=(unsigned long) parg;
         int ret=0;
@@ -4041,7 +4056,7 @@
         
         case VIDEO_CLEAR_BUFFER:
                 ring_buffer_flush(&av7110->avout);
-                reset_ipack(&av7110->ipack[1]);
+                dvb_filter_ipack_reset(&av7110->ipack[1]);
                 
                 if (av7110->playing==RP_AV) {
                         outcom(av7110, COMTYPE_REC_PLAY, 
@@ -4073,7 +4088,7 @@
 dvb_audio_ioctl(struct inode *inode, struct file *file,
             unsigned int cmd, void *parg)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         unsigned long arg=(unsigned long) parg;
         int ret=0;
@@ -4164,7 +4179,7 @@
 
         case AUDIO_CLEAR_BUFFER:
                 ring_buffer_flush(&av7110->aout);
-                reset_ipack(&av7110->ipack[0]);
+                dvb_filter_ipack_reset(&av7110->ipack[0]);
                 if (av7110->playing==RP_AV)
                         outcom(av7110, COMTYPE_REC_PLAY, 
                                __Play, 2, AV_PES, 0);
@@ -4192,7 +4207,7 @@
 dvb_osd_ioctl(struct inode *inode, struct file *file,
             unsigned int cmd, void *parg)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
 
 #ifdef CONFIG_DVB_AV7110_OSD
@@ -4204,7 +4219,7 @@
 
 static int dvb_video_open(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         int err;
 
@@ -4220,7 +4235,7 @@
 
 static int dvb_video_release(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
 
         AV_Stop(av7110, RP_VIDEO);
@@ -4229,7 +4244,7 @@
 
 static int dvb_audio_open(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         int err=dvb_generic_open(inode, file);
 
@@ -4242,7 +4257,7 @@
 
 static int dvb_audio_release(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         av7110_t *av7110=(av7110_t *) dvbdev->priv;
         
         AV_Stop(av7110, RP_AUDIO);
@@ -4256,75 +4271,70 @@
  ******************************************************************************/
 
 static struct file_operations dvb_video_fops = {
-	owner:		THIS_MODULE,
-        read:		0,
-	write:		dvb_video_write,
-	ioctl:		dvb_generic_ioctl,
-	open:		dvb_video_open,
-	release:	dvb_video_release,
-	poll:		dvb_video_poll,
+	.owner		= THIS_MODULE,
+	.write		= dvb_video_write,
+	.ioctl		= dvb_generic_ioctl,
+	.open		= dvb_video_open,
+	.release	= dvb_video_release,
+	.poll		= dvb_video_poll,
 };
 
-static dvb_device_t dvbdev_video = {
-        priv: 0,
-        users: 1,
-        writers: 1,
-        fops: &dvb_video_fops,
-        kernel_ioctl: dvb_video_ioctl,
+static struct dvb_device dvbdev_video = {
+	.priv		= 0,
+	.users		= 1,
+	.writers	= 1,
+	.fops		= &dvb_video_fops,
+	.kernel_ioctl	= dvb_video_ioctl,
 };
 
 static struct file_operations dvb_audio_fops = {
-	owner:		THIS_MODULE,
-        read:		0,
-	write:		dvb_audio_write,
-	ioctl:		dvb_generic_ioctl,
-	open:		dvb_audio_open,
-	release:	dvb_audio_release,
-	poll:		dvb_audio_poll,
+	.owner		= THIS_MODULE,
+	.write		= dvb_audio_write,
+	.ioctl		= dvb_generic_ioctl,
+	.open		= dvb_audio_open,
+	.release	= dvb_audio_release,
+	.poll		= dvb_audio_poll,
 };
 
-static dvb_device_t dvbdev_audio = {
-        priv: 0,
-        users: 1,
-        writers: 1,
-        fops: &dvb_audio_fops,
-        kernel_ioctl: dvb_audio_ioctl,
+static struct dvb_device dvbdev_audio = {
+	.priv		= 0,
+	.users		= 1,
+	.writers	= 1,
+	.fops		= &dvb_audio_fops,
+	.kernel_ioctl	= dvb_audio_ioctl,
 };
 
 static struct file_operations dvb_ca_fops = {
-	owner:		THIS_MODULE,
-        read:		dvb_ca_read,
-	write:		dvb_ca_write,
-	ioctl:		dvb_generic_ioctl,
-	open:		dvb_ca_open,
-	release:	dvb_generic_release,
-	poll:		dvb_ca_poll,
+	.owner		= THIS_MODULE,
+	.read		= dvb_ca_read,
+	.write		= dvb_ca_write,
+	.ioctl		= dvb_generic_ioctl,
+	.open		= dvb_ca_open,
+	.release	= dvb_generic_release,
+	.poll		= dvb_ca_poll,
 };
 
-static dvb_device_t dvbdev_ca = {
-        priv: 0,
-        users: 1,
-        writers: 1,
-        fops: &dvb_ca_fops,
-        kernel_ioctl: dvb_ca_ioctl,
+static struct dvb_device dvbdev_ca = {
+	.priv		= 0,
+	.users		= 1,
+	.writers	= 1,
+	.fops		= &dvb_ca_fops,
+	.kernel_ioctl	= dvb_ca_ioctl,
 };
 
 static struct file_operations dvb_osd_fops = {
-	owner:		THIS_MODULE,
-        read:		0,
-	write:		0,
-	ioctl:		dvb_generic_ioctl,
-	open:		dvb_generic_open,
-	release:	dvb_generic_release,
-	poll:		0,
+	.owner		= THIS_MODULE,
+	.ioctl		= dvb_generic_ioctl,
+	.open		= dvb_generic_open,
+	.release	= dvb_generic_release,
 };
 
-static dvb_device_t dvbdev_osd = {
-        priv: 0,
-        users: 1,
-        writers: 1,
-        fops: &dvb_osd_fops,
-        kernel_ioctl: dvb_osd_ioctl,
+static struct dvb_device dvbdev_osd = {
+	.priv		= 0,
+	.users		= 1,
+	.writers	= 1,
+	.fops		= &dvb_osd_fops,
+	.kernel_ioctl	= dvb_osd_ioctl,
 };
 
 
@@ -4359,7 +4369,7 @@
 {
         int ret, i;
         dmx_frontend_t *dvbfront=&av7110->hw_frontend;
-        dvb_demux_t *dvbdemux=&av7110->demux;
+        struct dvb_demux *dvbdemux=&av7110->demux;
 
         if (av7110->registered)
                 return -1;
@@ -4414,7 +4424,7 @@
                                              DMX_SECTION_FILTERING|
                                              DMX_MEMORY_BASED_FILTERING);
 
-                DvbDmxInit(&av7110->demux);
+                dvb_dmx_init(&av7110->demux);
 
 
                 dvbfront->id="hw_frontend";
@@ -4426,7 +4436,7 @@
                 av7110->dmxdev.demux=&dvbdemux->dmx;
                 av7110->dmxdev.capabilities=0;
 
-                DmxDevInit(&av7110->dmxdev, av7110->dvb_adapter);
+                dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter);
         }
 
         if (av7110->saa->card_type>=DVB_CARD_TT_BUDGET) {
@@ -4443,7 +4453,7 @@
                                              DMX_SECTION_FILTERING|
                                              DMX_MEMORY_BASED_FILTERING);
 
-                DvbDmxInit(&av7110->demux);
+                dvb_dmx_init(&av7110->demux);
 
                 dvbfront->id="hw_frontend";
                 dvbfront->vendor="VLSI";
@@ -4454,7 +4464,7 @@
                 av7110->dmxdev.demux=&dvbdemux->dmx;
                 av7110->dmxdev.capabilities=0;
 
-                DmxDevInit(&av7110->dmxdev, av7110->dvb_adapter);
+                dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter);
         }
 
         ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, 
@@ -4505,7 +4515,7 @@
 static void 
 dvb_unregister(av7110_t *av7110)
 {
-        dvb_demux_t *dvbdemux=&av7110->demux;
+        struct dvb_demux *dvbdemux=&av7110->demux;
 
         if (!av7110->registered)
                 return;
@@ -4516,8 +4526,8 @@
         dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
         dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
 
-        DmxDevRelease(&av7110->dmxdev);
-        DvbDmxRelease(&av7110->demux);
+        dvb_dmxdev_release(&av7110->dmxdev);
+        dvb_dmx_release(&av7110->demux);
 
 	if (av7110->saa->card_type==DVB_CARD_TT_SIEMENS) 
                 dvb_remove_frontend_notifier (av7110->dvb_adapter,
@@ -4584,9 +4594,9 @@
      
         av7110->vidmode=VIDEO_MODE_PAL;
 
-        init_ipack(&av7110->ipack[0], IPACKS, play_audio_cb);
+        dvb_filter_ipack_init(&av7110->ipack[0], IPACKS, play_audio_cb);
         av7110->ipack[0].data=(void *) av7110;
-        init_ipack(&av7110->ipack[1], IPACKS, play_video_cb);
+        dvb_filter_ipack_init(&av7110->ipack[1], IPACKS, play_video_cb);
         av7110->ipack[1].data=(void *) av7110;
         
 
@@ -4705,8 +4715,8 @@
 	saa7146_write(av7110->saa_mem, ISR,(MASK_19 | MASK_03));
 
 	ci_ll_release(&av7110->ci_rbuffer, &av7110->ci_wbuffer);
-	free_ipack(&av7110->ipack[0]);
-	free_ipack(&av7110->ipack[1]);
+	dvb_filter_ipack_free(&av7110->ipack[0]);
+	dvb_filter_ipack_free(&av7110->ipack[1]);
 	vfree(av7110->iobuf);
 	pci_free_consistent(av7110->saa->device, 8192, av7110->debi_virt,
 			    av7110->debi_bus);
diff -Nru a/drivers/media/dvb/av7110/av7110.h b/drivers/media/dvb/av7110/av7110.h
--- a/drivers/media/dvb/av7110/av7110.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/dvb/av7110/av7110.h	Wed Nov 27 14:36:31 2002
@@ -479,7 +479,7 @@
         u8                counter;
         long int          pos;
         int               frags;
-        dvb_demux_feed_t *feed;
+        struct dvb_demux_feed *feed;
 } p2t_t;
 
 
@@ -561,7 +561,7 @@
 
         int                     vidmode;
         dmxdev_t                dmxdev;
-        dvb_demux_t             demux;
+        struct dvb_demux             demux;
         char                    demux_id[16];
 
         dmx_frontend_t          hw_frontend;
@@ -580,9 +580,9 @@
 #define TRICK_FREEZE 3
         struct audio_status      audiostate;
 
-        dvb_demux_filter_t     *handle2filter[32];
+        struct dvb_demux_filter     *handle2filter[32];
         p2t_t                   p2t_filter[MAXFILT];
-        pes2ts_t                p2t[2];
+        dvb_filter_pes2ts_t     p2t[2];
         struct ipack_s          ipack[2];
         u8                     *kbuf[2];
 
@@ -621,11 +621,11 @@
         ring_buffer_t       ci_wbuffer;
 
 
-        dvb_adapter_t       *dvb_adapter;
-        dvb_device_t        *video_dev;
-        dvb_device_t        *audio_dev;
-        dvb_device_t        *ca_dev;
-        dvb_device_t        *osd_dev;
+        struct dvb_adapter       *dvb_adapter;
+        struct dvb_device        *video_dev;
+        struct dvb_device        *audio_dev;
+        struct dvb_device        *ca_dev;
+        struct dvb_device        *osd_dev;
 
         int                 dsp_dev;
 } av7110_t;
diff -Nru a/drivers/media/dvb/av7110/saa7146.c b/drivers/media/dvb/av7110/saa7146.c
--- a/drivers/media/dvb/av7110/saa7146.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/av7110/saa7146.c	Wed Nov 27 14:36:28 2002
@@ -1399,7 +1399,7 @@
 	/* if any error is still present, a fatal error has occured ... */
 	if ( SAA7146_I2C_BBR != (status = i2c_status_check(saa)) ) {
 		hprintk("saa7146: i2c_reset: fatal error, status:0x%08x\n",status);
-		return -1;
+		return -EIO;
 	}
 
 	return 0;
diff -Nru a/drivers/media/dvb/av7110/saa7146_core.c b/drivers/media/dvb/av7110/saa7146_core.c
--- a/drivers/media/dvb/av7110/saa7146_core.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/dvb/av7110/saa7146_core.c	Wed Nov 27 14:36:31 2002
@@ -33,8 +33,8 @@
 #include "saa7146_core.h"
 #include "saa7146_v4l.h"
 #include "av7110.h"
-#include "../dvb-core/compat.h"
-#include "../dvb-core/dvb_i2c.h"
+#include "compat.h"
+#include "dvb_i2c.h"
 
 /* insmod parameter: here you can specify the number of video-buffers
    to be allocated. for simple capturing 2 buffers (double-buffering)
@@ -197,23 +197,23 @@
 int do_master_xfer (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num)
 {
 	struct saa7146 *a = i2c->data;
-	int result, count;
+	int count;
 	int i = 0;
 	
 	dprintk(KERN_ERR "saa7146_core.o: master_xfer called, num:%d\n",num);
 
 	/* prepare the message(s), get number of u32s to transfer */
 	count = prepare(msgs, num, a->i2c);
-	if ( 0 > count ) {
-		hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not prepare i2c-message\n");
+
+	if (count < 0) {
+		hprintk(KERN_ERR "saa7146_core.o: could not prepare i2c-message\n");
 		return -EIO;
 	}
 
 	/* reset the i2c-device if necessary */
-	result = i2c_reset( a );
-	if ( 0 > result ) {
-		hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not reset i2c-bus\n");
-		return result;
+	if (i2c_reset(a) < 0) {
+		hprintk(KERN_ERR "saa7146_core.o: could not reset i2c-bus\n");
+		return -EIO;
 	}	
 
 	for(i = 0; i < count; i++) {
@@ -222,31 +222,17 @@
 		 * we do not start the whole rps1-engine...
 		 */
 
-		result = i2c_write_out( a, &a->i2c[i],
-					SAA7146_I2C_TIMEOUT );
-
-		if ( 0 != result) {
 			/* if address-error occured, don't retry */
-			if ( result == -EREMOTEIO )
-			{
-				hprintk(KERN_ERR "saa7146_core.o: master_xfer: error in address phase\n");
-				return result;
-			}
-			hprintk(KERN_ERR "saa7146_core.o: master_xfer: error transferring, trying again\n");
-			break;
-		}
+		if (i2c_write_out(a, &a->i2c[i], SAA7146_I2C_TIMEOUT) < 0) {
+			hprintk (KERN_ERR "saa7146_core.o: "
+				"i2c error in address phase\n");
+			return -EREMOTEIO;
 	}
-
-	/* see if an error occured & the last retry failed */
-	if (0 != result) {
-		hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not transfer i2c-message\n");
-		return -EIO;
 	}
 
 	/* if any things had to be read, get the results */
-	result = clean_up(msgs, num, a->i2c);
-	if ( 0 > result ) {
-		hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not cleanup\n");
+	if (clean_up(msgs, num, a->i2c) < 0) {
+		hprintk(KERN_ERR "saa7146_core.o: i2c cleanup failed!\n");
 		return -EIO;
 	}
 
@@ -259,13 +245,19 @@
 static
 int master_xfer (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num)
 {
+	struct saa7146 *saa = i2c->data;
 	int retries = SAA7146_I2C_RETRIES;
 	int ret;
 
+	if (down_interruptible (&saa->i2c_sem))
+		return -ERESTARTSYS;
+
 	do {
 		ret = do_master_xfer (i2c, msgs, num);
 	} while (ret != num && retries--);
 
+	up (&saa->i2c_sem);
+
 	return ret;
 }
 
@@ -273,6 +265,8 @@
 /* registering functions to load algorithms at runtime */
 int i2c_saa7146_add_bus (struct saa7146 *saa)
 {
+	init_MUTEX(&saa->i2c_sem);
+
 	/* enable i2c-port pins */
 	saa7146_write (saa->mem, MC1, (MASK_08 | MASK_24));
 
@@ -389,9 +383,9 @@
 		
 			struct saa7146_debi_transfer *dt = arg;
 
-			printk("saa7146_core.o: SAA7146_DEBI_TRANSFER\n");
-			printk("saa7146_core.o: timeout:%d, swap:%d, slave16:%d, increment:%d, intel:%d, tien:%d\n", dt->timeout, dt->swap, dt->slave16, dt->increment, dt->intel, dt->tien);
-			printk("saa7146_core.o: address:0x%04x, num_bytes:%d, direction:%d, mem:0x%08x\n",dt->address,dt->address,dt->direction,dt->mem);						
+			dprintk("saa7146_core.o: SAA7146_DEBI_TRANSFER\n");
+			dprintk("saa7146_core.o: timeout:%d, swap:%d, slave16:%d, increment:%d, intel:%d, tien:%d\n", dt->timeout, dt->swap, dt->slave16, dt->increment, dt->intel, dt->tien);
+			dprintk("saa7146_core.o: address:0x%04x, num_bytes:%d, direction:%d, mem:0x%08x\n",dt->address,dt->address,dt->direction,dt->mem);						
 
 			debi_transfer(saa, dt);
 			break;
@@ -622,7 +616,7 @@
 	}
 	
 	/* print status message */
-    	printk(KERN_ERR "saa7146_core.o: %s: bus:%d, rev:%d, mem:0x%08x.\n", saa->name, saa->device->bus->number, saa->revision, (unsigned int) saa->mem);
+    	dprintk("saa7146_core.o: %s: bus:%d, rev:%d, mem:0x%08x.\n", saa->name, saa->device->bus->number, saa->revision, (unsigned int) saa->mem);
 
 	/* enable bus-mastering */
  	pci_set_master( saa->device );
@@ -827,7 +821,7 @@
 int __devinit saa7146_init_one (struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
-	struct dvb_adapter_s *adap;
+	struct dvb_adapter *adap;
 	struct saa7146 *saa;
 	int card_type;
 	struct card_info *cinfo= (struct card_info *) ent->driver_data;
diff -Nru a/drivers/media/dvb/av7110/saa7146_core.h b/drivers/media/dvb/av7110/saa7146_core.h
--- a/drivers/media/dvb/av7110/saa7146_core.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/dvb/av7110/saa7146_core.h	Wed Nov 27 14:36:31 2002
@@ -1,17 +1,11 @@
 #ifndef __SAA7146_CORE__
 #define __SAA7146_CORE__
 
-#include <asm/io.h>		/* definitions of u32 etc. */
-#include "../dvb-core/dvbdev.h"
+#include <asm/io.h>
+#include <asm/semaphore.h>
+
+#include "dvbdev.h"
 
-#if LINUX_VERSION_CODE < 0x020300
-#define DECLARE_MUTEX(foo)         struct semaphore foo = MUTEX
-#define DECLARE_MUTEX_LOCKED(foo)  struct semaphore foo = MUTEX_LOCKED
-#define WAIT_QUEUE                 struct wait_queue*
-#define init_waitqueue_head(wq)    *(wq) = NULL;
-#else
-#define WAIT_QUEUE                 wait_queue_head_t
-#endif
 
 /* maximum number of capture frames we support */
 #define SAA7146_MAX_BUF		5
@@ -37,12 +31,13 @@
         char			name[32];	/* give it a nice name */
 
 	struct list_head	list_head;
-
-	dvb_adapter_t		*dvb_adapter;
-	struct dvb_i2c_bus	*i2c_bus;	
 	struct pci_dev		*device;
 	int 			card_type;
 
+	struct dvb_adapter	*dvb_adapter;
+	struct dvb_i2c_bus	*i2c_bus;
+	struct semaphore	i2c_sem;
+
 	void*			  data[SAA7146_MAX_EXTENSIONS];	/* data hooks for extensions */
 
 	int (*command) (struct dvb_i2c_bus *i, unsigned int cmd, void *arg);
@@ -70,8 +65,8 @@
 	int grab_format[SAA7146_MAX_BUF];	/* video format of grabs */
 	int grab_port[SAA7146_MAX_BUF];		/* video port for grab */
 
-        WAIT_QUEUE rps0_wq;                /* rps0 interrupt queue (=> capture) */
-        WAIT_QUEUE rps1_wq;                /* rps1 interrupt queue (=> i2c, ...) */
+        wait_queue_head_t rps0_wq;     /* rps0 interrupt queue (=> capture) */
+        wait_queue_head_t rps1_wq;     /* rps1 interrupt queue (=> i2c, ...) */
 };
 
 #define	SAA7146_IRQ_RPS0  
diff -Nru a/drivers/media/dvb/av7110/saa7146_v4l.c b/drivers/media/dvb/av7110/saa7146_v4l.c
--- a/drivers/media/dvb/av7110/saa7146_v4l.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/media/dvb/av7110/saa7146_v4l.c	Wed Nov 27 14:36:32 2002
@@ -320,7 +320,6 @@
 						
 			/* set corresponding buffer to ´unused´ */
 			saa->frame_stat[i] = GBUFFER_UNUSED;
-printk ("saa7146_v4l.o: SAA7146_V4L_CSYNC, frame %i done.\n", i);
 
 			break;
 		}
diff -Nru a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
--- a/drivers/media/dvb/dvb-core/dmxdev.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/dvb/dvb-core/dmxdev.c	Wed Nov 27 14:36:31 2002
@@ -24,6 +24,7 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/poll.h>
+#include <linux/videodev.h>
 #include <asm/uaccess.h>
 
 #include "dmxdev.h"
@@ -40,19 +41,19 @@
 #define dprintk	if (debug) printk
 
 inline dmxdev_filter_t *
-DmxDevFile2Filter(struct file *file)
+dvb_dmxdev_file_to_filter(struct file *file)
 {
         return (dmxdev_filter_t *) file->private_data;
 }
 
 inline dmxdev_dvr_t *
-DmxDevFile2DVR(dmxdev_t *dmxdev, struct file *file)
+dvb_dmxdev_file_to_dvr(dmxdev_t *dmxdev, struct file *file)
 {
         return (dmxdev_dvr_t *) file->private_data;
 }
 
 static inline void 
-DmxDevBufferInit(dmxdev_buffer_t *buffer) 
+dvb_dmxdev_buffer_init(dmxdev_buffer_t *buffer) 
 {
         buffer->data=0;
         buffer->size=8192;
@@ -63,7 +64,7 @@
 }
 
 static inline int 
-DmxDevBufferWrite(dmxdev_buffer_t *buf, uint8_t *src, int len) 
+dvb_dmxdev_buffer_write(dmxdev_buffer_t *buf, uint8_t *src, int len) 
 {
         int split;
         int free;
@@ -98,7 +99,7 @@
 }
 
 static ssize_t 
-DmxDevBufferRead(dmxdev_buffer_t *src, int non_blocking, 
+dvb_dmxdev_buffer_read(dmxdev_buffer_t *src, int non_blocking, 
 		 char *buf, size_t count, loff_t *ppos)
 {
         unsigned long todo=count;
@@ -108,6 +109,7 @@
 	        return 0;
 
 	if ((error=src->error)) {
+		src->pwrite=src->pread;
 	        src->error=0;
 		return error; 
 	}
@@ -125,6 +127,7 @@
 		        return count-todo;
 
 		if ((error=src->error)) {
+			src->pwrite=src->pread;
 		        src->error=0;
 			return error; 
 		}
@@ -172,7 +175,7 @@
 }
 
 static inline void 
-DmxDevDVRStateSet(dmxdev_dvr_t *dmxdevdvr, int state)
+dvb_dmxdev_dvr_state_set(dmxdev_dvr_t *dmxdevdvr, int state)
 {
         spin_lock_irq(&dmxdevdvr->dev->lock);
         dmxdevdvr->state=state;
@@ -181,7 +184,7 @@
 
 static int dvb_dvr_open(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
 	dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv;
         dmx_frontend_t *front;
 
@@ -198,7 +201,7 @@
 	}
 
 	if ((file->f_flags&O_ACCMODE)==O_RDONLY) {
-	      DmxDevBufferInit(&dmxdev->dvr_buffer);
+	      dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer);
 	      dmxdev->dvr_buffer.size=DVR_BUFFER_SIZE;
 	      dmxdev->dvr_buffer.data=vmalloc(DVR_BUFFER_SIZE);
 	      if (!dmxdev->dvr_buffer.data) {
@@ -230,7 +233,7 @@
 
 static int dvb_dvr_release(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
 	dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv;
 
         if (down_interruptible (&dmxdev->mutex))
@@ -258,7 +261,7 @@
 static ssize_t 
 dvb_dvr_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
 	dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv;
 	int ret;
 
@@ -276,12 +279,12 @@
 static ssize_t 
 dvb_dvr_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
 	dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv;
 	int ret;
 
         //down(&dmxdev->mutex);
-        ret= DmxDevBufferRead(&dmxdev->dvr_buffer, 
+        ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, 
 			      file->f_flags&O_NONBLOCK, 
 			      buf, count, ppos);
         //up(&dmxdev->mutex);
@@ -289,7 +292,7 @@
 }
 
 static inline void 
-DmxDevFilterStateSet(dmxdev_filter_t *dmxdevfilter, int state)
+dvb_dmxdev_filter_state_set(dmxdev_filter_t *dmxdevfilter, int state)
 {
         spin_lock_irq(&dmxdevfilter->dev->lock);
         dmxdevfilter->state=state;
@@ -297,7 +300,7 @@
 }
 
 static int 
-DmxDevSetBufferSize(dmxdev_filter_t *dmxdevfilter, unsigned long size)
+dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size)
 {
 	dmxdev_buffer_t *buf=&dmxdevfilter->buffer;
 	void *mem;
@@ -327,7 +330,7 @@
 }
 
 static void
-DmxDevFilterTimeout(unsigned long data)
+dvb_dmxdev_filter_timeout(unsigned long data)
 {
         dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *)data;
 	
@@ -339,13 +342,13 @@
 }
 
 static void
-DmxDevFilterTimer(dmxdev_filter_t *dmxdevfilter)
+dvb_dmxdev_filter_timer(dmxdev_filter_t *dmxdevfilter)
 {
         struct dmx_sct_filter_params *para=&dmxdevfilter->params.sec;
   
 	del_timer(&dmxdevfilter->timer);
 	if (para->timeout) {
-	        dmxdevfilter->timer.function=DmxDevFilterTimeout;
+	        dmxdevfilter->timer.function=dvb_dmxdev_filter_timeout;
 		dmxdevfilter->timer.data=(unsigned long) dmxdevfilter;
 		dmxdevfilter->timer.expires=jiffies+1+(HZ/2+HZ*para->timeout)/1000;
 		add_timer(&dmxdevfilter->timer);
@@ -353,7 +356,7 @@
 }
 
 static int 
-DmxDevSectionCallback(u8 *buffer1, size_t buffer1_len,
+dvb_dmxdev_section_callback(u8 *buffer1, size_t buffer1_len,
 		      u8 *buffer2, size_t buffer2_len,
 		      dmx_section_filter_t *filter,
 		      dmx_success_t success)
@@ -375,9 +378,9 @@
 		buffer1[0], buffer1[1], 
 		buffer1[2], buffer1[3], 
 		buffer1[4], buffer1[5]);
-        ret=DmxDevBufferWrite(&dmxdevfilter->buffer, buffer1, buffer1_len);
+        ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, buffer1_len);
         if (ret==buffer1_len) {
-	        ret=DmxDevBufferWrite(&dmxdevfilter->buffer, buffer2, buffer2_len);
+	        ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, buffer2_len);
 	}
         if (ret<0) {
 	        dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread;    
@@ -391,7 +394,7 @@
 }
 
 static int 
-DmxDevTSCallback(u8 *buffer1, size_t buffer1_len,
+dvb_dmxdev_ts_callback(u8 *buffer1, size_t buffer1_len,
 		 u8 *buffer2, size_t buffer2_len,
 		 dmx_ts_feed_t *feed,
 		 dmx_success_t success)
@@ -415,9 +418,9 @@
 		wake_up(&buffer->queue);
 	        return 0;
 	}
-        ret=DmxDevBufferWrite(buffer, buffer1, buffer1_len);
+        ret=dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
         if (ret==buffer1_len) 
-	        ret=DmxDevBufferWrite(buffer, buffer2, buffer2_len);
+	        ret=dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
         if (ret<0) {
 	        buffer->pwrite=buffer->pread;    
 	        buffer->error=-EOVERFLOW;
@@ -431,9 +434,9 @@
 /* stop feed but only mark the specified filter as stopped (state set) */
 
 static int 
-DmxDevFeedStop(dmxdev_filter_t *dmxdevfilter)
+dvb_dmxdev_feed_stop(dmxdev_filter_t *dmxdevfilter)
 {
-	DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 
 	switch (dmxdevfilter->type) {
 	case DMXDEV_TYPE_SEC:
@@ -453,9 +456,9 @@
 /* start feed associated with the specified filter */
 
 static int 
-DmxDevFeedStart(dmxdev_filter_t *dmxdevfilter)
+dvb_dmxdev_feed_start(dmxdev_filter_t *dmxdevfilter)
 {
-	DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_GO);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_GO);
 
 	switch (dmxdevfilter->type) {
 	case DMXDEV_TYPE_SEC:
@@ -475,7 +478,7 @@
    otherwise release the feed */
 
 static int 
-DmxDevFeedRestart(dmxdev_filter_t *dmxdevfilter)
+dvb_dmxdev_feed_restart(dmxdev_filter_t *dmxdevfilter)
 {
 	int i;
 	dmxdev_t *dmxdev=dmxdevfilter->dev;
@@ -485,7 +488,7 @@
 		if (dmxdev->filter[i].state>=DMXDEV_STATE_GO &&
 		    dmxdev->filter[i].type==DMXDEV_TYPE_SEC &&
 		    dmxdev->filter[i].pid==pid) {
-			DmxDevFeedStart(&dmxdev->filter[i]);
+			dvb_dmxdev_feed_start(&dmxdev->filter[i]);
 			return 0;
 		}
 	
@@ -497,7 +500,7 @@
 }
 
 static int 
-DmxDevFilterStop(dmxdev_filter_t *dmxdevfilter)
+dvb_dmxdev_filter_stop(dmxdev_filter_t *dmxdevfilter)
 {
         if (dmxdevfilter->state<DMXDEV_STATE_GO) 
 	        return 0;
@@ -506,18 +509,18 @@
 	case DMXDEV_TYPE_SEC:
 	        if (!dmxdevfilter->feed.sec)
 		        break;
-	        DmxDevFeedStop(dmxdevfilter);
+	        dvb_dmxdev_feed_stop(dmxdevfilter);
 	        if (dmxdevfilter->filter.sec)
 		        dmxdevfilter->feed.sec->
 				release_filter(dmxdevfilter->feed.sec,
 					       dmxdevfilter->filter.sec);
-	        DmxDevFeedRestart(dmxdevfilter);
+	        dvb_dmxdev_feed_restart(dmxdevfilter);
 		dmxdevfilter->feed.sec=0;
 		break;
 	case DMXDEV_TYPE_PES:
 	        if (!dmxdevfilter->feed.ts)
 		        break;
-	        DmxDevFeedStop(dmxdevfilter);
+	        dvb_dmxdev_feed_stop(dmxdevfilter);
 	        dmxdevfilter->dev->demux->
 			release_ts_feed(dmxdevfilter->dev->demux,
 					dmxdevfilter->feed.ts);
@@ -533,19 +536,19 @@
 }
 
 static inline int 
-DmxDevFilterReset(dmxdev_filter_t *dmxdevfilter)
+dvb_dmxdev_filter_reset(dmxdev_filter_t *dmxdevfilter)
 {
 	if (dmxdevfilter->state<DMXDEV_STATE_SET) 
 		return 0;
 
 	dmxdevfilter->type=DMXDEV_TYPE_NONE;
 	dmxdevfilter->pid=0xffff;
-	DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
         return 0;
 }
 
 static int 
-DmxDevFilterStart(dmxdev_filter_t *dmxdevfilter)
+dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter)
 {
 	dmxdev_t *dmxdev=dmxdevfilter->dev;
 	void *mem;
@@ -554,7 +557,7 @@
         if (dmxdevfilter->state<DMXDEV_STATE_SET) 
 	        return -EINVAL;
         if (dmxdevfilter->state>=DMXDEV_STATE_GO)
-	        DmxDevFilterStop(dmxdevfilter); 
+	        dvb_dmxdev_filter_stop(dmxdevfilter); 
 
 	mem=dmxdevfilter->buffer.data;
 	if (!mem) {
@@ -566,6 +569,8 @@
                         return -ENOMEM;
 	}
 
+	dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread=0;
+
 	switch (dmxdevfilter->type) {
 	case DMXDEV_TYPE_SEC:
 	{
@@ -588,10 +593,9 @@
 
 		/* if no feed found, try to allocate new one */ 
 		if (!*secfeed) {
-			ret=dmxdev->demux->
-				allocate_section_feed(dmxdev->demux, 
+			ret=dmxdev->demux->allocate_section_feed(dmxdev->demux, 
 						      secfeed, 
-						      DmxDevSectionCallback);
+					           dvb_dmxdev_section_callback);
 			if (ret<0) {
 				printk ("DVB (%s): could not alloc feed\n",
 					__FUNCTION__);
@@ -604,18 +608,17 @@
 			if (ret<0) {
 				printk ("DVB (%s): could not set feed\n",
 					__FUNCTION__);
-				DmxDevFeedRestart(dmxdevfilter);
+				dvb_dmxdev_feed_restart(dmxdevfilter);
 				return ret;
 			}
 		}
 	        else 
-			DmxDevFeedStop(dmxdevfilter);
+			dvb_dmxdev_feed_stop(dmxdevfilter);
 			
 		ret=(*secfeed)->allocate_filter(*secfeed, secfilter);
 		if (ret<0) {
-			DmxDevFeedRestart(dmxdevfilter);
-			dmxdevfilter->feed.sec->
-				start_filtering(*secfeed);
+			dvb_dmxdev_feed_restart(dmxdevfilter);
+			dmxdevfilter->feed.sec->start_filtering(*secfeed);
 			dprintk ("could not get filter\n");
 			return ret;
 		}
@@ -636,15 +639,14 @@
 		(*secfilter)->filter_mask[2]=0;
 		
 	        dmxdevfilter->todo=0;
-	        dmxdevfilter->feed.sec->
-			start_filtering(dmxdevfilter->feed.sec);
-	        DmxDevFilterTimer(dmxdevfilter);
+	        dmxdevfilter->feed.sec->start_filtering(dmxdevfilter->feed.sec);
+	        dvb_dmxdev_filter_timer(dmxdevfilter);
 		break;
 	}
 
 	case DMXDEV_TYPE_PES: 
 	{
-		struct timespec timeout = {0 };
+		struct timespec timeout = { 0 };
 		struct dmx_pes_filter_params *para=&dmxdevfilter->params.pes;
 		dmx_output_t otype;
 		int ret;
@@ -670,31 +672,29 @@
 		
 		ret=dmxdev->demux->allocate_ts_feed(dmxdev->demux, 
 						    tsfeed, 
-						    DmxDevTSCallback);
+						    dvb_dmxdev_ts_callback);
 		if (ret<0) 
 			return ret;
 
 		(*tsfeed)->priv=(void *) dmxdevfilter;
 		ret=(*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes, 188, 32768, 0, timeout);
 		if (ret<0) {
-			dmxdev->demux->
-				release_ts_feed(dmxdev->demux, *tsfeed);
+			dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed);
 			return ret;
 		}
-	        dmxdevfilter->feed.ts->
-			start_filtering(dmxdevfilter->feed.ts);
+	        dmxdevfilter->feed.ts->start_filtering(dmxdevfilter->feed.ts);
 		break;
 	}
 	default:
 	        return -EINVAL;
 	}
-	DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_GO);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_GO);
         return 0;
 }
 
 static int dvb_demux_open(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
 	dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv;
         int i;
         dmxdev_filter_t *dmxdevfilter;
@@ -714,9 +714,9 @@
         dmxdevfilter->dvbdev=dmxdev->dvbdev;
 	file->private_data=dmxdevfilter;
 
-	DmxDevBufferInit(&dmxdevfilter->buffer);
+	dvb_dmxdev_buffer_init(&dmxdevfilter->buffer);
         dmxdevfilter->type=DMXDEV_TYPE_NONE;
-	DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 	dmxdevfilter->feed.ts=0;
 	init_timer(&dmxdevfilter->timer);
 
@@ -725,13 +725,13 @@
 }
 
 int 
-DmxDevFilterFree(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter)
+dvb_dmxdev_filter_free(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter)
 {
         if (down_interruptible(&dmxdev->mutex))
 		return -ERESTARTSYS;
 
-        DmxDevFilterStop(dmxdevfilter);
-	DmxDevFilterReset(dmxdevfilter);
+        dvb_dmxdev_filter_stop(dmxdevfilter);
+	dvb_dmxdev_filter_reset(dmxdevfilter);
         
         if (dmxdevfilter->buffer.data) {
 	        void *mem=dmxdevfilter->buffer.data;
@@ -741,7 +741,7 @@
 	        spin_unlock_irq(&dmxdev->lock);
 		vfree(mem);
 	}
-	DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_FREE);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE);
 	wake_up(&dmxdevfilter->buffer.queue);
 	up(&dmxdev->mutex);
         return 0;
@@ -758,33 +758,33 @@
 
 
 static int 
-DmxDevFilterSet(dmxdev_t *dmxdev, 
+dvb_dmxdev_filter_set(dmxdev_t *dmxdev, 
                 dmxdev_filter_t *dmxdevfilter, 
 		struct dmx_sct_filter_params *params)
 {
         dprintk ("function : %s\n", __FUNCTION__);
 
-	DmxDevFilterStop(dmxdevfilter);
+	dvb_dmxdev_filter_stop(dmxdevfilter);
         
         dmxdevfilter->type=DMXDEV_TYPE_SEC;
         dmxdevfilter->pid=params->pid;
 	memcpy(&dmxdevfilter->params.sec, 
 	       params, sizeof(struct dmx_sct_filter_params));
 	invert_mode(&dmxdevfilter->params.sec.filter);
-	DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 		
         if (params->flags&DMX_IMMEDIATE_START) 
-                return DmxDevFilterStart(dmxdevfilter);
+                return dvb_dmxdev_filter_start(dmxdevfilter);
 
         return 0;
 }
 
 static int 
-DmxDevPesFilterSet(dmxdev_t *dmxdev,
+dvb_dmxdev_pes_filter_set(dmxdev_t *dmxdev,
                    dmxdev_filter_t *dmxdevfilter,
                    struct dmx_pes_filter_params *params)
 {
-	DmxDevFilterStop(dmxdevfilter);
+	dvb_dmxdev_filter_stop(dmxdevfilter);
 
 	if (params->pes_type>DMX_PES_OTHER || params->pes_type<0)
 	        return -EINVAL;
@@ -793,16 +793,16 @@
         dmxdevfilter->pid=params->pid;
 	memcpy(&dmxdevfilter->params, params, sizeof(struct dmx_pes_filter_params));
 
-	DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 
         if (params->flags&DMX_IMMEDIATE_START) 
-                return DmxDevFilterStart(dmxdevfilter);
+                return dvb_dmxdev_filter_start(dmxdevfilter);
 
         return 0;
 }
 
 static ssize_t 
-DmxDevReadSec(dmxdev_filter_t *dfil, struct file *file, 
+dvb_dmxdev_read_sec(dmxdev_filter_t *dfil, struct file *file, 
 	      char *buf, size_t count, loff_t *ppos)
 {
         int result, hcount;
@@ -812,7 +812,7 @@
 	        hcount=3+dfil->todo;
 	        if (hcount>count)
 		        hcount=count;
-		result=DmxDevBufferRead(&dfil->buffer, file->f_flags&O_NONBLOCK, 
+		result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK, 
 					buf, hcount, ppos);
 		if (result<0) {
 			dfil->todo=0;
@@ -832,7 +832,7 @@
 	}
 	if (count>dfil->todo)
 	        count=dfil->todo;
-        result=DmxDevBufferRead(&dfil->buffer, file->f_flags&O_NONBLOCK, 
+        result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK, 
 				buf, count, ppos);
 	if (result<0)
 	        return result;
@@ -844,16 +844,16 @@
 ssize_t 
 dvb_demux_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-        dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(file);
+        dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file);
 	//dmxdev_t *dmxdev=dmxdevfilter->dev;
 	int ret=0;
 
 	// semaphore should not be necessary (I hope ...)
         //down(&dmxdev->mutex);
 	if (dmxdevfilter->type==DMXDEV_TYPE_SEC)
-	        ret=DmxDevReadSec(dmxdevfilter, file, buf, count, ppos);
+	        ret=dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
 	else
-	        ret=DmxDevBufferRead(&dmxdevfilter->buffer, 
+	        ret=dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, 
 				     file->f_flags&O_NONBLOCK, 
 				     buf, count, ppos);
         //up(&dmxdev->mutex);
@@ -864,7 +864,7 @@
 static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
 			      unsigned int cmd, void *parg)
 {
-        dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(file);
+        dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file);
 	dmxdev_t *dmxdev=dmxdevfilter->dev;
         unsigned long arg=(unsigned long) parg;
 	int ret=0;
@@ -877,25 +877,25 @@
 	        if (dmxdevfilter->state<DMXDEV_STATE_SET)
 		        ret=-EINVAL;
 		else
-		        ret=DmxDevFilterStart(dmxdevfilter);
+		        ret=dvb_dmxdev_filter_start(dmxdevfilter);
 		break;
 
 	case DMX_STOP: 
-		ret=DmxDevFilterStop(dmxdevfilter);
+		ret=dvb_dmxdev_filter_stop(dmxdevfilter);
 		break;
 
 	case DMX_SET_FILTER: 
-		ret=DmxDevFilterSet(dmxdev, dmxdevfilter, 
+		ret=dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, 
 				    (struct dmx_sct_filter_params *)parg);
 		break;
 
 	case DMX_SET_PES_FILTER: 
-		ret=DmxDevPesFilterSet(dmxdev, dmxdevfilter, 
+		ret=dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, 
 					       (struct dmx_pes_filter_params *)parg);
 		break;
 
 	case DMX_SET_BUFFER_SIZE: 
-	        ret=DmxDevSetBufferSize(dmxdevfilter, arg);
+	        ret=dvb_dmxdev_set_buffer_size(dmxdevfilter, arg);
 		break;
         
         case DMX_GET_EVENT: 
@@ -919,13 +919,13 @@
 static int dvb_demux_ioctl(struct inode *inode, struct file *file,
 			   unsigned int cmd, unsigned long arg)
 {
-	return generic_usercopy(inode, file, cmd, arg, dvb_demux_do_ioctl);
+	return video_usercopy(inode, file, cmd, arg, dvb_demux_do_ioctl);
 }
 
 
 static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
 {
-        dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(file);
+        dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file);
 
 	if (!dmxdevfilter)
 	        return -EINVAL;
@@ -958,33 +958,32 @@
 
 static int dvb_demux_release(struct inode *inode, struct file *file)
 {
-        dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(file);
+        dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file);
 	dmxdev_t *dmxdev=dmxdevfilter->dev;
 
-	return DmxDevFilterFree(dmxdev, dmxdevfilter);
+	return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
 }
 
 static struct file_operations dvb_demux_fops = {
-	owner:		THIS_MODULE,
-        read:		dvb_demux_read,
-	write:		0,
-	ioctl:		dvb_demux_ioctl,
-	open:		dvb_demux_open,
-	release:	dvb_demux_release,
-	poll:		dvb_demux_poll,
+	.owner		= THIS_MODULE,
+	.read		= dvb_demux_read,
+	.ioctl		= dvb_demux_ioctl,
+	.open		= dvb_demux_open,
+	.release	= dvb_demux_release,
+	.poll		= dvb_demux_poll,
 };
 
-static dvb_device_t dvbdev_demux = {
-        priv: 0,
-        users: 1,
-        writers: 1,
-        fops: &dvb_demux_fops
+static struct dvb_device dvbdev_demux = {
+	.priv		= 0,
+	.users		= 1,
+	.writers	= 1,
+	.fops		= &dvb_demux_fops
 };
 
 static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
 			    unsigned int cmd, void *parg)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
 	dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv;
 
 	int ret=0;
@@ -1008,13 +1007,13 @@
 static int dvb_dvr_ioctl(struct inode *inode, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
-	return generic_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl);
+	return video_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl);
 }
 
 
 static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
 	dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv;
 
         dprintk ("function : %s\n", __FUNCTION__);
@@ -1040,24 +1039,24 @@
 }
 
 static struct file_operations dvb_dvr_fops = {
-	owner:		THIS_MODULE,
-        read:		dvb_dvr_read,
-	write:		dvb_dvr_write,
-	ioctl:		dvb_dvr_ioctl,
-	open:		dvb_dvr_open,
-	release:	dvb_dvr_release,
-	poll:		dvb_dvr_poll,
+	.owner		= THIS_MODULE,
+	.read		= dvb_dvr_read,
+	.write		= dvb_dvr_write,
+	.ioctl		= dvb_dvr_ioctl,
+	.open		= dvb_dvr_open,
+	.release	= dvb_dvr_release,
+	.poll		=dvb_dvr_poll,
 };
 
-static dvb_device_t dvbdev_dvr = {
-        priv: 0,
-        users: 1,
-        writers: 1,
-        fops: &dvb_dvr_fops
+static struct dvb_device dvbdev_dvr = {
+	.priv		= 0,
+	.users		= 1,
+	.writers	= 1,
+	.fops		= &dvb_dvr_fops
 };
 
 int 
-DmxDevInit(dmxdev_t *dmxdev, dvb_adapter_t *dvb_adapter)
+dvb_dmxdev_init(dmxdev_t *dmxdev, struct dvb_adapter *dvb_adapter)
 {
         int i;
 
@@ -1079,22 +1078,22 @@
 	for (i=0; i<dmxdev->filternum; i++) {
                 dmxdev->filter[i].dev=dmxdev;
                 dmxdev->filter[i].buffer.data=0;
-	        DmxDevFilterStateSet(&dmxdev->filter[i], DMXDEV_STATE_FREE);
+	        dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE);
                 dmxdev->dvr[i].dev=dmxdev;
                 dmxdev->dvr[i].buffer.data=0;
-	        DmxDevFilterStateSet(&dmxdev->filter[i], DMXDEV_STATE_FREE);
-	        DmxDevDVRStateSet(&dmxdev->dvr[i], DMXDEV_STATE_FREE);
+	        dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE);
+	        dvb_dmxdev_dvr_state_set(&dmxdev->dvr[i], DMXDEV_STATE_FREE);
 	}
 	dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, DVB_DEVICE_DEMUX);
 	dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev, DVB_DEVICE_DVR);
 
-	DmxDevBufferInit(&dmxdev->dvr_buffer);
+	dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
 void 
-DmxDevRelease(dmxdev_t *dmxdev)
+dvb_dmxdev_release(dmxdev_t *dmxdev)
 {
 	dvb_unregister_device(dmxdev->dvbdev);
 	dvb_unregister_device(dmxdev->dvr_dvbdev);
diff -Nru a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
--- a/drivers/media/dvb/dvb-core/dmxdev.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/media/dvb/dvb-core/dmxdev.h	Wed Nov 27 14:36:32 2002
@@ -64,7 +64,7 @@
 
 
 typedef struct dmxdev_filter_s {
-	dvb_device_t *dvbdev;
+	struct dvb_device *dvbdev;
 
         union {
 	        dmx_section_filter_t *sec;
@@ -102,8 +102,8 @@
 
 
 typedef struct dmxdev_s {
-	dvb_device_t *dvbdev;
-	dvb_device_t *dvr_dvbdev;
+	struct dvb_device *dvbdev;
+	struct dvb_device *dvr_dvbdev;
 
         dmxdev_filter_t *filter;
         dmxdev_dvr_t *dvr;
@@ -122,7 +122,7 @@
 } dmxdev_t;
 
 
-int DmxDevInit(dmxdev_t *dmxdev, dvb_adapter_t *);
-void DmxDevRelease(dmxdev_t *dmxdev);
+int dvb_dmxdev_init(dmxdev_t *dmxdev, struct dvb_adapter *);
+void dvb_dmxdev_release(dmxdev_t *dmxdev);
 
 #endif /* _DMXDEV_H_ */
diff -Nru a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
--- a/drivers/media/dvb/dvb-core/dvb_demux.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c	Wed Nov 27 14:36:28 2002
@@ -182,7 +182,7 @@
  ******************************************************************************/
 
 static inline int
-DvbDmxSWFilterPayload(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) 
+dvb_dmx_swfilter_payload(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf) 
 {
         int p, count;
 	//int ccok;
@@ -208,8 +208,8 @@
 
 
 static int
-DvbDmxSWFilterSectionFilter(dvb_demux_feed_t *dvbdmxfeed, 
-                            dvb_demux_filter_t *f)
+dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *dvbdmxfeed, 
+                            struct dvb_demux_filter *f)
 {
         dmx_section_filter_t *filter=&f->filter;
         int i;
@@ -229,10 +229,10 @@
 }
 
 static inline int
-DvbDmxSWFilterSectionFeed(dvb_demux_feed_t *dvbdmxfeed)
+dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
         u8 *buf=dvbdmxfeed->secbuf;
-        dvb_demux_filter_t *f;
+        struct dvb_demux_filter *f;
 
         if (dvbdmxfeed->secbufp!=dvbdmxfeed->seclen)
                 return -1;
@@ -241,7 +241,7 @@
         if (!(f=dvbdmxfeed->filter))
                 return 0;
         do 
-                if (DvbDmxSWFilterSectionFilter(dvbdmxfeed, f)<0)
+                if (dvb_dmx_swfilter_sectionfilter(dvbdmxfeed, f)<0)
                         return -1;
         while ((f=f->next) && dvbdmxfeed->feed.sec.is_filtering);
 
@@ -251,7 +251,7 @@
 }
 
 static inline int
-DvbDmxSWFilterSectionPacket(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) 
+dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf) 
 {
         int p, count;
         int ccok, rest;
@@ -286,7 +286,7 @@
                                 memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp,
                                        buf+p+1, buf[p]);
                                 dvbdmxfeed->secbufp+=buf[p];
-                                DvbDmxSWFilterSectionFeed(dvbdmxfeed);
+                                dvb_dmx_swfilter_section_feed(dvbdmxfeed);
                         }
                 }
                 p+=buf[p]+1; 		// skip rest of last section
@@ -301,7 +301,7 @@
                                 dvbdmxfeed->secbufp=dvbdmxfeed->seclen;
                                 p+=dvbdmxfeed->seclen;
                                 count=188-p;
-                                DvbDmxSWFilterSectionFeed(dvbdmxfeed);
+                                dvb_dmx_swfilter_section_feed(dvbdmxfeed);
 
                                 // filling bytes until packet end?
                                 if (count && buf[p]==0xff) 
@@ -337,7 +337,7 @@
 	if (rest<=count) {	// section completed in this TS packet
 		memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, rest);
 		dvbdmxfeed->secbufp+=rest;
-		DvbDmxSWFilterSectionFeed(dvbdmxfeed);
+		dvb_dmx_swfilter_section_feed(dvbdmxfeed);
 	} else 	{	// section continues in following ts packet
 		memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, count);
 		dvbdmxfeed->secbufp+=count;
@@ -346,7 +346,7 @@
 }
 
 static inline void 
-DvbDmxSWFilterPacketType(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf)
+dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf)
 {
         switch(dvbdmxfeed->type) {
         case DMX_TYPE_TS:
@@ -354,7 +354,7 @@
                         break;
                 if (dvbdmxfeed->ts_type & TS_PACKET) {
                         if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
-                                DvbDmxSWFilterPayload(dvbdmxfeed, buf);
+                                dvb_dmx_swfilter_payload(dvbdmxfeed, buf);
                         else
                                 dvbdmxfeed->cb.ts((u8 *)buf, 188, 0, 0, 
                                                   &dvbdmxfeed->feed.ts, DMX_OK); 
@@ -368,7 +368,7 @@
         case DMX_TYPE_SEC:
                 if (!dvbdmxfeed->feed.sec.is_filtering)
                         break;
-                if (DvbDmxSWFilterSectionPacket(dvbdmxfeed, buf)<0)
+                if (dvb_dmx_swfilter_section_packet(dvbdmxfeed, buf)<0)
                         dvbdmxfeed->seclen=dvbdmxfeed->secbufp=0;
                 break;
 
@@ -377,27 +377,27 @@
         }
 }
 
-void inline
-DvbDmxSWFilterPacket(dvb_demux_t *dvbdmx, const u8 *buf)
+void
+dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf)
 {
-        dvb_demux_feed_t *dvbdmxfeed;
+        struct dvb_demux_feed *dvbdmxfeed;
 
         if (!(dvbdmxfeed=dvbdmx->pid2feed[ts_pid(buf)]))
                 return;
-        DvbDmxSWFilterPacketType(dvbdmxfeed, buf);
+        dvb_dmx_swfilter_packet_type(dvbdmxfeed, buf);
 }
 
 void
-DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count)
+dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, int count)
 {
-        dvb_demux_feed_t *dvbdmxfeed;
+        struct dvb_demux_feed *dvbdmxfeed;
 
 	spin_lock(&dvbdmx->lock);
 	if ((dvbdmxfeed=dvbdmx->pid2feed[0x2000]))
 		dvbdmxfeed->cb.ts((u8 *)buf, count*188, 0, 0, 
 				  &dvbdmxfeed->feed.ts, DMX_OK); 
         while (count) {
-		DvbDmxSWFilterPacket(dvbdmx, buf);
+		dvb_dmx_swfilter_packet(dvbdmx, buf);
 		count--;
 		buf+=188;
 	}
@@ -405,7 +405,7 @@
 }
 
 static inline void
-DvbDmxSWFilter(dvb_demux_t *dvbdmx, const u8 *buf, size_t count)
+dvb_dmx_swfilter(struct dvb_demux *dvbdmx, const u8 *buf, size_t count)
 {
         int p=0,i, j;
         
@@ -416,7 +416,7 @@
                         return;
                 }
                 memcpy(&dvbdmx->tsbuf[i], buf, j);
-                DvbDmxSWFilterPacket(dvbdmx, dvbdmx->tsbuf);
+                dvb_dmx_swfilter_packet(dvbdmx, dvbdmx->tsbuf);
                 dvbdmx->tsbufp=0;
                 p+=j;
         }
@@ -424,7 +424,7 @@
         while (p<count) {
                 if (buf[p]==0x47) {
                         if (count-p>=188) {
-                                DvbDmxSWFilterPacket(dvbdmx, buf+p);
+                                dvb_dmx_swfilter_packet(dvbdmx, buf+p);
                                 p+=188;
                         } else {
                                 i=count-p;
@@ -444,8 +444,8 @@
  ******************************************************************************
  ******************************************************************************/
 
-static dvb_demux_filter_t *
-DvbDmxFilterAlloc(dvb_demux_t *dvbdmx)
+static struct dvb_demux_filter *
+dvb_dmx_filter_alloc(struct dvb_demux *dvbdmx)
 {
         int i;
 
@@ -458,8 +458,8 @@
         return &dvbdmx->filter[i];
 }
 
-static dvb_demux_feed_t *
-DvbDmxFeedAlloc(dvb_demux_t *dvbdmx)
+static struct dvb_demux_feed *
+dvb_dmx_feed_alloc(struct dvb_demux *dvbdmx)
 {
         int i;
 
@@ -478,10 +478,10 @@
  ******************************************************************************/
 
 static int 
-dmx_pid_set(u16 pid, dvb_demux_feed_t *dvbdmxfeed)
+dmx_pid_set(u16 pid, struct dvb_demux_feed *dvbdmxfeed)
 {
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
-	dvb_demux_feed_t **pid2feed=dvbdmx->pid2feed;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
+	struct dvb_demux_feed **pid2feed=dvbdmx->pid2feed;
 
 	if (pid>DMX_MAX_PID)
                 return -EINVAL;
@@ -510,8 +510,8 @@
                 struct timespec timeout
                 )
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
 	int ret;
 	
         if (down_interruptible (&dvbdmx->mutex))
@@ -576,8 +576,8 @@
 static int 
 dmx_ts_feed_start_filtering(struct dmx_ts_feed_s* feed)
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
 	int ret;
 
         if (down_interruptible (&dvbdmx->mutex))
@@ -608,8 +608,8 @@
 static int 
 dmx_ts_feed_stop_filtering(struct dmx_ts_feed_s* feed)
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
 	int ret;
 
         if (down_interruptible (&dvbdmx->mutex))
@@ -637,13 +637,13 @@
                                    dmx_ts_feed_t **feed, 
                                    dmx_ts_cb callback)
 {
-        dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
-        dvb_demux_feed_t *dvbdmxfeed;
+        struct dvb_demux *dvbdmx=(struct dvb_demux *) demux;
+        struct dvb_demux_feed *dvbdmxfeed;
 
         if (down_interruptible (&dvbdmx->mutex))
 		return -ERESTARTSYS;
 
-        if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) {
+        if (!(dvbdmxfeed=dvb_dmx_feed_alloc(dvbdmx))) {
 		up(&dvbdmx->mutex);
                 return -EBUSY;
 	}
@@ -663,7 +663,7 @@
         (*feed)->stop_filtering=dmx_ts_feed_stop_filtering;
 
 
-        if (!(dvbdmxfeed->filter=DvbDmxFilterAlloc(dvbdmx))) {
+        if (!(dvbdmxfeed->filter=dvb_dmx_filter_alloc(dvbdmx))) {
                 dvbdmxfeed->state=DMX_STATE_FREE;
 		up(&dvbdmx->mutex);
                 return -EBUSY;
@@ -679,8 +679,8 @@
 
 static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed)
 {
-        dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
+        struct dvb_demux *dvbdmx=(struct dvb_demux *) demux;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
 
         if (down_interruptible (&dvbdmx->mutex))
 		return -ERESTARTSYS;
@@ -715,14 +715,14 @@
 dmx_section_feed_allocate_filter(struct dmx_section_feed_s* feed, 
                                  dmx_section_filter_t** filter) 
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdemux=dvbdmxfeed->demux;
-        dvb_demux_filter_t *dvbdmxfilter;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdemux=dvbdmxfeed->demux;
+        struct dvb_demux_filter *dvbdmxfilter;
 
 	if (down_interruptible (&dvbdemux->mutex))
 		return -ERESTARTSYS;
 
-        dvbdmxfilter=DvbDmxFilterAlloc(dvbdemux);
+        dvbdmxfilter=dvb_dmx_filter_alloc(dvbdemux);
         if (!dvbdmxfilter) {
 		up(&dvbdemux->mutex);
                 return -ENOSPC;
@@ -747,8 +747,8 @@
                      u16 pid, size_t circular_buffer_size, 
                      int descramble, int check_crc) 
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
 
         if (pid>0x1fff)
                 return -EINVAL;
@@ -789,11 +789,11 @@
         return 0;
 }
 
-static void prepare_secfilters(dvb_demux_feed_t *dvbdmxfeed)
+static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
 {
 	int i;
         dmx_section_filter_t *sf;
-	dvb_demux_filter_t *f;
+	struct dvb_demux_filter *f;
 	u8 mask, mode, doneq;
 		
 	if (!(f=dvbdmxfeed->filter))
@@ -815,8 +815,8 @@
 static int 
 dmx_section_feed_start_filtering(dmx_section_feed_t *feed)
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
 	int ret;
 
         if (down_interruptible (&dvbdmx->mutex))
@@ -854,8 +854,8 @@
 static int 
 dmx_section_feed_stop_filtering(struct dmx_section_feed_s* feed)
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
         int ret;
 
         if (down_interruptible (&dvbdmx->mutex))
@@ -878,9 +878,9 @@
 dmx_section_feed_release_filter(dmx_section_feed_t *feed, 
                                 dmx_section_filter_t* filter)
 {
-        dvb_demux_filter_t *dvbdmxfilter=(dvb_demux_filter_t *) filter, *f;
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdmx=dvbdmxfeed->demux;
+        struct dvb_demux_filter *dvbdmxfilter=(struct dvb_demux_filter *) filter, *f;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
 
         if (down_interruptible (&dvbdmx->mutex))
 		return -ERESTARTSYS;
@@ -911,13 +911,13 @@
                                         dmx_section_feed_t **feed,
                                         dmx_section_cb callback)
 {
-        dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
-        dvb_demux_feed_t *dvbdmxfeed;
+        struct dvb_demux *dvbdmx=(struct dvb_demux *) demux;
+        struct dvb_demux_feed *dvbdmxfeed;
 
         if (down_interruptible (&dvbdmx->mutex))
 		return -ERESTARTSYS;
 
-        if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) {
+        if (!(dvbdmxfeed=dvb_dmx_feed_alloc(dvbdmx))) {
 		up(&dvbdmx->mutex);
                 return -EBUSY;
 	}
@@ -946,8 +946,8 @@
 static int dvbdmx_release_section_feed(dmx_demux_t *demux, 
                                        dmx_section_feed_t *feed)
 {
-        dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed;
-        dvb_demux_t *dvbdmx=(dvb_demux_t *) demux;
+        struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
+        struct dvb_demux *dvbdmx=(struct dvb_demux *) demux;
 
         if (down_interruptible (&dvbdmx->mutex))
 		return -ERESTARTSYS;
@@ -977,7 +977,7 @@
 
 static int dvbdmx_open(dmx_demux_t *demux)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
 
         if (dvbdemux->users>=MAX_DVB_DEMUX_USERS)
                 return -EUSERS;
@@ -987,7 +987,7 @@
 
 static int dvbdmx_close(struct dmx_demux_s *demux)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
 
         if (dvbdemux->users==0)
                 return -ENODEV;
@@ -998,7 +998,7 @@
 
 static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
 
         if ((!demux->frontend) ||
             (demux->frontend->source!=DMX_MEMORY_FE))
@@ -1007,7 +1007,7 @@
         if (down_interruptible (&dvbdemux->mutex))
 		return -ERESTARTSYS;
 
-        DvbDmxSWFilter(dvbdemux, buf, count);
+        dvb_dmx_swfilter(dvbdemux, buf, count);
         up(&dvbdemux->mutex);
         return count;
 }
@@ -1016,7 +1016,7 @@
 static int dvbdmx_add_frontend(dmx_demux_t *demux, 
                                dmx_frontend_t *frontend)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
         struct list_head *pos, *head=&dvbdemux->frontend_list;
 	
 	if (!(frontend->id && frontend->vendor && frontend->model)) 
@@ -1035,7 +1035,7 @@
 dvbdmx_remove_frontend(dmx_demux_t *demux, 
                        dmx_frontend_t *frontend)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
         struct list_head *pos, *n, *head=&dvbdemux->frontend_list;
 
 	list_for_each_safe (pos, n, head) 
@@ -1052,7 +1052,7 @@
 static struct list_head *
 dvbdmx_get_frontends(dmx_demux_t *demux)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
 
         if (list_empty(&dvbdemux->frontend_list))
 	        return NULL;
@@ -1062,7 +1062,7 @@
 static int dvbdmx_connect_frontend(dmx_demux_t *demux, 
                                    dmx_frontend_t *frontend)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
 
         if (demux->frontend)
                 return -EINVAL;
@@ -1077,7 +1077,7 @@
 
 static int dvbdmx_disconnect_frontend(dmx_demux_t *demux)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
 
         if (down_interruptible (&dvbdemux->mutex))
 		return -ERESTARTSYS;
@@ -1089,24 +1089,24 @@
 
 static int dvbdmx_get_pes_pids(dmx_demux_t *demux, u16 *pids)
 {
-        dvb_demux_t *dvbdemux=(dvb_demux_t *) demux;
+        struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
 
         memcpy(pids, dvbdemux->pids, 5*sizeof(u16));
         return 0;
 }
 
 int 
-DvbDmxInit(dvb_demux_t *dvbdemux)
+dvb_dmx_init(struct dvb_demux *dvbdemux)
 {
         int i;
         dmx_demux_t *dmx=&dvbdemux->dmx;
 
         dvbdemux->users=0;
-	dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(dvb_demux_filter_t));
+	dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter));
 	if (!dvbdemux->filter)
                 return -ENOMEM;
 
-	dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(dvb_demux_feed_t));
+	dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed));
 	if (!dvbdemux->feed) {
 	        vfree(dvbdemux->filter);
                 return -ENOMEM;
@@ -1125,7 +1125,7 @@
                 dvbdemux->pids[i]=0xffff;
 	}
         dvbdemux->playing=dvbdemux->recording=0;
-        memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(dvb_demux_feed_t *));
+        memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(struct dvb_demux_feed *));
         dvbdemux->tsbufp=0;
 
         dmx->frontend=0;
@@ -1159,7 +1159,7 @@
 }
 
 int 
-DvbDmxRelease(dvb_demux_t *dvbdemux)
+dvb_dmx_release(struct dvb_demux *dvbdemux)
 {
         dmx_demux_t *dmx=&dvbdemux->dmx;
 
diff -Nru a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
--- a/drivers/media/dvb/dvb-core/dvb_demux.h	Wed Nov 27 14:36:29 2002
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h	Wed Nov 27 14:36:29 2002
@@ -39,14 +39,14 @@
 
 #define DVB_DEMUX_MASK_MAX 18
 
-typedef struct dvb_demux_filter_s {
+struct dvb_demux_filter {
         dmx_section_filter_t filter;
         u8 maskandmode    [DMX_MAX_FILTER_SIZE]; 
         u8 maskandnotmode [DMX_MAX_FILTER_SIZE]; 
 	int doneq;
 		
-        struct dvb_demux_filter_s *next;
-        struct dvb_demux_feed_s *feed;
+        struct dvb_demux_filter *next;
+        struct dvb_demux_feed *feed;
         int index;
         int state;
         int type;
@@ -56,11 +56,10 @@
         u16 hw_handle;
         struct timer_list timer;
 	int ts_state;
+};
 
-        //u16 pid;  //to be removed
-} dvb_demux_filter_t;
 
-typedef struct dvb_demux_feed_s {
+struct dvb_demux_feed {
         union {
 	        dmx_ts_feed_t ts;
 	        dmx_section_feed_t sec;
@@ -71,7 +70,7 @@
 	        dmx_section_cb sec;
 	} cb;
 
-        struct dvb_demux_s *demux;
+        struct dvb_demux *demux;
         int type;
         int state;
         u16 pid;
@@ -81,7 +80,7 @@
         int check_crc;
 
         struct timespec timeout; 
-        dvb_demux_filter_t *filter;
+        struct dvb_demux_filter *filter;
         int cb_length;
   
         int ts_type;
@@ -93,42 +92,43 @@
         int cc;
 
         u16 peslen;
-} dvb_demux_feed_t;
+};
 
-typedef struct dvb_demux_s {
+struct dvb_demux {
         dmx_demux_t dmx;
         void *priv;
         int filternum;
         int feednum;
-        int (*start_feed)(dvb_demux_feed_t *);
-        int (*stop_feed)(dvb_demux_feed_t *);
-        int (*write_to_decoder)(dvb_demux_feed_t *, u8 *, size_t);
+        int (*start_feed)(struct dvb_demux_feed *);
+        int (*stop_feed)(struct dvb_demux_feed *);
+        int (*write_to_decoder)(struct dvb_demux_feed *, u8 *, size_t);
 
   
         int users;
 #define MAX_DVB_DEMUX_USERS 10
-        dvb_demux_filter_t *filter;
-        dvb_demux_feed_t *feed;
+        struct dvb_demux_filter *filter;
+        struct dvb_demux_feed *feed;
 
         struct list_head frontend_list;
 
-        dvb_demux_feed_t *pesfilter[DMX_TS_PES_OTHER];
+        struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
         u16 pids[DMX_TS_PES_OTHER];
         int playing; 
         int recording; 
 
 #define DMX_MAX_PID 0x2000
-        dvb_demux_feed_t *pid2feed[DMX_MAX_PID+1];
+        struct dvb_demux_feed *pid2feed[DMX_MAX_PID+1];
         u8 tsbuf[188];
         int tsbufp;
 
 	struct semaphore mutex;
 	spinlock_t lock;
-} dvb_demux_t;
+};
 
 
-int DvbDmxInit(dvb_demux_t *dvbdemux);
-int DvbDmxRelease(dvb_demux_t *dvbdemux);
-void DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count);
+int dvb_dmx_init(struct dvb_demux *dvbdemux);
+int dvb_dmx_release(struct dvb_demux *dvbdemux);
+void dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf);
+void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, int count);
 
 #endif /* _DVB_DEMUX_H_ */
diff -Nru a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c
--- a/drivers/media/dvb/dvb-core/dvb_filter.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/media/dvb/dvb-core/dvb_filter.c	Wed Nov 27 14:36:32 2002
@@ -24,454 +24,23 @@
 
 
 
-void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, 
-		 pes2ts_cb_t *cb, void *priv)
-{
-	unsigned char *buf=p2ts->buf;
-
-	buf[0]=0x47;
-	buf[1]=(pid>>8);
-	buf[2]=pid&0xff;
-	p2ts->cc=0;
-	p2ts->cb=cb;
-	p2ts->priv=priv;
-}
-
-int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len)
-{
-	unsigned char *buf=p2ts->buf;
-	int ret=0, rest;
-	
-	//len=6+((pes[4]<<8)|pes[5]);
-
-	buf[1]|=0x40;
-	while (len>=184) {
-		buf[3]=0x10|((p2ts->cc++)&0x0f);
-		memcpy(buf+4, pes, 184);
-		if ((ret=p2ts->cb(p2ts->priv, buf)))
-			return ret;
-		len-=184; pes+=184;
-		buf[1]&=~0x40;
-	}
-	if (!len)
-	        return 0;
-	buf[3]=0x30|((p2ts->cc++)&0x0f);
-	rest=183-len;
-	if (rest) {
-	        buf[5]=0x00;
-		if (rest-1)
-			memset(buf+6, 0xff, rest-1);
-	}
-	buf[4]=rest;
-	memcpy(buf+5+rest, pes, len);
-	return p2ts->cb(p2ts->priv, buf);
-}
-
-void reset_ipack(ipack *p)
-{
-	p->found = 0;
-	p->cid = 0;
-	p->plength = 0;
-	p->flag1 = 0;
-	p->flag2 = 0;
-	p->hlength = 0;
-	p->mpeg = 0;
-	p->check = 0;
-	p->which = 0;
-	p->done = 0;
-	p->count = 0;
-}
-
-void init_ipack(ipack *p, int size,
-		void (*func)(u8 *buf, int size, void *priv))
-{
-	if ( !(p->buf = vmalloc(size*sizeof(u8))) ){
-		printk ("Couldn't allocate memory for ipack\n");
-	}
-	p->size = size;
-	p->func = func;
-	p->repack_subids = 0;
-	reset_ipack(p);
-}
-
-void free_ipack(ipack * p)
-{
-	if (p->buf) vfree(p->buf);
-}
-
-void send_ipack(ipack *p)
-{
-	int off;
-	AudioInfo ai;
-	int ac3_off = 0;
-	int streamid=0;
-	int nframes= 0;
-	int f=0;
-
-	switch ( p->mpeg ){
-	case 2:		
-		if (p->count < 10) return;
-		p->buf[3] = p->cid;
-		
-		p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8);
-		p->buf[5] = (u8)((p->count-6) & 0x00FF);
-		if (p->repack_subids && p->cid == PRIVATE_STREAM1){
-			
-			off = 9+p->buf[8];
-			streamid = p->buf[off];
-			if ((streamid & 0xF8) == 0x80){
-				ai.off = 0;
-				ac3_off = ((p->buf[off+2] << 8)| 
-					   p->buf[off+3]);
-				if (ac3_off < p->count)
-					f=get_ac3info(p->buf+off+3+ac3_off, 
-						      p->count-ac3_off, &ai,0);
-				if ( !f ){
-					nframes = (p->count-off-3-ac3_off)/ 
-						ai.framesize + 1;
-					p->buf[off+2] = (ac3_off >> 8)& 0xFF;
-					p->buf[off+3] = (ac3_off)& 0xFF;
-					p->buf[off+1] = nframes;
-					
-					ac3_off +=  nframes * ai.framesize - 
-						p->count;
-				}
-			}
-		} 
-		p->func(p->buf, p->count, p->data);
-	
-		p->buf[6] = 0x80;
-		p->buf[7] = 0x00;
-		p->buf[8] = 0x00;
-		p->count = 9;
-		if (p->repack_subids && p->cid == PRIVATE_STREAM1 
-		    && (streamid & 0xF8)==0x80 ){
-			p->count += 4;
-			p->buf[9] = streamid;
-			p->buf[10] = (ac3_off >> 8)& 0xFF;
-			p->buf[11] = (ac3_off)& 0xFF;
-			p->buf[12] = 0;
-		}
-
-		break;
-	case 1:
-		if (p->count < 8) return;
-		p->buf[3] = p->cid;
-		
-		p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8);
-		p->buf[5] = (u8)((p->count-6) & 0x00FF);
-		p->func(p->buf, p->count, p->data);
-	
-		p->buf[6] = 0x0F;
-		p->count = 7;
-		break;
-	}
-}
-
-void send_ipack_rest(ipack *p)
-{
-	if (p->plength != MMAX_PLENGTH-6 || p->found<=6)
-		return;
-	p->plength = p->found-6;
-	p->found = 0;
-	send_ipack(p);
-	reset_ipack(p);
-}
-
-static void write_ipack(ipack *p, u8 *data, int count)
-{
-	u8 headr[3] = { 0x00, 0x00, 0x01} ;
-
-	if (p->count < 6){
-		memcpy(p->buf, headr, 3);
-		p->count = 6;
-	}
-
-	if (p->count + count < p->size){
-		memcpy(p->buf+p->count, data, count);
-		p->count += count;
-	} else {
-		int rest = p->size - p->count;
-		memcpy(p->buf+p->count, data, rest);
-		p->count += rest;
-		send_ipack(p);
-		if (count - rest > 0)
-			write_ipack(p, data+rest, count-rest);
-	}
-}
-
-int instant_repack(u8 *buf, int count, ipack *p)
-{
-	int l;
-	int c=0;
-
-	while (c < count && (p->mpeg == 0 ||
-			     (p->mpeg == 1 && p->found < 7) ||
-			     (p->mpeg == 2 && p->found < 9))
-	       &&  (p->found < 5 || !p->done)){
-		switch ( p->found ){
-		case 0:
-		case 1:
-			if (buf[c] == 0x00) p->found++;
-			else p->found = 0;
-			c++;
-			break;
-		case 2:
-			if (buf[c] == 0x01) p->found++;
-			else if (buf[c] == 0) {
-				p->found = 2;
-			} else p->found = 0;
-			c++;
-			break;
-		case 3:
-			p->cid = 0;
-			switch (buf[c]){
-			case PROG_STREAM_MAP:
-			case PRIVATE_STREAM2:
-			case PROG_STREAM_DIR:
-			case ECM_STREAM     :
-			case EMM_STREAM     :
-			case PADDING_STREAM :
-			case DSM_CC_STREAM  :
-			case ISO13522_STREAM:
-				p->done = 1;
-			case PRIVATE_STREAM1:
-			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
-			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
-				p->found++;
-				p->cid = buf[c];
-				c++;
-				break;
-			default:
-				p->found = 0;
-				break;
-			}
-			break;
-			
-		case 4:
-			if (count-c > 1){
-				p->plen[0] = buf[c];
-				c++;
-				p->plen[1] = buf[c];
-				c++;
-				p->found+=2;
-				p->plength=(p->plen[0]<<8)|p->plen[1];
- 			} else {
-				p->plen[0] = buf[c];
-				p->found++;
-				return count;
-			}
-			break;
-		case 5:
-			p->plen[1] = buf[c];
-			c++;
-			p->found++;
-			p->plength=(p->plen[0]<<8)|p->plen[1];
-			break;
-		case 6:
-			if (!p->done){
-				p->flag1 = buf[c];
-				c++;
-				p->found++;
-				if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
-				else {
-					p->hlength = 0;
-					p->which = 0;
-					p->mpeg = 1;
-					p->flag2 = 0;
-				}
-			}
-			break;
-
-		case 7:
-			if ( !p->done && p->mpeg == 2) {
-				p->flag2 = buf[c];
-				c++;
-				p->found++;
-			}	
-			break;
-
-		case 8:
-			if ( !p->done && p->mpeg == 2) {
-				p->hlength = buf[c];
-				c++;
-				p->found++;
-			}
-			break;
-			
-		default:
-
-			break;
-		}
-	}
-
-	if (c == count) return count;
-
-	if (!p->plength) p->plength = MMAX_PLENGTH-6;
-
-	if ( p->done || ((p->mpeg == 2 && p->found >= 9) || 
-	     (p->mpeg == 1 && p->found >= 7)) ){
-		switch (p->cid){
-			
-		case AUDIO_STREAM_S ... AUDIO_STREAM_E:			
-		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
-		case PRIVATE_STREAM1:
-			
-			if (p->mpeg == 2 && p->found == 9) {
-				write_ipack(p, &p->flag1, 1);
-				write_ipack(p, &p->flag2, 1);
-				write_ipack(p, &p->hlength, 1);
-			}
-
-			if (p->mpeg == 1 && p->found == 7) 
-				write_ipack(p, &p->flag1, 1);
-			
-			if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&  
-			    p->found < 14) {
-				while (c < count && p->found < 14) {
-					p->pts[p->found-9] = buf[c];
-					write_ipack(p, buf+c, 1);
-					c++;
-					p->found++;
-				}
-				if (c == count) return count;
-			}
-
-			if (p->mpeg == 1 && p->which < 2000) {
-
-				if (p->found == 7) {
-					p->check = p->flag1;
-					p->hlength = 1;
-				}
-
-				while (!p->which && c < count && 
-				       p->check == 0xFF){
-					p->check = buf[c];
-					write_ipack(p, buf+c, 1);
-					c++;
-					p->found++;
-					p->hlength++;
-				}
-				
-				if ( c == count) return count;
-				
-				if ( (p->check & 0xC0) == 0x40 && !p->which){
-					p->check = buf[c];
-					write_ipack(p, buf+c, 1);
-					c++;
-					p->found++;
-					p->hlength++;
-					
-					p->which = 1;
-					if ( c == count) return count;
-					p->check = buf[c];
-					write_ipack(p, buf+c, 1);
-					c++;
-					p->found++;
-					p->hlength++;
-					p->which = 2;
-					if ( c == count) return count;
-				}
-				
-				if (p->which == 1){
-					p->check = buf[c];
-					write_ipack(p, buf+c, 1);
-					c++;
-					p->found++;
-					p->hlength++;
-					p->which = 2;
-					if ( c == count) return count;
-				}
-				
-				if ( (p->check & 0x30) && p->check != 0xFF){
-					p->flag2 = (p->check & 0xF0) << 2;
-					p->pts[0] = p->check;
-					p->which = 3;
-				} 
-			
-				if ( c == count) return count;
-				if (p->which > 2){
-					if ((p->flag2 & PTS_DTS_FLAGS)
-					    == PTS_ONLY){
-						while (c < count && 
-						       p->which < 7){
-							p->pts[p->which-2] =
-								buf[c];
-							write_ipack(p,buf+c,1);
-							c++;
-							p->found++;
-							p->which++;
-							p->hlength++;
-						}
-						if ( c == count) return count;
-					} else if ((p->flag2 & PTS_DTS_FLAGS) 
-						   == PTS_DTS){
-						while (c < count && 
-						       p->which< 12){
-							if (p->which< 7)
-								p->pts[p->which
-								      -2] =
-									buf[c];
-							write_ipack(p,buf+c,1);
-							c++;
-							p->found++;
-							p->which++;
-							p->hlength++;
-						}
-						if ( c == count) return count;
-					}
-					p->which = 2000;
-				}
-				
-			}
-			
-			while (c < count && p->found < p->plength+6){
-				l = count -c;
-				if (l+p->found > p->plength+6)
-					l = p->plength+6-p->found;
-				write_ipack(p, buf+c, l);
-				p->found += l;
-				c += l;
-			}	
-			
-			break;
-		}
-
-
-		if ( p->done ){
-			if( p->found + count - c < p->plength+6){
-				p->found += count-c;
-				c = count;
-			} else {
-				c += p->plength+6 - p->found;
-				p->found = p->plength+6;
-			}
-		}
-
-		if (p->plength && p->found == p->plength+6) {
-			send_ipack(p);
-			reset_ipack(p);
-			if (c < count)
-				instant_repack(buf+c, count-c, p);
-		}
-	}
-	return count;
-}
-
-
-
+#if 0
+static
 void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, 
 		  void (*pes_write)(u8 *buf, int count, void *data),
 		  void *priv)
 {
-	init_ipack(pa, IPACKS, pes_write);
-	init_ipack(pv, IPACKS, pes_write);
+	dvb_filter_ipack_init(pa, IPACKS, pes_write);
+	dvb_filter_ipack_init(pv, IPACKS, pes_write);
 	pa->pid = pida;
 	pv->pid = pidv;
 	pa->data = priv;
 	pv->data = priv;
 }
+#endif
 
+#if 0
+static
 void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
 {
 	u8 off = 0;
@@ -483,28 +52,31 @@
 	if (buf[1]&PAY_START) {
 		if (p->plength == MMAX_PLENGTH-6 && p->found>6){
 			p->plength = p->found-6;
-			p->found = 0;
+	p->found = 0;
 			send_ipack(p);
-			reset_ipack(p);
-		}
+			dvb_filter_ipack_reset(p);
+	}
 	}
 	if (buf[3] & ADAPT_FIELD) {  // adaptation field?
 		off = buf[4] + 1;
 		if (off+4 > 187) return;
 	}
-	instant_repack(buf+4+off, TS_SIZE-4-off, p);
+	dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
 }
+#endif
 
+#if 0
 /* needs 5 byte input, returns picture coding type*/
+static
 int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr)
 {
 	uint8_t pct;
-
+			
 	if (pr) printk( "Pic header: ");
         pic->temporal_reference[field] = (( headr[0] << 2 ) | 
 					  (headr[1] & 0x03) )& 0x03ff;
 	if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
-
+					
 	pct = ( headr[1] >> 2 ) & 0x07;
         pic->picture_coding_type[field] = pct;
 	if (pr) {
@@ -518,29 +90,31 @@
 			case P_FRAME:
 				printk( "  P-FRAME");
 				break;
-		}
-	}
-
+			}
+		} 
+	
 
         pic->vinfo.vbv_delay  = (( headr[1] >> 5 ) | ( headr[2] << 3) | 
 				 ( (headr[3] & 0x1F) << 11) ) & 0xffff;
-
+		
 	if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
-
+	
         pic->picture_header_parameter = ( headr[3] & 0xe0 ) | 
 		((headr[4] & 0x80) >> 3);
 
         if ( pct == B_FRAME ){
                 pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
-        }
+	}
 	if (pr) printk( " pic head param: 0x%x", 
 			pic->picture_header_parameter);
 
 	return pct;
-} 
-
+}
+#endif
 
+#if 0
 /* needs 4 byte input */
+static
 int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr)
 {
 	if (pr) printk("GOP header: "); 
@@ -556,20 +130,23 @@
                 pic->closed_gop = 1;
         } else {
                 pic->closed_gop = 0;
-        }
+	}
 	if (pr) printk("closed: %d", pic->closed_gop); 
 
         if ( ( headr[3] & 0x20 ) != 0 ){
                 pic->broken_link = 1;
-        } else {
+	} else {
                 pic->broken_link = 0;
-        }
+	}
 	if (pr) printk(" broken: %d\n", pic->broken_link); 
 
 	return 0;
 }
+#endif
 
+#if 0
 /* needs 8 byte input */
+static
 int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr)
 {
         int sw;
@@ -583,37 +160,37 @@
         sw = (int)((headr[3]&0xF0) >> 4) ;
 
         switch( sw ){
-	case 1:
+		case 1:
 		if (pr)
 			printk("Videostream: ASPECT: 1:1");
 		vi->aspect_ratio = 100;        
-		break;
-	case 2:
+			break;
+		case 2:
 		if (pr)
 			printk("Videostream: ASPECT: 4:3");
                 vi->aspect_ratio = 133;        
-		break;
-	case 3:
+			break;
+		case 3:
 		if (pr)
 			printk("Videostream: ASPECT: 16:9");
                 vi->aspect_ratio = 177;        
-		break;
+				break;
 	case 4:
 		if (pr)
 			printk("Videostream: ASPECT: 2.21:1");
                 vi->aspect_ratio = 221;        
-		break;
+				break;
 
         case 5 ... 15:
 		if (pr)
 			printk("Videostream: ASPECT: reserved");
                 vi->aspect_ratio = 0;        
-		break;
-
+			break;
+			
         default:
                 vi->aspect_ratio = 0;        
                 return -1;
-	}
+			}
 
 	if (pr)
 		printk("  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
@@ -644,29 +221,29 @@
 			printk("  FRate: 29.97 fps");
                 vi->framerate = 29970;
 		form = VIDEO_MODE_NTSC;
-		break;
-	case 5:
+			break;
+		case 5:
 		if (pr)
 			printk("  FRate: 30 fps");
                 vi->framerate = 30000;
 		form = VIDEO_MODE_NTSC;
-		break;
-	case 6:
+			break;
+		case 6:
 		if (pr)
 			printk("  FRate: 50 fps");
                 vi->framerate = 50000;
 		form = VIDEO_MODE_PAL;
-		break;
-	case 7:
+			break;
+		case 7:
 		if (pr)
 			printk("  FRate: 60 fps");
                 vi->framerate = 60000;
 		form = VIDEO_MODE_NTSC;
-		break;
-	}
-
+			break;
+			}
+			
 	vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
-	
+
         vi->vbv_buffer_size
                 = (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
 
@@ -680,13 +257,17 @@
 
 	return 0;
 }
+#endif
 
+			
+#if 0
+static
 int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr)
 {
 	uint8_t *headr;
 	int found = 0;
 	int c = 0;
-
+			
 	while (found < 4 && c+4 < count){
 		uint8_t *b;
 
@@ -696,7 +277,7 @@
 		else {
 			c++;
 		}
-	}
+			}
 
 	if (! found) return -1;
 	c += 4;
@@ -706,7 +287,11 @@
 	vi->off = c-4;
 	return 0;
 }
+#endif
+			
 
+#if 0
+static
 int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
 {
 	uint8_t *headr;
@@ -721,9 +306,9 @@
 		if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
 			found = 2;
 		else {
-			c++;
-		}
-	}	
+					c++;
+				}
+			}
 
 	if (!found) return -1;
 
@@ -745,7 +330,7 @@
 			printk("  BRate: reserved");
 		else
 			printk("  BRate: %d kb/s", ai->bit_rate/1000);
-	}
+				}
 
 	fr = (headr[2] & 0x0c ) >> 2;
 	ai->frequency = freq[fr]*100;
@@ -755,11 +340,13 @@
 		else
 			printk("  Freq: %d kHz\n",ai->frequency); 
 			       
-	}
+				}
 	ai->off = c;
 	return 0;
 }
-
+#endif
+				
+static
 int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr)
 {
 	uint8_t *headr;
@@ -767,27 +354,27 @@
 	int c = 0;
 	uint8_t frame = 0;
 	int fr = 0;
-	
+				
 	while ( !found  && c < count){
 		uint8_t *b = mbuf+c;
-
+					
 		if ( b[0] == 0x0b &&  b[1] == 0x77 )
 			found = 1;
 		else {
-			c++;
-		}
-	}	
-
+					c++;
+				}
+				}
+				
 	if (!found) return -1;
 	if (pr)
 		printk("Audiostream: AC3");
-
+				
 	ai->off = c;
 	if (c+5 >= count) return -1;
-
+			
 	ai->layer = 0;  // 0 for AC3
         headr = mbuf+c+2;
-
+			
 	frame = (headr[2]&0x3f);
 	ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
 
@@ -809,6 +396,9 @@
 	return 0;
 }
 
+
+#if 0
+static
 uint8_t *skip_pes_header(uint8_t **bufp)
 {
         uint8_t *inbuf = *bufp;
@@ -816,10 +406,10 @@
         uint8_t *pts = NULL;
         int skip = 0;
 
-int mpeg1_skip_table[16] = {
-        1, 0xffff,      5,     10, 0xffff, 0xffff, 0xffff, 0xffff,
-        0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
-};
+	static const int mpeg1_skip_table[16] = {
+        	1, 0xffff,      5,     10, 0xffff, 0xffff, 0xffff, 0xffff,
+	        0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
+	};
 
 
         if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
@@ -830,8 +420,8 @@
         } else {        /* mpeg1 */
                 for (buf = inbuf + 6; *buf == 0xff; buf++)
                         if (buf == inbuf + 6 + 16) {
-                                break;
-                        }
+				break;
+		}
                 if ((*buf & 0xc0) == 0x40)
                         buf += 2;
                 skip = mpeg1_skip_table [*buf >> 4];
@@ -843,9 +433,11 @@
 
         *bufp = buf;
         return pts;
-}
-
+} 
+#endif
 
+#if 0
+static
 void initialize_quant_matrix( uint32_t *matrix )
 {
         int i;
@@ -870,7 +462,10 @@
         for ( i = 16 ; i < 32 ; i++ )
                 matrix[i] = 0x10101010;
 }
+#endif
 
+#if 0
+static
 void initialize_mpg_picture(mpg_picture *pic)
 {
         int i;
@@ -895,8 +490,10 @@
 	pic->gop_flag = 0;              
         pic->sequence_end_flag = 0;	
 }
+#endif
 
-
+#if 0
+static
 void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic )
 {
         int16_t last_h_offset;
@@ -912,7 +509,7 @@
                 pic->progressive_frame = 1;
                 pic->picture_coding_parameter = 0x000010;
         }
-
+    
         /* Reset flag */
         pic->picture_display_extension_flag[field_type] = 0;
 
@@ -930,9 +527,12 @@
         } else {
                 pic->frame_centre_horizontal_offset[3] = last_h_offset;
                 pic->frame_centre_vertical_offset[3] = last_v_offset;
-        }
+	}
 }
+#endif
 
+#if 0
+static
 void init_mpg_picture( mpg_picture *pic, int chan, int32_t field_type)
 {
         pic->picture_header = 0;
@@ -960,3 +560,442 @@
         pic->last_frame_centre_vertical_offset = 0;
 	pic->channel = chan;
 }
+#endif
+
+void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid, 
+			    dvb_filter_pes2ts_cb_t *cb, void *priv)
+{
+	unsigned char *buf=p2ts->buf;
+	
+	buf[0]=0x47;
+	buf[1]=(pid>>8);
+	buf[2]=pid&0xff;
+	p2ts->cc=0;
+	p2ts->cb=cb;
+	p2ts->priv=priv;
+}
+
+int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len)
+{
+	unsigned char *buf=p2ts->buf;
+	int ret=0, rest;
+
+	//len=6+((pes[4]<<8)|pes[5]);
+
+	buf[1]|=0x40;
+	while (len>=184) {
+		buf[3]=0x10|((p2ts->cc++)&0x0f);
+		memcpy(buf+4, pes, 184);
+		if ((ret=p2ts->cb(p2ts->priv, buf)))
+			return ret;
+		len-=184; pes+=184;
+		buf[1]&=~0x40;
+	}
+	if (!len)
+	return 0;
+	buf[3]=0x30|((p2ts->cc++)&0x0f);
+	rest=183-len;
+	if (rest) {
+	        buf[5]=0x00;
+		if (rest-1)
+			memset(buf+6, 0xff, rest-1);
+	}
+	buf[4]=rest;
+	memcpy(buf+5+rest, pes, len);
+	return p2ts->cb(p2ts->priv, buf);
+}
+
+void dvb_filter_ipack_reset(ipack *p)
+{
+	p->found = 0;
+	p->cid = 0;
+	p->plength = 0;
+	p->flag1 = 0;
+	p->flag2 = 0;
+	p->hlength = 0;
+	p->mpeg = 0;
+	p->check = 0;
+	p->which = 0;
+	p->done = 0;
+	p->count = 0;
+}
+
+void dvb_filter_ipack_init(ipack *p, int size,
+		void (*func)(u8 *buf, int size, void *priv))
+{
+	if ( !(p->buf = vmalloc(size*sizeof(u8))) ){
+		printk ("Couldn't allocate memory for ipack\n");
+	}
+	p->size = size;
+	p->func = func;
+	p->repack_subids = 0;
+	dvb_filter_ipack_reset(p);
+}
+
+void dvb_filter_ipack_free(ipack * p)
+{
+	if (p->buf) vfree(p->buf);
+}
+
+static
+void send_ipack(ipack *p)
+{
+	int off;
+	AudioInfo ai;
+	int ac3_off = 0;
+	int streamid=0;
+	int nframes= 0;
+	int f=0;
+
+	switch ( p->mpeg ){
+	case 2:		
+		if (p->count < 10) return;
+		p->buf[3] = p->cid;
+
+		p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8);
+		p->buf[5] = (u8)((p->count-6) & 0x00FF);
+		if (p->repack_subids && p->cid == PRIVATE_STREAM1){
+			
+			off = 9+p->buf[8];
+			streamid = p->buf[off];
+			if ((streamid & 0xF8) == 0x80){
+				ai.off = 0;
+				ac3_off = ((p->buf[off+2] << 8)| 
+					   p->buf[off+3]);
+				if (ac3_off < p->count)
+					f=get_ac3info(p->buf+off+3+ac3_off, 
+						      p->count-ac3_off, &ai,0);
+				if ( !f ){
+					nframes = (p->count-off-3-ac3_off)/ 
+						ai.framesize + 1;
+					p->buf[off+2] = (ac3_off >> 8)& 0xFF;
+					p->buf[off+3] = (ac3_off)& 0xFF;
+					p->buf[off+1] = nframes;
+					
+					ac3_off +=  nframes * ai.framesize - 
+						p->count;
+				}
+		}
+	}	
+		p->func(p->buf, p->count, p->data);
+
+		p->buf[6] = 0x80;
+		p->buf[7] = 0x00;
+		p->buf[8] = 0x00;
+		p->count = 9;
+		if (p->repack_subids && p->cid == PRIVATE_STREAM1 
+		    && (streamid & 0xF8)==0x80 ){
+			p->count += 4;
+			p->buf[9] = streamid;
+			p->buf[10] = (ac3_off >> 8)& 0xFF;
+			p->buf[11] = (ac3_off)& 0xFF;
+			p->buf[12] = 0;
+		}
+
+		break;
+	case 1:
+		if (p->count < 8) return;
+		p->buf[3] = p->cid;
+
+		p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8);
+		p->buf[5] = (u8)((p->count-6) & 0x00FF);
+		p->func(p->buf, p->count, p->data);
+
+		p->buf[6] = 0x0F;
+		p->count = 7;
+		break;
+	}
+}
+
+void dvb_filter_ipack_flush(ipack *p)
+{
+	if (p->plength != MMAX_PLENGTH-6 || p->found<=6)
+		return;
+	p->plength = p->found-6;
+	p->found = 0;
+	send_ipack(p);
+	dvb_filter_ipack_reset(p);
+}
+
+static 
+void write_ipack(ipack *p, u8 *data, int count)
+{
+	u8 headr[3] = { 0x00, 0x00, 0x01} ;
+
+	if (p->count < 6){
+		memcpy(p->buf, headr, 3);
+		p->count = 6;
+	}
+
+	if (p->count + count < p->size){
+		memcpy(p->buf+p->count, data, count);
+		p->count += count;
+	} else {
+		int rest = p->size - p->count;
+		memcpy(p->buf+p->count, data, rest);
+		p->count += rest;
+		send_ipack(p);
+		if (count - rest > 0)
+			write_ipack(p, data+rest, count-rest);
+	}
+}
+
+
+int dvb_filter_instant_repack(u8 *buf, int count, ipack *p)
+{
+	int l;
+	int c=0;
+	
+	while (c < count && (p->mpeg == 0 ||
+			     (p->mpeg == 1 && p->found < 7) ||
+			     (p->mpeg == 2 && p->found < 9))
+	       &&  (p->found < 5 || !p->done)){
+		switch ( p->found ){
+		case 0:
+		case 1:
+			if (buf[c] == 0x00) p->found++;
+			else p->found = 0;
+			c++;
+			break;
+		case 2:
+			if (buf[c] == 0x01) p->found++;
+			else if (buf[c] == 0) {
+				p->found = 2;
+			} else p->found = 0;
+			c++;
+			break;
+		case 3:
+			p->cid = 0;
+			switch (buf[c]){
+			case PROG_STREAM_MAP:
+			case PRIVATE_STREAM2:
+			case PROG_STREAM_DIR:
+			case ECM_STREAM     :
+			case EMM_STREAM     :
+			case PADDING_STREAM :
+			case DSM_CC_STREAM  :
+			case ISO13522_STREAM:
+				p->done = 1;
+			case PRIVATE_STREAM1:
+			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+				p->found++;
+				p->cid = buf[c];
+				c++;
+				break;
+			default:
+				p->found = 0;
+				break;
+			}
+			break;
+
+		case 4:
+			if (count-c > 1){
+				p->plen[0] = buf[c];
+			c++;
+				p->plen[1] = buf[c];
+				c++;
+				p->found+=2;
+				p->plength=(p->plen[0]<<8)|p->plen[1];
+ 			} else {
+				p->plen[0] = buf[c];
+				p->found++;
+				return count;
+		}
+			break;
+		case 5:
+			p->plen[1] = buf[c];
+			c++;
+			p->found++;
+			p->plength=(p->plen[0]<<8)|p->plen[1];
+			break;
+		case 6:
+			if (!p->done){
+				p->flag1 = buf[c];
+				c++;
+				p->found++;
+				if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2;
+				else {
+					p->hlength = 0;
+					p->which = 0;
+					p->mpeg = 1;
+					p->flag2 = 0;
+	}	
+			}
+			break;
+
+		case 7:
+			if ( !p->done && p->mpeg == 2) {
+				p->flag2 = buf[c];
+				c++;
+				p->found++;
+			}	
+			break;
+
+		case 8:
+			if ( !p->done && p->mpeg == 2) {
+				p->hlength = buf[c];
+				c++;
+				p->found++;
+			}
+			break;
+
+		default:
+
+			break;
+		}
+	}
+
+	if (c == count) return count;
+
+	if (!p->plength) p->plength = MMAX_PLENGTH-6;
+
+	if ( p->done || ((p->mpeg == 2 && p->found >= 9) || 
+	     (p->mpeg == 1 && p->found >= 7)) ){
+		switch (p->cid){
+
+		case AUDIO_STREAM_S ... AUDIO_STREAM_E:			
+		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
+		case PRIVATE_STREAM1:
+
+			if (p->mpeg == 2 && p->found == 9) {
+				write_ipack(p, &p->flag1, 1);
+				write_ipack(p, &p->flag2, 1);
+				write_ipack(p, &p->hlength, 1);
+			}
+
+			if (p->mpeg == 1 && p->found == 7) 
+				write_ipack(p, &p->flag1, 1);
+
+			if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&  
+			    p->found < 14) {
+				while (c < count && p->found < 14) {
+					p->pts[p->found-9] = buf[c];
+					write_ipack(p, buf+c, 1);
+					c++;
+					p->found++;
+                        }
+				if (c == count) return count;
+        }
+
+			if (p->mpeg == 1 && p->which < 2000) {
+
+				if (p->found == 7) {
+					p->check = p->flag1;
+					p->hlength = 1;
+				}
+
+				while (!p->which && c < count && 
+				       p->check == 0xFF){
+					p->check = buf[c];
+					write_ipack(p, buf+c, 1);
+					c++;
+					p->found++;
+					p->hlength++;
+				}
+
+				if ( c == count) return count;
+
+				if ( (p->check & 0xC0) == 0x40 && !p->which){
+					p->check = buf[c];
+					write_ipack(p, buf+c, 1);
+					c++;
+					p->found++;
+					p->hlength++;
+
+					p->which = 1;
+					if ( c == count) return count;
+					p->check = buf[c];
+					write_ipack(p, buf+c, 1);
+					c++;
+					p->found++;
+					p->hlength++;
+					p->which = 2;
+					if ( c == count) return count;
+				}
+
+				if (p->which == 1){
+					p->check = buf[c];
+					write_ipack(p, buf+c, 1);
+					c++;
+					p->found++;
+					p->hlength++;
+					p->which = 2;
+					if ( c == count) return count;
+        }
+
+				if ( (p->check & 0x30) && p->check != 0xFF){
+					p->flag2 = (p->check & 0xF0) << 2;
+					p->pts[0] = p->check;
+					p->which = 3;
+				} 
+
+				if ( c == count) return count;
+				if (p->which > 2){
+					if ((p->flag2 & PTS_DTS_FLAGS)
+					    == PTS_ONLY){
+						while (c < count && 
+						       p->which < 7){
+							p->pts[p->which-2] =
+								buf[c];
+							write_ipack(p,buf+c,1);
+							c++;
+							p->found++;
+							p->which++;
+							p->hlength++;
+						}
+						if ( c == count) return count;
+					} else if ((p->flag2 & PTS_DTS_FLAGS) 
+						   == PTS_DTS){
+						while (c < count && 
+						       p->which< 12){
+							if (p->which< 7)
+								p->pts[p->which
+								      -2] =
+									buf[c];
+							write_ipack(p,buf+c,1);
+							c++;
+							p->found++;
+							p->which++;
+							p->hlength++;
+						}
+						if ( c == count) return count;
+					}
+					p->which = 2000;
+				}
+
+			}
+
+			while (c < count && p->found < p->plength+6){
+				l = count -c;
+				if (l+p->found > p->plength+6)
+					l = p->plength+6-p->found;
+				write_ipack(p, buf+c, l);
+				p->found += l;
+				c += l;
+			}	
+
+			break;
+        }
+
+
+		if ( p->done ){
+			if( p->found + count - c < p->plength+6){
+				p->found += count-c;
+				c = count;
+        } else {
+				c += p->plength+6 - p->found;
+				p->found = p->plength+6;
+			}
+        }
+
+		if (p->plength && p->found == p->plength+6) {
+			send_ipack(p);
+			dvb_filter_ipack_reset(p);
+			if (c < count)
+				dvb_filter_instant_repack(buf+c, count-c, p);
+		}
+	}
+	return count;
+}
+
diff -Nru a/drivers/media/dvb/dvb-core/dvb_filter.h b/drivers/media/dvb/dvb-core/dvb_filter.h
--- a/drivers/media/dvb/dvb-core/dvb_filter.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/dvb-core/dvb_filter.h	Wed Nov 27 14:36:28 2002
@@ -6,18 +6,18 @@
 
 #include "demux.h"
 
-typedef int (pes2ts_cb_t) (void *, unsigned char *);
+typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
 
-typedef struct pes2ts_s {
+typedef struct dvb_filter_pes2ts_s {
 	unsigned char buf[188];
         unsigned char cc;
-        pes2ts_cb_t *cb;
+        dvb_filter_pes2ts_cb_t *cb;
 	void *priv;
-} pes2ts_t;
+} dvb_filter_pes2ts_t;
 
-void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, 
-		 pes2ts_cb_t *cb, void *priv);
-int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len);
+void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid, 
+		 	    dvb_filter_pes2ts_cb_t *cb, void *priv);
+int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len);
 
 
 #define PROG_STREAM_MAP  0xBC
@@ -224,26 +224,11 @@
 } AudioInfo;
 
 
-void reset_ipack(ipack *p);
-int instant_repack(u8 *buf, int count, ipack *p);
-void init_ipack(ipack *p, int size,
+void dvb_filter_ipack_reset(ipack *p);
+int dvb_filter_instant_repack(u8 *buf, int count, ipack *p);
+void dvb_filter_ipack_init(ipack *p, int size,
 		void (*func)(u8 *buf,  int size, void *priv));
-void free_ipack(ipack * p);
-void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, 
-		  void (*pes_write)(u8 *buf, int count, void *data),
-		  void *priv);
-void ts_to_pes(ipack *p, u8 *buf); 
-void send_ipack(ipack *p);
-void send_ipack_rest(ipack *p);
-int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr);
-int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr);
-int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr);
-uint8_t *skip_pes_header(uint8_t **bufp);
-void initialize_quant_matrix( uint32_t *matrix );
-void initialize_mpg_picture(mpg_picture *pic);
-void init_mpg_picture( mpg_picture *pic, int chan, int32_t field_type);
-void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic );
-int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr);
-int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr);
-int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr);
+void dvb_filter_ipack_free(ipack * p);
+void dvb_filter_ipack_flush(ipack *p);
+
 #endif
diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c	Wed Nov 27 14:36:28 2002
@@ -83,7 +83,7 @@
 
 struct dvb_frontend_ioctl_data {
 	struct list_head list_head;
-	struct dvb_adapter_s *adapter;
+	struct dvb_adapter *adapter;
 	int (*before_ioctl) (struct dvb_frontend *frontend,
 			     unsigned int cmd, void *arg);
 	int (*after_ioctl)  (struct dvb_frontend *frontend,
@@ -336,9 +336,6 @@
 	struct dvb_frontend *frontend = &fe->frontend;
 	int err;
 
-	dprintk ("%s: f == %i, drift == %i\n",
-		 __FUNCTION__, param->frequency, fe->lnb_drift);
-
 	dvb_bend_frequency (fe, 0);
 
 	if (first_trial) {
@@ -352,6 +349,9 @@
 			sizeof (struct dvb_frontend_parameters));
 	}
 
+	dprintk ("%s: f == %i, drift == %i\n",
+		 __FUNCTION__, param->frequency, fe->lnb_drift);
+
 	param->frequency += fe->lnb_drift + fe->bending;
 	err = dvb_frontend_internal_ioctl (frontend, FE_SET_FRONTEND, param);
 	param->frequency -= fe->lnb_drift + fe->bending;
@@ -367,9 +367,8 @@
 	struct dvb_frontend *frontend = &fe->frontend;
 	struct dvb_frontend_parameters *init_param;
 
-	printk ("%s: initialising frontend %i:%i (%s)...\n", __FUNCTION__,
-		frontend->i2c->adapter->num, frontend->i2c->id,
-		fe->info->name);
+	printk ("DVB: initialising frontend %i:%i (%s)...\n",
+		frontend->i2c->adapter->num, frontend->i2c->id, fe->info->name);
 
 	dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL);
 
@@ -436,15 +435,20 @@
 	 */
 	{
 		int j = fe->lost_sync_count;
-		int stepsize = fe->info->frequency_stepsize;
-
-		if (j % 32 == 0)
-			fe->lnb_drift = 0;
+		int stepsize;
 		
-		if (j % 2)
-			fe->lnb_drift += stepsize * ((j+1)/2);
+		if (fe->info->type == FE_QPSK)
+			stepsize = fe->parameters.u.qpsk.symbol_rate / 16000;
 		else
+			stepsize = fe->info->frequency_stepsize * 2;
+
+		if (j % 32 == 0) {
+			fe->lnb_drift = 0;
+		} else {
 			fe->lnb_drift = -fe->lnb_drift;
+			if (j % 2)
+				fe->lnb_drift += stepsize;
+		}
 
 		dvb_frontend_set_parameters (fe, &fe->parameters, 0);
 	}
@@ -511,7 +515,8 @@
 			fe->lost_sync_count = 0;
 		} else {
 			fe->lost_sync_count++;
-
+			if (fe->lost_sync_count < 10)  /* XXX FIXME CHECKME! */
+				continue;
 			dvb_frontend_recover (fe);
 			delay = HZ/5;
 			if (jiffies - fe->lost_sync_jiffies > TIMEOUT) {
@@ -627,7 +632,7 @@
 static
 int dvb_frontend_open (struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev = file->private_data;
+	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend_data *fe = dvbdev->priv;
 	int ret;
 
@@ -648,7 +653,7 @@
 static
 int dvb_frontend_release (struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev = file->private_data;
+	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend_data *fe = dvbdev->priv;
 
 	dprintk ("%s\n", __FUNCTION__);
@@ -661,7 +666,7 @@
 
 
 int
-dvb_add_frontend_ioctls (struct dvb_adapter_s *adapter,
+dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
                          int (*before_ioctl) (struct dvb_frontend *frontend,
                                               unsigned int cmd, void *arg),
                          int (*after_ioctl)  (struct dvb_frontend *frontend,
@@ -715,7 +720,7 @@
 
 
 void
-dvb_remove_frontend_ioctls (struct dvb_adapter_s *adapter,
+dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
 			    int (*before_ioctl) (struct dvb_frontend *frontend,
                                                  unsigned int cmd, void *arg),
                             int (*after_ioctl)  (struct dvb_frontend *frontend,
@@ -748,7 +753,7 @@
 
 
 int
-dvb_add_frontend_notifier (struct dvb_adapter_s *adapter,
+dvb_add_frontend_notifier (struct dvb_adapter *adapter,
 			   void (*callback) (fe_status_t s, void *data),
 			   void *data)
 {
@@ -791,7 +796,7 @@
 
 
 void
-dvb_remove_frontend_notifier (struct dvb_adapter_s *adapter,
+dvb_remove_frontend_notifier (struct dvb_adapter *adapter,
 			      void (*callback) (fe_status_t s, void *data))
 {
         struct list_head *entry;
@@ -827,11 +832,11 @@
 
 static
 struct file_operations dvb_frontend_fops = {
-        owner:          THIS_MODULE,
-        ioctl:          dvb_generic_ioctl,
-	poll:		dvb_frontend_poll,
-        open:           dvb_frontend_open,
-        release:        dvb_frontend_release
+	.owner		= THIS_MODULE,
+	.ioctl		= dvb_generic_ioctl,
+	.poll		= dvb_frontend_poll,
+	.open		= dvb_frontend_open,
+	.release	= dvb_frontend_release
 };
 
 
@@ -845,9 +850,11 @@
 {
 	struct list_head *entry;
 	struct dvb_frontend_data *fe;
-	dvb_device_t dvbdev_template = { users: 1, writers: 1,
-					 fops: &dvb_frontend_fops,
-					 kernel_ioctl: dvb_frontend_ioctl
+	static const struct dvb_device dvbdev_template = {
+		.users = 1,
+		.writers = 1,
+		.fops = &dvb_frontend_fops,
+		.kernel_ioctl = dvb_frontend_ioctl
 	};
 
 	dprintk ("%s\n", __FUNCTION__);
@@ -878,7 +885,9 @@
 	list_for_each (entry, &frontend_ioctl_list) {
 		struct dvb_frontend_ioctl_data *ioctl;
 
-		ioctl = list_entry (entry, struct dvb_frontend_ioctl_data, list_head);
+		ioctl = list_entry (entry,
+				    struct dvb_frontend_ioctl_data,
+				    list_head);
 
 		if (ioctl->adapter == i2c->adapter) {
 			fe->frontend.before_ioctl = ioctl->before_ioctl;
@@ -936,3 +945,4 @@
 MODULE_PARM(dvb_shutdown_timeout,"i");
 MODULE_PARM_DESC(dvb_frontend_debug, "enable verbose debug messages");
 MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
+
diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h	Wed Nov 27 14:36:32 2002
@@ -90,7 +90,7 @@
  *  Return value: number of frontends where the ioctl's were applied.
  */
 extern int
-dvb_add_frontend_ioctls (struct dvb_adapter_s *adapter,
+dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
 			 int (*before_ioctl) (struct dvb_frontend *frontend,
 					      unsigned int cmd, void *arg),
 			 int (*after_ioctl)  (struct dvb_frontend *frontend,
@@ -99,18 +99,18 @@
 
 
 extern void
-dvb_remove_frontend_ioctls (struct dvb_adapter_s *adapter,
+dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
 			    int (*before_ioctl) (struct dvb_frontend *frontend,
 					         unsigned int cmd, void *arg),
 			    int (*after_ioctl)  (struct dvb_frontend *frontend,
 					         unsigned int cmd, void *arg));
 
 extern int
-dvb_add_frontend_notifier (struct dvb_adapter_s *adapter,
+dvb_add_frontend_notifier (struct dvb_adapter *adapter,
 			   void (*callback) (fe_status_t s, void *data),
 			   void *data);
 extern void
-dvb_remove_frontend_notifier (struct dvb_adapter_s *adapter,
+dvb_remove_frontend_notifier (struct dvb_adapter *adapter,
 			      void (*callback) (fe_status_t s, void *data));
 
 #endif
diff -Nru a/drivers/media/dvb/dvb-core/dvb_i2c.c b/drivers/media/dvb/dvb-core/dvb_i2c.c
--- a/drivers/media/dvb/dvb-core/dvb_i2c.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/dvb/dvb-core/dvb_i2c.c	Wed Nov 27 14:36:31 2002
@@ -173,7 +173,7 @@
 dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
 				   struct i2c_msg msgs[], int num),
 		      void *data,
-		      struct dvb_adapter_s *adapter,
+		      struct dvb_adapter *adapter,
 		      int id)
 {
 	struct dvb_i2c_bus *i2c;
@@ -200,7 +200,7 @@
 struct dvb_i2c_bus*
 dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
                                    struct i2c_msg msgs[], int num),
-                  struct dvb_adapter_s *adapter,
+                  struct dvb_adapter *adapter,
 		  int id)
 {
 	struct list_head *entry;
@@ -231,7 +231,7 @@
 
 void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
 					  struct i2c_msg msgs[], int num),
-			     struct dvb_adapter_s *adapter,
+			     struct dvb_adapter *adapter,
 			     int id)
 {
 	struct dvb_i2c_bus *i2c = dvb_find_i2c_bus (xfer, adapter, id);
diff -Nru a/drivers/media/dvb/dvb-core/dvb_i2c.h b/drivers/media/dvb/dvb-core/dvb_i2c.h
--- a/drivers/media/dvb/dvb-core/dvb_i2c.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/dvb-core/dvb_i2c.h	Wed Nov 27 14:36:28 2002
@@ -32,7 +32,7 @@
 	struct list_head list_head;
 	int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num);
 	void *data;
-	struct dvb_adapter_s *adapter;
+	struct dvb_adapter *adapter;
 	int id;
 	struct list_head client_list;
 };
@@ -43,13 +43,13 @@
 						       struct i2c_msg msgs[],
 						       int num),
 					  void *data,
-					  struct dvb_adapter_s *adapter,
+					  struct dvb_adapter *adapter,
 					  int id);
 
 extern
 void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
 					  struct i2c_msg msgs[], int num),
-			     struct dvb_adapter_s *adapter,
+			     struct dvb_adapter *adapter,
 			     int id);
 
 
diff -Nru a/drivers/media/dvb/dvb-core/dvb_ksyms.c b/drivers/media/dvb/dvb-core/dvb_ksyms.c
--- a/drivers/media/dvb/dvb-core/dvb_ksyms.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/media/dvb/dvb-core/dvb_ksyms.c	Wed Nov 27 14:36:32 2002
@@ -9,11 +9,12 @@
 #include "dvb_net.h"
 
 
-EXPORT_SYMBOL(DmxDevInit);
-EXPORT_SYMBOL(DmxDevRelease);
-EXPORT_SYMBOL(DvbDmxInit);
-EXPORT_SYMBOL(DvbDmxRelease);
-EXPORT_SYMBOL(DvbDmxSWFilterPackets);
+EXPORT_SYMBOL(dvb_dmxdev_init);
+EXPORT_SYMBOL(dvb_dmxdev_release);
+EXPORT_SYMBOL(dvb_dmx_init);
+EXPORT_SYMBOL(dvb_dmx_release);
+EXPORT_SYMBOL(dvb_dmx_swfilter_packet);
+EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 
 EXPORT_SYMBOL(dvb_register_frontend);
 EXPORT_SYMBOL(dvb_unregister_frontend);
@@ -37,13 +38,12 @@
 EXPORT_SYMBOL(dvb_generic_ioctl);
 EXPORT_SYMBOL(dvb_generic_open);
 EXPORT_SYMBOL(dvb_generic_release);
-EXPORT_SYMBOL(generic_usercopy);
 
-EXPORT_SYMBOL(init_ipack);
-EXPORT_SYMBOL(reset_ipack);
-EXPORT_SYMBOL(free_ipack);
-EXPORT_SYMBOL(send_ipack_rest);
-EXPORT_SYMBOL(instant_repack);
-EXPORT_SYMBOL(pes2ts_init);
-EXPORT_SYMBOL(pes2ts);
+EXPORT_SYMBOL(dvb_filter_ipack_init);
+EXPORT_SYMBOL(dvb_filter_ipack_reset);
+EXPORT_SYMBOL(dvb_filter_ipack_free);
+EXPORT_SYMBOL(dvb_filter_ipack_flush);
+EXPORT_SYMBOL(dvb_filter_instant_repack);
+EXPORT_SYMBOL(dvb_filter_pes2ts_init);
+EXPORT_SYMBOL(dvb_filter_pes2ts);
 
diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
--- a/drivers/media/dvb/dvb-core/dvb_net.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/dvb-core/dvb_net.c	Wed Nov 27 14:36:28 2002
@@ -435,7 +435,7 @@
 int dvb_net_ioctl(struct inode *inode, struct file *file, 
 		  unsigned int cmd, void *parg)
 {
-	dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;
+	struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
 	dvb_net_t *dvbnet=(dvb_net_t *) dvbdev->priv;
 
 	if (((file->f_flags&O_ACCMODE)==O_RDONLY))
@@ -462,21 +462,18 @@
 }
 
 static struct file_operations dvb_net_fops = {
-	owner:		THIS_MODULE,
-        read:		0,
-	write:		0,
-	ioctl:		dvb_generic_ioctl,
-	open:		dvb_generic_open,
-	release:	dvb_generic_release,
-	poll:		0,
+	.owner		= THIS_MODULE,
+	.ioctl		= dvb_generic_ioctl,
+	.open		= dvb_generic_open,
+	.release	= dvb_generic_release,
 };
 
-static dvb_device_t dvbdev_net = {
-        priv: 0,
-        users: 1,
-        writers: 1,
-        fops: &dvb_net_fops,
-        kernel_ioctl: dvb_net_ioctl,
+static struct dvb_device dvbdev_net = {
+	.priv		= 0,
+	.users		= 1,
+	.writers	= 1,
+	.fops		= &dvb_net_fops,
+	.kernel_ioctl	= dvb_net_ioctl,
 };
 
 void
@@ -493,7 +490,7 @@
 }
 
 int
-dvb_net_init(dvb_adapter_t *adap, dvb_net_t *dvbnet, dmx_demux_t *demux)
+dvb_net_init(struct dvb_adapter *adap, dvb_net_t *dvbnet, dmx_demux_t *demux)
 {
 	int i;
 		
diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h
--- a/drivers/media/dvb/dvb-core/dvb_net.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/media/dvb/dvb-core/dvb_net.h	Wed Nov 27 14:36:27 2002
@@ -47,7 +47,7 @@
 } dvb_net_priv_t;
 
 typedef struct dvb_net_s {
-	dvb_device_t *dvbdev;
+	struct dvb_device *dvbdev;
 
 	int card_num;
 	int dev_num;
@@ -58,6 +58,6 @@
 
 
 void dvb_net_release(dvb_net_t *);
-int  dvb_net_init(dvb_adapter_t *, dvb_net_t *, dmx_demux_t *);
+int  dvb_net_init(struct dvb_adapter *, dvb_net_t *, dmx_demux_t *);
 
 #endif
diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
--- a/drivers/media/dvb/dvb-core/dvbdev.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/dvb-core/dvbdev.c	Wed Nov 27 14:36:28 2002
@@ -37,6 +37,7 @@
 #include <asm/system.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
+#include <linux/videodev.h>
 
 #include "compat.h"
 #include "dvbdev.h"
@@ -69,17 +70,17 @@
 
 
 static
-dvb_device_t* dvbdev_find_device (int minor)
+struct dvb_device* dvbdev_find_device (int minor)
 {
 	struct list_head *entry;
 
 	list_for_each (entry, &dvb_adapter_list) {
 		struct list_head *entry0;
-		dvb_adapter_t *adap;
-		adap = list_entry (entry, dvb_adapter_t, list_head);
+		struct dvb_adapter *adap;
+		adap = list_entry (entry, struct dvb_adapter, list_head);
 		list_for_each (entry0, &adap->device_list) {
-			dvb_device_t *dev;
-			dev = list_entry (entry0, dvb_device_t, list_head);
+			struct dvb_device *dev;
+			dev = list_entry (entry0, struct dvb_device, list_head);
 			if (nums2minor(adap->num, dev->type, dev->id) == minor)
 				return dev;
 		}
@@ -92,7 +93,7 @@
 static
 int dvb_device_open(struct inode *inode, struct file *file)
 {
-	dvb_device_t *dvbdev;
+	struct dvb_device *dvbdev;
 	
 	dvbdev = dvbdev_find_device (minor(inode->i_rdev));
 
@@ -118,13 +119,8 @@
 
 static struct file_operations dvb_device_fops =
 {
-	owner:		THIS_MODULE,
-        read:		NULL,
-	write:		NULL,
-	ioctl:		NULL,
-	open:		dvb_device_open,
-	release:	NULL,
-	poll:		NULL,
+	.owner =	THIS_MODULE,
+	.open =		dvb_device_open,
 };
 #endif /* CONFIG_DVB_DEVFS_ONLY */
 
@@ -132,7 +128,7 @@
 
 int dvb_generic_open(struct inode *inode, struct file *file)
 {
-        dvb_device_t *dvbdev = file->private_data;
+        struct dvb_device *dvbdev = file->private_data;
 
         if (!dvbdev)
                 return -ENODEV;
@@ -153,7 +149,7 @@
 
 int dvb_generic_release(struct inode *inode, struct file *file)
 {
-        dvb_device_t *dvbdev = file->private_data;
+        struct dvb_device *dvbdev = file->private_data;
 
 	if (!dvbdev)
                 return -ENODEV;
@@ -166,73 +162,10 @@
 }
 
 
-/*
- * helper function -- handles userspace copying for ioctl arguments
- */
-int
-generic_usercopy(struct inode *inode, struct file *file,
-		 unsigned int cmd, unsigned long arg,
-		 int (*func)(struct inode *inode, struct file *file,
-			     unsigned int cmd, void *arg))
-{
-	char	sbuf[128];
-	void    *mbuf = NULL;
-	void	*parg = NULL;
-	int	err  = -EINVAL;
-
-	/*  Copy arguments into temp kernel buffer  */
-	switch (_IOC_DIR(cmd)) {
-	case _IOC_NONE:
-		parg = (void *)arg;
-		break;
-	case _IOC_READ: /* some v4l ioctls are marked wrong ... */
-	case _IOC_WRITE:
-	case (_IOC_WRITE | _IOC_READ):
-		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
-			parg = sbuf;
-		} else {
-			/* too big to allocate from stack */
-			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
-			if (NULL == mbuf)
-				return -ENOMEM;
-			parg = mbuf;
-		}
-		
-		err = -EFAULT;
-		if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd)))
-			goto out;
-		break;
-	}
-
-	/* call driver */
-	if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD)
-		err = -EINVAL;
-
-	if (err < 0)
-		goto out;
-
-	/*  Copy results into user buffer  */
-	switch (_IOC_DIR(cmd))
-	{
-	case _IOC_READ:
-	case (_IOC_WRITE | _IOC_READ):
-		if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd)))
-			err = -EFAULT;
-		break;
-	}
-
-out:
-	if (mbuf)
-		kfree(mbuf);
-
-	return err;
-}
-
-
 int dvb_generic_ioctl(struct inode *inode, struct file *file,
 		      unsigned int cmd, unsigned long arg)
 {
-        dvb_device_t *dvbdev = file->private_data;
+        struct dvb_device *dvbdev = file->private_data;
 	
         if (!dvbdev)
 	        return -ENODEV;
@@ -240,20 +173,20 @@
 	if (!dvbdev->kernel_ioctl)
 		return -EINVAL;
 
-	return generic_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl);
+	return video_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl);
 }
 
 
 static
-int dvbdev_get_free_id (struct dvb_adapter_s *adap, int type)
+int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
 {
 	u32 id = 0;
 
 	while (id < DVB_MAX_IDS) {
 		struct list_head *entry;
 		list_for_each (entry, &adap->device_list) {
-			dvb_device_t *dev;
-			dev = list_entry (entry, dvb_device_t, list_head);
+			struct dvb_device *dev;
+			dev = list_entry (entry, struct dvb_device, list_head);
 			if (dev->type == type && dev->id == id)
 				goto skip;
 		}
@@ -265,12 +198,12 @@
 }
 
 
-int dvb_register_device(dvb_adapter_t *adap, dvb_device_t **pdvbdev, 
-			dvb_device_t *template, void *priv, int type)
+int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, 
+			const struct dvb_device *template, void *priv, int type)
 {
 	u32 id;
 	char name [20];
-	dvb_device_t *dvbdev;
+	struct dvb_device *dvbdev;
 
 	if (down_interruptible (&dvbdev_register_lock))
 		return -ERESTARTSYS;
@@ -282,7 +215,7 @@
 		return -ENFILE;
 	}
 
-	*pdvbdev = dvbdev = kmalloc(sizeof(dvb_device_t), GFP_KERNEL);
+	*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
 
 	if (!dvbdev) {
 		up(&dvbdev_register_lock);
@@ -291,7 +224,7 @@
 
 	up (&dvbdev_register_lock);
 	
-	memcpy(dvbdev, template, sizeof(dvb_device_t));
+	memcpy(dvbdev, template, sizeof(struct dvb_device));
 	dvbdev->type = type;
 	dvbdev->id = id;
 	dvbdev->adapter = adap;
@@ -307,15 +240,15 @@
 					      S_IFCHR | S_IRUSR | S_IWUSR,
 					      dvbdev->fops, dvbdev);
 
-	dprintk("%s: register adapter%d/%s @ minor: %i (0x%02x) - dvbdev: %p\n",
-		__FUNCTION__, adap->num, name, nums2minor(adap->num, type, id),
-		nums2minor(adap->num, type, id), dvbdev);
+	dprintk("DVB: register adapter%d/%s @ minor: %i (0x%02x)\n",
+		adap->num, name, nums2minor(adap->num, type, id),
+		nums2minor(adap->num, type, id));
 
 	return 0;
 }
 
 
-void dvb_unregister_device(dvb_device_t *dvbdev)
+void dvb_unregister_device(struct dvb_device *dvbdev)
 {
 	if (!dvbdev)
 		return;
@@ -334,8 +267,8 @@
 	while (1) {
 		struct list_head *entry;
 		list_for_each (entry, &dvb_adapter_list) {
-			dvb_adapter_t *adap;
-			adap = list_entry (entry, dvb_adapter_t, list_head);
+			struct dvb_adapter *adap;
+			adap = list_entry (entry, struct dvb_adapter, list_head);
 			if (adap->num == num)
 				goto skip;
 		}
@@ -348,10 +281,10 @@
 }
 
 
-int dvb_register_adapter(dvb_adapter_t **padap, char *name)
+int dvb_register_adapter(struct dvb_adapter **padap, char *name)
 {
 	char dirname[16];
-	dvb_adapter_t *adap;
+	struct dvb_adapter *adap;
 	int num;
 
 	if (down_interruptible (&dvbdev_register_lock))
@@ -362,17 +295,17 @@
 		return -ENFILE;
 	}
 
-	if (!(*padap = adap = kmalloc(sizeof(dvb_adapter_t), GFP_KERNEL))) {
+	if (!(*padap = adap = kmalloc(sizeof(struct dvb_adapter), GFP_KERNEL))) {
 		up(&dvbdev_register_lock);
 		return -ENOMEM;
 	}
 
-	memset (adap, 0, sizeof(dvb_adapter_t));
+	memset (adap, 0, sizeof(struct dvb_adapter));
 	INIT_LIST_HEAD (&adap->device_list);
 
 	MOD_INC_USE_COUNT;
 
-	printk ("%s: registering new adapter (%s).\n", __FUNCTION__, name);
+	printk ("DVB: registering new adapter (%s).\n", name);
 	
 	sprintf(dirname, "dvb/adapter%d", num);
 	adap->devfs_handle = devfs_mk_dir(NULL, dirname, NULL);
@@ -386,7 +319,7 @@
 }
 
 
-int dvb_unregister_adapter(dvb_adapter_t *adap)
+int dvb_unregister_adapter(struct dvb_adapter *adap)
 {
         devfs_unregister (adap->devfs_handle);
 	if (down_interruptible (&dvbdev_register_lock))
diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
--- a/drivers/media/dvb/dvb-core/dvbdev.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/dvb-core/dvbdev.h	Wed Nov 27 14:36:28 2002
@@ -43,49 +43,48 @@
 #define DVB_DEVICE_OSD        8
 
 
-typedef struct dvb_adapter_s
-{
+struct dvb_adapter {
 	int num;
 	devfs_handle_t devfs_handle;
 	struct list_head list_head;
 	struct list_head device_list;
-} dvb_adapter_t;
+};
 
 
-typedef struct dvb_device
-{
+struct dvb_device {
 	struct list_head list_head;
 	struct file_operations *fops;
 	devfs_handle_t devfs_handle;
-	dvb_adapter_t *adapter;
+	struct dvb_adapter *adapter;
 	int type;
 	u32 id;
 
 	int users;
 	int writers;
 
-	/* don't really need those !? */
+        /* don't really need those !? -- FIXME: use video_usercopy  */
 	int (*kernel_ioctl)(struct inode *inode, struct file *file,
-			    unsigned int cmd, void *arg);  // FIXME: use generic_usercopy()
+			    unsigned int cmd, void *arg);
 
 	void *priv;
-} dvb_device_t;
+};
 
 
-int dvb_register_device(dvb_adapter_t *adap, dvb_device_t **pdvbdev, 
-			dvb_device_t *template, void *priv, int type);
-void dvb_unregister_device(struct dvb_device *dvbdev);
+extern int dvb_register_adapter (struct dvb_adapter **padap, char *name);
+extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 
-int dvb_register_adapter(dvb_adapter_t **padap, char *name);
-int dvb_unregister_adapter(dvb_adapter_t *adap);
+extern int dvb_register_device (struct dvb_adapter *adap,
+				struct dvb_device **pdvbdev, 
+				const struct dvb_device *template,
+				void *priv,
+				int type);
 
-int dvb_generic_ioctl(struct inode *inode, struct file *file,
+extern void dvb_unregister_device (struct dvb_device *dvbdev);
+
+extern int dvb_generic_open (struct inode *inode, struct file *file);
+extern int dvb_generic_release (struct inode *inode, struct file *file);
+extern int dvb_generic_ioctl (struct inode *inode, struct file *file,
 		      unsigned int cmd, unsigned long arg);
-int dvb_generic_open(struct inode *inode, struct file *file);
-int dvb_generic_release(struct inode *inode, struct file *file);
-int generic_usercopy(struct inode *inode, struct file *file,
-		     unsigned int cmd, unsigned long arg,
-		     int (*func)(struct inode *inode, struct file *file,
-				 unsigned int cmd, void *arg));
 
-#endif /* #ifndef __DVBDEV_H */
+#endif /* #ifndef _DVBDEV_H_ */
+
diff -Nru a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
--- a/drivers/media/dvb/frontends/Kconfig	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/frontends/Kconfig	Wed Nov 27 14:36:28 2002
@@ -23,6 +23,30 @@
 	  DVB adapter simply enable all supported frontends, the 
 	  right one will get autodetected.
 
+config DVB_ALPS_TDLB7
+	tristate "Alps TDLB7 (OFDM)"
+	depends on DVB_CORE
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+	  This tuner module needs some microcode located in a file called 
+	  "Sc_main.mc" in the windows driver. Please pass the module parameter
+	  mcfile="/PATH/FILENAME" when loading alps_tdlb7.o.
+
+	  If you don't know what tuner module is soldered on your 
+	  DVB adapter simply enable all supported frontends, the 
+	  right one will get autodetected.
+
+config DVB_ALPS_TDMB7
+	tristate "Alps BSRV2 (OFDM)"
+	depends on DVB_CORE
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+	  If you don't know what tuner module is soldered on your 
+	  DVB adapter simply enable all supported frontends, the 
+	  right one will get autodetected.
+
 config DVB_GRUNDIG_29504_491
 	tristate "Grundig 29504-491 (QPSK)"
 	depends on DVB_CORE
diff -Nru a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
--- a/drivers/media/dvb/frontends/Makefile	Wed Nov 27 14:36:27 2002
+++ b/drivers/media/dvb/frontends/Makefile	Wed Nov 27 14:36:27 2002
@@ -6,6 +6,8 @@
 
 obj-$(CONFIG_DVB_ALPS_BSRU6) += alps_bsru6.o
 obj-$(CONFIG_DVB_ALPS_BSRV2) += alps_bsrv2.o
+obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o
+obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o
 obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o
 obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o
 obj-$(CONFIG_DVB_VES1820) += ves1820.o
diff -Nru a/drivers/media/dvb/frontends/alps_bsru6.c b/drivers/media/dvb/frontends/alps_bsru6.c
--- a/drivers/media/dvb/frontends/alps_bsru6.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/media/dvb/frontends/alps_bsru6.c	Wed Nov 27 14:36:32 2002
@@ -1,8 +1,9 @@
 /* 
-    Alps BSRU6 DVB QPSK frontend driver
+    Alps BSRU6 and LG TDQB-S00x DVB QPSK frontend driver
 
     Copyright (C) 2001-2002 Convergence Integrated Media GmbH
-	<ralph@convergence.de>, <holger@convergence.de>
+	<ralph@convergence.de>, <holger@convergence.de>,
+	<js@convergence.de>
 
     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
@@ -32,12 +33,16 @@
 
 
 #define M_CLK (88000000UL)
-
 /* M=21, K=0, P=0, f_VCO = 4MHz*4*(M+1)/(K+1) = 352 MHz */
 
+
 static
 struct dvb_frontend_info bsru6_info = {
+#ifdef CONFIG_ALPS_BSRU6_IS_LG_TDQBS00X
+	name: "LG TDQB-S00x",
+#else
 	name: "Alps BSRU6",
+#endif
 	type: FE_QPSK,
 	frequency_min: 950000,
 	frequency_max: 2150000,
@@ -63,7 +68,8 @@
 	0x05, 0x35,   // SDAT:0 SCLT:0 I2CT:1
 	0x06, 0x00,   // DAC mode and MSB 
 	0x07, 0x00,   // DAC LSB
-	0x08, 0x43,   // DiSEqC
+//	0x08, 0x43,   // DiSEqC
+	0x08, 0x03,   // DiSEqC
 	0x09, 0x00,
 	0x0a, 0x42, 
 	0x0c, 0x51,   // QPSK reverse:1  Nyquist:0 OP0 val:1 OP0 con:1 OP1 val:1 OP1 con:1 
@@ -79,17 +85,20 @@
 	0x15, 0xc9,   // lock detector threshold
 	
 	0x16, 0x1d,
-	0x17, 0x0,
+	0x17, 0x00,
 	0x18, 0x14,
 	0x19, 0xf2,
 
 	0x1a, 0x11,
 
 	0x1b, 0x9c,
-	0x1c, 0x0,
-	0x1d, 0x0,
-	0x1e, 0xb,
+	0x1c, 0x00,
+	0x1d, 0x00,
+	0x1e, 0x0b,
+	0x1f, 0x50,
 
+	0x20, 0x00,
+	0x21, 0x00,
 	0x22, 0x00,
 	0x23, 0x00,
 	0x24, 0xff,
@@ -110,16 +119,37 @@
 	0x33, 0xfc,  // rs control
 	0x34, 0x93,  // error control
 
-	
 	0x0b, 0x00, 
-	0x27, 0x00, 0x2f, 0x00, 0x30, 0x00,
-	0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 
-	0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, 
-	0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
-	0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00,
-	0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 
-	0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, 
-	0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00
+	0x27, 0x00,
+	0x2f, 0x00,
+	0x30, 0x00,
+	0x35, 0x00,
+	0x36, 0x00,
+	0x37, 0x00,
+	0x38, 0x00,
+	0x39, 0x00,
+	0x3a, 0x00,
+	0x3b, 0x00,
+	0x3c, 0x00,
+	0x3d, 0x00,
+	0x3e, 0x00,
+	0x3f, 0x00,
+	0x40, 0x00,
+	0x41, 0x00,
+	0x42, 0x00,
+	0x43, 0x00,
+	0x44, 0x00,
+	0x45, 0x00,
+	0x46, 0x00,
+	0x47, 0x00,
+	0x48, 0x00,
+	0x49, 0x00,
+	0x4a, 0x00,
+	0x4b, 0x00,
+	0x4c, 0x00,
+	0x4d, 0x00,
+	0x4e, 0x00,
+	0x4f, 0x00
 };
 
 
@@ -231,12 +261,27 @@
 
 
 static
-int stv0299_set_inversion (struct dvb_i2c_bus *i2c, int inversion)
+int stv0299_set_inversion (struct dvb_i2c_bus *i2c,
+			   fe_spectral_inversion_t inversion)
 {
 	u8 val;
 
 	dprintk ("%s\n", __FUNCTION__);
 
+#ifdef CONFIG_ALPS_BSRU6_IS_LG_TDQBS00X    /*  reversed I/Q pins  */
+	switch (inversion) {
+	case INVERSION_AUTO:
+		return -EOPNOTSUPP;
+	case INVERSION_OFF:
+		val = stv0299_readreg (i2c, 0x0c);
+		return stv0299_writereg (i2c, 0x0c, val & 0xfe);
+	case INVERSION_ON:
+		val = stv0299_readreg (i2c, 0x0c);
+		return stv0299_writereg (i2c, 0x0c, val | 0x01);
+	default:
+		return -EINVAL;
+	};
+#else
 	switch (inversion) {
 	case INVERSION_AUTO:
 		return -EOPNOTSUPP;
@@ -248,7 +293,8 @@
 		return stv0299_writereg (i2c, 0x0c, val & 0xfe);
 	default:
 		return -EINVAL;
-	}
+	};
+#endif
 }
 
 
@@ -277,9 +323,10 @@
 
 
 static
-fe_code_rate_t stv0299_get_FEC (struct dvb_i2c_bus *i2c)
+fe_code_rate_t stv0299_get_fec (struct dvb_i2c_bus *i2c)
 {
-	static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_1_2 };
+	static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6,
+					     FEC_7_8, FEC_1_2 };
 	u8 index;
 
 	dprintk ("%s\n", __FUNCTION__);
@@ -343,6 +390,9 @@
 
 	dprintk ("%s\n", __FUNCTION__);
 
+	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
+		return -ETIMEDOUT;
+
 	val = stv0299_readreg (i2c, 0x08);
 
 	if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x6))  /* DiSEqC mode */
@@ -356,12 +406,7 @@
 			return -EREMOTEIO;
 	}
 
-	/* Shouldn't we wait for idle state (FE=1, FF=0) here to 
-	   make certain all bytes have been sent ? 
-	   Hmm, actually we should do that before all mode changes too ...
-	   if (stv0299_wait_diseqc_idle (i2c, 100) < 0) */ 
-
-	if (stv0299_wait_diseqc_fifo (i2c, 100) < 0)
+	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
 		return -ETIMEDOUT;
 
 	return 0;
@@ -375,18 +420,18 @@
 
 	dprintk ("%s\n", __FUNCTION__);
 
-	val = stv0299_readreg (i2c, 0x08);
-
-	if (stv0299_wait_diseqc_fifo (i2c, 100) < 0)
+	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
 		return -ETIMEDOUT;
 
+	val = stv0299_readreg (i2c, 0x08);
+
 	if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x2))   /* burst mode */
 		return -EREMOTEIO;
 
 	if (stv0299_writereg (i2c, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff))
 		return -EREMOTEIO;
 
-	if (stv0299_wait_diseqc_fifo (i2c, 100) < 0)
+	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
 		return -ETIMEDOUT;
 
 	if (stv0299_writereg (i2c, 0x08, val))
@@ -403,6 +448,9 @@
 
 	dprintk ("%s\n", __FUNCTION__);
 
+	if (stv0299_wait_diseqc_idle (i2c, 100) < 0)
+		return -ETIMEDOUT;
+
 	val = stv0299_readreg (i2c, 0x08);
 
 	switch (tone) {
@@ -445,8 +493,6 @@
 	u32 tmp;
 	u8 aclk = 0xb4, bclk = 0x51;
 
-	dprintk ("%s\n", __FUNCTION__);
-
 	if (srate > M_CLK)
 		srate = M_CLK;
         if (srate < 500000)
@@ -479,7 +525,6 @@
 }
 
 
-
 static
 int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c)
 {
@@ -608,7 +653,7 @@
 		p->frequency += derot_freq;
 		p->inversion = (stv0299_readreg (i2c, 0x0c) & 1) ?
 						INVERSION_OFF : INVERSION_ON;
-		p->u.qpsk.fec_inner = stv0299_get_FEC (i2c);
+		p->u.qpsk.fec_inner = stv0299_get_fec (i2c);
 		p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c);
                 break;
         }
@@ -694,7 +739,7 @@
 
 MODULE_PARM(debug,"i");
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
-MODULE_DESCRIPTION("BSRU6 DVB Frontend driver");
+MODULE_DESCRIPTION("Alps BSRU6/LG TDQB-S00x DVB Frontend driver");
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
 MODULE_LICENSE("GPL");
 
diff -Nru a/drivers/media/dvb/frontends/alps_bsrv2.c b/drivers/media/dvb/frontends/alps_bsrv2.c
--- a/drivers/media/dvb/frontends/alps_bsrv2.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/dvb/frontends/alps_bsrv2.c	Wed Nov 27 14:36:28 2002
@@ -342,7 +342,7 @@
 
 		*ber = ves1893_readreg (i2c, 0x15);
                 *ber |= (ves1893_readreg (i2c, 0x16) << 8);
-                *ber |= (ves1893_readreg (i2c, 0x17) << 16);
+                *ber |= ((ves1893_readreg (i2c, 0x17) & 0x0f) << 16);
 		*ber *= 10;
 		break;
 	}
diff -Nru a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/frontends/alps_tdlb7.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,437 @@
+/*
+    Driver for Alps TDLB7 Frontend
+
+    Copyright (C) 1999 Juergen Peitz <peitz@snafu.de>
+
+    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.
+
+*/
+
+
+/* 
+    
+    Wrote this code mainly to get my own card running. It's working for me, but I
+    hope somebody who knows more about linux programming and the DVB driver can 
+    improve it.
+    
+    Reused a lot from the existing driver and tuner code.
+    Thanks to everybody who worked on it!
+    
+    This driver needs a copy of the microcode file 'Sc_main.mc' from the Haupauge 
+    windows driver in the 'usr/lib/DVB/driver/frontends' directory.  
+    You can also pass the complete file name with the module parameter 'mcfile'.
+    
+    The code only needs to be loaded once after a power on. Because loading the 
+    microcode to the card takes some time, you can use the 'loadcode=0' module 
+    parameter, if you only want to reload the dvb driver.      
+    
+    Juergen Peitz
+    
+*/  
+
+
+
+#define __KERNEL_SYSCALLS__
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/unistd.h>
+
+#include "compat.h"
+#include "dvb_frontend.h"
+
+static int debug = 0;
+
+static int loadcode = 1;
+
+static char * mcfile = "/usr/lib/DVB/driver/frontends/Sc_main.mc";
+
+#define dprintk	if (debug) printk
+
+/* microcode size for sp8870 */
+#define SP8870_CODE_SIZE 16384
+
+/* starting point for microcode in file 'Sc_main.mc' */
+#define SP8870_CODE_OFFSET 0x0A
+
+
+static int errno;
+
+static
+struct dvb_frontend_info tdlb7_info = {
+	name: "Alps TDLB7",
+	type: FE_OFDM,
+	frequency_min: 470000000,
+	frequency_max: 860000000,
+	frequency_stepsize: 166666,
+#if 0
+    	frequency_tolerance: ???,
+	symbol_rate_min: ???,
+	symbol_rate_max: ???,
+	symbol_rate_tolerance: ???,
+	notifier_delay: 0,
+#endif
+	caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+	      FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+	      FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64
+};
+
+
+static
+int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data)
+{
+        u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
+	struct i2c_msg msg = { addr: 0x71, flags: 0, buf: buf, len: 4 };
+	int err;
+
+        if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
+		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+		return -EREMOTEIO;
+	}
+
+        return 0;
+}
+
+
+static
+u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg)
+{
+	int ret;
+	u8 b0 [] = { reg >> 8 , reg & 0xff };
+	u8 b1 [] = { 0, 0 };
+	struct i2c_msg msg [] = { { addr: 0x71, flags: 0, buf: b0, len: 2 },
+			   { addr: 0x71, flags: I2C_M_RD, buf: b1, len: 2 } };
+
+	ret = i2c->xfer (i2c, msg, 2);
+
+	if (ret != 2)
+		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+
+	return (b1[0] << 8 | b1[1]);
+}
+
+
+static
+int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4])
+{
+        int ret;
+        struct i2c_msg msg = { addr: 0x60, flags: 0, buf: data, len: 4 };
+
+        ret = i2c->xfer (i2c, &msg, 1);
+
+        if (ret != 1)
+                printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret);
+
+        return (ret != 1) ? -1 : 0;
+}
+
+
+static
+int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr)
+{
+        u32 div = (freq + 36200000) / 166666;
+        u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x85, (pwr << 5) | 0x30 };
+
+	return sp5659_write (i2c, buf);
+}
+
+
+static
+int sp8870_read_code(const char *fn, char **fp)
+{
+        int fd;
+	loff_t l;
+	char *dp;
+
+	fd = open(fn, 0, 0);
+	if (fd == -1) {
+                printk(KERN_INFO "%s: Unable to load '%s'.\n", __FUNCTION__, fn);
+		return -1;
+	}
+	l = lseek(fd, 0L, 2);
+	if (l <= 0 || l < SP8870_CODE_OFFSET+SP8870_CODE_SIZE) {
+	        printk(KERN_INFO "%s: code file too small '%s'\n", __FUNCTION__, fn);
+		sys_close(fd);
+		return -1;
+	}
+	lseek(fd, SP8870_CODE_OFFSET, 0);
+	*fp= dp = vmalloc(SP8870_CODE_SIZE);
+	if (dp == NULL)	{
+		printk(KERN_INFO "%s: Out of memory loading '%s'.\n", __FUNCTION__, fn);
+		sys_close(fd);
+		return -1;
+	}
+	if (read(fd, dp, SP8870_CODE_SIZE) != SP8870_CODE_SIZE) {
+		printk(KERN_INFO "%s: Failed to read '%s'.\n",__FUNCTION__, fn);
+		vfree(dp);
+		sys_close(fd);
+		return -1;
+	}
+	sys_close(fd);
+	*fp = dp;
+	return 0;
+}
+
+
+static 
+int sp8870_load_code(struct dvb_i2c_bus *i2c)
+{
+	/* this takes a long time. is there a way to do it faster? */
+	char *lcode;
+	struct i2c_msg msg;
+	unsigned char buf[255];
+	int err;
+	int p=0;
+	int c;
+	mm_segment_t fs = get_fs();
+
+	sp8870_writereg(i2c,0x8F08,0x1FFF);
+	sp8870_writereg(i2c,0x8F0A,0x0000);
+
+	set_fs(get_ds());
+        if (sp8870_read_code(mcfile,(char**) &lcode)<0) return -1;
+	set_fs(fs);
+	while (p<SP8870_CODE_SIZE){
+		c = (p<=SP8870_CODE_SIZE-252) ? 252 : SP8870_CODE_SIZE-p;
+		buf[0]=0xCF;
+		buf[1]=0x0A;
+		memcpy(&buf[2],lcode+p,c);
+		c+=2;
+		msg.addr=0x71;
+		msg.flags=0;
+		msg.buf=buf;
+		msg.len=c;
+        	if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {
+			dprintk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
+        		vfree(lcode);
+			return -EREMOTEIO;
+		}
+
+		p+=252;
+	}
+        vfree(lcode);
+	return 0;
+};
+
+
+static
+int sp8870_init (struct dvb_i2c_bus *i2c)
+{
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	sp8870_readreg(i2c,0x200);
+     	sp8870_readreg(i2c,0x200);
+	sp8870_readreg(i2c,0x0F00);	/* system controller stop */
+	sp8870_readreg(i2c,0x0301);	/* ???????? */
+	sp8870_readreg(i2c,0x0309);	/* integer carrier offset */
+	sp8870_readreg(i2c,0x030A);	/* fractional carrier offset */
+	sp8870_readreg(i2c,0x0311);	/* filter for 8 Mhz channel */
+	sp8870_readreg(i2c,0x0319);	/* sample rate correction bit [23..17] */
+	sp8870_readreg(i2c,0x031A);	/* sample rate correction bit [16..0] */
+	sp8870_readreg(i2c,0x0338);	/* ???????? */
+	sp8870_readreg(i2c,0x0F00);
+	sp8870_readreg(i2c,0x0200);
+
+	if (loadcode) {
+		dprintk("%s: loading mcfile '%s' !\n", __FUNCTION__, mcfile);
+		if (sp8870_load_code(i2c)==0)
+		    dprintk("%s: microcode loaded!\n", __FUNCTION__);
+	}else{
+		dprintk("%s: without loading mcfile!\n", __FUNCTION__);
+	}
+
+	return 0;
+}
+
+
+static
+int sp8870_reset (struct dvb_i2c_bus *i2c)
+{
+	dprintk("%s\n", __FUNCTION__);
+	sp8870_writereg(i2c,0x0F00,0x0000);	/* system controller stop */
+	sp8870_writereg(i2c,0x0301,0x0003);	/* ???????? */
+	sp8870_writereg(i2c,0x0309,0x0400);	/* integer carrier offset */
+	sp8870_writereg(i2c,0x030A,0x0000);	/* fractional carrier offset */
+	sp8870_writereg(i2c,0x0311,0x0000);	/* filter for 8 Mhz channel */
+	sp8870_writereg(i2c,0x0319,0x000A);	/* sample rate correction bit [23..17] */
+	sp8870_writereg(i2c,0x031A,0x0AAB);	/* sample rate correction bit [16..0] */
+	sp8870_writereg(i2c,0x0338,0x0000);	/* ???????? */
+	sp8870_writereg(i2c,0x0201,0x0000);	/* interrupts for change of lock or tuner adjustment disabled */
+	sp8870_writereg(i2c,0x0F00,0x0001);	/* system controller start */
+
+        return 0;
+}
+
+static
+int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
+{
+	struct dvb_i2c_bus *i2c = fe->i2c;
+
+        switch (cmd) {
+        case FE_GET_INFO:
+		memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info));
+		break;
+
+        case FE_READ_STATUS:
+	{
+		fe_status_t *status = arg;
+		int sync = sp8870_readreg (i2c, 0x0200);
+
+		*status=0;
+
+		if (sync&0x04) // FIXME: find criteria for having signal
+			*status |= FE_HAS_SIGNAL;
+
+		if (sync&0x04) // FIXME: find criteria
+			*status |= FE_HAS_CARRIER;
+
+		if (sync&0x04) // FIXME
+			*status |= FE_HAS_VITERBI;
+
+		if (sync&0x08) // FIXME
+			*status |= FE_HAS_SYNC;
+
+		if (sync&0x04)
+			*status |= FE_HAS_LOCK;
+		break;
+
+	}
+
+        case FE_READ_BER:
+	{
+		u32 *ber=(u32 *) arg;
+		*ber=sp8870_readreg(i2c,0x0C07);  // bit error rate before Viterbi
+		break;
+
+	}
+
+        case FE_READ_SIGNAL_STRENGTH:		// not supported by hardware?
+	{
+		s32 *signal=(s32 *) arg;
+                *signal=0;
+		break;
+	}
+
+        case FE_READ_SNR:			// not supported by hardware?
+	{
+		s32 *snr=(s32 *) arg;
+                *snr=0;  
+		break;
+	}
+
+	case FE_READ_UNCORRECTED_BLOCKS: 	// not supported by hardware?
+	{
+		u32 *ublocks=(u32 *) arg;
+		*ublocks=0;  
+		break;
+	}
+
+        case FE_SET_FRONTEND:
+        {
+		struct dvb_frontend_parameters *p = arg;
+		sp5659_set_tv_freq (i2c, p->frequency, 0);
+		 			// all other parameters are set by the on card
+					// system controller. Don't know how to pass 
+					// distinct values to the card.
+		break;			
+        }
+
+	case FE_GET_FRONTEND: 		// how to do this?
+	{
+		break;
+	}
+
+        case FE_SLEEP:			// is this supported by hardware?
+		return -EOPNOTSUPP;
+
+        case FE_INIT:
+		return sp8870_init (i2c);
+
+	case FE_RESET:
+		return sp8870_reset (i2c);
+
+	default:
+		return -EOPNOTSUPP;
+        };
+
+        return 0;
+}
+
+
+static
+int tdlb7_attach (struct dvb_i2c_bus *i2c)
+{
+
+	struct i2c_msg msg = { addr: 0x71, flags: 0, buf: NULL, len: 0 };
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (i2c->xfer (i2c, &msg, 1) != 1)
+                return -ENODEV;
+
+	dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info);
+
+	return 0;
+}
+
+
+static
+void tdlb7_detach (struct dvb_i2c_bus *i2c)
+{
+	dprintk ("%s\n", __FUNCTION__);
+
+	dvb_unregister_frontend (tdlb7_ioctl, i2c);
+}
+
+
+static
+int __init init_tdlb7 (void)
+{
+	dprintk ("%s\n", __FUNCTION__);
+
+	return dvb_register_i2c_device (THIS_MODULE, tdlb7_attach, tdlb7_detach);
+}
+
+
+static
+void __exit exit_tdlb7 (void)
+{
+	dprintk ("%s\n", __FUNCTION__);
+
+	dvb_unregister_i2c_device (tdlb7_attach);
+}
+
+
+module_init(init_tdlb7);
+module_exit(exit_tdlb7);
+
+
+MODULE_PARM(debug,"i");
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+MODULE_PARM(loadcode,"i");
+MODULE_PARM_DESC(loadcode, "load tuner microcode");
+
+MODULE_PARM(mcfile,"s");
+MODULE_PARM_DESC(mcfile, "where to find the microcode file");
+
+MODULE_DESCRIPTION("TDLB7 DVB-T Frontend");
+MODULE_AUTHOR("Juergen Peitz");
+MODULE_LICENSE("GPL");
+
+
diff -Nru a/drivers/media/dvb/frontends/alps_tdmb7.c b/drivers/media/dvb/frontends/alps_tdmb7.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/frontends/alps_tdmb7.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,468 @@
+/* 
+    Alps TDMB7 DVB OFDM frontend driver
+
+    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
+	Holger Waechtler <holger@convergence.de>
+
+    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/init.h>
+#include <linux/module.h>
+
+#include "compat.h"
+#include "dvb_frontend.h"
+
+
+static int debug = 0;
+#define dprintk	if (debug) printk
+
+
+static
+struct dvb_frontend_info tdmb7_info = {
+	name: "Alps TDMB7",
+	type: FE_OFDM,
+	frequency_min: 470000000,
+	frequency_max: 860000000,
+	frequency_stepsize: 166667,
+#if 0
+    	frequency_tolerance: ???,
+	symbol_rate_min: ???,
+	symbol_rate_max: ???,
+	symbol_rate_tolerance: 500,  /* ppm */
+	notifier_delay: 0,
+#endif
+	caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+	      FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+	      FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64
+};
+
+
+static
+inline void ddelay (int timeout)
+{
+	current->state=TASK_INTERRUPTIBLE;
+	schedule_timeout(timeout);
+}
+
+
+static
+u8 init_tab [] = {
+	0x04, 0x10,
+	0x05, 0x09,
+	0x06, 0x00,
+	0x08, 0x04,
+	0x09, 0x00,
+	0x0a, 0x01,
+	0x15, 0x40,
+	0x16, 0x10,
+	0x17, 0x87,
+	0x18, 0x17,
+	0x1a, 0x10,
+	0x25, 0x04,
+	0x2e, 0x00,
+	0x39, 0x00,
+	0x3a, 0x04,
+	0x45, 0x08,
+	0x46, 0x02,
+	0x47, 0x05,
+};
+
+
+static
+int cx22700_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf [] = { reg, data };
+	struct i2c_msg msg = { addr: 0x43, flags: 0, buf: buf, len: 2 };
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	ret = i2c->xfer (i2c, &msg, 1);
+
+	if (ret != 1) 
+		printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			__FUNCTION__, reg, data, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+
+static
+u8 cx22700_readreg (struct dvb_i2c_bus *i2c, u8 reg)
+{
+	int ret;
+	u8 b0 [] = { reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { addr: 0x43, flags: 0, buf: b0, len: 1 },
+			   { addr: 0x43, flags: I2C_M_RD, buf: b1, len: 1 } };
+        
+	dprintk ("%s\n", __FUNCTION__);
+
+	ret = i2c->xfer (i2c, msg, 2);
+        
+	if (ret != 2) 
+		printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+
+	return b1[0];
+}
+
+
+static
+int pll_write (struct dvb_i2c_bus *i2c, u8 data [4])
+{
+	struct i2c_msg msg = { addr: 0x61, flags: 0, buf: data, len: 4 };
+	int ret;
+
+	cx22700_writereg (i2c, 0x0a, 0x00);  /* open i2c bus switch */
+	ret = i2c->xfer (i2c, &msg, 1);
+	cx22700_writereg (i2c, 0x0a, 0x01);  /* close i2c bus switch */
+
+	if (ret != 1)
+		printk("%s: i/o error (addr == 0x%02x, ret == %i)\n", __FUNCTION__, msg.addr, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+
+/**
+ *   set up the downconverter frequency divisor for a 
+ *   reference clock comparision frequency of 125 kHz.
+ */
+static
+int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq)
+{
+	u32 div = (freq + 36166667) / 166667;
+#if 1 //ALPS_SETTINGS
+	u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, ((div >> 10) & 0x60) | 0x85,
+		       freq < 592000000 ? 0x40 : 0x80 };
+#else
+	u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, ((div >> 10) & 0x60) | 0x85,
+		       freq < 470000000 ? 0x42 : freq < 862000000 ? 0x41 : 0x81 };
+#endif
+
+	dprintk ("%s: freq == %i, div == %i\n", __FUNCTION__, freq, div);
+
+	return pll_write (i2c, buf);
+}
+
+
+static
+int cx22700_init (struct dvb_i2c_bus *i2c)
+{
+	int i;
+
+	dprintk("cx22700_init: init chip\n");
+
+	cx22700_writereg (i2c, 0x00, 0x02);   /*  soft reset */
+	cx22700_writereg (i2c, 0x00, 0x00);
+
+	ddelay (HZ/100);
+	
+	for (i=0; i<sizeof(init_tab); i+=2)
+		cx22700_writereg (i2c, init_tab[i], init_tab[i+1]);
+
+	cx22700_writereg (i2c, 0x00, 0x01);
+	
+	return 0;
+}
+
+
+static
+int cx22700_set_inversion (struct dvb_i2c_bus *i2c, int inversion)
+{
+	u8 val;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	switch (inversion) {
+	case INVERSION_AUTO:
+		return -EOPNOTSUPP;
+	case INVERSION_ON:
+		val = cx22700_readreg (i2c, 0x09);
+		return cx22700_writereg (i2c, 0x09, val | 0x01);
+	case INVERSION_OFF:
+		val = cx22700_readreg (i2c, 0x09);
+		return cx22700_writereg (i2c, 0x09, val & 0xfe);
+	default:
+		return -EINVAL;
+	}
+}
+
+
+static
+int cx22700_set_tps (struct dvb_i2c_bus *i2c, struct dvb_ofdm_parameters *p)
+{
+	static const u8 qam_tab [4] = { 0, 1, 0, 2 };
+	static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
+	u8 val;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8)
+		return -EINVAL;
+
+	if (p->code_rate_LP < FEC_1_2 || p->code_rate_LP > FEC_7_8)
+
+	if (p->code_rate_HP == FEC_4_5 || p->code_rate_LP == FEC_4_5)
+		return -EINVAL;
+
+	if (p->guard_interval < GUARD_INTERVAL_1_32 ||
+	    p->guard_interval > GUARD_INTERVAL_1_4)
+		return -EINVAL;
+
+	if (p->transmission_mode != TRANSMISSION_MODE_2K &&
+	    p->transmission_mode != TRANSMISSION_MODE_8K)
+		return -EINVAL;
+
+	if (p->constellation != QPSK &&
+	    p->constellation != QAM_16 &&
+	    p->constellation != QAM_64)
+		return -EINVAL;
+
+	if (p->hierarchy_information < HIERARCHY_NONE ||
+	    p->hierarchy_information > HIERARCHY_4)
+		return -EINVAL;
+
+	if (p->bandwidth < BANDWIDTH_8_MHZ && p->bandwidth > BANDWIDTH_6_MHZ)
+		return -EINVAL;
+
+	if (p->bandwidth == BANDWIDTH_7_MHZ)
+		cx22700_writereg (i2c, 0x09, cx22700_readreg (i2c, 0x09 | 0x10));
+	else
+		cx22700_writereg (i2c, 0x09, cx22700_readreg (i2c, 0x09 & ~0x10));
+
+	val = qam_tab[p->constellation - QPSK];
+	val |= p->hierarchy_information - HIERARCHY_NONE;
+
+	cx22700_writereg (i2c, 0x04, val);
+
+	val = fec_tab[p->code_rate_HP - FEC_1_2] << 3;
+	val |= fec_tab[p->code_rate_LP - FEC_1_2];
+
+	cx22700_writereg (i2c, 0x05, val);
+
+	val = (p->guard_interval - GUARD_INTERVAL_1_32) << 2;
+	val |= p->transmission_mode - TRANSMISSION_MODE_2K;
+
+	cx22700_writereg (i2c, 0x06, val);
+
+	cx22700_writereg (i2c, 0x08, 0x04 | 0x02);  /* use user tps parameters */
+	cx22700_writereg (i2c, 0x08, 0x04);         /* restart aquisition */
+
+	return 0;
+}
+
+
+static
+int cx22700_get_tps (struct dvb_i2c_bus *i2c, struct dvb_ofdm_parameters *p)
+{
+	static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 };
+	static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4,
+						    FEC_5_6, FEC_7_8 };
+	u8 val;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (!(cx22700_readreg(i2c, 0x07) & 0x20))  /*  tps valid? */
+		return -EAGAIN;
+
+	val = cx22700_readreg (i2c, 0x01);
+
+	if ((val & 0x7) > 4)
+		p->hierarchy_information = HIERARCHY_AUTO;
+	else
+		p->hierarchy_information = HIERARCHY_NONE + (val & 0x7);
+
+	if (((val >> 3) & 0x3) > 2)
+		p->constellation = QAM_AUTO;
+	else
+		p->constellation = qam_tab[(val >> 3) & 0x3];
+
+
+	val = cx22700_readreg (i2c, 0x02);
+
+	if ((val >> 3) > 4)
+		p->code_rate_HP = FEC_AUTO;
+	else
+		p->code_rate_HP = fec_tab[val >> 3];
+
+	if ((val & 0x7) > 4)
+		p->code_rate_LP = FEC_AUTO;
+	else
+		p->code_rate_LP = fec_tab[val >> 3];
+
+
+	val = cx22700_readreg (i2c, 0x03);
+
+	p->guard_interval = GUARD_INTERVAL_1_32 + ((val >> 6) & 0x3);
+	p->transmission_mode = TRANSMISSION_MODE_2K + ((val >> 5) & 0x1);
+
+	return 0;
+}
+
+
+static
+int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
+{
+	struct dvb_i2c_bus *i2c = fe->i2c;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	switch (cmd) {
+	case FE_GET_INFO:
+		memcpy (arg, &tdmb7_info, sizeof(struct dvb_frontend_info));
+		break;
+
+	case FE_READ_STATUS:
+	{
+		fe_status_t *status = (fe_status_t *) arg;
+		u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9)
+			   | (cx22700_readreg (i2c, 0x0e) << 1);
+		u8 sync = cx22700_readreg (i2c, 0x07);
+
+		*status = 0;
+
+		if (rs_ber < 0xff00)
+			*status |= FE_HAS_SIGNAL;
+
+		if (sync & 0x20)
+			*status |= FE_HAS_CARRIER;
+
+		if (sync & 0x10)
+			*status |= FE_HAS_VITERBI;
+
+		if (sync & 0x10)
+			*status |= FE_HAS_SYNC;
+
+		if (sync & 0x10)
+			*status |= FE_HAS_LOCK;
+
+		break;
+	}
+
+        case FE_READ_BER:
+		*((uint32_t*) arg) = cx22700_readreg (i2c, 0x0c) & 0x7f;
+		break;
+
+	case FE_READ_SIGNAL_STRENGTH:
+	{
+		u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9)
+			   | (cx22700_readreg (i2c, 0x0e) << 1);
+		*((uint16_t*) arg) = ~rs_ber;
+		break;
+	}
+        case FE_READ_SNR:
+	{
+		u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9)
+			   | (cx22700_readreg (i2c, 0x0e) << 1);
+		*((uint16_t*) arg) = ~rs_ber;
+		break;
+	}
+	case FE_READ_UNCORRECTED_BLOCKS: 
+		*((uint32_t*) arg) = cx22700_readreg (i2c, 0x0f);
+		break;
+
+        case FE_SET_FRONTEND:
+        {
+		struct dvb_frontend_parameters *p = arg;
+
+		cx22700_writereg (i2c, 0x00, 0x02); /* XXX CHECKME: soft reset*/
+		cx22700_writereg (i2c, 0x00, 0x00);
+
+		pll_set_tv_freq (i2c, p->frequency);
+		cx22700_set_inversion (i2c, p->inversion);
+                cx22700_set_tps (i2c, &p->u.ofdm);
+		cx22700_writereg (i2c, 0x37, 0x01);  /* PAL loop filter off */
+		cx22700_writereg (i2c, 0x00, 0x01);  /* restart aquire */
+                break;
+        }
+
+        case FE_GET_FRONTEND:
+        {
+		struct dvb_frontend_parameters *p = arg;
+		u8 reg09 = cx22700_readreg (i2c, 0x09);
+		
+		p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
+		return cx22700_get_tps (i2c, &p->u.ofdm);
+        }
+
+        case FE_INIT:
+		return cx22700_init (i2c);
+
+        case FE_RESET:
+                break;
+
+	default:
+		return -EOPNOTSUPP;
+	};
+
+	return 0;
+}
+
+
+
+static
+int tdmb7_attach (struct dvb_i2c_bus *i2c)
+{
+	struct i2c_msg msg = { addr: 0x43, flags: 0, buf: NULL, len: 0 };
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (i2c->xfer (i2c, &msg, 1) != 1)
+                return -ENODEV;
+
+	dvb_register_frontend (tdmb7_ioctl, i2c, NULL, &tdmb7_info);
+
+	return 0;
+}
+
+
+static
+void tdmb7_detach (struct dvb_i2c_bus *i2c)
+{
+	dprintk ("%s\n", __FUNCTION__);
+
+	dvb_unregister_frontend (tdmb7_ioctl, i2c);
+}
+
+
+static
+int __init init_tdmb7 (void)
+{
+	dprintk ("%s\n", __FUNCTION__);
+
+	return dvb_register_i2c_device (THIS_MODULE, tdmb7_attach, tdmb7_detach);
+}
+
+
+static 
+void __exit exit_tdmb7 (void)
+{
+	dprintk ("%s\n", __FUNCTION__);
+
+	dvb_unregister_i2c_device (tdmb7_attach);
+}
+
+module_init (init_tdmb7);
+module_exit (exit_tdmb7);
+
+MODULE_PARM(debug,"i");
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+MODULE_DESCRIPTION("TDMB7 DVB Frontend driver");
+MODULE_AUTHOR("Holger Waechtler");
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
--- a/drivers/media/dvb/frontends/ves1820.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/media/dvb/frontends/ves1820.c	Wed Nov 27 14:36:30 2002
@@ -199,8 +199,8 @@
 	u8 b0 [] = { 0xff };
 	u8 pwm;
 	int i;
-	struct i2c_msg msg [] = { { addr: 0x28, flags: 0, buf: b0, len: 1 },
-	                   { addr: 0x28, flags: I2C_M_RD, buf: &pwm, len: 1 } };
+	struct i2c_msg msg [] = { { addr: 0x50, flags: 0, buf: b0, len: 1 },
+	                   { addr: 0x50, flags: I2C_M_RD, buf: &pwm, len: 1 } };
         
         dprintk("VES1820: init chip\n");
 
@@ -433,12 +433,13 @@
 	}
 
 	case FE_READ_BER:
-		*((u32*) arg) = ves1820_readreg(frontend->i2c, 0x14) |
+	{
+		u32 ber = ves1820_readreg(frontend->i2c, 0x14) |
 			        (ves1820_readreg(frontend->i2c, 0x15) << 8) |
-			        (ves1820_readreg(frontend->i2c, 0x16) << 16);
-		/* XXX FIXME: scale!!*/
+			 ((ves1820_readreg(frontend->i2c, 0x16) & 0x0f) << 16);
+		*((u32*) arg) = 10 * ber;
 		break;
-
+	}
 	case FE_READ_SIGNAL_STRENGTH:
 	{
 		u8 gain = ves1820_readreg(frontend->i2c, 0x17);
diff -Nru a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
--- a/drivers/media/radio/radio-sf16fmi.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/radio/radio-sf16fmi.c	Wed Nov 27 14:36:31 2002
@@ -82,24 +82,15 @@
 
 static inline int fmi_setfreq(struct fmi_device *dev)
 {
-        int myport = dev->port;
+	int myport = dev->port;
 	unsigned long freq = dev->curfreq;
-	int i;
-	
+
 	down(&lock);
-	
+
 	outbits(16, RSF16_ENCODE(freq), myport);
 	outbits(8, 0xC0, myport);
-	for(i=0; i< 100; i++)
-	{
-		udelay(1400);
-		cond_resched();
-	}
-/* If this becomes allowed use it ... 	
 	current->state = TASK_UNINTERRUPTIBLE;
 	schedule_timeout(HZ/7);
-*/	
-
 	up(&lock);
 	if (dev->curvol) fmi_unmute(myport);
 	return 0;
@@ -110,7 +101,7 @@
 	int val;
 	int res;
 	int myport = dev->port;
-	int i;
+
 	
 	down(&lock);
 	val = dev->curvol ? 0x08 : 0x00;	/* unmute/mute */
diff -Nru a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
--- a/drivers/media/video/bttv-cards.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/media/video/bttv-cards.c	Wed Nov 27 14:36:30 2002
@@ -2990,7 +2990,7 @@
 
 	/* print which chipset we have */
 	while ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8,dev)))
-		printk(KERN_INFO "bttv: Host bridge is %s\n",dev->name);
+		printk(KERN_INFO "bttv: Host bridge is %s\n",dev->dev.name);
 
 	/* print warnings about any quirks found */
 	if (triton1)
diff -Nru a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
--- a/drivers/media/video/bw-qcam.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/video/bw-qcam.c	Wed Nov 27 14:36:28 2002
@@ -89,27 +89,27 @@
 MODULE_PARM(video_nr,"i");
 #endif
 
-extern __inline__ int read_lpstatus(struct qcam_device *q)
+static inline int read_lpstatus(struct qcam_device *q)
 {
 	return parport_read_status(q->pport);
 }
 
-extern __inline__ int read_lpcontrol(struct qcam_device *q)
+static inline int read_lpcontrol(struct qcam_device *q)
 {
 	return parport_read_control(q->pport);
 }
 
-extern __inline__ int read_lpdata(struct qcam_device *q)
+static inline int read_lpdata(struct qcam_device *q)
 {
 	return parport_read_data(q->pport);
 }
 
-extern __inline__ void write_lpdata(struct qcam_device *q, int d)
+static inline void write_lpdata(struct qcam_device *q, int d)
 {
 	parport_write_data(q->pport, d);
 }
 
-extern __inline__ void write_lpcontrol(struct qcam_device *q, int d)
+static inline void write_lpcontrol(struct qcam_device *q, int d)
 {
 	parport_write_control(q->pport, d);
 }
@@ -506,7 +506,7 @@
    the supplied buffer.  It returns the number of bytes read,
    or -1 on error. */
 
-extern __inline__ int qc_readbytes(struct qcam_device *q, char buffer[])
+static inline int qc_readbytes(struct qcam_device *q, char buffer[])
 {
 	int ret=1;
 	unsigned int hi, lo;
diff -Nru a/drivers/media/video/pms.c b/drivers/media/video/pms.c
--- a/drivers/media/video/pms.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/video/pms.c	Wed Nov 27 14:36:31 2002
@@ -69,12 +69,12 @@
 
 	
 
-extern __inline__ void mvv_write(u8 index, u8 value)
+static inline void mvv_write(u8 index, u8 value)
 {
 	outw(index|(value<<8), io_port);
 }
 
-extern __inline__ u8 mvv_read(u8 index)
+static inline u8 mvv_read(u8 index)
 {
 	outb(index, io_port);
 	return inb(data_port);
diff -Nru a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
--- a/drivers/media/video/saa7111.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/media/video/saa7111.c	Wed Nov 27 14:36:29 2002
@@ -34,7 +34,7 @@
 
 #include <linux/videodev.h>
 #include <linux/version.h>
-#include <linux/i2c-old.h>
+#include <linux/i2c.h>
 
 #include <linux/video_decoder.h>
 
@@ -43,8 +43,9 @@
 /* ----------------------------------------------------------------------- */
 
 struct saa7111 {
-	struct i2c_bus *bus;
+	struct i2c_client *client;
 	int addr;
+	struct semaphore lock;
 	unsigned char reg[32];
 
 	int norm;
@@ -60,74 +61,32 @@
 
 #define   I2C_DELAY   10
 
-/* ----------------------------------------------------------------------- */
-
-static int saa7111_write(struct saa7111 *dev, unsigned char subaddr,
-			 unsigned char data)
-{
-	int ack;
-
-	LOCK_I2C_BUS(dev->bus);
-	i2c_start(dev->bus);
-	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
-	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
-	ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
-	dev->reg[subaddr] = data;
-	i2c_stop(dev->bus);
-	UNLOCK_I2C_BUS(dev->bus);
-	return ack;
-}
-
-static int saa7111_write_block(struct saa7111 *dev,
-	       unsigned const char *data, unsigned int len)
-{
-	int ack = -1;
-	unsigned subaddr;
-
-	while (len > 1) {
-		LOCK_I2C_BUS(dev->bus);
-		i2c_start(dev->bus);
-		i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
-		ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY);
-		ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
-		len -= 2;
-		while (len > 1 && *data == ++subaddr) {
-			data++;
-			ack =
-			    i2c_sendbyte(dev->bus,
-					 (dev->reg[subaddr] =
-					  *data++), I2C_DELAY);
-			len -= 2;
-		}
-		i2c_stop(dev->bus);
-		UNLOCK_I2C_BUS(dev->bus);
-	}
-	return ack;
-}
-
-static int saa7111_read(struct saa7111 *dev, unsigned char subaddr)
-{
-	int data;
-
-	LOCK_I2C_BUS(dev->bus);
-	i2c_start(dev->bus);
-	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
-	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
-	i2c_start(dev->bus);
-	i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY);
-	data = i2c_readbyte(dev->bus, 1);
-	i2c_stop(dev->bus);
-	UNLOCK_I2C_BUS(dev->bus);
-	return data;
-}
+static unsigned short normal_i2c[] = { 34>>1, I2C_CLIENT_END };	
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };	
+static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };	
+
+static struct i2c_client_address_data addr_data = {
+	.normal_i2c 		= normal_i2c,
+	.normal_i2c_range 	= normal_i2c_range,
+	.probe			= probe, 
+	.probe_range 		= probe_range,
+	.ignore 		= ignore, 
+	.ignore_range 		= ignore_range,
+	.force 			= force
+};
 
+static struct i2c_client client_template;
 /* ----------------------------------------------------------------------- */
 
-static int saa7111_attach(struct i2c_device *device)
+static int saa7111_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
 {
 	int i;
 	struct saa7111 *decoder;
-
+	struct i2c_client *client;
 	static const unsigned char init[] = {
 		0x00, 0x00,	/* 00 - ID byte */
 		0x01, 0x00,	/* 01 - reserved */
@@ -158,20 +117,25 @@
 		0x16, 0x00,	/* 16 - VBI */
 		0x17, 0x00,	/* 17 - VBI */
 	};
+	client = kmalloc(sizeof(*client), GFP_KERNEL);
+	if(client == NULL) 
+		return -ENOMEM;
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	memcpy(client, &client_template, sizeof(*client));
 
-	MOD_INC_USE_COUNT;
-
-	device->data = decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL);
+	decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
 	if (decoder == NULL)
 	{
-		MOD_DEC_USE_COUNT;
+		kfree(client);
 		return -ENOMEM;
 	}
 
-	memset(decoder, 0, sizeof(struct saa7111));
-	strcpy(device->name, "saa7111");
-	decoder->bus = device->bus;
-	decoder->addr = device->addr;
+	memset(decoder, 0, sizeof(*decoder));
+	strcpy(client->name, "saa7111");
+	decoder->client = client;
+	client->data = decoder;
+	decoder->addr = addr;
 	decoder->norm = VIDEO_MODE_NTSC;
 	decoder->input = 0;
 	decoder->enable = 1;
@@ -180,29 +144,38 @@
 	decoder->hue = 32768;
 	decoder->sat = 32768;
 
-	i = saa7111_write_block(decoder, init, sizeof(init));
+	i = i2c_master_send(client, init, sizeof(init));
 	if (i < 0) {
 		printk(KERN_ERR "%s_attach: init status %d\n",
-		       device->name, i);
+		       client->name, i);
 	} else {
 		printk(KERN_INFO "%s_attach: chip version %x\n",
-		       device->name, saa7111_read(decoder, 0x00) >> 4);
+		       client->name, i2c_smbus_read_byte_data(client, 0x00) >> 4);
 	}
+	init_MUTEX(&decoder->lock);
+	i2c_attach_client(client);
+	MOD_INC_USE_COUNT;
 	return 0;
 }
+static int saa7111_probe(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, saa7111_attach);
+}
 
-
-static int saa7111_detach(struct i2c_device *device)
+static int saa7111_detach(struct i2c_client *client)
 {
-	kfree(device->data);
+	struct saa7111 *decoder = client->data;
+	i2c_detach_client(client);
+	kfree(decoder);
+	kfree(client);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
-static int saa7111_command(struct i2c_device *device, unsigned int cmd,
+static int saa7111_command(struct i2c_client *client, unsigned int cmd,
 			   void *arg)
 {
-	struct saa7111 *decoder = device->data;
+	struct saa7111 *decoder = client->data;
 
 	switch (cmd) {
 
@@ -214,11 +187,11 @@
 			for (i = 0; i < 32; i += 16) {
 				int j;
 
-				printk("KERN_DEBUG %s: %03x", device->name,
+				printk("KERN_DEBUG %s: %03x", client->name,
 				       i);
 				for (j = 0; j < 16; ++j) {
 					printk(" %02x",
-					       saa7111_read(decoder,
+					       i2c_smbus_read_byte_data(client,
 							    i + j));
 				}
 				printk("\n");
@@ -246,7 +219,7 @@
 			int status;
 			int res;
 
-			status = saa7111_read(decoder, 0x1f);
+			status = i2c_smbus_read_byte_data(client, 0x1f);
 			res = 0;
 			if ((status & (1 << 6)) == 0) {
 				res |= DECODER_STATUS_GOOD;
@@ -281,19 +254,19 @@
 			switch (*iarg) {
 
 			case VIDEO_MODE_NTSC:
-				saa7111_write(decoder, 0x08,
+				i2c_smbus_write_byte_data(client, 0x08,
 					      (decoder->
 					       reg[0x08] & 0x3f) | 0x40);
 				break;
 
 			case VIDEO_MODE_PAL:
-				saa7111_write(decoder, 0x08,
+				i2c_smbus_write_byte_data(client, 0x08,
 					      (decoder->
 					       reg[0x08] & 0x3f) | 0x00);
 				break;
 
 			case VIDEO_MODE_AUTO:
-				saa7111_write(decoder, 0x08,
+				i2c_smbus_write_byte_data(client, 0x08,
 					      (decoder->
 					       reg[0x08] & 0x3f) | 0x80);
 				break;
@@ -317,12 +290,12 @@
 			if (decoder->input != *iarg) {
 				decoder->input = *iarg;
 				/* select mode */
-				saa7111_write(decoder, 0x02,
+				i2c_smbus_write_byte_data(client, 0x02,
 					      (decoder->
 					       reg[0x02] & 0xf8) |
 					      decoder->input);
 				/* bypass chrominance trap for modes 4..7 */
-				saa7111_write(decoder, 0x09,
+				i2c_smbus_write_byte_data(client, 0x09,
 					      (decoder->
 					       reg[0x09] & 0x7f) |
 					      ((decoder->input >
@@ -357,26 +330,26 @@
 //     If output should be enabled, we have to reverse the above.
 
 				if (decoder->enable) {
-					saa7111_write(decoder, 0x02,
+					i2c_smbus_write_byte_data(client, 0x02,
 						      (decoder->
 						       reg[0x02] & 0xf8) |
 						      decoder->input);
-					saa7111_write(decoder, 0x08,
+					i2c_smbus_write_byte_data(client, 0x08,
 						      (decoder->
 						       reg[0x08] & 0xfb));
-					saa7111_write(decoder, 0x11,
+					i2c_smbus_write_byte_data(client, 0x11,
 						      (decoder->
 						       reg[0x11] & 0xf3) |
 						      0x0c);
 				} else {
-					saa7111_write(decoder, 0x02,
+					i2c_smbus_write_byte_data(client, 0x02,
 						      (decoder->
 						       reg[0x02] & 0xf8));
-					saa7111_write(decoder, 0x08,
+					i2c_smbus_write_byte_data(client, 0x08,
 						      (decoder->
 						       reg[0x08] & 0xfb) |
 						      0x04);
-					saa7111_write(decoder, 0x11,
+					i2c_smbus_write_byte_data(client, 0x11,
 						      (decoder->
 						       reg[0x11] & 0xf3));
 				}
@@ -391,25 +364,25 @@
 			if (decoder->bright != pic->brightness) {
 				/* We want 0 to 255 we get 0-65535 */
 				decoder->bright = pic->brightness;
-				saa7111_write(decoder, 0x0a,
+				i2c_smbus_write_byte_data(client, 0x0a,
 					      decoder->bright >> 8);
 			}
 			if (decoder->contrast != pic->contrast) {
 				/* We want 0 to 127 we get 0-65535 */
 				decoder->contrast = pic->contrast;
-				saa7111_write(decoder, 0x0b,
+				i2c_smbus_write_byte_data(client, 0x0b,
 					      decoder->contrast >> 9);
 			}
 			if (decoder->sat != pic->colour) {
 				/* We want 0 to 127 we get 0-65535 */
 				decoder->sat = pic->colour;
-				saa7111_write(decoder, 0x0c,
+				i2c_smbus_write_byte_data(client, 0x0c,
 					      decoder->sat >> 9);
 			}
 			if (decoder->hue != pic->hue) {
 				/* We want -128 to 127 we get 0-65535 */
 				decoder->hue = pic->hue;
-				saa7111_write(decoder, 0x0d,
+				i2c_smbus_write_byte_data(client, 0x0d,
 					      (decoder->hue - 32768) >> 8);
 			}
 		}
@@ -425,23 +398,28 @@
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_saa7111 = {
-	"saa7111",		/* name */
-	I2C_DRIVERID_VIDEODECODER,	/* ID */
-	I2C_SAA7111, I2C_SAA7111 + 1,
-
-	saa7111_attach,
-	saa7111_detach,
-	saa7111_command
+	.name 		= "saa7111",		 /* name */
+	.id 		= I2C_DRIVERID_SAA7111A, /* ID */
+	.flags 		= I2C_DF_NOTIFY,
+	.attach_adapter = saa7111_probe,
+	.detach_client 	= saa7111_detach,
+	.command 	= saa7111_command
+};
+
+static struct i2c_client client_template = {
+	.name 	= "saa7111_client",
+	.id 	= -1,
+	.driver = &i2c_driver_saa7111
 };
 
 static int saa7111_init(void)
 {
-	return i2c_register_driver(&i2c_driver_saa7111);
+	return i2c_add_driver(&i2c_driver_saa7111);
 }
 
 static void saa7111_exit(void)
 {
-	i2c_unregister_driver(&i2c_driver_saa7111);
+	i2c_del_driver(&i2c_driver_saa7111);
 }
 
 module_init(saa7111_init);
diff -Nru a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
--- a/drivers/media/video/saa7185.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/media/video/saa7185.c	Wed Nov 27 14:36:27 2002
@@ -43,7 +43,7 @@
 #include <linux/version.h>
 #include <asm/uaccess.h>
 
-#include <linux/i2c-old.h>
+#include <linux/i2c.h>
 
 #include <linux/video_encoder.h>
 
@@ -52,9 +52,10 @@
 /* ----------------------------------------------------------------------- */
 
 struct saa7185 {
-	struct i2c_bus *bus;
+	struct i2c_client *client;
 	int addr;
 	unsigned char reg[128];
+	struct semaphore lock;
 
 	int norm;
 	int enable;
@@ -69,66 +70,25 @@
 #define I2C_DELAY   10
 
 /* ----------------------------------------------------------------------- */
+static unsigned short normal_i2c[] = { 34>>1, I2C_CLIENT_END };	
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+static unsigned short probe[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short probe_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+	.normal_i2c 		= normal_i2c,
+	.normal_i2c_range 	= normal_i2c_range,
+	.probe 			= probe, 
+	.probe_range 		= probe_range,
+	.ignore 		= ignore,
+	.ignore_range 		= ignore_range,
+	.force 			= force
+};
 
-static int saa7185_read(struct saa7185 *dev)
-{
-	int ack;
-
-	LOCK_I2C_BUS(dev->bus);
-
-	i2c_start(dev->bus);
-	i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY);
-	ack = i2c_readbyte(dev->bus, 1);
-	i2c_stop(dev->bus);
-	UNLOCK_I2C_BUS(dev->bus);
-	return ack;
-}
-
-static int saa7185_write(struct saa7185 *dev, unsigned char subaddr,
-			 unsigned char data)
-{
-	int ack;
-
-	DEBUG(printk
-	      (KERN_DEBUG "SAA7185: %02x set to %02x\n", subaddr, data);
-	    )
-	    LOCK_I2C_BUS(dev->bus);
-
-	i2c_start(dev->bus);
-	i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
-	i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
-	ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
-	dev->reg[subaddr] = data;
-	i2c_stop(dev->bus);
-	UNLOCK_I2C_BUS(dev->bus);
-	return ack;
-}
-
-static int saa7185_write_block(struct saa7185 *dev,
-			       unsigned const char *data, unsigned int len)
-{
-	int ack = -1;
-	unsigned subaddr;
-
-	while (len > 1) {
-		LOCK_I2C_BUS(dev->bus);
-		i2c_start(dev->bus);
-		i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
-		ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY);
-		ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
-		len -= 2;
-		while (len > 1 && *data == ++subaddr) {
-			data++;
-			ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
-			len -= 2;
-		}
-		i2c_stop(dev->bus);
-		UNLOCK_I2C_BUS(dev->bus);
-	}
-	return ack;
-}
-
-/* ----------------------------------------------------------------------- */
+static struct i2c_client client_template;
 
 static const unsigned char init_common[] = {
 	0x3a, 0x0f,		/* CBENB=0, V656=0, VY2C=1, YUV2C=1, MY2C=1, MUV2C=1 */
@@ -222,58 +182,71 @@
 	0x66, 0x21,		/* FSC3 */
 };
 
-static int saa7185_attach(struct i2c_device *device)
+static int saa7185_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
 {
 	int i;
 	struct saa7185 *encoder;
+	struct i2c_client client;
 
-	MOD_INC_USE_COUNT;
-	
-	device->data = encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
+	client = kmalloc(sizeof(*client), GFP_KERNEL);
+	if (client == NULL)
+		return -ENOMEM;
+	client_template.adapter = adap;
+	client_template.addr = addr;
+	memcpy(client, &client_template, sizeof(*client));
+	encoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
 	if (encoder == NULL) {
-		MOD_DEC_USE_COUNT;
+		kfree(client);
 		return -ENOMEM;
 	}
 
 
-	memset(encoder, 0, sizeof(struct saa7185));
-	strcpy(device->name, "saa7185");
-	encoder->bus = device->bus;
-	encoder->addr = device->addr;
+	memset(encoder, 0, sizeof(*decoder));
+	strcpy(client->name, "saa7185");
+	encoder->client = client;
+	client->data = encoder;
+	encoder->addr = addr;
 	encoder->norm = VIDEO_MODE_NTSC;
 	encoder->enable = 1;
 
-	i = saa7185_write_block(encoder, init_common, sizeof(init_common));
+	i = i2c_master_send(client, init_common, sizeof(init_common));
 	if (i >= 0) {
-		i = saa7185_write_block(encoder, init_ntsc,
+		i = i2c_master_send(client, init_ntsc,
 					sizeof(init_ntsc));
 	}
 	if (i < 0) {
-		printk(KERN_ERR "%s_attach: init error %d\n", device->name,
+		printk(KERN_ERR "%s_attach: init error %d\n", client->name,
 		       i);
 	} else {
 		printk(KERN_INFO "%s_attach: chip version %d\n",
-		       device->name, saa7185_read(encoder) >> 5);
+		       client->name, i2c_smbus_read_byte(client) >> 5);
 	}
-
+	init_MUTEX(&decoder->lock);
+	i2c_attach_client(client);
+	MOD_INC_USE_COUNT;
 	return 0;
 }
+static int saa7185_probe(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, saa7185_attach);
+}
 
-
-static int saa7185_detach(struct i2c_device *device)
+static int saa7185_detach(struct i2c_client *client)
 {
-	struct saa7185 *encoder = device->data;
-	saa7185_write(encoder, 0x61, (encoder->reg[0x61]) | 0x40);	/* SW: output off is active */
-	//saa7185_write(encoder, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */
+	struct saa7185 *encoder = client->data;
+	i2c_detach_client(client);
+	i2c_smbus_write_byte_data(client, 0x61, (encoder->reg[0x61]) | 0x40);	/* SW: output off is active */
+	//i2c_smbus_write_byte_data(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */
 	kfree(encoder);
+	kfree(client);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
-static int saa7185_command(struct i2c_device *device, unsigned int cmd,
+static int saa7185_command(struct i2c_client *client, unsigned int cmd,
 			   void *arg)
 {
-	struct saa7185 *encoder = device->data;
+	struct saa7185 *encoder = client->data;
 
 	switch (cmd) {
 
@@ -297,12 +270,12 @@
 			switch (*iarg) {
 
 			case VIDEO_MODE_NTSC:
-				saa7185_write_block(encoder, init_ntsc,
+				i2c_master_send(client, init_ntsc,
 						    sizeof(init_ntsc));
 				break;
 
 			case VIDEO_MODE_PAL:
-				saa7185_write_block(encoder, init_pal,
+				i2c_master_send(client, init_pal,
 						    sizeof(init_pal));
 				break;
 
@@ -326,19 +299,19 @@
 
 			case 0:
 				/* Switch RTCE to 1 */
-				saa7185_write(encoder, 0x61,
+				i2c_smbus_write_byte_data(client, 0x61,
 					      (encoder->
 					       reg[0x61] & 0xf7) | 0x08);
-				saa7185_write(encoder, 0x6e, 0x01);
+				i2c_smbus_write_byte_data(client, 0x6e, 0x01);
 				break;
 
 			case 1:
 				/* Switch RTCE to 0 */
-				saa7185_write(encoder, 0x61,
+				i2c_smbus_write_byte_data(client, 0x61,
 					      (encoder->
 					       reg[0x61] & 0xf7) | 0x00);
 				/* SW: a slight sync problem... */
-				saa7185_write(encoder, 0x6e, 0x00);
+				i2c_smbus_write_byte_data(client, 0x6e, 0x00);
 				break;
 
 			default:
@@ -364,7 +337,7 @@
 			int *iarg = arg;
 
 			encoder->enable = !!*iarg;
-			saa7185_write(encoder, 0x61,
+			i2c_smbus_write_byte_data(client, 0x61,
 				      (encoder->
 				       reg[0x61] & 0xbf) | (encoder->
 							    enable ? 0x00 :
@@ -382,23 +355,28 @@
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver i2c_driver_saa7185 = {
-	"saa7185",		/* name */
-	I2C_DRIVERID_VIDEOENCODER,	/* ID */
-	I2C_SAA7185, I2C_SAA7185 + 1,
-
-	saa7185_attach,
-	saa7185_detach,
-	saa7185_command
+	.name	 	= "saa7185",		 /* name */
+	.id 		= I2C_DRIVERID_SAA7185B, /* ID */
+	.flags 		= I2C_DF_NOTIFY,
+	.attach_adapter = saa7185_probe,
+	.detach_client 	= saa7185_detach,
+	.command	= saa7185_command
+};
+
+static struct i2c_client client_template = {
+	.name 	= "saa7185_client",
+	.id 	= -1,
+	.driver = &i2c_driver_saa7185
 };
 
 static int saa7185_init(void)
 {
-	return i2c_register_driver(&i2c_driver_saa7185);
+	return i2c_add_driver(&i2c_driver_saa7185);
 }
 
 static void saa7185_exit(void)
 {
-	i2c_unregister_driver(&i2c_driver_saa7185);
+	i2c_del_driver(&i2c_driver_saa7185);
 }
 
 module_init(saa7185_init);
diff -Nru a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
--- a/drivers/media/video/stradis.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/media/video/stradis.c	Wed Nov 27 14:36:31 2002
@@ -1428,6 +1428,9 @@
 				if (copy_from_user(saa->dmavid2, vw.clips,
 						   VIDEO_CLIPMAP_SIZE))
 					return -EFAULT;
+			}
+			else if (vw.clipcount > 16384) {
+				return -EINVAL;
 			} else if (vw.clipcount > 0) {
 				if ((vcp = vmalloc(sizeof(struct video_clip) *
 					        (vw.clipcount))) == NULL)
diff -Nru a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
--- a/drivers/media/video/w9966.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/media/video/w9966.c	Wed Nov 27 14:36:28 2002
@@ -568,7 +568,7 @@
 	if (state) {
 		timeout = jiffies + 100;
 		while (!w9966_i2c_getscl(cam)) {
-			if (jiffies > timeout)
+			if (time_after(jiffies, timeout))
 				return -1;
 		}
 	}
diff -Nru a/drivers/media/video/zr36067.c b/drivers/media/video/zr36067.c
--- a/drivers/media/video/zr36067.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/media/video/zr36067.c	Wed Nov 27 14:36:32 2002
@@ -1416,7 +1416,7 @@
 		zr36060_sleep(zr, 0);
 		post_office_write(zr, 3, 0, 0);
 		udelay(2);
-	default:
+	default:;
 	}
 	return 0;
 }
@@ -3758,7 +3758,7 @@
 			 *   Write the overlay mask if clips are wanted.
 			 */
 			 
-			if (vw.clipcount > 2048)
+			if (vw.clipcount < 0 || vw.clipcount > 2048)
 				return -EINVAL;
 			if (vw.clipcount) {
 				vcp =
diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
--- a/drivers/message/fusion/mptbase.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/message/fusion/mptbase.c	Wed Nov 27 14:36:28 2002
@@ -49,7 +49,7 @@
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:Pam.Delaney@lsil.com)
  *
- *  $Id: mptbase.c,v 1.122 2002/10/03 13:10:11 pdelaney Exp $
+ *  $Id: mptbase.c,v 1.123 2002/10/17 20:15:56 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -1156,7 +1156,7 @@
 	dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n"));
 
 	/*
-	 *  NOTE: The 929, 929X and 1030 will appear as 2 separate PCI devices,
+	 *  NOTE: The 929, 929X, 1030 and 1035 will appear as 2 separate PCI devices,
 	 *  one for each channel.
 	 */
 	pci_for_each_dev(pdev) {
@@ -1170,18 +1170,14 @@
 		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929X) &&
 		    (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919X) &&
 		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) &&
-#if 0
-		    /* FIXME! C103x family */
-		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) &&
-		    (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1035) &&
-#endif
+		    (pdev->device != MPI_MANUFACTPAGE_DEVID_1030_53C1035) &&
 		    1) {
 			dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device));
 			continue;
 		}
 
 		/* GRRRRR
-		 * dual function devices (929, 929X, 1030) may be presented in Func 1,0 order,
+		 * dual function devices (929, 929X, 1030, 1035) may be presented in Func 1,0 order,
 		 * but we'd really really rather have them in Func 0,1 order.
 		 * Do some kind of look ahead here...
 		 */
@@ -1445,15 +1441,24 @@
 		ioc->chip_type = C1030;
 		ioc->prod_name = "LSI53C1030";
 		{
+			u8 revision;
+
 			/* 1030 Chip Fix. Disable Split transactions
-			 * for PCIX. Set bits 4 - 6 to zero.
+			 * for PCIX. Set bits 4 - 6 to zero if Rev < C0( = 8)
 			 */
-			u16 pcixcmd = 0;
-			pci_read_config_word(pdev, 0x6a, &pcixcmd);
-			pcixcmd &= 0xFF8F;
-			pci_write_config_word(pdev, 0x6a, pcixcmd);
+			pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
+			if (revision < 0x08) {
+				u16 pcixcmd = 0;
+				pci_read_config_word(pdev, 0x6a, &pcixcmd);
+				pcixcmd &= 0xFF8F;
+				pci_write_config_word(pdev, 0x6a, pcixcmd);
+			}
 		}
 	}
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
+		ioc->chip_type = C1035;
+		ioc->prod_name = "LSI53C1035";
+	}
 
 	sprintf(ioc->name, "ioc%d", ioc->id);
 
@@ -1500,9 +1505,10 @@
 	mpt_adapters[ioc->id] = ioc;
 
 	/* NEW!  20010220 -sralston
-	 * Check for "bound ports" (929, 929X, 1030) to reduce redundant resets.
+	 * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
 	 */
-	if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) || (ioc->chip_type == FC929X))
+	if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) 
+			|| (ioc->chip_type == C1035) || (ioc->chip_type == FC929X))
 		mpt_detect_bound_ports(ioc, pdev);
 
 	if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
@@ -1746,7 +1752,7 @@
 /*
  *	mpt_detect_bound_ports - Search for PCI bus/dev_function
  *	which matches PCI bus/dev_function (+/-1) for newly discovered 929,
- *	929X or 1030.
+ *	929X, 1030 or 1035.
  *	@ioc: Pointer to MPT adapter structure
  *	@pdev: Pointer to (struct pci_dev) structure
  *
@@ -1806,8 +1812,7 @@
 		/* Disable the FW */
 		state = mpt_GetIocState(this, 1);
 		if (state == MPI_IOC_STATE_OPERATIONAL) {
-			if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP) != 0)
-				(void) KickStart(this, 1, NO_SLEEP);
+			SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP);
 		}
 
 		if (this->cached_fw != NULL) {
@@ -1819,7 +1824,6 @@
 			}
 		}
 
-
 		/* Disable adapter interrupts! */
 		CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
 		this->active = 0;
@@ -2291,9 +2295,6 @@
 			ioc->reply_sz = ioc->req_sz;
 			ioc->reply_depth = MIN(MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
 
-			/* 1030 - should we use a smaller DEFAULT_REPLY_DEPTH?
-			 * FIX
-			 */
 			dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
 				ioc->name, ioc->reply_sz, ioc->reply_depth));
 			dprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
@@ -2891,6 +2892,7 @@
 	 */
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
 	while ((diag0val & MPI_DIAG_DRWE) == 0) {
+		CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
@@ -3126,6 +3128,18 @@
 	int cnt = 0;
 
 	dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
+	if ((int)ioc->chip_type > (int)FC929) {
+		/* Always issue a Msg Unit Reset first. This will clear some
+		 * SCSI bus hang conditions.
+		 */
+		SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
+
+		if (sleepFlag == CAN_SLEEP) {
+			schedule_timeout(HZ);
+		} else {
+			mdelay (1000);
+		}
+	}
 
 	hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
 	if (hard_reset_done < 0)
@@ -5841,6 +5855,15 @@
 
 	while (! Q_IS_EMPTY(&MptAdapters)) {
 		this = MptAdapters.head;
+
+		/* Disable interrupts! */
+		CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
+
+		this->active = 0;
+
+		/* Clear any lingering interrupt */
+		CHIPREG_WRITE32(&this->chip->IntStatus, 0);
+
 		Q_DEL_ITEM(this);
 		mpt_adapter_dispose(this);
 	}
diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
--- a/drivers/message/fusion/mptbase.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/message/fusion/mptbase.h	Wed Nov 27 14:36:28 2002
@@ -13,7 +13,7 @@
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:Pam.Delaney@lsil.com)
  *
- *  $Id: mptbase.h,v 1.134 2002/10/03 13:10:12 pdelaney Exp $
+ *  $Id: mptbase.h,v 1.136 2002/10/21 13:51:54 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -80,8 +80,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2002 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"2.02.01.07"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-2.02.01.07"
+#define MPT_LINUX_VERSION_COMMON	"2.03.00.02"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-2.03.00.02"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -301,6 +301,7 @@
 	FC919 = 0x0919,
 	FC929 = 0x0929,
 	C1030 = 0x1030,
+	C1035 = 0x1035,
 	FCUNK = 0xFBAD
 } CHIP_TYPE;
 
@@ -368,6 +369,7 @@
 typedef struct _VirtDevice {
 	struct _VirtDevice	*forw;
 	struct _VirtDevice	*back;
+	struct scsi_device	*device;
 	rwlock_t		 VdevLock;
 	int			 ref_cnt;
 	u8			 tflags;
@@ -912,6 +914,10 @@
 	MPT_FRAME_HDR		 *cmdPtr;		/* Ptr to nonOS request */
 	struct scsi_cmnd	 *abortSCpnt;
 	MPT_LOCAL_REPLY		  localReply;		/* internal cmd reply struct */
+	unsigned long		  hard_resets;		/* driver forced bus resets count */
+	unsigned long		  soft_resets;		/* fw/external bus resets count */
+	unsigned long		  timeouts;		/* cmd timeouts */
+	ushort			  sel_timeout[MPT_MAX_FC_DEVICES];
 } MPT_SCSI_HOST;
 
 /*
diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
--- a/drivers/message/fusion/mptctl.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/message/fusion/mptctl.c	Wed Nov 27 14:36:27 2002
@@ -34,7 +34,7 @@
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:Pam.Delaney@lsil.com)
  *
- *  $Id: mptctl.c,v 1.60 2002/10/03 13:10:13 pdelaney Exp $
+ *  $Id: mptctl.c,v 1.61 2002/10/17 20:15:57 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -136,14 +136,8 @@
 static int mptctl_replace_fw (unsigned long arg);
 
 static int mptctl_do_reset(unsigned long arg);
-
-static int mptctl_compaq_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-static int mptctl_cpq_getpciinfo(unsigned long arg);
-static int mptctl_cpq_getdriver(unsigned long arg);
-static int mptctl_cpq_ctlr_status(unsigned long arg);
-static int mptctl_cpq_target_address(unsigned long arg);
-static int mptctl_cpq_passthru(unsigned long arg);
-static int mptctl_compaq_scsiio(VENDOR_IOCTL_REQ *pVenReq, cpqfc_passthru_t *pPass);
+static int mptctl_hp_hostinfo(unsigned long arg);
+static int mptctl_hp_targetinfo(unsigned long arg);
 
 /*
  * Private function calls.
@@ -415,7 +409,7 @@
 	/* Send request
 	 */
 	if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc->id)) == NULL) {
-		dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
+		dctlprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
 				ioctl->ioc->name));
 
 		mptctl_free_tm_flags(ioctl->ioc);
@@ -623,21 +617,13 @@
 	}
 	ret = -ENXIO;				/* (-6) No such device or address */
 
-
-	/* Test for Compaq-specific IOCTL's.
-	 */
-	if ((cmd == CPQFCTS_GETPCIINFO) || (cmd == CPQFCTS_CTLR_STATUS) ||
-		(cmd == CPQFCTS_GETDRIVVER) || (cmd == CPQFCTS_SCSI_PASSTHRU) ||
-		(cmd == CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS))
-		return mptctl_compaq_ioctl(file, cmd, arg);
-
 	/* Verify intended MPT adapter - set iocnum and the adapter
 	 * pointer (iocp)
 	 */
 	iocnumX = khdr.iocnum & 0xFF;
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	    (iocp == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_ioctl() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_ioctl() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnumX));
 		return -ENODEV;
 	}
@@ -683,6 +669,12 @@
 	case MPTHARDRESET:
 		ret = mptctl_do_reset(arg);
 		break;
+	case HP_GETHOSTINFO:
+		ret = mptctl_hp_hostinfo(arg);
+		break;
+	case HP_GETTARGETINFO:
+		ret = mptctl_hp_targetinfo(arg);
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -708,7 +700,7 @@
 	}
 
 	if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
-		dtmprintk((KERN_ERR "%s@%d::mptctl_do_reset - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s@%d::mptctl_do_reset - ioc%d not found!\n",
 				__FILE__, __LINE__, krinfo.hdr.iocnum));
 		return -ENODEV; /* (-6) No such device or address */
 	}
@@ -816,7 +808,7 @@
 	dctlprintk((KERN_INFO "DbG: kfwdl.ioc   = %04xh\n", ioc));
 
 	if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) {
-		dtmprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n",
+		dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n",
 				__FILE__, __LINE__, ioc));
 		return -ENODEV; /* (-6) No such device or address */
 	}
@@ -1252,7 +1244,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1379,7 +1371,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1510,7 +1502,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1568,7 +1560,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1606,7 +1598,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1654,7 +1646,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1708,7 +1700,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1794,7 +1786,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1842,7 +1834,7 @@
 
 	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
@@ -1926,6 +1918,14 @@
 			int target = (int) pScsiReq->TargetID;
 			int dataSize;
 
+			if ((target < 0) || (target >= ioc->sh->max_id)) {
+				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+					"Target ID out of bounds. \n",
+					__FILE__, __LINE__);
+				rc = -ENODEV;
+				goto done_free_mem;
+			}
+
 			pScsiReq->MsgFlags = mpt_msg_flags();
 
 			/* verify that app has not requested
@@ -2049,9 +2049,37 @@
 		}
 		break;
 
+	case MPI_FUNCTION_IOC_INIT:
+		{
+			IOCInit_t	*pInit = (IOCInit_t *) mf;
+			u32		high_addr, sense_high;
+
+			/* Verify that all entries in the IOC INIT match
+			 * existing setup (and in LE format).
+			 */
+			if (sizeof(dma_addr_t) == sizeof(u64)) {
+				high_addr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
+				sense_high= cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
+			} else {
+				high_addr = 0;
+				sense_high= 0;
+			}
+
+			if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) ||
+				(pInit->MaxBuses != ioc->facts.MaxBuses) || 
+				(pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) ||
+				(pInit->HostMfaHighAddr != high_addr) ||
+				(pInit->SenseBufferHighAddr != sense_high)) {
+				printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+					"IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n",
+					__FILE__, __LINE__);
+				rc = -EFAULT;
+				goto done_free_mem;
+			}
+		}
+		break;
 	default:
 		/*
-		 * MPI_FUNCTION_IOC_INIT
 		 * MPI_FUNCTION_PORT_ENABLE
 		 * MPI_FUNCTION_TARGET_CMD_BUFFER_POST
 		 * MPI_FUNCTION_TARGET_ASSIST
@@ -2357,131 +2385,85 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Routine for the Compaq IOCTL commands.
+/* Prototype Routine for the HP HOST INFO command.
  *
  * Outputs:	None.
  * Return:	0 if successful
- *		-EBUSY  if previous command timout and IOC reset is not complete.
  *		-EFAULT if data unavailable
- *		-ENODEV if no such device/adapter
- *		-ETIME	if timer expires
- *		-ENOMEM if memory allocation error
- */
-static int
-mptctl_compaq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int iocnum = 0;
-	unsigned iocnumX = 0;
-	int ret;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	MPT_ADAPTER *iocp = NULL;
-
-	if (cmd == CPQFCTS_SCSI_PASSTHRU) {
-		/* Update the iocnum */
-		if (copy_from_user(&iocnumX, (int *)arg, sizeof(int))) {
-			printk(KERN_ERR "%s::mptctl_compaq_ioctl() @%d - "
-				"Unable to read controller number @ %p\n",
-				__FILE__, __LINE__, (void*)arg);
-			return -EFAULT;
-		}
-		iocnumX &= 0xFF;
-	}
-
-	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
-	    (iocp == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_compaq_ioctl() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnumX));
-		return -ENODEV;
-	}
-
-	/* All of these commands require an interrupt or
-	 * are unknown/illegal.
-	 */
-	if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
-		return ret;
-
-	dctlprintk((MYIOC_s_INFO_FMT ": mptctl_compaq_ioctl()\n", iocp->name));
-
-	switch(cmd) {
-	case CPQFCTS_GETPCIINFO:
-		ret = mptctl_cpq_getpciinfo(arg);
-		break;
-	case CPQFCTS_GETDRIVVER:
-		ret = mptctl_cpq_getdriver(arg);
-		break;
-	case CPQFCTS_CTLR_STATUS:
-		ret = mptctl_cpq_ctlr_status(arg);
-		break;
-	case CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS:
-		ret = mptctl_cpq_target_address(arg);
-		break;
-	case CPQFCTS_SCSI_PASSTHRU:
-		ret = mptctl_cpq_passthru(arg);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
-
-	return ret;
-
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_cpq_getpciinfo - Get PCI Information in format desired by Compaq
- *
- * Outputs:	None.
- * Return:	0 if successful
  *		-EBUSY  if previous command timout and IOC reset is not complete.
- *		-EFAULT if data unavailable
  *		-ENODEV if no such device/adapter
  *		-ETIME	if timer expires
+ *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_cpq_getpciinfo(unsigned long arg)
+mptctl_hp_hostinfo(unsigned long arg)
 {
-	cpqfc_pci_info_struct *uarg = (cpqfc_pci_info_struct *) arg;
-	cpqfc_pci_info_struct karg;
+	hp_host_info_t	*uarg = (hp_host_info_t *) arg;
 	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
+	char			*pbuf;
+	dma_addr_t		buf_dma;
+	hp_host_info_t		karg;
 	CONFIGPARMS		cfg;
 	ConfigPageHeader_t	hdr;
-	int			iocnum = 0, iocnumX = 0;
-	dma_addr_t		buf_dma;
-	u8			*pbuf = NULL;
-	int			failed;
+	int			iocnum;
+	int			rc;
 
-	dctlprintk((": mptctl_cpq_pciinfo called.\n"));
-	if (copy_from_user(&karg, uarg, sizeof(cpqfc_pci_info_struct))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_pciinfo - "
-			"Unable to read in cpqfc_pci_info_struct @ %p\n",
+	dctlprintk((": mptctl_hp_hostinfo called.\n"));
+	if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) {
+		printk(KERN_ERR "%s@%d::mptctl_hp_host_info - "
+			"Unable to read in hp_host_info struct @ %p\n",
 				__FILE__, __LINE__, (void*)uarg);
-		return -EINVAL;
+		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) ||
+	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
 	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_pciinfo() @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
 
+	/* Fill in the data and return the structure to the calling
+	 * program
+	 */
 	pdev = (struct pci_dev *) ioc->pcidev;
 
-	/* Populate the structure. */
-	karg.bus = pdev->bus->number;
-	karg.bus_type = 1;	/* 1 = PCI; 4 = unknown */
-	karg.device_fn = PCI_FUNC(pdev->devfn);
-	karg.slot_number = PCI_SLOT(pdev->devfn);
-	karg.vendor_id = pdev->vendor;
-	karg.device_id = pdev->device;
-	karg.board_id = (karg.device_id | (karg.vendor_id << 16));
-	karg.class_code = pdev->class;
+	karg.vendor = pdev->vendor;
+	karg.device = pdev->device;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-	karg.sub_vendor_id = pdev->subsystem_vendor;
-	karg.sub_device_id = pdev->subsystem_device;
+	karg.subsystem_id = pdev->subsystem_device;
+	karg.subsystem_vendor = pdev->subsystem_vendor;
 #endif
+	karg.devfn = pdev->devfn;
+	karg.bus = pdev->bus->number;
+
+	/* Save the SCSI host no. if
+	 * SCSI driver loaded 
+	 */
+	if (ioc->sh != NULL)
+		karg.host_no = ioc->sh->host_no;
+	else
+		karg.host_no =  -1;
+
+	/* Reformat the fw_version into a string
+	 */
+	karg.fw_version[0] = ioc->facts.FWVersion.Struct.Major >= 10 ?
+		((ioc->facts.FWVersion.Struct.Major / 10) + '0') : '0';
+	karg.fw_version[1] = (ioc->facts.FWVersion.Struct.Major % 10 ) + '0';
+	karg.fw_version[2] = '.';
+	karg.fw_version[3] = ioc->facts.FWVersion.Struct.Minor >= 10 ?
+		((ioc->facts.FWVersion.Struct.Minor / 10) + '0') : '0';
+	karg.fw_version[4] = (ioc->facts.FWVersion.Struct.Minor % 10 ) + '0';
+	karg.fw_version[5] = '.';
+	karg.fw_version[6] = ioc->facts.FWVersion.Struct.Unit >= 10 ?
+		((ioc->facts.FWVersion.Struct.Unit / 10) + '0') : '0';
+	karg.fw_version[7] = (ioc->facts.FWVersion.Struct.Unit % 10 ) + '0';
+	karg.fw_version[8] = '.';
+	karg.fw_version[9] = ioc->facts.FWVersion.Struct.Dev >= 10 ?
+		((ioc->facts.FWVersion.Struct.Dev / 10) + '0') : '0';
+	karg.fw_version[10] = (ioc->facts.FWVersion.Struct.Dev % 10 ) + '0';
+	karg.fw_version[11] = '\0';
 
 	/* Issue a config request to get the device serial number
 	 */
@@ -2496,8 +2478,7 @@
 	cfg.dir = 0;	/* read */
 	cfg.timeout = 10;
 
-	failed = 1;
-
+	strncpy(karg.serial_number, " ", 24);
 	if (mpt_config(ioc, &cfg) == 0) {
 		if (cfg.hdr->PageLength > 0) {
 			/* Issue the second config page request */
@@ -2508,242 +2489,207 @@
 				cfg.physAddr = buf_dma;
 				if (mpt_config(ioc, &cfg) == 0) {
 					ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf;
-					strncpy(karg.serial_number, pdata->BoardTracerNumber, 17);
-					failed = 0;
+					if (strlen(pdata->BoardTracerNumber) > 1)
+						strncpy(karg.serial_number, pdata->BoardTracerNumber, 24);
 				}
 				pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
 				pbuf = NULL;
 			}
 		}
 	}
-	if (failed)
-		strncpy(karg.serial_number, " ", 17);
-
-	/* Copy the data from kernel memory to user memory
-	 */
-	if (copy_to_user((char *)arg, &karg,
-				sizeof(cpqfc_pci_info_struct))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_pciinfo - "
-			"Unable to write out cpqfc_pci_info_struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
-		return -EFAULT;
-	}
+	rc = mpt_GetIocState(ioc, 1);
+	switch (rc) {
+	case MPI_IOC_STATE_OPERATIONAL:
+		karg.ioc_status =  HP_STATUS_OK;
+		break;
 
-	return 0;
-}
+	case MPI_IOC_STATE_FAULT:
+		karg.ioc_status =  HP_STATUS_FAILED;
+		break;
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_cpq_getdriver - Get Driver Version in format desired by Compaq
- *
- * Outputs:	None.
- * Return:	0 if successful
- *		-EFAULT if data unavailable
- *		-ENODEV if no such device/adapter
- */
-static int
-mptctl_cpq_getdriver(unsigned long arg)
-{
-	int		*uarg = (int *)arg;
-	int		karg;
-	MPT_ADAPTER	*ioc = NULL;
-	int		iocnum = 0, iocnumX = 0;
-	int		ii, jj;
-	char		version[10];
-	char		val;
-	char		*vptr = NULL;
-	char		*pptr = NULL;
-
-	dctlprintk((": mptctl_cpq_getdriver called.\n"));
-	if (copy_from_user(&karg, uarg, sizeof(int))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_getdriver - "
-			"Unable to read in struct @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
-		return -EFAULT;
+	case MPI_IOC_STATE_RESET:
+	case MPI_IOC_STATE_READY:
+	default:
+		karg.ioc_status =  HP_STATUS_OTHER;
+		break;
 	}
 
-	if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_cpq_getdriver() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum));
-		return -ENODEV;
-	}
+	karg.base_io_addr = pdev->PCI_BASEADDR_START(0);
 
-	strncpy(version, MPT_LINUX_VERSION_COMMON, 8);
+	if ((int)ioc->chip_type <= (int) FC929)
+		karg.bus_phys_width = HP_BUS_WIDTH_UNK;
+	else
+		karg.bus_phys_width = HP_BUS_WIDTH_16;
 
-	karg = 0;
-	vptr = version;
-	ii = 3;
-	while (ii > 0) {
-		pptr = strchr(vptr, '.');
-		if (pptr) {
-			*pptr = '\0';
-			val = 0;
-			for (jj=0; vptr[jj]>='0' && vptr[jj]<='9'; jj++)
-				val = 10 * val + (vptr[jj] - '0');
-			karg |= (val << (8*ii));
-			pptr++;
-			vptr = pptr;
-		} else
-			break;
-		ii--;
+	karg.hard_resets = 0;
+	karg.soft_resets = 0;
+	karg.timeouts = 0;
+	if (ioc->sh != NULL) {
+		MPT_SCSI_HOST *hd =  (MPT_SCSI_HOST *)ioc->sh->hostdata;
+
+		if (hd) {
+			karg.hard_resets = hd->hard_resets;
+			karg.soft_resets = hd->soft_resets;
+			karg.timeouts = hd->timeouts;
+		}
 	}
 
 	/* Copy the data from kernel memory to user memory
 	 */
 	if (copy_to_user((char *)arg, &karg,
-				sizeof(int))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_getdriver - "
-			"Unable to write out stuct @ %p\n",
+				sizeof(hp_host_info_t))) {
+		printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - "
+			"Unable to write out hp_host_info @ %p\n",
 				__FILE__, __LINE__, (void*)uarg);
 		return -EFAULT;
 	}
 
 	return 0;
+
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_cpq_ctlr_status - Get controller status in format desired by Compaq
+/* Prototype Routine for the HP TARGET INFO command.
  *
  * Outputs:	None.
  * Return:	0 if successful
  *		-EFAULT if data unavailable
+ *		-EBUSY  if previous command timout and IOC reset is not complete.
  *		-ENODEV if no such device/adapter
+ *		-ETIME	if timer expires
+ *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_cpq_ctlr_status(unsigned long arg)
+mptctl_hp_targetinfo(unsigned long arg)
 {
-	cpqfc_ctlr_status *uarg = (cpqfc_ctlr_status *) arg;
-	cpqfc_ctlr_status karg;
+	hp_target_info_t	*uarg = (hp_target_info_t *) arg;
+	SCSIDevicePage0_t	*pg0_alloc;
+	SCSIDevicePage3_t	*pg3_alloc;
 	MPT_ADAPTER		*ioc;
-	int			iocnum = 0, iocnumX = 0;
+	MPT_SCSI_HOST 		*hd = NULL;
+	hp_target_info_t	karg;
+	int			iocnum;
+	int			data_sz;
+	dma_addr_t		page_dma;
+	CONFIGPARMS	 	cfg;
+	ConfigPageHeader_t	hdr;
+	int			tmp, np, rc = 0;
 
-	dctlprintk((": mptctl_cpq_pciinfo called.\n"));
-	if (copy_from_user(&karg, uarg, sizeof(cpqfc_ctlr_status))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_ctlr_status - "
-			"Unable to read in cpqfc_ctlr_status @ %p\n",
+	dctlprintk((": mptctl_hp_targetinfo called.\n"));
+	if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) {
+		printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - "
+			"Unable to read in hp_host_targetinfo struct @ %p\n",
 				__FILE__, __LINE__, (void*)uarg);
 		return -EFAULT;
 	}
-
-	if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_cpq_ctlr_status() @%d - ioc%d not found!\n",
+	
+	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+		(ioc == NULL)) {
+		dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
 				__FILE__, __LINE__, iocnum));
 		return -ENODEV;
 	}
 
-	karg.status = ioc->last_state;
-	karg.offline_reason = 0;
-
-	/* Copy the data from kernel memory to user memory
+	/*  There is nothing to do for FCP parts.
 	 */
-	if (copy_to_user((char *)arg, &karg,
-				sizeof(cpqfc_ctlr_status))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_ctlr_status - "
-			"Unable to write out cpqfc_ctlr_status @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
-		return -EFAULT;
-	}
-
-	return 0;
-}
+	if ((int) ioc->chip_type <= (int) FC929)
+		return 0;
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_cpq_target_address - Get WWN Information in format desired by Compaq
- *
- * Outputs:	None.
- * Return:	0 if successful
- *		-EBUSY  if previous command timout and IOC reset is not complete.
- *		-EFAULT if data unavailable
- *		-ENODEV if no such device/adapter
- *		-ETIME	if timer expires
- */
-static int
-mptctl_cpq_target_address(unsigned long arg)
-{
-	Scsi_FCTargAddress *uarg = (Scsi_FCTargAddress *) arg;
-	Scsi_FCTargAddress karg;
-	MPT_ADAPTER		*ioc;
-	int			iocnum = 0, iocnumX = 0;
-	CONFIGPARMS		cfg;
-	ConfigPageHeader_t	hdr;
-	dma_addr_t		buf_dma;
-	u8			*pbuf = NULL;
-	FCPortPage0_t		*ppp0;
-	int			ii, failed;
-	u32			low, high;
-
-	dctlprintk((": mptctl_cpq_target_address called.\n"));
-	if (copy_from_user(&karg, uarg, sizeof(Scsi_FCTargAddress))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_target_address - "
-			"Unable to read in Scsi_FCTargAddress @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
-		return -EFAULT;
-	}
+	if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL))
+		return 0;
 
-	if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_cpq_target_address() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum));
+	if (ioc->sh->host_no != karg.hdr.host)
 		return -ENODEV;
-	}
-
-	karg.host_port_id = 0;
+		
+       /* Get the data transfer speeds
+        */
+	data_sz = ioc->spi_data.sdp0length * 4;
+	pg0_alloc = (SCSIDevicePage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
+	if (pg0_alloc) {
+		hdr.PageVersion = ioc->spi_data.sdp0version;
+		hdr.PageLength = data_sz;
+		hdr.PageNumber = 0;
+		hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
+		cfg.hdr = &hdr;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+		cfg.dir = 0;
+		cfg.timeout = 0;
+		cfg.physAddr = page_dma;
+
+		cfg.pageAddr = (karg.hdr.channel << 8) | karg.hdr.id;
+
+		if ((rc = mpt_config(ioc, &cfg)) == 0) {
+			np = le32_to_cpu(pg0_alloc->NegotiatedParameters);
+			karg.negotiated_width = np & MPI_SCSIDEVPAGE0_NP_WIDE ? 
+					HP_BUS_WIDTH_16 : HP_BUS_WIDTH_8;
+
+			if (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) {
+				tmp = (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
+				if (tmp < 0x09)
+					karg.negotiated_speed = HP_DEV_SPEED_ULTRA320;
+				else if (tmp <= 0x09)
+					karg.negotiated_speed = HP_DEV_SPEED_ULTRA160;
+				else if (tmp <= 0x0A)
+					karg.negotiated_speed = HP_DEV_SPEED_ULTRA2;
+				else if (tmp <= 0x0C)
+					karg.negotiated_speed = HP_DEV_SPEED_ULTRA;
+				else if (tmp <= 0x25)
+					karg.negotiated_speed = HP_DEV_SPEED_FAST;
+				else
+					karg.negotiated_speed = HP_DEV_SPEED_ASYNC;
+			} else
+				karg.negotiated_speed = HP_DEV_SPEED_ASYNC;
+		}
+
+		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg0_alloc, page_dma);
+	}
+
+	/* Set defaults
+	 */
+	karg.message_rejects = -1;
+	karg.phase_errors = -1;
+	karg.parity_errors = -1;
+	karg.select_timeouts = -1;
 
-	/* Issue a config request to get the device wwn
+	/* Get the target error parameters
 	 */
 	hdr.PageVersion = 0;
 	hdr.PageLength = 0;
-	hdr.PageNumber = 0;
-	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
+	hdr.PageNumber = 3;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
 	cfg.hdr = &hdr;
-	cfg.physAddr = -1;
-	cfg.pageAddr = 0;
 	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
-	cfg.dir = 0;	/* read */
-	cfg.timeout = 10;
-
-	failed = 1;
-
-	if (mpt_config(ioc, &cfg) == 0) {
-		if (cfg.hdr->PageLength > 0) {
-			/* Issue the second config page request */
-			cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-
-			pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
-			if (pbuf) {
-				cfg.physAddr = buf_dma;
-				if (mpt_config(ioc, &cfg) == 0) {
-					ppp0 = (FCPortPage0_t *) pbuf;
-
-					low = le32_to_cpu(ppp0->WWNN.Low);
-					high = le32_to_cpu(ppp0->WWNN.High);
-
-					for (ii = 0; ii < 4; ii++) {
-						karg.host_wwn[7-ii] = low & 0xFF;
-						karg.host_wwn[3-ii] = high & 0xFF;
-						low = (low >> 8);
-						high = (high >> 8);
-					}
-					failed = 0;
-				}
-				pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
-				pbuf = NULL;
+	cfg.dir = 0;
+	cfg.timeout = 0;
+	cfg.physAddr = -1;
+	if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) {
+		/* Issue the second config page request */
+		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+		data_sz = (int) cfg.hdr->PageLength * 4;
+		pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent(
+							ioc->pcidev, data_sz, &page_dma);
+		if (pg3_alloc) {
+			cfg.physAddr = page_dma;
+			cfg.pageAddr = (karg.hdr.channel << 8) | karg.hdr.id;
+			if ((rc = mpt_config(ioc, &cfg)) == 0) {
+				karg.message_rejects = (u32) le16_to_cpu(pg3_alloc->MsgRejectCount);
+				karg.phase_errors = (u32) le16_to_cpu(pg3_alloc->PhaseErrorCount);
+				karg.parity_errors = (u32) le16_to_cpu(pg3_alloc->ParityErrorCount);
 			}
+			pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg3_alloc, page_dma);
 		}
 	}
-
-	if (failed) {
-		for (ii = 7; ii >= 0; ii--)
-			karg.host_wwn[ii] = 0;
-	}
+	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+	if (hd != NULL)
+		karg.select_timeouts = hd->sel_timeout[karg.hdr.id];
 
 	/* Copy the data from kernel memory to user memory
 	 */
-	if (copy_to_user((char *)arg, &karg,
-				sizeof(Scsi_FCTargAddress))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_target_address - "
-			"Unable to write out Scsi_FCTargAddress @ %p\n",
+	if (copy_to_user((char *)arg, &karg, sizeof(hp_target_info_t))) {
+		printk(KERN_ERR "%s@%d::mptctl_hp_target_info - "
+			"Unable to write out mpt_ioctl_targetinfo struct @ %p\n",
 				__FILE__, __LINE__, (void*)uarg);
 		return -EFAULT;
 	}
@@ -2752,161 +2698,6 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_cpq_passthru - Construct and issue a SCSI IO Passthru
- *
- * Requires the SCSI host driver to be loaded.
- * I386 version.
- *
- * Outputs:	None.
- * Return:	0 if successful
- *		-EBUSY  if previous command timout and IOC reset is not complete.
- *		-EFAULT if data unavailable
- *		-ENODEV if no such device/adapter
- *		-ETIME	if timer expires
- */
-static int
-mptctl_cpq_passthru(unsigned long arg)
-{
-	VENDOR_IOCTL_REQ	*uarg = (VENDOR_IOCTL_REQ *) arg;
-	VENDOR_IOCTL_REQ	karg;
-	cpqfc_passthru_t	kpass;
-	MPT_ADAPTER		*ioc;
-	int			iocnum = 0, iocnumX = 0;
-	int			rc;
-
-	dctlprintk((": mptctl_cpq_passthru called.\n"));
-	if (copy_from_user(&karg, uarg, sizeof(VENDOR_IOCTL_REQ))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_passthru - "
-			"Unable to read in VENDOR_IOCTL_REQ @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
-		return -EFAULT;
-	}
-
-	/* Set the IOC number */
-	iocnumX = karg.lc & 0xFF;
-	if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR "%s::mptctl_cpq_passthru() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum));
-		return -ENODEV;
-	}
-
-	if (ioc->sh == NULL) {
-		printk(KERN_ERR "%s::mptctl_cpq_passthru() @%d - SCSI Host driver not loaded!\n",
-				__FILE__, __LINE__);
-		return -EFAULT;
-	}
-
-	/* Read in the second buffer */
-	if (copy_from_user(&kpass, uarg->argp, sizeof(cpqfc_passthru_t))) {
-		printk(KERN_ERR "%s@%d::mptctl_cpq_passthru - "
-			"Unable to read in cpqfc_passthru_t @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
-		return -EFAULT;
-	}
-
-
-	/* Generate the SCSI IO command and issue */
-	rc = mptctl_compaq_scsiio(&karg, &kpass);
-	return rc;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_compaq_scsiio - Reformat Compaq structures into driver structures
- * Call the generic _do_mpt_command function.
- *
- * Requires the SCSI host driver to be loaded.
- * I386 version.
- *
- * Outputs:	None.
- * Return:	0 if successful
- *		-EBUSY  if previous command timout and IOC reset is not complete.
- *		-EFAULT if data unavailable
- *		-ENODEV if no such device/adapter
- *		-ETIME	if timer expires
- */
-static int
-mptctl_compaq_scsiio(VENDOR_IOCTL_REQ *pVenReq, cpqfc_passthru_t *pPass)
-{
-	struct mpt_ioctl_command karg;
-	SCSIIORequest_t		 request ;
-	SCSIIORequest_t		 *pMf;
-	int			 ii, rc;
-	u8			 opcode;
-
-	/* Fill in parameters to karg */
-	karg.hdr.iocnum = pVenReq->lc;
-	karg.hdr.port = 0;
-	karg.hdr.maxDataSize = 0;	/* not used */
-	karg.timeout = 0;		/* use default */
-
-	karg.replyFrameBufPtr = NULL;	/* no reply data */
-	karg.maxReplyBytes = 0;
-
-	karg.senseDataPtr = pPass->sense_data;
-	karg.maxSenseBytes = pPass->sense_len;	/* max is 40 */
-
-	if (pPass->rw_flag == MPT_COMPAQ_WRITE) {
-		karg.dataOutBufPtr = pPass->bufp;
-		karg.dataOutSize = pPass->len;
-		karg.dataInBufPtr = NULL;
-		karg.dataInSize = 0;
-	} else {
-		karg.dataInBufPtr = pPass->bufp;
-		karg.dataInSize = pPass->len;
-		karg.dataOutBufPtr = NULL;
-		karg.dataOutSize = 0;
-	}
-
-	karg.dataSgeOffset = (sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION))/4;
-
-	/* Construct the Message frame */
-	pMf = &request;
-
-	pMf->TargetID =	(u8) pVenReq->ld;			/* ???? FIXME */
-	pMf->Bus = (u8) pPass->bus;
-	pMf->ChainOffset = 0;
-	pMf->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
-
-	/* May need some tweaking here */
-	opcode = (u8) pPass->cdb[0];
-	if (opcode < 0x20)
-		pMf->CDBLength = 6;
-	else if (opcode < 0x60)
-		pMf->CDBLength = 10;
-	else if ((opcode < 0xC0) && (opcode >= 0xA0))
-		pMf->CDBLength = 12;
-	else
-		pMf->CDBLength = 16;
-
-	pMf->SenseBufferLength = karg.maxSenseBytes;	/* max is 40 */
-	pMf->Reserved = 0;
-	pMf->MsgFlags = 0;				/* set later */
-	pMf->MsgContext = 0;				/* set later */
-
-	for (ii = 0; ii < 8; ii++)
-		pMf->LUN[ii] = 0;
-	pMf->LUN[1] = 0;				/* ???? FIXME */
-
-	/* Tag values set by _do_mpt_command */
-	if (pPass->rw_flag == MPT_COMPAQ_WRITE)
-		pMf->Control = MPI_SCSIIO_CONTROL_WRITE;
-	else
-		pMf->Control = MPI_SCSIIO_CONTROL_READ;
-
-	for (ii = 0; ii < 16; ii++)
-		pMf->CDB[ii] = pPass->cdb[ii];
-
-	pMf->DataLength = pPass->len;
-
-	/* All remaining fields are set by the next function
-	 */
-	rc = mptctl_do_mpt_command (karg, (char *)pMf, 1);
-	return rc;
-}
-
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51)
 #define	owner_THIS_MODULE  owner:		THIS_MODULE,
@@ -2971,7 +2762,7 @@
 	iocnumX = kfw32.iocnum & 0xFF;
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	    (iocp == NULL)) {
-		dtmprintk((KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n",
 				__LINE__, iocnumX));
 		return -ENODEV;
 	}
@@ -3011,7 +2802,7 @@
 	iocnumX = karg32.hdr.iocnum & 0xFF;
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
 	    (iocp == NULL)) {
-		dtmprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n",
+		dctlprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n",
 				__LINE__, iocnumX));
 		return -ENODEV;
 	}
@@ -3044,70 +2835,6 @@
 	return ret;
 }
 
-static int
-sparc32_mptctl_cpq_passthru(unsigned int fd, unsigned int cmd,
-			unsigned long arg, struct file *filp)
-{
-	VENDOR_IOCTL_REQ32	*uarg = (VENDOR_IOCTL_REQ32 *) arg;
-	VENDOR_IOCTL_REQ32	karg32;
-	VENDOR_IOCTL_REQ	karg;
-	cpqfc_passthru32_t	kpass32;
-	cpqfc_passthru_t	kpass;
-	MPT_ADAPTER		*ioc;
-	int			nonblock = (filp->f_flags & O_NONBLOCK);
-	int			iocnum = 0, iocnumX = 0;
-	int			rc;
-	int			ii;
-
-	dctlprintk((KERN_INFO MYNAM "::sparc32_mptctl_cpq_passthru() called\n"));
-
-	if (copy_from_user(&karg32, (char *)arg, sizeof(karg32)))
-		return -EFAULT;
-
-	/* Verify intended MPT adapter */
-	iocnumX = karg32.lc & 0xFF;
-	if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		dtmprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n",
-				__LINE__, iocnumX));
-		return -ENODEV;
-	}
-
-	if ((rc = mptctl_syscall_down(ioc, nonblock)) != 0)
-		return rc;
-
-	/* Copy data to karg */
-	karg.ld = karg32.ld;
-	karg.node = karg32.node;
-	karg.lc = karg32.lc;
-	karg.nexus = karg32.nexus;
-	karg.argp = (void *)(unsigned long)karg32.argp;
-
-	/* Read in the second buffer */
-	if (copy_from_user(&kpass32, karg.argp, sizeof(cpqfc_passthru32_t))) {
-		printk(KERN_ERR "%s@%d::sparc32_mptctl_cpq_passthru - "
-			"Unable to read in cpqfc_passthru_t @ %p\n",
-				__FILE__, __LINE__, (void*)uarg);
-		return -EFAULT;
-	}
-
-	/* Copy the 32bit buffer to kpass */
-	for (ii = 0; ii < 16; ii++)
-		kpass.cdb[ii] = kpass32.cdb[ii];
-	kpass.bus = kpass32.bus;
-	kpass.pdrive = kpass32.pdrive;
-	kpass.len = kpass32.len;
-	kpass.sense_len = kpass32.sense_len;
-	kpass.bufp = (void *)(unsigned long)kpass32.bufp;
-	kpass.rw_flag = kpass32.rw_flag;
-
-	/* Generate the SCSI IO command and issue */
-	rc = mptctl_compaq_scsiio(&karg, &kpass);
-
-	up(&mptctl_syscall_sem_ioc[ioc->id]);
-	return rc;
-}
-
 #endif		/*} linux >= 2.3.x */
 #endif		/*} sparc */
 
@@ -3176,15 +2903,9 @@
 	err = register_ioctl32_conversion(MPTFWDOWNLOAD32,
 					  sparc32_mptfwxfer_ioctl);
 	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(CPQFCTS_GETPCIINFO, NULL);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(CPQFCTS_CTLR_STATUS, NULL);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(CPQFCTS_GETDRIVVER, NULL);
-	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS, NULL);
+	err = register_ioctl32_conversion(HP_GETHOSTINFO, NULL);
 	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(CPQFCTS_SCSI_PASSTHRU32, sparc32_mptctl_cpq_passthru);
+	err = register_ioctl32_conversion(HP_GETTARGETINFO, NULL);
 	if (++where && err) goto out_fail;
 #endif		/*} linux >= 2.3.x */
 #endif		/*} sparc */
@@ -3233,11 +2954,8 @@
 	unregister_ioctl32_conversion(MPTHARDRESET);
 	unregister_ioctl32_conversion(MPTCOMMAND32);
 	unregister_ioctl32_conversion(MPTFWDOWNLOAD32);
-	unregister_ioctl32_conversion(CPQFCTS_GETPCIINFO);
-	unregister_ioctl32_conversion(CPQFCTS_GETDRIVVER);
-	unregister_ioctl32_conversion(CPQFCTS_CTLR_STATUS);
-	unregister_ioctl32_conversion(CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS);
-	unregister_ioctl32_conversion(CPQFCTS_SCSI_PASSTHRU32);
+	unregister_ioctl32_conversion(HP_GETHOSTINFO);
+	unregister_ioctl32_conversion(HP_GETTARGETINFO);
 #endif		/*} linux >= 2.3.x */
 #endif		/*} sparc */
 
diff -Nru a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
--- a/drivers/message/fusion/mptctl.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/message/fusion/mptctl.h	Wed Nov 27 14:36:30 2002
@@ -20,7 +20,7 @@
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:Pam.Delaney@lsil.com)
  *
- *  $Id: mptctl.h,v 1.11 2002/10/03 13:10:13 pdelaney Exp $
+ *  $Id: mptctl.h,v 1.12 2002/10/17 20:15:58 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -310,95 +310,91 @@
 #endif	/*}*/
 
 
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
- /*
-  *	COMPAQ Specific IOCTL Defines and Structures
-  */
+/*
+ *	HP Specific IOCTL Defines and Structures
+ */
 
 #define CPQFCTS_IOC_MAGIC 'Z'
+#define HP_IOC_MAGIC 'Z'
+#define HP_GETHOSTINFO		_IOR(HP_IOC_MAGIC, 20, hp_host_info_t)
+#define HP_GETTARGETINFO	_IOR(HP_IOC_MAGIC, 21, hp_target_info_t)
 
-#define CPQFCTS_GETPCIINFO		_IOR(CPQFCTS_IOC_MAGIC, 1, cpqfc_pci_info_struct)
-#define CPQFCTS_GETDRIVVER		_IOR(CPQFCTS_IOC_MAGIC, 9, int)
-#define CPQFCTS_CTLR_STATUS		_IOR(CPQFCTS_IOC_MAGIC, 3, struct _cpqfc_ctlr_status)
-#define CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS	_IOR(CPQFCTS_IOC_MAGIC, 13, struct scsi_fctargaddress)
-#define CPQFCTS_SCSI_PASSTHRU		_IOWR(CPQFCTS_IOC_MAGIC, 11, VENDOR_IOCTL_REQ)
-#if defined(__sparc__) && defined(__sparc_v9__)
-#define CPQFCTS_SCSI_PASSTHRU32		_IOWR(CPQFCTS_IOC_MAGIC, 11, VENDOR_IOCTL_REQ32)
-#endif
-
-typedef struct {
-	unsigned short bus;
-	unsigned short bus_type;
-	unsigned short device_fn;
-	u32 board_id;
-	u32 slot_number;
-	unsigned short vendor_id;
-	unsigned short device_id;
-	unsigned short class_code;
-	unsigned short sub_vendor_id;
-	unsigned short sub_device_id;
-	u8 serial_number[81];
-} cpqfc_pci_info_struct;
-
-
-typedef struct scsi_fctargaddress {
-	unsigned int host_port_id;
-	u8 host_wwn[8];	/* WW Network Name */
-} Scsi_FCTargAddress;
-
-typedef struct _cpqfc_ctlr_status {
-	u32 status;
-	u32 offline_reason;
-} cpqfc_ctlr_status;
-
-
-/* Compaq SCSI I/O Passthru structures.
+/* All HP IOCTLs must include this header
  */
-#define MPT_COMPAQ_READ		0x26
-#define MPT_COMPAQ_WRITE	0x27
-
-typedef struct {
-	int lc;		/* controller number */
-	int node;	/* node number */
-	int ld;		/* target logical id */
-	u32 nexus;
-	void *argp;
-} VENDOR_IOCTL_REQ;
-
-#if defined(__KERNEL__) && defined(__sparc__) && defined(__sparc_v9__)		/*{*/
-typedef struct {
-	int lc;		/* controller number */
-	int node;	/* node number */
-	int ld;		/* target logical id */
-	u32 nexus;
-	u32 argp;
-} VENDOR_IOCTL_REQ32;
-#endif
-
-typedef struct {
-	char cdb[16];		/* cdb */
-	unsigned short bus;	/* bus number */
-	unsigned short pdrive;	/* physical drive */
-	int len;		/* data area size */
-	int sense_len;		/* sense size */
-	char sense_data[40];	/* sense buffer */
-	void *bufp;		/* data buffer pointer */
-	char rw_flag;
-} cpqfc_passthru_t;
-
-#if defined(__KERNEL__) && defined(__sparc__) && defined(__sparc_v9__)		/*{*/
-typedef struct {
-	char cdb[16];		/* cdb */
-	unsigned short bus;	/* bus number */
-	unsigned short pdrive;	/* physical drive */
-	int len;		/* data area size */
-	int sense_len;		/* sense size */
-	char sense_data[40];	/* sense buffer */
-	u32 bufp;		/* data buffer pointer */
-	char rw_flag;
-} cpqfc_passthru32_t;
-#endif
+typedef struct _hp_header {
+	unsigned int iocnum;
+	unsigned int host;
+	unsigned int channel;
+	unsigned int id;
+	unsigned int lun;
+} hp_header_t;
+
+/*  
+ *  Header:
+ *  iocnum 	required (input)
+ *  host 	ignored	
+ *  channe	ignored
+ *  id		ignored
+ *  lun		ignored
+ */
+typedef struct _hp_host_info {
+	hp_header_t	 hdr;
+	u16		 vendor;
+	u16		 device;
+	u16		 subsystem_vendor;
+	u16		 subsystem_id;
+	u8		 devfn;
+	u8		 bus;
+	ushort		 host_no;		/* SCSI Host number, if scsi driver not loaded*/
+	u8		 fw_version[16];	/* string */	
+	u8		 serial_number[24];	/* string */
+	u32		 ioc_status;	
+	u32		 bus_phys_width;
+	u32		 base_io_addr;
+	u32		 rsvd;
+	unsigned long	 hard_resets;		/* driver initiated resets */
+	unsigned long	 soft_resets;		/* ioc, external resets */
+	unsigned long	 timeouts;		/* num timeouts */
+} hp_host_info_t;
+
+/*  
+ *  Header:
+ *  iocnum 	required (input)
+ *  host 	required	
+ *  channel	required	(bus number)
+ *  id		required
+ *  lun		ignored
+ *
+ *  All error values between 0 and 0xFFFF in size.
+ */
+typedef struct _hp_target_info {
+	hp_header_t	 hdr;
+	u32 parity_errors;
+	u32 phase_errors;
+	u32 select_timeouts;
+	u32 message_rejects;
+	u32 negotiated_speed;
+	u8  negotiated_width;
+	u8  rsvd[7];				/* 8 byte alignment */
+} hp_target_info_t;
+
+#define HP_STATUS_OTHER		1
+#define HP_STATUS_OK		2
+#define HP_STATUS_FAILED	3
+
+#define HP_BUS_WIDTH_UNK	1
+#define HP_BUS_WIDTH_8		2
+#define HP_BUS_WIDTH_16		3
+#define HP_BUS_WIDTH_32		4
+
+#define HP_DEV_SPEED_ASYNC	2
+#define HP_DEV_SPEED_FAST	3
+#define HP_DEV_SPEED_ULTRA	4
+#define HP_DEV_SPEED_ULTRA2	5
+#define HP_DEV_SPEED_ULTRA160	6
+#define HP_DEV_SPEED_SCSI1	7
+#define HP_DEV_SPEED_ULTRA320	8
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
diff -Nru a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
--- a/drivers/message/fusion/mptlan.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/message/fusion/mptlan.c	Wed Nov 27 14:36:30 2002
@@ -26,7 +26,7 @@
  *  Copyright (c) 2000-2002 LSI Logic Corporation
  *  Originally By: Noah Romer
  *
- *  $Id: mptlan.c,v 1.52 2002/05/06 13:45:07 sshirron Exp $
+ *  $Id: mptlan.c,v 1.53 2002/10/17 20:15:58 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
diff -Nru a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
--- a/drivers/message/fusion/mptlan.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/message/fusion/mptlan.h	Wed Nov 27 14:36:31 2002
@@ -8,7 +8,6 @@
 #include <linux/module.h>
 #endif
 
-#include <linux/version.h>
 #include <linux/netdevice.h>
 #include <linux/errno.h>
 // #include <linux/etherdevice.h>
diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/message/fusion/mptscsih.c	Wed Nov 27 14:36:29 2002
@@ -26,7 +26,7 @@
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:Pam.Delaney@lsil.com)
  *
- *  $Id: mptscsih.c,v 1.102 2002/10/03 13:10:14 pdelaney Exp $
+ *  $Id: mptscsih.c,v 1.103 2002/10/17 20:15:59 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -78,6 +78,9 @@
 #include <linux/reboot.h>	/* notifier code */
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45)
+#include "../../scsi/sd.h"
+#endif
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -198,7 +201,7 @@
 static int	mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
 static void	mptscsih_domainValidation(void *hd);
 static int	mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
-static void	mptscsih_qas_check(MPT_SCSI_HOST *hd);
+static void	mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
 static int	mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int target);
 static void	mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
 static void	mptscsih_fillbuf(char *buffer, int size, int index, int width);
@@ -399,6 +402,9 @@
 		case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:	/* 0x0043 */
 			/* Spoof to SCSI Selection Timeout! */
 			sc->result = DID_NO_CONNECT << 16;
+
+			if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
+				hd->sel_timeout[pScsiReq->TargetID]++;
 			break;
 
 		case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */
@@ -1289,11 +1295,17 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
 				sh->max_sectors = MPT_SCSI_MAX_SECTORS;
 #endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) || defined CONFIG_HIGHIO
 				sh->highmem_io = 1;
 #endif
 				sh->this_id = this->pfacts[portnum].PortSCSIID;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
+				/* OS entry to allow host drivers to force
+				 * a queue depth on a per device basis.
+				 */
+				sh->select_queue_depths = mptscsih_select_queue_depths;
+#endif
 				/* Required entry.
 				 */
 				sh->unique_id = this->id;
@@ -2546,14 +2558,13 @@
 
 		/* Isse the Task Mgmt request.
 		 */
+		if (hd->hard_resets < -1)
+			hd->hard_resets++;
 		rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, sleepFlag);
 		if (rc) {
-#ifdef MPT_SCSI_USE_NEW_EH
-			hd->tmState = TM_STATE_ERROR;
-#endif
 			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
 		} else {
-			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name);
+			dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
 		}
 	}
 #ifdef DROP_TEST
@@ -2681,7 +2692,6 @@
 {
 	MPT_SCSI_HOST	*hd;
 	MPT_FRAME_HDR	*mf;
-	unsigned long	 flags;
 	u32		 ctx2abort;
 	int		 scpnt_idx;
 
@@ -2696,10 +2706,11 @@
 		return FAILED;
 	}
 
-	printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
-	       hd->ioc->name, SCpnt);
-	printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n",
-	       hd->ioc->name, atomic_read(&queue_depth));
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p, numIOs=%d)\n",
+	       hd->ioc->name, SCpnt, atomic_read(&queue_depth));
+
+	if (hd->timeouts < -1)
+		hd->timeouts++;
 
 	/* Find this command
 	 */
@@ -2753,11 +2764,9 @@
 	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
 
 	hd->abortSCpnt = SCpnt;
-
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
-	                       SCpnt->target, SCpnt->lun, ctx2abort, CAN_SLEEP) 
-		< 0
-	    || hd->tmState == TM_STATE_ERROR) {
+	                       SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP) 
+		< 0) {
 
 		/* The TM request failed and the subsequent FW-reload failed!
 		 * Fatal error case.
@@ -2765,14 +2774,6 @@
 		printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
 		       hd->ioc->name, SCpnt);
 
-		/* If command not found, do not do callback,
-		 *  just return failed.  CHECKME
-		 */
-		if (hd->ScsiLookup[scpnt_idx] != NULL) {
-			SCpnt->result = STS_BUSY;
-			SCpnt->scsi_done(SCpnt);
-		}
-
 		/* We must clear our pending flag before clearing our state.
 		 */
 		hd->tmPending = 0;
@@ -2780,34 +2781,8 @@
 
 		return FAILED;
 	}
+	return FAILED;
 
-	/* Our task management request will either complete or time out.  So we
-	 * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
-	 * we encountered an error executing the task management request.
-	 */
-	while (hd->tmPending == 1){
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/4);
-	}
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	if (hd->tmState == TM_STATE_ERROR){
-		hd->tmState = TM_STATE_NONE;
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
-			   "TM timeout error! (sc=%p)\n",
-			   hd->ioc->name,
-			   SCpnt));
-		return FAILED;
-	}
-	hd->tmState = TM_STATE_NONE;
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
-	nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
-		   "Abort was successful! (sc=%p)\n",
-		   hd->ioc->name,
-		   SCpnt));
-
-	return SUCCESS;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2823,7 +2798,6 @@
 mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
-	unsigned long	 flags;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
@@ -2834,10 +2808,13 @@
 		return FAILED;
 	}
 
-	printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
-	       hd->ioc->name, SCpnt);
-	printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n",
-	       hd->ioc->name, atomic_read(&queue_depth));
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p, numIOs=%d)\n",
+	       hd->ioc->name, SCpnt, atomic_read(&queue_depth));
+
+	/* Unsupported for SCSI. Suppored for FCP
+	 */
+	if (hd->is_spi)
+		return FAILED;
 
 	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
 	 *  If we time out, then we return a FAILED status to the caller.  This
@@ -2853,7 +2830,7 @@
 	}
 
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
-	                       SCpnt->target, 0, 0, CAN_SLEEP) 
+	                       SCpnt->target, 0, 0, NO_SLEEP) 
 		< 0){
 		/* The TM request failed and the subsequent FW-reload failed!
 		 * Fatal error case.
@@ -2864,34 +2841,8 @@
 		hd->tmState = TM_STATE_NONE;
 		return FAILED;
 	}
-
-	/* Our task management request will either complete or time out.  So we
-	 * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
-	 * we encountered an error executing the task management request.
-	 */
-	while (hd->tmPending == 1){
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/4);
-	}
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	if (hd->tmState == TM_STATE_ERROR){
-		hd->tmState = TM_STATE_NONE;
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: "
-			   "TM timeout error! (sc=%p)\n",
-			   hd->ioc->name,
-			   SCpnt));
-		return FAILED;
-	}
-	hd->tmState = TM_STATE_NONE;
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
-	nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: "
-		   "Device reset was successful! (sc=%p)\n",
-		   hd->ioc->name,
-		   SCpnt));
-
 	return SUCCESS;
+
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2907,7 +2858,6 @@
 mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
-	unsigned long	 flags;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
@@ -2918,10 +2868,11 @@
 		return FAILED;
 	}
 
-	printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
-	       hd->ioc->name, SCpnt);
-	printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n",
-	       hd->ioc->name, atomic_read(&queue_depth));
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p, numIOs=%d)\n",
+	       hd->ioc->name, SCpnt, atomic_read(&queue_depth));
+
+	if (hd->timeouts < -1)
+		hd->timeouts++;
 
 	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
 	 *  If we time out, then we return a FAILED status to the caller.  This
@@ -2932,13 +2883,13 @@
 		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
 			   "Timed out waiting for previous TM to complete! "
 			   "(sc = %p)\n",
-			   hd->ioc->name, SCpnt ) );
+			   hd->ioc->name, SCpnt));
 		return FAILED;
 	}
 
 	/* We are now ready to execute the task management request. */
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
-	                       0, 0, 0, CAN_SLEEP) 
+	                       0, 0, 0, NO_SLEEP) 
 	    < 0){
 
 		/* The TM request failed and the subsequent FW-reload failed!
@@ -2952,32 +2903,6 @@
 		return FAILED;
 	}
 
-	/* Our task management request will either complete or time out.  So we
-	 * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, 
-	 * we encountered an error executing the task management request.
-	 */
-	while (hd->tmPending == 1){
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/4);
-	}
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	if (hd->tmState == TM_STATE_ERROR){
-		hd->tmState = TM_STATE_NONE;
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
-			   "TM timeout error! (sc=%p)\n",
-			   hd->ioc->name,
-			   SCpnt));
-		return FAILED;
-	}
-	hd->tmState = TM_STATE_NONE;
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-
-	nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: "
-		   "Bus reset was successful! (sc=%p)\n",
-		   hd->ioc->name,
-		   SCpnt));
-
 	return SUCCESS;
 }
 
@@ -3013,7 +2938,7 @@
 	/*  If our attempts to reset the host failed, then return a failed
 	 *  status.  The host will be taken off line by the SCSI mid-layer.
 	 */
-	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
+	if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0){
 		status = FAILED;
 	} else {
 		/*  Make sure TM pending is cleared and TM state is set to 
@@ -3056,9 +2981,7 @@
 			break;
 		}
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/4);
-
+		mdelay(250);
 	} while (--loop_count);
 
 	return status;
@@ -3093,6 +3016,9 @@
 		return SCSI_ABORT_NOT_RUNNING;
 	}
 
+	if (hd->timeouts < -1)
+		hd->timeouts++;
+
 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
 		/* Cmd not found in ScsiLookup.
 		 * If found in doneQ, delete from Q.
@@ -3166,7 +3092,7 @@
 	SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx);
 
 	/* For the time being, force bus reset on any abort
-	 * requests for the 1030 FW.
+	 * requests for the 1030/1035 FW.
 	 */
 	if (hd->is_spi)
 		mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
@@ -3226,6 +3152,9 @@
 		return SCSI_RESET_SUCCESS;
 	}
 
+	if (hd->timeouts < -1)
+		hd->timeouts++;
+
 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
 		/* Cmd not found in ScsiLookup.
 		 * If found in doneQ, delete from Q.
@@ -3583,9 +3512,6 @@
 					}
 				}
 			}
-#ifdef MPT_SCSI_USE_NEW_EH
-			hd->tmState = TM_STATE_ERROR;
-#endif
 		} else {
 			dtmprintk((KERN_INFO "  SCSI TaskMgmt SUCCESS!\n"));
 
@@ -3629,6 +3555,9 @@
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 	hd->tmPending = 0;
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+#ifdef MPT_SCSI_USE_NEW_EH
+	hd->tmState = TM_STATE_NONE;
+#endif
 
 	return 1;
 }
@@ -3638,14 +3567,18 @@
  *	This is anyones guess quite frankly.
  */
 int
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
 		sector_t capacity, int *ip)
 {
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28)
+mptscsih_bios_param(Disk * disk, struct block_device *bdev, int *ip)
+{
+	sector_t capacity = disk->capacity;
 #else
 mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip)
 {
-	sector_t capacity = disk->capacity;
+	unsigned capacity = disk->capacity;
 #endif
 	int size;
 
@@ -3666,20 +3599,63 @@
  *	Called once per device the bus scan. Use it to force the queue_depth
  *	member to 1 if a device does not support Q tags.
  */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44)
 int
-mptscsih_slave_attach(Scsi_Device *device)
+mptscsih_slave_configure(Scsi_Device *device)
 {
+	struct Scsi_Host	*host = device->host;
 	VirtDevice		*pTarget;
-	pTarget = device->hostdata;
-	if (!device->tagged_supported ||
-	    !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) {
-		scsi_adjust_queue_depth(device, 0, 1);
-	} else {
-		scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
-					       device->host->can_queue >> 1);
+	MPT_SCSI_HOST		*hd;
+
+	hd = (MPT_SCSI_HOST *)host->hostdata;
+	if (hd && (hd->Targets != NULL)) {
+		pTarget = hd->Targets[device->id];
+		if (pTarget) {
+			if (!device->tagged_supported ||
+			    !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) {
+				scsi_adjust_queue_depth(device, 0, 1);
+			} else {
+				scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, 
+							device->host->can_queue >> 1);
+			}
+		}
 	}
 	return 0;
 }
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) */
+void
+mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList)
+{
+	struct scsi_device	*device;
+	VirtDevice		*pTarget;
+	MPT_SCSI_HOST		*hd;
+	int			 ii, max;
+
+	for (device = sdList; device != NULL; device = device->next) {
+
+		if (device->host != sh)
+			continue;
+
+		hd = (MPT_SCSI_HOST *) sh->hostdata;
+		if (hd == NULL)
+			continue;
+
+		if (hd->Targets != NULL) {
+			if (hd->is_spi)
+				max = MPT_MAX_SCSI_DEVICES;
+			else
+				max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
+
+			for (ii=0; ii < max; ii++) {
+				pTarget = hd->Targets[ii];
+				if (pTarget && !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) {
+					device->queue_depth = 1;
+				}
+			}
+		}
+	}
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) */
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -4126,6 +4102,9 @@
 		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 		hd->resetPending = 0;
 		hd->numTMrequests = 0;
+#ifdef MPT_SCSI_USE_NEW_EH
+		hd->tmState = TM_STATE_NONE;
+#endif
 
 		/* 6. If there was an internal command,
 		 * wake this process up.
@@ -4167,10 +4146,13 @@
 		/* FIXME! */
 		break;
 	case MPI_EVENT_IOC_BUS_RESET:			/* 04 */
-		/* FIXME! */
-		break;
 	case MPI_EVENT_EXT_BUS_RESET:			/* 05 */
-		/* FIXME! */
+		hd = NULL;
+		if (ioc->sh) {
+			hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+			if (hd && (hd->is_spi) && (hd->soft_resets < -1))
+				hd->soft_resets++;
+		}
 		break;
 	case MPI_EVENT_LOGOUT:				/* 09 */
 		/* FIXME! */
@@ -4804,9 +4786,10 @@
 	}
 
 	if (vdev) {
-		if (hd->ioc->spi_data.isRaid & (1 << target_id))
+		if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
 			vdev->raidVolume = 1;
-		else
+			ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
+		} else
 			vdev->raidVolume = 0;
 	}
 
@@ -4868,6 +4851,8 @@
 	u8 version, nfactor;
 	u8 noQas = 1;
 
+	ddvtprintk((KERN_INFO "set Target: (id %d) byte56 0x%x\n", id, byte56));
+
 	/* Set flags based on Inquiry data
 	 */
 	if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
@@ -4886,12 +4871,18 @@
 				 */
 				if ((byte56 & 0x04) == 0)
 					factor = MPT_ULTRA2;
+				else if ((byte56 & 0x03) == 0)
+					factor = MPT_ULTRA160;
 				else
 					factor = MPT_ULTRA320;
 
-				/* bit 1 QAS support, non-raid only
+				/* If RAID, never disable QAS
+				 * else if non RAID, do not disable 
+				 *   QAS if bit 1 is set
+				 * bit 1 QAS support, non-raid only
+				 * bit 0 IU support
 				 */
-				if ((target->raidVolume == 0) && (byte56 & 0x02) != 0)
+				if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
 					noQas = 0;
 
 				offset = pspi_data->maxSyncOffset;
@@ -4976,6 +4967,7 @@
 			VirtDevice	*vdev;
 			int ii;
 
+			ddvtprintk((KERN_INFO "Disabling QAS!\n"));
 			pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS;
 			for (ii = 0; ii < id; ii++) {
 				vdev = hd->Targets[id];
@@ -5204,6 +5196,17 @@
 			//negoFlags = MPT_TARGET_NO_NEGO_SYNC;
 		}
 
+#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
+		/* Force to async and narrow if DV has not been executed
+		 * for this ID
+		 */
+		if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
+			width = 0;
+			factor = MPT_ASYNC;
+			offset = 0;
+		}
+#endif
+
 		/* If id is not a raid volume, get the updated
 		 * transmission settings from the target structure.
 		 */
@@ -5313,13 +5316,6 @@
 	 */
 	del_timer(&hd->TMtimer);
 
-#ifdef MPT_SCSI_USE_NEW_EH
-	/* Set the error flag to 1 so that the function that started the
-	 * task management request knows it timed out.
-	 */
-	hd->tmState = TM_STATE_ERROR;
-#endif
-
 	/* Call the reset handler. Already had a TM request
 	 * timeout - so issue a diagnostic reset
 	 */
@@ -5853,6 +5849,12 @@
 	else
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
 
+	if (cmd == CMD_RequestSense) {
+		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
+		ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
+			hd->ioc->name, cmd));
+	}
+
 	for (ii=0; ii < 16; ii++)
 		pScsiReq->CDB[ii] = CDB[ii];
 
@@ -6184,7 +6186,7 @@
 					post_pendingQ_commands(hd);
 
 					if (hd->ioc->spi_data.noQas)
-						mptscsih_qas_check(hd);
+						mptscsih_qas_check(hd, id);
 				}
 			}
 		}
@@ -6218,7 +6220,7 @@
 
 /* Write SDP1 if no QAS has been enabled
  */
-static void mptscsih_qas_check(MPT_SCSI_HOST *hd)
+static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
 {
 	VirtDevice *pTarget = NULL;
 	int ii;
@@ -6227,6 +6229,9 @@
 		return;
 
 	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
+		if (ii == id)
+			continue;
+
 		if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
 			continue;
 
@@ -6510,6 +6515,7 @@
 					rc = hd->pLocal->completion;
 					if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
 						dv.max.width = 0;
+						doFallback = 0;
 					} else
 						goto target_done;
 				}
@@ -7059,6 +7065,10 @@
 		dv.cmd = MPT_SAVE;
 		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
 
+#if 0	
+	/* Double writes to SDP1 can cause problems, 
+	 * skip here since unnecessary
+	 */
 		/* Save the final negotiated settings to
 		 * SCSI device page 1.
 		 */
@@ -7067,13 +7077,14 @@
 		cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 		cfg.dir = 1;
 		mpt_config(hd->ioc, &cfg);
+#endif
 	}
 
 	/* If this is a RAID Passthrough, enable internal IOs
 	 */
 	if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
 		if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
-			ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
+			ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
 	}
 
 	/* Done with the DV scan of the current target
@@ -7227,8 +7238,7 @@
 			pPage1->Configuration = le32_to_cpu(configuration);
 		}
 		ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
-				dv->now.width, dv->now.factor,
-				dv->now.offset, val, configuration));
+				width, factor, offset, val, configuration));
 		break;
 
 	case MPT_FALLBACK:
diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
--- a/drivers/message/fusion/mptscsih.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/message/fusion/mptscsih.h	Wed Nov 27 14:36:32 2002
@@ -20,7 +20,7 @@
  *  (mailto:netscape.net)
  *  (mailto:Pam.Delaney@lsil.com)
  *
- *  $Id: mptscsih.h,v 1.19 2002/10/03 13:10:15 pdelaney Exp $
+ *  $Id: mptscsih.h,v 1.20 2002/10/17 20:16:00 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -206,12 +206,11 @@
 #define x_scsi_dev_reset	mptscsih_dev_reset
 #define x_scsi_host_reset	mptscsih_host_reset
 #define x_scsi_bios_param	mptscsih_bios_param
-#define x_scsi_slave_attach	mptscsih_slave_attach
+#define x_scsi_slave_configure	mptscsih_slave_configure
 
 #define x_scsi_taskmgmt_bh	mptscsih_taskmgmt_bh
 #define x_scsi_old_abort	mptscsih_old_abort
 #define x_scsi_old_reset	mptscsih_old_reset
-#define x_scsi_slave_attach	mptscsih_slave_attach
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -231,13 +230,15 @@
 extern	int		 x_scsi_old_reset(Scsi_Cmnd *, unsigned int);
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
-extern	int		 x_scsi_bios_param(Scsi_Device *, struct block_device *, sector_t, int[]);
+extern int		 x_scsi_bios_param(struct scsi_device * sdev, struct block_device *bdev,
+				sector_t capacity, int *ip);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28)
+extern	int		 x_scsi_bios_param(Disk *, struct block_device *, int *);
 #else
 extern	int		 x_scsi_bios_param(Disk *, kdev_t, int *);
 #endif
-extern	int		 x_scsi_slave_attach(Scsi_Device *);
+extern	int		 x_scsi_slave_configure(Scsi_Device *);
 extern	void		 x_scsi_taskmgmt_bh(void *);
-extern	int		 x_scsi_slave_attach(Scsi_Device *);
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
 #define PROC_SCSI_DECL
@@ -247,7 +248,7 @@
 
 #ifdef MPT_SCSI_USE_NEW_EH
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44)
 
 #define MPT_SCSIHOST {						\
 	PROC_SCSI_DECL						\
@@ -255,8 +256,6 @@
 	.detect				= x_scsi_detect,	\
 	.release			= x_scsi_release,	\
 	.info				= x_scsi_info,		\
-	.queuecommand			= x_scsi_queuecommand,	\
-	.slave_attach			= x_scsi_slave_attach,	\
 	.eh_abort_handler		= x_scsi_abort,		\
 	.eh_device_reset_handler	= x_scsi_dev_reset,	\
 	.eh_bus_reset_handler		= x_scsi_bus_reset,	\
@@ -267,27 +266,32 @@
 	.sg_tablesize			= MPT_SCSI_SG_DEPTH,	\
 	.max_sectors			= MPT_SCSI_MAX_SECTORS,	\
 	.cmd_per_lun			= MPT_SCSI_CMD_PER_LUN,	\
+	.unchecked_isa_dma		= 0,			\
 	.use_clustering			= ENABLE_CLUSTERING,	\
-	.slave_attach			x_scsi_slave_attach,	\
 }
 
 #else  /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */
 
 #define MPT_SCSIHOST {						\
+	.next				= NULL,			\
 	PROC_SCSI_DECL						\
 	.name				= "MPT SCSI Host",	\
 	.detect				= x_scsi_detect,	\
 	.release			= x_scsi_release,	\
 	.info				= x_scsi_info,		\
+	.command			= NULL,			\
 	.queuecommand			= x_scsi_queuecommand,	\
+	.eh_strategy_handler		= NULL,			\
 	.eh_abort_handler		= x_scsi_abort,		\
 	.eh_device_reset_handler	= x_scsi_dev_reset,	\
 	.eh_bus_reset_handler		= x_scsi_bus_reset,	\
+	.eh_host_reset_handler		= NULL,			\
 	.bios_param			= x_scsi_bios_param,	\
 	.can_queue			= MPT_SCSI_CAN_QUEUE,	\
 	.this_id			= -1,			\
 	.sg_tablesize			= MPT_SCSI_SG_DEPTH,	\
 	.cmd_per_lun			= MPT_SCSI_CMD_PER_LUN,	\
+	.unchecked_isa_dma		= 0,			\
 	.use_clustering			= ENABLE_CLUSTERING,	\
 	.use_new_eh_code		= 1			\
 }
@@ -297,11 +301,13 @@
 #else /* MPT_SCSI_USE_NEW_EH */
 
 #define MPT_SCSIHOST {						\
+	.next				= NULL,			\
 	PROC_SCSI_DECL						\
 	.name				= "MPT SCSI Host",	\
 	.detect				= x_scsi_detect,	\
 	.release			= x_scsi_release,	\
 	.info				= x_scsi_info,		\
+	.command			= NULL,			\
 	.queuecommand			= x_scsi_queuecommand,	\
 	.abort				= x_scsi_old_abort,	\
 	.reset				= x_scsi_old_reset,	\
@@ -310,6 +316,7 @@
 	.this_id			= -1,			\
 	.sg_tablesize			= MPT_SCSI_SG_DEPTH,	\
 	.cmd_per_lun			= MPT_SCSI_CMD_PER_LUN,	\
+	.unchecked_isa_dma		= 0,			\
 	.use_clustering			= ENABLE_CLUSTERING	\
 }
 #endif  /* MPT_SCSI_USE_NEW_EH */
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/message/i2o/i2o_block.c	Wed Nov 27 14:36:31 2002
@@ -1669,7 +1669,6 @@
 	if(i2o_install_handler(&i2o_block_handler)<0)
 	{
 		unregister_blkdev(MAJOR_NR, "i2o_block");
-		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		printk(KERN_ERR "i2o_block: unable to register OSM.\n");
 		return -EINVAL;
 	}
@@ -1682,8 +1681,7 @@
 	evt_pid = kernel_thread(i2ob_evt, NULL, CLONE_SIGHAND);
 	if(evt_pid < 0)
 	{
-		printk(KERN_ERR 
-			"i2o_block: Could not initialize event thread.  Aborting\n");
+		printk(KERN_ERR "i2o_block: Could not initialize event thread.  Aborting\n");
 		i2o_remove_handler(&i2o_block_handler);
 		return 0;
 	}
diff -Nru a/drivers/message/i2o/i2o_core.c b/drivers/message/i2o/i2o_core.c
--- a/drivers/message/i2o/i2o_core.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/message/i2o/i2o_core.c	Wed Nov 27 14:36:31 2002
@@ -3344,6 +3344,9 @@
 	u16 detailed_status = msg[4]&0xFFFF;
 	struct i2o_handler *h = i2o_handlers[msg[2] & (MAX_I2O_MODULES-1)];
 
+	if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
+		return;				// No status in this reply
+
 	printk("%s%s: ", severity, str);
 
 	if (cmd < 0x1F) 			// Utility cmd
diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
--- a/drivers/message/i2o/i2o_scsi.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/message/i2o/i2o_scsi.c	Wed Nov 27 14:36:31 2002
@@ -57,7 +57,6 @@
 #include <linux/i2o.h>
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
-#include "../../scsi/sd.h"
 
 #if BITS_PER_LONG == 64
 #error FIXME: driver does not support 64-bit platforms
@@ -336,15 +335,10 @@
 	return;
 }
 
-struct i2o_handler i2o_scsi_handler=
-{
-	i2o_scsi_reply,
-	NULL,
-	NULL,
-	NULL,
-	"I2O SCSI OSM",
-	0,
-	I2O_CLASS_SCSI_PERIPHERAL
+struct i2o_handler i2o_scsi_handler = {
+	.reply	= i2o_scsi_reply,
+	.name	= "I2O SCSI OSM",
+	.class	= I2O_CLASS_SCSI_PERIPHERAL,
 };
 
 /**
@@ -918,6 +912,7 @@
 	unsigned long msg;
 	u32 m;
 	int tid;
+	unsigned long timeout;
 	
 	printk(KERN_WARNING "i2o_scsi: Aborting command block.\n");
 	
@@ -930,21 +925,21 @@
 		return FAILED;
 	}
 	c = hostdata->controller;
-	
-	/*
-	 *	Obtain an I2O message. Right now we _have_ to obtain one
-	 *	until the scsi layer stuff is cleaned up.
-	 *
-	 *	FIXME: we are in error context so we could sleep retry
-	 * 	a bit and then bail in the improved scsi layer.
-	 */	
-	 
+
+	spin_unlock_irq(host->host_lock);
+		
+	timeout = jiffies+2*HZ;
 	do
 	{
-		mb();
 		m = le32_to_cpu(I2O_POST_READ32(c));
+		if(m != 0xFFFFFFFF)
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+		mb();
 	}
-	while(m==0xFFFFFFFF);
+	while(time_before(jiffies, timeout));
+	
 	msg = c->mem_offset + m;
 	
 	i2o_raw_writel(FIVE_WORD_MSG_SIZE, msg);
@@ -955,6 +950,8 @@
 	wmb();
 	i2o_post_message(c,m);
 	wmb();
+	
+	spin_lock_irq(host->host_lock);
 	return SUCCESS;
 }
 
@@ -977,14 +974,20 @@
 	struct i2o_scsi_host *hostdata;
 	u32 m;
 	unsigned long msg;
+	unsigned long timeout;
 
+	
 	/*
 	 *	Find the TID for the bus
 	 */
 
-	printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n");
 	
 	host = SCpnt->host;
+
+	spin_unlock_irq(host->host_lock);
+
+	printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n");
+
 	hostdata = (struct i2o_scsi_host *)host->hostdata;
 	tid = hostdata->bus_task;
 	c = hostdata->controller;
@@ -994,15 +997,19 @@
 	 *	will be aborted by the IOP. We need to catch the reply
 	 *	possibly ?
 	 */
-	 
-	m = le32_to_cpu(I2O_POST_READ32(c));
+
+	timeout = jiffies+2*HZ;
+	do
+	{
+		m = le32_to_cpu(I2O_POST_READ32(c));
+		if(m != 0xFFFFFFFF)
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+		mb();
+	}
+	while(time_before(jiffies, timeout));
 	
-	/*
-	 *	No free messages, try again next time - no big deal
-	 */
-	 
-	if(m == 0xFFFFFFFF)
-		return SCSI_RESET_PUNT;
 	
 	msg = c->mem_offset + m;
 	i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg);
@@ -1012,7 +1019,12 @@
 	/* Now store unit,tid so we can tie the completion back to a specific device */
 	__raw_writel(c->unit << 16 | tid, msg+12);
 	wmb();
+
+	/* We want the command to complete after we return */	
+	spin_lock_irq(host->host_lock);
 	i2o_post_message(c,m);
+
+	/* Should we wait for the reset to complete ? */	
 	return SUCCESS;
 }
 
@@ -1044,8 +1056,9 @@
 
 /**
  *	i2o_scsi_bios_param	-	Invent disk geometry
- *	@disk: device 
+ *	@sdev: scsi device 
  *	@dev: block layer device
+ *	@capacity: size in sectors
  *	@ip: geometry array
  *
  *	This is anyones guess quite frankly. We use the same rules everyone 
diff -Nru a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
--- a/drivers/net/appletalk/ltpc.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/net/appletalk/ltpc.c	Wed Nov 27 14:36:28 2002
@@ -1059,26 +1059,39 @@
 	int autoirq;
 	unsigned long flags;
 	unsigned long f;
+	int portfound=0;
 
 	SET_MODULE_OWNER(dev);
 
 	save_flags(flags);
 
 	/* probe for the I/O port address */
-	if (io != 0x240 && !check_region(0x220,8)) {
+	if (io != 0x240 && request_region(0x220,8,"ltpc")) {
 		x = inb_p(0x220+6);
-		if ( (x!=0xff) && (x>=0xf0) ) io = 0x220;
+		if ( (x!=0xff) && (x>=0xf0) ) {
+			io = 0x220;
+			portfound=1;
+		}
+		else {
+			release_region(0x220,8);
+		}
 	}
 	
-	if (io != 0x220 && !check_region(0x240,8)) {
+	if (io != 0x220 && request_region(0x240,8,"ltpc")) {
 		y = inb_p(0x240+6);
-		if ( (y!=0xff) && (y>=0xf0) ) io = 0x240;
+		if ( (y!=0xff) && (y>=0xf0) ){ 
+			io = 0x240;
+			portfound=1;
+		}
+		else {
+			release_region(0x240,8);
+		}
 	} 
 
-	if(io) {
-		/* found it, now grab it */
-		request_region(io,8,"ltpc");
-	} else {
+	if(io && !portfound && request_region(io,8,"ltpc")){
+		portfound = 1;
+	}
+	if(!portfound) {
 		/* give up in despair */
 		printk ("LocalTalk card not found; 220 = %02x, 240 = %02x.\n",
 			x,y);
diff -Nru a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
--- a/drivers/net/arcnet/com20020-pci.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/net/arcnet/com20020-pci.c	Wed Nov 27 14:36:28 2002
@@ -90,7 +90,7 @@
 	dev->base_addr = ioaddr;
 	dev->irq = pdev->irq;
 	dev->dev_addr[0] = node;
-	lp->card_name = pdev->name;
+	lp->card_name = pdev->dev.name;
 	lp->card_flags = id->driver_data;
 	lp->backplane = backplane;
 	lp->clockp = clockp & 7;
diff -Nru a/drivers/net/de600.c b/drivers/net/de600.c
--- a/drivers/net/de600.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/de600.c	Wed Nov 27 14:36:32 2002
@@ -444,7 +444,10 @@
 		return -ENODEV;
 	}
 
-	request_region(DE600_IO, 3, "de600");
+	if (!request_region(DE600_IO, 3, "de600")) {
+		printk(KERN_WARNING "DE600: port 0x%x busy\n", DE600_IO);
+		return -EBUSY;
+	}
 
 	printk(", Ethernet Address: %02X", dev->dev_addr[0]);
 	for (i = 1; i < ETH_ALEN; i++)
diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c
--- a/drivers/net/depca.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/net/depca.c	Wed Nov 27 14:36:30 2002
@@ -463,8 +463,6 @@
 static void depca_dbg_open(struct net_device *dev);
 
 #ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
 static int autoprobed = 1, loading_module = 1;
 # else
 static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 };
diff -Nru a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
--- a/drivers/net/ewrk3.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/ewrk3.c	Wed Nov 27 14:36:32 2002
@@ -332,8 +332,6 @@
 
 
 #ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
 static int autoprobed = 1, loading_module = 1;
 
 #else
@@ -2083,7 +2081,25 @@
 MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");
 MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");
 
-int init_module(void)
+static void ewrk3_exit_module(void)
+{
+	int i;
+
+	for( i=0; i<ndevs; i++ ) {
+		unregister_netdev(ewrk3_devs[i]);
+		if (ewrk3_devs[i]->priv) {
+			kfree(ewrk3_devs[i]->priv);
+			ewrk3_devs[i]->priv = NULL;
+		}
+		ewrk3_devs[i]->irq = 0;
+
+		release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);
+		kfree(ewrk3_devs[i]);
+		ewrk3_devs[i] = NULL;
+	}
+}
+
+static int ewrk3_init_module(void)
 {
 	int i=0;
 
@@ -2107,27 +2123,14 @@
 	return ndevs ? 0 : -EIO;
 
 error:
-	cleanup_module();
+	ewrk3_exit_module();
 	return -ENOMEM;
 }
 
-void cleanup_module(void)
-{
-	int i;
-
-	for( i=0; i<ndevs; i++ ) {
-		unregister_netdev(ewrk3_devs[i]);
-		if (ewrk3_devs[i]->priv) {
-			kfree(ewrk3_devs[i]->priv);
-			ewrk3_devs[i]->priv = NULL;
-		}
-		ewrk3_devs[i]->irq = 0;
 
-		release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);
-		kfree(ewrk3_devs[i]);
-		ewrk3_devs[i] = NULL;
-	}
-}
+/* Hack for breakage in new module stuff */
+module_exit(ewrk3_exit_module);
+module_init(ewrk3_init_module);
 #endif				/* MODULE */
 MODULE_LICENSE("GPL");
 
diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c
--- a/drivers/net/fc/iph5526.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/net/fc/iph5526.c	Wed Nov 27 14:36:28 2002
@@ -3791,8 +3791,10 @@
 		sprintf(fi->name, "fc%d", count);
 
 		host = scsi_register(tmpt, sizeof(struct iph5526_hostdata));
-		if(host==NULL)
+		if(host==NULL) {
+			kfree(fc[count]);
 			return no_of_hosts;
+		}
 			
 		hostdata = (struct iph5526_hostdata *)host->hostdata;
 		memset(hostdata, 0 , sizeof(struct iph5526_hostdata));
diff -Nru a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig
--- a/drivers/net/hamradio/Kconfig	Wed Nov 27 14:36:27 2002
+++ b/drivers/net/hamradio/Kconfig	Wed Nov 27 14:36:27 2002
@@ -185,120 +185,6 @@
 	  say M here and read <file:Documentation/modules.txt>.  This is
 	  recommended.  The module will be called baycom_par.o.
 
-config SOUNDMODEM
-	tristate "Soundcard modem driver"
-	depends on PARPORT && AX25
-	---help---
-	  This experimental driver allows a standard Sound Blaster or
-	  WindowsSoundSystem compatible sound card to be used as a packet
-	  radio modem (NOT as a telephone modem!), to send digital traffic
-	  over amateur radio.
-
-	  To configure the driver, use the sethdlc, smdiag and smmixer
-	  utilities available in the standard ax25 utilities package. For
-	  information on how to key the transmitter, see
-	  <http://www.ife.ee.ethz.ch/~sailer/pcf/ptt_circ/ptt.html> and
-	  <file:Documentation/networking/soundmodem.txt>.
-
-	  If you want to compile this driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>.  This is
-	  recommended.  The module will be called soundmodem.o.
-
-config SOUNDMODEM_SBC
-	bool "soundmodem support for Soundblaster and compatible cards"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver to use Sound Blaster and
-	  compatible cards. If you have a dual mode card (i.e. a WSS cards
-	  with a Sound Blaster emulation) you should say N here and Y to
-	  "Sound card modem support for WSS and Crystal cards", below, because
-	  this usually results in better performance. This option also
-	  supports SB16/32/64 in full-duplex mode.
-
-config SOUNDMODEM_WSS
-	bool "soundmodem support for WSS and Crystal cards"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver to use WindowsSoundSystem
-	  compatible cards. These cards feature a codec chip from either
-	  Analog Devices (such as AD1848, AD1845, AD1812) or Crystal
-	  Semiconductors (such as CS4248, CS423x). This option also supports
-	  the WSS full-duplex operation which currently works with Crystal
-	  CS423x chips. If you don't need full-duplex operation, do not enable
-	  it to save performance.
-
-config SOUNDMODEM_AFSK1200
-	bool "soundmodem support for 1200 baud AFSK modulation"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver 1200 baud AFSK modem,
-	  compatible to popular modems using TCM3105 or AM7911. The
-	  demodulator requires about 12% of the CPU power of a Pentium 75 CPU
-	  per channel.
-
-config SOUNDMODEM_AFSK2400_7
-	bool "soundmodem support for 2400 baud AFSK modulation (7.3728MHz crystal)"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver 2400 baud AFSK modem,
-	  compatible to TCM3105 modems (over-)clocked with a 7.3728MHz
-	  crystal. Note that the availability of this driver does _not_ imply
-	  that I recommend building such links. It is only here since users
-	  especially in eastern Europe have asked me to do so. In fact this
-	  modulation scheme has many disadvantages, mainly its incompatibility
-	  with many transceiver designs and the fact that the TCM3105 (if
-	  used) is operated widely outside its specifications.
-
-config SOUNDMODEM_AFSK2400_8
-	bool "soundmodem support for 2400 baud AFSK modulation (8MHz crystal)"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver 2400 baud AFSK modem,
-	  compatible to TCM3105 modems (over-)clocked with an 8MHz crystal.
-	  Note that the availability of this driver does _not_ imply that I
-	  recommend building such links. It is only here since users
-	  especially in eastern Europe have asked me to do so. In fact this
-	  modulation scheme has many disadvantages, mainly its incompatibility
-	  with many transceiver designs and the fact that the TCM3105 (if
-	  used) is operated widely outside its specifications.
-
-config SOUNDMODEM_AFSK2666
-	bool "soundmodem support for 2666 baud AFSK modulation"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver 2666 baud AFSK modem.
-	  This modem is experimental, and not compatible to anything
-	  else I know of.
-
-config SOUNDMODEM_HAPN4800
-	bool "soundmodem support for 4800 baud HAPN-1 modulation"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver 4800 baud HAPN-1
-	  compatible modem. This modulation seems to be widely used 'down
-	  under' and in the Netherlands. Here, nobody uses it, so I could not
-	  test if it works. It is compatible to itself, however :-)
-
-config SOUNDMODEM_PSK4800
-	bool "soundmodem support for 4800 baud PSK modulation"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver 4800 baud 8PSK modem.
-	  This modem is experimental, and not compatible to anything
-	  else I know of.
-
-config SOUNDMODEM_FSK9600
-	bool "soundmodem support for 9600 baud FSK G3RUH modulation"
-	depends on SOUNDMODEM
-	help
-	  This option enables the soundmodem driver 9600 baud FSK modem,
-	  compatible to the G3RUH standard. The demodulator requires about 4%
-	  of the CPU power of a Pentium 75 CPU per channel. You can say Y to
-	  both 1200 baud AFSK and 9600 baud FSK if you want (but obviously you
-	  can only use one protocol at a time, depending on what the other end
-	  can understand).
-
 config YAM
 	tristate "YAM driver for AX.25"
 	depends on AX25
diff -Nru a/drivers/net/hamradio/Makefile b/drivers/net/hamradio/Makefile
--- a/drivers/net/hamradio/Makefile	Wed Nov 27 14:36:27 2002
+++ b/drivers/net/hamradio/Makefile	Wed Nov 27 14:36:27 2002
@@ -22,6 +22,5 @@
 obj-$(CONFIG_BAYCOM_SER_HDX)	+= baycom_ser_hdx.o	hdlcdrv.o
 obj-$(CONFIG_BAYCOM_PAR)	+= baycom_par.o		hdlcdrv.o
 obj-$(CONFIG_BAYCOM_EPP)	+= baycom_epp.o		hdlcdrv.o
-obj-$(CONFIG_SOUNDMODEM)	+= soundmodem/		hdlcdrv.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
--- a/drivers/net/hamradio/baycom_epp.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/hamradio/baycom_epp.c	Wed Nov 27 14:36:32 2002
@@ -54,7 +54,6 @@
 #include <linux/kmod.h>
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
-#include <linux/soundmodem.h>
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 /* prototypes for ax25_encapsulate and ax25_rebuild_header */
 #include <net/ax25.h> 
@@ -1200,7 +1199,6 @@
 	struct baycom_state *bc;
 	struct baycom_ioctl bi;
 	struct hdlcdrv_ioctl hi;
-	struct sm_ioctl si;
 
 	baycom_paranoia_check(dev, "baycom_ioctl", -EINVAL);
 	bc = (struct baycom_state *)dev->priv;
@@ -1208,28 +1206,6 @@
 		return -ENOIOCTLCMD;
 	if (get_user(cmd, (int *)ifr->ifr_data))
 		return -EFAULT;
-#ifdef BAYCOM_DEBUG
-	if (cmd == BAYCOMCTL_GETDEBUG) {
-		bi.data.dbg.debug1 = bc->ptt_keyed;
-		bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;
-		bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;
-		bc->debug_vals.last_intcnt = 0;
-		if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == SMCTL_GETDEBUG) {
-                si.data.dbg.int_rate = bc->debug_vals.last_intcnt;
-                si.data.dbg.mod_cycles = bc->debug_vals.mod_cycles;
-                si.data.dbg.demod_cycles = bc->debug_vals.demod_cycles;
-                si.data.dbg.dma_residue = 0;
-                bc->debug_vals.mod_cycles = bc->debug_vals.demod_cycles = 0;
-		bc->debug_vals.last_intcnt = 0;
-                if (copy_to_user(ifr->ifr_data, &si, sizeof(si)))
-                        return -EFAULT;
-                return 0;
-	}
-#endif /* BAYCOM_DEBUG */
 
 	if (copy_from_user(&hi, ifr->ifr_data, sizeof(hi)))
 		return -EFAULT;
diff -Nru a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
--- a/drivers/net/hamradio/dmascc.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/net/hamradio/dmascc.c	Wed Nov 27 14:36:30 2002
@@ -235,6 +235,8 @@
   int state;
   unsigned long tx_start;
   int rr0;
+  spinlock_t *register_lock;	/* Per scc_info */
+  spinlock_t ring_lock;
 };
 
 struct scc_info {
@@ -243,6 +245,7 @@
   struct net_device dev[2];
   struct scc_priv priv[2];
   struct scc_info *next;
+  spinlock_t register_lock;	/* Per device register lock */
 };
 
 
@@ -371,7 +374,7 @@
   /* Cards found = 0 */
   n = 0;
   /* Warning message */
-  if (!io[0]) printk("dmascc: autoprobing (dangerous)\n");
+  if (!io[0]) printk(KERN_INFO "dmascc: autoprobing (dangerous)\n");
 
   /* Run autodetection for each card type */
   for (h = 0; h < NUM_TYPES; h++) {
@@ -456,7 +459,7 @@
   if (n) return 0;
 
   /* If no adapter found, return error */
-  printk("dmascc: no adapters found\n");
+  printk(KERN_INFO "dmascc: no adapters found\n");
   return -EIO;
 }
 
@@ -475,18 +478,21 @@
   /* Allocate memory */
   info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
   if (!info) {
-    printk("dmascc: could not allocate memory for %s at %#3x\n",
+    printk(KERN_ERR "dmascc: could not allocate memory for %s at %#3x\n",
 	   hw[type].name, card_base);
     return -1;
   }
 
   /* Initialize what is necessary for write_scc and write_scc_data */
   memset(info, 0, sizeof(struct scc_info));
+  spin_lock_init(&info->register_lock);
+  
   priv = &info->priv[0];
   priv->type = type;
   priv->card_base = card_base;
   priv->scc_cmd = scc_base + SCCA_CMD;
   priv->scc_data = scc_base + SCCA_DATA;
+  priv->register_lock = &info->register_lock;
 
   /* Reset SCC */
   write_scc(priv, R9, FHWRES | MIE | NV);
@@ -510,7 +516,6 @@
   write_scc(priv, R15, 0);
 
   /* Start IRQ auto-detection */
-  sti();
   irqs = probe_irq_on();
 
   /* Enable interrupts */
@@ -543,7 +548,7 @@
   }
 
   if (irq <= 0) {
-    printk("dmascc: could not find irq of %s at %#3x (irq=%d)\n",
+    printk(KERN_ERR "dmascc: could not find irq of %s at %#3x (irq=%d)\n",
 	   hw[type].name, card_base, irq);
     kfree(info);
     return -1;
@@ -558,6 +563,8 @@
     priv->dev = dev;
     priv->info = info;
     priv->channel = i;
+    spin_lock_init(&priv->ring_lock);
+    priv->register_lock = &info->register_lock;
     priv->card_base = card_base;
     priv->scc_cmd = scc_base + (i ? SCCB_CMD : SCCA_CMD);
     priv->scc_data = scc_base + (i ? SCCB_DATA : SCCA_DATA);
@@ -594,7 +601,7 @@
     memcpy(dev->dev_addr, ax25_test, 7);
     rtnl_lock();
     if (register_netdevice(dev)) {
-      printk("dmascc: could not register %s\n", dev->name);
+      printk(KERN_ERR "dmascc: could not register %s\n", dev->name);
     }
     rtnl_unlock();
   }
@@ -603,7 +610,7 @@
 
   info->next = first;
   first = info;
-  printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name,
+  printk(KERN_INFO "dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name,
 	 chipnames[chip], card_base, irq);
   return 0;
 }
@@ -623,13 +630,12 @@
     outb_p(val, priv->scc_cmd);
     return;
   default:
-    save_flags(flags);
-    cli();
+    spin_lock_irqsave(priv->register_lock, flags);
     outb_p(0, priv->card_base + PI_DREQ_MASK);
     if (reg) outb_p(reg, priv->scc_cmd);
     outb_p(val, priv->scc_cmd);
     outb(1, priv->card_base + PI_DREQ_MASK);
-    restore_flags(flags);
+    spin_unlock_irqrestore(priv->register_lock, flags);
     return;
   }
 }
@@ -647,12 +653,11 @@
   default:
     if (fast) outb_p(val, priv->scc_data);
     else {
-      save_flags(flags);
-      cli();
+      spin_lock_irqsave(priv->register_lock, flags);
       outb_p(0, priv->card_base + PI_DREQ_MASK);
       outb_p(val, priv->scc_data);
       outb(1, priv->card_base + PI_DREQ_MASK);
-      restore_flags(flags);
+      spin_unlock_irqrestore(priv->register_lock, flags);
     }
     return;
   }
@@ -670,13 +675,12 @@
     if (reg) outb_p(reg, priv->scc_cmd);
     return inb_p(priv->scc_cmd);
   default:
-    save_flags(flags);
-    cli();
+    spin_lock_irqsave(&priv->register_lock, flags);
     outb_p(0, priv->card_base + PI_DREQ_MASK);
     if (reg) outb_p(reg, priv->scc_cmd);
     rc = inb_p(priv->scc_cmd);
     outb(1, priv->card_base + PI_DREQ_MASK);
-    restore_flags(flags);
+    spin_unlock_irqrestore(priv->register_lock, flags);
     return rc;
   }
 }
@@ -691,12 +695,11 @@
   case TYPE_TWIN:
     return inb_p(priv->scc_data);
   default:
-    save_flags(flags);
-    cli();
+    spin_lock_irqsave(priv->register_lock, flags);
     outb_p(0, priv->card_base + PI_DREQ_MASK);
     rc = inb_p(priv->scc_data);
     outb(1, priv->card_base + PI_DREQ_MASK);
-    restore_flags(flags);
+    spin_unlock_irqrestore(priv->register_lock, flags);
     return rc;
   }
 }
@@ -905,9 +908,8 @@
   priv->tx_len[i] = skb->len-1;
 
   /* Clear interrupts while we touch our circular buffers */
-  save_flags(flags);
-  cli();
 
+  spin_lock_irqsave(&priv->ring_lock, flags);
   /* Move the ring buffer's head */
   priv->tx_head = (i + 1) % NUM_TX_BUF;
   priv->tx_count++;
@@ -928,7 +930,7 @@
   }
 
   /* Turn interrupts back on and free buffer */
-  restore_flags(flags);
+  spin_unlock_irqrestore(&priv->ring_lock, flags);
   dev_kfree_skb(skb);
 
   return 0;
@@ -951,6 +953,7 @@
 static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
   struct scc_info *info = dev_id;
 
+  spin_lock(info->priv[0].register_lock);
   /* At this point interrupts are enabled, and the interrupt under service
      is already acknowledged, but masked off.
 
@@ -978,6 +981,7 @@
       }
     }
   } else z8530_isr(info);
+  spin_unlock(info->priv[0].register_lock);
 }
 
 
@@ -1002,7 +1006,7 @@
     i++;
   }
   if (i < 0) {
-    printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is);
+    printk(KERN_ERR "dmascc: stuck in ISR with RR3=0x%02x.\n", is);
   }
   /* Ok, no interrupts pending from this 8530. The INT line should
      be inactive now. */
@@ -1099,11 +1103,9 @@
   struct sk_buff *skb;
   unsigned char *data;
 
-  save_flags(flags);
-  cli();
-
+  spin_lock_irqsave(&priv->ring_lock, flags);
   while (priv->rx_count) {
-    restore_flags(flags);
+    spin_unlock_irqrestore(&priv->ring_lock, flags);
     cb = priv->rx_len[i];
     /* Allocate buffer */
     skb = dev_alloc_skb(cb+1);
@@ -1123,14 +1125,12 @@
       priv->stats.rx_packets++;
       priv->stats.rx_bytes += cb;
     }
-    save_flags(flags);
-    cli();
+    spin_lock_irqsave(&priv->ring_lock, flags);
     /* Move tail */
     priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
     priv->rx_count--;
   }
-
-  restore_flags(flags);
+  spin_unlock_irqrestore(&priv->ring_lock, flags);
 }
 
 
@@ -1319,12 +1319,11 @@
     else
       write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
     /* Write first byte(s) */
-    save_flags(flags);
-    cli();
+    spin_lock_irqsave(priv->register_lock, flags);
     for (i = 0; i < n; i++)
       write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
     enable_dma(priv->param.dma);
-    restore_flags(flags);
+    spin_unlock_irqrestore(priv->register_lock, flags);
   } else {
     write_scc(priv, R15, TxUIE);
     write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
diff -Nru a/drivers/net/hamradio/soundmodem/Makefile b/drivers/net/hamradio/soundmodem/Makefile
--- a/drivers/net/hamradio/soundmodem/Makefile	Wed Nov 27 14:36:27 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,42 +0,0 @@
-#
-# Makefile for the soundmodem device driver.
-#
-
-obj-$(CONFIG_SOUNDMODEM) += soundmodem.o
-
-soundmodem-y					:= sm.o
-soundmodem-$(CONFIG_SOUNDMODEM_SBC)		+= sm_sbc.o
-soundmodem-$(CONFIG_SOUNDMODEM_WSS)		+= sm_wss.o
-soundmodem-$(CONFIG_SOUNDMODEM_AFSK1200)	+= sm_afsk1200.o
-soundmodem-$(CONFIG_SOUNDMODEM_AFSK2400_7)	+= sm_afsk2400_7.o
-soundmodem-$(CONFIG_SOUNDMODEM_AFSK2400_8)	+= sm_afsk2400_8.o
-soundmodem-$(CONFIG_SOUNDMODEM_AFSK2666)	+= sm_afsk2666.o
-soundmodem-$(CONFIG_SOUNDMODEM_HAPN4800)	+= sm_hapn4800.o
-soundmodem-$(CONFIG_SOUNDMODEM_PSK4800)		+= sm_psk4800.o
-soundmodem-$(CONFIG_SOUNDMODEM_FSK9600)		+= sm_fsk9600.o
-soundmodem-objs					:= $(soundmodem-y)
-
-host-progs := gentbl
-HOST_LOADLIBES := -lm
-
-# Files generated that shall be removed upon make clean
-clean-files  :=	sm_tbl_afsk1200.h   sm_tbl_afsk2400_7.h	\
-		sm_tbl_afsk2400_8.h sm_tbl_afsk2666.h	\
-		sm_tbl_psk4800.h    sm_tbl_hapn4800.h	\
-		sm_tbl_fsk9600.h
-
-include $(TOPDIR)/Rules.make
-
-# Dependencies on generates files need to be listed explicitly
-
-$(obj)/sm_afsk1200.o:   $(obj)/sm_tbl_afsk1200.h
-$(obj)/sm_afsk2400_7.o: $(obj)/sm_tbl_afsk2400_7.h
-$(obj)/sm_afsk2400_8.o: $(obj)/sm_tbl_afsk2400_8.h
-$(obj)/sm_afsk2666.o:   $(obj)/sm_tbl_afsk2666.h
-$(obj)/sm_psk4800.o:    $(obj)/sm_tbl_psk4800.h
-$(obj)/sm_hapn4800.o:   $(obj)/sm_tbl_hapn4800.h
-$(obj)/sm_fsk9600.o:    $(obj)/sm_tbl_fsk9600.h
-
-$(obj)/sm_tbl_%: $(obj)/gentbl
-	cd $(obj) && ./gentbl
-
diff -Nru a/drivers/net/hamradio/soundmodem/gentbl.c b/drivers/net/hamradio/soundmodem/gentbl.c
--- a/drivers/net/hamradio/soundmodem/gentbl.c	Wed Nov 27 14:36:29 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,689 +0,0 @@
-/*****************************************************************************/
-
-/*
- *      gentbl.c  -- soundcard radio modem driver table generator.
- *
- *      Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *      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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-/* -------------------------------------------------------------------- */
-
-static void gentbl_offscostab(FILE *f, unsigned int nbits)
-{
-	int i;
-
-	fprintf(f, "\n/*\n * small cosine table in U8 format\n */\n"
-		"#define OFFSCOSTABBITS %u\n"
-		"#define OFFSCOSTABSIZE (1<<OFFSCOSTABBITS)\n\n", 
-		nbits);
-	fprintf(f, "static unsigned char offscostab[OFFSCOSTABSIZE] = {\n\t");
-	for (i = 0; i < (1<<nbits); i++) {
-		fprintf(f, "%4u", (int)
-			(128+127.0*cos(i*2.0*M_PI/(1<<nbits))));
-		if (i < (1<<nbits)-1) 
-			fprintf(f, "%s", (i & 7) == 7 ? ",\n\t" : ",");
-	}
-	fprintf(f, "\n};\n\n"
-		"#define OFFSCOS(x) offscostab[((x)>>%d)&0x%x]\n\n",
-		16-nbits, (1<<nbits)-1);
-}
-
-/* -------------------------------------------------------------------- */
-
-static void gentbl_costab(FILE *f, unsigned int nbits)
-{
-        int i;
-
-	fprintf(f, "\n/*\n * more accurate cosine table\n */\n\n"
-		"static const short costab[%d] = {", (1<<nbits));
-        for (i = 0; i < (1<<nbits); i++) {
-                if (!(i & 7))
-                        fprintf(f, "\n\t");
-                fprintf(f, "%6d", (int)(32767.0*cos(i*2.0*M_PI/(1<<nbits))));
-                if (i != ((1<<nbits)-1))
-                        fprintf(f, ", ");
-        }
-        fprintf(f, "\n};\n\n#define COS(x) costab[((x)>>%d)&0x%x]\n"
-		"#define SIN(x) COS((x)+0xc000)\n\n", 16-nbits,
-		(1<<nbits)-1);
-}
-
-/* -------------------------------------------------------------------- */
-
-#define AFSK12_SAMPLE_RATE 9600
-#define AFSK12_TX_FREQ_LO 1200
-#define AFSK12_TX_FREQ_HI 2200
-#define AFSK12_CORRLEN 8
-
-static void gentbl_afsk1200(FILE *f)
-{
-        int i, v, sum;
-
-#define ARGLO(x) 2.0*M_PI*(double)x*(double)AFSK12_TX_FREQ_LO/(double)AFSK12_SAMPLE_RATE
-#define ARGHI(x) 2.0*M_PI*(double)x*(double)AFSK12_TX_FREQ_HI/(double)AFSK12_SAMPLE_RATE
-
-	fprintf(f, "\n/*\n * afsk1200 specific tables\n */\n"
-		"#define AFSK12_SAMPLE_RATE %u\n"
-		"#define AFSK12_TX_FREQ_LO %u\n"
-		"#define AFSK12_TX_FREQ_HI %u\n"
-		"#define AFSK12_CORRLEN %u\n\n",
-		AFSK12_SAMPLE_RATE, AFSK12_TX_FREQ_LO, 
-		AFSK12_TX_FREQ_HI, AFSK12_CORRLEN);
-	fprintf(f, "static const int afsk12_tx_lo_i[] = {\n\t");
-        for(sum = i = 0; i < AFSK12_CORRLEN; i++) {
-		sum += (v = 127.0*cos(ARGLO(i)));
-                fprintf(f, " %4i%c", v, (i < AFSK12_CORRLEN-1) ? ',' : ' ');
-	}
-        fprintf(f, "\n};\n#define SUM_AFSK12_TX_LO_I %d\n\n"
-		"static const int afsk12_tx_lo_q[] = {\n\t", sum);
-        for(sum = i = 0; i < AFSK12_CORRLEN; i++) {
-		sum += (v = 127.0*sin(ARGLO(i))); 
-                fprintf(f, " %4i%c", v, (i < AFSK12_CORRLEN-1) ? ',' : ' ');
-	}
-        fprintf(f, "\n};\n#define SUM_AFSK12_TX_LO_Q %d\n\n"
-		"static const int afsk12_tx_hi_i[] = {\n\t", sum);
-        for(sum = i = 0; i < AFSK12_CORRLEN; i++) {
-		sum += (v = 127.0*cos(ARGHI(i))); 
-                fprintf(f, " %4i%c", v, (i < AFSK12_CORRLEN-1) ? ',' : ' ');
-	}
-        fprintf(f, "\n};\n#define SUM_AFSK12_TX_HI_I %d\n\n"
-		"static const int afsk12_tx_hi_q[] = {\n\t", sum);
-        for(sum = i = 0; i < AFSK12_CORRLEN; i++)  {
-		sum += (v = 127.0*sin(ARGHI(i)));
-                fprintf(f, " %4i%c", v, (i < AFSK12_CORRLEN-1) ? ',' : ' ');
-	}
-	fprintf(f, "\n};\n#define SUM_AFSK12_TX_HI_Q %d\n\n", sum);
-#undef ARGLO
-#undef ARGHI
-}
-
-/* -------------------------------------------------------------------- */
-
-static const float fsk96_tx_coeff_4[32] = {
-              -0.001152,        0.000554,        0.002698,        0.002753,
-              -0.002033,       -0.008861,       -0.008002,        0.006607,
-               0.023727,        0.018905,       -0.018056,       -0.057957,
-              -0.044368,        0.055683,        0.207667,        0.322048,
-               0.322048,        0.207667,        0.055683,       -0.044368,
-              -0.057957,       -0.018056,        0.018905,        0.023727,
-               0.006607,       -0.008002,       -0.008861,       -0.002033,
-               0.002753,        0.002698,        0.000554,       -0.001152
-};
-
-static const float fsk96_tx_coeff_5[40] = {
-              -0.001009,       -0.000048,        0.001376,        0.002547,
-               0.002061,       -0.001103,       -0.005795,       -0.008170,
-              -0.004017,        0.006924,        0.018225,        0.019238,
-               0.002925,       -0.025777,       -0.048064,       -0.039683,
-               0.013760,        0.104144,        0.200355,        0.262346,
-               0.262346,        0.200355,        0.104144,        0.013760,
-              -0.039683,       -0.048064,       -0.025777,        0.002925,
-               0.019238,        0.018225,        0.006924,       -0.004017,
-              -0.008170,       -0.005795,       -0.001103,        0.002061,
-               0.002547,        0.001376,       -0.000048,       -0.001009
-};
-
-#define HAMMING(x) (0.54-0.46*cos(2*M_PI*(x)));
-
-static inline float hamming(float x)
-{
-	return 0.54-0.46*cos(2*M_PI*x);
-}
-
-static inline float sinc(float x)
-{
-	if (x == 0)
-		return 1;
-	x *= M_PI;
-	return sin(x)/x;
-}
-
-static void gentbl_fsk9600(FILE *f)
-{
-        int i, j, k, l, m;
-	float s;
-	float c[44];
-	float min, max;
-
-	fprintf(f, "\n/*\n * fsk9600 specific tables\n */\n");
-	min = max = 0;
-	memset(c, 0, sizeof(c));
-#if 0
-	memcpy(c+2, fsk96_tx_coeff_4, sizeof(fsk96_tx_coeff_4));
-#else
-	for (i = 0; i < 29; i++)
-		c[3+i] = sinc(1.2*((i-14.0)/4.0))*hamming(i/28.0)/3.5;
-#endif
-	fprintf(f, "static unsigned char fsk96_txfilt_4[] = {\n\t");
-	for (i = 0; i < 4; i++) {
-		for (j = 0; j < 256; j++) {
-			for (k = 1, s = 0, l = i; k < 256; k <<= 1) {
-				if (j & k) {
-					for (m = 0; m < 4; m++, l++)
-						s += c[l];
-				} else {
-					for (m = 0; m < 4; m++, l++)
-						s -= c[l];
-				}
-			}
-			s *= 0.75;
-			if (s > max)
-				max = s;
-			if (s < min)
-				min = s;
-			fprintf(f, "%4d", (int)(128+127*s));
-			if (i < 3 || j < 255)
-				fprintf(f, ",%s", (j & 7) == 7 
-					? "\n\t" : "");
-		}
-	}
-#ifdef VERBOSE
-	fprintf(stderr, "fsk9600: txfilt4: min = %f; max = %f\n", min, max);
-#endif
-	fprintf(f, "\n};\n\n");
-	min = max = 0;
-	memset(c, 0, sizeof(c));
-#if 0
-	memcpy(c+2, fsk96_tx_coeff_5, sizeof(fsk96_tx_coeff_5));
-#else
-	for (i = 0; i < 36; i++)
-		c[4+i] = sinc(1.2*((i-17.5)/5.0))*hamming(i/35.0)/4.5;
-#endif
-	fprintf(f, "static unsigned char fsk96_txfilt_5[] = {\n\t");
-	for (i = 0; i < 5; i++) {
-		for (j = 0; j < 256; j++) {
-			for (k = 1, s = 0, l = i; k < 256; k <<= 1) {
-				if (j & k) {
-					for (m = 0; m < 5; m++, l++)
-						s += c[l];
-				} else {
-					for (m = 0; m < 5; m++, l++)
-						s -= c[l];
-				}
-			}
-			s *= 0.75;
-			if (s > max)
-				max = s;
-			if (s < min)
-				min = s;
-			fprintf(f, "%4d", (int)(128+127*s));
-			if (i < 4 || j < 255)
-				fprintf(f, ",%s", (j & 7) == 7 
-					? "\n\t" : "");
-		}
-	}
-#ifdef VERBOSE
-	fprintf(stderr, "fsk9600: txfilt5: min = %f; max = %f\n", min, max);
-#endif
-	fprintf(f, "\n};\n\n");
-}
-	
-/* -------------------------------------------------------------------- */
-
-#define AFSK26_SAMPLERATE  16000
-
-#define AFSK26_NUMCAR      2
-#define AFSK26_FIRSTCAR    2000
-#define AFSK26_MSK_LEN     6
-#define AFSK26_RXOVER      2
-
-#define AFSK26_DEMCORRLEN (2*AFSK26_MSK_LEN)
-
-#define AFSK26_WINDOW(x) ((1-cos(2.0*M_PI*(x)))/2.0)
-
-#define AFSK26_AMPL(x) (((x)?1.0:0.7))
-
-#undef AFSK26_AMPL
-#define AFSK26_AMPL(x) 1
-
-static void gentbl_afsk2666(FILE *f)
-{
-        int i, j, k, l, o, v, sumi, sumq;
-        float window[AFSK26_DEMCORRLEN*AFSK26_RXOVER];
-	int cfreq[AFSK26_NUMCAR];
-
-	fprintf(f, "\n/*\n * afsk2666 specific tables\n */\n"
-		"#define AFSK26_DEMCORRLEN %d\n"
-		"#define AFSK26_SAMPLERATE %d\n\n", AFSK26_DEMCORRLEN,
-		AFSK26_SAMPLERATE);
-	fprintf(f, "static const unsigned int afsk26_carfreq[%d] = { ",
-		AFSK26_NUMCAR);
-	for (i = 0; i < AFSK26_NUMCAR; i++) {
-		cfreq[i] = 0x10000*AFSK26_FIRSTCAR/AFSK26_SAMPLERATE+
-			0x10000*i/AFSK26_MSK_LEN/2;
-		fprintf(f, "0x%x", cfreq[i]);
-		if (i < AFSK26_NUMCAR-1)
-			fprintf(f, ", ");
-	}
-	fprintf(f, " };\n\n");
-        for (i = 0; i < AFSK26_DEMCORRLEN*AFSK26_RXOVER; i++)
-                window[i] = AFSK26_WINDOW(((float)i)/(AFSK26_DEMCORRLEN*
-						      AFSK26_RXOVER)) * 127.0;
-        fprintf(f, "\nstatic const struct {\n\t"
-               "int i[%d];\n\tint q[%d];\n} afsk26_dem_tables[%d][%d] = {\n", 
-               AFSK26_DEMCORRLEN, AFSK26_DEMCORRLEN, AFSK26_RXOVER, AFSK26_NUMCAR);
-        for (o = AFSK26_RXOVER-1; o >= 0; o--) {
-                fprintf(f, "\t{\n");
-                for (i = 0; i < AFSK26_NUMCAR; i++) {
-                        j = cfreq[i];
-                        fprintf(f, "\t\t{{ ");
-                        for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumi = 0; l >= 0; 
-                             l--, k = (k+j)&0xffffu) {
-				sumi += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]*
-					 cos(M_PI*k/32768.0));
-                                fprintf(f, "%6d%s", v, l ? ", " : " }, { ");
-			}
-                        for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumq = 0; l >= 0; 
-                             l--, k = (k+j)&0xffffu) {
-				sumq += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]*
-					 sin(M_PI*k/32768.0));
-                                fprintf(f, "%6d%s", v, l ? ", " : " }}");
-			}
-                        if (i < 1)
-                                fprintf(f, ",");
-                        fprintf(f, "\n#define AFSK26_DEM_SUM_I_%d_%d %d\n"
-				"#define AFSK26_DEM_SUM_Q_%d_%d %d\n", 
-				AFSK26_RXOVER-1-o, i, sumi, AFSK26_RXOVER-1-o, i, sumq);
-                }
-                fprintf(f, "\t}%s\n", o ? "," : "");
-        }
-        fprintf(f, "};\n\n");
-}
-
-/* -------------------------------------------------------------------- */
-
-#define ATAN_TABLEN 1024
-
-static void gentbl_atantab(FILE *f)
-{
-        int i;
-        short x;
-
-	fprintf(f, "\n/*\n"
-		" * arctan table (indexed by i/q; should really be indexed by i/(i+q)\n"
-		" */\n""#define ATAN_TABLEN %d\n\n"
-		"static const unsigned short atan_tab[ATAN_TABLEN+2] = {",
-               ATAN_TABLEN);
-        for (i = 0; i <= ATAN_TABLEN; i++) {
-                if (!(i & 7))
-                        fprintf(f, "\n\t");
-                x = atan(i / (float)ATAN_TABLEN) / M_PI * 0x8000;
-                fprintf(f, "%6d, ", x);
-        }
-        fprintf(f, "%6d\n};\n\n", x);
-	
-}
-
-/* -------------------------------------------------------------------- */
-
-#define PSK48_TXF_OVERSAMPLING 5
-#define PSK48_TXF_NUMSAMPLES 16
-#define PSK48_RXF_LEN     64
-
-static const float psk48_tx_coeff[80] = {
-              -0.000379,       -0.000640,       -0.000000,        0.000772,
-               0.000543,       -0.000629,       -0.001187,       -0.000000,
-               0.001634,        0.001183,       -0.001382,       -0.002603,
-              -0.000000,        0.003481,        0.002472,       -0.002828,
-              -0.005215,       -0.000000,        0.006705,        0.004678,
-              -0.005269,       -0.009584,       -0.000000,        0.012065,
-               0.008360,       -0.009375,       -0.017028,       -0.000000,
-               0.021603,        0.015123,       -0.017229,       -0.032012,
-              -0.000000,        0.043774,        0.032544,       -0.040365,
-              -0.084963,       -0.000000,        0.201161,        0.374060,
-               0.374060,        0.201161,       -0.000000,       -0.084963,
-              -0.040365,        0.032544,        0.043774,       -0.000000,
-              -0.032012,       -0.017229,        0.015123,        0.021603,
-              -0.000000,       -0.017028,       -0.009375,        0.008360,
-               0.012065,       -0.000000,       -0.009584,       -0.005269,
-               0.004678,        0.006705,       -0.000000,       -0.005215,
-              -0.002828,        0.002472,        0.003481,       -0.000000,
-              -0.002603,       -0.001382,        0.001183,        0.001634,
-              -0.000000,       -0.001187,       -0.000629,        0.000543,
-               0.000772,       -0.000000,       -0.000640,       -0.000379
-};
-
-static const float psk48_rx_coeff[PSK48_RXF_LEN] = {
-              -0.000219,        0.000360,        0.000873,        0.001080,
-               0.000747,       -0.000192,       -0.001466,       -0.002436,
-              -0.002328,       -0.000699,        0.002101,        0.004809,
-               0.005696,        0.003492,       -0.001633,       -0.007660,
-              -0.011316,       -0.009627,       -0.001780,        0.009712,
-               0.019426,        0.021199,        0.011342,       -0.008583,
-              -0.030955,       -0.044093,       -0.036634,       -0.002651,
-               0.054742,        0.123101,        0.184198,        0.220219,
-               0.220219,        0.184198,        0.123101,        0.054742,
-              -0.002651,       -0.036634,       -0.044093,       -0.030955,
-              -0.008583,        0.011342,        0.021199,        0.019426,
-               0.009712,       -0.001780,       -0.009627,       -0.011316,
-              -0.007660,       -0.001633,        0.003492,        0.005696,
-               0.004809,        0.002101,       -0.000699,       -0.002328,
-              -0.002436,       -0.001466,       -0.000192,        0.000747,
-               0.001080,        0.000873,        0.000360,       -0.000219
-};
-
-static void gentbl_psk4800(FILE *f)
-{
-        int i, j, k;
-        short x;
-
-	fprintf(f, "\n/*\n * psk4800 specific tables\n */\n"
-		"#define PSK48_TXF_OVERSAMPLING %d\n"
-		"#define PSK48_TXF_NUMSAMPLES %d\n\n"
-		"#define PSK48_SAMPLERATE  8000\n"
-		"#define PSK48_CAR_FREQ    2000\n"
-		"#define PSK48_PSK_LEN     5\n"
-		"#define PSK48_RXF_LEN     %u\n"
-		"#define PSK48_PHASEINC    (0x10000*PSK48_CAR_FREQ/PSK48_SAMPLERATE)\n"
-		"#define PSK48_SPHASEINC   (0x10000/(2*PSK48_PSK_LEN))\n\n"
-		"static const short psk48_tx_table[PSK48_TXF_OVERSAMPLING*"
-		"PSK48_TXF_NUMSAMPLES*8*2] = {", 
-		PSK48_TXF_OVERSAMPLING, PSK48_TXF_NUMSAMPLES, PSK48_RXF_LEN);
-        for (i = 0; i < PSK48_TXF_OVERSAMPLING; i++) {
-                for (j = 0; j < PSK48_TXF_NUMSAMPLES; j++) {
-                        fprintf(f, "\n\t");
-                        for (k = 0; k < 8; k++) {
-                                x = 32767.0 * cos(k*M_PI/4.0) * 
-                                        psk48_tx_coeff[j * PSK48_TXF_OVERSAMPLING + i];
-                                fprintf(f, "%6d, ", x);
-                        }
-                        fprintf(f, "\n\t");
-                        for (k = 0; k < 8; k++) {
-                                x = 32767.0 * sin(k*M_PI/4.0) * 
-                                        psk48_tx_coeff[j * PSK48_TXF_OVERSAMPLING + i];
-                                fprintf(f, "%6d", x);
-                                if (k != 7 || j != PSK48_TXF_NUMSAMPLES-1 || 
-                                    i != PSK48_TXF_OVERSAMPLING-1)
-                                        fprintf(f, ", ");
-                        }
-                }
-        }
-        fprintf(f, "\n};\n\n");
-
-	fprintf(f, "static const short psk48_rx_coeff[PSK48_RXF_LEN] = {\n\t");
-	for (i = 0; i < PSK48_RXF_LEN; i++) {
-		fprintf(f, "%6d", (int)(psk48_rx_coeff[i]*32767.0));
-		if (i < PSK48_RXF_LEN-1)
-			fprintf(f, ",%s", (i & 7) == 7 ? "\n\t" : "");
-	}
-	fprintf(f, "\n};\n\n");
-}
-
-/* -------------------------------------------------------------------- */
-
-static void gentbl_hapn4800(FILE *f)
-{
-        int i, j, k, l;
-	float s;
-	float c[44];
-	float min, max;
-
-	fprintf(f, "\n/*\n * hapn4800 specific tables\n */\n\n");
-	/*
-	 * firstly generate tables for the FM transmitter modulator
-	 */
-	min = max = 0;
-	memset(c, 0, sizeof(c));
-	for (i = 0; i < 24; i++)
-		c[8+i] = sinc(1.5*((i-11.5)/8.0))*hamming(i/23.0)/2.4;
-	for (i = 0; i < 24; i++)
-		c[i] -= c[i+8];
-	fprintf(f, "static unsigned char hapn48_txfilt_8[] = {\n\t");
-	for (i = 0; i < 8; i++) {
-		for (j = 0; j < 16; j++) {
-			for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 8) {
-				if (j & k)
-					s += c[l];
-				else 
-					s -= c[l];
-			}
-			if (s > max)
-				max = s;
-			if (s < min)
-				min = s;
-			fprintf(f, "%4d", (int)(128+127*s));
-			if (i < 7 || j < 15)
-				fprintf(f, ",%s", (j & 7) == 7 
-					? "\n\t" : "");
-		}
-	}
-#ifdef VERBOSE
-	fprintf(stderr, "hapn4800: txfilt8: min = %f; max = %f\n", min, max);
-#endif
-	fprintf(f, "\n};\n\n");
-	min = max = 0;
-	memset(c, 0, sizeof(c));
-	for (i = 0; i < 30; i++)
-		c[10+i] = sinc(1.5*((i-14.5)/10.0))*hamming(i/29.0)/2.4;
-	for (i = 0; i < 30; i++)
-		c[i] -= c[i+10];
-	fprintf(f, "static unsigned char hapn48_txfilt_10[] = {\n\t");
-	for (i = 0; i < 10; i++) {
-		for (j = 0; j < 16; j++) {
-			for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 10) {
-				if (j & k) 
-					s += c[l];
-				else 
-					s -= c[l];
-			}
-			if (s > max)
-				max = s;
-			if (s < min)
-				min = s;
-			fprintf(f, "%4d", (int)(128+127*s));
-			if (i < 9 || j < 15)
-				fprintf(f, ",%s", (j & 7) == 7 
-					? "\n\t" : "");
-		}
-	}
-#ifdef VERBOSE
-	fprintf(stderr, "hapn4800: txfilt10: min = %f; max = %f\n", min, max);
-#endif
-	fprintf(f, "\n};\n\n");
-	/*
-	 * secondly generate tables for the PM transmitter modulator
-	 */
-	min = max = 0;
-	memset(c, 0, sizeof(c));
-	for (i = 0; i < 25; i++)
-		c[i] = sinc(1.4*((i-12.0)/8.0))*hamming(i/24.0)/6.3;
-	for (i = 0; i < 25; i++)
-		for (j = 1; j < 8; j++)
-			c[i] += c[i+j];
-	fprintf(f, "static unsigned char hapn48_txfilt_pm8[] = {\n\t");
-	for (i = 0; i < 8; i++) {
-		for (j = 0; j < 16; j++) {
-			for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 8) {
-				if (j & k)
-					s += c[l];
-				else 
-					s -= c[l];
-			}
-			if (s > max)
-				max = s;
-			if (s < min)
-				min = s;
-			fprintf(f, "%4d", (int)(128+127*s));
-			if (i < 7 || j < 15)
-				fprintf(f, ",%s", (j & 7) == 7 
-					? "\n\t" : "");
-		}
-	}
-#ifdef VERBOSE
-	fprintf(stderr, "hapn4800: txfiltpm8: min = %f; max = %f\n", min, max);
-#endif
-	fprintf(f, "\n};\n\n");
-	min = max = 0;
-	memset(c, 0, sizeof(c));
-	for (i = 0; i < 31; i++)
-		c[10+i] = sinc(1.4*((i-15.0)/10.0))*hamming(i/30.0)/7.9;
-	for (i = 0; i < 31; i++)
-		for (j = 1; j < 10; j++)
-			c[i] += c[i+j];
-	fprintf(f, "static unsigned char hapn48_txfilt_pm10[] = {\n\t");
-	for (i = 0; i < 10; i++) {
-		for (j = 0; j < 16; j++) {
-			for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 10) {
-				if (j & k) 
-					s += c[l];
-				else 
-					s -= c[l];
-			}
-			if (s > max)
-				max = s;
-			if (s < min)
-				min = s;
-			fprintf(f, "%4d", (int)(128+127*s));
-			if (i < 9 || j < 15)
-				fprintf(f, ",%s", (j & 7) == 7 
-					? "\n\t" : "");
-		}
-	}
-#ifdef VERBOSE
-	fprintf(stderr, "hapn4800: txfiltpm10: min = %f; max = %f\n", min, max);
-#endif
-	fprintf(f, "\n};\n\n");
-	
-}
-
-/* -------------------------------------------------------------------- */
-
-#define AFSK24_SAMPLERATE  16000
-#define AFSK24_CORRLEN     14
-
-static void gentbl_afsk2400(FILE *f, float tcm3105clk)
-{
-	int i, sum, v;
-
-	fprintf(f, "\n/*\n * afsk2400 specific tables (tcm3105 clk %7fHz)\n */\n"
-		"#define AFSK24_TX_FREQ_LO %d\n"
-		"#define AFSK24_TX_FREQ_HI %d\n"
-		"#define AFSK24_BITPLL_INC %d\n"
-		"#define AFSK24_SAMPLERATE %d\n\n", tcm3105clk, 
-		(int)(tcm3105clk/3694.0), (int)(tcm3105clk/2015.0), 
-		0x10000*2400/AFSK24_SAMPLERATE, AFSK24_SAMPLERATE);
-
-#define ARGLO(x) 2.0*M_PI*(double)x*(tcm3105clk/3694.0)/(double)AFSK24_SAMPLERATE
-#define ARGHI(x) 2.0*M_PI*(double)x*(tcm3105clk/2015.0)/(double)AFSK24_SAMPLERATE
-#define WINDOW(x) hamming((float)(x)/(AFSK24_CORRLEN-1.0))
-
-	fprintf(f, "static const int afsk24_tx_lo_i[] = {\n\t");
-        for(sum = i = 0; i < AFSK24_CORRLEN; i++) {
-		sum += (v = 127.0*cos(ARGLO(i))*WINDOW(i));
-                fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' ');
-	}
-        fprintf(f, "\n};\n#define SUM_AFSK24_TX_LO_I %d\n\n"
-		"static const int afsk24_tx_lo_q[] = {\n\t", sum);
-        for(sum = i = 0; i < AFSK24_CORRLEN; i++) {
-		sum += (v = 127.0*sin(ARGLO(i))*WINDOW(i)); 
-                fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' ');
-	}
-        fprintf(f, "\n};\n#define SUM_AFSK24_TX_LO_Q %d\n\n"
-		"static const int afsk24_tx_hi_i[] = {\n\t", sum);
-        for(sum = i = 0; i < AFSK24_CORRLEN; i++) {
-		sum += (v = 127.0*cos(ARGHI(i))*WINDOW(i)); 
-                fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' ');
-	}
-        fprintf(f, "\n};\n#define SUM_AFSK24_TX_HI_I %d\n\n"
-		"static const int afsk24_tx_hi_q[] = {\n\t", sum);
-        for(sum = i = 0; i < AFSK24_CORRLEN; i++)  {
-		sum += (v = 127.0*sin(ARGHI(i))*WINDOW(i));
-                fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' ');
-	}
-	fprintf(f, "\n};\n#define SUM_AFSK24_TX_HI_Q %d\n\n", sum);
-#undef ARGLO
-#undef ARGHI
-#undef WINDOW
-}
-
-/* -------------------------------------------------------------------- */
-
-static char *progname;
-
-static void gentbl_banner(FILE *f)
-{
-	fprintf(f, "/*\n * THIS FILE IS GENERATED AUTOMATICALLY BY %s, "
-		"DO NOT EDIT!\n */\n\n", progname);
-}
-
-/* -------------------------------------------------------------------- */
-
-int main(int argc, char *argv[])
-{
-	FILE *f;
-	
-	progname = argv[0];
-	if (!(f = fopen("sm_tbl_afsk1200.h", "w")))
-		exit(1);
-	gentbl_banner(f);
-	gentbl_offscostab(f, 6);
-	gentbl_costab(f, 6);
-	gentbl_afsk1200(f);
-	fclose(f);
-	if (!(f = fopen("sm_tbl_afsk2666.h", "w")))
-		exit(1);
-	gentbl_banner(f);
-	gentbl_offscostab(f, 6);
-	gentbl_costab(f, 6);
-	gentbl_afsk2666(f);
-	fclose(f);
-	if (!(f = fopen("sm_tbl_psk4800.h", "w")))
-		exit(1);
-	gentbl_banner(f);
-	gentbl_psk4800(f);
-	gentbl_costab(f, 8);
-	gentbl_atantab(f);
-	fclose(f);
-	if (!(f = fopen("sm_tbl_hapn4800.h", "w")))
-		exit(1);
-	gentbl_banner(f);
-	gentbl_hapn4800(f);
-	fclose(f);
-	if (!(f = fopen("sm_tbl_fsk9600.h", "w")))
-		exit(1);
-	gentbl_banner(f);
-	gentbl_fsk9600(f);
-	fclose(f);
-	if (!(f = fopen("sm_tbl_afsk2400_8.h", "w")))
-		exit(1);
-	gentbl_banner(f);
-	gentbl_offscostab(f, 6);
-	gentbl_costab(f, 6);
-	gentbl_afsk2400(f, 8000000);
-	fclose(f);
-	if (!(f = fopen("sm_tbl_afsk2400_7.h", "w")))
-		exit(1);
-	gentbl_banner(f);
-	gentbl_offscostab(f, 6);
-	gentbl_costab(f, 6);
-	gentbl_afsk2400(f, 7372800);
-	fclose(f);
-	exit(0);
-}
-
-
-/* -------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm.c b/drivers/net/hamradio/soundmodem/sm.c
--- a/drivers/net/hamradio/soundmodem/sm.c	Wed Nov 27 14:36:31 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,759 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm.c  -- soundcard radio modem driver.
- *
- *	Copyright (C) 1996-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- *
- *  Command line options (insmod command line)
- *
- *  mode     mode string; eg. "wss:afsk1200"
- *  iobase   base address of the soundcard; common values are 0x220 for sbc,
- *           0x530 for wss
- *  irq      interrupt number; common values are 7 or 5 for sbc, 11 for wss
- *  dma      dma number; common values are 0 or 1
- *
- *
- *  History:
- *   0.1  21.09.1996  Started
- *        18.10.1996  Changed to new user space access routines (copy_{to,from}_user)
- *   0.4  21.01.1997  Separately compileable soundcard/modem modules
- *   0.5  03.03.1997  fixed LPT probing (check_lpt result was interpreted the wrong way round)
- *   0.6  16.04.1997  init code/data tagged
- *   0.7  30.07.1997  fixed halfduplex interrupt handlers/hotfix for CS423X
- *   0.8  14.04.1998  cleanups
- *   0.9  03.08.1999  adapt to Linus' new __setup/__initcall
- *                    use parport lowlevel drivers instead of directly writing to a parallel port
- *                    removed some pre-2.2 kernel compatibility cruft
- *   0.10 10.08.1999  Check if parport can do SPP and is safe to access during interrupt contexts
- *   0.11 12.02.2000  adapted to softnet driver interface
- *   0.12 03.07.2000  fix interface name handling
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/parport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include "sm.h"
-
-/* --------------------------------------------------------------------- */
-
-/*static*/ const char sm_drvname[] = "soundmodem";
-static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "soundmodem: version 0.12 compiled " __TIME__ " " __DATE__ "\n";
-
-/* --------------------------------------------------------------------- */
-
-/*static*/ const struct modem_tx_info *sm_modem_tx_table[] = {
-#ifdef CONFIG_SOUNDMODEM_AFSK1200
-	&sm_afsk1200_tx,
-#endif /* CONFIG_SOUNDMODEM_AFSK1200 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2400_7
-	&sm_afsk2400_7_tx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2400_8
-	&sm_afsk2400_8_tx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2666
-	&sm_afsk2666_tx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2666 */
-#ifdef CONFIG_SOUNDMODEM_PSK4800
-	&sm_psk4800_tx,
-#endif /* CONFIG_SOUNDMODEM_PSK4800 */
-#ifdef CONFIG_SOUNDMODEM_HAPN4800
-	&sm_hapn4800_8_tx,
-	&sm_hapn4800_10_tx,
-	&sm_hapn4800_pm8_tx,
-	&sm_hapn4800_pm10_tx,
-#endif /* CONFIG_SOUNDMODEM_HAPN4800 */
-#ifdef CONFIG_SOUNDMODEM_FSK9600
-	&sm_fsk9600_4_tx,
-	&sm_fsk9600_5_tx,
-#endif /* CONFIG_SOUNDMODEM_FSK9600 */
-	NULL
-};
-
-/*static*/ const struct modem_rx_info *sm_modem_rx_table[] = {
-#ifdef CONFIG_SOUNDMODEM_AFSK1200
-	&sm_afsk1200_rx,
-#endif /* CONFIG_SOUNDMODEM_AFSK1200 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2400_7
-	&sm_afsk2400_7_rx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2400_8
-	&sm_afsk2400_8_rx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */
-#ifdef CONFIG_SOUNDMODEM_AFSK2666
-	&sm_afsk2666_rx,
-#endif /* CONFIG_SOUNDMODEM_AFSK2666 */
-#ifdef CONFIG_SOUNDMODEM_PSK4800
-	&sm_psk4800_rx,
-#endif /* CONFIG_SOUNDMODEM_PSK4800 */
-#ifdef CONFIG_SOUNDMODEM_HAPN4800
-	&sm_hapn4800_8_rx,
-	&sm_hapn4800_10_rx,
-	&sm_hapn4800_pm8_rx,
-	&sm_hapn4800_pm10_rx,
-#endif /* CONFIG_SOUNDMODEM_HAPN4800 */
-#ifdef CONFIG_SOUNDMODEM_FSK9600
-	&sm_fsk9600_4_rx,
-	&sm_fsk9600_5_rx,
-#endif /* CONFIG_SOUNDMODEM_FSK9600 */
-	NULL
-};
-
-static const struct hardware_info *sm_hardware_table[] = {
-#ifdef CONFIG_SOUNDMODEM_SBC
-	&sm_hw_sbc,
-	&sm_hw_sbcfdx,
-#endif /* CONFIG_SOUNDMODEM_SBC */
-#ifdef CONFIG_SOUNDMODEM_WSS
-	&sm_hw_wss,
-	&sm_hw_wssfdx,
-#endif /* CONFIG_SOUNDMODEM_WSS */
-	NULL
-};
-
-/* --------------------------------------------------------------------- */
-
-#define NR_PORTS 4
-
-static struct net_device sm_device[NR_PORTS];
-
-/* --------------------------------------------------------------------- */
-
-#define UART_RBR(iobase) (iobase+0)
-#define UART_THR(iobase) (iobase+0)
-#define UART_IER(iobase) (iobase+1)
-#define UART_IIR(iobase) (iobase+2)
-#define UART_FCR(iobase) (iobase+2)
-#define UART_LCR(iobase) (iobase+3)
-#define UART_MCR(iobase) (iobase+4)
-#define UART_LSR(iobase) (iobase+5)
-#define UART_MSR(iobase) (iobase+6)
-#define UART_SCR(iobase) (iobase+7)
-#define UART_DLL(iobase) (iobase+0)
-#define UART_DLM(iobase) (iobase+1)
-
-#define SER_EXTENT 8
-
-#define MIDI_DATA(iobase)     (iobase)
-#define MIDI_STATUS(iobase)   (iobase+1)
-#define MIDI_READ_FULL 0x80   /* attention: negative logic!! */
-#define MIDI_WRITE_EMPTY 0x40 /* attention: negative logic!! */
-
-#define MIDI_EXTENT 2
-
-/* ---------------------------------------------------------------------- */
-
-#define PARAM_TXDELAY   1
-#define PARAM_PERSIST   2
-#define PARAM_SLOTTIME  3
-#define PARAM_TXTAIL    4
-#define PARAM_FULLDUP   5
-#define PARAM_HARDWARE  6
-#define PARAM_RETURN    255
-
-#define SP_SER  1
-#define SP_PAR  2
-#define SP_MIDI 4
-
-/*
- * ===================== port checking routines ========================
- */
-
-enum uart { c_uart_unknown, c_uart_8250,
-	c_uart_16450, c_uart_16550, c_uart_16550A};
-static const char *uart_str[] =
-	{ "unknown", "8250", "16450", "16550", "16550A" };
-
-static enum uart check_uart(unsigned int iobase)
-{
-	unsigned char b1,b2,b3;
-	enum uart u;
-	enum uart uart_tab[] =
-		{ c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
-
-	if (iobase <= 0 || iobase > 0x1000-SER_EXTENT)
-		return c_uart_unknown;
-	if (check_region(iobase, SER_EXTENT))
-		return c_uart_unknown;
-	b1 = inb(UART_MCR(iobase));
-	outb(b1 | 0x10, UART_MCR(iobase));	/* loopback mode */
-	b2 = inb(UART_MSR(iobase));
-	outb(0x1a, UART_MCR(iobase));
-	b3 = inb(UART_MSR(iobase)) & 0xf0;
-	outb(b1, UART_MCR(iobase));	   /* restore old values */
-	outb(b2, UART_MSR(iobase));
-	if (b3 != 0x90)
-		return c_uart_unknown;
-	inb(UART_RBR(iobase));
-	inb(UART_RBR(iobase));
-	outb(0x01, UART_FCR(iobase));		/* enable FIFOs */
-	u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3];
-	if (u == c_uart_16450) {
-		outb(0x5a, UART_SCR(iobase));
-		b1 = inb(UART_SCR(iobase));
-		outb(0xa5, UART_SCR(iobase));
-		b2 = inb(UART_SCR(iobase));
-		if ((b1 != 0x5a) || (b2 != 0xa5))
-			u = c_uart_8250;
-	}
-	return u;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int check_midi(unsigned int iobase)
-{
-	unsigned long timeout;
-	unsigned long flags;
-	unsigned char b;
-
-	if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT)
-		return 0;
-	if (check_region(iobase, MIDI_EXTENT))
-		return 0;
-	timeout = jiffies + (HZ / 100);
-	while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)
-		if ((signed)(jiffies - timeout) > 0)
-			return 0;
-	save_flags(flags);
-	cli();
-	outb(0xff, MIDI_DATA(iobase));
-	b = inb(MIDI_STATUS(iobase));
-	restore_flags(flags);
-	if (!(b & MIDI_WRITE_EMPTY))
-		return 0;
-	while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY)
-		if ((signed)(jiffies - timeout) > 0)
-			return 0;
-	return 1;
-}
-
-/* --------------------------------------------------------------------- */
-
-void sm_output_status(struct sm_state *sm)
-{
-	int invert_dcd = 0;
-	int invert_ptt = 0;
-
-	int ptt = /*hdlcdrv_ptt(&sm->hdrv)*/(sm->dma.ptt_cnt > 0) ^ invert_ptt;
-	int dcd = (!!sm->hdrv.hdlcrx.dcd) ^ invert_dcd;
-
-	if (sm->hdrv.ptt_out.flags & SP_SER) {
-		outb(dcd | (ptt << 1), UART_MCR(sm->hdrv.ptt_out.seriobase));
-		outb(0x40 & (-ptt), UART_LCR(sm->hdrv.ptt_out.seriobase));
-	}
-	if (sm->hdrv.ptt_out.flags & SP_PAR && sm->pardev && sm->pardev->port)
-		parport_write_data(sm->pardev->port, ptt | (dcd << 1));
-	if (sm->hdrv.ptt_out.flags & SP_MIDI && hdlcdrv_ptt(&sm->hdrv))
-		outb(0, MIDI_DATA(sm->hdrv.ptt_out.midiiobase));
-}
-
-/* --------------------------------------------------------------------- */
-
-static void sm_output_open(struct sm_state *sm, const char *ifname)
-{
-	enum uart u = c_uart_unknown;
-	struct parport *pp = NULL;
-
-	sm->hdrv.ptt_out.flags = 0;
-	if (sm->hdrv.ptt_out.seriobase > 0 &&
-	    sm->hdrv.ptt_out.seriobase <= 0x1000-SER_EXTENT &&
-	    ((u = check_uart(sm->hdrv.ptt_out.seriobase))) != c_uart_unknown) {
-		sm->hdrv.ptt_out.flags |= SP_SER;
-		request_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT, "sm ser ptt");
-		outb(0, UART_IER(sm->hdrv.ptt_out.seriobase));
-		/* 5 bits, 1 stop, no parity, no break, Div latch access */
-		outb(0x80, UART_LCR(sm->hdrv.ptt_out.seriobase));
-		outb(0, UART_DLM(sm->hdrv.ptt_out.seriobase));
-		outb(1, UART_DLL(sm->hdrv.ptt_out.seriobase)); /* as fast as possible */
-		/* LCR and MCR set by output_status */
-	}
-	sm->pardev = NULL;
-	if (sm->hdrv.ptt_out.pariobase > 0) {
-		pp = parport_enumerate();
-		while (pp && pp->base != sm->hdrv.ptt_out.pariobase) 
-			pp = pp->next;
-		if (!pp)
-			printk(KERN_WARNING "%s: parport at address 0x%x not found\n", sm_drvname, sm->hdrv.ptt_out.pariobase);
-		else if ((~pp->modes) & (PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT))
-			printk(KERN_WARNING "%s: parport at address 0x%x cannot be used\n", sm_drvname, sm->hdrv.ptt_out.pariobase);
-		else {
-			sm->pardev = parport_register_device(pp, ifname, NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-			if (!sm->pardev) {
-				pp = NULL;
-				printk(KERN_WARNING "%s: cannot register parport device (address 0x%x)\n", sm_drvname, sm->hdrv.ptt_out.pariobase);
-			} else {
-				if (parport_claim(sm->pardev)) {
-					parport_unregister_device(sm->pardev);
-					sm->pardev = NULL;
-					printk(KERN_WARNING "%s: cannot claim parport at address 0x%x\n", sm_drvname, sm->hdrv.ptt_out.pariobase);
-				} else
-					sm->hdrv.ptt_out.flags |= SP_PAR;
-			}
-		}
-	}
-	if (sm->hdrv.ptt_out.midiiobase > 0 &&
-	    sm->hdrv.ptt_out.midiiobase <= 0x1000-MIDI_EXTENT &&
-	    check_midi(sm->hdrv.ptt_out.midiiobase)) {
-		sm->hdrv.ptt_out.flags |= SP_MIDI;
-		request_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT,
-			       "sm midi ptt");
-	}
-	sm_output_status(sm);
-
-	printk(KERN_INFO "%s: ptt output:", sm_drvname);
-	if (sm->hdrv.ptt_out.flags & SP_SER)
-		printk(" serial interface at 0x%x, uart %s", sm->hdrv.ptt_out.seriobase,
-		       uart_str[u]);
-	if (sm->hdrv.ptt_out.flags & SP_PAR)
-		printk(" parallel interface at 0x%x", sm->hdrv.ptt_out.pariobase);
-	if (sm->hdrv.ptt_out.flags & SP_MIDI)
-		printk(" mpu401 (midi) interface at 0x%x", sm->hdrv.ptt_out.midiiobase);
-	if (!sm->hdrv.ptt_out.flags)
-		printk(" none");
-	printk("\n");
-}
-
-/* --------------------------------------------------------------------- */
-
-static void sm_output_close(struct sm_state *sm)
-{
-	/* release regions used for PTT output */
-	sm->hdrv.hdlctx.ptt = sm->hdrv.hdlctx.calibrate = 0;
-	sm_output_status(sm);
-	if (sm->hdrv.ptt_out.flags & SP_SER)
-		release_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT);
-       	if (sm->hdrv.ptt_out.flags & SP_PAR && sm->pardev) {
-		        parport_release(sm->pardev);
-			parport_unregister_device(sm->pardev);
-	}
-       	if (sm->hdrv.ptt_out.flags & SP_MIDI)
-		release_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT);
-	sm->hdrv.ptt_out.flags = 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sm_open(struct net_device *dev);
-static int sm_close(struct net_device *dev);
-static int sm_ioctl(struct net_device *dev, struct ifreq *ifr,
-		    struct hdlcdrv_ioctl *hi, int cmd);
-
-/* --------------------------------------------------------------------- */
-
-static const struct hdlcdrv_ops sm_ops = {
-	sm_drvname, sm_drvinfo, sm_open, sm_close, sm_ioctl
-};
-
-/* --------------------------------------------------------------------- */
-
-static int sm_open(struct net_device *dev)
-{
-	struct sm_state *sm;
-	int err;
-
-	if (!dev || !dev->priv ||
-	    ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
-		printk(KERN_ERR "sm_open: invalid device struct\n");
-		return -EINVAL;
-	}
-	sm = (struct sm_state *)dev->priv;
-
-	if (!sm->mode_tx || !sm->mode_rx || !sm->hwdrv || !sm->hwdrv->open)
-		return -ENODEV;
-	sm->hdrv.par.bitrate = sm->mode_rx->bitrate;
-	err = sm->hwdrv->open(dev, sm);
-	if (err)
-		return err;
-	sm_output_open(sm, dev->name);
-	MOD_INC_USE_COUNT;
-	printk(KERN_INFO "%s: %s mode %s.%s at iobase 0x%lx irq %u dma %u dma2 %u\n",
-	       sm_drvname, sm->hwdrv->hw_name, sm->mode_tx->name,
-	       sm->mode_rx->name, dev->base_addr, dev->irq, dev->dma, sm->hdrv.ptt_out.dma2);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sm_close(struct net_device *dev)
-{
-	struct sm_state *sm;
-	int err = -ENODEV;
-
-	if (!dev || !dev->priv ||
-	    ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
-		printk(KERN_ERR "sm_close: invalid device struct\n");
-		return -EINVAL;
-	}
-	sm = (struct sm_state *)dev->priv;
-
-
-	if (sm->hwdrv && sm->hwdrv->close)
-		err = sm->hwdrv && sm->hwdrv->close(dev, sm);
-	sm_output_close(sm);
-	MOD_DEC_USE_COUNT;
-	printk(KERN_INFO "%s: close %s at iobase 0x%lx irq %u dma %u\n",
-	       sm_drvname, sm->hwdrv->hw_name, dev->base_addr, dev->irq, dev->dma);
-	return err;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sethw(struct net_device *dev, struct sm_state *sm, char *mode)
-{
-	char *cp = strchr(mode, ':');
-	const struct hardware_info **hwp = sm_hardware_table;
-
-	if (!cp)
-		cp = mode;
-	else {
-		*cp++ = '\0';
-		while (hwp && (*hwp) && (*hwp)->hw_name && strcmp((*hwp)->hw_name, mode))
-			hwp++;
-		if (!hwp || !*hwp || !(*hwp)->hw_name)
-			return -EINVAL;
-		if ((*hwp)->loc_storage > sizeof(sm->hw)) {
-			printk(KERN_ERR "%s: insufficient storage for hw driver %s (%d)\n",
-			       sm_drvname, (*hwp)->hw_name, (*hwp)->loc_storage);
-			return -EINVAL;
-		}
-		sm->hwdrv = *hwp;
-	}
-	if (!*cp)
-		return 0;
-	if (sm->hwdrv && sm->hwdrv->sethw)
-		return sm->hwdrv->sethw(dev, sm, cp);
-	return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sm_ioctl(struct net_device *dev, struct ifreq *ifr,
-		    struct hdlcdrv_ioctl *hi, int cmd)
-{
-	struct sm_state *sm;
-	struct sm_ioctl bi;
-	unsigned long flags;
-	unsigned int newdiagmode;
-	unsigned int newdiagflags;
-	char *cp;
-	const struct modem_tx_info **mtp = sm_modem_tx_table;
-	const struct modem_rx_info **mrp = sm_modem_rx_table;
-	const struct hardware_info **hwp = sm_hardware_table;
-
-	if (!dev || !dev->priv ||
-	    ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
-		printk(KERN_ERR "sm_ioctl: invalid device struct\n");
-		return -EINVAL;
-	}
-	sm = (struct sm_state *)dev->priv;
-
-	if (cmd != SIOCDEVPRIVATE) {
-		if (!sm->hwdrv || !sm->hwdrv->ioctl)
-			return sm->hwdrv->ioctl(dev, sm, ifr, hi, cmd);
-		return -ENOIOCTLCMD;
-	}
-	switch (hi->cmd) {
-	default:
-		if (sm->hwdrv && sm->hwdrv->ioctl)
-			return sm->hwdrv->ioctl(dev, sm, ifr, hi, cmd);
-		return -ENOIOCTLCMD;
-
-	case HDLCDRVCTL_GETMODE:
-		cp = hi->data.modename;
-		if (sm->hwdrv && sm->hwdrv->hw_name)
-			cp += sprintf(cp, "%s:", sm->hwdrv->hw_name);
-		else
-			cp += sprintf(cp, "<unspec>:");
-		if (sm->mode_tx && sm->mode_tx->name)
-			cp += sprintf(cp, "%s", sm->mode_tx->name);
-		else
-			cp += sprintf(cp, "<unspec>");
-		if (!sm->mode_rx || !sm->mode_rx ||
-		    strcmp(sm->mode_rx->name, sm->mode_tx->name)) {
-			if (sm->mode_rx && sm->mode_rx->name)
-				cp += sprintf(cp, ",%s", sm->mode_rx->name);
-			else
-				cp += sprintf(cp, ",<unspec>");
-		}
-		if (copy_to_user(ifr->ifr_data, hi, sizeof(*hi)))
-			return -EFAULT;
-		return 0;
-
-	case HDLCDRVCTL_SETMODE:
-		if (netif_running(dev) || !capable(CAP_NET_ADMIN))
-			return -EACCES;
-		hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
-		return sethw(dev, sm, hi->data.modename);
-
-	case HDLCDRVCTL_MODELIST:
-		cp = hi->data.modename;
-		while (*hwp) {
-			if ((*hwp)->hw_name)
-				cp += sprintf(cp, "%s:,", (*hwp)->hw_name);
-			hwp++;
-		}
-		while (*mtp) {
-			if ((*mtp)->name)
-				cp += sprintf(cp, ">%s,", (*mtp)->name);
-			mtp++;
-		}
-		while (*mrp) {
-			if ((*mrp)->name)
-				cp += sprintf(cp, "<%s,", (*mrp)->name);
-			mrp++;
-		}
-		cp[-1] = '\0';
-		if (copy_to_user(ifr->ifr_data, hi, sizeof(*hi)))
-			return -EFAULT;
-		return 0;
-
-#ifdef SM_DEBUG
-	case SMCTL_GETDEBUG:
-		if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
-			return -EFAULT;
-		bi.data.dbg.int_rate = sm->debug_vals.last_intcnt;
-		bi.data.dbg.mod_cycles = sm->debug_vals.mod_cyc;
-		bi.data.dbg.demod_cycles = sm->debug_vals.demod_cyc;
-		bi.data.dbg.dma_residue = sm->debug_vals.dma_residue;
-		sm->debug_vals.mod_cyc = sm->debug_vals.demod_cyc =
-			sm->debug_vals.dma_residue = 0;
-		if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-			return -EFAULT;
-		return 0;
-#endif /* SM_DEBUG */
-
-	case SMCTL_DIAGNOSE:
-		if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
-			return -EFAULT;
-		newdiagmode = bi.data.diag.mode;
-		newdiagflags = bi.data.diag.flags;
-		if (newdiagmode > SM_DIAGMODE_CONSTELLATION)
-			return -EINVAL;
-		bi.data.diag.mode = sm->diag.mode;
-		bi.data.diag.flags = sm->diag.flags;
-		bi.data.diag.samplesperbit = sm->mode_rx->sperbit;
-		if (sm->diag.mode != newdiagmode) {
-			save_flags(flags);
-			cli();
-			sm->diag.ptr = -1;
-			sm->diag.flags = newdiagflags & ~SM_DIAGFLAG_VALID;
-			sm->diag.mode = newdiagmode;
-			restore_flags(flags);
-			if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-				return -EFAULT;
-			return 0;
-		}
-		if (sm->diag.ptr < 0 || sm->diag.mode == SM_DIAGMODE_OFF) {
-			if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-				return -EFAULT;
-			return 0;
-		}
-		if (bi.data.diag.datalen > DIAGDATALEN)
-			bi.data.diag.datalen = DIAGDATALEN;
-		if (sm->diag.ptr < bi.data.diag.datalen) {
-			if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-				return -EFAULT;
-			return 0;
-		}
-		if (copy_to_user(bi.data.diag.data, sm->diag.data,
-				 bi.data.diag.datalen * sizeof(short)))
-			return -EFAULT;
-		bi.data.diag.flags |= SM_DIAGFLAG_VALID;
-		save_flags(flags);
-		cli();
-		sm->diag.ptr = -1;
-		sm->diag.flags = newdiagflags & ~SM_DIAGFLAG_VALID;
-		sm->diag.mode = newdiagmode;
-		restore_flags(flags);
-		if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-			return -EFAULT;
-		return 0;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * command line settable parameters
- */
-static char *mode[NR_PORTS] = { [0 ... NR_PORTS-1] = NULL };
-static int iobase[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 };
-static int irq[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 };
-static int dma[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 };
-static int dma2[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 };
-static int serio[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 };
-static int pario[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 };
-static int midiio[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 };
-
-MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s");
-MODULE_PARM_DESC(mode, "soundmodem operating mode; eg. sbc:afsk1200 or wss:fsk9600");
-MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i");
-MODULE_PARM_DESC(iobase, "soundmodem base address");
-MODULE_PARM(irq, "1-" __MODULE_STRING(NR_PORTS) "i");
-MODULE_PARM_DESC(irq, "soundmodem interrupt");
-MODULE_PARM(dma, "1-" __MODULE_STRING(NR_PORTS) "i");
-MODULE_PARM_DESC(dma, "soundmodem dma channel");
-MODULE_PARM(dma2, "1-" __MODULE_STRING(NR_PORTS) "i");
-MODULE_PARM_DESC(dma2, "soundmodem 2nd dma channel; full duplex only");
-MODULE_PARM(serio, "1-" __MODULE_STRING(NR_PORTS) "i");
-MODULE_PARM_DESC(serio, "soundmodem PTT output on serial port");
-MODULE_PARM(pario, "1-" __MODULE_STRING(NR_PORTS) "i");
-MODULE_PARM_DESC(pario, "soundmodem PTT output on parallel port");
-MODULE_PARM(midiio, "1-" __MODULE_STRING(NR_PORTS) "i");
-MODULE_PARM_DESC(midiio, "soundmodem PTT output on midi port");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("Soundcard amateur radio modem driver");
-
-/* --------------------------------------------------------------------- */
-
-static int __init init_soundmodem(void)
-{
-	int i, j, found = 0;
-	char set_hw = 1;
-	struct sm_state *sm;
-
-	printk(sm_drvinfo);
-	/*
-	 * register net devices
-	 */
-	for (i = 0; i < NR_PORTS; i++) {
-		struct net_device *dev = sm_device+i;
-		char ifname[IFNAMSIZ];
-
-		sprintf(ifname, "sm%d", i);
-		if (!mode[i])
-			set_hw = 0;
-		else {
-			if (!strncmp(mode[i], "sbc", 3)) {
-				if (iobase[i] == -1)
-					iobase[i] = 0x220;
-				if (irq[i] == -1)
-					irq[i] = 5;
-				if (dma[i] == -1)
-					dma[i] = 1;
-			} else {
-				if (iobase[i] == -1)
-					iobase[i] = 0x530;
-				if (irq[i] == -1)
-					irq[i] = 11;
-				if (dma[i] == -1)
-					dma[i] = 1;
-			}
-		}
-		if (!set_hw)
-			iobase[i] = irq[i] = 0;
-		j = hdlcdrv_register_hdlcdrv(dev, &sm_ops, sizeof(struct sm_state), ifname, iobase[i], irq[i], dma[i]);
-		if (!j) {
-			sm = (struct sm_state *)dev->priv;
-			sm->hdrv.ptt_out.dma2 = dma2[i];
-			sm->hdrv.ptt_out.seriobase = serio[i];
-			sm->hdrv.ptt_out.pariobase = pario[i];
-			sm->hdrv.ptt_out.midiiobase = midiio[i];
-			if (set_hw && sethw(dev, sm, mode[i]))
-				set_hw = 0;
-			found++;
-		} else {
-			printk(KERN_WARNING "%s: cannot register net device\n", sm_drvname);
-		}
-	}
-	if (!found)
-		return -ENXIO;
-	return 0;
-}
-
-static void __exit cleanup_soundmodem(void)
-{
-	int i;
-
-	printk(KERN_INFO "sm: cleanup_module called\n");
-
-	for(i = 0; i < NR_PORTS; i++) {
-		struct net_device *dev = sm_device+i;
-		struct sm_state *sm = (struct sm_state *)dev->priv;
-
-		if (sm) {
-			if (sm->hdrv.magic != HDLCDRV_MAGIC)
-				printk(KERN_ERR "sm: invalid magic in "
-				       "cleanup_module\n");
-			else
-				hdlcdrv_unregister_hdlcdrv(dev);
-		}
-	}
-}
-
-module_init(init_soundmodem);
-module_exit(cleanup_soundmodem);
-
-/* --------------------------------------------------------------------- */
-
-#ifndef MODULE
-
-/*
- * format: soundmodem=io,irq,dma[,dma2[,serio[,pario]]],mode
- * mode: hw:modem
- * hw: sbc, wss, wssfdx
- * modem: afsk1200, fsk9600
- */
-
-static int __init sm_setup(char *str)
-{
-	static unsigned nr_dev;
-	int ints[8];
-
-	if (nr_dev >= NR_PORTS)
-		return 0;
-	str = get_options(str, 8, ints);
-	mode[nr_dev] = str;
-	if (ints[0] >= 1)
-		iobase[nr_dev] = ints[1];
-	if (ints[0] >= 2)
-		irq[nr_dev] = ints[2];
-	if (ints[0] >= 3)
-		dma[nr_dev] = ints[3];
-	if (ints[0] >= 4)
-		dma2[nr_dev] = ints[4];
-	if (ints[0] >= 5)
-		serio[nr_dev] = ints[5];
-	if (ints[0] >= 6)
-		pario[nr_dev] = ints[6];
-	if (ints[0] >= 7)
-		midiio[nr_dev] = ints[7];
-	nr_dev++;
-	return 1;
-}
-
-__setup("soundmodem=", sm_setup);
-
-#endif /* MODULE */
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm.h b/drivers/net/hamradio/soundmodem/sm.h
--- a/drivers/net/hamradio/soundmodem/sm.h	Wed Nov 27 14:36:27 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,383 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm.h  --  soundcard radio modem driver internal header.
- *
- *	Copyright (C) 1996-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#ifndef _SM_H
-#define _SM_H
-
-/* ---------------------------------------------------------------------- */
-
-#include <linux/hdlcdrv.h>
-#include <linux/soundmodem.h>
-#include <asm/processor.h>
-#include <linux/bitops.h>
-#include <linux/parport.h>
-
-#define SM_DEBUG
-
-/* ---------------------------------------------------------------------- */
-/*
- * Information that need to be kept for each board.
- */
-
-struct sm_state {
-	struct hdlcdrv_state hdrv;
-
-	const struct modem_tx_info *mode_tx;
-	const struct modem_rx_info *mode_rx;
-
-	const struct hardware_info *hwdrv;
-
-	struct pardevice *pardev;
-
-	/*
-	 * Hardware (soundcard) access routines state
-	 */
-	struct {
-		void *ibuf;
-		unsigned int ifragsz;
-		unsigned int ifragptr;
-		unsigned int i16bit;
-		void *obuf;
-		unsigned int ofragsz;
-		unsigned int ofragptr;
-		unsigned int o16bit;
-		int ptt_cnt;
-	} dma;
-
-	union {
-		long hw[32/sizeof(long)];
-	} hw;
-
-	/*
-	 * state of the modem code
-	 */
-	union {
-		long m[48/sizeof(long)];
-	} m;
-	union {
-		long d[256/sizeof(long)];
-	} d;
-
-#define DIAGDATALEN 64
-	struct diag_data {
-		unsigned int mode;
-		unsigned int flags;
-		volatile int ptr;
-		short data[DIAGDATALEN];
-	} diag;
-
-
-#ifdef SM_DEBUG
-	struct debug_vals {
-		unsigned long last_jiffies;
-		unsigned cur_intcnt;
-		unsigned last_intcnt;
-		unsigned mod_cyc;
-		unsigned demod_cyc;
-		unsigned dma_residue;
-	} debug_vals;
-#endif /* SM_DEBUG */
-};
-
-/* ---------------------------------------------------------------------- */
-/*
- * Mode definition structure
- */
-
-struct modem_tx_info {
-	const char *name;
-	unsigned int loc_storage;
-	int srate;
-	int bitrate;
-        void (*modulator_u8)(struct sm_state *, unsigned char *, unsigned int);
-        void (*modulator_s16)(struct sm_state *, short *, unsigned int);
-        void (*init)(struct sm_state *);
-};
-
-struct modem_rx_info {
-	const char *name;
-	unsigned int loc_storage;
-	int srate;
-	int bitrate;
-	unsigned int overlap;
-	unsigned int sperbit;
-        void (*demodulator_u8)(struct sm_state *, const unsigned char *, unsigned int);
-        void (*demodulator_s16)(struct sm_state *, const short *, unsigned int);
-        void (*init)(struct sm_state *);
-};
-
-/* ---------------------------------------------------------------------- */
-/*
- * Soundcard driver definition structure
- */
-
-struct hardware_info {
-	char *hw_name; /* used for request_{region,irq,dma} */
-	unsigned int loc_storage;
-	/*
-	 * mode specific open/close
-	 */
-	int (*open)(struct net_device *, struct sm_state *);
-	int (*close)(struct net_device *, struct sm_state *);
-	int (*ioctl)(struct net_device *, struct sm_state *, struct ifreq *,
-		     struct hdlcdrv_ioctl *, int);
-	int (*sethw)(struct net_device *, struct sm_state *, char *);
-};
-
-/* --------------------------------------------------------------------- */
-
-extern const char sm_drvname[];
-extern const char sm_drvinfo[];
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== diagnostics stuff ===============================
- */
-
-static inline void diag_trigger(struct sm_state *sm)
-{
-	if (sm->diag.ptr < 0)
-		if (!(sm->diag.flags & SM_DIAGFLAG_DCDGATE) || sm->hdrv.hdlcrx.dcd)
-			sm->diag.ptr = 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-#define SHRT_MAX ((short)(((unsigned short)(~0U))>>1))
-#define SHRT_MIN (-SHRT_MAX-1)
-
-static inline void diag_add(struct sm_state *sm, int valinp, int valdemod)
-{
-	int val;
-
-	if ((sm->diag.mode != SM_DIAGMODE_INPUT &&
-	     sm->diag.mode != SM_DIAGMODE_DEMOD) ||
-	    sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0)
-		return;
-	val = (sm->diag.mode == SM_DIAGMODE_DEMOD) ? valdemod : valinp;
-	/* clip */
-	if (val > SHRT_MAX)
-		val = SHRT_MAX;
-	if (val < SHRT_MIN)
-		val = SHRT_MIN;
-	sm->diag.data[sm->diag.ptr++] = val;
-}
-
-/* --------------------------------------------------------------------- */
-
-static inline void diag_add_one(struct sm_state *sm, int val)
-{
-	if ((sm->diag.mode != SM_DIAGMODE_INPUT &&
-	     sm->diag.mode != SM_DIAGMODE_DEMOD) ||
-	    sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0)
-		return;
-	/* clip */
-	if (val > SHRT_MAX)
-		val = SHRT_MAX;
-	if (val < SHRT_MIN)
-		val = SHRT_MIN;
-	sm->diag.data[sm->diag.ptr++] = val;
-}
-
-/* --------------------------------------------------------------------- */
-
-static inline void diag_add_constellation(struct sm_state *sm, int vali, int valq)
-{
-	if ((sm->diag.mode != SM_DIAGMODE_CONSTELLATION) ||
-	    sm->diag.ptr >= DIAGDATALEN-1 || sm->diag.ptr < 0)
-		return;
-	/* clip */
-	if (vali > SHRT_MAX)
-		vali = SHRT_MAX;
-	if (vali < SHRT_MIN)
-		vali = SHRT_MIN;
-	if (valq > SHRT_MAX)
-		valq = SHRT_MAX;
-	if (valq < SHRT_MIN)
-		valq = SHRT_MIN;
-	sm->diag.data[sm->diag.ptr++] = vali;
-	sm->diag.data[sm->diag.ptr++] = valq;
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== utility functions ===============================
- */
-
-#if 0
-static inline unsigned int hweight32(unsigned int w)
-	__attribute__ ((unused));
-static inline unsigned int hweight16(unsigned short w)
-	__attribute__ ((unused));
-static inline unsigned int hweight8(unsigned char w)
-        __attribute__ ((unused));
-
-static inline unsigned int hweight32(unsigned int w)
-{
-        unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
-        res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
-        res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
-        res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
-        return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
-}
-
-static inline unsigned int hweight16(unsigned short w)
-{
-        unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
-        res = (res & 0x3333) + ((res >> 2) & 0x3333);
-        res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
-        return (res & 0x00FF) + ((res >> 8) & 0x00FF);
-}
-
-static inline unsigned int hweight8(unsigned char w)
-{
-        unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
-        res = (res & 0x33) + ((res >> 2) & 0x33);
-        return (res & 0x0F) + ((res >> 4) & 0x0F);
-}
-
-#endif
-
-static inline unsigned int gcd(unsigned int x, unsigned int y)
-	__attribute__ ((unused));
-static inline unsigned int lcm(unsigned int x, unsigned int y)
-	__attribute__ ((unused));
-
-static inline unsigned int gcd(unsigned int x, unsigned int y)
-{
-	for (;;) {
-		if (!x)
-			return y;
-		if (!y)
-			return x;
-		if (x > y)
-			x %= y;
-		else
-			y %= x;
-	}
-}
-
-static inline unsigned int lcm(unsigned int x, unsigned int y)
-{
-	return x * y / gcd(x, y);
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== profiling =======================================
- */
-
-
-#ifdef __i386__
-
-#include <asm/msr.h>
-
-/*
- * only do 32bit cycle counter arithmetic; we hope we won't overflow.
- * in fact, overflowing modems would require over 2THz CPU clock speeds :-)
- */
-
-#define time_exec(var,cmd)                                              \
-({                                                                      \
-	if (cpu_has_tsc) {                                              \
-		unsigned int cnt1, cnt2;                                \
-		rdtscl(cnt1);                                           \
-		cmd;                                                    \
-		rdtscl(cnt2);                                           \
-		var = cnt2-cnt1;                                        \
-	} else {                                                        \
-		cmd;                                                    \
-	}                                                               \
-})
-
-#else /* __i386__ */
-
-#define time_exec(var,cmd) cmd
-
-#endif /* __i386__ */
-
-/* --------------------------------------------------------------------- */
-
-extern const struct modem_tx_info sm_afsk1200_tx;
-extern const struct modem_tx_info sm_afsk2400_7_tx;
-extern const struct modem_tx_info sm_afsk2400_8_tx;
-extern const struct modem_tx_info sm_afsk2666_tx;
-extern const struct modem_tx_info sm_psk4800_tx;
-extern const struct modem_tx_info sm_hapn4800_8_tx;
-extern const struct modem_tx_info sm_hapn4800_10_tx;
-extern const struct modem_tx_info sm_hapn4800_pm8_tx;
-extern const struct modem_tx_info sm_hapn4800_pm10_tx;
-extern const struct modem_tx_info sm_fsk9600_4_tx;
-extern const struct modem_tx_info sm_fsk9600_5_tx;
-
-extern const struct modem_rx_info sm_afsk1200_rx;
-extern const struct modem_rx_info sm_afsk2400_7_rx;
-extern const struct modem_rx_info sm_afsk2400_8_rx;
-extern const struct modem_rx_info sm_afsk2666_rx;
-extern const struct modem_rx_info sm_psk4800_rx;
-extern const struct modem_rx_info sm_hapn4800_8_rx;
-extern const struct modem_rx_info sm_hapn4800_10_rx;
-extern const struct modem_rx_info sm_hapn4800_pm8_rx;
-extern const struct modem_rx_info sm_hapn4800_pm10_rx;
-extern const struct modem_rx_info sm_fsk9600_4_rx;
-extern const struct modem_rx_info sm_fsk9600_5_rx;
-
-extern const struct hardware_info sm_hw_sbc;
-extern const struct hardware_info sm_hw_sbcfdx;
-extern const struct hardware_info sm_hw_wss;
-extern const struct hardware_info sm_hw_wssfdx;
-
-extern const struct modem_tx_info *sm_modem_tx_table[];
-extern const struct modem_rx_info *sm_modem_rx_table[];
-extern const struct hardware_info *sm_hardware_table[];
-
-/* --------------------------------------------------------------------- */
-
-void sm_output_status(struct sm_state *sm);
-/*void sm_output_open(struct sm_state *sm);*/
-/*void sm_output_close(struct sm_state *sm);*/
-
-/* --------------------------------------------------------------------- */
-
-extern void inline sm_int_freq(struct sm_state *sm)
-{
-#ifdef SM_DEBUG
-	unsigned long cur_jiffies = jiffies;
-	/*
-	 * measure the interrupt frequency
-	 */
-	sm->debug_vals.cur_intcnt++;
-	if ((cur_jiffies - sm->debug_vals.last_jiffies) >= HZ) {
-		sm->debug_vals.last_jiffies = cur_jiffies;
-		sm->debug_vals.last_intcnt = sm->debug_vals.cur_intcnt;
-		sm->debug_vals.cur_intcnt = 0;
-	}
-#endif /* SM_DEBUG */
-}
-
-/* --------------------------------------------------------------------- */
-#endif /* _SM_H */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk1200.c b/drivers/net/hamradio/soundmodem/sm_afsk1200.c
--- a/drivers/net/hamradio/soundmodem/sm_afsk1200.c	Wed Nov 27 14:36:32 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,272 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm_afsk1200.c  -- soundcard radio modem driver, 1200 baud AFSK modem
- *
- *	Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#include "sm.h"
-#include "sm_tbl_afsk1200.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_afsk12 {
-	unsigned int shreg;
-	unsigned int bit_pll;
-	unsigned char last_sample;
-	unsigned int dcd_shreg;
-	int dcd_sum0, dcd_sum1, dcd_sum2;
-	unsigned int dcd_time;
-	unsigned char last_rxbit;
-};
-
-struct mod_state_afsk12 {
-	unsigned int shreg;
-	unsigned char tx_bit;
-	unsigned int bit_pll;
-	unsigned int dds_inc;
-	unsigned int txphase;
-};
-
-/* --------------------------------------------------------------------- */
-
-static const int dds_inc[2] = { 
-	AFSK12_TX_FREQ_LO*0x10000/AFSK12_SAMPLE_RATE,
-	AFSK12_TX_FREQ_HI*0x10000/AFSK12_SAMPLE_RATE 
-};
-
-static void modulator_1200_u8(struct sm_state *sm, unsigned char *buf, 
-			      unsigned int buflen)
-{
-	struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m);
-
-	for (; buflen > 0; buflen--) {
-		if (!((st->txphase++) & 7)) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
-			st->shreg >>= 1;
-		}
-		st->dds_inc = dds_inc[st->tx_bit & 1];
-		*buf++ = OFFSCOS(st->bit_pll);
-		st->bit_pll += st->dds_inc;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_1200_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m);
-
-	for (; buflen > 0; buflen--) {
-		if (!((st->txphase++) & 7)) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
-			st->shreg >>= 1;
-		}
-		st->dds_inc = dds_inc[st->tx_bit & 1];
-		*buf++ = COS(st->bit_pll);
-		st->bit_pll += st->dds_inc;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ int convolution8_u8(const unsigned char *st, const int *coeff, int csum)
-{
-	int sum = -0x80 * csum;
-	
-	sum += (st[0] * coeff[0]);
-	sum += (st[-1] * coeff[1]);
-	sum += (st[-2] * coeff[2]);
-	sum += (st[-3] * coeff[3]);
-	sum += (st[-4] * coeff[4]);
-	sum += (st[-5] * coeff[5]);
-	sum += (st[-6] * coeff[6]);
-	sum += (st[-7] * coeff[7]);
-
-	sum >>= 7;
-	return sum * sum;
-}
-
-static __inline__ int convolution8_s16(const short *st, const int *coeff, int csum)
-{
-	int sum = 0;
-	
-	sum += (st[0] * coeff[0]);
-	sum += (st[-1] * coeff[1]);
-	sum += (st[-2] * coeff[2]);
-	sum += (st[-3] * coeff[3]);
-	sum += (st[-4] * coeff[4]);
-	sum += (st[-5] * coeff[5]);
-	sum += (st[-6] * coeff[6]);
-	sum += (st[-7] * coeff[7]);
-
-	sum >>= 15;
-	return sum * sum;
-}
-
-static __inline__ int do_filter_1200_u8(const unsigned char *buf)
-{
-	int sum = convolution8_u8(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I);
-	sum += convolution8_u8(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q);
-	sum -= convolution8_u8(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I);
-	sum -= convolution8_u8(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q);
-	return sum;
-}
-
-static __inline__ int do_filter_1200_s16(const short *buf)
-{
-	int sum = convolution8_s16(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I);
-	sum += convolution8_s16(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q);
-	sum -= convolution8_s16(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I);
-	sum -= convolution8_s16(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q);
-	return sum;
-}
-
-/* --------------------------------------------------------------------- */
-
-static const int pll_corr[2] = { -0x1000, 0x1000 };
-
-static void demodulator_1200_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
-	int j;
-	int sum;
-	unsigned char newsample;
-
-	for (; buflen > 0; buflen--, buf++) {
-		sum = do_filter_1200_u8(buf);
-		st->dcd_shreg <<= 1;
-		st->bit_pll += 0x2000;
-		newsample = (sum > 0);
-		if (st->last_sample ^ newsample) {
-			st->last_sample = newsample;
-			st->dcd_shreg |= 1;
-			st->bit_pll += pll_corr
-				[st->bit_pll < 0x9000];
-			j = 4 * hweight8(st->dcd_shreg & 0x38)
-				- hweight16(st->dcd_shreg & 0x7c0);
-			st->dcd_sum0 += j;
-		}
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 120;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->shreg >>= 1;
-			st->shreg |= (!(st->last_rxbit ^
-					st->last_sample)) << 16;
-			st->last_rxbit = st->last_sample;
-			diag_trigger(sm);
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-		}
-		diag_add(sm, (((int)*buf)-0x80) << 8, sum);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_1200_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
-	int j;
-	int sum;
-	unsigned char newsample;
-
-	for (; buflen > 0; buflen--, buf++) {
-		sum = do_filter_1200_s16(buf);
-		st->dcd_shreg <<= 1;
-		st->bit_pll += 0x2000;
-		newsample = (sum > 0);
-		if (st->last_sample ^ newsample) {
-			st->last_sample = newsample;
-			st->dcd_shreg |= 1;
-			st->bit_pll += pll_corr
-				[st->bit_pll < 0x9000];
-			j = 4 * hweight8(st->dcd_shreg & 0x38)
-				- hweight16(st->dcd_shreg & 0x7c0);
-			st->dcd_sum0 += j;
-		}
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 120;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->shreg >>= 1;
-			st->shreg |= (!(st->last_rxbit ^
-					st->last_sample)) << 16;
-			st->last_rxbit = st->last_sample;
-			diag_trigger(sm);
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-		}
-		diag_add(sm, *buf, sum);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_1200(struct sm_state *sm)
-{
-	struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d);
-
-       	st->dcd_time = 120;
-	st->dcd_sum0 = 2;	
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_afsk1200_tx = {
-	"afsk1200", sizeof(struct mod_state_afsk12), 
-	AFSK12_SAMPLE_RATE, 1200, modulator_1200_u8, modulator_1200_s16, NULL
-};
-
-const struct modem_rx_info sm_afsk1200_rx = {
-	"afsk1200", sizeof(struct demod_state_afsk12), 
-	AFSK12_SAMPLE_RATE, 1200, 8, AFSK12_SAMPLE_RATE/1200, 
-	demodulator_1200_u8, demodulator_1200_s16, demod_init_1200
-};
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c b/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c
--- a/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c	Wed Nov 27 14:36:31 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,296 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm_afsk2400_7.c  -- soundcard radio modem driver, 2400 baud AFSK modem
- *
- *	Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-/*
- * This driver is intended to be compatible with TCM3105 modems
- * overclocked to 7.3728MHz. The mark and space frequencies therefore
- * lie at 3658 and 1996 Hz.
- * Note that I do _not_ recommend the building of such links, I provide
- * this only for the users who live in the coverage area of such
- * a "legacy" link.
- */
-
-#include "sm.h"
-#include "sm_tbl_afsk2400_7.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_afsk24 {
-	unsigned int shreg;
-	unsigned int bit_pll;
-	unsigned char last_sample;
-	unsigned int dcd_shreg;
-	int dcd_sum0, dcd_sum1, dcd_sum2;
-	unsigned int dcd_time;
-	unsigned char last_rxbit;
-};
-
-struct mod_state_afsk24 {
-	unsigned int shreg;
-	unsigned char tx_bit;
-	unsigned int bit_pll;
-	unsigned int tx_seq;
-	unsigned int phinc;
-};
-
-/* --------------------------------------------------------------------- */
-
-static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE,
-				AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE };
-
-static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (st->tx_seq < 0x5555) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
-			st->shreg >>= 1;
-			st->phinc = dds_inc[st->tx_bit & 1];
-		}
-		st->tx_seq += 0x5555;
-		st->tx_seq &= 0xffff;
-		*buf = OFFSCOS(st->bit_pll);
-		st->bit_pll += st->phinc;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (st->tx_seq < 0x5555) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
-			st->shreg >>= 1;
-			st->phinc = dds_inc[st->tx_bit & 1];
-		}
-		st->tx_seq += 0x5555;
-		st->tx_seq &= 0xffff;
-		*buf = COS(st->bit_pll);
-		st->bit_pll += st->phinc;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
-{
-	int sum = -0x80 * csum;
-	
-	sum += (st[0] * coeff[0]);
-	sum += (st[-1] * coeff[1]);
-	sum += (st[-2] * coeff[2]);
-	sum += (st[-3] * coeff[3]);
-	sum += (st[-4] * coeff[4]);
-	sum += (st[-5] * coeff[5]);
-	sum += (st[-6] * coeff[6]);
-	sum += (st[-7] * coeff[7]);
-	sum += (st[-8] * coeff[8]);
-	sum += (st[-9] * coeff[9]);
-	sum += (st[-10] * coeff[10]);
-	sum += (st[-11] * coeff[11]);
-	sum += (st[-12] * coeff[12]);
-	sum += (st[-13] * coeff[13]);
-
-	sum >>= 7;
-	return sum * sum;
-}
-
-static __inline__ int convolution14_s16(const short *st, const int *coeff, int csum)
-{
-	int sum = 0;
-	
-	sum += (st[0] * coeff[0]);
-	sum += (st[-1] * coeff[1]);
-	sum += (st[-2] * coeff[2]);
-	sum += (st[-3] * coeff[3]);
-	sum += (st[-4] * coeff[4]);
-	sum += (st[-5] * coeff[5]);
-	sum += (st[-6] * coeff[6]);
-	sum += (st[-7] * coeff[7]);
-	sum += (st[-8] * coeff[8]);
-	sum += (st[-9] * coeff[9]);
-	sum += (st[-10] * coeff[10]);
-	sum += (st[-11] * coeff[11]);
-	sum += (st[-12] * coeff[12]);
-	sum += (st[-13] * coeff[13]);
-
-	sum >>= 15;
-	return sum * sum;
-}
-
-static __inline__ int do_filter_2400_u8(const unsigned char *buf)
-{
-	int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
-	sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
-	sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
-	sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
-	return sum;
-}
-
-static __inline__ int do_filter_2400_s16(const short *buf)
-{
-	int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
-	sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
-	sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
-	sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
-	return sum;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
-	int j;
-	int sum;
-	unsigned char newsample;
-
-	for (; buflen > 0; buflen--, buf++) {
-		sum = do_filter_2400_u8(buf);
-		st->dcd_shreg <<= 1;
-		st->bit_pll += AFSK24_BITPLL_INC;
-		newsample = (sum > 0);
-		if (st->last_sample ^ newsample) {
-			st->last_sample = newsample;
-			st->dcd_shreg |= 1;
-			if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
-				st->bit_pll += AFSK24_BITPLL_INC/2;
-			else
-				st->bit_pll -= AFSK24_BITPLL_INC/2;
-			j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
-				- hweight16(st->dcd_shreg & 0x1e0);
-			st->dcd_sum0 += j;
-		}
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 120;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->shreg >>= 1;
-			st->shreg |= (!(st->last_rxbit ^
-					st->last_sample)) << 16;
-			st->last_rxbit = st->last_sample;
-			diag_trigger(sm);
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-		}
-		diag_add(sm, (((int)*buf)-0x80) << 8, sum);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
-	int j;
-	int sum;
-	unsigned char newsample;
-
-	for (; buflen > 0; buflen--, buf++) {
-		sum = do_filter_2400_s16(buf);
-		st->dcd_shreg <<= 1;
-		st->bit_pll += AFSK24_BITPLL_INC;
-		newsample = (sum > 0);
-		if (st->last_sample ^ newsample) {
-			st->last_sample = newsample;
-			st->dcd_shreg |= 1;
-			if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
-				st->bit_pll += AFSK24_BITPLL_INC/2;
-			else
-				st->bit_pll -= AFSK24_BITPLL_INC/2;
-			j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
-				- hweight16(st->dcd_shreg & 0x1e0);
-			st->dcd_sum0 += j;
-		}
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 120;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->shreg >>= 1;
-			st->shreg |= (!(st->last_rxbit ^
-					st->last_sample)) << 16;
-			st->last_rxbit = st->last_sample;
-			diag_trigger(sm);
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-		}
-		diag_add(sm, *buf, sum);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_2400(struct sm_state *sm)
-{
-	struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
-
-       	st->dcd_time = 120;
-	st->dcd_sum0 = 2;
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_afsk2400_7_tx = {
-	"afsk2400_7", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, 
-	modulator_2400_u8, modulator_2400_s16, NULL
-};
-
-const struct modem_rx_info sm_afsk2400_7_rx = {
-	"afsk2400_7", sizeof(struct demod_state_afsk24), 
-	AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, 
-	demodulator_2400_u8, demodulator_2400_s16, demod_init_2400
-};
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c b/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c
--- a/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c	Wed Nov 27 14:36:31 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,296 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm_afsk2400_8.c  -- soundcard radio modem driver, 2400 baud AFSK modem
- *
- *	Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-/*
- * This driver is intended to be compatible with TCM3105 modems
- * overclocked to 8MHz. The mark and space frequencies therefore
- * lie at 3970 and 2165 Hz.
- * Note that I do _not_ recommend the building of such links, I provide
- * this only for the users who live in the coverage area of such
- * a "legacy" link.
- */
-
-#include "sm.h"
-#include "sm_tbl_afsk2400_8.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_afsk24 {
-	unsigned int shreg;
-	unsigned int bit_pll;
-	unsigned char last_sample;
-	unsigned int dcd_shreg;
-	int dcd_sum0, dcd_sum1, dcd_sum2;
-	unsigned int dcd_time;
-	unsigned char last_rxbit;
-};
-
-struct mod_state_afsk24 {
-	unsigned int shreg;
-	unsigned char tx_bit;
-	unsigned int bit_pll;
-	unsigned int tx_seq;
-	unsigned int phinc;
-};
-
-/* --------------------------------------------------------------------- */
-
-static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE,
-				AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE };
-
-static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (st->tx_seq < 0x5555) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
-			st->shreg >>= 1;
-			st->phinc = dds_inc[st->tx_bit & 1];
-		}
-		st->tx_seq += 0x5555;
-		st->tx_seq &= 0xffff;
-		*buf = OFFSCOS(st->bit_pll);
-		st->bit_pll += st->phinc;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (st->tx_seq < 0x5555) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1;
-			st->shreg >>= 1;
-			st->phinc = dds_inc[st->tx_bit & 1];
-		}
-		st->tx_seq += 0x5555;
-		st->tx_seq &= 0xffff;
-		*buf = COS(st->bit_pll);
-		st->bit_pll += st->phinc;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
-{
-	int sum = -0x80 * csum;
-	
-	sum += (st[0] * coeff[0]);
-	sum += (st[-1] * coeff[1]);
-	sum += (st[-2] * coeff[2]);
-	sum += (st[-3] * coeff[3]);
-	sum += (st[-4] * coeff[4]);
-	sum += (st[-5] * coeff[5]);
-	sum += (st[-6] * coeff[6]);
-	sum += (st[-7] * coeff[7]);
-	sum += (st[-8] * coeff[8]);
-	sum += (st[-9] * coeff[9]);
-	sum += (st[-10] * coeff[10]);
-	sum += (st[-11] * coeff[11]);
-	sum += (st[-12] * coeff[12]);
-	sum += (st[-13] * coeff[13]);
-
-	sum >>= 7;
-	return sum * sum;
-}
-
-static __inline__ int convolution14_s16(const short *st, const int *coeff, int csum)
-{
-	int sum = 0;
-	
-	sum += (st[0] * coeff[0]);
-	sum += (st[-1] * coeff[1]);
-	sum += (st[-2] * coeff[2]);
-	sum += (st[-3] * coeff[3]);
-	sum += (st[-4] * coeff[4]);
-	sum += (st[-5] * coeff[5]);
-	sum += (st[-6] * coeff[6]);
-	sum += (st[-7] * coeff[7]);
-	sum += (st[-8] * coeff[8]);
-	sum += (st[-9] * coeff[9]);
-	sum += (st[-10] * coeff[10]);
-	sum += (st[-11] * coeff[11]);
-	sum += (st[-12] * coeff[12]);
-	sum += (st[-13] * coeff[13]);
-
-	sum >>= 15;
-	return sum * sum;
-}
-
-static __inline__ int do_filter_2400_u8(const unsigned char *buf)
-{
-	int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
-	sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
-	sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
-	sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
-	return sum;
-}
-
-static __inline__ int do_filter_2400_s16(const short *buf)
-{
-	int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
-	sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
-	sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I);
-	sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q);
-	return sum;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
-	int j;
-	int sum;
-	unsigned char newsample;
-
-	for (; buflen > 0; buflen--, buf++) {
-		sum = do_filter_2400_u8(buf);
-		st->dcd_shreg <<= 1;
-		st->bit_pll += AFSK24_BITPLL_INC;
-		newsample = (sum > 0);
-		if (st->last_sample ^ newsample) {
-			st->last_sample = newsample;
-			st->dcd_shreg |= 1;
-			if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
-				st->bit_pll += AFSK24_BITPLL_INC/2;
-			else
-				st->bit_pll -= AFSK24_BITPLL_INC/2;
-			j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
-				- hweight16(st->dcd_shreg & 0x1e0);
-			st->dcd_sum0 += j;
-		}
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 120;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->shreg >>= 1;
-			st->shreg |= (!(st->last_rxbit ^
-					st->last_sample)) << 16;
-			st->last_rxbit = st->last_sample;
-			diag_trigger(sm);
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-		}
-		diag_add(sm, (((int)*buf)-0x80) << 8, sum);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
-	int j;
-	int sum;
-	unsigned char newsample;
-
-	for (; buflen > 0; buflen--, buf++) {
-		sum = do_filter_2400_s16(buf);
-		st->dcd_shreg <<= 1;
-		st->bit_pll += AFSK24_BITPLL_INC;
-		newsample = (sum > 0);
-		if (st->last_sample ^ newsample) {
-			st->last_sample = newsample;
-			st->dcd_shreg |= 1;
-			if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2))
-				st->bit_pll += AFSK24_BITPLL_INC/2;
-			else
-				st->bit_pll -= AFSK24_BITPLL_INC/2;
-			j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c)
-				- hweight16(st->dcd_shreg & 0x1e0);
-			st->dcd_sum0 += j;
-		}
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 120;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->shreg >>= 1;
-			st->shreg |= (!(st->last_rxbit ^
-					st->last_sample)) << 16;
-			st->last_rxbit = st->last_sample;
-			diag_trigger(sm);
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-		}
-		diag_add(sm, *buf, sum);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_2400(struct sm_state *sm)
-{
-	struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d);
-
-       	st->dcd_time = 120;
-	st->dcd_sum0 = 2;
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_afsk2400_8_tx = {
-	"afsk2400_8", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, 
-	modulator_2400_u8, modulator_2400_s16, NULL
-};
-
-const struct modem_rx_info sm_afsk2400_8_rx = {
-	"afsk2400_8", sizeof(struct demod_state_afsk24), 
-	AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, 
-	demodulator_2400_u8, demodulator_2400_s16, demod_init_2400
-};
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2666.c b/drivers/net/hamradio/soundmodem/sm_afsk2666.c
--- a/drivers/net/hamradio/soundmodem/sm_afsk2666.c	Wed Nov 27 14:36:31 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,356 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm_afsk2666.c  -- soundcard radio modem driver, 2666 baud AFSK modem
- *
- *	Copyright (C) 1997  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#include "sm.h"
-#include "sm_tbl_afsk2666.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_afsk26 {
-	unsigned int shreg;
-	unsigned long descram;
-	int dem_sum[8];
-	int dem_sum_mean;
-	int dem_cnt;
-	unsigned int bit_pll;
-	unsigned char last_sample;
-	unsigned int dcd_shreg;
-	int dcd_sum0, dcd_sum1, dcd_sum2;
-	unsigned int dcd_time;
-};
-
-struct mod_state_afsk26 {
-	unsigned int shreg;
-	unsigned long scram;
-	unsigned int bit_pll;
-	unsigned int phinc;
-	unsigned int tx_seq;
-};
-
-/* --------------------------------------------------------------------- */
-
-#define DESCRAM_TAP1 0x20000
-#define DESCRAM_TAP2 0x01000
-#define DESCRAM_TAP3 0x00001
-
-#define DESCRAM_TAPSH1 17
-#define DESCRAM_TAPSH2 12
-#define DESCRAM_TAPSH3 0
-
-#define SCRAM_TAP1 0x20000 /* X^17 */
-#define SCRAM_TAPN 0x00021 /* X^0+X^5 */
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_2666_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_afsk26 *st = (struct mod_state_afsk26 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->scram = ((st->scram << 1) | (st->scram & 1));
-			st->scram ^= (!(st->shreg & 1));
-			st->shreg >>= 1;
-			if (st->scram & (SCRAM_TAP1 << 1))
-				st->scram ^= SCRAM_TAPN << 1;
-			st->phinc = afsk26_carfreq[!(st->scram & (SCRAM_TAP1 << 2))];
-		}
-		if (st->tx_seq >= 6)
-			st->tx_seq = 0;
-		*buf = OFFSCOS(st->bit_pll);
-		st->bit_pll += st->phinc;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_2666_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_afsk26 *st = (struct mod_state_afsk26 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->scram = ((st->scram << 1) | (st->scram & 1));
-			st->scram ^= (!(st->shreg & 1));
-			st->shreg >>= 1;
-			if (st->scram & (SCRAM_TAP1 << 1))
-				st->scram ^= SCRAM_TAPN << 1;
-			st->phinc = afsk26_carfreq[!(st->scram & (SCRAM_TAP1 << 2))];
-		}
-		if (st->tx_seq >= 6)
-			st->tx_seq = 0;
-		*buf = COS(st->bit_pll);
-		st->bit_pll += st->phinc;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ int convolution12_u8(const unsigned char *st, const int *coeff, int csum)
-{
-	int sum = -0x80 * csum;
-	
-	sum += (st[0] * coeff[0]);
-	sum += (st[-1] * coeff[1]);
-	sum += (st[-2] * coeff[2]);
-	sum += (st[-3] * coeff[3]);
-	sum += (st[-4] * coeff[4]);
-	sum += (st[-5] * coeff[5]);
-	sum += (st[-6] * coeff[6]);
-	sum += (st[-7] * coeff[7]);
-	sum += (st[-8] * coeff[8]);
-	sum += (st[-9] * coeff[9]);
-	sum += (st[-10] * coeff[10]);
-	sum += (st[-11] * coeff[11]);
-
-	return sum;
-}
-
-static __inline__ int convolution12_s16(const short *st, const int *coeff, int csum)
-{
-	int sum = 0;
-	
-	sum += (st[0] * coeff[0]);
-	sum += (st[-1] * coeff[1]);
-	sum += (st[-2] * coeff[2]);
-	sum += (st[-3] * coeff[3]);
-	sum += (st[-4] * coeff[4]);
-	sum += (st[-5] * coeff[5]);
-	sum += (st[-6] * coeff[6]);
-	sum += (st[-7] * coeff[7]);
-	sum += (st[-8] * coeff[8]);
-	sum += (st[-9] * coeff[9]);
-	sum += (st[-10] * coeff[10]);
-	sum += (st[-11] * coeff[11]);
-
-	sum >>= 8;
-	return sum;
-}
-
-/* ---------------------------------------------------------------------- */
-
-#if 0
-static int binexp(unsigned int i)
-{
-	int ret = 31;
-	
-	if (!i)
-		return 0;
-	if (i < 0x10000LU) {
-		i <<= 16;
-		ret -= 16;
-	}
-	if (i < 0x1000000LU) {
-		i <<= 8;
-		ret -= 8;
-	}
-	if (i < 0x10000000LU) {
-		i <<= 4;
-		ret -= 4;
-	}
-	if (i < 0x40000000LU) {
-		i <<= 2;
-		ret -= 2;
-	}
-	if (i < 0x80000000LU)
-		ret -= 1;
-	return ret;
-}
-
-static const sqrt_tab[16] = {
-	00000, 16384, 23170, 28378, 32768, 36636, 40132, 43348,
-	46341, 49152, 51811, 54340, 56756, 59073, 61303, 63455
-};
-
-
-static unsigned int int_sqrt_approx(unsigned int i)
-{
-	unsigned int j;
-
-	if (i < 16)
-		return sqrt_tab[i] >> 14;
-	j = binexp(i) >> 1;
-	i >>= (j * 2 - 2);
-      	return (sqrt_tab[i & 0xf] << j) >> 15;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-extern unsigned int est_pwr(int i, int q)
-{
-	unsigned int ui = abs(i);
-	unsigned int uq = abs(q);
-
-	if (uq > ui) {
-		unsigned int tmp;
-		tmp = ui;
-		ui = uq;
-		uq = tmp;
-	}
-	if (uq > (ui >> 1))
-		return 7*(ui>>3) + 9*(uq>>4);
-	else
-		return ui + (uq>>2);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_one_sample(struct sm_state *sm, struct demod_state_afsk26 *st, int curval,
-			     int loi, int loq, int hii, int hiq)
-{
-	static const int pll_corr[2] = { -0xa00, 0xa00 };
-	unsigned char curbit;
-	unsigned int descx;
-	int val;
-
-	/* 
-	 * estimate power
-	 */
-	val = est_pwr(hii, hiq) - est_pwr(loi, loq);
-	/*
-	 * estimate center value
-	 */
-	st->dem_sum[0] += val >> 8;
-	if ((++st->dem_cnt) >= 256) {
-		st->dem_cnt = 0;
-		st->dem_sum_mean = (st->dem_sum[0]+st->dem_sum[1]+
-				    st->dem_sum[2]+st->dem_sum[3]+
-				    st->dem_sum[4]+st->dem_sum[5]+
-				    st->dem_sum[6]+st->dem_sum[7]) >> 3;
-		memmove(st->dem_sum+1, st->dem_sum, 
-			sizeof(st->dem_sum)-sizeof(st->dem_sum[0]));
-		st->dem_sum[0] = 0;
-	}
-	/*
-	 * decision and bit clock regen
-	 */
-	val -= st->dem_sum_mean;
-	diag_add(sm, curval, val);
-	
-	st->dcd_shreg <<= 1;
-	st->bit_pll += 0x1555;
-	curbit = (val > 0);
-	if (st->last_sample ^ curbit) {
-		st->dcd_shreg |= 1;
-		st->bit_pll += pll_corr[st->bit_pll < (0x8000+0x1555)];
-		st->dcd_sum0 += 4*hweight8(st->dcd_shreg & 0x1e) -
-			hweight16(st->dcd_shreg & 0xfe00);
-	}
-	st->last_sample = curbit;
-	hdlcdrv_channelbit(&sm->hdrv, curbit);
-	if ((--st->dcd_time) <= 0) {
-		hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + st->dcd_sum1 + 
-					   st->dcd_sum2) < 0);
-		st->dcd_sum2 = st->dcd_sum1;
-		st->dcd_sum1 = st->dcd_sum0;
-		st->dcd_sum0 = 2; /* slight bias */
-		st->dcd_time = 400;
-	}
-	if (st->bit_pll >= 0x10000) {
-		st->bit_pll &= 0xffffu;
-		st->descram = (st->descram << 1) | curbit;
-		descx = st->descram ^ (st->descram >> 1);
-		descx ^= ((descx >> DESCRAM_TAPSH1) ^
-			  (descx >> DESCRAM_TAPSH2));
-		st->shreg >>= 1;
-		st->shreg |= (!(descx & 1)) << 16;
-		if (st->shreg & 1) {
-			hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-			st->shreg = 0x10000;
-		}
-		diag_trigger(sm);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2666_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d);
-
-	for (; buflen > 0; buflen--, buf++) {
-		demod_one_sample(sm, st, (*buf-0x80)<<8,
-				 convolution12_u8(buf, afsk26_dem_tables[0][0].i, AFSK26_DEM_SUM_I_0_0),
-				 convolution12_u8(buf, afsk26_dem_tables[0][0].q, AFSK26_DEM_SUM_Q_0_0),
-				 convolution12_u8(buf, afsk26_dem_tables[0][1].i, AFSK26_DEM_SUM_I_0_1),
-				 convolution12_u8(buf, afsk26_dem_tables[0][1].q, AFSK26_DEM_SUM_Q_0_1));
-		demod_one_sample(sm, st,  (*buf-0x80)<<8,
-				 convolution12_u8(buf, afsk26_dem_tables[1][0].i, AFSK26_DEM_SUM_I_1_0),
-				 convolution12_u8(buf, afsk26_dem_tables[1][0].q, AFSK26_DEM_SUM_Q_1_0),
-				 convolution12_u8(buf, afsk26_dem_tables[1][1].i, AFSK26_DEM_SUM_I_1_1),
-				 convolution12_u8(buf, afsk26_dem_tables[1][1].q, AFSK26_DEM_SUM_Q_1_1));
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_2666_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d);
-
-	for (; buflen > 0; buflen--, buf++) {
-		demod_one_sample(sm, st, *buf,
-				 convolution12_s16(buf, afsk26_dem_tables[0][0].i, AFSK26_DEM_SUM_I_0_0),
-				 convolution12_s16(buf, afsk26_dem_tables[0][0].q, AFSK26_DEM_SUM_Q_0_0),
-				 convolution12_s16(buf, afsk26_dem_tables[0][1].i, AFSK26_DEM_SUM_I_0_1),
-				 convolution12_s16(buf, afsk26_dem_tables[0][1].q, AFSK26_DEM_SUM_Q_0_1));
-		demod_one_sample(sm, st, *buf, 
-				 convolution12_s16(buf, afsk26_dem_tables[1][0].i, AFSK26_DEM_SUM_I_1_0),
-				 convolution12_s16(buf, afsk26_dem_tables[1][0].q, AFSK26_DEM_SUM_Q_1_0),
-				 convolution12_s16(buf, afsk26_dem_tables[1][1].i, AFSK26_DEM_SUM_I_1_1),
-				 convolution12_s16(buf, afsk26_dem_tables[1][1].q, AFSK26_DEM_SUM_Q_1_1));
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_2666(struct sm_state *sm)
-{
-	struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d);
-
-	st->dcd_time = 400;
-	st->dcd_sum0 = 2;	
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_afsk2666_tx = {
-	"afsk2666", sizeof(struct mod_state_afsk26), AFSK26_SAMPLERATE, 2666, 
-	modulator_2666_u8, modulator_2666_s16, NULL
-};
-
-const struct modem_rx_info sm_afsk2666_rx = {
-	"afsk2666", sizeof(struct demod_state_afsk26), AFSK26_SAMPLERATE, 2666, 12, 6, 
-	demodulator_2666_u8, demodulator_2666_s16, demod_init_2666
-};
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_fsk9600.c b/drivers/net/hamradio/soundmodem/sm_fsk9600.c
--- a/drivers/net/hamradio/soundmodem/sm_fsk9600.c	Wed Nov 27 14:36:31 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,391 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm_fsk9600.c  --  soundcard radio modem driver, 
- *                        9600 baud G3RUH compatible FSK modem
- *
- *	Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#include "sm.h"
-#include "sm_tbl_fsk9600.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_fsk96 {
-	unsigned int shreg;
-	unsigned long descram;
-	unsigned int bit_pll;
-	unsigned char last_sample;
-	unsigned int dcd_shreg;
-	int dcd_sum0, dcd_sum1, dcd_sum2;
-	unsigned int dcd_time;
-};
-
-struct mod_state_fsk96 {
-	unsigned int shreg;
-	unsigned long scram;
-	unsigned char tx_bit;
-	unsigned char *txtbl;
-	unsigned int txphase;
-};
-
-/* --------------------------------------------------------------------- */
-
-#define DESCRAM_TAP1 0x20000
-#define DESCRAM_TAP2 0x01000
-#define DESCRAM_TAP3 0x00001
-
-#define DESCRAM_TAPSH1 17
-#define DESCRAM_TAPSH2 12
-#define DESCRAM_TAPSH3 0
-
-#define SCRAM_TAP1 0x20000 /* X^17 */
-#define SCRAM_TAPN 0x00021 /* X^0+X^5 */
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_9600_4_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m);
-
-	for (; buflen > 0; buflen--) {
-		if (!st->txphase++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->scram = (st->scram << 1) | (st->scram & 1);
-			st->scram ^= !(st->shreg & 1);
-			st->shreg >>= 1;
-			if (st->scram & (SCRAM_TAP1 << 1))
-				st->scram ^= SCRAM_TAPN << 1;
-			st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2)));
-			st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff);
-		}
-		if (st->txphase >= 4)
-			st->txphase = 0;
-		*buf++ = *st->txtbl;
-		st->txtbl += 0x100;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_9600_4_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m);
-
-	for (; buflen > 0; buflen--) {
-		if (!st->txphase++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->scram = (st->scram << 1) | (st->scram & 1);
-			st->scram ^= !(st->shreg & 1);
-			st->shreg >>= 1;
-			if (st->scram & (SCRAM_TAP1 << 1))
-				st->scram ^= SCRAM_TAPN << 1;
-			st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2)));
-			st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff);
-		}
-		if (st->txphase >= 4)
-			st->txphase = 0;
-		*buf++ = ((*st->txtbl)-0x80) << 8;
-		st->txtbl += 0x100;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_9600_4_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
-	static const int pll_corr[2] = { -0x1000, 0x1000 };
-	unsigned char curbit;
-	unsigned int descx;
-
-	for (; buflen > 0; buflen--, buf++) {
-		st->dcd_shreg <<= 1;
-		st->bit_pll += 0x4000;
-		curbit = (*buf >= 0x80);
-		if (st->last_sample ^ curbit) {
-			st->dcd_shreg |= 1;
-			st->bit_pll += pll_corr[st->bit_pll < 0xa000];
-			st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) - 
-				!!(st->dcd_shreg & 0x10);
-		}
-		st->last_sample = curbit;
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 240;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->descram = (st->descram << 1) | curbit;
-			descx = st->descram ^ (st->descram >> 1);
-			descx ^= ((descx >> DESCRAM_TAPSH1) ^
-				  (descx >> DESCRAM_TAPSH2));
-			st->shreg >>= 1;
-			st->shreg |= (!(descx & 1)) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-		}
-		diag_add_one(sm, ((short)(*buf - 0x80)) << 8);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_9600_4_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
-	static const int pll_corr[2] = { -0x1000, 0x1000 };
-	unsigned char curbit;
-	unsigned int descx;
-
-	for (; buflen > 0; buflen--, buf++) {
-		st->dcd_shreg <<= 1;
-		st->bit_pll += 0x4000;
-		curbit = (*buf >= 0);
-		if (st->last_sample ^ curbit) {
-			st->dcd_shreg |= 1;
-			st->bit_pll += pll_corr[st->bit_pll < 0xa000];
-			st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) - 
-				!!(st->dcd_shreg & 0x10);
-		}
-		st->last_sample = curbit;
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 240;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->descram = (st->descram << 1) | curbit;
-			descx = st->descram ^ (st->descram >> 1);
-			descx ^= ((descx >> DESCRAM_TAPSH1) ^
-				  (descx >> DESCRAM_TAPSH2));
-			st->shreg >>= 1;
-			st->shreg |= (!(descx & 1)) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-		}
-		diag_add_one(sm, *buf);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_9600_5_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m);
-
-	for (; buflen > 0; buflen--) {
-		if (!st->txphase++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->scram = (st->scram << 1) | (st->scram & 1);
-			st->scram ^= !(st->shreg & 1);
-			st->shreg >>= 1;
-			if (st->scram & (SCRAM_TAP1 << 1))
-				st->scram ^= SCRAM_TAPN << 1;
-			st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2)));
-			st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff);
-		}
-		if (st->txphase >= 5)
-			st->txphase = 0;
-		*buf++ = *st->txtbl;
-		st->txtbl += 0x100;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_9600_5_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m);
-
-	for (; buflen > 0; buflen--) {
-		if (!st->txphase++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->scram = (st->scram << 1) | (st->scram & 1);
-			st->scram ^= !(st->shreg & 1);
-			st->shreg >>= 1;
-			if (st->scram & (SCRAM_TAP1 << 1))
-				st->scram ^= SCRAM_TAPN << 1;
-			st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2)));
-			st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff);
-		}
-		if (st->txphase >= 5)
-			st->txphase = 0;
-		*buf++ = ((*st->txtbl)-0x80)<<8;
-		st->txtbl += 0x100;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_9600_5_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
-	static const int pll_corr[2] = { -0x1000, 0x1000 };
-	unsigned char curbit;
-	unsigned int descx;
-
-	for (; buflen > 0; buflen--, buf++) {
-		st->dcd_shreg <<= 1;
-		st->bit_pll += 0x3333;
-		curbit = (*buf >= 0x80);
-		if (st->last_sample ^ curbit) {
-			st->dcd_shreg |= 1;
-			st->bit_pll += pll_corr[st->bit_pll < 0x9999];
-			st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) - 
-				hweight8(st->dcd_shreg & 0x70);
-		}
-		st->last_sample = curbit;
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 240;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->descram = (st->descram << 1) | curbit;
-			descx = st->descram ^ (st->descram >> 1);
-			descx ^= ((descx >> DESCRAM_TAPSH1) ^
-				  (descx >> DESCRAM_TAPSH2));
-			st->shreg >>= 1;
-			st->shreg |= (!(descx & 1)) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-		}
-		diag_add_one(sm, ((short)(*buf - 0x80)) << 8);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_9600_5_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
-	static const int pll_corr[2] = { -0x1000, 0x1000 };
-	unsigned char curbit;
-	unsigned int descx;
-
-	for (; buflen > 0; buflen--, buf++) {
-		st->dcd_shreg <<= 1;
-		st->bit_pll += 0x3333;
-		curbit = (*buf >= 0);
-		if (st->last_sample ^ curbit) {
-			st->dcd_shreg |= 1;
-			st->bit_pll += pll_corr[st->bit_pll < 0x9999];
-			st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) - 
-				hweight8(st->dcd_shreg & 0x70);
-		}
-		st->last_sample = curbit;
-		hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 240;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->descram = (st->descram << 1) | curbit;
-			descx = st->descram ^ (st->descram >> 1);
-			descx ^= ((descx >> DESCRAM_TAPSH1) ^
-				  (descx >> DESCRAM_TAPSH2));
-			st->shreg >>= 1;
-			st->shreg |= (!(descx & 1)) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-		}
-		diag_add_one(sm, *buf);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_9600(struct sm_state *sm)
-{
-	struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d);
-
-	st->dcd_time = 240;
-	st->dcd_sum0 = 2;	
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_fsk9600_4_tx = {
-	"fsk9600", sizeof(struct mod_state_fsk96), 38400, 9600,
-	modulator_9600_4_u8, modulator_9600_4_s16, NULL
-};
-
-const struct modem_rx_info sm_fsk9600_4_rx = {
-	"fsk9600", sizeof(struct demod_state_fsk96), 38400, 9600, 1, 4,
-	demodulator_9600_4_u8, demodulator_9600_4_s16, demod_init_9600
-};
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_fsk9600_5_tx = {
-	"fsk9600", sizeof(struct mod_state_fsk96), 48000, 9600,
-	modulator_9600_5_u8, modulator_9600_5_s16, NULL
-};
-
-const struct modem_rx_info sm_fsk9600_5_rx = {
-	"fsk9600", sizeof(struct demod_state_fsk96), 48000, 9600, 1, 5, 
-	demodulator_9600_5_u8, demodulator_9600_5_s16, demod_init_9600
-};
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_hapn4800.c b/drivers/net/hamradio/soundmodem/sm_hapn4800.c
--- a/drivers/net/hamradio/soundmodem/sm_hapn4800.c	Wed Nov 27 14:36:28 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,560 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm_hapn4800.c  -- soundcard radio modem driver, 4800 baud HAPN modem
- *
- *	Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- *
- *  This module implements a (hopefully) HAPN (Hamilton Area Packet
- *  Network) compatible 4800 baud modem.
- *  The HAPN modem uses kind of "duobinary signalling" (not really,
- *  duobinary signalling gives ... 0 0 -1 0 1 0 0 ... at the sampling
- *  instants, whereas HAPN signalling gives ... 0 0 -1 1 0 0 ..., see
- *  Proakis, Digital Communications).
- *  The code is untested. It is compatible with itself (i.e. it can decode
- *  the packets it sent), but I could not test if it is compatible with
- *  any "real" HAPN modem, since noone uses it in my region of the world.
- *  Feedback therefore welcome.
- */
-
-#include "sm.h"
-#include "sm_tbl_hapn4800.h"
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_hapn48 {
-	unsigned int shreg;
-	unsigned int bit_pll;
-	unsigned char last_bit;
-	unsigned char last_bit2;
-	unsigned int dcd_shreg;
-	int dcd_sum0, dcd_sum1, dcd_sum2;
-	unsigned int dcd_time;
-	int lvlhi, lvllo;
-};
-
-struct mod_state_hapn48 {
-	unsigned int shreg;
-	unsigned char tx_bit;
-	unsigned int tx_seq;
-	const unsigned char *tbl;
-};
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) { 
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = ((st->tx_bit << 1) |
-				      (st->tx_bit & 1));
-			st->tx_bit ^= (!(st->shreg & 1));
-			st->shreg >>= 1;
-			st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf);
-		}
-		if (st->tx_seq >= 10)
-			st->tx_seq = 0;
-		*buf = *st->tbl;
-		st->tbl += 0x10;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_10_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) { 
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = ((st->tx_bit << 1) |
-				      (st->tx_bit & 1));
-			st->tx_bit ^= (!(st->shreg & 1));
-			st->shreg >>= 1;
-			st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf);
-		}
-		if (st->tx_seq >= 10)
-			st->tx_seq = 0;
-		*buf = ((*st->tbl)-0x80)<<8;
-		st->tbl += 0x10;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1);
-			st->tx_bit ^= !(st->shreg & 1);
-			st->shreg >>= 1;
-			st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf);
-		}
-		if (st->tx_seq >= 8)
-			st->tx_seq = 0;
-		*buf = *st->tbl;
-		st->tbl += 0x10;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_8_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1);
-			st->tx_bit ^= !(st->shreg & 1);
-			st->shreg >>= 1;
-			st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf);
-		}
-		if (st->tx_seq >= 8)
-			st->tx_seq = 0;
-		*buf = ((*st->tbl)-0x80)<<8;
-		st->tbl += 0x10;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_pm10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) { 
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = ((st->tx_bit << 1) |
-				      (st->tx_bit & 1));
-			st->tx_bit ^= (!(st->shreg & 1));
-			st->shreg >>= 1;
-			st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf);
-		}
-		if (st->tx_seq >= 10)
-			st->tx_seq = 0;
-		*buf = *st->tbl;
-		st->tbl += 0x10;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_pm10_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) { 
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = ((st->tx_bit << 1) |
-				      (st->tx_bit & 1));
-			st->tx_bit ^= (!(st->shreg & 1));
-			st->shreg >>= 1;
-			st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf);
-		}
-		if (st->tx_seq >= 10)
-			st->tx_seq = 0;
-		*buf = ((*st->tbl)-0x80)<<8;
-		st->tbl += 0x10;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_pm8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1);
-			st->tx_bit ^= !(st->shreg & 1);
-			st->shreg >>= 1;
-			st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf);
-		}
-		if (st->tx_seq >= 8)
-			st->tx_seq = 0;
-		*buf = *st->tbl;
-		st->tbl += 0x10;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_hapn4800_pm8_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m);
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->tx_seq++) {
-			if (st->shreg <= 1)
-				st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-			st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1);
-			st->tx_bit ^= !(st->shreg & 1);
-			st->shreg >>= 1;
-			st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf);
-		}
-		if (st->tx_seq >= 8)
-			st->tx_seq = 0;
-		*buf = ((*st->tbl)-0x80)<<8;
-		st->tbl += 0x10;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_hapn4800_10_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
-	static const int pll_corr[2] = { -0x800, 0x800 };
-	int curst, cursync;
-	int inv;
-
-	for (; buflen > 0; buflen--, buf++) {
-		inv = ((int)(buf[-2])-0x80) << 8;
-		st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */
-		st->lvllo = (st->lvllo * 65309) >> 16; /* decay */
-		if (inv > st->lvlhi)
-			st->lvlhi = inv;
-		if (inv < st->lvllo)
-			st->lvllo = inv;
-		if (buflen & 1)
-			st->dcd_shreg <<= 1;
-		st->bit_pll += 0x199a;
-		curst = cursync = 0;
-		if (inv > st->lvlhi >> 1) {
-			curst = 1;
-			cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] &&
-				   buf[-2] > buf[-0] && buf[-2] > buf[-4]);
-		} else if (inv < st->lvllo >> 1) {
-			curst = -1;
-			cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] &&
-				   buf[-2] < buf[-0] && buf[-2] < buf[-4]);
-		}
-		if (cursync) {
-			st->dcd_shreg |= cursync;
-			st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu];
-			st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) - 
-				hweight32(st->dcd_shreg & 0xe739ce70);
-		}
-		hdlcdrv_channelbit(&sm->hdrv, cursync);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 240;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->last_bit2 = st->last_bit;
-			if (curst < 0)
-				st->last_bit = 0;
-			else if (curst > 0)
-				st->last_bit = 1;
-			st->shreg >>= 1;
-			st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-		}
-		diag_add_one(sm, inv);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_hapn4800_10_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
-	static const int pll_corr[2] = { -0x800, 0x800 };
-	int curst, cursync;
-	int inv;
-
-	for (; buflen > 0; buflen--, buf++) {
-		inv = buf[-2];
-		st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */
-		st->lvllo = (st->lvllo * 65309) >> 16; /* decay */
-		if (inv > st->lvlhi)
-			st->lvlhi = inv;
-		if (inv < st->lvllo)
-			st->lvllo = inv;
-		if (buflen & 1)
-			st->dcd_shreg <<= 1;
-		st->bit_pll += 0x199a;
-		curst = cursync = 0;
-		if (inv > st->lvlhi >> 1) {
-			curst = 1;
-			cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] &&
-				   buf[-2] > buf[-0] && buf[-2] > buf[-4]);
-		} else if (inv < st->lvllo >> 1) {
-			curst = -1;
-			cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] &&
-				   buf[-2] < buf[-0] && buf[-2] < buf[-4]);
-		}
-		if (cursync) {
-			st->dcd_shreg |= cursync;
-			st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu];
-			st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) - 
-				hweight32(st->dcd_shreg & 0xe739ce70);
-		}
-		hdlcdrv_channelbit(&sm->hdrv, cursync);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 240;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->last_bit2 = st->last_bit;
-			if (curst < 0)
-				st->last_bit = 0;
-			else if (curst > 0)
-				st->last_bit = 1;
-			st->shreg >>= 1;
-			st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-		}
-		diag_add_one(sm, inv);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_hapn4800_8_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
-	static const int pll_corr[2] = { -0x800, 0x800 };
-	int curst, cursync;
-	int inv;
-
-	for (; buflen > 0; buflen--, buf++) {
-		inv = ((int)(buf[-2])-0x80) << 8;
-		st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */
-		st->lvllo = (st->lvllo * 65309) >> 16; /* decay */
-		if (inv > st->lvlhi)
-			st->lvlhi = inv;
-		if (inv < st->lvllo)
-			st->lvllo = inv;
-		if (buflen & 1)
-			st->dcd_shreg <<= 1;
-		st->bit_pll += 0x2000;
-		curst = cursync = 0;
-		if (inv > st->lvlhi >> 1) {
-			curst = 1;
-			cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] &&
-				   buf[-2] > buf[-0] && buf[-2] > buf[-4]);
-		} else if (inv < st->lvllo >> 1) {
-			curst = -1;
-			cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] &&
-				   buf[-2] < buf[-0] && buf[-2] < buf[-4]);
-		}
-		if (cursync) {
-			st->dcd_shreg |= cursync;
-			st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u];
-			st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) - 
-				hweight32(st->dcd_shreg & 0xbbbbbbbb);
-		}
-		hdlcdrv_channelbit(&sm->hdrv, cursync);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 240;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->last_bit2 = st->last_bit;
-			if (curst < 0)
-				st->last_bit = 0;
-			else if (curst > 0)
-				st->last_bit = 1;
-			st->shreg >>= 1;
-			st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-		}
-		diag_add_one(sm, inv);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_hapn4800_8_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
-	static const int pll_corr[2] = { -0x800, 0x800 };
-	int curst, cursync;
-	int inv;
-
-	for (; buflen > 0; buflen--, buf++) {
-		inv = buf[-2];
-		st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */
-		st->lvllo = (st->lvllo * 65309) >> 16; /* decay */
-		if (inv > st->lvlhi)
-			st->lvlhi = inv;
-		if (inv < st->lvllo)
-			st->lvllo = inv;
-		if (buflen & 1)
-			st->dcd_shreg <<= 1;
-		st->bit_pll += 0x2000;
-		curst = cursync = 0;
-		if (inv > st->lvlhi >> 1) {
-			curst = 1;
-			cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] &&
-				   buf[-2] > buf[-0] && buf[-2] > buf[-4]);
-		} else if (inv < st->lvllo >> 1) {
-			curst = -1;
-			cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] &&
-				   buf[-2] < buf[-0] && buf[-2] < buf[-4]);
-		}
-		if (cursync) {
-			st->dcd_shreg |= cursync;
-			st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u];
-			st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) - 
-				hweight32(st->dcd_shreg & 0xbbbbbbbb);
-		}
-		hdlcdrv_channelbit(&sm->hdrv, cursync);
-		if ((--st->dcd_time) <= 0) {
-			hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-						   st->dcd_sum1 + 
-						   st->dcd_sum2) < 0);
-			st->dcd_sum2 = st->dcd_sum1;
-			st->dcd_sum1 = st->dcd_sum0;
-			st->dcd_sum0 = 2; /* slight bias */
-			st->dcd_time = 240;
-		}
-		if (st->bit_pll >= 0x10000) {
-			st->bit_pll &= 0xffff;
-			st->last_bit2 = st->last_bit;
-			if (curst < 0)
-				st->last_bit = 0;
-			else if (curst > 0)
-				st->last_bit = 1;
-			st->shreg >>= 1;
-			st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-		}
-		diag_add_one(sm, inv);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_hapn4800(struct sm_state *sm)
-{
-	struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d);
-
-	st->dcd_time = 120;
-	st->dcd_sum0 = 2;	
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_hapn4800_8_tx = {
-	"hapn4800", sizeof(struct mod_state_hapn48), 38400, 4800, 
-	modulator_hapn4800_8_u8, modulator_hapn4800_8_s16, NULL
-};
-
-const struct modem_rx_info sm_hapn4800_8_rx = {
-	"hapn4800", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8, 
-	demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800
-};
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_hapn4800_10_tx = {
-	"hapn4800", sizeof(struct mod_state_hapn48), 48000, 4800,
-	modulator_hapn4800_10_u8, modulator_hapn4800_10_s16, NULL
-};
-
-const struct modem_rx_info sm_hapn4800_10_rx = {
-	"hapn4800", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10, 
-	demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800
-};
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_hapn4800_pm8_tx = {
-	"hapn4800pm", sizeof(struct mod_state_hapn48), 38400, 4800, 
-	modulator_hapn4800_pm8_u8, modulator_hapn4800_pm8_s16, NULL
-};
-
-const struct modem_rx_info sm_hapn4800_pm8_rx = {
-	"hapn4800pm", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8, 
-	demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800
-};
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_hapn4800_pm10_tx = {
-	"hapn4800pm", sizeof(struct mod_state_hapn48), 48000, 4800,
-	modulator_hapn4800_pm10_u8, modulator_hapn4800_pm10_s16, NULL
-};
-
-const struct modem_rx_info sm_hapn4800_pm10_rx = {
-	"hapn4800pm", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10,
-	demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800
-};
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_psk4800.c b/drivers/net/hamradio/soundmodem/sm_psk4800.c
--- a/drivers/net/hamradio/soundmodem/sm_psk4800.c	Wed Nov 27 14:36:29 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,418 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm_psk4800.c  -- soundcard radio modem driver, 4800 baud 8PSK modem
- *
- *	Copyright (C) 1997  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#include "sm.h"
-#include "sm_tbl_psk4800.h"
-
-/* --------------------------------------------------------------------- */
-
-#define DESCRAM_TAP1 0x20000
-#define DESCRAM_TAP2 0x01000
-#define DESCRAM_TAP3 0x00001
-
-#define DESCRAM_TAPSH1 17
-#define DESCRAM_TAPSH2 12
-#define DESCRAM_TAPSH3 0
-
-#define SCRAM_TAP1 0x20000 /* X^17 */
-#define SCRAM_TAPN 0x00021 /* X^0+X^5 */
-
-#define SCRAM_SHIFT 17
-
-/* --------------------------------------------------------------------- */
-
-struct demod_state_psk48 {
-	/*
-	 * input mixer and lowpass
-	 */
-	short infi[PSK48_RXF_LEN/2], infq[PSK48_RXF_LEN/2];
-	unsigned int downmixer;
-	int ovrphase;
-	short magi, magq;
-	/*
-	 * sampling instant recovery
-	 */
-	int pwrhist[5];
-	unsigned int s_phase;
-	int cur_sync;
-	/*
-	 * phase recovery
-	 */
-	short cur_phase_dev;
-	short last_ph_err;
-	unsigned short pskph;
-	unsigned int phase;
-	unsigned short last_pskph;
-	unsigned char cur_raw, last_raw, rawbits;
-	/*
-	 * decoding
-	 */
-	unsigned int shreg;
-	unsigned long descram;
-	unsigned int bit_pll;
-	unsigned char last_sample;
-	unsigned int dcd_shreg;
-	int dcd_sum0, dcd_sum1, dcd_sum2;
-	unsigned int dcd_time;
-};
-
-struct mod_state_psk48 {
-	unsigned char txbits[PSK48_TXF_NUMSAMPLES];
-	unsigned short txphase;
-	unsigned int shreg;
-	unsigned long scram;
-	const short *tbl;
-	unsigned int txseq;
-};
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_4800_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen)
-{
-	struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m);
-	int i, j;
-	int si, sq;
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->txseq++) {
-			memmove(st->txbits+1, st->txbits, 
-				sizeof(st->txbits)-sizeof(st->txbits[0]));
-			for (i = 0; i < 3; i++) {
-				if (st->shreg <= 1)
-					st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-				st->scram = (st->scram << 1) |
-					(st->shreg & 1);
-				st->shreg >>= 1;
-				if (st->scram & SCRAM_TAP1)
-					st->scram ^= SCRAM_TAPN;
-			}
-			j = (st->scram >> (SCRAM_SHIFT+3)) & 7;
-			st->txbits[0] -= (j ^ (j >> 1));
-			st->txbits[0] &= 7;
-			st->tbl = psk48_tx_table;
-		}
-		if (st->txseq >= PSK48_TXF_OVERSAMPLING)
-			st->txseq = 0;
-		for (j = si = sq = 0; j < PSK48_TXF_NUMSAMPLES; j++, st->tbl += 16) {
-			si += st->tbl[st->txbits[j]];
-			sq += st->tbl[st->txbits[j]+8];
-		}
-		*buf = ((si*COS(st->txphase)+ sq*SIN(st->txphase)) >> 23) + 0x80;
-		st->txphase = (st->txphase + PSK48_PHASEINC) & 0xffffu;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void modulator_4800_s16(struct sm_state *sm, short *buf, unsigned int buflen)
-{
-	struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m);
-	int i, j;
-	int si, sq;
-
-	for (; buflen > 0; buflen--, buf++) {
-		if (!st->txseq++) {
-			memmove(st->txbits+1, st->txbits, 
-				sizeof(st->txbits)-sizeof(st->txbits[0]));
-			for (i = 0; i < 3; i++) {
-				if (st->shreg <= 1)
-					st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000;
-				st->scram = (st->scram << 1) |
-					(st->shreg & 1);
-				st->shreg >>= 1;
-				if (st->scram & SCRAM_TAP1)
-					st->scram ^= SCRAM_TAPN;
-			}
-			j = (st->scram >> (SCRAM_SHIFT+3)) & 7;
-			st->txbits[0] -= (j ^ (j >> 1));
-			st->txbits[0] &= 7;
-			st->tbl = psk48_tx_table;
-		}
-		if (st->txseq >= PSK48_TXF_OVERSAMPLING)
-			st->txseq = 0;
-		for (j = si = sq = 0; j < PSK48_TXF_NUMSAMPLES; j++, st->tbl += 16) {
-			si += st->tbl[st->txbits[j]];
-			sq += st->tbl[st->txbits[j]+8];
-		}
-		*buf = (si*COS(st->txphase)+ sq*SIN(st->txphase)) >> 15;
-		st->txphase = (st->txphase + PSK48_PHASEINC) & 0xffffu;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ unsigned short tbl_atan(short q, short i)
-{
-	short tmp;
-	unsigned short argoffs = 0;
-
-	if (i == 0 && q == 0)
-		return 0;
-	switch (((q < 0) << 1) | (i < 0)) {
-	case 0:
-		break;
-	case 1:
-		tmp = q;
-		q = -i;
-		i = tmp;
-		argoffs = 0x4000;
-		break;
-	case 3:
-		q = -q;
-		i = -i;
-		argoffs = 0x8000;
-		break;
-	case 2:
-		tmp = -q;
-		q = i;
-		i = tmp;
-		argoffs = 0xc000;
-		break;
-	}
-	if (q > i) {
-		tmp = i / q * ATAN_TABLEN;
-		return (argoffs+0x4000-atan_tab[((i<<15)/q*ATAN_TABLEN>>15)])
-			&0xffffu;
-	}
-	return (argoffs+atan_tab[((q<<15)/i*ATAN_TABLEN)>>15])&0xffffu;
-}
-
-#define ATAN(q,i) tbl_atan(q, i)
-
-/* --------------------------------------------------------------------- */
-
-static void demod_psk48_baseband(struct sm_state *sm, struct demod_state_psk48 *st,
-				 short vali, short valq)
-{
-	int i, j;
-
-	st->magi = vali;
-	st->magq = valq;
-	memmove(st->pwrhist+1, st->pwrhist, 
-		sizeof(st->pwrhist)-sizeof(st->pwrhist[0]));
-	st->pwrhist[0] = st->magi * st->magi +
-		st->magq * st->magq;
-	st->cur_sync = ((st->pwrhist[4] >> 2) > st->pwrhist[2] && 
-			(st->pwrhist[0] >> 2) > st->pwrhist[2] &&
-			st-> pwrhist[3] > st->pwrhist[2] && 
-			st->pwrhist[1] > st->pwrhist[2]);
-	st->s_phase &= 0xffff;
-	st->s_phase += PSK48_SPHASEINC;
-	st->dcd_shreg <<= 1;
-	if (st->cur_sync) {
-		if (st->s_phase >= (0x8000 + 5*PSK48_SPHASEINC/2))
-			st->s_phase -= PSK48_SPHASEINC/6;
-		else
-			st->s_phase += PSK48_SPHASEINC/6;
-		st->dcd_sum0 = 4*hweight8(st->dcd_shreg & 0xf8)-
-			hweight16(st->dcd_shreg & 0x1f00);
-	}
-	if ((--st->dcd_time) <= 0) {
-		hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + st->dcd_sum1 + 
-					   st->dcd_sum2) < 0);
-		st->dcd_sum2 = st->dcd_sum1;
-		st->dcd_sum1 = st->dcd_sum0;
-		st->dcd_sum0 = 2; /* slight bias */
-		st->dcd_time = 240;
-	}
-	if (st->s_phase < 0x10000)
-		return;
-	/*
-	 * sample one constellation
-	 */
-	st->last_pskph = st->pskph;
-	st->pskph = (ATAN(st->magq, st->magi)-
-			       st->phase) & 0xffffu;
-	st->last_ph_err = (st->pskph & 0x1fffu) - 0x1000;
-	st->phase += st->last_ph_err/16;
-	st->last_raw = st->cur_raw;
-	st->cur_raw = ((st->pskph >> 13) & 7);
-	i = (st->cur_raw - st->last_raw) & 7;
-	st->rawbits = i ^ (i >> 1) ^ (i >> 2);
-	st->descram = (st->descram << 3) | (st->rawbits);
-	hdlcdrv_channelbit(&sm->hdrv, st->descram & 4);
-	hdlcdrv_channelbit(&sm->hdrv, st->descram & 2);
-	hdlcdrv_channelbit(&sm->hdrv, st->descram & 1);
-	i = (((st->descram >> DESCRAM_TAPSH1) & 7) ^
-	     ((st->descram >> DESCRAM_TAPSH2) & 7) ^
-	     ((st->descram >> DESCRAM_TAPSH3) & 7));
- 	for (j = 4; j; j >>= 1) {
-		st->shreg >>= 1;
-		st->shreg |= (!!(i & j)) << 16;
-		if (st->shreg & 1) {
-			hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-			st->shreg = 0x10000;
-		}
-	}
-
-#if 0
-	st->dcd_shreg <<= 1;
-	st->bit_pll += 0x4000;
-	curbit = (*buf >= 0x80);
-	if (st->last_sample ^ curbit) {
-		st->dcd_shreg |= 1;
-		st->bit_pll += pll_corr
-			[st->bit_pll < 0xa000];
-		st->dcd_sum0 += 8 * 
-			hweight8(st->dcd_shreg & 0x0c) - 
-				!!(st->dcd_shreg & 0x10);
-	}
-	st->last_sample = curbit;
-	hdlcdrv_channelbit(&sm->hdrv, st->last_sample);
-	if ((--st->dcd_time) <= 0) {
-		hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + 
-					   st->dcd_sum1 + 
-					   st->dcd_sum2) < 0);
-		st->dcd_sum2 = st->dcd_sum1;
-		st->dcd_sum1 = st->dcd_sum0;
-		st->dcd_sum0 = 2; /* slight bias */
-		st->dcd_time = 240;
-	}
-	if (st->bit_pll >= 0x10000) {
-		st->bit_pll &= 0xffffu;
-		st->descram = (st->descram << 1) | curbit;
-		descx = st->descram ^ (st->descram >> 1);
-			descx ^= ((descx >> DESCRAM_TAPSH1) ^
-				  (descx >> DESCRAM_TAPSH2));
-			st->shreg >>= 1;
-			st->shreg |= (!(descx & 1)) << 16;
-			if (st->shreg & 1) {
-				hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1);
-				st->shreg = 0x10000;
-			}
-			diag_trigger(sm);
-	}
-	diag_add_one(sm, ((short)(*buf - 0x80)) << 8);
-#endif
-	
-	diag_trigger(sm);
-	diag_add_constellation(sm, (vali*COS(st->phase)+ valq*SIN(st->phase)) >> 13, 
-			       (valq*COS(st->phase) - vali*SIN(st->phase)) >> 13);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_4800_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen)
-{
-	struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d);
-	int i, si, sq;
-	const short *coeff;
-
-	for (; buflen > 0; buflen--, buf++) {
-		memmove(st->infi+1, st->infi, 
-			sizeof(st->infi)-sizeof(st->infi[0]));
-		memmove(st->infq+1, st->infq, 
-			sizeof(st->infq)-sizeof(st->infq[0]));
-		si = *buf;
-		si &= 0xff;
-		si -= 128;
-		diag_add_one(sm, si << 8);
-		st->infi[0] = (si * COS(st->downmixer))>>7;
-		st->infq[0] = (si * SIN(st->downmixer))>>7;
-		st->downmixer = (st->downmixer-PSK48_PHASEINC)&0xffffu;
-		for (i = si = sq = 0, coeff = psk48_rx_coeff; i < (PSK48_RXF_LEN/2); 
-		     i++, coeff += 2) {
-			si += st->infi[i] * (*coeff);
-			sq += st->infq[i] * (*coeff);
-		}
-		demod_psk48_baseband(sm, st, si >> 15, sq >> 15);
-		for (i = si = sq = 0, coeff = psk48_rx_coeff + 1; i < (PSK48_RXF_LEN/2); 
-		     i++, coeff += 2) {
-			si += st->infi[i] * (*coeff);
-			sq += st->infq[i] * (*coeff);
-		}
-		demod_psk48_baseband(sm, st, si >> 15, sq >> 15);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demodulator_4800_s16(struct sm_state *sm, const short *buf, unsigned int buflen)
-{
-	struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d);
-	int i, si, sq;
-	const short *coeff;
-
-	for (; buflen > 0; buflen--, buf++) {
-		memmove(st->infi+1, st->infi, 
-			sizeof(st->infi)-sizeof(st->infi[0]));
-		memmove(st->infq+1, st->infq, 
-			sizeof(st->infq)-sizeof(st->infq[0]));
-		si = *buf;
-		diag_add_one(sm, si);
-		st->infi[0] = (si * COS(st->downmixer))>>15;
-		st->infq[0] = (si * SIN(st->downmixer))>>15;
-		st->downmixer = (st->downmixer-PSK48_PHASEINC)&0xffffu;
-		for (i = si = sq = 0, coeff = psk48_rx_coeff; i < (PSK48_RXF_LEN/2); 
-		     i++, coeff += 2) {
-			si += st->infi[i] * (*coeff);
-			sq += st->infq[i] * (*coeff);
-		}
-		demod_psk48_baseband(sm, st, si >> 15, sq >> 15);
-		for (i = si = sq = 0, coeff = psk48_rx_coeff + 1; i < (PSK48_RXF_LEN/2); 
-		     i++, coeff += 2) {
-			si += st->infi[i] * (*coeff);
-			sq += st->infq[i] * (*coeff);
-		}
-		demod_psk48_baseband(sm, st, si >> 15, sq >> 15);
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static void mod_init_4800(struct sm_state *sm)
-{
-	struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m);
-
-	st->scram = 1;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void demod_init_4800(struct sm_state *sm)
-{
-	struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d);
-
-	st->dcd_time = 120;
-	st->dcd_sum0 = 2;	
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct modem_tx_info sm_psk4800_tx = {
-	"psk4800", sizeof(struct mod_state_psk48), 
-	PSK48_SAMPLERATE, 4800,
-	modulator_4800_u8, modulator_4800_s16, mod_init_4800
-};
-
-const struct modem_rx_info sm_psk4800_rx = {
-	"psk4800", sizeof(struct demod_state_psk48), 
-	PSK48_SAMPLERATE, 4800, 1, PSK48_TXF_OVERSAMPLING, 
-	demodulator_4800_u8, demodulator_4800_s16, demod_init_4800
-};
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_sbc.c b/drivers/net/hamradio/soundmodem/sm_sbc.c
--- a/drivers/net/hamradio/soundmodem/sm_sbc.c	Wed Nov 27 14:36:31 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,942 +0,0 @@
-
-
-/*
- *	sm_sbc.c  -- soundcard radio modem driver soundblaster hardware driver
- *
- *	Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/soundmodem.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "sm.h"
-#include "smdma.h"
-
-/* --------------------------------------------------------------------- */
-
-/*
- * currently this module is supposed to support both module styles, i.e.
- * the old one present up to about 2.1.9, and the new one functioning
- * starting with 2.1.21. The reason is I have a kit allowing to compile
- * this module also under 2.0.x which was requested by several people.
- * This will go in 2.2
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= 0x20100
-#include <asm/uaccess.h>
-#else
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-#undef put_user
-#undef get_user
-
-#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
-#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
-
-static inline int copy_from_user(void *to, const void *from, unsigned long n)
-{
-        int i = verify_area(VERIFY_READ, from, n);
-        if (i)
-                return i;
-        memcpy_fromfs(to, from, n);
-        return 0;
-}
-
-static inline int copy_to_user(void *to, const void *from, unsigned long n)
-{
-        int i = verify_area(VERIFY_WRITE, to, n);
-        if (i)
-                return i;
-        memcpy_tofs(to, from, n);
-        return 0;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-struct sc_state_sbc {
-	unsigned char revhi, revlo;
-	unsigned char fmt[2];
-	unsigned int sr[2];
-};
-
-#define SCSTATE ((struct sc_state_sbc *)(&sm->hw))
-
-/* --------------------------------------------------------------------- */
-/* 
- * the sbc converter's registers 
- */
-#define DSP_RESET(iobase)        (iobase+0x6)
-#define DSP_READ_DATA(iobase)    (iobase+0xa)
-#define DSP_WRITE_DATA(iobase)   (iobase+0xc)
-#define DSP_WRITE_STATUS(iobase) (iobase+0xc)
-#define DSP_DATA_AVAIL(iobase)   (iobase+0xe)
-#define DSP_MIXER_ADDR(iobase)   (iobase+0x4)
-#define DSP_MIXER_DATA(iobase)   (iobase+0x5)
-#define DSP_INTACK_16BIT(iobase) (iobase+0xf)
-#define SBC_EXTENT               16
-
-/* --------------------------------------------------------------------- */
-/*
- * SBC commands
- */
-#define SBC_OUTPUT             0x14
-#define SBC_INPUT              0x24
-#define SBC_BLOCKSIZE          0x48
-#define SBC_HI_OUTPUT          0x91 
-#define SBC_HI_INPUT           0x99 
-#define SBC_LO_OUTPUT_AUTOINIT 0x1c
-#define SBC_LO_INPUT_AUTOINIT  0x2c
-#define SBC_HI_OUTPUT_AUTOINIT 0x90 
-#define SBC_HI_INPUT_AUTOINIT  0x98
-#define SBC_IMMED_INT          0xf2
-#define SBC_GET_REVISION       0xe1
-#define ESS_GET_REVISION       0xe7
-#define SBC_SPEAKER_ON         0xd1
-#define SBC_SPEAKER_OFF        0xd3
-#define SBC_DMA_ON             0xd0
-#define SBC_DMA_OFF            0xd4
-#define SBC_SAMPLE_RATE        0x40
-#define SBC_SAMPLE_RATE_OUT    0x41
-#define SBC_SAMPLE_RATE_IN     0x42
-#define SBC_MONO_8BIT          0xa0
-#define SBC_MONO_16BIT         0xa4
-#define SBC_STEREO_8BIT        0xa8
-#define SBC_STEREO_16BIT       0xac
-
-#define SBC4_OUT8_AI           0xc6
-#define SBC4_IN8_AI            0xce
-#define SBC4_MODE_UNS_MONO     0x00
-#define SBC4_MODE_SIGN_MONO    0x10
-
-#define SBC4_OUT16_AI          0xb6
-#define SBC4_IN16_AI           0xbe
-
-/* --------------------------------------------------------------------- */
-
-static int inline reset_dsp(struct net_device *dev)
-{
-	int i;
-
-	outb(1, DSP_RESET(dev->base_addr));
-	udelay(300);
-	outb(0, DSP_RESET(dev->base_addr));
-	for (i = 0; i < 0xffff; i++)
-		if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80)
-			if (inb(DSP_READ_DATA(dev->base_addr)) == 0xaa)
-				return 1;
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void inline write_dsp(struct net_device *dev, unsigned char data)
-{
-	int i;
-	
-	for (i = 0; i < 0xffff; i++)
-		if (!(inb(DSP_WRITE_STATUS(dev->base_addr)) & 0x80)) {
-			outb(data, DSP_WRITE_DATA(dev->base_addr));
-			return;
-		}
-}
-
-/* --------------------------------------------------------------------- */
-
-static int inline read_dsp(struct net_device *dev, unsigned char *data)
-{
-	int i;
-
-	if (!data)
-		return 0;
-	for (i = 0; i < 0xffff; i++) 
-		if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80) {
-			*data = inb(DSP_READ_DATA(dev->base_addr));
-			return 1;
-		}
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int config_resources(struct net_device *dev, struct sm_state *sm, int fdx)
-{
-	unsigned char irqreg = 0, dmareg = 0, realirq, realdma;
-	unsigned long flags;
-
-	switch (dev->irq) {
-	case 2:
-	case 9:
-		irqreg |= 0x01;
-		break;
-
-	case 5:
-		irqreg |= 0x02;
-		break;
-
-	case 7:
-		irqreg |= 0x04;
-		break;
-
-	case 10:
-		irqreg |= 0x08;
-		break;
-		
-	default:
-		return -ENODEV;
-	}
-
-	switch (dev->dma) {
-	case 0:
-		dmareg |= 0x01;
-		break;
-
-	case 1:
-		dmareg |= 0x02;
-		break;
-
-	case 3:
-		dmareg |= 0x08;
-		break;
-
-	default:
-		return -ENODEV;
-	}
-		
-	if (fdx) {
-		switch (sm->hdrv.ptt_out.dma2) {
-		case 5:
-			dmareg |= 0x20;
-			break;
-			
-		case 6:
-			dmareg |= 0x40;
-			break;
-			
-		case 7:
-			dmareg |= 0x80;
-			break;
-			
-		default:
-			return -ENODEV;
-		}
-	}
-	save_flags(flags);
-	cli();
-	outb(0x80, DSP_MIXER_ADDR(dev->base_addr));
-	outb(irqreg, DSP_MIXER_DATA(dev->base_addr));
-	realirq = inb(DSP_MIXER_DATA(dev->base_addr));
-	outb(0x81, DSP_MIXER_ADDR(dev->base_addr));
-	outb(dmareg, DSP_MIXER_DATA(dev->base_addr));
-	realdma = inb(DSP_MIXER_DATA(dev->base_addr));
-	restore_flags(flags);
-	if ((~realirq) & irqreg || (~realdma) & dmareg) {
-		printk(KERN_ERR "%s: sbc resource registers cannot be set; PnP device "
-		       "and IRQ/DMA specified wrongly?\n", sm_drvname);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void inline sbc_int_ack_8bit(struct net_device *dev)
-{
-	inb(DSP_DATA_AVAIL(dev->base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-static void inline sbc_int_ack_16bit(struct net_device *dev)
-{
-	inb(DSP_INTACK_16BIT(dev->base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-static void setup_dma_dsp(struct net_device *dev, struct sm_state *sm, int send)
-{
-        unsigned long flags;
-        static const unsigned char sbcmode[2][2] = {
-		{ SBC_LO_INPUT_AUTOINIT, SBC_LO_OUTPUT_AUTOINIT }, 
-		{ SBC_HI_INPUT_AUTOINIT, SBC_HI_OUTPUT_AUTOINIT }
-	};
-	static const unsigned char sbc4mode[2] = { SBC4_IN8_AI, SBC4_OUT8_AI };
-	static const unsigned char sbcskr[2] = { SBC_SPEAKER_OFF, SBC_SPEAKER_ON };
-	unsigned int nsamps;
-
-	send = !!send;
-        if (!reset_dsp(dev)) {
-                printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname);
-                return;
-        }
-        save_flags(flags);
-        cli();
-        sbc_int_ack_8bit(dev);
-        write_dsp(dev, SBC_SAMPLE_RATE); /* set sampling rate */
-        write_dsp(dev, SCSTATE->fmt[send]);
-        write_dsp(dev, sbcskr[send]); 
-	nsamps = dma_setup(sm, send, dev->dma) - 1;
-        sbc_int_ack_8bit(dev);
-	if (SCSTATE->revhi >= 4) {
-		write_dsp(dev, sbc4mode[send]);
-		write_dsp(dev, SBC4_MODE_UNS_MONO);
-		write_dsp(dev, nsamps & 0xff);
-		write_dsp(dev, nsamps >> 8);
-	} else {
-		write_dsp(dev, SBC_BLOCKSIZE);
-		write_dsp(dev, nsamps & 0xff);
-		write_dsp(dev, nsamps >> 8);
-		write_dsp(dev, sbcmode[SCSTATE->fmt[send] >= 180][send]);
-		/* hispeed mode if sample rate > 13kHz */
-	}
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void sbc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	struct sm_state *sm = (struct sm_state *)dev->priv;
-	unsigned int curfrag;
-
-	if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC)
-		return;
-	cli();
- 	sbc_int_ack_8bit(dev);
-	disable_dma(dev->dma);
-	clear_dma_ff(dev->dma);
-	dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag);
-	enable_dma(dev->dma);
-	sm_int_freq(sm);
-	sti();
-	if (sm->dma.ptt_cnt <= 0) {
-		dma_receive(sm, curfrag);
-		hdlcdrv_arbitrate(dev, &sm->hdrv);
-		if (hdlcdrv_ptt(&sm->hdrv)) {
-			/* starting to transmit */
-			disable_dma(dev->dma);
-			hdlcdrv_transmitter(dev, &sm->hdrv); /* prefill HDLC buffer */
-			dma_start_transmit(sm);
-			setup_dma_dsp(dev, sm, 1);
-			dma_transmit(sm);
-		}
-	} else if (dma_end_transmit(sm, curfrag)) {
-		/* stopping transmission */
-		disable_dma(dev->dma);
-		sti();
-		dma_init_receive(sm);
-		setup_dma_dsp(dev, sm, 0);
-        } else
-		dma_transmit(sm);
-	sm_output_status(sm);
-	hdlcdrv_transmitter(dev, &sm->hdrv);
-	hdlcdrv_receiver(dev, &sm->hdrv);
-
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbc_open(struct net_device *dev, struct sm_state *sm) 
-{
-	int err;
-	unsigned int dmasz, u;
-
-	if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) {
-		printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n", 
-		       sizeof(struct sc_state_sbc), sizeof(sm->m));
-		return -ENODEV;
-	}
-	if (!dev || !sm)
-		return -ENXIO;
-	if (dev->base_addr <= 0 || dev->base_addr > 0x1000-SBC_EXTENT || 
-	    dev->irq < 2 || dev->irq > 15 || dev->dma > 3)
-		return -ENXIO;
-	if (check_region(dev->base_addr, SBC_EXTENT))
-		return -EACCES;
-	/*
-	 * check if a card is available
-	 */
-	if (!reset_dsp(dev)) {
-		printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n",
-		       sm_drvname, dev->base_addr);
-		return -ENODEV;
-	}
-	write_dsp(dev, SBC_GET_REVISION);
-	if (!read_dsp(dev, &SCSTATE->revhi) || 
-	    !read_dsp(dev, &SCSTATE->revlo))
-		return -ENODEV;
-	printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname, 
-	       SCSTATE->revhi, SCSTATE->revlo);
-	if (SCSTATE->revhi < 2) {
-		printk(KERN_ERR "%s: your card is an antiquity, at least DSP "
-		       "rev 2.00 required\n", sm_drvname);
-		return -ENODEV;
-	}
-	if (SCSTATE->revhi < 3 && 
-	    (SCSTATE->fmt[0] >= 180 || SCSTATE->fmt[1] >= 180)) {
-		printk(KERN_ERR "%s: sbc io 0x%lx: DSP rev %d.%02d too "
-		       "old, at least 3.00 required\n", sm_drvname,
-		       dev->base_addr, SCSTATE->revhi, SCSTATE->revlo);
-		return -ENODEV;
-	}
-	if (SCSTATE->revhi >= 4 && 
-	    (err = config_resources(dev, sm, 0))) {
-		printk(KERN_ERR "%s: invalid IRQ and/or DMA specified\n", sm_drvname);
-		return err;
-	}
-	/*
-	 * initialize some variables
-	 */
-	dma_init_receive(sm);
-	dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz;
-	u = NUM_FRAGMENTS * sm->dma.ofragsz;
-	if (u > dmasz)
-		dmasz = u;
-	if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA)))
-		return -ENOMEM;
-	dma_init_transmit(sm);
-	dma_init_receive(sm);
-
-	memset(&sm->m, 0, sizeof(sm->m));
-	memset(&sm->d, 0, sizeof(sm->d));
-	if (sm->mode_tx->init)
-		sm->mode_tx->init(sm);
-	if (sm->mode_rx->init)
-		sm->mode_rx->init(sm);
-
-	if (request_dma(dev->dma, sm->hwdrv->hw_name)) {
-		kfree(sm->dma.obuf);
-		return -EBUSY;
-	}
-	if (request_irq(dev->irq, sbc_interrupt, SA_INTERRUPT, 
-			sm->hwdrv->hw_name, dev)) {
-		free_dma(dev->dma);
-		kfree(sm->dma.obuf);
-		return -EBUSY;
-	}
-	request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name);
-	setup_dma_dsp(dev, sm, 0);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbc_close(struct net_device *dev, struct sm_state *sm) 
-{
-	if (!dev || !sm)
-		return -EINVAL;
-	/*
-	 * disable interrupts
-	 */
-	disable_dma(dev->dma);
-	reset_dsp(dev);	
-	free_irq(dev->irq, dev);	
-	free_dma(dev->dma);	
-	release_region(dev->base_addr, SBC_EXTENT);
-	kfree(sm->dma.obuf);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbc_sethw(struct net_device *dev, struct sm_state *sm, char *mode)
-{
-	char *cp = strchr(mode, '.');
-	const struct modem_tx_info **mtp = sm_modem_tx_table;
-	const struct modem_rx_info **mrp;
-
-	if (!strcmp(mode, "off")) {
-		sm->mode_tx = NULL;
-		sm->mode_rx = NULL;
-		return 0;
-	}
-	if (cp)
-		*cp++ = '\0';
-	else
-		cp = mode;
-	for (; *mtp; mtp++) {
-		if ((*mtp)->loc_storage > sizeof(sm->m)) {
-			printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n",
-			       sm_drvname, (*mtp)->name, (*mtp)->loc_storage);
-			continue;
-		}
-		if (!(*mtp)->name || strcmp((*mtp)->name, mode))
-			continue;
-		if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100)
-			continue;
-		if (!(*mtp)->modulator_u8)
-			continue;
-		for (mrp = sm_modem_rx_table; *mrp; mrp++) {
-			if ((*mrp)->loc_storage > sizeof(sm->d)) {
-				printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n",
-				       sm_drvname, (*mrp)->name, (*mrp)->loc_storage);
-				continue;
-			}
-			if (!(*mrp)->demodulator_u8)
-				continue;
-			if ((*mrp)->name && !strcmp((*mrp)->name, cp) &&
-			    (*mrp)->srate >= 5000 && (*mrp)->srate <= 44100) {
-				sm->mode_tx = *mtp;
-				sm->mode_rx = *mrp;
-				SCSTATE->fmt[0] = 256-((1000000L+sm->mode_rx->srate/2)/
-							 sm->mode_rx->srate);
-				SCSTATE->fmt[1] = 256-((1000000L+sm->mode_tx->srate/2)/
-							 sm->mode_tx->srate);
-				sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100;
-				sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100;
-				if (sm->dma.ifragsz < sm->mode_rx->overlap)
-					sm->dma.ifragsz = sm->mode_rx->overlap;
-				sm->dma.i16bit = sm->dma.o16bit = 0;
-				return 0;
-			}
-		}
-	}
-	return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbc_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, 
-		     struct hdlcdrv_ioctl *hi, int cmd)
-{
-	struct sm_ioctl bi;
-	unsigned long flags;
-	int i;
-	
-	if (cmd != SIOCDEVPRIVATE)
-		return -ENOIOCTLCMD;
-
-	if (hi->cmd == HDLCDRVCTL_MODEMPARMASK)
-		return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | 
-			HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_SERIOBASE | 
-			HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE;
-
-	if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
-		return -EFAULT;
-
-	switch (bi.cmd) {
-	default:
-		return -ENOIOCTLCMD;
-
-	case SMCTL_GETMIXER:
-		i = 0;
-		bi.data.mix.sample_rate = sm->mode_rx->srate;
-		bi.data.mix.bit_rate = sm->hdrv.par.bitrate;
-		bi.data.mix.mixer_type = SM_MIXER_INVALID;
-		switch (SCSTATE->revhi) {
-		case 2:
-			bi.data.mix.mixer_type = SM_MIXER_CT1335;
-			break;
-		case 3:
-			bi.data.mix.mixer_type = SM_MIXER_CT1345;
-			break;
-		case 4:
-			bi.data.mix.mixer_type = SM_MIXER_CT1745;
-			break;
-		}
-		if (bi.data.mix.mixer_type != SM_MIXER_INVALID &&
-		    bi.data.mix.reg < 0x80) {
-			save_flags(flags);
-			cli();
-			outb(bi.data.mix.reg, DSP_MIXER_ADDR(dev->base_addr));
-			bi.data.mix.data = inb(DSP_MIXER_DATA(dev->base_addr));
-			restore_flags(flags);
-			i = 1;
-		}
-		if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-			return -EFAULT;
-		return i;
-		
-	case SMCTL_SETMIXER:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EACCES;
-		switch (SCSTATE->revhi) {
-		case 2:
-			if (bi.data.mix.mixer_type != SM_MIXER_CT1335)
-				return -EINVAL;
-			break;
-		case 3:
-			if (bi.data.mix.mixer_type != SM_MIXER_CT1345)
-				return -EINVAL;
-			break;
-		case 4:
-			if (bi.data.mix.mixer_type != SM_MIXER_CT1745)
-				return -EINVAL;
-			break;
-		default:
-			return -ENODEV;
-		}
-		if (bi.data.mix.reg >= 0x80)
-			return -EACCES;
-		save_flags(flags);
-		cli();
-		outb(bi.data.mix.reg, DSP_MIXER_ADDR(dev->base_addr));
-		outb(bi.data.mix.data, DSP_MIXER_DATA(dev->base_addr));
-		restore_flags(flags);
-		return 0;
-		
-	}
-	if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-		return -EFAULT;
-	return 0;
-
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct hardware_info sm_hw_sbc = {
-	"sbc", sizeof(struct sc_state_sbc), 
-	sbc_open, sbc_close, sbc_ioctl, sbc_sethw
-};
-
-/* --------------------------------------------------------------------- */
-
-static void setup_dma_fdx_dsp(struct net_device *dev, struct sm_state *sm)
-{
-        unsigned long flags;
-	unsigned int isamps, osamps;
-
-        if (!reset_dsp(dev)) {
-                printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname);
-                return;
-        }
-        save_flags(flags);
-        cli();
-        sbc_int_ack_8bit(dev);
-        sbc_int_ack_16bit(dev);
-	/* should eventually change to set rates individually by SBC_SAMPLE_RATE_{IN/OUT} */
-	write_dsp(dev, SBC_SAMPLE_RATE_IN);
-	write_dsp(dev, SCSTATE->sr[0] >> 8);
-	write_dsp(dev, SCSTATE->sr[0] & 0xff);
-	write_dsp(dev, SBC_SAMPLE_RATE_OUT);
-	write_dsp(dev, SCSTATE->sr[1] >> 8);
-	write_dsp(dev, SCSTATE->sr[1] & 0xff);
-        write_dsp(dev, SBC_SPEAKER_ON);
-	if (sm->dma.o16bit) {
-		/*
-		 * DMA channel 1 (8bit) does input (capture),
-		 * DMA channel 2 (16bit) does output (playback)
-		 */
-		isamps = dma_setup(sm, 0, dev->dma) - 1;
-		osamps = dma_setup(sm, 1, sm->hdrv.ptt_out.dma2) - 1;
-		sbc_int_ack_8bit(dev);
-		sbc_int_ack_16bit(dev);
-		write_dsp(dev, SBC4_IN8_AI);
-		write_dsp(dev, SBC4_MODE_UNS_MONO);
-		write_dsp(dev, isamps & 0xff);
-		write_dsp(dev, isamps >> 8);
-		write_dsp(dev, SBC4_OUT16_AI);
-		write_dsp(dev, SBC4_MODE_SIGN_MONO);
-		write_dsp(dev, osamps & 0xff);
-		write_dsp(dev, osamps >> 8);
-	} else {
-		/*
-		 * DMA channel 1 (8bit) does output (playback),
-		 * DMA channel 2 (16bit) does input (capture)
-		 */
-		isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1;
-		osamps = dma_setup(sm, 1, dev->dma) - 1;
-		sbc_int_ack_8bit(dev);
-		sbc_int_ack_16bit(dev);
-		write_dsp(dev, SBC4_OUT8_AI);
-		write_dsp(dev, SBC4_MODE_UNS_MONO);
-		write_dsp(dev, osamps & 0xff);
-		write_dsp(dev, osamps >> 8);
-		write_dsp(dev, SBC4_IN16_AI);
-		write_dsp(dev, SBC4_MODE_SIGN_MONO);
-		write_dsp(dev, isamps & 0xff);
-		write_dsp(dev, isamps >> 8);
-	}
-	dma_init_receive(sm);
-	dma_init_transmit(sm);
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void sbcfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	struct sm_state *sm = (struct sm_state *)dev->priv;
-	unsigned char intsrc, pbint = 0, captint = 0;
-	unsigned int ocfrag, icfrag;
-	unsigned long flags;
-
-	if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC)
-		return;
-	save_flags(flags);
-	cli();
-	outb(0x82, DSP_MIXER_ADDR(dev->base_addr));
-	intsrc = inb(DSP_MIXER_DATA(dev->base_addr));
-	if (intsrc & 0x01) {
-		sbc_int_ack_8bit(dev);
-		if (sm->dma.o16bit) {
-			captint = 1;
-			disable_dma(dev->dma);
-			clear_dma_ff(dev->dma);
-			dma_ptr(sm, 0, dev->dma, &icfrag);
-			enable_dma(dev->dma);
-		} else {     
-			pbint = 1;
-			disable_dma(dev->dma);
-			clear_dma_ff(dev->dma);
-			dma_ptr(sm, 1, dev->dma, &ocfrag);
-			enable_dma(dev->dma);
-		}
-	}
-	if (intsrc & 0x02) {
-		sbc_int_ack_16bit(dev);
-		if (sm->dma.o16bit) {
-			pbint = 1;
-			disable_dma(sm->hdrv.ptt_out.dma2);
-			clear_dma_ff(sm->hdrv.ptt_out.dma2);
-			dma_ptr(sm, 1, sm->hdrv.ptt_out.dma2, &ocfrag);
-			enable_dma(sm->hdrv.ptt_out.dma2);
-		} else {
-			captint = 1;
-			disable_dma(sm->hdrv.ptt_out.dma2);
-			clear_dma_ff(sm->hdrv.ptt_out.dma2);
-			dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag);
-			enable_dma(sm->hdrv.ptt_out.dma2);
-		}
-	}
-	restore_flags(flags);
-	sm_int_freq(sm);
-	sti();
-	if (pbint) {
-		if (dma_end_transmit(sm, ocfrag))
-			dma_clear_transmit(sm);
-		dma_transmit(sm);
-	}
-	if (captint) { 
-		dma_receive(sm, icfrag);
-		hdlcdrv_arbitrate(dev, &sm->hdrv);
-	}
-	sm_output_status(sm);
-	hdlcdrv_transmitter(dev, &sm->hdrv);
-	hdlcdrv_receiver(dev, &sm->hdrv);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbcfdx_open(struct net_device *dev, struct sm_state *sm) 
-{
-	int err;
-
-	if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) {
-		printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n", 
-		       sizeof(struct sc_state_sbc), sizeof(sm->m));
-		return -ENODEV;
-	}
-	if (!dev || !sm)
-		return -ENXIO;
-	if (dev->base_addr <= 0 || dev->base_addr > 0x1000-SBC_EXTENT || 
-	    dev->irq < 2 || dev->irq > 15 || dev->dma > 3)
-		return -ENXIO;
-	if (check_region(dev->base_addr, SBC_EXTENT))
-		return -EACCES;
-	/*
-	 * check if a card is available
-	 */
-	if (!reset_dsp(dev)) {
-		printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n",
-		       sm_drvname, dev->base_addr);
-		return -ENODEV;
-	}
-	write_dsp(dev, SBC_GET_REVISION);
-	if (!read_dsp(dev, &SCSTATE->revhi) || 
-	    !read_dsp(dev, &SCSTATE->revlo))
-		return -ENODEV;
-	printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname, 
-	       SCSTATE->revhi, SCSTATE->revlo);
-	if (SCSTATE->revhi < 4) {
-		printk(KERN_ERR "%s: at least DSP rev 4.00 required\n", sm_drvname);
-		return -ENODEV;
-	}
-	if ((err = config_resources(dev, sm, 1))) {
-		printk(KERN_ERR "%s: invalid IRQ and/or DMA specified\n", sm_drvname);
-		return err;
-	}
-	/*
-	 * initialize some variables
-	 */
-	if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA)))
-		return -ENOMEM;
-	if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) {
-		kfree(sm->dma.ibuf);
-		return -ENOMEM;
-	}
-	dma_init_transmit(sm);
-	dma_init_receive(sm);
-
-	memset(&sm->m, 0, sizeof(sm->m));
-	memset(&sm->d, 0, sizeof(sm->d));
-	if (sm->mode_tx->init)
-		sm->mode_tx->init(sm);
-	if (sm->mode_rx->init)
-		sm->mode_rx->init(sm);
-
-	if (request_dma(dev->dma, sm->hwdrv->hw_name)) {
-		kfree(sm->dma.ibuf);
-		kfree(sm->dma.obuf);
-		return -EBUSY;
-	}
-	if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) {
-		kfree(sm->dma.ibuf);
-		kfree(sm->dma.obuf);
-		free_dma(dev->dma);
-		return -EBUSY;
-	}
-	if (request_irq(dev->irq, sbcfdx_interrupt, SA_INTERRUPT, 
-			sm->hwdrv->hw_name, dev)) {
-		kfree(sm->dma.ibuf);
-		kfree(sm->dma.obuf);
-		free_dma(dev->dma);
-		free_dma(sm->hdrv.ptt_out.dma2);
-		return -EBUSY;
-	}
-	request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name);
-	setup_dma_fdx_dsp(dev, sm);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbcfdx_close(struct net_device *dev, struct sm_state *sm) 
-{
-	if (!dev || !sm)
-		return -EINVAL;
-	/*
-	 * disable interrupts
-	 */
-	disable_dma(dev->dma);
-	disable_dma(sm->hdrv.ptt_out.dma2);
-	reset_dsp(dev);	
-	free_irq(dev->irq, dev);	
-	free_dma(dev->dma);	
-	free_dma(sm->hdrv.ptt_out.dma2);	
-	release_region(dev->base_addr, SBC_EXTENT);
-	kfree(sm->dma.ibuf);
-	kfree(sm->dma.obuf);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbcfdx_sethw(struct net_device *dev, struct sm_state *sm, char *mode)
-{
-	char *cp = strchr(mode, '.');
-	const struct modem_tx_info **mtp = sm_modem_tx_table;
-	const struct modem_rx_info **mrp;
-
-	if (!strcmp(mode, "off")) {
-		sm->mode_tx = NULL;
-		sm->mode_rx = NULL;
-		return 0;
-	}
-	if (cp)
-		*cp++ = '\0';
-	else
-		cp = mode;
-	for (; *mtp; mtp++) {
-		if ((*mtp)->loc_storage > sizeof(sm->m)) {
-			printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n",
-			       sm_drvname, (*mtp)->name, (*mtp)->loc_storage);
-			continue;
-		}
-		if (!(*mtp)->name || strcmp((*mtp)->name, mode))
-			continue;
-		if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100)
-			continue;
-		for (mrp = sm_modem_rx_table; *mrp; mrp++) {
-			if ((*mrp)->loc_storage > sizeof(sm->d)) {
-				printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n",
-				       sm_drvname, (*mrp)->name, (*mrp)->loc_storage);
-				continue;
-			}
-			if ((*mrp)->name && !strcmp((*mrp)->name, cp) &&
-			    (*mtp)->srate >= 5000 && (*mtp)->srate <= 44100 &&
-			    (*mrp)->srate == (*mtp)->srate) {
-				sm->mode_tx = *mtp;
-				sm->mode_rx = *mrp;
-				SCSTATE->sr[0] = sm->mode_rx->srate;
-				SCSTATE->sr[1] = sm->mode_tx->srate;
-				sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100;
-				sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100;
-				if (sm->dma.ifragsz < sm->mode_rx->overlap)
-					sm->dma.ifragsz = sm->mode_rx->overlap;
-				if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_u8) {
-					sm->dma.i16bit = 1;
-					sm->dma.o16bit = 0;
-					sm->dma.ifragsz <<= 1;
-				} else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_s16) {
-					sm->dma.i16bit = 0;
-					sm->dma.o16bit = 1;
-					sm->dma.ofragsz <<= 1;
-				} else {
-					printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, 
-					       sm->mode_rx->name, sm->mode_tx->name);
-					sm->mode_tx = NULL;
-					sm->mode_rx = NULL;
-					return -EINVAL;
-				}
-				return 0;
-			}
-		}
-	}
-	return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int sbcfdx_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, 
-			struct hdlcdrv_ioctl *hi, int cmd)
-{
-	if (cmd != SIOCDEVPRIVATE)
-		return -ENOIOCTLCMD;
-
-	if (hi->cmd == HDLCDRVCTL_MODEMPARMASK)
-		return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | 
-			HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_DMA2 | HDLCDRV_PARMASK_SERIOBASE | 
-			HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE;
-
-	return sbc_ioctl(dev, sm, ifr, hi, cmd);
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct hardware_info sm_hw_sbcfdx = {
-	"sbcfdx", sizeof(struct sc_state_sbc), 
-	sbcfdx_open, sbcfdx_close, sbcfdx_ioctl, sbcfdx_sethw
-};
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/net/hamradio/soundmodem/sm_wss.c b/drivers/net/hamradio/soundmodem/sm_wss.c
--- a/drivers/net/hamradio/soundmodem/sm_wss.c	Wed Nov 27 14:36:29 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,968 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	sm_wss.c  -- soundcard radio modem driver, WSS (half duplex) driver
- *
- *	Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/soundmodem.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "sm.h"
-#include "smdma.h"
-
-/* --------------------------------------------------------------------- */
-
-/*
- * currently this module is supposed to support both module styles, i.e.
- * the old one present up to about 2.1.9, and the new one functioning
- * starting with 2.1.21. The reason is I have a kit allowing to compile
- * this module also under 2.0.x which was requested by several people.
- * This will go in 2.2
- */
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= 0x20100
-#include <asm/uaccess.h>
-#else
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-#undef put_user
-#undef get_user
-
-#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
-#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
-
-static inline int copy_from_user(void *to, const void *from, unsigned long n)
-{
-        int i = verify_area(VERIFY_READ, from, n);
-        if (i)
-                return i;
-        memcpy_fromfs(to, from, n);
-        return 0;
-}
-
-static inline int copy_to_user(void *to, const void *from, unsigned long n)
-{
-        int i = verify_area(VERIFY_WRITE, to, n);
-        if (i)
-                return i;
-        memcpy_tofs(to, from, n);
-        return 0;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-struct sc_state_wss {
-	unsigned char revwss, revid, revv, revcid;
-	unsigned char fmt[2];
-	unsigned char crystal;
-};
-
-#define SCSTATE ((struct sc_state_wss *)(&sm->hw))
-
-/* --------------------------------------------------------------------- */
-
-#define WSS_CONFIG(iobase)       (iobase+0)
-#define WSS_STATUS(iobase)       (iobase+3)
-#define WSS_CODEC_IA(iobase)     (iobase+4)
-#define WSS_CODEC_ID(iobase)     (iobase+5)
-#define WSS_CODEC_STATUS(iobase) (iobase+6)
-#define WSS_CODEC_DATA(iobase)   (iobase+7)
-
-#define WSS_EXTENT   8
-
-#define CS423X_HOTFIX
-
-/* --------------------------------------------------------------------- */
-
-static void write_codec(struct net_device *dev, unsigned char idx,
-			unsigned char data)
-{
-	int timeout = 900000;
-
-	/* wait until codec ready */
-	while (timeout > 0 && inb(WSS_CODEC_IA(dev->base_addr)) & 0x80)
-		timeout--;
-	outb(idx, WSS_CODEC_IA(dev->base_addr));
-	outb(data, WSS_CODEC_ID(dev->base_addr));
-}
-
-
-/* --------------------------------------------------------------------- */
-
-static unsigned char read_codec(struct net_device *dev, unsigned char idx)
-{
-	int timeout = 900000;
-
-	/* wait until codec ready */
-	while (timeout > 0 && inb(WSS_CODEC_IA(dev->base_addr)) & 0x80)
-		timeout--;
-	outb(idx & 0x1f, WSS_CODEC_IA(dev->base_addr));
-	return inb(WSS_CODEC_ID(dev->base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-extern void inline wss_ack_int(struct net_device *dev)
-{
-	outb(0, WSS_CODEC_STATUS(dev->base_addr));
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_srate_tab[16] = {
-	8000, 5510, 16000, 11025, 27420, 18900, 32000, 22050,
-	-1, 37800, -1, 44100, 48000, 33075, 9600, 6620
-};
-
-static int wss_srate_index(int srate)
-{
-	int i;
-
-	for (i = 0; i < (sizeof(wss_srate_tab)/sizeof(wss_srate_tab[0])); i++)
-		if (srate == wss_srate_tab[i] && wss_srate_tab[i] > 0)
-			return i;
-	return -1;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_set_codec_fmt(struct net_device *dev, struct sm_state *sm, unsigned char fmt, 
-			     unsigned char fmt2, char fdx, char fullcalib)
-{
-	unsigned long time;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	/* Clock and data format register */
-	write_codec(dev, 0x48, fmt);
-	if (SCSTATE->crystal) {
-		write_codec(dev, 0x5c, fmt2 & 0xf0);
-		/* MCE and interface config reg */	
-		write_codec(dev, 0x49, (fdx ? 0 : 0x4) | (fullcalib ? 0x18 : 0));
-	} else 
-		/* MCE and interface config reg */
-		write_codec(dev, 0x49, fdx ? 0x8 : 0xc);
-	outb(0xb, WSS_CODEC_IA(dev->base_addr)); /* leave MCE */
-	if (SCSTATE->crystal && !fullcalib) {
-		restore_flags(flags);
-		return 0;
-	}
-	/*
-	 * wait for ACI start
-	 */
-	time = 1000;
-	while (!(read_codec(dev, 0x0b) & 0x20))
-		if (!(--time)) {
-			printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n", 
-			       sm_drvname);
-			restore_flags(flags);
-			return -1;
-		}
-	/*
-	 * wait for ACI end
-	 */
-	sti();
-	time = jiffies + HZ/4;
-	while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0));
-	restore_flags(flags);
-	if ((signed)(jiffies - time) >= 0) {
-		printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n", 
-		       sm_drvname);
-		return -1;
-	}
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_init_codec(struct net_device *dev, struct sm_state *sm, char fdx, 
-			  unsigned char src_l, unsigned char src_r, 
-			  int igain_l, int igain_r,
-			  int ogain_l, int ogain_r)
-{
-	unsigned char tmp, reg0, reg1, reg6, reg7;
-	static const signed char irqtab[16] = 
-	{ -1, -1, 0x10, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20, -1, -1,
-		  -1, -1 };
-	static const signed char dmatab[4] = { 1, 2, -1, 3 };
-	
-	tmp = inb(WSS_STATUS(dev->base_addr));
-	if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x00 && 
-	    (tmp & 0x3f) != 0x0f) {
-		printk(KERN_WARNING "sm: WSS card id register not found, "
-		       "address 0x%lx, ID register 0x%02x\n", 
-		       dev->base_addr, (int)tmp);
-		/* return -1; */
-		SCSTATE->revwss = 0;
-	} else {
-		if ((tmp & 0x80) && ((dev->dma == 0) || 
-				     ((dev->irq >= 8) && (dev->irq != 9)))) {
-			printk(KERN_ERR "%s: WSS: DMA0 and/or IRQ8..IRQ15 "
-			       "(except IRQ9) cannot be used on an 8bit "
-			       "card\n", sm_drvname);
-			return -1;
-		}		
-		if (dev->irq > 15 || irqtab[dev->irq] == -1) {
-			printk(KERN_ERR "%s: WSS: invalid interrupt %d\n", 
-			       sm_drvname, (int)dev->irq);
-			return -1;
-		}
-		if (dev->dma > 3 || dmatab[dev->dma] == -1) {
-			printk(KERN_ERR "%s: WSS: invalid dma channel %d\n", 
-			       sm_drvname, (int)dev->dma);
-			return -1;
-		}
-		tmp = irqtab[dev->irq] | dmatab[dev->dma];
-		/* irq probe */
-		outb((tmp & 0x38) | 0x40, WSS_CONFIG(dev->base_addr));
-		if (!(inb(WSS_STATUS(dev->base_addr)) & 0x40)) {
-			outb(0, WSS_CONFIG(dev->base_addr));
-			printk(KERN_ERR "%s: WSS: IRQ%d is not free!\n", 
-			       sm_drvname, dev->irq);
-		}
-		outb(tmp, WSS_CONFIG(dev->base_addr));
-		SCSTATE->revwss = inb(WSS_STATUS(dev->base_addr)) & 0x3f;
-	}
-	/*
-	 * initialize the codec
-	 */
-	if (igain_l < 0)
-		igain_l = 0;
-	if (igain_r < 0)
-		igain_r = 0;
-	if (ogain_l > 0)
-		ogain_l = 0;
-	if (ogain_r > 0)
-		ogain_r = 0;
-	reg0 = (src_l << 6) & 0xc0;
-	reg1 = (src_r << 6) & 0xc0;
-	if (reg0 == 0x80 && igain_l >= 20) {
-		reg0 |= 0x20;
-		igain_l -= 20;
-	}
-	if (reg1 == 0x80 && igain_r >= 20) {
-		reg1 |= 0x20;
-		igain_r -= 20;
-	}
-	if (igain_l > 23)
-		igain_l = 23;
-	if (igain_r > 23)
-		igain_r = 23;
-	reg0 |= igain_l * 2 / 3;
-	reg1 |= igain_r * 2 / 3;
-	reg6 = (ogain_l < -95) ? 0x80 : (ogain_l * (-2) / 3);
-	reg7 = (ogain_r < -95) ? 0x80 : (ogain_r * (-2) / 3);
-	write_codec(dev, 9, 0);
-	write_codec(dev, 0, 0x45);
-	if (read_codec(dev, 0) != 0x45)
-		goto codec_err;
-	write_codec(dev, 0, 0xaa);
-	if (read_codec(dev, 0) != 0xaa)
-		goto codec_err;
-	write_codec(dev, 12, 0x40); /* enable MODE2 */
-	write_codec(dev, 16, 0);
-	write_codec(dev, 0, 0x45);
-	SCSTATE->crystal = (read_codec(dev, 16) != 0x45);
-	write_codec(dev, 0, 0xaa);
-	SCSTATE->crystal &= (read_codec(dev, 16) != 0xaa);
-	if (SCSTATE->crystal) {
-		SCSTATE->revcid = read_codec(dev, 0x19);
-		SCSTATE->revv = (SCSTATE->revcid >> 5) & 7;
-		SCSTATE->revcid &= 7;
-		write_codec(dev, 0x10, 0x80); /* maximum output level */
-		write_codec(dev, 0x11, 0x02); /* xtal enable and no HPF */
-		write_codec(dev, 0x12, 0x80); /* left line input control */
-		write_codec(dev, 0x13, 0x80); /* right line input control */
-		write_codec(dev, 0x16, 0); /* disable alternative freq sel */
-		write_codec(dev, 0x1a, 0xe0); /* mono IO disable */
-		write_codec(dev, 0x1b, 0x00); /* left out no att */
-		write_codec(dev, 0x1d, 0x00); /* right out no att */
-	}
-
-	if (wss_set_codec_fmt(dev, sm, SCSTATE->fmt[0], SCSTATE->fmt[0], fdx, 1))
-		goto codec_err;
-
-        write_codec(dev, 0, reg0); /* left input control */
-        write_codec(dev, 1, reg1); /* right input control */
-        write_codec(dev, 2, 0x80); /* left aux#1 input control */
-        write_codec(dev, 3, 0x80); /* right aux#1 input control */
-        write_codec(dev, 4, 0x80); /* left aux#2 input control */
-        write_codec(dev, 5, 0x80); /* right aux#2 input control */
-        write_codec(dev, 6, reg6); /* left dac control */
-        write_codec(dev, 7, reg7); /* right dac control */
-        write_codec(dev, 0xa, 0x2); /* pin control register */
-        write_codec(dev, 0xd, 0x0); /* digital mix control */
-	SCSTATE->revid = read_codec(dev, 0xc) & 0xf;
-	/*
-	 * print revisions
-	 */
-	if (SCSTATE->crystal) 
-		printk(KERN_INFO "%s: Crystal CODEC ID %d, Chip revision %d, "
-		       " Chip ID %d\n", sm_drvname, (int)SCSTATE->revid,
-		       (int)SCSTATE->revv, (int)SCSTATE->revcid);
-	else
-		printk(KERN_INFO "%s: WSS revision %d, CODEC revision %d\n", 
-		       sm_drvname, (int)SCSTATE->revwss, 
-		       (int)SCSTATE->revid);
-	return 0;
- codec_err:
-	outb(0, WSS_CONFIG(dev->base_addr));
-	printk(KERN_ERR "%s: no WSS soundcard found at address 0x%lx\n", 
-	       sm_drvname, dev->base_addr);
-	return -1;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void setup_dma_wss(struct net_device *dev, struct sm_state *sm, int send)
-{
-        unsigned long flags;
-        static const unsigned char codecmode[2] = { 0x0e, 0x0d };
-	unsigned char oldcodecmode;
-	long abrt;
-	unsigned char fmt;
-	unsigned int numsamps;
-
-	send = !!send;
-	fmt = SCSTATE->fmt[send];
-	save_flags(flags);
-        cli();
-	/*
-	 * perform the final DMA sequence to disable the codec request
-	 */
-	oldcodecmode = read_codec(dev, 9);
-        write_codec(dev, 9, 0xc); /* disable codec */
-	wss_ack_int(dev);
-	if (read_codec(dev, 11) & 0x10) {
-		dma_setup(sm, oldcodecmode & 1, dev->dma);
-		abrt = 0;
-		while ((read_codec(dev, 11) & 0x10) || ((++abrt) >= 0x10000));
-	}
-#ifdef CS423X_HOTFIX
-	if (read_codec(dev, 0x8) != fmt || SCSTATE->crystal)
-		wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0);
-#else /* CS423X_HOTFIX */
-	if (read_codec(dev, 0x8) != fmt)
-		wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0);
-#endif /* CS423X_HOTFIX */
-	numsamps = dma_setup(sm, send, dev->dma) - 1;
-	write_codec(dev, 15, numsamps & 0xff);
-	write_codec(dev, 14, numsamps >> 8);
-	write_codec(dev, 9, codecmode[send]);
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wss_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	struct sm_state *sm = (struct sm_state *)dev->priv;
-	unsigned int curfrag;
-	unsigned int nums;
-
-	if (!dev || !sm || !sm->mode_rx || !sm->mode_tx || 
-	    sm->hdrv.magic != HDLCDRV_MAGIC)
-		return;
-	cli();
-	wss_ack_int(dev);
-	disable_dma(dev->dma);
-	clear_dma_ff(dev->dma);
-	nums = dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag) - 1;
-	write_codec(dev, 15, nums  & 0xff);
-	write_codec(dev, 14, nums >> 8);
-	enable_dma(dev->dma);
-	sm_int_freq(sm);
-	sti();
-	if (sm->dma.ptt_cnt <= 0) {
-		dma_receive(sm, curfrag);
-		hdlcdrv_arbitrate(dev, &sm->hdrv);
-		if (hdlcdrv_ptt(&sm->hdrv)) {
-			/* starting to transmit */
-			disable_dma(dev->dma);
-			hdlcdrv_transmitter(dev, &sm->hdrv); /* prefill HDLC buffer */
-			dma_start_transmit(sm);
-			setup_dma_wss(dev, sm, 1);
-			dma_transmit(sm);
-		}
-	} else if (dma_end_transmit(sm, curfrag)) {
-		/* stopping transmission */
-		disable_dma(dev->dma);
-		dma_init_receive(sm);
-		setup_dma_wss(dev, sm, 0);
-        } else
-		dma_transmit(sm);
-	sm_output_status(sm);
-	hdlcdrv_transmitter(dev, &sm->hdrv);
-	hdlcdrv_receiver(dev, &sm->hdrv);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_open(struct net_device *dev, struct sm_state *sm) 
-{
-	unsigned int dmasz, u;
-
-	if (sizeof(sm->m) < sizeof(struct sc_state_wss)) {
-		printk(KERN_ERR "sm wss: wss state too big: %d > %d\n", 
-		       sizeof(struct sc_state_wss), sizeof(sm->m));
-		return -ENODEV;
-	}
-	if (!dev || !sm || !sm->mode_rx || !sm->mode_tx)
-		return -ENXIO;
-	if (dev->base_addr <= 0 || dev->base_addr > 0x1000-WSS_EXTENT || 
-	    dev->irq < 2 || dev->irq > 15 || dev->dma > 3)
-		return -ENXIO;
-	if (check_region(dev->base_addr, WSS_EXTENT))
-		return -EACCES;
-	/*
-	 * check if a card is available
-	 */
-	if (wss_init_codec(dev, sm, 0, 1, 1, 0, 0, -45, -45))
-		return -ENODEV;
-	/*
-	 * initialize some variables
-	 */
-	dma_init_receive(sm);
-	dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz;
-	u = NUM_FRAGMENTS * sm->dma.ofragsz;
-	if (u > dmasz)
-		dmasz = u;
-	if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA)))
-		return -ENOMEM;
-	dma_init_transmit(sm);
-	dma_init_receive(sm);
-
-	memset(&sm->m, 0, sizeof(sm->m));
-	memset(&sm->d, 0, sizeof(sm->d));
-	if (sm->mode_tx->init)
-		sm->mode_tx->init(sm);
-	if (sm->mode_rx->init)
-		sm->mode_rx->init(sm);
-
-	if (request_dma(dev->dma, sm->hwdrv->hw_name)) {
-		kfree(sm->dma.obuf);
-		return -EBUSY;
-	}
-	if (request_irq(dev->irq, wss_interrupt, SA_INTERRUPT, 
-			sm->hwdrv->hw_name, dev)) {
-		free_dma(dev->dma);
-		kfree(sm->dma.obuf);
-		return -EBUSY;
-	}
-	request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name);
-	setup_dma_wss(dev, sm, 0);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_close(struct net_device *dev, struct sm_state *sm) 
-{
-	if (!dev || !sm)
-		return -EINVAL;
-	/*
-	 * disable interrupts
-	 */
-	disable_dma(dev->dma);
-        write_codec(dev, 9, 0xc); /* disable codec */
-	free_irq(dev->irq, dev);	
-	free_dma(dev->dma);	
-	release_region(dev->base_addr, WSS_EXTENT);
-	kfree(sm->dma.obuf);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_sethw(struct net_device *dev, struct sm_state *sm, char *mode)
-{
-	char *cp = strchr(mode, '.');
-	const struct modem_tx_info **mtp = sm_modem_tx_table;
-	const struct modem_rx_info **mrp;
-	int i, j;
-
-	if (!strcmp(mode, "off")) {
-		sm->mode_tx = NULL;
-		sm->mode_rx = NULL;
-		return 0;
-	}
-	if (cp)
-		*cp++ = '\0';
-	else
-		cp = mode;
-	for (; *mtp; mtp++) {
-		if ((*mtp)->loc_storage > sizeof(sm->m)) {
-			printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n",
-			       sm_drvname, (*mtp)->name, (*mtp)->loc_storage);
-			continue;
-		}
-		if (!(*mtp)->name || strcmp((*mtp)->name, mode))
-			continue;
-		if ((i = wss_srate_index((*mtp)->srate)) < 0) 
-			continue;
-		for (mrp = sm_modem_rx_table; *mrp; mrp++) {
-			if ((*mrp)->loc_storage > sizeof(sm->d)) {
-				printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n",
-				       sm_drvname, (*mrp)->name, (*mrp)->loc_storage);
-				continue;
-			}
-			if ((*mrp)->name && !strcmp((*mrp)->name, cp) &&
-			    ((j = wss_srate_index((*mrp)->srate)) >= 0)) {
-				sm->mode_tx = *mtp;
-				sm->mode_rx = *mrp;
-				SCSTATE->fmt[0] = j;
-				SCSTATE->fmt[1] = i;
-				sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100;
-				sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100;
-				if (sm->dma.ifragsz < sm->mode_rx->overlap)
-					sm->dma.ifragsz = sm->mode_rx->overlap;
-				/* prefer same data format if possible to minimize switching times */
-				sm->dma.i16bit = sm->dma.o16bit = 2;
-				if (sm->mode_rx->srate == sm->mode_tx->srate) {
-					if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_s16)
-						sm->dma.i16bit = sm->dma.o16bit = 1;
-					else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_u8)
-						sm->dma.i16bit = sm->dma.o16bit = 0;
-				}
-				if (sm->dma.i16bit == 2) {
-					if (sm->mode_rx->demodulator_s16)
-						sm->dma.i16bit = 1;
-					else if (sm->mode_rx->demodulator_u8)
-						sm->dma.i16bit = 0;
-				}
-				if (sm->dma.o16bit == 2) {
-					if (sm->mode_tx->modulator_s16)
-						sm->dma.o16bit = 1;
-					else if (sm->mode_tx->modulator_u8)
-						sm->dma.o16bit = 0;
-				}
-				if (sm->dma.i16bit == 2 ||  sm->dma.o16bit == 2) {
-					printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, 
-					       sm->mode_rx->name, sm->mode_tx->name);
-					sm->mode_tx = NULL;
-					sm->mode_rx = NULL;
-					return -EINVAL;
-				}
-#ifdef __BIG_ENDIAN
-				/* big endian 16bit only works on crystal cards... */
-				if (sm->dma.i16bit) {
-					SCSTATE->fmt[0] |= 0xc0;
-					sm->dma.ifragsz <<= 1;
-				}
-				if (sm->dma.o16bit) {
-					SCSTATE->fmt[1] |= 0xc0;
-					sm->dma.ofragsz <<= 1;
-				}
-#else /* __BIG_ENDIAN */
-				if (sm->dma.i16bit) {
-					SCSTATE->fmt[0] |= 0x40;
-					sm->dma.ifragsz <<= 1;
-				}
-				if (sm->dma.o16bit) {
-					SCSTATE->fmt[1] |= 0x40;
-					sm->dma.ofragsz <<= 1;
-				}
-#endif /* __BIG_ENDIAN */
-				return 0;
-			}
-		}
-	}
-	return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wss_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, 
-		     struct hdlcdrv_ioctl *hi, int cmd)
-{
-	struct sm_ioctl bi;
-	int i;
-	
-	if (cmd != SIOCDEVPRIVATE)
-		return -ENOIOCTLCMD;
-
-	if (hi->cmd == HDLCDRVCTL_MODEMPARMASK)
-		return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | 
-			HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_SERIOBASE | 
-			HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE;
-
-	if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi)))
-		return -EFAULT;
-
-	switch (bi.cmd) {
-	default:
-		return -ENOIOCTLCMD;
-
-	case SMCTL_GETMIXER:
-		i = 0;
-		bi.data.mix.sample_rate = sm->mode_rx->srate;
-		bi.data.mix.bit_rate = sm->hdrv.par.bitrate;
-		bi.data.mix.mixer_type = SCSTATE->crystal ? 
-			SM_MIXER_CRYSTAL : SM_MIXER_AD1848;
-		if (((SCSTATE->crystal ? 0x2c0c20fflu: 0x20fflu) 
-		     >> bi.data.mix.reg) & 1) {
-			bi.data.mix.data = read_codec(dev, bi.data.mix.reg);
-			i = 1;
-		}
-		if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-			return -EFAULT;
-		return i;
-
-	case SMCTL_SETMIXER:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EACCES;
-		if ((bi.data.mix.mixer_type != SM_MIXER_CRYSTAL || 
-		     !SCSTATE->crystal) &&
-		    (bi.data.mix.mixer_type != SM_MIXER_AD1848 ||
-		     bi.data.mix.reg >= 0x10))
-			return -EINVAL;
-		if (!((0x2c0c20fflu >> bi.data.mix.reg) & 1))
-			return -EACCES;
-		write_codec(dev, bi.data.mix.reg, bi.data.mix.data);
-		return 0;
-		
-	}
-	if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi)))
-		return -EFAULT;
-	return 0;
-
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct hardware_info sm_hw_wss = {
-	"wss", sizeof(struct sc_state_wss), 
-	wss_open, wss_close, wss_ioctl, wss_sethw
-};
-
-/* --------------------------------------------------------------------- */
-
-static void setup_fdx_dma_wss(struct net_device *dev, struct sm_state *sm)
-{
-        unsigned long flags;
-	unsigned char oldcodecmode, codecdma;
-	long abrt;
-	unsigned int osamps, isamps;
-	
-        save_flags(flags);
-        cli();
-	/*
-	 * perform the final DMA sequence to disable the codec request
-	 */
-	oldcodecmode = read_codec(dev, 9);
-        write_codec(dev, 9, 0); /* disable codec DMA */
-	wss_ack_int(dev);
-	if ((codecdma = read_codec(dev, 11)) & 0x10) {
-		dma_setup(sm, 1, dev->dma);
-		dma_setup(sm, 0, sm->hdrv.ptt_out.dma2);
-		abrt = 0;
-		while (((codecdma = read_codec(dev, 11)) & 0x10) || ((++abrt) >= 0x10000));
-	}
-       	wss_set_codec_fmt(dev, sm, SCSTATE->fmt[1], SCSTATE->fmt[0], 1, 1);
-	osamps = dma_setup(sm, 1, dev->dma) - 1;
-	isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1;
-	write_codec(dev, 15, osamps & 0xff);
-	write_codec(dev, 14, osamps >> 8);
-	if (SCSTATE->crystal) {
-		write_codec(dev, 31, isamps & 0xff);
-		write_codec(dev, 30, isamps >> 8);
-	}
-	write_codec(dev, 9, 3);
-        restore_flags(flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-static void wssfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	struct sm_state *sm = (struct sm_state *)dev->priv;
-	unsigned long flags;
-	unsigned char cry_int_src;
-	unsigned icfrag, ocfrag, isamps, osamps;
-
-	if (!dev || !sm || !sm->mode_rx || !sm->mode_tx || 
-	    sm->hdrv.magic != HDLCDRV_MAGIC)
-		return;
-	save_flags(flags);
-	cli();
-	if (SCSTATE->crystal) { 
-		/* Crystal has an essentially different interrupt handler! */
-		cry_int_src = read_codec(dev, 0x18);
-		wss_ack_int(dev);
-		if (cry_int_src & 0x10) {       /* playback interrupt */
-			disable_dma(dev->dma);
-			clear_dma_ff(dev->dma);
-			osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1;
-			write_codec(dev, 15, osamps & 0xff);
-			write_codec(dev, 14, osamps >> 8);
-			enable_dma(dev->dma);
-		}
-		if (cry_int_src & 0x20) {       /* capture interrupt */
-			disable_dma(sm->hdrv.ptt_out.dma2);
-			clear_dma_ff(sm->hdrv.ptt_out.dma2);
-			isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1;
-			write_codec(dev, 31, isamps & 0xff);
-			write_codec(dev, 30, isamps >> 8);
-			enable_dma(sm->hdrv.ptt_out.dma2);
-		}
-		restore_flags(flags);
-		sm_int_freq(sm);
-		sti();
-		if (cry_int_src & 0x10) {
-			if (dma_end_transmit(sm, ocfrag))
-				dma_clear_transmit(sm);
-			dma_transmit(sm);
-		}
-		if (cry_int_src & 0x20) { 
-			dma_receive(sm, icfrag);
-			hdlcdrv_arbitrate(dev, &sm->hdrv);
-		}
-		sm_output_status(sm);
-		hdlcdrv_transmitter(dev, &sm->hdrv);
-		hdlcdrv_receiver(dev, &sm->hdrv);
-		return;
-	}
-	wss_ack_int(dev);
-	disable_dma(dev->dma);
-	disable_dma(sm->hdrv.ptt_out.dma2);
-	clear_dma_ff(dev->dma);
-	clear_dma_ff(sm->hdrv.ptt_out.dma2);
-	osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1;
-	isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1;
-	write_codec(dev, 15, osamps & 0xff);
-	write_codec(dev, 14, osamps >> 8);
-	if (SCSTATE->crystal) {
-		write_codec(dev, 31, isamps & 0xff);
-		write_codec(dev, 30, isamps >> 8);
-	}
-	enable_dma(dev->dma);
-	enable_dma(sm->hdrv.ptt_out.dma2);
-	restore_flags(flags);
-	sm_int_freq(sm);
-	sti();
-	if (dma_end_transmit(sm, ocfrag))
-		dma_clear_transmit(sm);
-	dma_transmit(sm);
-	dma_receive(sm, icfrag);
-	hdlcdrv_arbitrate(dev, &sm->hdrv);
-	sm_output_status(sm);
-	hdlcdrv_transmitter(dev, &sm->hdrv);
-	hdlcdrv_receiver(dev, &sm->hdrv);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wssfdx_open(struct net_device *dev, struct sm_state *sm) 
-{
-	if (!dev || !sm || !sm->mode_rx || !sm->mode_tx)
-		return -ENXIO;
-	if (dev->base_addr <= 0 || dev->base_addr > 0x1000-WSS_EXTENT || 
-	    dev->irq < 2 || dev->irq > 15 || dev->dma > 3)
-		return -ENXIO;
-	if (check_region(dev->base_addr, WSS_EXTENT))
-		return -EACCES;
-	/*
-	 * check if a card is available
-	 */
-	if (wss_init_codec(dev, sm, 1, 1, 1, 0, 0, -45, -45))
-		return -ENODEV;
-	/*
-	 * initialize some variables
-	 */
-	if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA)))
-		return -ENOMEM;
-	if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) {
-		kfree(sm->dma.ibuf);
-		return -ENOMEM;
-	}
-	dma_init_transmit(sm);
-	dma_init_receive(sm);
-
-	memset(&sm->m, 0, sizeof(sm->m));
-	memset(&sm->d, 0, sizeof(sm->d));
-	if (sm->mode_tx->init)
-		sm->mode_tx->init(sm);
-	if (sm->mode_rx->init)
-		sm->mode_rx->init(sm);
-
-	if (request_dma(dev->dma, sm->hwdrv->hw_name)) {
-		kfree(sm->dma.ibuf);
-		kfree(sm->dma.obuf);
-		return -EBUSY;
-	}
-	if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) {
-		kfree(sm->dma.ibuf);
-		kfree(sm->dma.obuf);
-		free_dma(dev->dma);
-		return -EBUSY;
-	}
-	if (request_irq(dev->irq, wssfdx_interrupt, SA_INTERRUPT, 
-			sm->hwdrv->hw_name, dev)) {
-		kfree(sm->dma.ibuf);
-		kfree(sm->dma.obuf);
-		free_dma(dev->dma);
-		free_dma(sm->hdrv.ptt_out.dma2);
-		return -EBUSY;
-	}
-	request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name);
-	setup_fdx_dma_wss(dev, sm);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wssfdx_close(struct net_device *dev, struct sm_state *sm) 
-{
-	if (!dev || !sm)
-		return -EINVAL;
-	/*
-	 * disable interrupts
-	 */
-	disable_dma(dev->dma);
-	disable_dma(sm->hdrv.ptt_out.dma2);
-        write_codec(dev, 9, 0xc); /* disable codec */
-	free_irq(dev->irq, dev);	
-	free_dma(dev->dma);	
-	free_dma(sm->hdrv.ptt_out.dma2);	
-	release_region(dev->base_addr, WSS_EXTENT);
-	kfree(sm->dma.ibuf);
-	kfree(sm->dma.obuf);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wssfdx_sethw(struct net_device *dev, struct sm_state *sm, char *mode)
-{
-	char *cp = strchr(mode, '.');
-	const struct modem_tx_info **mtp = sm_modem_tx_table;
-	const struct modem_rx_info **mrp;
-	int i;
-
-	if (!strcmp(mode, "off")) {
-		sm->mode_tx = NULL;
-		sm->mode_rx = NULL;
-		return 0;
-	}
-	if (cp)
-		*cp++ = '\0';
-	else
-		cp = mode;
-	for (; *mtp; mtp++) {
-		if ((*mtp)->loc_storage > sizeof(sm->m)) {
-			printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n",
-			       sm_drvname, (*mtp)->name, (*mtp)->loc_storage);
-			continue;
-		}
-		if (!(*mtp)->name || strcmp((*mtp)->name, mode))
-			continue;
-		if ((i = wss_srate_index((*mtp)->srate)) < 0) 
-			continue;
-		for (mrp = sm_modem_rx_table; *mrp; mrp++) {
-			if ((*mrp)->loc_storage > sizeof(sm->d)) {
-				printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n",
-				       sm_drvname, (*mrp)->name, (*mrp)->loc_storage);
-				continue;
-			}
-			if ((*mrp)->name && !strcmp((*mrp)->name, cp) &&
-			    (*mtp)->srate == (*mrp)->srate) {
-				sm->mode_tx = *mtp;
-				sm->mode_rx = *mrp;
-				SCSTATE->fmt[0] = SCSTATE->fmt[1] = i;
-				sm->dma.ifragsz = sm->dma.ofragsz = (sm->mode_rx->srate + 50)/100;
-				if (sm->dma.ifragsz < sm->mode_rx->overlap)
-					sm->dma.ifragsz = sm->mode_rx->overlap;
-				sm->dma.i16bit = sm->dma.o16bit = 2;
-				if (sm->mode_rx->demodulator_s16) {
-					sm->dma.i16bit = 1;
-					sm->dma.ifragsz <<= 1;
-#ifdef __BIG_ENDIAN    /* big endian 16bit only works on crystal cards... */
-					SCSTATE->fmt[0] |= 0xc0;
-#else /* __BIG_ENDIAN */
-					SCSTATE->fmt[0] |= 0x40;
-#endif /* __BIG_ENDIAN */
-				} else if (sm->mode_rx->demodulator_u8)
-					sm->dma.i16bit = 0;
-				if (sm->mode_tx->modulator_s16) {
-					sm->dma.o16bit = 1;
-					sm->dma.ofragsz <<= 1;
-#ifdef __BIG_ENDIAN    /* big endian 16bit only works on crystal cards... */
-					SCSTATE->fmt[1] |= 0xc0;
-#else /* __BIG_ENDIAN */
-					SCSTATE->fmt[1] |= 0x40;
-#endif /* __BIG_ENDIAN */
-				} else if (sm->mode_tx->modulator_u8)
-					sm->dma.o16bit = 0;
-				if (sm->dma.i16bit == 2 ||  sm->dma.o16bit == 2) {
-					printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, 
-					       sm->mode_rx->name, sm->mode_tx->name);
-					sm->mode_tx = NULL;
-					sm->mode_rx = NULL;
-					return -EINVAL;
-				}
-				return 0;
-			}
-		}
-	}
-	return -EINVAL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wssfdx_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, 
-			struct hdlcdrv_ioctl *hi, int cmd)
-{
-	if (cmd != SIOCDEVPRIVATE)
-		return -ENOIOCTLCMD;
-
-	if (hi->cmd == HDLCDRVCTL_MODEMPARMASK)
-		return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ |
-			HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_DMA2 |
-			HDLCDRV_PARMASK_SERIOBASE | HDLCDRV_PARMASK_PARIOBASE |
-			HDLCDRV_PARMASK_MIDIIOBASE;
-
-	return wss_ioctl(dev, sm, ifr, hi, cmd);
-}
-
-/* --------------------------------------------------------------------- */
-
-const struct hardware_info sm_hw_wssfdx = {
-	"wssfdx", sizeof(struct sc_state_wss), 
-	wssfdx_open, wssfdx_close, wssfdx_ioctl, wssfdx_sethw
-};
-
-/* --------------------------------------------------------------------- */
-
-#undef SCSTATE
diff -Nru a/drivers/net/hamradio/soundmodem/smdma.h b/drivers/net/hamradio/soundmodem/smdma.h
--- a/drivers/net/hamradio/soundmodem/smdma.h	Wed Nov 27 14:36:27 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,217 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	smdma.h  --  soundcard radio modem driver dma buffer routines.
- *
- *	Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	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.
- *
- *  Please note that the GPL allows you to use the driver, NOT the radio.
- *  In order to use the radio, you need a license from the communications
- *  authority of your country.
- *
- */
-
-#ifndef _SMDMA_H
-#define _SMDMA_H
-
-/* ---------------------------------------------------------------------- */
-
-#include "sm.h"
-
-/* ---------------------------------------------------------------------- */
-
-#define DMA_MODE_AUTOINIT      0x10
-#define NUM_FRAGMENTS          4
-
-/*
- * NOTE: make sure that hdlcdrv_hdlcbuffer contains enough space
- * for the modulator to fill the whole DMA buffer without underrun
- * at the highest possible baud rate, otherwise the TX state machine will
- * not work correctly. That is (9k6 FSK): HDLCDRV_HDLCBUFFER > 6*NUM_FRAGMENTS
- */ 
-
-/* --------------------------------------------------------------------- */
-/*
- * ===================== DMA buffer management ===========================
- */
-
-/*
- * returns the number of samples per fragment
- */
-static __inline__ unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr)
-{
-	if (send) {
-		disable_dma(dmanr);
-		clear_dma_ff(dmanr);
-		set_dma_mode(dmanr, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
-		set_dma_addr(dmanr, virt_to_bus(sm->dma.obuf));
-		set_dma_count(dmanr, sm->dma.ofragsz * NUM_FRAGMENTS);
-		enable_dma(dmanr);
-		if (sm->dma.o16bit)
-			return sm->dma.ofragsz/2;
-		return sm->dma.ofragsz;
-	} else {
-		disable_dma(dmanr);
-		clear_dma_ff(dmanr);
-		set_dma_mode(dmanr, DMA_MODE_READ | DMA_MODE_AUTOINIT);
-		set_dma_addr(dmanr, virt_to_bus(sm->dma.ibuf));
-		set_dma_count(dmanr, sm->dma.ifragsz * NUM_FRAGMENTS);
-		enable_dma(dmanr);
-		if (sm->dma.i16bit)
-			return sm->dma.ifragsz/2;
-		return sm->dma.ifragsz;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr,
-				       unsigned int *curfrag)
-{
-	unsigned int dmaptr, sz, frg, offs;
-	
-	dmaptr = get_dma_residue(dmanr);
-	if (send) {
-		sz = sm->dma.ofragsz * NUM_FRAGMENTS;
-		if (dmaptr == 0 || dmaptr > sz)
-			dmaptr = sz;
-		dmaptr--;
-		frg = dmaptr / sm->dma.ofragsz;
-		offs = (dmaptr % sm->dma.ofragsz) + 1;
-		*curfrag = NUM_FRAGMENTS - 1 - frg;
-#ifdef SM_DEBUG
-		if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue)
-			sm->debug_vals.dma_residue = offs;
-#endif /* SM_DEBUG */
-		if (sm->dma.o16bit)
-			return offs/2;
-		return offs;
-	} else {
-		sz = sm->dma.ifragsz * NUM_FRAGMENTS;
-		if (dmaptr == 0 || dmaptr > sz)
-			dmaptr = sz;
-		dmaptr--;
-		frg = dmaptr / sm->dma.ifragsz;
-		offs = (dmaptr % sm->dma.ifragsz) + 1;
-		*curfrag = NUM_FRAGMENTS - 1 - frg;
-#ifdef SM_DEBUG
-		if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue)
-			sm->debug_vals.dma_residue = offs;
-#endif /* SM_DEBUG */
-		if (sm->dma.i16bit)
-			return offs/2;
-		return offs;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ int dma_end_transmit(struct sm_state *sm, unsigned int curfrag)
-{
-	unsigned int diff = (NUM_FRAGMENTS + curfrag - sm->dma.ofragptr) % NUM_FRAGMENTS;
-
-	sm->dma.ofragptr = curfrag;
-	if (sm->dma.ptt_cnt <= 0) {
-		sm->dma.ptt_cnt = 0;
-		return 0;
-	}
-	sm->dma.ptt_cnt -= diff;
-	if (sm->dma.ptt_cnt <= 0) {
-		sm->dma.ptt_cnt = 0;
-		return -1;
-	}
-	return 0;
-}
-
-static __inline__ void dma_transmit(struct sm_state *sm)
-{
-	void *p;
-
-	while (sm->dma.ptt_cnt < NUM_FRAGMENTS && hdlcdrv_ptt(&sm->hdrv)) {
-		p = (unsigned char *)sm->dma.obuf + sm->dma.ofragsz *
-			((sm->dma.ofragptr + sm->dma.ptt_cnt) % NUM_FRAGMENTS);
-		if (sm->dma.o16bit) {
-			time_exec(sm->debug_vals.mod_cyc, 
-				  sm->mode_tx->modulator_s16(sm, p, sm->dma.ofragsz/2));
-		} else {
-			time_exec(sm->debug_vals.mod_cyc, 
-				  sm->mode_tx->modulator_u8(sm, p, sm->dma.ofragsz));
-		}
-		sm->dma.ptt_cnt++;
-	}
-}
-
-static __inline__ void dma_init_transmit(struct sm_state *sm)
-{
-	sm->dma.ofragptr = 0;
-	sm->dma.ptt_cnt = 0;
-}
-
-static __inline__ void dma_start_transmit(struct sm_state *sm)
-{
-	sm->dma.ofragptr = 0;
-	if (sm->dma.o16bit) {
-		time_exec(sm->debug_vals.mod_cyc, 
-			  sm->mode_tx->modulator_s16(sm, sm->dma.obuf, sm->dma.ofragsz/2));
-	} else {
-		time_exec(sm->debug_vals.mod_cyc, 
-			  sm->mode_tx->modulator_u8(sm, sm->dma.obuf, sm->dma.ofragsz));
-	}
-	sm->dma.ptt_cnt = 1;
-}
-
-static __inline__ void dma_clear_transmit(struct sm_state *sm)
-{
-	sm->dma.ptt_cnt = 0;
-	memset(sm->dma.obuf, (sm->dma.o16bit) ? 0 : 0x80, sm->dma.ofragsz * NUM_FRAGMENTS);
-}
-
-/* --------------------------------------------------------------------- */
-
-static __inline__ void dma_receive(struct sm_state *sm, unsigned int curfrag)
-{
-	void *p;
-
-	while (sm->dma.ifragptr != curfrag) {
-		if (sm->dma.ifragptr)
-			p = (unsigned char *)sm->dma.ibuf + 
-				sm->dma.ifragsz * sm->dma.ifragptr;
-		else {
-			p = (unsigned char *)sm->dma.ibuf + NUM_FRAGMENTS * sm->dma.ifragsz;
-			memcpy(p, sm->dma.ibuf, sm->dma.ifragsz);
-		}
-		if (sm->dma.o16bit) {
-			time_exec(sm->debug_vals.demod_cyc, 
-				  sm->mode_rx->demodulator_s16(sm, p, sm->dma.ifragsz/2));
-		} else {
-			time_exec(sm->debug_vals.demod_cyc, 
-				  sm->mode_rx->demodulator_u8(sm, p, sm->dma.ifragsz));
-		}
-		sm->dma.ifragptr = (sm->dma.ifragptr + 1) % NUM_FRAGMENTS;
-	}
-}
-
-static __inline__ void dma_init_receive(struct sm_state *sm)
-{
-	sm->dma.ifragptr = 0;
-}
-
-/* --------------------------------------------------------------------- */
-#endif /* _SMDMA_H */
-
-
-
diff -Nru a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
--- a/drivers/net/irda/ali-ircc.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/net/irda/ali-ircc.c	Wed Nov 27 14:36:29 2002
@@ -281,15 +281,13 @@
         self->io.fifo_size = 16;		/* SIR: 16, FIR: 32 Benjamin 2000/11/1 */
 	
 	/* Reserve the ioports that we need */
-	ret = check_region(self->io.fir_base, self->io.fir_ext);
-	if (ret < 0) { 
+	if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) {
 		WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
 			self->io.fir_base);
 		dev_self[i] = NULL;
 		kfree(self);
 		return -ENODEV;
 	}
-	request_region(self->io.fir_base, self->io.fir_ext, driver_name);
 
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&self->qos);
diff -Nru a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
--- a/drivers/net/irda/vlsi_ir.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/net/irda/vlsi_ir.c	Wed Nov 27 14:36:27 2002
@@ -162,7 +162,7 @@
 		return 0;
 
 	out += sprintf(out, "\n%s (vid/did: %04x/%04x)\n",
-			pdev->name, (int)pdev->vendor, (int)pdev->device);
+			pdev->dev.name, (int)pdev->vendor, (int)pdev->device);
 	out += sprintf(out, "pci-power-state: %u\n", (unsigned) pdev->current_state);
 	out += sprintf(out, "resources: irq=%u / io=0x%04x / dma_mask=0x%016Lx\n",
 			pdev->irq, (unsigned)pci_resource_start(pdev, 0), (u64)pdev->dma_mask);
@@ -1517,7 +1517,7 @@
 
 	if (vlsi_start_hw(idev))
 		printk(KERN_CRIT "%s: failed to restart hw - %s(%s) unusable!\n",
-			__FUNCTION__, idev->pdev->name, ndev->name);
+			__FUNCTION__, idev->pdev->dev.name, ndev->name);
 	else
 		netif_start_queue(ndev);
 }
@@ -1765,7 +1765,7 @@
 		pdev->current_state = 0; /* hw must be running now */
 
 	printk(KERN_INFO "%s: IrDA PCI controller %s detected\n",
-		drivername, pdev->name);
+		drivername, pdev->dev.name);
 
 	if ( !pci_resource_start(pdev,0)
 	     || !(pci_resource_flags(pdev,0) & IORESOURCE_IO) ) {
@@ -1863,7 +1863,7 @@
 	 * ndev->destructor called (if present) when going to free
 	 */
 
-	printk(KERN_INFO "%s: %s removed\n", drivername, pdev->name);
+	printk(KERN_INFO "%s: %s removed\n", drivername, pdev->dev.name);
 }
 
 #ifdef CONFIG_PM
@@ -1879,7 +1879,7 @@
 {
 	if (state < 1 || state > 3 ) {
 		printk( KERN_ERR "%s - %s: invalid pm state request: %u\n",
-			__FUNCTION__, pdev->name, state);
+			__FUNCTION__, pdev->dev.name, state);
 		return -1;
 	}
 	return 0;
@@ -1892,11 +1892,11 @@
 
 	if (state < 1 || state > 3 ) {
 		printk( KERN_ERR "%s - %s: invalid pm state request: %u\n",
-			__FUNCTION__, pdev->name, state);
+			__FUNCTION__, pdev->dev.name, state);
 		return 0;
 	}
 	if (!ndev) {
-		printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->name);
+		printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->dev.name);
 		return 0;
 	}
 	idev = ndev->priv;	
@@ -1908,7 +1908,7 @@
 		}
 		else
 			printk(KERN_ERR "%s - %s: invalid suspend request %u -> %u\n",
-				__FUNCTION__, pdev->name, pdev->current_state, state);
+				__FUNCTION__, pdev->dev.name, pdev->current_state, state);
 		up(&idev->sem);
 		return 0;
 	}
@@ -1935,14 +1935,14 @@
 	vlsi_irda_dev_t	*idev;
 
 	if (!ndev) {
-		printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->name);
+		printk(KERN_ERR "%s - %s: no netdevice \n", __FUNCTION__, pdev->dev.name);
 		return 0;
 	}
 	idev = ndev->priv;	
 	down(&idev->sem);
 	if (pdev->current_state == 0) {
 		up(&idev->sem);
-		printk(KERN_ERR "%s - %s: already resumed\n", __FUNCTION__, pdev->name);
+		printk(KERN_ERR "%s - %s: already resumed\n", __FUNCTION__, pdev->dev.name);
 		return 0;
 	}
 	
diff -Nru a/drivers/net/macsonic.c b/drivers/net/macsonic.c
--- a/drivers/net/macsonic.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/net/macsonic.c	Wed Nov 27 14:36:27 2002
@@ -195,6 +195,7 @@
 	if ((lp->rba = (char *)
 	     kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) {
 		printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
+		kfree(lp);
 		return -ENOMEM;
 	}
 
diff -Nru a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
--- a/drivers/net/myri_sbus.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/net/myri_sbus.c	Wed Nov 27 14:36:27 2002
@@ -1085,6 +1085,7 @@
 #endif
 	return 0;
 err:	unregister_netdev(dev);
+	/* This will also free the co-allocated 'dev->priv' */
 	kfree(dev);
 	return -ENODEV;
 }
@@ -1141,6 +1142,7 @@
 		struct myri_eth *next = root_myri_dev->next_module;
 
 		unregister_netdev(root_myri_dev->dev);
+		/* this will also free the co-allocated 'root_myri_dev' */
 		kfree(root_myri_dev->dev);
 		root_myri_dev = next;
 	}
diff -Nru a/drivers/net/pcmcia/aironet4500_cs.c b/drivers/net/pcmcia/aironet4500_cs.c
--- a/drivers/net/pcmcia/aironet4500_cs.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/net/pcmcia/aironet4500_cs.c	Wed Nov 27 14:36:27 2002
@@ -39,11 +39,6 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
-#include <pcmcia/k_compat.h>
-#endif
-#endif
 #include <pcmcia/ds.h>
 
 #include <asm/uaccess.h>
diff -Nru a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
--- a/drivers/net/pcmcia/pcnet_cs.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/net/pcmcia/pcnet_cs.c	Wed Nov 27 14:36:31 2002
@@ -300,7 +300,8 @@
     memset(info, 0, sizeof(*info));
     link = &info->link; dev = &info->dev;
     link->priv = info;
-    
+
+    init_timer(&link->release);
     link->release.function = &pcnet_release;
     link->release.data = (u_long)link;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
--- a/drivers/net/pcmcia/smc91c92_cs.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/net/pcmcia/smc91c92_cs.c	Wed Nov 27 14:36:31 2002
@@ -357,6 +357,7 @@
     memset(smc, 0, sizeof(struct smc_private));
     link = &smc->link; dev = &smc->dev;
     spin_lock_init(&smc->lock);
+    init_timer(&link->release);
     link->release.function = &smc91c92_release;
     link->release.data = (u_long)link;
     link->io.NumPorts1 = 16;
diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c
--- a/drivers/net/pppoe.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/net/pppoe.c	Wed Nov 27 14:36:31 2002
@@ -644,8 +644,10 @@
 	release_sock(sk);
 	return error;
 err_put:
-	dev_put(po->pppoe_dev);
-	po->pppoe_dev = NULL;
+	if (po->pppoe_dev) {
+		dev_put(po->pppoe_dev);
+		po->pppoe_dev = NULL;
+	}
 	goto end;
 }
 
diff -Nru a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
--- a/drivers/net/sk98lin/h/skgehw.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/sk98lin/h/skgehw.h	Wed Nov 27 14:36:32 2002
@@ -813,7 +813,7 @@
 									/* Bit 31..12:	reserved */
 #define	IS_IRQ_MST_ERR	(1L<<11)	/* Bit 11:	IRQ master error */
 									/*	PERR,RMABORT,RTABORT,DATAPERR */
-#define	IS_IRQ_STAT		(1L<<10)	/* Bit 10:	IRQ status execption */
+#define	IS_IRQ_STAT		(1L<<10)	/* Bit 10:	IRQ status exception */
 									/*	RMABORT, RTABORT, DATAPERR */
 #define IS_NO_STAT_M1	(1L<<9)		/* Bit	9:	No Rx Status from MAC1*/
 #define IS_NO_STAT_M2	(1L<<8)		/* Bit	8:	No Rx Status from MAC2*/
diff -Nru a/drivers/net/skfp/h/skfbi.h b/drivers/net/skfp/h/skfbi.h
--- a/drivers/net/skfp/h/skfbi.h	Wed Nov 27 14:36:29 2002
+++ b/drivers/net/skfp/h/skfbi.h	Wed Nov 27 14:36:29 2002
@@ -1308,7 +1308,7 @@
 #define IS_I2C_READY	(1L<<27)	/* Bit 27: (ML)	IRQ on end of I2C tx */
 #define IS_IRQ_SW	(1L<<26)	/* Bit 26: (ML)	SW forced IRQ	     */
 #define IS_EXT_REG	(1L<<25)	/* Bit 25: (ML) IRQ from external reg*/
-#define	IS_IRQ_STAT	(1L<<24)	/* Bit 24:	IRQ status execption */
+#define	IS_IRQ_STAT	(1L<<24)	/* Bit 24:	IRQ status exception */
 					/*   PERR, RMABORT, RTABORT DATAPERR */
 #define	IS_IRQ_MST_ERR	(1L<<23)	/* Bit 23:	IRQ master error     */
 					/*   RMABORT, RTABORT, DATAPERR	     */
@@ -1360,7 +1360,7 @@
 #define IRQ_I2C_READY	(1L<<27)	/* Bit 27: (ML)	IRQ on end of I2C tx */
 #define IRQ_SW		(1L<<26)	/* Bit 26: (ML)	SW forced IRQ	     */
 #define IRQ_EXT_REG	(1L<<25)	/* Bit 25: (ML) IRQ from external reg*/
-#define	IRQ_STAT	(1L<<24)	/* Bit 24:	IRQ status execption */
+#define	IRQ_STAT	(1L<<24)	/* Bit 24:	IRQ status exception */
 					/*   PERR, RMABORT, RTABORT DATAPERR */
 #define	IRQ_MST_ERR	(1L<<23)	/* Bit 23:	IRQ master error     */
 					/*   RMABORT, RTABORT, DATAPERR	     */
diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c
--- a/drivers/net/slip.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/slip.c	Wed Nov 27 14:36:32 2002
@@ -261,7 +261,7 @@
 	if (xbuff == NULL || rbuff == NULL)  {
 #endif
 		if (mtu >= sl->mtu) {
-			printk("%s: unable to grow slip buffers, MTU change cancelled.\n",
+			printk(KERN_WARNING "%s: unable to grow slip buffers, MTU change cancelled.\n",
 			       dev->name);
 			err = -ENOBUFS;
 		}
@@ -348,7 +348,7 @@
 		if ((c = sl->rbuff[0]) & SL_TYPE_COMPRESSED_TCP) {
 			/* ignore compressed packets when CSLIP is off */
 			if (!(sl->mode & SL_MODE_CSLIP)) {
-				printk("%s: compressed packet ignored\n", sl->dev->name);
+				printk(KERN_WARNING "%s: compressed packet ignored\n", sl->dev->name);
 				return;
 			}
 			/* make sure we've reserved enough space for uncompress to use */
@@ -365,7 +365,7 @@
 				/* turn on header compression */
 				sl->mode |= SL_MODE_CSLIP;
 				sl->mode &= ~SL_MODE_ADAPTIVE;
-				printk("%s: header compression turned on\n", sl->dev->name);
+				printk(KERN_INFO "%s: header compression turned on\n", sl->dev->name);
 			}
 			sl->rbuff[0] &= 0x4f;
 			if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) {
@@ -379,7 +379,7 @@
 	
 	skb = dev_alloc_skb(count);
 	if (skb == NULL)  {
-		printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
+		printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name);
 		sl->rx_dropped++;
 		return;
 	}
@@ -400,7 +400,7 @@
 	int actual, count;
 
 	if (len > sl->mtu) {		/* Sigh, shouldn't occur BUT ... */
-		printk ("%s: truncating oversized transmit packet!\n", sl->dev->name);
+		printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name);
 		sl->tx_dropped++;
 		sl_unlock(sl);
 		return;
@@ -487,7 +487,7 @@
 			/* 20 sec timeout not reached */
 			goto out;
 		}
-		printk("%s: transmit timed out, %s?\n", dev->name,
+		printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
 		       (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
 		       "bad line quality" : "driver error");
 		sl->xleft = 0;
@@ -510,7 +510,7 @@
 	spin_lock(&sl->lock);
 	if (!netif_running(dev))  {
 		spin_unlock(&sl->lock);
-		printk("%s: xmit call when iface is down\n", dev->name);
+		printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
 		dev_kfree_skb(skb);
 		return 0;
 	}
@@ -1332,7 +1332,7 @@
 	       ".\n",
 	       SLIP_VERSION, slip_maxdev );
 #if defined(SL_INCLUDE_CSLIP) && !defined(MODULE)
-	printk("CSLIP: code copyright 1989 Regents of the University of California.\n");
+	printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n");
 #endif
 #ifdef CONFIG_SLIP_SMART
 	printk(KERN_INFO "SLIP linefill/keepalive option.\n");
@@ -1341,7 +1341,7 @@
 	slip_ctrls = (slip_ctrl_t **) kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL);
 	if (slip_ctrls == NULL)
 	{
-		printk("SLIP: Can't allocate slip_ctrls[] array!  Uaargh! (-> No SLIP available)\n");
+		printk(KERN_ERR "SLIP: Can't allocate slip_ctrls[] array!  Uaargh! (-> No SLIP available)\n");
 		return -ENOMEM;
 	}
 
@@ -1364,7 +1364,7 @@
 	sl_ldisc.receive_room = slip_receive_room;
 	sl_ldisc.write_wakeup = slip_write_wakeup;
 	if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
-		printk("SLIP: can't register line discipline (err = %d)\n", status);
+		printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
 	}
 
 
@@ -1418,7 +1418,7 @@
 			if (slc) {
 				unregister_netdev(&slc->dev);
 				if (slc->ctrl.tty) {
-					printk("%s: tty discipline is still running\n", slc->dev.name);
+					printk(KERN_ERR "%s: tty discipline is still running\n", slc->dev.name);
 					/* Pin module forever */
 					MOD_INC_USE_COUNT;
 					busy++;
@@ -1436,7 +1436,7 @@
 	}
 	if ((i = tty_register_ldisc(N_SLIP, NULL)))
 	{
-		printk("SLIP: can't unregister line discipline (err = %d)\n", i);
+		printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);
 	}
 }
 #endif /* MODULE */
@@ -1498,7 +1498,7 @@
 			/* keepalive still high :(, we must hangup */
 			if( sl->outfill ) /* outfill timer must be deleted too */
 				(void)del_timer(&sl->outfill_timer);
-			printk("%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
+			printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
 			tty_hangup(sl->tty); /* this must hangup tty & close slip */
 			/* I think we need not something else */
 			goto out;
diff -Nru a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
--- a/drivers/net/sunbmac.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/net/sunbmac.c	Wed Nov 27 14:36:30 2002
@@ -1209,6 +1209,7 @@
 				     bp->bblock_dvma);
 
 	unregister_netdev(dev);
+	/* This also frees the co-located 'dev->priv' */
 	kfree(dev);
 	return -ENODEV;
 }
diff -Nru a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
--- a/drivers/net/tokenring/3c359.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/tokenring/3c359.c	Wed Nov 27 14:36:32 2002
@@ -315,7 +315,7 @@
 	dev->irq=pdev->irq;
 	dev->base_addr=pci_resource_start(pdev,0) ; 
 	dev->init=NULL ; /* Must be null with new api, otherwise get called twice */
-	xl_priv->xl_card_name = (char *)pdev->name ; 
+	xl_priv->xl_card_name = (char *)pdev->dev.name ; 
 	xl_priv->xl_mmio=ioremap(pci_resource_start(pdev,1), XL_IO_SPACE);
 	xl_priv->pdev = pdev ; 
 		
diff -Nru a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
--- a/drivers/net/tokenring/madgemc.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/tokenring/madgemc.c	Wed Nov 27 14:36:32 2002
@@ -226,16 +226,12 @@
 			goto getout;
 		}
 
-		request_region(dev->base_addr, MADGEMC_IO_EXTENT, "madgemc");
-#if 0
-		/* why is this not working? */
-		if (request_region(dev->base_addr, MADGEMC_IO_EXTENT, 
+		if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT, 
 				   "madgemc")) {
 			printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", slot, dev->base_addr);
 			dev->base_addr += MADGEMC_SIF_OFFSET;
 			goto getout;
 		}
-#endif
 		dev->base_addr += MADGEMC_SIF_OFFSET;
 		
 		/*
diff -Nru a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
--- a/drivers/net/tokenring/olympic.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/net/tokenring/olympic.c	Wed Nov 27 14:36:31 2002
@@ -230,7 +230,7 @@
 	dev->irq=pdev->irq;
 	dev->base_addr=pci_resource_start(pdev, 0);
 	dev->init=NULL; /* Must be NULL otherwise we get called twice */
-	olympic_priv->olympic_card_name = (char *)pdev->name ; 
+	olympic_priv->olympic_card_name = (char *)pdev->dev.name ; 
 	olympic_priv->olympic_mmio = ioremap(pci_resource_start(pdev,1),256);
 	olympic_priv->olympic_lap = ioremap(pci_resource_start(pdev,2),2048);
 	olympic_priv->pdev = pdev ; 
@@ -654,8 +654,8 @@
 	printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7])  );
 
 	printk("RXCDA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCDA),&olympic_priv->olympic_rx_ring[0]);
-	printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr =
-%08x\n",olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; 
+	printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr = %08x\n",
+		olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; 
 #endif
 
 	writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ);
diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
--- a/drivers/net/wan/cosa.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/net/wan/cosa.c	Wed Nov 27 14:36:27 2002
@@ -610,7 +610,8 @@
 static int cosa_sppp_open(struct net_device *d)
 {
 	struct channel_data *chan = d->priv;
-	int err, flags;
+	int err;
+	unsigned long flags;
 
 	if (!(chan->cosa->firmware_status & COSA_FW_START)) {
 		printk(KERN_NOTICE "%s: start the firmware first (status %d)\n",
@@ -681,7 +682,7 @@
 static int cosa_sppp_close(struct net_device *d)
 {
 	struct channel_data *chan = d->priv;
-	int flags;
+	unsigned long flags;
 
 	netif_stop_queue(d);
 	sppp_close(d);
@@ -778,7 +779,7 @@
 	char *buf, size_t count, loff_t *ppos)
 {
 	DECLARE_WAITQUEUE(wait, current);
-	int flags;
+	unsigned long flags;
 	struct channel_data *chan = (struct channel_data *)file->private_data;
 	struct cosa_data *cosa = chan->cosa;
 	char *kbuf;
@@ -855,7 +856,7 @@
 	DECLARE_WAITQUEUE(wait, current);
 	struct channel_data *chan = (struct channel_data *)file->private_data;
 	struct cosa_data *cosa = chan->cosa;
-	unsigned int flags;
+	unsigned long flags;
 	char *kbuf;
 
 	if (!(cosa->firmware_status & COSA_FW_START)) {
@@ -1242,7 +1243,7 @@
 static int cosa_start_tx(struct channel_data *chan, char *buf, int len)
 {
 	struct cosa_data *cosa = chan->cosa;
-	int flags;
+	unsigned long flags;
 #ifdef DEBUG_DATA
 	int i;
 
@@ -1268,7 +1269,7 @@
 
 static void put_driver_status(struct cosa_data *cosa)
 {
-	unsigned flags=0;
+	unsigned long flags;
 	int status;
 
 	spin_lock_irqsave(&cosa->lock, flags);
@@ -1336,7 +1337,7 @@
  */
 static void cosa_kick(struct cosa_data *cosa)
 {
-	unsigned flags, flags1;
+	unsigned long flags, flags1;
 	char *s = "(probably) IRQ";
 
 	if (test_bit(RXBIT, &cosa->rxtx))
diff -Nru a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
--- a/drivers/net/wan/hostess_sv11.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/net/wan/hostess_sv11.c	Wed Nov 27 14:36:31 2002
@@ -284,9 +284,11 @@
 				goto dmafail;
 		}
 	}
-	save_flags(flags);
-	cli();
-	
+
+	/* Kill our private IRQ line the hostess can end up chattering
+	   until the configuration is set */
+	disable_irq(irq);
+		
 	/*
 	 *	Begin normal initialise
 	 */
@@ -294,7 +296,7 @@
 	if(z8530_init(dev)!=0)
 	{
 		printk(KERN_ERR "Z8530 series device not found.\n");
-		restore_flags(flags);
+		enable_irq(irq);
 		goto dmafail2;
 	}
 	z8530_channel_load(&dev->chanB, z8530_dead_port);
@@ -303,8 +305,8 @@
 	else
 		z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream_85230);
 	
-	restore_flags(flags);
-
+	enable_irq(irq);
+	
 
 	/*
 	 *	Now we can take the IRQ
@@ -399,7 +401,7 @@
 
 int init_module(void)
 {
-	printk(KERN_INFO "SV-11 Z85230 Synchronous Driver v 0.02.\n");
+	printk(KERN_INFO "SV-11 Z85230 Synchronous Driver v 0.03.\n");
 	printk(KERN_INFO "(c) Copyright 2001, Red Hat Inc.\n");	
 	if((sv11_unit=sv11_init(io,irq))==NULL)
 		return -ENODEV;
diff -Nru a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
--- a/drivers/net/wan/pc300_drv.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/wan/pc300_drv.c	Wed Nov 27 14:36:32 2002
@@ -3688,3 +3688,9 @@
 
 module_init(cpc_init);
 module_exit(cpc_cleanup_module);
+
+MODULE_DESCRIPTION("Cyclades-PC300 cards driver");
+MODULE_AUTHOR(  "Author: Ivan Passos <ivan@cyclades.com>\r\n"
+                "Maintainer: Henrique Gobbi <henrique.gobbi@cyclades.com");
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
--- a/drivers/net/wan/sbni.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/net/wan/sbni.c	Wed Nov 27 14:36:28 2002
@@ -194,7 +194,7 @@
 sbni_isa_probe( struct net_device  *dev )
 {
 	if( dev->base_addr > 0x1ff
-	    &&  !check_region( dev->base_addr, SBNI_IO_EXTENT )
+	    &&  request_region( dev->base_addr, SBNI_IO_EXTENT, dev->name )
 	    &&  sbni_probe1( dev, dev->base_addr, dev->irq ) )
 
 		return  0;
@@ -249,7 +249,7 @@
 
 	for( i = 0;  netcard_portlist[ i ];  ++i ) {
 		int  ioaddr = netcard_portlist[ i ];
-		if( !check_region( ioaddr, SBNI_IO_EXTENT )
+		if( request_region( ioaddr, SBNI_IO_EXTENT, dev->name )
 		    &&  sbni_probe1( dev, ioaddr, 0 ))
 			return 0;
 	}
@@ -280,7 +280,7 @@
 		pci_irq_line = pdev->irq;
 
 		/* Avoid already found cards from previous calls */
-		if( check_region( pci_ioaddr, SBNI_IO_EXTENT ) ) {
+		if( !pci_request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) {
 			pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys );
 			if( subsys != 2  ||	/* Dual adapter is present */
 			    check_region( pci_ioaddr += 4, SBNI_IO_EXTENT ) )
@@ -309,9 +309,6 @@
 sbni_probe1( struct net_device  *dev,  unsigned long  ioaddr,  int  irq )
 {
 	struct net_local  *nl;
-
-	if( !request_region( ioaddr, SBNI_IO_EXTENT, dev->name ) )
-		return  0;
 
 	if( sbni_card_probe( ioaddr ) ) {
 		release_region( ioaddr, SBNI_IO_EXTENT );
diff -Nru a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
--- a/drivers/net/wan/sdla_fr.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/net/wan/sdla_fr.c	Wed Nov 27 14:36:32 2002
@@ -162,14 +162,9 @@
 
 #include <linux/sdla_fr.h>		/* frame relay firmware API definitions */
 
-#if defined(LINUX_2_1) || defined(LINUX_2_4)
- #include <asm/uaccess.h>
- #include <linux/inetdevice.h>
- #include <linux/netdevice.h>
-
-#else
- #include <asm/segment.h>
-#endif
+#include <asm/uaccess.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
 
 #include <net/route.h>          	/* Dynamic Route Creation */
 #include <linux/etherdevice.h>		/* eth_type_trans() used for bridging */
diff -Nru a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
--- a/drivers/net/wan/sealevel.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/net/wan/sealevel.c	Wed Nov 27 14:36:31 2002
@@ -302,9 +302,8 @@
 	if(request_dma(dev->chanA.rxdma, "SeaLevel (RX)")!=0)
 		goto dmafail;
 	
-	save_flags(flags);
-	cli();
-	
+	disable_irq(irq);
+		
 	/*
 	 *	Begin normal initialise
 	 */
@@ -312,7 +311,7 @@
 	if(z8530_init(dev)!=0)
 	{
 		printk(KERN_ERR "Z8530 series device not found.\n");
-		restore_flags(flags);
+		enable_irq(irq);
 		goto dmafail2;
 	}
 	if(dev->type==Z85C30)
@@ -330,7 +329,7 @@
 	 *	Now we can take the IRQ
 	 */
 	
-	restore_flags(flags);
+	enable_irq(irq);
 
 	for(u=0; u<2; u++)
 	{
@@ -446,7 +445,7 @@
 
 int init_module(void)
 {
-	printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.01.\n");
+	printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.02.\n");
 	printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n");	
 	if((slvl_unit=slvl_init(io,irq, txdma, rxdma, slow))==NULL)
 		return -ENODEV;
diff -Nru a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
--- a/drivers/net/wireless/airo_cs.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/net/wireless/airo_cs.c	Wed Nov 27 14:36:28 2002
@@ -242,6 +242,11 @@
 	
 	/* Allocate space for private device-specific data */
 	local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+	if (!local) {
+		printk(KERN_ERR "airo_cs: no memory for new device\n");
+		kfree (link);
+		return NULL;
+	}
 	memset(local, 0, sizeof(local_info_t));
 	link->priv = local;
 	
diff -Nru a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
--- a/drivers/oprofile/cpu_buffer.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/oprofile/cpu_buffer.c	Wed Nov 27 14:36:27 2002
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
+#include <linux/errno.h>
  
 #include "cpu_buffer.h"
 #include "oprof.h"
diff -Nru a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog
--- a/drivers/parport/ChangeLog	Wed Nov 27 14:36:31 2002
+++ b/drivers/parport/ChangeLog	Wed Nov 27 14:36:31 2002
@@ -1,8 +1,7 @@
-2001-11-14  Tim Waugh  <twaugh@redhat.com>
+2002-04-25  Tim Waugh  <twaugh@redhat.com>
 
-	* parport_pc.c (parport_pc_pci_probe): Hooks for PCI cards before
-	and after probing for ports.
-	* parport_serial.c (parport_register): Likewise.
+	* parport_serial.c, parport_pc.c: Move some SIIG cards around.
+	Patch from Andrey Panin.
 
 2002-01-20  Tim Waugh  <twaugh@redhat.com>
 
@@ -21,17 +20,17 @@
 	* daisy.c: Apply patch from Max Vorobiev to make parport_daisy_select
 	work for ECP/EPP modes.
 
-2002-01-04  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_claim_or_block): Sleep interruptibly to prevent
-	a possible deadlock.
-
 2002-01-13  Niels Kristian Bech Jensen  <nkbj@image.dk>
 
 	* parport_pc.c: Change some occurrences of frob_set_mode to
 	ECR_WRITE.  This fixes PLIP.
 
-2001-10-25  Damian Gruszka  <damian.gruszka@VisionSystems.de>
+2002-01-04  Tim Waugh  <twaugh@redhat.com>
+
+	* share.c (parport_claim_or_block): Sleep interruptibly to prevent
+	a possible deadlock.
+
+2001-12-07  Damian Gruszka  <damian.gruszka@VisionSystems.de>
 
 	* parport_pc.c (ECR_WRITE): Define.  If there are forbidden bits
 	in the ECR register for some chips, this will be a useful place to
@@ -68,7 +67,7 @@
 	(parport_irq_probe): If no IRQ is found, take ackIntEn out of the
 	writable bit set.
 
-2001-10-25  Tim Waugh  <twaugh@redhat.com>
+2001-12-07  Tim Waugh  <twaugh@redhat.com>
 
 	* parport_pc.c (parport_pc_fifo_write_block_pio): Correct typo.
 	(parport_pc_init_state): Only set ackIntEn if we know which IRQ
@@ -85,6 +84,16 @@
 	too buggy at the moment.  Use 'dma=auto' to restore the previous
 	behaviour.
 
+2001-12-07  Tim Waugh  <twaugh@redhat.com>
+
+	* daisy.c (DEBUG): Undefine.
+
+2001-12-06  Tim Waugh  <twaugh@redhat.com>
+
+	* ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off
+	PARPORT_CONTROL_AUTOFD as well.  Bug spotted by Joe
+	<joeja@mindspring.com>.
+
 2001-12-03  Rich Liu  <Rich.Liu@ite.com.tw>
 
 	* parport_pc.c (sio_ite_8872_probe): ITE8873 is a single-port
@@ -94,11 +103,11 @@
 
 	* parport_pc.c: Fix compiler warning.
 
-2001-12-06  Tim Waugh  <twaugh@redhat.com>
+2001-11-14  Tim Waugh  <twaugh@redhat.com>
 
-	* ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off
-	PARPORT_CONTROL_AUTOFD as well.  Bug spotted by Joe
-	<joeja@mindspring.com>.
+	* parport_pc.c (parport_pc_pci_probe): Hooks for PCI cards before
+	and after probing for ports.
+	* parport_serial.c (parport_register): Likewise.
 
 2001-11-12  Tim Waugh  <twaugh@redhat.com>
 
diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
--- a/drivers/parport/parport_pc.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/parport/parport_pc.c	Wed Nov 27 14:36:32 2002
@@ -2709,6 +2709,7 @@
 	oxsemi_954,
 	oxsemi_840,
 	aks_0100,
+	mobility_pp,
 };
 
 
@@ -2792,6 +2793,7 @@
 	/* oxsemi_954 */		{ 1, { { 0, -1 }, } },
 	/* oxsemi_840 */		{ 1, { { 0, -1 }, } },
 	/* aks_0100 */			{ 1, { { 0, 1 }, } },
+	/* mobility_pp */		{ 1, { { 0, 1 }, } },
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
@@ -2873,6 +2875,7 @@
 	{ 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a },
 	{ 0x1409, 0x7268, 0x1409, 0x0104, 0, 0, timedia_4018 },
 	{ 0x1409, 0x7268, 0x1409, 0x9018, 0, 0, timedia_9018a },
+	{ 0x14f2, 0x0121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, mobility_pp },
 	{ PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_2P_EPP,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp },
 	{ PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_1P_ECP,
diff -Nru a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
--- a/drivers/parport/parport_serial.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/parport/parport_serial.c	Wed Nov 27 14:36:31 2002
@@ -41,6 +41,11 @@
 	avlab_2s1p,
 	avlab_2s1p_650,
 	avlab_2s1p_850,
+	siig_1s1p_10x,
+	siig_2s1p_10x,
+	siig_2p1s_20x,
+	siig_1s1p_20x,
+	siig_2s1p_20x,
 };
 
 
@@ -74,6 +79,11 @@
 	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
 	/* avlab_2s1p_650 */		{ 1, { { 2, 3}, } },
 	/* avlab_2s1p_850 */		{ 1, { { 2, 3}, } },
+	/* siig_1s1p_10x */		{ 1, { { 3, 4 }, } },
+	/* siig_2s1p_10x */		{ 1, { { 4, 5 }, } },
+	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
+	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
+	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
 };
 
 static struct pci_device_id parport_serial_pci_tbl[] __devinitdata = {
@@ -92,6 +102,37 @@
 	{ 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p},
 	{ 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650},
 	{ 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850},
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
@@ -107,6 +148,16 @@
 	int first_uart_offset;
 };
 
+static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
+{
+	return pci_siig10x_fn(dev, NULL, enable);
+}
+
+static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
+{
+	return pci_siig20x_fn(dev, NULL, enable);
+}
+
 static struct pci_board_no_ids pci_boards[] __devinitdata = {
 	/*
 	 * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
@@ -129,6 +180,11 @@
 /* avlab_2s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
 /* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
 /* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* siig_1s1p_10x */	{ SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },
+/* siig_2s1p_10x */	{ SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },
+/* siig_2p1s_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/* siig_1s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/* siig_2s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
 };
 
 struct parport_serial_private {
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/pci/pci.c	Wed Nov 27 14:36:28 2002
@@ -729,6 +729,7 @@
 __setup("pci=", pci_setup);
 
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+/* FIXME: Some boxes have multiple ISA bridges! */
 struct pci_dev *isa_bridge;
 EXPORT_SYMBOL(isa_bridge);
 #endif
diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids
--- a/drivers/pci/pci.ids	Wed Nov 27 14:36:30 2002
+++ b/drivers/pci/pci.ids	Wed Nov 27 14:36:30 2002
@@ -497,8 +497,8 @@
 		1011 500b  DE500B Fast Ethernet
 		1014 0001  10/100 EtherJet Cardbus
 		1025 0315  ALN315 Fast Ethernet
-		1033 800c  PC-9821-CS01
-		1033 800d  PC-9821NR-B06
+		1033 800c  PC-9821-CS01 100BASE-TX Interface Card
+		1033 800d  PC-9821NR-B06 100BASE-TX Interface Card
 		108d 0016  Rapidfire 2327 10/100 Ethernet
 		108d 0017  GoCard 2250 Ethernet 10/100 Cardbus
 		10b8 2005  SMC8032DT Extreme Ethernet 10/100
@@ -1049,17 +1049,21 @@
 	0003  ATM Controller
 	0004  R4000 PCI Bridge
 	0005  PCI to 486-like bus Bridge
-	0006  GUI Accelerator
+	0006  PC-9800 Graphic Accelerator
 	0007  PCI to UX-Bus Bridge
-	0008  GUI Accelerator
-	0009  GUI Accelerator for W98
+	0008  PC-9800 Graphic Accelerator
+	0009  PCI to PC9800 Core-Graph Bridge
+	0016  PCI to VL Bridge
 	001a  [Nile II]
 	0021  Vrc4373 [Nile I]
 	0029  PowerVR PCX1
 	002a  PowerVR 3D
+	002c  Star Alpha 2
+	002d  PCI to C-bus Bridge
 	0035  USB
 		1179 0001  USB
 		12ee 7000  Root Hub
+	003b  PCI to C-bus Bridge
 	003e  NAPCCARD Cardbus Controller
 	0046  PowerVR PCX2 [midas]
 	005a  Vrc5074 [Nile 4]
@@ -3489,7 +3493,7 @@
 	5811  FW323
 		dead 0800  FireWire Host Bus Adapter
 11c2  Sand Microelectronics
-11c3  NEC Corp
+11c3  NEC Corporation
 11c4  Document Technologies, Inc
 11c5  Shiva Corporation
 11c6  Dainippon Screen Mfg. Co. Ltd
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/pci/quirks.c	Wed Nov 27 14:36:27 2002
@@ -212,6 +212,19 @@
 }	
 
 /*
+ *	ATI Northbridge setups MCE the processor if you even
+ *	read somewhere between 0x3b0->0x3bb or read 0x3d3
+ */
+ 
+static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
+{
+	printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n");
+	/* Mae rhaid in i beidio a edrych ar y lleoliad I/O hyn */
+	request_region(0x3b0, 0x0C, "RadeonIGP");
+	request_region(0x3d3, 0x01, "RadeonIGP");
+}
+
+/*
  * Let's make the southbridge information explicit instead
  * of having to worry about people probing the ACPI areas,
  * for example.. (Yes, it happens, and if you read the wrong
@@ -313,6 +326,35 @@
 	pci_write_config_byte (dev, 0x58, tmp);
 }
 
+/*
+ * The AMD io apic can hang the box when an apic irq is masked.
+ * We check all revs >= B0 (yet not in the pre production!) as the bug
+ * is currently marked NoFix
+ *
+ * We have multiple reports of hangs with this chipset that went away with
+ * noapic specified. For the moment we assume its the errata. We may be wrong
+ * of course. However the advice is demonstrably good even if so..
+ */
+ 
+static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
+{
+	u8 rev;
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+	if(rev >= 0x02)
+	{
+		printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n");
+		printk(KERN_WARNING "        : booting with the \"noapic\" option.\n");
+	}
+}
+
+static void __init quirk_ioapic_rmw(struct pci_dev *dev)
+{
+	if (dev->devfn == 0 && dev->bus->number == 0)
+		sis_apic_bug = 1;
+}
+
+
 #endif /* CONFIG_X86_IO_APIC */
 
 
@@ -412,28 +454,6 @@
 }
 
 /*
- * The AMD io apic can hang the box when an apic irq is masked.
- * We check all revs >= B0 (yet not in the pre production!) as the bug
- * is currently marked NoFix
- *
- * We have multiple reports of hangs with this chipset that went away with
- * noapic specified. For the moment we assume its the errata. We may be wrong
- * of course. However the advice is demonstrably good even if so..
- */
- 
-static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
-{
-	u8 rev;
-
-	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-	if(rev >= 0x02)
-	{
-		printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n");
-		printk(KERN_WARNING "        : booting with the \"noapic\" option.\n");
-	}
-}
-
-/*
  * Following the PCI ordering rules is optional on the AMD762. I'm not
  * sure what the designers were smoking but let's not inhale...
  *
@@ -477,6 +497,24 @@
 }
 
 /*
+ * Common misconfiguration of the MediaGX/Geode PCI master that will
+ * reduce PCI bandwidth from 70MB/s to 25MB/s.  See the GXM/GXLV/GX1
+ * datasheets found at http://www.national.com/ds/GX for info on what
+ * these bits do.  <christer@weinigel.se>
+ */
+ 
+static void __init quirk_mediagx_master(struct pci_dev *dev)
+{
+	u8 reg;
+	pci_read_config_byte(dev, 0x41, &reg);
+	if (reg & 2) {
+		reg &= ~2;
+		printk(KERN_INFO "PCI: Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg);
+                pci_write_config_byte(dev, 0x41, reg);
+	}
+}
+
+/*
  *  The main table of quirks.
  */
 
@@ -491,6 +529,7 @@
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton }, 
@@ -521,6 +560,8 @@
 
 #ifdef CONFIG_X86_IO_APIC 
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic },
+	{ PCI_FIXUP_FINAL, 	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SIS,	PCI_ANY_ID,			quirk_ioapic_rmw },
 #endif
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi },
@@ -528,8 +569,8 @@
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_5,	quirk_via_irqpic },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_6,	quirk_via_irqpic },
 
-	{ PCI_FIXUP_FINAL, 	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RADEON_IGP,   quirk_ati_exploding_mce },
 	/*
 	 * i82380FB mobile docking controller: its PCI-to-PCI bridge
 	 * is subtractive decoding (transparent), and does indicate this
@@ -537,6 +578,9 @@
 	 * instead of 0x01.
 	 */
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge },
+
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master },
+	
 
 	{ 0 }
 };
diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
--- a/drivers/pcmcia/cardbus.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/pcmcia/cardbus.c	Wed Nov 27 14:36:28 2002
@@ -283,6 +283,8 @@
 		dev->hdr_type = hdr & 0x7f;
 
 		pci_setup_device(dev);
+		if (pci_enable_device(dev))
+			continue;
 
 		strcpy(dev->dev.bus_id, dev->slot_name);
 
@@ -300,7 +302,6 @@
 			pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
 		}
 
-		pci_enable_device(dev); /* XXX check return */
 		device_register(&dev->dev);
 		pci_insert_device(dev, bus);
 	}
diff -Nru a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
--- a/drivers/pcmcia/sa1100_assabet.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/pcmcia/sa1100_assabet.c	Wed Nov 27 14:36:31 2002
@@ -6,13 +6,14 @@
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
+#include <asm/signal.h>
 #include <asm/arch/assabet.h>
 
 #include "sa1100_generic.h"
diff -Nru a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c
--- a/drivers/pcmcia/sa1100_badge4.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/pcmcia/sa1100_badge4.c	Wed Nov 27 14:36:28 2002
@@ -31,40 +31,41 @@
  *
  * PCM Vcc:
  *
- *  PCM Vcc on BadgePAD 4 can be jumpered for 3.3V (short pins 1 and 3
- *  on JP6) or 5V (short pins 3 and 5 on JP6).  N.B., 5V supply rail
- *  is enabled by the SA-1110's BADGE4_GPIO_PCMEN5V (GPIO 24).
+ *  PCM Vcc on BadgePAD 4 can be jumpered for 3v3 (short pins 1 and 3
+ *  on JP6) or 5v0 (short pins 3 and 5 on JP6).
  *
  * PCM Vpp:
  *
- *  PCM Vpp on BadgePAD 4 can be jumpered for 12V (short pins 2 and 4
- *  on JP6) or tied to PCM Vcc (short pins 4 and 6 on JP6).  N.B., 12V
- *  operation requires that the power supply actually supply 12V.
+ *  PCM Vpp on BadgePAD 4 can be jumpered for 12v0 (short pins 4 and 6
+ *  on JP6) or tied to PCM Vcc (short pins 2 and 4 on JP6).  N.B.,
+ *  12v0 operation requires that the power supply actually supply 12v0
+ *  via pin 7 of JP7.
  *
  * CF Vcc:
  *
- *  CF Vcc on BadgePAD 4 can be jumpered either for 3.3V (short pins 1
- *  and 2 on JP10) or 5V (short pins 2 and 3 on JP10).  The note above
- *  about the 5V supply rail applies.
- *
- * There's no way programmatically to determine how a given board is
- * jumpered.  This code assumes a default jumpering: 5V PCM Vcc (pins
- * 3 and 5 shorted) and PCM Vpp = PCM Vcc (pins 4 and 6 shorted) and
- * no jumpering for CF Vcc.  If this isn't correct, Override these
- * defaults with a pcmv setup argument: pcmv=<pcm vcc>,<pcm vpp>,<cf
- * vcc>.  E.g. pcmv=33,120,50 indicates 3.3V PCM Vcc, 12.0V PCM Vpp,
- * and 5.0V CF Vcc.
+ *  CF Vcc on BadgePAD 4 can be jumpered either for 3v3 (short pins 1
+ *  and 2 on JP10) or 5v0 (short pins 2 and 3 on JP10).
+ *
+ * Unfortunately there's no way programmatically to determine how a
+ * given board is jumpered.  This code assumes a default jumpering
+ * as described below.
+ *
+ * If the defaults aren't correct, you may override them with a pcmv
+ * setup argument: pcmv=<pcm vcc>,<pcm vpp>,<cf vcc>.  The units are
+ * tenths of volts; e.g. pcmv=33,120,50 indicates 3v3 PCM Vcc, 12v0
+ * PCM Vpp, and 5v0 CF Vcc.
  *
  */
 
-static int badge4_pcmvcc = 50;
-static int badge4_pcmvpp = 50;
-static int badge4_cfvcc = 33;
+static int badge4_pcmvcc = 50;  /* pins 3 and 5 jumpered on JP6 */
+static int badge4_pcmvpp = 50;  /* pins 2 and 4 jumpered on JP6 */
+static int badge4_cfvcc = 33;   /* pins 1 and 2 jumpered on JP10 */
 
 static int badge4_pcmcia_init(struct pcmcia_init *init)
 {
-	printk(KERN_INFO __FUNCTION__
-	       ": badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
+	printk(KERN_INFO
+	       "%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
+	       __FUNCTION__,
 	       badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
 
 	return sa1111_pcmcia_init(init);
@@ -74,7 +75,7 @@
 {
 	int rc = sa1111_pcmcia_shutdown();
 
-	/* be sure to disable 5V use */
+	/* be sure to disable 5v0 use */
 	badge4_set_5V(BADGE4_5V_PCMCIA_SOCK0, 0);
 	badge4_set_5V(BADGE4_5V_PCMCIA_SOCK1, 0);
 
@@ -105,7 +106,8 @@
 		    (conf->vcc != badge4_pcmvcc)) {
 			complain_about_jumpering(__FUNCTION__, "pcmvcc",
 						 badge4_pcmvcc, conf->vcc);
-			return -1;
+			// Apply power regardless of the jumpering.
+			// return -1;
 		}
 		if ((conf->vpp != 0) &&
 		    (conf->vpp != badge4_pcmvpp)) {
@@ -156,7 +158,7 @@
 	.socket_suspend		= sa1111_pcmcia_socket_suspend,
 };
 
-int __init pcmcia_badge4_init(void)
+int pcmcia_badge4_init(void)
 {
 	int ret = -ENODEV;
 
@@ -166,7 +168,7 @@
 	return ret;
 }
 
-void __exit pcmcia_badge4_exit(void)
+void __devexit pcmcia_badge4_exit(void)
 {
 	sa1100_unregister_pcmcia(&badge4_pcmcia_ops);
 }
diff -Nru a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
--- a/drivers/pcmcia/sa1111_generic.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/pcmcia/sa1111_generic.c	Wed Nov 27 14:36:28 2002
@@ -7,9 +7,9 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/device.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
--- a/drivers/pcmcia/tcic.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/pcmcia/tcic.c	Wed Nov 27 14:36:30 2002
@@ -392,7 +392,11 @@
     printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
     sock = 0;
 
-    if (check_region(tcic_base, 16) == 0) {
+    if (!request_region(tcic_base, 16, "tcic-2")) {
+	printk("could not allocate ports,\n ");
+	return -ENODEV;
+    }
+    else {
 	tcic_setw(TCIC_ADDR, 0);
 	if (tcic_getw(TCIC_ADDR) == 0) {
 	    tcic_setw(TCIC_ADDR, 0xc3a5);
@@ -408,15 +412,12 @@
 		if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
 	    }
 	}
-    } else
-	printk("could not allocate ports, ");
-
+    }
     if (sock == 0) {
 	printk("not found.\n");
+	release_region(tcic_base, 16);
 	return -ENODEV;
     }
-
-    request_region(tcic_base, 16, "tcic-2");
 
     sockets = 0;
     for (i = 0; i < sock; i++) {
diff -Nru a/drivers/pnp/core.c b/drivers/pnp/core.c
--- a/drivers/pnp/core.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/pnp/core.c	Wed Nov 27 14:36:28 2002
@@ -164,7 +164,7 @@
 	return bus_register(&pnp_bus_type);
 }
 
-core_initcall(pnp_init);
+subsys_initcall(pnp_init);
 
 EXPORT_SYMBOL(pnp_protocol_register);
 EXPORT_SYMBOL(pnp_protocol_unregister);
diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c
--- a/drivers/pnp/interface.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/pnp/interface.c	Wed Nov 27 14:36:28 2002
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <linux/types.h>
+#include <linux/stat.h>
 
 #include "base.h"
 
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/pnp/isapnp/core.c	Wed Nov 27 14:36:30 2002
@@ -1167,7 +1167,7 @@
 	return 0;
 }
 
-subsys_initcall(isapnp_init);
+device_initcall(isapnp_init);
 
 /* format is: noisapnp */
 
diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c
--- a/drivers/pnp/system.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/pnp/system.c	Wed Nov 27 14:36:32 2002
@@ -120,4 +120,4 @@
 	return pnp_register_driver(&system_pnp_driver);
 }
 
-core_initcall(pnp_system_init);
+subsys_initcall(pnp_system_init);
diff -Nru a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
--- a/drivers/sbus/char/bpp.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/sbus/char/bpp.c	Wed Nov 27 14:36:27 2002
@@ -95,7 +95,7 @@
 /*
  * These are for data access.
  * Control lines accesses are hidden in set_bits() and get_bits().
- * The exeption is the probe procedure, which is system-dependent.
+ * The exception is the probe procedure, which is system-dependent.
  */
 #define bpp_outb_p(data, base)  outb_p((data), (base))
 #define bpp_inb(base)  inb(base)
diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
--- a/drivers/scsi/3w-xxxx.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/3w-xxxx.c	Wed Nov 27 14:36:31 2002
@@ -189,6 +189,7 @@
 #include <linux/smp.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
+#include <linux/interrupt.h>
 
 #include <asm/errno.h>
 #include <asm/io.h>
diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
--- a/drivers/scsi/53c700.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/53c700.c	Wed Nov 27 14:36:28 2002
@@ -170,8 +170,8 @@
 STATIC int NCR_700_proc_directory_info(char *, char **, off_t, int, int, int);
 STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
 STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
-STATIC int NCR_700_slave_attach(Scsi_Device *SDpnt);
-STATIC void NCR_700_slave_detach(Scsi_Device *SDpnt);
+STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt);
+STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt);
 
 static char *NCR_700_phase[] = {
 	"",
@@ -285,8 +285,8 @@
 	tpnt->cmd_per_lun = NCR_700_CMD_PER_LUN;
 	tpnt->use_clustering = DISABLE_CLUSTERING;
 	tpnt->proc_info = NCR_700_proc_directory_info;
-	tpnt->slave_attach = NCR_700_slave_attach;
-	tpnt->slave_detach = NCR_700_slave_detach;
+	tpnt->slave_configure = NCR_700_slave_configure;
+	tpnt->slave_destroy = NCR_700_slave_destroy;
 	tpnt->use_blk_tcq = 1;
 	tpnt->highmem_io = 1;
 	
@@ -1513,7 +1513,7 @@
 			       host->host_no, SCp, SCp == NULL ? NULL : SCp->host_scribble, dsp, dsp - hostdata->pScript);
 
 			/* clear all the negotiated parameters */
-			for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next)
+	    		list_for_each_entry(SDp, &host->my_devices, siblings)
 				SDp->hostdata = 0;
 			
 			/* clear all the slots and their pending commands */
@@ -1740,7 +1740,7 @@
 	len += sprintf(&buf[len],"\
 Target	Depth  Active  Next Tag\n\
 ======	=====  ======  ========\n");
-	for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) {
+	list_for_each_entry(SDp, &host->my_devices, siblings) {
 		len += sprintf(&buf[len]," %2d:%2d   %4d    %4d      %4d\n", SDp->id, SDp->lun, SDp->current_queue_depth, NCR_700_get_depth(SDp), SDp->current_tag);
 	}
 	if((len -= offset) <= 0)
@@ -1999,7 +1999,7 @@
 }
 
 STATIC int
-NCR_700_slave_attach(Scsi_Device *SDp)
+NCR_700_slave_configure(Scsi_Device *SDp)
 {
 	/* to do here: allocate memory; build a queue_full list */
 	if(SDp->tagged_supported) {
@@ -2012,7 +2012,7 @@
 }
 
 STATIC void
-NCR_700_slave_detach(Scsi_Device *SDp)
+NCR_700_slave_destroy(Scsi_Device *SDp)
 {
 	/* to do here: deallocate memory */
 }
diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
--- a/drivers/scsi/BusLogic.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/BusLogic.c	Wed Nov 27 14:36:32 2002
@@ -1,3 +1,4 @@
+
 /*
 
   Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
@@ -2702,14 +2703,14 @@
 }
 
 /*
-  BusLogic_SlaveAttach will actually set the queue depth on individual
+  BusLogic_SlaveConfigure will actually set the queue depth on individual
   scsi devices as they are permanently added to the device chain.  We
   shamelessly rip off the SelectQueueDepths code to make this work mostly
   like it used to.  Since we don't get called once at the end of the scan
   but instead get called for each device, we have to do things a bit
   differently.
 */
-int BusLogic_SlaveAttach(SCSI_Device_T *Device)
+int BusLogic_SlaveConfigure(SCSI_Device_T *Device)
 {
   BusLogic_HostAdapter_T *HostAdapter =
     (BusLogic_HostAdapter_T *) Device->host->hostdata;
diff -Nru a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
--- a/drivers/scsi/BusLogic.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/BusLogic.h	Wed Nov 27 14:36:30 2002
@@ -57,7 +57,7 @@
 extern int BusLogic_BIOSDiskParameters(struct scsi_device *,
 		struct block_device *, sector_t, int *);
 extern int BusLogic_ProcDirectoryInfo(char *, char **, off_t, int, int, int);
-extern int BusLogic_SlaveAttach(SCSI_Device_T *);
+extern int BusLogic_SlaveConfigure(SCSI_Device_T *);
 
 
 /*
@@ -72,7 +72,7 @@
     release:        BusLogic_ReleaseHostAdapter,  /* Release Host Adapter   */ \
     info:           BusLogic_DriverInfo,	  /* Driver Info Function   */ \
     queuecommand:   BusLogic_QueueCommand,	  /* Queue Command Function */ \
-    slave_attach:   BusLogic_SlaveAttach,	  /* Configure a SCSI_Device*/ \
+    slave_configure:BusLogic_SlaveConfigure,	  /* Configure a SCSI_Device*/ \
     bios_param:     BusLogic_BIOSDiskParameters,  /* BIOS Disk Parameters   */ \
     unchecked_isa_dma: 1,			  /* Default Initial Value  */ \
     max_sectors:    128,			  /* I/O queue len limit    */ \
diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/NCR53C9x.c	Wed Nov 27 14:36:28 2002
@@ -865,13 +865,13 @@
 	copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\n");
 	for(i = 0; i < 15; i++) {
 		if(esp->targets_present & (1 << i)) {
-			Scsi_Device *SDptr = esp->ehost->host_queue;
+			Scsi_Device *SDptr;
 			struct esp_device *esp_dev;
 
-			while((SDptr->host != esp->ehost) &&
-			      (SDptr->id != i) &&
-			      (SDptr->next))
-				SDptr = SDptr->next;
+			list_for_each_entry(SDptr, &esp->ehost->my_devices,
+					siblings)
+				if(SDptr->id == i)
+					break;
 
 			esp_dev = SDptr->hostdata;
 			copy_info(&info, "%d\t\t", i);
diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
--- a/drivers/scsi/NCR53c406a.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/NCR53c406a.c	Wed Nov 27 14:36:30 2002
@@ -55,7 +55,6 @@
 #include <linux/spinlock.h>
 #include "scsi.h"
 #include "hosts.h"
-#include "NCR53c406a.h"
 
 /* ============================================================= */
 
diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
--- a/drivers/scsi/aacraid/linit.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/scsi/aacraid/linit.c	Wed Nov 27 14:36:29 2002
@@ -128,7 +128,7 @@
 static int aac_eh_bus_reset(Scsi_Cmnd* cmd);
 static int aac_eh_reset(Scsi_Cmnd* cmd);
 
-static int aac_slave_attach(Scsi_Device *);
+static int aac_slave_configure(Scsi_Device *);
 
 /**
  *	aac_detect	-	Probe for aacraid cards
@@ -518,13 +518,13 @@
 }
 
 /**
- *	aac_slave_attach	-	do device specific setup
+ *	aac_slave_configure	-	do device specific setup
  *	@dev:	SCSI device we are attaching
  *
  * 	Currently, all we do is set the queue depth on the device.
  */
 
-static int aac_slave_attach(Scsi_Device * dev )
+static int aac_slave_configure(Scsi_Device * dev )
 {
 
 	if(dev->tagged_supported)
@@ -685,7 +685,7 @@
 	ioctl:          	aac_ioctl,
 	queuecommand:   	aac_queuecommand,
 	bios_param:     	aac_biosparm,	
-	slave_attach:		aac_slave_attach,
+	slave_configure:	aac_slave_configure,
 	can_queue:      	AAC_NUM_IO_FIB,	
 	this_id:        	16,
 	sg_tablesize:   	16,
diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
--- a/drivers/scsi/advansys.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/advansys.c	Wed Nov 27 14:36:28 2002
@@ -674,7 +674,7 @@
 	 1. hacks for lk 2.5 series (D. Gilbert)
 
      3.3GJD (10/14/02):
-         1. change select_queue_depths to slave_attach
+         1. change select_queue_depths to slave_configure
 	 2. make cmd_per_lun be sane again
 
   I. Known Problems/Fix List (XXX)
@@ -4209,7 +4209,7 @@
  */
 
 STATIC void       advansys_interrupt(int, void *, struct pt_regs *);
-STATIC int	  advansys_slave_attach(Scsi_Device *);
+STATIC int	  advansys_slave_configure(Scsi_Device *);
 STATIC void       asc_scsi_done_list(Scsi_Cmnd *, int from_isr);
 STATIC int        asc_execute_scsi_cmnd(Scsi_Cmnd *);
 STATIC int        asc_build_req(asc_board_t *, Scsi_Cmnd *);
@@ -4398,7 +4398,7 @@
      * Display target driver information for each device attached
      * to the board.
      */
-    for (scd = shp->host_queue; scd; scd = scd->next)
+    list_for_each_entry (scd, &shp->my_devices, siblings)
     {
         if (scd->host == shp) {
             cp = boardp->prtbuf;
@@ -6345,7 +6345,7 @@
  * specified host adapter.
  */
 STATIC int
-advansys_slave_attach(Scsi_Device *device)
+advansys_slave_configure(Scsi_Device *device)
 {
     asc_board_t        *boardp;
 
@@ -6368,7 +6368,7 @@
     } else {
 	scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun);
     }
-    ASC_DBG3(1, "advansys_slave_attach: shp 0x%lx, id %d, depth %d\n",
+    ASC_DBG3(1, "advansys_slave_configure: shp 0x%lx, id %d, depth %d\n",
             (ulong) shp, device->id, device->queue_depth);
     return 0;
 }
@@ -9386,8 +9386,8 @@
 
 #if ASC_LINUX_KERNEL24
     printk(
-" host_queue 0x%lx, hostt 0x%lx\n",
-        (ulong) s->host_queue, (ulong) s->hostt);
+" hostt 0x%lx\n",
+        (ulong) s->hostt);
 #elif ASC_LINUX_KERNEL22
     printk(
 " host_queue 0x%lx, hostt 0x%lx, block 0x%lx,\n",
diff -Nru a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h
--- a/drivers/scsi/advansys.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/advansys.h	Wed Nov 27 14:36:32 2002
@@ -54,7 +54,7 @@
 int advansys_reset(Scsi_Cmnd *);
 int advansys_biosparam(struct scsi_device *, struct block_device *,
 		sector_t, int[]);
-static int advansys_slave_attach(Scsi_Device *);
+static int advansys_slave_configure(Scsi_Device *);
 #ifdef CONFIG_PROC_FS
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,28)
 extern struct proc_dir_entry proc_scsi_advansys;
@@ -81,7 +81,7 @@
     queuecommand:               advansys_queuecommand, \
     eh_bus_reset_handler:	advansys_reset, \
     bios_param:                 advansys_biosparam, \
-    slave_attach:		advansys_slave_attach, \
+    slave_configure:		advansys_slave_configure, \
     /* \
      * Because the driver may control an ISA adapter 'unchecked_isa_dma' \
      * must be set. The flag will be cleared in advansys_detect for non-ISA \
diff -Nru a/drivers/scsi/aha152x.h b/drivers/scsi/aha152x.h
--- a/drivers/scsi/aha152x.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/aha152x.h	Wed Nov 27 14:36:31 2002
@@ -42,7 +42,6 @@
 		  eh_bus_reset_handler:		aha152x_bus_reset,	\
 		  eh_host_reset_handler:	aha152x_host_reset,	\
                   release:			aha152x_release,	\
-                  slave_attach:			0,			\
                   bios_param:			aha152x_biosparam,	\
                   can_queue:			1,			\
                   this_id:			7,			\
diff -Nru a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
--- a/drivers/scsi/aic7xxx/aic7770.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/aic7xxx/aic7770.c	Wed Nov 27 14:36:32 2002
@@ -50,6 +50,7 @@
 #define ID_AHA_274x	0x04907771
 #define ID_AHA_284xB	0x04907756 /* BIOS enabled */
 #define ID_AHA_284x	0x04907757 /* BIOS disabled*/
+#define ID_AIC_7782	0x04907782
 
 static void aha2840_load_seeprom(struct ahc_softc *ahc);
 static ahc_device_setup_t ahc_aic7770_VL_setup;
@@ -76,6 +77,13 @@
 		ID_AIC7770,
 		0xFFFFFFFF,
 		"Adaptec aic7770 SCSI adapter",
+		ahc_aic7770_EISA_setup
+	},
+	{
+		/* (Olivetti 2 channel EISA) */
+		ID_AIC_7782,
+		0xFFFFFFFF,
+		"Adaptec aic7782 SCSI adapter",
 		ahc_aic7770_EISA_setup
 	}
 };
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux.c b/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- a/drivers/scsi/aic7xxx/aic7xxx_linux.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux.c	Wed Nov 27 14:36:30 2002
@@ -428,7 +428,7 @@
 static void ahc_linux_release_sim_queue(u_long arg);
 static int  ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
 static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
-static int  ahc_linux_slave_attach(Scsi_Device *device);
+static int  ahc_linux_slave_configure(Scsi_Device *device);
 static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
 					 Scsi_Device *device);
 static struct ahc_linux_target*	ahc_linux_alloc_target(struct ahc_softc*,
@@ -1446,7 +1446,7 @@
  * off the input host adapter.
  */
 static int
-ahc_linux_slave_attach(Scsi_Device * device)
+ahc_linux_slave_configure(Scsi_Device * device)
 {
 	struct	ahc_softc *ahc;
 	u_long	flags;
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h
--- a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h	Wed Nov 27 14:36:29 2002
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h	Wed Nov 27 14:36:29 2002
@@ -72,7 +72,7 @@
 	eh_abort_handler: ahc_linux_abort,			\
 	eh_device_reset_handler: ahc_linux_dev_reset,		\
 	eh_bus_reset_handler: ahc_linux_bus_reset,		\
-	slave_attach: ahc_linux_slave_attach,			\
+	slave_configure: ahc_linux_slave_configure,		\
 	bios_param: AIC7XXX_BIOSPARAM,				\
 	can_queue: 253,		/* max simultaneous cmds      */\
 	this_id: -1,		/* scsi id of host adapter    */\
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h	Wed Nov 27 14:36:29 2002
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h	Wed Nov 27 14:36:29 2002
@@ -72,6 +72,7 @@
 #include <linux/version.h>
 #include <linux/module.h>
 #include <asm/byteorder.h>
+#include <asm/io.h>
 
 #ifndef KERNEL_VERSION
 #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
diff -Nru a/drivers/scsi/aic7xxx_old/aic7xxx.h b/drivers/scsi/aic7xxx_old/aic7xxx.h
--- a/drivers/scsi/aic7xxx_old/aic7xxx.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/aic7xxx_old/aic7xxx.h	Wed Nov 27 14:36:27 2002
@@ -35,8 +35,9 @@
 	release: aic7xxx_release,				\
 	info: aic7xxx_info,					\
 	queuecommand: aic7xxx_queue,				\
-	slave_attach: aic7xxx_slave_attach,			\
-	slave_detach: aic7xxx_slave_detach,			\
+	slave_alloc: aic7xxx_slave_alloc,			\
+	slave_configure: aic7xxx_slave_configure,		\
+	slave_destroy: aic7xxx_slave_destroy,			\
 	bios_param: aic7xxx_biosparam,				\
 	eh_abort_handler: aic7xxx_abort,			\
 	eh_device_reset_handler: aic7xxx_bus_device_reset,	\
@@ -56,8 +57,9 @@
 extern int aic7xxx_detect(Scsi_Host_Template *);
 extern int aic7xxx_command(Scsi_Cmnd *);
 extern int aic7xxx_release(struct Scsi_Host *);
-extern int aic7xxx_slave_attach(Scsi_Device *);
-extern void aic7xxx_slave_detach(Scsi_Device *);
+static int aic7xxx_slave_alloc(Scsi_Device *);
+static int aic7xxx_slave_configure(Scsi_Device *);
+static void aic7xxx_slave_destroy(Scsi_Device *);
 extern int aic7xxx_abort(Scsi_Cmnd *);
 extern int aic7xxx_bus_device_reset(Scsi_Cmnd *);
 extern int aic7xxx_reset(Scsi_Cmnd *);
diff -Nru a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c
--- a/drivers/scsi/aic7xxx_old/aic7xxx_proc.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/aic7xxx_old/aic7xxx_proc.c	Wed Nov 27 14:36:31 2002
@@ -313,7 +313,7 @@
                     p->user[tindex].options);
     if(sdptr->simple_tags)
     {
-      size += sprintf(BLS, "  Tagged Command Queueing Enabled, Ordered Tags %s\n", sdptr->ordered_tags ? "Enabled" : "Disabled");
+      size += sprintf(BLS, "  Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->new_queue_depth, aic_dev->max_q_depth);
     }
     if(aic_dev->barrier_total)
       size += sprintf(BLS, "  Total transfers %ld:\n    (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n",
diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
--- a/drivers/scsi/aic7xxx_old.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/scsi/aic7xxx_old.c	Wed Nov 27 14:36:29 2002
@@ -3137,36 +3137,18 @@
   struct scsi_device *sd;
   unsigned char active_scb, tcl, scb_tag;
   int i = 0, init_lists = FALSE;
-  struct aic_dev_data *aic_dev, *remove_aic_dev = NULL;
+  struct aic_dev_data *aic_dev;
 
   /*
    * Restore this when we're done
    */
   active_scb = aic_inb(p, SCBPTR);
-  /*
-   * If we are still scanning devices, this device may not be linked into
-   * our host controller yet.  So, we grab the temporary aic_dev that we
-   * allocate during the device scan (by getting device->hostdata for the
-   * active device) and if the list struct in the aic_dev is empty, we
-   * add it to p->aic_devs.  Then at the end of the function, if we added
-   * the aic_dev to our host struct so our loop would work, then we just
-   * remove it.
-   */
   scb_tag = aic_inb(p, SCB_TAG);
-  if(scb_tag < p->scb_data->numscbs)
-  {
-    scbp = p->scb_data->scb_array[scb_tag];
-    remove_aic_dev = (struct aic_dev_data *)scbp->cmd->device->hostdata;
-    if(list_empty(&remove_aic_dev->list))
-      list_add_tail(&remove_aic_dev->list, &p->aic_devs);
-    else
-      remove_aic_dev = NULL;
-  }
 
   if (aic7xxx_verbose & (VERBOSE_RESET_PROCESS | VERBOSE_ABORT_PROCESS))
   {
-    printk(INFO_LEAD "Reset device, hardware_scb %d, aic_dev %p,\n",
-         p->host_no, channel, target, lun, active_scb, remove_aic_dev);
+    printk(INFO_LEAD "Reset device, hardware_scb %d,\n",
+         p->host_no, channel, target, lun, active_scb);
     printk(INFO_LEAD "Current scb %d, SEQADDR 0x%x, LASTPHASE "
            "0x%x\n",
          p->host_no, channel, target, lun, scb_tag,
@@ -3230,8 +3212,6 @@
       }
     }
   }
-  if (remove_aic_dev)
-    list_del(&remove_aic_dev->list);
 
   if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
     printk(INFO_LEAD "Cleaning QINFIFO.\n", p->host_no, channel, target, lun );
@@ -3956,6 +3936,7 @@
   unsigned char target, lun, tindex;
   unsigned char queue_flag = FALSE;
   char channel;
+  int result;
 
   target = ((aic_inb(p, SAVED_TCL) >> 4) & 0x0f);
   if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 )
@@ -4457,69 +4438,42 @@
                   printk(INFO_LEAD "Target busy\n", p->host_no, CTL_OF_SCB(scb));
               }
 #endif
-#if 0
               if (queue_flag)
               {
-                if ( p->dev_last_queue_full[tindex] !=
-                     p->dev_active_cmds[tindex] )
-                {
-                  p->dev_last_queue_full[tindex] = 
-                      p->dev_active_cmds[tindex];
-                  p->dev_last_queue_full_count[tindex] = 0;
-                }
-                else
-                {
-                  p->dev_last_queue_full_count[tindex]++;
-                }
-                if ( (p->dev_last_queue_full_count[tindex] > 14) &&
-                     (p->dev_active_cmds[tindex] > 4) )
-                {
-		  int diff, lun;
-		  if (p->dev_active_cmds[tindex] > p->dev_lun_queue_depth[tindex])
-		    /* We don't know what to do here, so bail. */
-		    break;
+		int diff;
+		result = scsi_track_queue_full(cmd->device,
+			       	aic_dev->active_cmds);
+		if ( result < 0 )
+		{
+                  if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
+                    printk(INFO_LEAD "Tagged Command Queueing disabled.\n",
+			p->host_no, CTL_OF_SCB(scb));
+		  diff = aic_dev->max_q_depth - p->host->cmd_per_lun;
+		  aic_dev->temp_q_depth = 1;
+		  aic_dev->max_q_depth = 1;
+		}
+		else if ( result > 0 )
+		{
                   if (aic7xxx_verbose & VERBOSE_NEGOTIATION2)
                     printk(INFO_LEAD "Queue depth reduced to %d\n", p->host_no,
-                      CTL_OF_SCB(scb), p->dev_active_cmds[tindex]);
-		  diff = p->dev_lun_queue_depth[tindex] -
-			 p->dev_active_cmds[tindex];
-		  p->dev_lun_queue_depth[tindex] -= diff;
-		  for(lun = 0; lun < p->host->max_lun; lun++)
-		  {
-		    if(p->Scsi_Dev[tindex][lun] != NULL)
-		    {
-		      p->dev_max_queue_depth[tindex] -= diff;
-		      scsi_adjust_queue_depth(p->Scsi_Dev[tindex][lun], 1,
-				              p->dev_lun_queue_depth[tindex]);
-		      if(p->dev_temp_queue_depth[tindex] > p->dev_max_queue_depth[tindex])
-		        p->dev_temp_queue_depth[tindex] = p->dev_max_queue_depth[tindex];
-		    }
-		  }
-                  p->dev_last_queue_full[tindex] = 0;
-                  p->dev_last_queue_full_count[tindex] = 0;
-                }
-                else if (p->dev_active_cmds[tindex] == 0)
-                {
-                  if (aic7xxx_verbose & VERBOSE_NEGOTIATION)
-                  {
-                    printk(INFO_LEAD "QUEUE_FULL status received with 0 "
-                           "commands active.\n", p->host_no, CTL_OF_SCB(scb));
-                    printk(INFO_LEAD "Tagged Command Queueing disabled\n",
-                           p->host_no, CTL_OF_SCB(scb));
-                  }
-                  p->dev_max_queue_depth[tindex] = 1;
-                  p->dev_temp_queue_depth[tindex] = 1;
-                  scb->tag_action = 0;
-                  scb->hscb->control &= ~(MSG_ORDERED_Q_TAG|MSG_SIMPLE_Q_TAG);
-                }
-                else
-                {
-                  aic_dev->flags[tindex] |= DEVICE_WAS_BUSY;
-                  p->dev_temp_queue_depth[tindex] = 
-                    p->dev_active_cmds[tindex];
-                }
-              }
-#endif
+                      CTL_OF_SCB(scb), result);
+		  diff = aic_dev->max_q_depth - result;
+		  aic_dev->max_q_depth = result;
+		  /* temp_q_depth could have been dropped to 1 for an untagged
+		   * command that might be coming up */
+		  if(aic_dev->temp_q_depth > result)
+		    aic_dev->temp_q_depth = result;
+		}
+		/* We should free up the no unused SCB entries.  But, that's
+		 * a difficult thing to do because we use a direct indexed
+		 * array, so we can't just take any entries and free them,
+		 * we *have* to free the ones at the end of the array, and
+		 * they very well could be in use right now, which means
+		 * in order to do this right, we have to add a delayed
+		 * freeing mechanism tied into the scb_free() code area.
+		 * We'll add that later.
+		 */
+	      }
               break;
             }
             
@@ -6623,19 +6577,42 @@
 
 /*+F*************************************************************************
  * Function:
- *   aic7xxx_alloc_aic_dev
+ *   aic7xxx_slave_alloc
  *
  * Description:
  *   Set up the initial aic_dev struct pointers
  *-F*************************************************************************/
-static struct aic_dev_data *
-aic7xxx_alloc_aic_dev(struct aic7xxx_host *p, Scsi_Device *SDptr)
+static int
+aic7xxx_slave_alloc(Scsi_Device *SDptr)
 {
+  struct aic7xxx_host *p = (struct aic7xxx_host *)SDptr->host->hostdata;
   struct aic_dev_data *aic_dev;
 
   aic_dev = kmalloc(sizeof(struct aic_dev_data), GFP_ATOMIC | GFP_KERNEL);
   if(!aic_dev)
-    return aic_dev;
+    return 1;
+  /*
+   * Check to see if channel was scanned.
+   */
+  
+  if (!(p->flags & AHC_A_SCANNED) && (SDptr->channel == 0))
+  {
+    if (aic7xxx_verbose & VERBOSE_PROBE2)
+      printk(INFO_LEAD "Scanning channel for devices.\n",
+        p->host_no, 0, -1, -1);
+    p->flags |= AHC_A_SCANNED;
+  }
+  else
+  {
+    if (!(p->flags & AHC_B_SCANNED) && (SDptr->channel == 1))
+    {
+      if (aic7xxx_verbose & VERBOSE_PROBE2)
+        printk(INFO_LEAD "Scanning channel for devices.\n",
+          p->host_no, 1, -1, -1);
+      p->flags |= AHC_B_SCANNED;
+    }
+  }
+
   memset(aic_dev, 0, sizeof(struct aic_dev_data));
   SDptr->hostdata = aic_dev;
   aic_dev->SDptr = SDptr;
@@ -6643,7 +6620,8 @@
   aic_dev->temp_q_depth = 1;
   scbq_init(&aic_dev->delayed_scbs);
   INIT_LIST_HEAD(&aic_dev->list);
-  return aic_dev;
+  list_add_tail(&aic_dev->list, &p->aic_devs);
+  return 0;
 }
 
 /*+F*************************************************************************
@@ -6752,13 +6730,13 @@
 
 /*+F*************************************************************************
  * Function:
- *   aic7xxx_slave_detach
+ *   aic7xxx_slave_destroy
  *
  * Description:
  *   prepare for this device to go away
  *-F*************************************************************************/
-void
-aic7xxx_slave_detach(Scsi_Device *sdpnt)
+static void
+aic7xxx_slave_destroy(Scsi_Device *sdpnt)
 {
   struct aic_dev_data *aic_dev = sdpnt->hostdata;
 
@@ -6770,15 +6748,15 @@
 
 /*+F*************************************************************************
  * Function:
- *   aic7xxx_slave_attach
+ *   aic7xxx_slave_configure
  *
  * Description:
  *   Configure the device we are attaching to the controller.  This is
  *   where we get to do things like scan the INQUIRY data, set queue
  *   depths, allocate command structs, etc.
  *-F*************************************************************************/
-int
-aic7xxx_slave_attach(Scsi_Device *sdpnt)
+static int
+aic7xxx_slave_configure(Scsi_Device *sdpnt)
 {
   struct aic7xxx_host *p = (struct aic7xxx_host *) sdpnt->host->hostdata;
   struct aic_dev_data *aic_dev;
@@ -6786,12 +6764,6 @@
 
   aic_dev = (struct aic_dev_data *)sdpnt->hostdata;
 
-  if(!aic_dev) {
-    aic_dev = aic7xxx_alloc_aic_dev(p, sdpnt);
-  }
-  if(!aic_dev)
-    return 1;
-  
   aic7xxx_init_transinfo(p, aic_dev);
   aic7xxx_device_queue_depth(p, sdpnt);
   if(list_empty(&aic_dev->list))
@@ -10337,39 +10309,7 @@
   p = (struct aic7xxx_host *) cmd->host->hostdata;
 
   aic_dev = cmd->device->hostdata;  
-  if(!aic_dev) {
-    aic_dev = aic7xxx_alloc_aic_dev(p, cmd->device);
-    if(!aic_dev)
-      return 1;
-  }
-  else
-  {
-    aic_dev = AIC_DEV(cmd);
-  }
-
 #ifdef AIC7XXX_VERBOSE_DEBUGGING
-  /*
-   * Check to see if channel was scanned.
-   */
-  
-  if (!(p->flags & AHC_A_SCANNED) && (cmd->channel == 0))
-  {
-    if (aic7xxx_verbose & VERBOSE_PROBE2)
-      printk(INFO_LEAD "Scanning channel for devices.\n",
-        p->host_no, 0, -1, -1);
-    p->flags |= AHC_A_SCANNED;
-  }
-  else
-  {
-    if (!(p->flags & AHC_B_SCANNED) && (cmd->channel == 1))
-    {
-      if (aic7xxx_verbose & VERBOSE_PROBE2)
-        printk(INFO_LEAD "Scanning channel for devices.\n",
-          p->host_no, 1, -1, -1);
-      p->flags |= AHC_B_SCANNED;
-    }
-  }
-
   if (aic_dev->active_cmds > aic_dev->max_q_depth)
   {
     printk(WARN_LEAD "Commands queued exceeds queue "
@@ -10975,7 +10915,8 @@
 aic7xxx_biosparam(struct scsi_device *sdev, struct block_device *bdev,
 		sector_t capacity, int geom[])
 {
-  int heads, sectors, cylinders, ret;
+  sector_t heads, sectors, cylinders;
+  int ret;
   struct aic7xxx_host *p;
   unsigned char *buf;
 
@@ -10992,18 +10933,22 @@
   
   heads = 64;
   sectors = 32;
-  cylinders = (unsigned long)capacity / (heads * sectors);
+  cylinders = capacity >> 11;
 
   if ((p->flags & AHC_EXTEND_TRANS_A) && (cylinders > 1024))
   {
     heads = 255;
     sectors = 63;
-    cylinders = (unsigned long)capacity / (heads * sectors);
+    cylinders = capacity >> 14;
+    if(capacity > (65535 * heads * sectors))
+      cylinders = 65535;
+    else
+      cylinders = ((unsigned int)capacity) / (unsigned int)(heads * sectors);
   }
 
-  geom[0] = heads;
-  geom[1] = sectors;
-  geom[2] = cylinders;
+  geom[0] = (int)heads;
+  geom[1] = (int)sectors;
+  geom[2] = (int)cylinders;
 
   return (0);
 }
diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
--- a/drivers/scsi/cpqfcTSinit.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/cpqfcTSinit.c	Wed Nov 27 14:36:27 2002
@@ -1601,7 +1601,7 @@
   scsi_cdb[0] = RELEASE;
 
   // allocate with wait = true, interruptible = false 
-  SCpnt = scsi_allocate_device(ScsiDev, 1, 0);
+  SCpnt = scsi_allocate_device(ScsiDev, 1);
   {
     CPQFC_DECLARE_COMPLETION(wait);
     
diff -Nru a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c
--- a/drivers/scsi/cpqfcTSworker.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/cpqfcTSworker.c	Wed Nov 27 14:36:31 2002
@@ -3487,7 +3487,6 @@
 static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, 
 		        PFC_LOGGEDIN_PORT pLoggedInPort)
 {
-//  Scsi_Device *sdev = HostAdapter->host_queue;
   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
   Scsi_Cmnd* *SCptr = &cpqfcHBAdata->LinkDnCmnd[0];
   Scsi_Cmnd *Cmnd;
diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
--- a/drivers/scsi/dmx3191d.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/dmx3191d.c	Wed Nov 27 14:36:30 2002
@@ -31,6 +31,7 @@
 #include <linux/signal.h>
 #include <linux/stat.h>
 #include <linux/version.h>
+#include <linux/interrupt.h>
 #include <linux/delay.h>
 
 #include "scsi.h"
diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
--- a/drivers/scsi/dpt_i2o.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/dpt_i2o.c	Wed Nov 27 14:36:31 2002
@@ -355,7 +355,7 @@
 }
 
 
-static int adpt_slave_attach(Scsi_Device * device)
+static int adpt_slave_configure(Scsi_Device * device)
 {
 	struct Scsi_Host *host = device->host;
 	adpt_hba* pHba;
@@ -2509,20 +2509,13 @@
 	Scsi_Cmnd* 	cmd = NULL;
 	Scsi_Device* 	d = NULL;
 
-	if( pHba->host->host_queue != NULL ) {
-		d = pHba->host->host_queue;
-		if(!d){
-			return;
-		}
-		while( d->next != NULL ){
-			for(cmd = d->device_queue; cmd ; cmd = cmd->next){
-				if(cmd->serial_number == 0){
-					continue;
-				}
-				cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
-				cmd->scsi_done(cmd);
+	list_for_each_entry(d, &pHba->host->my_devices, siblings) {
+		for(cmd = d->device_queue; cmd ; cmd = cmd->next){
+			if(cmd->serial_number == 0){
+				continue;
 			}
-			d = d->next;
+			cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
+			cmd->scsi_done(cmd);
 		}
 	}
 }
diff -Nru a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
--- a/drivers/scsi/dpti.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/dpti.h	Wed Nov 27 14:36:27 2002
@@ -44,7 +44,7 @@
 static int adpt_abort(Scsi_Cmnd * cmd);
 static int adpt_reset(Scsi_Cmnd* cmd);
 static int adpt_release(struct Scsi_Host *host);
-static int adpt_slave_attach(Scsi_Device *);
+static int adpt_slave_configure(Scsi_Device *);
 
 static const char *adpt_info(struct Scsi_Host *pSHost);
 static int adpt_bios_param(struct scsi_device * sdev, struct block_device *dev,
@@ -93,7 +93,7 @@
 	eh_bus_reset_handler: adpt_bus_reset,				\
 	eh_host_reset_handler: adpt_reset,				\
 	bios_param: adpt_bios_param,					\
-	slave_attach: adpt_slave_attach,				\
+	slave_configure: adpt_slave_configure,				\
 	can_queue: MAX_TO_IOP_MESSAGES,	/* max simultaneous cmds      */\
 	this_id: 7,			/* scsi id of host adapter    */\
 	sg_tablesize: 0,		/* max scatter-gather cmds    */\
diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
--- a/drivers/scsi/dtc.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/dtc.c	Wed Nov 27 14:36:31 2002
@@ -78,15 +78,16 @@
 #include <linux/sched.h>
 #include <linux/blk.h>
 #include <linux/delay.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include "scsi.h"
 #include "hosts.h"
 #include "dtc.h"
 #define AUTOPROBE_IRQ
 #include "NCR5380.h"
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/init.h>
 
 
 #define DTC_PUBLIC_RELEASE 2
diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c
--- a/drivers/scsi/eata.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/eata.c	Wed Nov 27 14:36:31 2002
@@ -464,6 +464,7 @@
 
 #endif
 
+#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -474,18 +475,18 @@
 #include <asm/byteorder.h>
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
-#include "scsi.h"
-#include "hosts.h"
-#include <asm/dma.h>
-#include <asm/irq.h>
-#include "eata.h"
+#include <linux/interrupt.h>
 #include <linux/stat.h>
-#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
 #include <scsi/scsicam.h>
+#include "scsi.h"
+#include "hosts.h"
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include "eata.h"
 
 #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD)
 #error "Adjust your <asm/byteorder.h> defines"
@@ -802,7 +803,7 @@
 static int pci_probe = FALSE;
 #endif
 
-static int eata2x_slave_attach(Scsi_Device *dev) {
+static int eata2x_slave_configure(Scsi_Device *dev) {
    int j, tqd, utqd;
    char *tag_suffix, *link_suffix;
    struct Scsi_Host *host = dev->host;
diff -Nru a/drivers/scsi/eata.h b/drivers/scsi/eata.h
--- a/drivers/scsi/eata.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/eata.h	Wed Nov 27 14:36:28 2002
@@ -9,7 +9,7 @@
 static int eata2x_eh_host_reset(Scsi_Cmnd *);
 static int eata2x_biosparam(struct scsi_device *, struct block_device *,
 		sector_t, int *);
-static int eata2x_slave_attach(Scsi_Device *);
+static int eata2x_slave_configure(Scsi_Device *);
 
 #define EATA_VERSION "8.00.00"
 
@@ -23,7 +23,7 @@
                 eh_bus_reset_handler:    NULL,                               \
                 eh_host_reset_handler:   eata2x_eh_host_reset,               \
                 bios_param:              eata2x_bios_param,                  \
-		slave_attach:		 eata2x_slave_attach,		     \
+		slave_configure:	 eata2x_slave_configure,	     \
                 this_id:                 7,                                  \
                 unchecked_isa_dma:       1,                                  \
                 use_clustering:          ENABLE_CLUSTERING                   \
diff -Nru a/drivers/scsi/eata_dma_proc.c b/drivers/scsi/eata_dma_proc.c
--- a/drivers/scsi/eata_dma_proc.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/eata_dma_proc.c	Wed Nov 27 14:36:31 2002
@@ -431,11 +431,11 @@
     }
 
     size = sprintf(buffer+len,"Attached devices: %s\n", 
-		   (HBA_ptr->host_queue)?"":"none");
+		   (!list_empty(&HBA_ptr->my_devices))?"":"none");
     len += size; 
     pos = begin + len;
     
-    for(scd = HBA_ptr->host_queue; scd; scd = scd->next) {
+    list_for_each_entry(scd, &HBA_ptr->my_devices, siblings) {
 	    proc_print_scsidevice(scd, buffer, &size, len);
 	    len += size; 
 	    pos = begin + len;
diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
--- a/drivers/scsi/eata_pio.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/eata_pio.c	Wed Nov 27 14:36:31 2002
@@ -58,6 +58,7 @@
 #include <linux/in.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include "eata_pio.h"
 #include "eata_dma_proc.h"
@@ -805,13 +806,13 @@
 	u32 base, x;
 
 	while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) {
-		DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->name));
+		DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->dev.name));
 		if (pci_enable_device(dev))
 			continue;
 		pci_set_master(dev);
 		base = pci_resource_flags(dev, 0);
 		if (base & IORESOURCE_MEM) {
-			printk("eata_pio: invalid base address of device %s\n", dev->name);
+			printk("eata_pio: invalid base address of device %s\n", dev->dev.name);
 			continue;
 		}
 		base = pci_resource_start(dev, 0);
diff -Nru a/drivers/scsi/eata_pio_proc.c b/drivers/scsi/eata_pio_proc.c
--- a/drivers/scsi/eata_pio_proc.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/eata_pio_proc.c	Wed Nov 27 14:36:31 2002
@@ -81,11 +81,11 @@
 	goto stop_output;
     
     size = sprintf(buffer+len,"Attached devices: %s\n", 
-		   (HBA_ptr->host_queue)?"":"none");
+		   (!list_empty(&HBA_ptr->my_devices))?"":"none");
     len += size; 
     pos = begin + len;
     
-    for(scd = HBA_ptr->host_queue; scd; scd = scd->next) {
+    list_for_each_entry(scd, &HBA_ptr->my_devices; siblings) {
 	    proc_print_scsidevice(scd, buffer, &size, len);
 	    len += size; 
 	    pos = begin + len;
diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c
--- a/drivers/scsi/esp.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/esp.c	Wed Nov 27 14:36:32 2002
@@ -1364,13 +1364,13 @@
 	copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\tWide\n");
 	for (i = 0; i < 15; i++) {
 		if (esp->targets_present & (1 << i)) {
-			Scsi_Device *SDptr = esp->ehost->host_queue;
+			Scsi_Device *SDptr;
 			struct esp_device *esp_dev;
 
-			while ((SDptr->host != esp->ehost) &&
-			       (SDptr->id != i) &&
-			       (SDptr->next))
-				SDptr = SDptr->next;
+			list_for_each_entry(SDptr, &esp->ehost->my_devices,
+					siblings)
+				if(SDptr->id == i)
+					break;
 
 			esp_dev = SDptr->hostdata;
 			copy_info(&info, "%d\t\t", i);
@@ -1562,24 +1562,6 @@
 	lun = SCptr->lun;
 	target = SCptr->target;
 
-	/*
-	 * We check that esp_dev != NULL.  If it is, we allocate it or bail.
-	 */
-	if (!esp_dev) {
-		esp_dev = kmalloc(sizeof(struct esp_device), GFP_ATOMIC);
-		if (!esp_dev) {
-			/* We're SOL.  Print a message and bail */
-			printk(KERN_WARNING "esp: no mem for esp_device %d/%d\n",
-					target, lun);
-			esp->current_SC = NULL;
-			SCptr->result = DID_ERROR << 16;
-			SCptr->done(SCptr);
-			return;
-		}
-		memset(esp_dev, 0, sizeof(struct esp_device));
-		SDptr->hostdata = esp_dev;
-	}
-
 	esp->snip = 0;
 	esp->msgout_len = 0;
 
@@ -4357,12 +4339,24 @@
 	spin_unlock_irqrestore(esp->ehost->host_lock, flags);
 }
 
-static void esp_slave_detach(Scsi_Device* SDptr)
+static int esp_slave_alloc(Scsi_Device *SDptr)
+{
+	struct esp_device *esp_dev =
+		kmalloc(sizeof(struct esp_device), GFP_ATOMIC);
+
+	if (!esp_dev)
+		return -ENOMEM;
+	memset(esp_dev, 0, sizeof(struct esp_device));
+	SDptr->hostdata = esp_dev;
+	return 0;
+}
+
+static void esp_slave_destroy(Scsi_Device *SDptr)
 {
 	struct esp *esp = (struct esp *) SDptr->host->hostdata;
+
 	esp->targets_present &= ~(1 << SDptr->id);
-	if (SDptr->hostdata)
-		kfree(SDptr->hostdata);
+	kfree(SDptr->hostdata);
 	SDptr->hostdata = NULL;
 }
 
@@ -4372,7 +4366,8 @@
 	.proc_info		= esp_proc_info,
 	.name			= "Sun ESP 100/100a/200",
 	.detect			= esp_detect,
-	.slave_detach		= esp_slave_detach,
+	.slave_alloc		= esp_slave_alloc,
+	.slave_destroy		= esp_slave_destroy,
 	.info			= esp_info,
 	.command		= esp_command,
 	.queuecommand		= esp_queue,
diff -Nru a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
--- a/drivers/scsi/fcal.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/fcal.c	Wed Nov 27 14:36:27 2002
@@ -70,7 +70,7 @@
 
 static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
 
-int fcal_slave_attach(Scsi_Device *device)
+int fcal_slave_configure(Scsi_Device *device)
 {
 	int depth_to_use;
 	
@@ -229,7 +229,7 @@
 #endif
 	SPRINTF ("Initiator AL-PA: %02x\n", fc->sid);
 
-	SPRINTF ("\nAttached devices: %s\n", host->host_queue ? "" : "none");
+	SPRINTF ("\nAttached devices: %s\n", !list_empty(&host->my_devices) ? "" : "none");
 	
 	for (i = 0; i < fc->posmap->len; i++) {
 		unsigned char alpa = fc->posmap->list[i];
@@ -246,8 +246,8 @@
 				 alpa, u1[0], u1[1], u2[0], u2[1]);
 		} else {
 			Scsi_Device *scd;
-			for (scd = host->host_queue ; scd; scd = scd->next)
-				if (scd->host->host_no == hostno && scd->id == target) {
+			list_for_each_entry (scd, &host->my_devices, siblings)
+				if (scd->id == target) {
 					SPRINTF ("  [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x]  ",
 						alpa, target, u1[0], u1[1], u2[0], u2[1]);
 					SPRINTF ("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ?
diff -Nru a/drivers/scsi/fcal.h b/drivers/scsi/fcal.h
--- a/drivers/scsi/fcal.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/fcal.h	Wed Nov 27 14:36:27 2002
@@ -23,7 +23,7 @@
 int fcal_detect(Scsi_Host_Template *);
 int fcal_release(struct Scsi_Host *);
 int fcal_proc_info (char *, char **, off_t, int, int, int);
-int fcal_slave_attach(Scsi_Device *);
+int fcal_slave_configure(Scsi_Device *);
 
 #define FCAL {							\
 	name:			"Fibre Channel Arbitrated Loop",\
@@ -31,7 +31,7 @@
 	release:		fcal_release,			\
 	proc_info:		fcal_proc_info,			\
 	queuecommand:		fcp_scsi_queuecommand,		\
-	slave_attach:		fcal_slave_attach,		\
+	slave_configure:	fcal_slave_configure,		\
 	can_queue:		FCAL_CAN_QUEUE,			\
 	this_id:		-1,				\
 	sg_tablesize:		1,				\
diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
--- a/drivers/scsi/g_NCR5380.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/g_NCR5380.c	Wed Nov 27 14:36:28 2002
@@ -814,7 +814,7 @@
 		PRINTP("  %d pending writes" ANDP hostdata->pendingw);
 	if (hostdata->pendingr || hostdata->pendingw)
 		PRINTP("\n");
-	for (dev = scsi_ptr->host_queue; dev; dev = dev->next) {
+	list_for_each_entry (dev, &scsi_ptr->my_devices, siblings) {
 		unsigned long br = hostdata->bytes_read[dev->id];
 		unsigned long bw = hostdata->bytes_write[dev->id];
 		long tr = hostdata->time_read[dev->id] / HZ;
diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
--- a/drivers/scsi/gdth.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/gdth.c	Wed Nov 27 14:36:31 2002
@@ -4599,7 +4599,7 @@
 
 #if LINUX_VERSION_CODE >= 0x020322
     sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-    scp  = scsi_allocate_device(sdev, 1, FALSE);
+    scp  = scsi_allocate_device(sdev, 1);
     scp->cmd_len = 12;
     scp->use_sg = 0;
 #else
@@ -4673,7 +4673,7 @@
         memset(cmnd, 0xff, MAX_COMMAND_SIZE);
 #if LINUX_VERSION_CODE >= 0x020322
         sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-        scp  = scsi_allocate_device(sdev, 1, FALSE);
+        scp  = scsi_allocate_device(sdev, 1);
         scp->cmd_len = 12;
         scp->use_sg = 0;
 #else
diff -Nru a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
--- a/drivers/scsi/gdth_proc.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/gdth_proc.c	Wed Nov 27 14:36:30 2002
@@ -48,7 +48,7 @@
 
 #if LINUX_VERSION_CODE >= 0x020322
     sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
-    scp  = scsi_allocate_device(sdev, 1, FALSE);
+    scp  = scsi_allocate_device(sdev, 1);
     if (!scp)
         return -ENOMEM;
     scp->cmd_len = 12;
@@ -712,7 +712,7 @@
 
 #if LINUX_VERSION_CODE >= 0x020322
     sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
-    scp  = scsi_allocate_device(sdev, 1, FALSE);
+    scp  = scsi_allocate_device(sdev, 1);
     if (!scp)
         return -ENOMEM;
     scp->cmd_len = 12;
diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/hosts.c	Wed Nov 27 14:36:27 2002
@@ -208,6 +208,48 @@
 	return 0;
 }
 
+static int scsi_check_device_busy(struct scsi_device *sdev)
+{
+	struct Scsi_Host *shost = sdev->host;
+	struct scsi_cmnd *scmd;
+
+	/*
+	 * Loop over all of the commands associated with the
+	 * device.  If any of them are busy, then set the state
+	 * back to inactive and bail.
+	 */
+	for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
+		if (scmd->request && scmd->request->rq_status != RQ_INACTIVE)
+			goto active;
+
+		/*
+		 * No, this device is really free.  Mark it as such, and
+		 * continue on.
+		 */
+		scmd->state = SCSI_STATE_DISCONNECTING;
+		if (scmd->request)
+			scmd->request->rq_status = RQ_SCSI_DISCONNECTING;
+	}
+
+	return 0;
+
+active:
+	printk(KERN_ERR "SCSI device not inactive - rq_status=%d, target=%d, "
+			"pid=%ld, state=%d, owner=%d.\n",
+			scmd->request->rq_status, scmd->target,
+			scmd->pid, scmd->state, scmd->owner);
+
+	list_for_each_entry(sdev, &shost->my_devices, siblings) {
+		for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
+			if (scmd->request->rq_status == RQ_SCSI_DISCONNECTING)
+				scmd->request->rq_status = RQ_INACTIVE;
+		}
+	}
+
+	printk(KERN_ERR "Device busy???\n");
+	return 1;
+}
+
 /**
  * scsi_remove_host - check a scsi host for release and release
  * @shost:	a pointer to a scsi host to release
@@ -218,59 +260,25 @@
 int scsi_remove_host(struct Scsi_Host *shost)
 {
 	struct scsi_device *sdev;
-	struct scsi_cmnd *scmd;
+	struct list_head *le, *lh;
 
 	/*
 	 * FIXME Do ref counting.  We force all of the devices offline to
 	 * help prevent race conditions where other hosts/processors could
 	 * try and get in and queue a command.
 	 */
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next) 
+	list_for_each_entry(sdev, &shost->my_devices, siblings)
 		sdev->online = FALSE;
 
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
-		/*
-		 * Loop over all of the commands associated with the
-		 * device.  If any of them are busy, then set the state
-		 * back to inactive and bail.
-		 */
-		for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
-			if (scmd->request && scmd->request->rq_status !=
-			    RQ_INACTIVE) {
-				printk(KERN_ERR "SCSI device not inactive"
-				       "- rq_status=%d, target=%d, pid=%ld,"
-				       "state=%d, owner=%d.\n",
-				       scmd->request->rq_status,
-				       scmd->target, scmd->pid,
-				       scmd->state, scmd->owner);
-				for (sdev = shost->host_queue; sdev;
-				     sdev = sdev->next) {
-					for (scmd = sdev->device_queue; scmd;
-					     scmd = scmd->next)
-						if (scmd->request->rq_status ==
-						    RQ_SCSI_DISCONNECTING)
-							scmd->request->rq_status = RQ_INACTIVE;
-				}
-				printk(KERN_ERR "Device busy???\n");
-				return 1;
-			}
-			/*
-			 * No, this device is really free.  Mark it as such, and
-			 * continue on.
-			 */
-			scmd->state = SCSI_STATE_DISCONNECTING;
-			if (scmd->request)
-				scmd->request->rq_status =
-					RQ_SCSI_DISCONNECTING;	/* Mark as
-								   busy */
-		}
-	}
+	list_for_each_entry(sdev, &shost->my_devices, siblings)
+		if (scsi_check_device_busy(sdev))
+			return 1;
 
 	/*
 	 * Next we detach the high level drivers from the Scsi_Device
 	 * structures
 	 */
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+	list_for_each_entry(sdev, &shost->my_devices, siblings) {
 		scsi_detach_device(sdev);
 
 		/* If something still attached, punt */
@@ -285,14 +293,8 @@
 
 	/* Next we free up the Scsi_Cmnd structures for this host */
 
-	for (sdev = shost->host_queue; sdev;
-	     sdev = shost->host_queue) {
-		blk_cleanup_queue(&sdev->request_queue);
-		/* Next free up the Scsi_Device structures for this host */
-		shost->host_queue = sdev->next;
-		if (sdev->inquiry)
-			kfree(sdev->inquiry);
-		kfree(sdev);
+	list_for_each_safe(le, lh, &shost->my_devices) {
+		scsi_free_sdev(list_entry(le, Scsi_Device, siblings));
 	}
 
 	return 0;
@@ -302,23 +304,21 @@
 {
 	Scsi_Host_Template *sht = shost->hostt;
 	struct scsi_device *sdev;
-	int error = 0;
+	int error = 0, saved_error = 0;
 
 	printk(KERN_INFO "scsi%d : %s\n", shost->host_no,
 			sht->info ? sht->info(shost) : sht->name);
 
 	device_register(&shost->host_driverfs_dev);
-	scan_scsis(shost, 0, 0, 0, 0);
+	scsi_scan_host(shost);
 			
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
-		if (sdev->host->hostt != sht)
-			continue; /* XXX(hch): can this really happen? */
+	list_for_each_entry (sdev, &shost->my_devices, siblings) {
 		error = scsi_attach_device(sdev);
 		if (error)
-			break;
+			saved_error = error;
 	}
 
-	return error;
+	return saved_error;
 }
 
 /**
@@ -370,7 +370,6 @@
 struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
 {
 	struct Scsi_Host *shost, *shost_scr;
-	struct list_head *lh;
 	int gfp_mask;
 	DECLARE_MUTEX_LOCKED(sem);
 
@@ -401,6 +400,7 @@
 	spin_lock_init(&shost->default_lock);
 	scsi_assign_lock(shost, &shost->default_lock);
 	atomic_set(&shost->host_active,0);
+	INIT_LIST_HEAD(&shost->my_devices);
 
 	init_waitqueue_head(&shost->host_wait);
 	shost->dma_channel = 0xff;
@@ -449,8 +449,7 @@
 	 * orders the scsi_host_list by host number and just do a
 	 * list_add_tail.
 	 */
-	list_for_each(lh, &scsi_host_list) {
-		shost_scr = list_entry(lh, struct Scsi_Host, sh_list);
+	list_for_each_entry(shost_scr, &scsi_host_list, sh_list) {
 		if (shost->host_no < shost_scr->host_no) {
 			__list_add(&shost->sh_list, shost_scr->sh_list.prev,
 				   &shost_scr->sh_list);
@@ -683,10 +682,7 @@
  * Notes:
  *	Attach a single Scsi_Device to the Scsi_Host - this should
  *	be made to look like a "pseudo-device" that points to the
- *	HA itself.  For the moment, we include it at the head of
- *	the host_queue itself - I don't think we want to show this
- *	to the HA in select_queue_depths(), as this would probably confuse
- *	matters.
+ *	HA itself.
  *
  *	Note - this device is not accessible from any high-level
  *	drivers (including generics), which is probably not
diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
--- a/drivers/scsi/hosts.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/hosts.h	Wed Nov 27 14:36:28 2002
@@ -187,59 +187,73 @@
     int (*reset)(int,int);
 
     /*
-     * Once the device has responded to an INQUIRY and we know the device
-     * is online, call into the low level driver with the Scsi_Device *
-     * (so that the low level driver may save it off in a safe location
-     * for later use in calling scsi_adjust_queue_depth() or possibly
-     * other scsi_* functions) and char * to the INQUIRY return data buffer.
-     * This way, low level drivers will no longer have to snoop INQUIRY data
-     * to see if a drive supports PPR message protocol for Ultra160 speed
-     * negotiations or other similar items.  Instead it can simply wait until
-     * the scsi mid layer calls them with the data in hand and then it can
-     * do it's checking of INQUIRY data.  This will happen once for each new
-     * device added on this controller (including once for each lun on
-     * multi-lun devices, so low level drivers should take care to make
-     * sure that if they do tagged queueing on a per physical unit basis
-     * instead of a per logical unit basis that they have the mid layer
-     * allocate tags accordingly).
+     * slave_alloc()  -  Optional
+     * 
+     * Before the mid layer attempts to scan for a new device where none
+     * currently exists, it will call this entry in your driver.  Should
+     * your driver need to allocate any structs or perform any other init
+     * items in order to send commands to a currently unused target/lun
+     * combo, then this is where you can perform those allocations.  This
+     * is specifically so that drivers won't have to perform any kind of
+     * "is this a new device" checks in their queuecommand routine,
+     * thereby making the hot path a bit quicker.
+     *
+     * Return values: 0 on success, non-0 on failure
      *
+     * Deallocation:  If we didn't find any devices at this ID, you will
+     * get an immediate call to slave_destroy().  If we find something here
+     * then you will get a call to slave_configure(), then the device will be
+     * used for however long it is kept around, then when the device is
+     * removed from the system (or * possibly at reboot time), you will
+     * then get a call to slave_detach().  This is assuming you implement
+     * slave_configure and slave_destroy.  However, if you allocate memory
+     * and hang it off the device struct, then you must implement the
+     * slave_destroy() routine at a minimum in order to avoid leaking memory
+     * each time a device is tore down.
+     */
+    int (* slave_alloc)(Scsi_Device *);
+
+    /*
+     * slave_configure()  -  Optional
+     * 
+     * Once the device has responded to an INQUIRY and we know the device
+     * is online, we call into the low level driver with the Scsi_Device *
+     * If the low level device driver implements this function, it *must*
+     * perform the task of setting the queue depth on the device.  All other
+     * tasks are optional and depend on what the driver supports and various
+     * implementation details.
+     * 
      * Things currently recommended to be handled at this time include:
      *
-     * 1.  Checking for tagged queueing capability and if able then calling
-     *     scsi_adjust_queue_depth() with the device pointer and the
-     *     suggested new queue depth.
-     * 2.  Checking for things such as SCSI level or DT bit in order to
-     *     determine if PPR message protocols are appropriate on this
-     *     device (or any other scsi INQUIRY data specific things the
-     *     driver wants to know in order to properly handle this device).
+     * 1.  Setting the device queue depth.  Proper setting of this is
+     *     described in the comments for scsi_adjust_queue_depth.
+     * 2.  Determining if the device supports the various synchronous
+     *     negotiation protocols.  The device struct will already have
+     *     responded to INQUIRY and the results of the standard items
+     *     will have been shoved into the various device flag bits, eg.
+     *     device->sdtr will be true if the device supports SDTR messages.
      * 3.  Allocating command structs that the device will need.
      * 4.  Setting the default timeout on this device (if needed).
-     * 5.  Saving the Scsi_Device pointer so that the low level driver
-     *     will be able to easily call back into scsi_adjust_queue_depth
-     *     again should it be determined that the queue depth for this
-     *     device should be lower or higher than it is initially set to.
-     * 6.  Allocate device data structures as needed that can be attached
-     *     to the Scsi_Device * via SDpnt->host_device_ptr
-     * 7.  Anything else the low level driver might want to do on a device
+     * 5.  Anything else the low level driver might want to do on a device
      *     specific setup basis...
-     * 8.  Return 0 on success, non-0 on error.  The device will be marked
-     *     as offline on error so that no access will occur.
+     * 6.  Return 0 on success, non-0 on error.  The device will be marked
+     *     as offline on error so that no access will occur.  If you return
+     *     non-0, your slave_detach routine will never get called for this
+     *     device, so don't leave any loose memory hanging around, clean
+     *     up after yourself before returning non-0
      */
-    int (* slave_attach)(Scsi_Device *);
+    int (* slave_configure)(Scsi_Device *);
 
     /*
-     * If we are getting ready to remove a device from the scsi chain then
-     * we call into the low level driver to let them know.  Once a low
-     * level driver has been informed that a drive is going away, the low
-     * level driver *must* remove it's pointer to the Scsi_Device because
-     * it is going to be kfree()'ed shortly.  It is no longer safe to call
-     * any mid layer functions with this Scsi_Device *.  Additionally, the
-     * mid layer will not make any more calls into the low level driver's
-     * queue routine with this device, so it is safe for the device driver
-     * to deallocate all structs/commands/etc that is has allocated
-     * specifically for this device at the time of this call.
+     * slave_destroy()  -  Optional
+     *
+     * Immediately prior to deallocating the device and after all activity
+     * has ceased the mid layer calls this point so that the low level driver
+     * may completely detach itself from the scsi device and vice versa.
+     * The low level driver is responsible for freeing any memory it allocated
+     * in the slave_alloc or slave_configure calls. 
      */
-    void (* slave_detach)(Scsi_Device *);
+    void (* slave_destroy)(Scsi_Device *);
 
     /*
      * This function determines the bios parameters for a given
@@ -359,8 +373,6 @@
      * struct private is a way of marking it in a sort of C++ type of way.
      */
     struct list_head      sh_list;
-    Scsi_Device           * host_queue;
-    struct list_head	  all_scsi_hosts;
     struct list_head	  my_devices;
 
     spinlock_t		  default_lock;
@@ -519,7 +531,7 @@
 /*
  * Prototypes for functions/data in scsi_scan.c
  */
-extern void scan_scsis(struct Scsi_Host *, uint, uint, uint, uint);
+extern void scsi_scan_host(struct Scsi_Host *);
 
 struct Scsi_Device_Template
 {
@@ -585,9 +597,7 @@
                                             int channel, int pun, int lun) {
         Scsi_Device *sdev;
 
-        for (sdev = shost->host_queue;
-            sdev != NULL;
-            sdev = sdev->next)
+	list_for_each_entry (sdev, &shost->my_devices, siblings)
                 if (sdev->channel == channel && sdev->id == pun
                    && sdev->lun ==lun)
                         break;
diff -Nru a/drivers/scsi/i60uscsi.c b/drivers/scsi/i60uscsi.c
--- a/drivers/scsi/i60uscsi.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/i60uscsi.c	Wed Nov 27 14:36:28 2002
@@ -566,10 +566,10 @@
 	ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
 	if (waitSCSIRSTdone(pHCB) == FALSE) {
 		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-		return (SCSI_RESET_ERROR);
+		return FAILED;
 	} else {
 		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-		return (SCSI_RESET_SUCCESS);
+		return SUCCESS;
 	}
 }
 
@@ -581,7 +581,7 @@
  Output         : None.
  Return         : pSRB  -       Pointer to SCSI request block.
 *****************************************************************************/
-int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target, unsigned int ResetFlags)
+int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target)
 {				/* I need Host Control Block Information */
 	ORC_SCB *pScb;
 	ESCB *pVirEscb;
@@ -608,11 +608,11 @@
 	if (i == ORC_MAXQUEUE) {
 		printk("Unable to Reset - No SCB Found\n");
 		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-		return (SCSI_RESET_NOT_RUNNING);
+		return FAILED;
 	}
 	if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
 		spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-		return (SCSI_RESET_NOT_RUNNING);
+		return FAILED;
 	}
 	pScb->SCB_Opcode = ORC_BUSDEVRST;
 	pScb->SCB_Target = target;
@@ -626,12 +626,10 @@
 	pScb->SCB_SGLen = 0;
 
 	pVirEscb->SCB_Srb = 0;
-	if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
-		pVirEscb->SCB_Srb = SCpnt;
-	}
+	pVirEscb->SCB_Srb = SCpnt;
 	orc_exec_scb(pHCB, pScb);	/* Start execute SCB            */
 	spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
-	return SCSI_RESET_PENDING;
+	return SUCCESS;
 }
 
 
@@ -838,21 +836,21 @@
 		if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) {
 			if (pVirScb->SCB_TagMsg == 0) {
 				spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-				return (SCSI_ABORT_BUSY);
+				return FAILED;
 			} else {
 				if (abort_SCB(hcsp, pVirScb)) {
 					pVirEscb->SCB_Srb = NULL;
 					spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-					return (SCSI_ABORT_SUCCESS);
+					return SUCCESS;
 				} else {
 					spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-					return (SCSI_ABORT_NOT_RUNNING);
+					return FAILED;
 				}
 			}
 		}
 	}
 	spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
-	return (SCSI_ABORT_NOT_RUNNING);
+	return FAILED;
 }
 
 /***********************************************************************
diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
--- a/drivers/scsi/in2000.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/in2000.c	Wed Nov 27 14:36:31 2002
@@ -1885,14 +1885,14 @@
 	0
 };
 
-static const unsigned short base_tab[] in2000__INITDATA = {
+static unsigned short base_tab[] in2000__INITDATA = {
 	0x220,
 	0x200,
 	0x110,
 	0x100,
 };
 
-static const int int_tab[] in2000__INITDATA = {
+static int int_tab[] in2000__INITDATA = {
 	15,
 	14,
 	11,
diff -Nru a/drivers/scsi/ini9100u.h b/drivers/scsi/ini9100u.h
--- a/drivers/scsi/ini9100u.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/ini9100u.h	Wed Nov 27 14:36:30 2002
@@ -105,7 +105,6 @@
  	eh_host_reset_handler: NULL, \
 	abort:		i91u_abort, \
 	reset:		i91u_reset, \
-	slave_attach:	NULL, \
 	bios_param:	i91u_biosparam, \
 	can_queue:	1, \
 	this_id:	1, \
diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c
--- a/drivers/scsi/inia100.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/inia100.c	Wed Nov 27 14:36:28 2002
@@ -126,7 +126,7 @@
 extern void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp);
 extern void orc_release_dma(ORC_HCS * hcsp, Scsi_Cmnd * cmnd);
 extern void orc_interrupt(ORC_HCS * hcsp);
-extern int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target, unsigned int ResetFlags);
+extern int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target);
 extern int orc_reset_scsi_bus(ORC_HCS * pHCB);
 extern int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb);
 extern int orc_abort_srb(ORC_HCS * hcsp, Scsi_Cmnd *SCpnt);
@@ -366,7 +366,11 @@
 			printk("inia100: initial orchid fail!!\n");
 			goto out_unalloc;
 		}
-		request_region(pHCB->HCS_Base, 256, "inia100");	/* Register */
+		if (!request_region(pHCB->HCS_Base, 256, "inia100")) {
+			printk(KERN_WARNING "inia100: io port 0x%x, is busy.\n", 
+			       pHCB->HCS_Base);
+			return (0);
+		}
 
 		hreg->io_port = pHCB->HCS_Base;
 		hreg->n_io_port = 0xff;
@@ -514,7 +518,7 @@
  Output         : None.
  Return         : pSRB  -       Pointer to SCSI request block.
 *****************************************************************************/
-int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+static int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
 	register ORC_SCB *pSCB;
 	ORC_HCS *pHCB;		/* Point to Host adapter control block */
@@ -541,7 +545,7 @@
  Output         : None.
  Return         : pSRB  -       Pointer to SCSI request block.
 *****************************************************************************/
-int inia100_abort(Scsi_Cmnd * SCpnt)
+static int inia100_abort(Scsi_Cmnd * SCpnt)
 {
 	ORC_HCS *hcsp;
 
@@ -557,15 +561,25 @@
  Output         : None.
  Return         : pSRB  -       Pointer to SCSI request block.
 *****************************************************************************/
-int inia100_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+static int inia100_bus_reset(Scsi_Cmnd * SCpnt)
 {				/* I need Host Control Block Information */
 	ORC_HCS *pHCB;
 	pHCB = (ORC_HCS *) SCpnt->host->hostdata;
+	return orc_reset_scsi_bus(pHCB);
+}
 
-	if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
-		return orc_reset_scsi_bus(pHCB);
-	else
-		return orc_device_reset(pHCB, SCpnt, SCpnt->target, reset_flags);
+/*****************************************************************************
+ Function name  : inia100_device_reset
+ Description    : Reset the device
+ Input          : pHCB  -       Pointer to host adapter structure
+ Output         : None.
+ Return         : pSRB  -       Pointer to SCSI request block.
+*****************************************************************************/
+static int inia100_device_reset(Scsi_Cmnd * SCpnt)
+{				/* I need Host Control Block Information */
+	ORC_HCS *pHCB;
+	pHCB = (ORC_HCS *) SCpnt->host->hostdata;
+	return orc_device_reset(pHCB, SCpnt, SCpnt->target);
 
 }
 
@@ -648,41 +662,6 @@
 	return;
 }
 
-/*****************************************************************************
- Function name  : inia100_biosparam
- Description    : Return the "logical geometry"
- Input          : pHCB  -       Pointer to host adapter structure
- Output         : None.
- Return         : pSRB  -       Pointer to SCSI request block.
-*****************************************************************************/
-int inia100_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-		sector_t capacity, int *info_array)
-{
-	ORC_HCS *pHcb;		/* Point to Host adapter control block */
-	ORC_TCS *pTcb;
-
-	pHcb = (ORC_HCS *) sdev->host->hostdata;
-	pTcb = &pHcb->HCS_Tcs[sdev->id];
-
-	if (pTcb->TCS_DrvHead) {
-		info_array[0] = pTcb->TCS_DrvHead;
-		info_array[1] = pTcb->TCS_DrvSector;
-		info_array[2] = (unsigned long)capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector;
-	} else {
-		if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) {
-			info_array[0] = 255;
-			info_array[1] = 63;
-			info_array[2] = (unsigned long)capacity / 255 / 63;
-		} else {
-			info_array[0] = 64;
-			info_array[1] = 32;
-			info_array[2] = capacity >> 11;
-		}
-	}
-	return 0;
-}
-
-
 /*
  * Interrupt handler (main routine of the driver)
  */
@@ -710,7 +689,7 @@
 /*
  * Release ressources
  */
-int inia100_release(struct Scsi_Host *hreg)
+static int inia100_release(struct Scsi_Host *hreg)
 {
 	ORC_HCS *pHCB = (ORC_HCS *)hreg->hostdata;
 
diff -Nru a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h
--- a/drivers/scsi/inia100.h	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/inia100.h	Wed Nov 27 14:36:27 2002
@@ -75,14 +75,12 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-extern int inia100_detect(Scsi_Host_Template *);
-extern int inia100_release(struct Scsi_Host *);
-extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-extern int inia100_abort(Scsi_Cmnd *);
-extern int inia100_reset(Scsi_Cmnd *, unsigned int);
-
-extern int inia100_biosparam(struct scsi_device *, struct block_device *,
-		sector_t, int *);
+static int inia100_detect(Scsi_Host_Template *);
+static int inia100_release(struct Scsi_Host *);
+static int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+static int inia100_abort(Scsi_Cmnd *);
+static int inia100_device_reset(Scsi_Cmnd *);
+static int inia100_bus_reset(Scsi_Cmnd *);
 
 #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02d"
 
@@ -92,8 +90,9 @@
 	detect:		inia100_detect, \
 	release:	inia100_release, \
 	queuecommand:	inia100_queue, \
-	abort:		inia100_abort, \
-	reset:		inia100_reset, \
+	eh_abort_handler:inia100_abort, \
+	eh_bus_reset_handler:	inia100_bus_reset, \
+	eh_device_reset_handler:inia100_device_reset, \
 	can_queue:	1, \
 	this_id:	1, \
 	sg_tablesize:	SG_ALL, \
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/ips.c	Wed Nov 27 14:36:27 2002
@@ -83,7 +83,7 @@
 /*            2.3.18 and later                                               */
 /*          - Sync with other changes from the 2.3 kernels                   */
 /* 4.00.06  - Fix timeout with initial FFDC command                          */
-/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@caldera.de>    */
+/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@infradead.org> */
 /* 4.10.00  - Add support for ServeRAID 4M/4L                                */
 /* 4.10.13  - Fix for dynamic unload and proc file system                    */
 /* 4.20.03  - Rename version to coincide with new release schedules          */
@@ -190,6 +190,7 @@
 #ifdef MODULE
    static char *ips = NULL;
    MODULE_PARM(ips, "s");
+   MODULE_LICENSE("GPL");
 #endif
 
 /*
@@ -433,7 +434,7 @@
 int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *));
 int ips_biosparam(struct scsi_device *, struct block_device *,
 		sector_t, int *);
-int ips_slave_attach(Scsi_Device *);
+int ips_slave_configure(Scsi_Device *);
 const char * ips_info(struct Scsi_Host *);
 void do_ipsintr(int, void *, struct pt_regs *);
 static int ips_hainit(ips_ha_t *);
@@ -856,7 +857,7 @@
                       ips_name, ips_next_controller, mem_addr, mem_len);
 
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0)
-            if (check_mem_region(mem_addr, mem_len)) {
+            if (!request_mem_region(mem_addr, mem_len, "ips")) {
                /* Couldn't allocate io space */
                printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n",
                       ips_name, ips_next_controller, io_addr, io_len);
@@ -866,7 +867,6 @@
                continue;
             }
 
-            request_mem_region(mem_addr, mem_len, "ips");
 #endif
 
             base = mem_addr & PAGE_MASK;
@@ -884,7 +884,7 @@
             DEBUG_VAR(1, "(%s%d) detect, IO region %x, size: %d",
                       ips_name, ips_next_controller, io_addr, io_len);
 
-            if (check_region(io_addr, io_len)) {
+            if (!request_region(io_addr, io_len, "ips")) {
                /* Couldn't allocate io space */
                printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n",
                       ips_name, ips_next_controller, io_addr, io_len);
@@ -893,8 +893,6 @@
 
                continue;
             }
-
-            request_region(io_addr, io_len, "ips");
          }
 
          /* get planer status */
@@ -1866,7 +1864,7 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_slave_attach                                           */
+/* Routine Name: ips_slave_configure                                        */
 /*                                                                          */
 /* Routine Description:                                                     */
 /*                                                                          */
@@ -1874,7 +1872,7 @@
 /*                                                                          */
 /****************************************************************************/
 int
-ips_slave_attach(Scsi_Device *SDptr)
+ips_slave_configure(Scsi_Device *SDptr)
 {
    ips_ha_t    *ha;
    int          min;
@@ -7329,12 +7327,11 @@
        uint32_t base;
        uint32_t offs;
 
-       if (check_mem_region(mem_addr, mem_len)) {
+       if (!request_mem_region(mem_addr, mem_len, "ips")) {
           printk(KERN_WARNING "Couldn't allocate IO Memory space %x len %d.\n", mem_addr, mem_len);
           return -1;
           }
 
-       request_mem_region(mem_addr, mem_len, "ips");
        base = mem_addr & PAGE_MASK;
        offs = mem_addr - base;
        ioremap_ptr = ioremap(base, PAGE_SIZE);
@@ -7346,11 +7343,10 @@
 
     /* setup I/O mapped area (if applicable) */
     if (io_addr) {
-       if (check_region(io_addr, io_len)) {
+       if (!request_region(io_addr, io_len, "ips")) {
           printk(KERN_WARNING "Couldn't allocate IO space %x len %d.\n", io_addr, io_len);
           return -1;
        }
-       request_region(io_addr, io_len, "ips");
     }
 
     /* get the revision ID */
diff -Nru a/drivers/scsi/ips.h b/drivers/scsi/ips.h
--- a/drivers/scsi/ips.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/ips.h	Wed Nov 27 14:36:28 2002
@@ -61,7 +61,7 @@
    extern int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *));
    extern int ips_biosparam(struct scsi_device *, struct block_device *,
 		   sector_t, int *);
-   extern int ips_slave_attach(Scsi_Device *);
+   extern int ips_slave_configure(Scsi_Device *);
    extern const char * ips_info(struct Scsi_Host *);
    extern void do_ips(int, void *, struct pt_regs *);
 
@@ -471,7 +471,7 @@
     queuecommand : ips_queue,             \
     eh_abort_handler : ips_eh_abort,      \
     eh_host_reset_handler : ips_eh_reset, \
-    slave_attach : ips_slave_attach,      \
+    slave_configure : ips_slave_configure,\
     bios_param : ips_biosparam,           \
     can_queue : 0,                        \
     this_id: -1,                          \
diff -Nru a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
--- a/drivers/scsi/megaraid.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/megaraid.h	Wed Nov 27 14:36:30 2002
@@ -974,13 +974,11 @@
 			   mega_ioctl_mbox * mbox);
 #endif
 
-static int megadev_open (struct inode *, struct file *);
 static int megadev_ioctl_entry (struct inode *, struct file *,
 				unsigned int, unsigned long);
 static int megadev_ioctl (struct inode *, struct file *,
 			  unsigned int, unsigned long);
 static mega_scb *megadev_doioctl (mega_host_config *, Scsi_Cmnd *);
-static int megadev_close (struct inode *, struct file *);
 static void megadev_ioctl_done (Scsi_Cmnd *);
 static int mega_init_scb (mega_host_config *);
 static void enq_scb_freelist (mega_host_config *, mega_scb *,
diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
--- a/drivers/scsi/ncr53c8xx.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/ncr53c8xx.c	Wed Nov 27 14:36:28 2002
@@ -8496,7 +8496,7 @@
 **   Linux select queue depths function
 */
 
-int ncr53c8xx_slave_attach(Scsi_Device *device)
+int ncr53c8xx_slave_configure(Scsi_Device *device)
 {
 	struct Scsi_Host *host = device->host;
 	ncb_p np;
diff -Nru a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
--- a/drivers/scsi/ncr53c8xx.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/ncr53c8xx.h	Wed Nov 27 14:36:28 2002
@@ -59,7 +59,7 @@
 const char *ncr53c8xx_info(struct Scsi_Host *host);
 int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int);
-int ncr53c8xx_slave_attach(Scsi_Device *);
+int ncr53c8xx_slave_configure(Scsi_Device *);
 
 #ifdef MODULE
 int ncr53c8xx_release(struct Scsi_Host *);
@@ -75,7 +75,7 @@
 			release:        ncr53c8xx_release,	\
 			info:           ncr53c8xx_info, 	\
 			queuecommand:   ncr53c8xx_queue_command,\
-			slave_attach:   ncr53c8xx_slave_attach, \
+			slave_configure:ncr53c8xx_slave_configure,\
 			abort:          ncr53c8xx_abort,	\
 			reset:          ncr53c8xx_reset,	\
 			can_queue:      SCSI_NCR_CAN_QUEUE,	\
diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
--- a/drivers/scsi/pas16.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/pas16.c	Wed Nov 27 14:36:27 2002
@@ -119,14 +119,16 @@
 #include <asm/io.h>
 #include <linux/blk.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+
 #include "scsi.h"
 #include "hosts.h"
 #include "pas16.h"
 #define AUTOPROBE_IRQ
 #include "NCR5380.h"
 
-#include <linux/stat.h>
-#include <linux/init.h>
 
 static int pas_maxi = 0;
 static int pas_wmaxi = 0;
diff -Nru a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
--- a/drivers/scsi/pcmcia/aha152x_stub.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/pcmcia/aha152x_stub.c	Wed Nov 27 14:36:31 2002
@@ -297,7 +297,7 @@
     for (host = scsi_host_get_next(NULL); host;
 	 host = scsi_host_get_next(host))
 	if (host->hostt == &driver_template)
-	    for (dev = host->host_queue; dev; dev = dev->next) {
+	    list_for_each_entry (dev, &host->my_devices, siblings) {
 	    u_long arg[2], id;
 	    kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
 	    id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
--- a/drivers/scsi/pcmcia/fdomain_stub.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/pcmcia/fdomain_stub.c	Wed Nov 27 14:36:30 2002
@@ -261,7 +261,7 @@
     for (host = scsi_host_get_next(NULL); host;
 	 host = scsi_host_get_next(host))
 	if (host->hostt == &driver_template)
-	    for (dev = host->host_queue; dev; dev = dev->next) {
+	    list_for_each_entry (dev, &host->my_devices, siblings) {
 	    u_long arg[2], id;
 	    kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
 	    id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
--- a/drivers/scsi/pcmcia/nsp_cs.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/pcmcia/nsp_cs.c	Wed Nov 27 14:36:32 2002
@@ -1779,7 +1779,7 @@
 	for (host = scsi_hostlist; host != NULL; host = host->next) {
 #endif
 		if (host->hostt == &driver_template) {
-			for (dev = host->host_queue; dev != NULL; dev = dev->next) {
+	    		list_for_each_entry (dev, &host->my_devices, siblings) {
 				u_long arg[2], id;
 				kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
 				id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
--- a/drivers/scsi/pcmcia/qlogic_stub.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/pcmcia/qlogic_stub.c	Wed Nov 27 14:36:30 2002
@@ -284,7 +284,7 @@
 	for (host = scsi_host_get_next(NULL); host;
 	     host = scsi_host_get_next(host))
 	if (host->hostt == &driver_template)
-	    for (dev = host->host_queue; dev; dev = dev->next) {
+	    list_for_each_entry (dev, &host->my_devices, siblings) {
 	    u_long arg[2], id;
 	    kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
 	    id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
diff -Nru a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
--- a/drivers/scsi/pluto.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/pluto.c	Wed Nov 27 14:36:28 2002
@@ -71,7 +71,7 @@
 		up(&fc_sem);
 }
 
-int pluto_slave_attach(Scsi_Device *device)
+int pluto_slave_configure(Scsi_Device *device)
 {
 	int depth_to_use;
 
diff -Nru a/drivers/scsi/pluto.h b/drivers/scsi/pluto.h
--- a/drivers/scsi/pluto.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/pluto.h	Wed Nov 27 14:36:30 2002
@@ -41,7 +41,7 @@
 int pluto_detect(Scsi_Host_Template *);
 int pluto_release(struct Scsi_Host *);
 const char * pluto_info(struct Scsi_Host *);
-int pluto_slave_attach(Scsi_Device *);
+int pluto_slave_configure(Scsi_Device *);
 
 #define PLUTO {							\
 	name:			"Sparc Storage Array 100/200",	\
@@ -49,7 +49,7 @@
 	release:		pluto_release,			\
 	info:			pluto_info,			\
 	queuecommand:		fcp_scsi_queuecommand,		\
-	slave_attach:		pluto_slave_attach,		\
+	slave_configure:	pluto_slave_configure,		\
 	can_queue:		PLUTO_CAN_QUEUE,		\
 	this_id:		-1,				\
 	sg_tablesize:		1,				\
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/qla1280.c	Wed Nov 27 14:36:32 2002
@@ -381,7 +381,7 @@
 static void qla1280_next(struct scsi_qla_host *, scsi_lu_t *, int);
 static void qla1280_putq_t(scsi_lu_t *, srb_t *);
 static void qla1280_done_q_put(srb_t *, srb_t **, srb_t **);
-static int qla1280_slave_attach(Scsi_Device *);
+static int qla1280_slave_configure(Scsi_Device *);
 #if STOP_ON_ERROR
 static void qla1280_panic(char *, struct Scsi_Host *host);
 #endif
@@ -1794,7 +1794,7 @@
 }
 
 /**************************************************************************
- *   qla1280_slave_attach
+ *   qla1280_slave_configure
  *
  * Description:
  *   Determines the queue depth for a given device.  There are two ways
@@ -1805,7 +1805,7 @@
  *   default queue depth (dependent on the number of hardware SCBs).
  **************************************************************************/
 static int
-qla1280_slave_attach(Scsi_Device * device)
+qla1280_slave_configure(Scsi_Device * device)
 {
 	struct scsi_qla_host *p = (struct scsi_qla_host *)device->host->hostdata;
 	int bus = device->channel;
diff -Nru a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
--- a/drivers/scsi/qla1280.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/qla1280.h	Wed Nov 27 14:36:32 2002
@@ -1315,7 +1315,7 @@
 int qla1280_reset(Scsi_Cmnd *, unsigned int);
 int qla1280_biosparam(struct scsi_device *, struct block_device *,
 		sector_t, int[]);
-static int qla1280_slave_attach(Scsi_Device *);
+static int qla1280_slave_configure(Scsi_Device *);
 void qla1280_intr_handler(int, void *, struct pt_regs *);
 void qla1280_setup(char *s, int *dummy);
 
@@ -1334,7 +1334,7 @@
 /*	use_new_eh_code: 0, */					\
 	abort: qla1280_abort,					\
 	reset: qla1280_reset,					\
-	slave_attach: qla1280_slave_attach,			\
+	slave_configure: qla1280_slave_configure,		\
 	bios_param: qla1280_biosparam,				\
 	can_queue: 255,		/* max simultaneous cmds      */\
 	this_id: -1,		/* scsi id of host adapter    */\
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/scsi.c	Wed Nov 27 14:36:30 2002
@@ -347,6 +347,33 @@
 }
 
 /*
+ * FIXME(eric) - this is not at all optimal.  Given that
+ * single lun devices are rare and usually slow
+ * (i.e. CD changers), this is good enough for now, but
+ * we may want to come back and optimize this later.
+ *
+ * Scan through all of the devices attached to this
+ * host, and see if any are active or not.  If so,
+ * we need to defer this command.
+ *
+ * We really need a busy counter per device.  This would
+ * allow us to more easily figure out whether we should
+ * do anything here or not.
+ */
+static int check_all_luns(struct Scsi_Host *shost, struct scsi_device *myself)
+{
+	struct scsi_device *sdev;
+
+	list_for_each_entry(sdev, &myself->same_target_siblings,
+		       	same_target_siblings) {
+		if (atomic_read(&sdev->device_active))
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
  * Function:    scsi_allocate_device
  *
  * Purpose:     Allocate a command descriptor.
@@ -372,172 +399,87 @@
  *              This function is deprecated, and drivers should be
  *              rewritten to use Scsi_Request instead of Scsi_Cmnd.
  */
-
-Scsi_Cmnd *scsi_allocate_device(Scsi_Device * device, int wait, 
-                                int interruptable)
+struct scsi_cmnd *scsi_allocate_device(struct scsi_device *sdev, int wait)
 {
- 	struct Scsi_Host *host;
-  	Scsi_Cmnd *SCpnt = NULL;
-	Scsi_Device *SDpnt;
+	DECLARE_WAITQUEUE(wq, current);
+	struct Scsi_Host *shost = sdev->host;
+	struct scsi_cmnd *scmnd;
 	unsigned long flags;
-  
-  	if (!device)
-  		panic("No device passed to scsi_allocate_device().\n");
-  
-  	host = device->host;
-  
+
 	spin_lock_irqsave(&device_request_lock, flags);
- 
-	while (1 == 1) {
-		SCpnt = NULL;
-		if (!device->device_blocked) {
-			if (device->single_lun) {
-				/*
-				 * FIXME(eric) - this is not at all optimal.  Given that
-				 * single lun devices are rare and usually slow
-				 * (i.e. CD changers), this is good enough for now, but
-				 * we may want to come back and optimize this later.
-				 *
-				 * Scan through all of the devices attached to this
-				 * host, and see if any are active or not.  If so,
-				 * we need to defer this command.
-				 *
-				 * We really need a busy counter per device.  This would
-				 * allow us to more easily figure out whether we should
-				 * do anything here or not.
-				 */
-				for (SDpnt = host->host_queue;
-				     SDpnt;
-				     SDpnt = SDpnt->next) {
-					/*
-					 * Only look for other devices on the same bus
-					 * with the same target ID.
-					 */
-					if (SDpnt->channel != device->channel
-					    || SDpnt->id != device->id
-					    || SDpnt == device) {
- 						continue;
-					}
-                                        if( atomic_read(&SDpnt->device_active) != 0)
-                                        {
-                                                break;
-                                        }
-				}
-				if (SDpnt) {
-					/*
-					 * Some other device in this cluster is busy.
-					 * If asked to wait, we need to wait, otherwise
-					 * return NULL.
-					 */
-					SCpnt = NULL;
-					goto busy;
-				}
-			}
-			/*
-			 * Now we can check for a free command block for this device.
-			 */
-			for (SCpnt = device->device_queue; SCpnt; SCpnt = SCpnt->next) {
-				if (SCpnt->request == NULL)
-					break;
-			}
-		}
+	while (1) {
+		if (sdev->device_blocked)
+			goto busy;
+		if (sdev->single_lun && check_all_luns(shost, sdev))
+			goto busy;
+
 		/*
-		 * If we couldn't find a free command block, and we have been
-		 * asked to wait, then do so.
+		 * Now we can check for a free command block for this device.
 		 */
-		if (SCpnt) {
-			break;
-		}
-      busy:
+		for (scmnd = sdev->device_queue; scmnd; scmnd = scmnd->next)
+			if (!scmnd->request)
+				goto found;
+
+busy:
+		if (!wait)
+			goto fail;
+
 		/*
-		 * If we have been asked to wait for a free block, then
-		 * wait here.
+		 * We need to wait for a free commandblock.  We need to
+		 * insert ourselves into the list before we release the
+		 * lock.  This way if a block were released the same
+		 * microsecond that we released the lock, the call
+		 * to schedule() wouldn't block (well, it might switch,
+		 * but the current task will still be schedulable.
 		 */
-		if (wait) {
-                        DECLARE_WAITQUEUE(wait, current);
-
-                        /*
-                         * We need to wait for a free commandblock.  We need to
-                         * insert ourselves into the list before we release the
-                         * lock.  This way if a block were released the same
-                         * microsecond that we released the lock, the call
-                         * to schedule() wouldn't block (well, it might switch,
-                         * but the current task will still be schedulable.
-                         */
-                        add_wait_queue(&device->scpnt_wait, &wait);
-                        if( interruptable ) {
-                                set_current_state(TASK_INTERRUPTIBLE);
-                        } else {
-                                set_current_state(TASK_UNINTERRUPTIBLE);
-                        }
-
-                        spin_unlock_irqrestore(&device_request_lock, flags);
-
-			/*
-			 * This should block until a device command block
-			 * becomes available.
-			 */
-                        schedule();
+		add_wait_queue(&sdev->scpnt_wait, &wq);
+		set_current_state(TASK_UNINTERRUPTIBLE);
 
-			spin_lock_irqsave(&device_request_lock, flags);
-
-                        remove_wait_queue(&device->scpnt_wait, &wait);
-                        /*
-                         * FIXME - Isn't this redundant??  Someone
-                         * else will have forced the state back to running.
-                         */
-                        set_current_state(TASK_RUNNING);
-                        /*
-                         * In the event that a signal has arrived that we need
-                         * to consider, then simply return NULL.  Everyone
-                         * that calls us should be prepared for this
-                         * possibility, and pass the appropriate code back
-                         * to the user.
-                         */
-                        if( interruptable ) {
-                                if (signal_pending(current)) {
-                                        spin_unlock_irqrestore(&device_request_lock, flags);
-                                        return NULL;
-                                }
-                        }
-		} else {
-                        spin_unlock_irqrestore(&device_request_lock, flags);
-			return NULL;
-		}
-	}
-
-	SCpnt->request = NULL;
-	atomic_inc(&SCpnt->host->host_active);
-	atomic_inc(&SCpnt->device->device_active);
-
-	SCpnt->buffer  = NULL;
-	SCpnt->bufflen = 0;
-	SCpnt->request_buffer = NULL;
-	SCpnt->request_bufflen = 0;
-
-	SCpnt->use_sg = 0;	/* Reset the scatter-gather flag */
-	SCpnt->old_use_sg = 0;
-	SCpnt->transfersize = 0;	/* No default transfer size */
-	SCpnt->cmd_len = 0;
-
-	SCpnt->sc_data_direction = SCSI_DATA_UNKNOWN;
-	SCpnt->sc_request = NULL;
-	SCpnt->sc_magic = SCSI_CMND_MAGIC;
-
-        SCpnt->result = 0;
-	SCpnt->underflow = 0;	/* Do not flag underflow conditions */
-	SCpnt->old_underflow = 0;
-	SCpnt->resid = 0;
-	SCpnt->state = SCSI_STATE_INITIALIZING;
-	SCpnt->owner = SCSI_OWNER_HIGHLEVEL;
+		spin_unlock_irqrestore(&device_request_lock, flags);
+		schedule();
+		spin_lock_irqsave(&device_request_lock, flags);
+
+		remove_wait_queue(&sdev->scpnt_wait, &wq);
+		set_current_state(TASK_RUNNING);
+	}
+
+found:
+	scmnd->request = NULL;
+	atomic_inc(&scmnd->host->host_active);
+	atomic_inc(&scmnd->device->device_active);
+
+	scmnd->buffer  = NULL;
+	scmnd->bufflen = 0;
+	scmnd->request_buffer = NULL;
+	scmnd->request_bufflen = 0;
+
+	scmnd->use_sg = 0;	/* Reset the scatter-gather flag */
+	scmnd->old_use_sg = 0;
+	scmnd->transfersize = 0;	/* No default transfer size */
+	scmnd->cmd_len = 0;
+
+	scmnd->sc_data_direction = SCSI_DATA_UNKNOWN;
+	scmnd->sc_request = NULL;
+	scmnd->sc_magic = SCSI_CMND_MAGIC;
+
+	scmnd->result = 0;
+	scmnd->underflow = 0;	/* Do not flag underflow conditions */
+	scmnd->old_underflow = 0;
+	scmnd->resid = 0;
+	scmnd->state = SCSI_STATE_INITIALIZING;
+	scmnd->owner = SCSI_OWNER_HIGHLEVEL;
 
 	spin_unlock_irqrestore(&device_request_lock, flags);
 
 	SCSI_LOG_MLQUEUE(5, printk("Activating command for device %d (%d)\n",
-				   SCpnt->target,
-				atomic_read(&SCpnt->host->host_active)));
+				scmnd->target,
+				atomic_read(&scmnd->host->host_active)));
+
+	return scmnd;
 
-	return SCpnt;
+fail:
+	spin_unlock_irqrestore(&device_request_lock, flags);
+	return NULL;
 }
 
 inline void __scsi_release_command(Scsi_Cmnd * SCpnt)
@@ -1662,6 +1604,58 @@
 }
 
 /*
+ * Function:	scsi_track_queue_full()
+ *
+ * Purpose:	This function will track successive QUEUE_FULL events on a
+ * 		specific SCSI device to determine if and when there is a
+ * 		need to adjust the queue depth on the device.
+ *
+ * Arguments:	SDpnt	- SCSI Device in question
+ * 		depth	- Current number of outstanding SCSI commands on
+ * 			  this device, not counting the one returned as
+ * 			  QUEUE_FULL.
+ *
+ * Returns:	0 - No change needed
+ * 		>0 - Adjust queue depth to this new depth
+ * 		-1 - Drop back to untagged operation using host->cmd_per_lun
+ * 			as the untagged command depth
+ *
+ * Lock Status:	None held on entry
+ *
+ * Notes:	Low level drivers may call this at any time and we will do
+ * 		"The Right Thing."  We are interrupt context safe.
+ */
+int scsi_track_queue_full(Scsi_Device *SDptr, int depth)
+{
+	if((jiffies >> 4) != SDptr->last_queue_full_time) {
+		SDptr->last_queue_full_time = (jiffies >> 4);
+		if(SDptr->last_queue_full_depth == depth)
+			SDptr->last_queue_full_count++;
+		else {
+			SDptr->last_queue_full_count = 1;
+			SDptr->last_queue_full_depth = depth;
+		}
+		if(SDptr->last_queue_full_count > 10) {
+			if(SDptr->last_queue_full_depth < 8) {
+				/* Drop back to untagged */
+				scsi_adjust_queue_depth(SDptr, 0 /* untagged */,
+						SDptr->host->cmd_per_lun);
+				return -1;
+			}
+			if(SDptr->ordered_tags)
+				scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG,
+						depth);
+			else
+				scsi_adjust_queue_depth(SDptr, MSG_SIMPLE_TAG,
+						depth);
+			return depth;
+		}
+	}
+	return 0;
+}
+
+
+/*
  * scsi_strcpy_devinfo: called from scsi_dev_info_list_add to copy into
  * devinfo vendor and model strings.
  */
@@ -1961,8 +1955,8 @@
 			       " configured\n");
 			return 1;
 		}
-		if (sdev->host->hostt->slave_attach != NULL) {
-			if (sdev->host->hostt->slave_attach(sdev) != 0) {
+		if (sdev->host->hostt->slave_configure != NULL) {
+			if (sdev->host->hostt->slave_configure(sdev) != 0) {
 				printk(KERN_INFO "scsi: failed low level driver"
 				       " attach, some SCSI device might not be"
 				       " configured\n");
@@ -1989,8 +1983,6 @@
 void scsi_slave_detach(struct scsi_device *sdev)
 {
 	if (--sdev->attached == 0) {
-		if (sdev->host->hostt->slave_detach != NULL)
-			sdev->host->hostt->slave_detach(sdev);
 		scsi_release_commandblocks(sdev);
 	}
 }
@@ -2033,19 +2025,9 @@
 	driver_register(&tpnt->scsi_driverfs_driver);
 
 	for (shpnt = scsi_host_get_next(NULL); shpnt;
-	     shpnt = scsi_host_get_next(shpnt)) {
-		for (SDpnt = shpnt->host_queue; SDpnt;
-		     SDpnt = SDpnt->next) {
-			if (tpnt->attach)
-				/*
-				 * XXX check result when the upper level
-				 * attach return values are fixed, and
-				 * stop attaching on failure.
-				 */
-				(*tpnt->attach) (SDpnt);
-
-		}
-	}
+	     shpnt = scsi_host_get_next(shpnt)) 
+		list_for_each_entry (SDpnt, &shpnt->my_devices, siblings)
+			(*tpnt->attach) (SDpnt);
 
 	return 0;
 }
@@ -2063,11 +2045,8 @@
 
 	for (shpnt = scsi_host_get_next(NULL); shpnt;
 	     shpnt = scsi_host_get_next(shpnt)) {
-		for (SDpnt = shpnt->host_queue; SDpnt;
-		     SDpnt = SDpnt->next) {
-			if (tpnt->detach)
-				(*tpnt->detach) (SDpnt);
-		}
+		list_for_each_entry(SDpnt, &shpnt->my_devices, siblings)
+			(*tpnt->detach) (SDpnt);
 	}
 	/*
 	 * Extract the template from the linked list.
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/scsi.h	Wed Nov 27 14:36:28 2002
@@ -15,23 +15,10 @@
 #ifndef _SCSI_H
 #define _SCSI_H
 
-#include <linux/config.h>	/* for CONFIG_SCSI_LOGGING */
-#include <linux/devfs_fs_kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-
-
-/*
- * Some of the public constants are being moved to this file.
- * We include it here so that what came from where is transparent.
- */
+#include <linux/config.h>	    /* for CONFIG_SCSI_LOGGING */
+#include <linux/devfs_fs_kernel.h>  /* some morons don't know struct pointers */
 #include <scsi/scsi.h>
 
-#include <linux/random.h>
-
-#include <asm/hardirq.h>
-#include <asm/scatterlist.h>
-#include <asm/io.h>
 
 /*
  * These are the values that the SCpnt->sc_data_direction and 
@@ -396,6 +383,7 @@
  * Forward-declaration of structs for prototypes.
  */
 struct Scsi_Host;
+struct scatterlist;
 
 /*
  * Add some typedefs so that we can prototyope a bunch of the functions.
@@ -445,10 +433,6 @@
  * Prototypes for functions in scsi_lib.c
  */
 extern int scsi_maybe_unblock_host(Scsi_Device * SDpnt);
-extern Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate,
-				   int sectors);
-extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *);
-extern int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt);
 extern void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt);
 extern int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int);
 extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
@@ -466,12 +450,13 @@
 extern void scsi_release_commandblocks(Scsi_Device * SDpnt);
 extern void scsi_build_commandblocks(Scsi_Device * SDpnt);
 extern void scsi_adjust_queue_depth(Scsi_Device *, int, int);
+extern int scsi_track_queue_full(Scsi_Device *, int);
 extern int scsi_slave_attach(struct scsi_device *sdev);
 extern void scsi_slave_detach(struct scsi_device *sdev);
 extern void scsi_done(Scsi_Cmnd * SCpnt);
 extern void scsi_finish_command(Scsi_Cmnd *);
 extern int scsi_retry_command(Scsi_Cmnd *);
-extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int, int);
+extern Scsi_Cmnd *scsi_allocate_device(Scsi_Device *, int);
 extern void __scsi_release_command(Scsi_Cmnd *);
 extern void scsi_release_command(Scsi_Cmnd *);
 extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
@@ -511,9 +496,11 @@
 extern void scsi_proc_host_rm(struct Scsi_Host *);
 
 extern struct proc_dir_entry *proc_scsi;
+extern void proc_print_scsidevice(Scsi_Device * sdev, char *buffer, int *size, int len);
 #else
-static inline int scsi_init_procfs(void) { return 0; };
-static inline void scsi_exit_procfs(void) { };
+static inline int scsi_init_procfs(void) { return 0; }
+static inline void scsi_exit_procfs(void) { ; }
+static inline void proc_print_scsidevice(Scsi_Device * sdev, char *buffer, int *size, int len) { ; }
 
 static inline void scsi_proc_host_add(struct Scsi_Host *);
 static inline void scsi_proc_host_rm(struct Scsi_Host *);
@@ -525,6 +512,8 @@
 extern struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *,
 			uint, uint, uint);
 extern void scsi_free_sdev(struct scsi_device *);
+extern int scsi_add_single_device(uint, uint, uint, uint);
+extern int scsi_remove_single_device(uint, uint, uint, uint);
 
 /*
  * Prototypes for functions in constants.c
@@ -551,7 +540,7 @@
 	unsigned flags;
 };
 
-extern struct dev_info scsi_static_device_list[] __initdata;
+extern struct dev_info scsi_static_device_list[];
 
 /*
  * scsi_dev_info_list: structure to hold black/white listed devices.
@@ -599,6 +588,11 @@
         Scsi_Cmnd *current_cmnd;	/* currently active command */
 	unsigned short current_queue_depth;/* How deep of a queue we have */
 	unsigned short new_queue_depth; /* How deep of a queue we want */
+	unsigned short last_queue_full_depth; /* These two are used by */
+	unsigned short last_queue_full_count; /* scsi_track_queue_full() */
+	unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same
+					   jiffie count on our counter, they
+					   could all be from the same event. */
 
 	unsigned int id, lun, channel;
 
diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
--- a/drivers/scsi/scsi_debug.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/scsi_debug.c	Wed Nov 27 14:36:31 2002
@@ -812,13 +812,13 @@
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
 
-static int scsi_debug_slave_attach(struct scsi_device * sdp)
+static int scsi_debug_slave_configure(struct scsi_device * sdp)
 {
 	int k;
 	struct sdebug_dev_info * devip; 
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: slave_attach <%u %u %u %u>\n",
+		printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN)
 		sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN;
@@ -838,13 +838,13 @@
 	return 0;
 }
 
-static void scsi_debug_slave_detach(struct scsi_device * sdp)
+static void scsi_debug_slave_destroy(struct scsi_device * sdp)
 {
 	struct sdebug_dev_info * devip = 
 				(struct sdebug_dev_info *)sdp->hostdata;
 
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: slave_detach <%u %u %u %u>\n",
+		printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (devip) {
 		/* make this slot avaliable for re-use */
diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h
--- a/drivers/scsi/scsi_debug.h	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/scsi_debug.h	Wed Nov 27 14:36:30 2002
@@ -2,8 +2,8 @@
 
 #include <linux/types.h>
 
-static int scsi_debug_slave_attach(struct scsi_device *);
-static void scsi_debug_slave_detach(struct scsi_device *);
+static int scsi_debug_slave_configure(struct scsi_device *);
+static void scsi_debug_slave_destroy(struct scsi_device *);
 static int scsi_debug_queuecommand(struct scsi_cmnd *, 
 				   void (*done) (struct scsi_cmnd *));
 static int scsi_debug_ioctl(struct scsi_device *, int, void *);
@@ -27,8 +27,8 @@
 	.proc_info =		scsi_debug_proc_info,
 	.name =			"SCSI DEBUG",
 	.info =			scsi_debug_info,
-	.slave_attach =		scsi_debug_slave_attach,
-	.slave_detach =		scsi_debug_slave_detach,
+	.slave_configure =	scsi_debug_slave_configure,
+	.slave_destroy =		scsi_debug_slave_destroy,
 	.ioctl =		scsi_debug_ioctl,
 	.queuecommand =		scsi_debug_queuecommand,
 	.eh_abort_handler =	scsi_debug_abort,
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/scsi_error.c	Wed Nov 27 14:36:27 2002
@@ -201,7 +201,7 @@
 	int devices_failed = 0;
 
 
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+	list_for_each_entry(sdev, &shost->my_devices, siblings) {
 		for (scmd = sc_list; scmd; scmd = scmd->bh_next) {
 			if (scmd->device == sdev) {
 				++total_failures;
@@ -246,7 +246,8 @@
 	Scsi_Device *sdev;
 	Scsi_Cmnd *scmd;
 
-	for (found = 0, sdev = shost->host_queue; sdev; sdev = sdev->next) {
+	found = 0;
+	list_for_each_entry(sdev, &shost->my_devices, siblings) {
 		for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
 			if (scsi_eh_eflags_chk(scmd, SCSI_EH_CMD_ERR)) {
 				scmd->bh_next = *sc_list;
@@ -961,7 +962,7 @@
 
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Trying BDR\n", __FUNCTION__));
 
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+	list_for_each_entry(sdev, &shost->my_devices, siblings) {
 		for (scmd = sc_todo; scmd; scmd = scmd->bh_next)
 			if ((scmd->device == sdev) &&
 			    scsi_eh_eflags_chk(scmd, SCSI_EH_CMD_ERR))
@@ -1015,7 +1016,7 @@
 		/*
 		 * Mark all affected devices to expect a unit attention.
 		 */
-		for (sdev = scmd->host->host_queue; sdev; sdev = sdev->next)
+		list_for_each_entry(sdev, &scmd->host->my_devices, siblings)
 			if (scmd->channel == sdev->channel) {
 				sdev->was_reset = 1;
 				sdev->expecting_cc_ua = 1;
@@ -1051,7 +1052,7 @@
 		/*
 		 * Mark all affected devices to expect a unit attention.
 		 */
-		for (sdev = scmd->host->host_queue; sdev; sdev = sdev->next)
+		list_for_each_entry(sdev, &scmd->host->my_devices, siblings)
 			if (scmd->channel == sdev->channel) {
 				sdev->was_reset = 1;
 				sdev->expecting_cc_ua = 1;
@@ -1457,7 +1458,7 @@
 	 * onto the head of the SCSI request queue for the device.  There
 	 * is no point trying to lock the door of an off-line device.
 	 */
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next)
+	list_for_each_entry(sdev, &shost->my_devices, siblings)
 		if (sdev->online && sdev->locked)
 			scsi_eh_lock_door(sdev);
 
@@ -1478,7 +1479,7 @@
 	 * requests are started.
 	 */
 	spin_lock_irqsave(shost->host_lock, flags);
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+	list_for_each_entry(sdev, &shost->my_devices, siblings) {
 		if ((shost->can_queue > 0 &&
 		     (shost->host_busy >= shost->can_queue))
 		    || (shost->host_blocked)
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/scsi_lib.c	Wed Nov 27 14:36:30 2002
@@ -12,6 +12,7 @@
 #include <linux/bio.h>
 #include <linux/kernel.h>
 #include <linux/blk.h>
+#include <asm/hardirq.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
 
@@ -95,7 +96,7 @@
  *              fields related to error handling.   Typically this will
  *              be called once for each command, as required.
  */
-int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt)
+static int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt)
 {
 	SCpnt->owner = SCSI_OWNER_MIDLEVEL;
 	SCpnt->reset_chain = NULL;
@@ -241,7 +242,7 @@
 	 * use function pointers to pick the right one.
 	 */
 	if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) {
-		for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
+		list_for_each_entry(SDpnt, &SHpnt->my_devices, siblings) {
 			if (((SHpnt->can_queue > 0)
 			     && (SHpnt->host_busy >= SHpnt->can_queue))
 			    || (SHpnt->host_blocked)
@@ -264,7 +265,7 @@
 	 */
 	all_clear = 1;
 	if (SHpnt->some_device_starved) {
-		for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
+		list_for_each_entry(SDpnt, &SHpnt->my_devices, siblings) {
 			if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue))
 			    || (SHpnt->host_blocked) 
 			    || (SHpnt->host_self_blocked)) {
@@ -306,11 +307,10 @@
  *		We are guaranteeing that the request queue will be goosed
  *		at some point during this call.
  */
-static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt, 
+static Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, 
 				     int uptodate, 
 				     int sectors,
-				     int requeue,
-				     int frequeue)
+				     int requeue)
 {
 	request_queue_t *q = &SCpnt->device->request_queue;
 	struct request *req = SCpnt->request;
@@ -337,12 +337,9 @@
 	add_disk_randomness(req->rq_disk);
 
 	spin_lock_irqsave(q->queue_lock, flags);
-
 	if (blk_rq_tagged(req))
 		blk_queue_end_tag(q, req);
-
 	end_that_request_last(req);
-
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	/*
@@ -350,39 +347,11 @@
 	 * need to worry about launching another command.
 	 */
 	__scsi_release_command(SCpnt);
-
-	if (frequeue)
-		scsi_queue_next_request(q, NULL);
-
+	scsi_queue_next_request(q, NULL);
 	return NULL;
 }
 
 /*
- * Function:    scsi_end_request()
- *
- * Purpose:     Post-processing of completed commands called from interrupt
- *              handler or a bottom-half handler.
- *
- * Arguments:   SCpnt    - command that is complete.
- *              uptodate - 1 if I/O indicates success, 0 for I/O error.
- *              sectors  - number of sectors we want to mark.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns:     Nothing
- *
- * Notes:       This is called for block device requests in order to
- *              mark some number of sectors as complete.
- * 
- *		We are guaranteeing that the request queue will be goosed
- *		at some point during this call.
- */
-Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors)
-{
-	return __scsi_end_request(SCpnt, uptodate, sectors, 1, 1);
-}
-
-/*
  * Function:    scsi_release_buffers()
  *
  * Purpose:     Completion processing for block device I/O requests.
@@ -429,6 +398,29 @@
 }
 
 /*
+ * Function:    scsi_get_request_dev()
+ *
+ * Purpose:     Find the upper-level driver that is responsible for this
+ *              request
+ *
+ * Arguments:   request   - I/O request we are preparing to queue.
+ *
+ * Lock status: No locks assumed to be held, but as it happens the
+ *              q->queue_lock is held when this is called.
+ *
+ * Returns:     Nothing
+ *
+ * Notes:       The requests in the request queue may have originated
+ *              from any block device driver.  We need to find out which
+ *              one so that we can later form the appropriate command.
+ */
+static struct Scsi_Device_Template *scsi_get_request_dev(struct request *req)
+{
+	struct gendisk *p = req->rq_disk;
+	return p ? *(struct Scsi_Device_Template **)p->private_data : NULL;
+}
+
+/*
  * Function:    scsi_io_completion()
  *
  * Purpose:     Completion processing for block device I/O requests.
@@ -527,11 +519,7 @@
 		 * requeueing right here - we will requeue down below
 		 * when we handle the bad sectors.
 		 */
-		SCpnt = __scsi_end_request(SCpnt, 
-					   1, 
-					   good_sectors,
-					   result == 0,
-					   1);
+		SCpnt = scsi_end_request(SCpnt, 1, good_sectors, result == 0);
 
 		/*
 		 * If the command completed without error, then either finish off the
@@ -574,7 +562,8 @@
 					 * and quietly refuse further access.
 		 			 */
 					SCpnt->device->changed = 1;
-					SCpnt = scsi_end_request(SCpnt, 0, this_count);
+					SCpnt = scsi_end_request(SCpnt, 0,
+							this_count, 1);
 					return;
 				} else {
 					/*
@@ -606,14 +595,14 @@
 				scsi_queue_next_request(q, SCpnt);
 				result = 0;
 			} else {
-				SCpnt = scsi_end_request(SCpnt, 0, this_count);
+				SCpnt = scsi_end_request(SCpnt, 0, this_count, 1);
 				return;
 			}
 			break;
 		case NOT_READY:
 			printk(KERN_INFO "Device %s not ready.\n",
 			       req->rq_disk ? req->rq_disk->disk_name : "");
-			SCpnt = scsi_end_request(SCpnt, 0, this_count);
+			SCpnt = scsi_end_request(SCpnt, 0, this_count, 1);
 			return;
 			break;
 		case MEDIUM_ERROR:
@@ -623,7 +612,7 @@
 			       (int) SCpnt->target, (int) SCpnt->lun);
 			print_command(SCpnt->data_cmnd);
 			print_sense("sd", SCpnt);
-			SCpnt = scsi_end_request(SCpnt, 0, block_sectors);
+			SCpnt = scsi_end_request(SCpnt, 0, block_sectors, 1);
 			return;
 		default:
 			break;
@@ -656,35 +645,12 @@
 		 * We sometimes get this cruft in the event that a medium error
 		 * isn't properly reported.
 		 */
-		SCpnt = scsi_end_request(SCpnt, 0, req->current_nr_sectors);
+		SCpnt = scsi_end_request(SCpnt, 0, req->current_nr_sectors, 1);
 		return;
 	}
 }
 
 /*
- * Function:    scsi_get_request_dev()
- *
- * Purpose:     Find the upper-level driver that is responsible for this
- *              request
- *
- * Arguments:   request   - I/O request we are preparing to queue.
- *
- * Lock status: No locks assumed to be held, but as it happens the
- *              q->queue_lock is held when this is called.
- *
- * Returns:     Nothing
- *
- * Notes:       The requests in the request queue may have originated
- *              from any block device driver.  We need to find out which
- *              one so that we can later form the appropriate command.
- */
-struct Scsi_Device_Template *scsi_get_request_dev(struct request *req)
-{
-	struct gendisk *p = req->rq_disk;
-	return p ? *(struct Scsi_Device_Template **)p->private_data : NULL;
-}
-
-/*
  * Function:    scsi_init_io()
  *
  * Purpose:     SCSI I/O initialize function.
@@ -763,7 +729,7 @@
 	/*
 	 * kill it. there should be no leftover blocks in this request
 	 */
-	SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
+	SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors, 1);
 	BUG_ON(SCpnt);
 	ret = BLKPREP_KILL;
 out:
@@ -797,8 +763,7 @@
 		SRpnt = (Scsi_Request *) req->special;
 		
 		if( SRpnt->sr_magic == SCSI_REQ_MAGIC ) {
-			SCpnt = scsi_allocate_device(SRpnt->sr_device, 
-						     FALSE, FALSE);
+			SCpnt = scsi_allocate_device(SRpnt->sr_device, 0);
 			if (!SCpnt)
 				return BLKPREP_DEFER;
 			scsi_init_cmd_from_req(SCpnt, SRpnt);
@@ -809,9 +774,9 @@
 		 * Now try and find a command block that we can use.
 		 */
 		if (req->special) {
-				SCpnt = (Scsi_Cmnd *) req->special;
+			SCpnt = (Scsi_Cmnd *) req->special;
 		} else {
-			SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE);
+			SCpnt = scsi_allocate_device(SDpnt, 0);
 		}
 		/*
 		 * if command allocation failure, wait a bit
@@ -1085,7 +1050,7 @@
 
 	SHpnt->host_self_blocked = FALSE;
 	/* Now that we are unblocked, try to start the queues. */
-	for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next)
+	list_for_each_entry(SDloop, &SHpnt->my_devices, siblings)
 		scsi_queue_next_request(&SDloop->request_queue, NULL);
 }
 
@@ -1113,7 +1078,7 @@
 void scsi_report_bus_reset(struct Scsi_Host * SHpnt, int channel)
 {
 	Scsi_Device *SDloop;
-	for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next) {
+	list_for_each_entry(SDloop, &SHpnt->my_devices, siblings) {
 		if (channel == SDloop->channel) {
 			SDloop->was_reset = 1;
 			SDloop->expecting_cc_ua = 1;
diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
--- a/drivers/scsi/scsi_proc.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/scsi/scsi_proc.c	Wed Nov 27 14:36:27 2002
@@ -16,14 +16,13 @@
  * Michael A. Griffith <grif@acm.org>
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/errno.h>
-#include <linux/stat.h>
 #include <linux/blk.h>
 #include <asm/uaccess.h>
 
@@ -282,7 +281,7 @@
 	 */
 	for (shost = scsi_host_get_next(NULL); shost;
 	     shost = scsi_host_get_next(shost)) {
-		if (shost->host_queue != NULL) {
+		if (!list_empty(&shost->my_devices)) {
 			break;
 		}
 	}
@@ -292,7 +291,7 @@
 	pos = begin + len;
 	for (shost = scsi_host_get_next(NULL); shost;
 	     shost = scsi_host_get_next(shost)) {
-		for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
+		list_for_each_entry(sdev, &shost->my_devices, siblings) {
 			proc_print_scsidevice(sdev, buffer, &size, len);
 			len += size;
 			pos = begin + len;
@@ -360,7 +359,7 @@
 	     shpnt = scsi_host_get_next(shpnt)) {
 		printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) "
 			"(ret all flg) (to/cmd to ito) cmd snse result\n");
-		for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
+		list_for_each_entry(SDpnt, &shpnt->my_devices, siblings) {
 			for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
 				/*  (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x      */
 				printk(KERN_INFO "(%3d) %2d:%1d:%2d:%2d (%6s %4llu %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n",
@@ -399,11 +398,8 @@
 static int proc_scsi_gen_write(struct file * file, const char * buf,
                               unsigned long length, void *data)
 {
-	Scsi_Device *sdev;
-	struct Scsi_Host *shost;
-	char *p;
 	int host, channel, id, lun;
-	char * buffer;
+	char *buffer, *p;
 	int err;
 
 	if (!buf || length>PAGE_SIZE)
@@ -529,35 +525,9 @@
 		id = simple_strtoul(p + 1, &p, 0);
 		lun = simple_strtoul(p + 1, &p, 0);
 
-		printk(KERN_INFO "scsi singledevice %d %d %d %d\n", host, channel,
-		       id, lun);
-
-		for (shost = scsi_host_get_next(NULL); shost;
-		     shost = scsi_host_get_next(shost)) {
-			if (shost->host_no == host) {
-				break;
-			}
-		}
-		err = -ENXIO;
-		if (!shost)
-			goto out;
-
-		for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
-			if ((sdev->channel == channel
-			     && sdev->id == id
-			     && sdev->lun == lun)) {
-				break;
-			}
-		}
-
-		err = -ENOSYS;
-		if (sdev)
-			goto out;	/* We do not yet support unplugging */
-
-		scan_scsis(shost, 1, channel, id, lun);
-		err = length;
-		goto out;
-	}
+		err = scsi_add_single_device(host, channel, id, lun);
+		if (err >= 0)
+			err = length;
 	/*
 	 * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi
 	 * with  "0 1 2 3" replaced by your "Host Channel Id Lun".
@@ -569,7 +539,7 @@
 	 *     hardware and thoroughly confuse the SCSI subsystem.
 	 *
 	 */
-	else if (!strncmp("remove-single-device", buffer + 5, 20)) {
+	} else if (!strncmp("remove-single-device", buffer + 5, 20)) {
 		p = buffer + 26;
 
 		host = simple_strtoul(p, &p, 0);
@@ -577,39 +547,7 @@
 		id = simple_strtoul(p + 1, &p, 0);
 		lun = simple_strtoul(p + 1, &p, 0);
 
-
-		for (shost = scsi_host_get_next(NULL); shost;
-		     shost = scsi_host_get_next(shost)) {
-			if (shost->host_no == host) {
-				break;
-			}
-		}
-		err = -ENODEV;
-		if (!shost)
-			goto out;
-
-		for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
-			if ((sdev->channel == channel
-			     && sdev->id == id
-			     && sdev->lun == lun)) {
-				break;
-			}
-		}
-
-		if (sdev == NULL)
-			goto out;	/* there is no such device attached */
-
-		err = -EBUSY;
-		if (sdev->access_count)
-			goto out;
-
-		scsi_detach_device(sdev);
-
-		if (sdev->attached == 0) {
-			devfs_unregister (sdev->de);
-			scsi_free_sdev(sdev);
-			err = 0;
-		}
+		err = scsi_remove_single_device(host, channel, id, lun);
 	}
 out:
 	
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/scsi_scan.c	Wed Nov 27 14:36:31 2002
@@ -168,6 +168,7 @@
 	{"DELL", "PV530F", NULL, BLIST_SPARSELUN},
 	{"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
 	{"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN},	/* HP VA7400 */
+	{"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */
 	{"CMD", "CRA-7280", NULL, BLIST_SPARSELUN},	/* CMD RAID Controller */
 	{"CNSI", "G7324", NULL, BLIST_SPARSELUN},	/* Chaparral G7324 RAID */
 	{"CNSi", "G8324", NULL, BLIST_SPARSELUN},	/* Chaparral G8324 RAID */
@@ -181,6 +182,12 @@
 	{"COMPAQ", "MSA1000", NULL, BLIST_FORCELUN},
 	{"HP", "C1557A", NULL, BLIST_FORCELUN},
 	{"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
+	{"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN},
+	{"HITACHI", "DF400", "*", BLIST_SPARSELUN},
+	{"HITACHI", "DF500", "*", BLIST_SPARSELUN},
+	{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
+	{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{ NULL, NULL, NULL, 0 },
 };
 
@@ -468,7 +475,7 @@
 struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel,
 				    uint id, uint lun)
 {
-	struct scsi_device *sdev;
+	struct scsi_device *sdev, *device;
 
 	sdev = kmalloc(sizeof(*sdev), GFP_ATOMIC);
 	if (sdev == NULL)
@@ -483,6 +490,8 @@
 		sdev->lun = lun;
 		sdev->channel = channel;
 		sdev->online = TRUE;
+		INIT_LIST_HEAD(&sdev->siblings);
+		INIT_LIST_HEAD(&sdev->same_target_siblings);
 		/*
 		 * Some low level driver could use device->type
 		 */
@@ -493,6 +502,12 @@
 		 * doesn't
 		 */
 		sdev->borken = 1;
+		if (shost->hostt->slave_alloc)
+			if (shost->hostt->slave_alloc(sdev)) {
+				kfree(sdev);
+				return NULL;
+			}
+
 		scsi_initialize_queue(sdev, shost);
 		sdev->request_queue.queuedata = (void *) sdev;
 
@@ -500,16 +515,21 @@
 		init_waitqueue_head(&sdev->scpnt_wait);
 
 		/*
-		 * Add it to the end of the shost->host_queue list.
+		 * If there are any same target siblings, add this to the
+		 * sibling list
 		 */
-		if (shost->host_queue != NULL) {
-			sdev->prev = shost->host_queue;
-			while (sdev->prev->next != NULL)
-				sdev->prev = sdev->prev->next;
-			sdev->prev->next = sdev;
-		} else
-			shost->host_queue = sdev;
-
+		list_for_each_entry(device, &shost->my_devices, siblings) {
+			if(device->id == sdev->id &&
+			   device->channel == sdev->channel) {
+				list_add_tail(&sdev->same_target_siblings,
+					      &device->same_target_siblings);
+				break;
+			}
+		}
+		/*
+		 * Add it to the end of the shost->my_devices list.
+		 */
+		list_add_tail(&sdev->siblings, &shost->my_devices);
 	}
 	return (sdev);
 }
@@ -524,14 +544,13 @@
  **/
 void scsi_free_sdev(struct scsi_device *sdev)
 {
-	if (sdev->prev != NULL)
-		sdev->prev->next = sdev->next;
-	else
-		sdev->host->host_queue = sdev->next;
-	if (sdev->next != NULL)
-		sdev->next->prev = sdev->prev;
+	list_del(&sdev->siblings);
+	list_del(&sdev->same_target_siblings);
 
 	blk_cleanup_queue(&sdev->request_queue);
+	scsi_release_commandblocks(sdev);
+	if (sdev->host->hostt->slave_destroy)
+		sdev->host->hostt->slave_destroy(sdev);
 	if (sdev->inquiry != NULL)
 		kfree(sdev->inquiry);
 	kfree(sdev);
@@ -1082,32 +1101,6 @@
 }
 
 /**
- * scsi_find_scsi_level - return the scsi_level of a matching target
- *
- * Description:
- *     Return the scsi_level of any Scsi_Device matching @channel, @id,
- *     and @shost.
- * Notes:
- *     Needs to issue an INQUIRY to LUN 0 if no Scsi_Device matches, and
- *     if the INQUIRY can't be sent return a failure.
- **/
-static int scsi_find_scsi_level(unsigned int channel, unsigned int id,
-				struct Scsi_Host *shost)
-{
-	int res = SCSI_2;
-	Scsi_Device *sdev;
-
-	for (sdev = shost->host_queue; sdev; sdev = sdev->next)
-		if ((id == sdev->id) && (channel == sdev->channel))
-			return (int) sdev->scsi_level;
-	/*
-	 * FIXME No matching target id is configured, this needs to get
-	 * the INQUIRY for LUN 0, and use it to determine the scsi_level.
-	 */
-	return res;
-}
-
-/**
  * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
  * @sreq:	used to send the INQUIRY
  * @inq_result:	area to store the INQUIRY result
@@ -1469,6 +1462,17 @@
 	if (sdevscan->current_queue_depth == 0)
 		goto alloc_failed;
 
+	/*
+	 * Since we reuse the same sdevscan over and over with different
+	 * target and lun values, we have to destroy and then recreate
+	 * any possible low level attachments since they very will might
+	 * also store the id and lun numbers in some form and need updating
+	 * with each scan.
+	 */
+	if (sdevscan->host->hostt->slave_destroy)
+		sdevscan->host->hostt->slave_destroy(sdevscan);
+	if (sdevscan->host->hostt->slave_alloc)
+		sdevscan->host->hostt->slave_alloc(sdevscan);
 	sreq = scsi_allocate_request(sdevscan);
 	if (sreq == NULL)
 		goto alloc_failed;
@@ -1703,6 +1707,22 @@
 		 */
 		return 0;
 	}
+	/*
+	 * Since we reuse the same sdevscan over and over with different
+	 * target and lun values, we have to destroy and then recreate
+	 * any possible low level attachments since they very will might
+	 * also store the id and lun numbers in some form and need updating
+	 * with each scan.
+	 *
+	 * This is normally handled in probe_and_add_lun, but since this
+	 * one particular function wants to scan lun 0 on each device
+	 * itself and will possibly pick up a resed sdevscan when doing
+	 * so, it also needs this hack.
+	 */
+	if (sdevscan->host->hostt->slave_destroy)
+		sdevscan->host->hostt->slave_destroy(sdevscan);
+	if (sdevscan->host->hostt->slave_alloc)
+		sdevscan->host->hostt->slave_alloc(sdevscan);
 	sreq = scsi_allocate_request(sdevscan);
 
 	sprintf(devname, "host %d channel %d id %d", sdevscan->host->host_no,
@@ -1862,6 +1882,74 @@
 
 }
 
+int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
+{
+	struct scsi_device *sdevscan, *sdev;
+	struct Scsi_Host *shost;
+	int error = -ENODEV;
+
+	shost = scsi_host_hn_get(host);
+	if (!shost)
+		return -ENODEV;
+	sdev = scsi_find_device(shost, channel, id, lun);
+	if (sdev)
+		goto out;
+
+	error = -ENOMEM;
+	sdevscan = scsi_alloc_sdev(shost, channel, id, lun);
+	if (!sdevscan)
+		goto out;
+
+	if(!list_empty(&sdevscan->same_target_siblings)) {
+		sdev = list_entry(&sdevscan->same_target_siblings, Scsi_Device,
+					same_target_siblings);
+		sdevscan->scsi_level = sdev->scsi_level;
+		sdev = NULL;
+	} else
+		sdevscan->scsi_level = SCSI_2;
+	error = scsi_probe_and_add_lun(sdevscan, &sdev, NULL);
+	scsi_free_sdev(sdevscan);
+
+	if (error != SCSI_SCAN_LUN_PRESENT) 
+		goto out;
+
+	scsi_attach_device(sdev);
+	error = 0;
+
+out:
+	scsi_host_put(shost);
+	return error;
+}
+
+int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)
+{
+	struct scsi_device *sdev;
+	struct Scsi_Host *shost;
+	int error = -ENODEV;
+
+	shost = scsi_host_hn_get(host);
+	if (!shost)
+		return -ENODEV;
+	sdev = scsi_find_device(shost, channel, id, lun);
+	if (!sdev)
+		goto out;
+
+	error = -EBUSY;
+	if (sdev->access_count)
+		goto out;
+	scsi_detach_device(sdev);
+	if (sdev->attached)
+		goto out;
+
+	devfs_unregister(sdev->de);
+	scsi_free_sdev(sdev);
+	error = 0;
+
+out:
+	scsi_host_put(shost);
+	return error;
+}
+
 /**
  * scsi_scan_target - scan a target id, possibly including all LUNs on the
  *     target.
@@ -1927,111 +2015,56 @@
 }
 
 /**
- * scsi_scan_selected_lun - probe and add one LUN
+ * scsi_scan_host - scan the given adapter
+ * @shost:	adapter to scan
  *
  * Description:
- *     Probe a single LUN on @shost, @channel, @id and @lun. If the LUN is
- *     found, set the queue depth, allocate command blocks, and call
- *     init/attach/finish of the upper level (sd, sg, etc.) drivers.
+ *     Iterate and call scsi_scan_target to scan all possible target id's
+ *     on all possible channels.
  **/
-static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
-				   uint id, uint lun)
+void scsi_scan_host(struct Scsi_Host *shost)
 {
-	Scsi_Device *sdevscan, *sdev = NULL;
-	int res;
+	struct scsi_device *sdevscan;
+	uint channel, id, order_id;
 
-	if ((channel > shost->max_channel) || (id >= shost->max_id) ||
-	    (lun >= shost->max_lun))
-		return;
-
-	sdevscan = scsi_alloc_sdev(shost, channel, id, lun);
+	/*
+	 * The blk layer queue allocation is a bit expensive to
+	 * repeat for each channel and id - for FCP max_id is near
+	 * 255: each call to scsi_alloc_sdev() implies a call to
+	 * blk_init_queue, and then blk_init_free_list, where 2 *
+	 * queue_nr_requests requests are allocated. Don't do so
+	 * here for scsi_scan_selected_lun, since we end up
+	 * calling select_queue_depths with an extra Scsi_Device
+	 * on the host_queue list.
+	 */
+	sdevscan = scsi_alloc_sdev(shost, 0, 0, 0);
 	if (sdevscan == NULL)
 		return;
-
-	sdevscan->scsi_level = scsi_find_scsi_level(channel, id, shost);
-	res = scsi_probe_and_add_lun(sdevscan, &sdev, NULL);
-	scsi_free_sdev(sdevscan);
-
-	if (res != SCSI_SCAN_LUN_PRESENT) 
-		return;
-
-	scsi_attach_device(sdev);
-}
-
-/**
- * scan_scsis - scan the given adapter, or scan a single LUN
- * @shost:	adapter to scan
- * @hardcoded:	1 if a single channel/id/lun should be scanned, else 0
- * @hchannel:	channel to scan for hardcoded case
- * @hid:	target id to scan for hardcoded case
- * @hlun:	lun to scan for hardcoded case
- *
- * Description:
- *     If @hardcoded is 1, call scsi_scan_selected_lun to scan a single
- *     LUN; else, iterate and call scsi_scan_target to scan all possible
- *     target id's on all possible channels.
- **/
-void scan_scsis(struct Scsi_Host *shost, uint hardcoded, uint hchannel,
-		uint hid, uint hlun)
-{
-	if (hardcoded == 1) {
+	/*
+	 * The sdevscan host, channel, id and lun are filled in as
+	 * needed to scan.
+	 */
+	for (channel = 0; channel <= shost->max_channel; channel++) {
 		/*
-		 * XXX Overload hchannel/hid/hlun to figure out what to
-		 * scan, and use the standard scanning code rather than
-		 * this function - that way, an entire bus (or fabric), or
-		 * target id can be scanned. There are problems with queue
-		 * depth and the init/attach/finish that must be resolved
-		 * before (re-)scanning can handle finding more than one new
-		 * LUN.
+		 * XXX adapter drivers when possible (FCP, iSCSI)
+		 * could modify max_id to match the current max,
+		 * not the absolute max.
 		 *
-		 * For example, set hchannel 0 and hid to 5, and hlun to -1
-		 * in order to scan all LUNs on channel 0, target id 5.
-		 */
-		scsi_scan_selected_lun(shost, hchannel, hid, hlun);
-	} else {
-		Scsi_Device *sdevscan;
-		uint channel;
-		unsigned int id, order_id;
-
-		/*
-		 * The blk layer queue allocation is a bit expensive to
-		 * repeat for each channel and id - for FCP max_id is near
-		 * 255: each call to scsi_alloc_sdev() implies a call to
-		 * blk_init_queue, and then blk_init_free_list, where 2 *
-		 * queue_nr_requests requests are allocated. Don't do so
-		 * here for scsi_scan_selected_lun, since we end up
-		 * calling select_queue_depths with an extra Scsi_Device
-		 * on the host_queue list.
-		 */
-		sdevscan = scsi_alloc_sdev(shost, 0, 0, 0);
-		if (sdevscan == NULL)
-			return;
-		/*
-		 * The sdevscan host, channel, id and lun are filled in as
-		 * needed to scan.
+		 * XXX add a shost id iterator, so for example,
+		 * the FC ID can be the same as a target id
+		 * without a huge overhead of sparse id's.
 		 */
-		for (channel = 0; channel <= shost->max_channel; channel++) {
-			/*
-			 * XXX adapter drivers when possible (FCP, iSCSI)
-			 * could modify max_id to match the current max,
-			 * not the absolute max.
-			 *
-			 * XXX add a shost id iterator, so for example,
-			 * the FC ID can be the same as a target id
-			 * without a huge overhead of sparse id's.
-			 */
-			for (id = 0; id < shost->max_id; ++id) {
-				if (shost->reverse_ordering)
-					/*
-					 * Scan from high to low id.
-					 */
-					order_id = shost->max_id - id - 1;
-				else
-					order_id = id;
-				scsi_scan_target(sdevscan, shost, channel,
-						 order_id);
-			}
+		for (id = 0; id < shost->max_id; ++id) {
+			if (shost->reverse_ordering)
+				/*
+				 * Scan from high to low id.
+				 */
+				order_id = shost->max_id - id - 1;
+			else
+				order_id = id;
+			scsi_scan_target(sdevscan, shost, channel,
+					 order_id);
 		}
-		scsi_free_sdev(sdevscan);
 	}
+	scsi_free_sdev(sdevscan);
 }
diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
--- a/drivers/scsi/scsi_syms.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/scsi_syms.c	Wed Nov 27 14:36:30 2002
@@ -68,6 +68,7 @@
 EXPORT_SYMBOL(scsi_block_requests);
 EXPORT_SYMBOL(scsi_unblock_requests);
 EXPORT_SYMBOL(scsi_adjust_queue_depth);
+EXPORT_SYMBOL(scsi_track_queue_full);
 
 EXPORT_SYMBOL(scsi_get_host_dev);
 EXPORT_SYMBOL(scsi_free_host_dev);
@@ -75,7 +76,6 @@
 EXPORT_SYMBOL(scsi_sleep);
 
 EXPORT_SYMBOL(scsi_io_completion);
-EXPORT_SYMBOL(scsi_end_request);
 
 EXPORT_SYMBOL(scsi_register_blocked_host);
 EXPORT_SYMBOL(scsi_deregister_blocked_host);
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/sg.c	Wed Nov 27 14:36:30 2002
@@ -474,9 +474,7 @@
 			sb_len = (hp->mx_sb_len > sb_len) ? sb_len : hp->mx_sb_len;
 			len = 8 + (int) srp->sense_b[7];	/* Additional sense length field */
 			len = (len > sb_len) ? sb_len : len;
-			if ((err = verify_area(VERIFY_WRITE, hp->sbp, len)))
-				goto err_out;
-			if (__copy_to_user(hp->sbp, srp->sense_b, len)) {
+			if (copy_to_user(hp->sbp, srp->sense_b, len)) {
 				err = -EFAULT;
 				goto err_out;
 			}
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/st.c	Wed Nov 27 14:36:31 2002
@@ -3673,19 +3673,18 @@
 	buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i);
 	if (buffer == NULL) {
 		printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n");
-		return 1;
+		goto out_slave_detach;
 	}
 
 	disk = alloc_disk(1);
 	if (!disk) {
 		printk(KERN_ERR "st: out of memory. Device not attached.\n");
-		return 1;
+		goto out_buffer_free;
 	}
 
 	write_lock(&st_dev_arr_lock);
 	if (st_nr_dev >= st_dev_max) {
 		Scsi_Tape **tmp_da;
-		ST_buffer **tmp_ba;
 		int tmp_dev_max;
 
 		tmp_dev_max = st_nr_dev + ST_DEV_ARR_LUMP;
@@ -3695,23 +3694,14 @@
 			write_unlock(&st_dev_arr_lock);
 			printk(KERN_ERR "st: Too many tape devices (max. %d).\n",
 			       ST_MAX_TAPES);
-			put_disk(disk);
-			scsi_slave_detach(SDp);
-			return 1;
+			goto out_put_disk;
 		}
 
 		tmp_da = kmalloc(tmp_dev_max * sizeof(Scsi_Tape *), GFP_ATOMIC);
-		tmp_ba = kmalloc(tmp_dev_max * sizeof(ST_buffer *), GFP_ATOMIC);
-		if (tmp_da == NULL || tmp_ba == NULL) {
-			if (tmp_da != NULL)
-				kfree(tmp_da);
-			if (tmp_ba != NULL)
-				kfree(tmp_ba);
+		if (tmp_da == NULL) {
 			write_unlock(&st_dev_arr_lock);
 			printk(KERN_ERR "st: Can't extend device array.\n");
-			put_disk(disk);
-			scsi_slave_detach(SDp);
-			return 1;
+			goto out_put_disk;
 		}
 
 		memset(tmp_da, 0, tmp_dev_max * sizeof(Scsi_Tape *));
@@ -3735,9 +3725,7 @@
 	if (tpnt == NULL) {
 		write_unlock(&st_dev_arr_lock);
 		printk(KERN_ERR "st: Can't allocate device descriptor.\n");
-		put_disk(disk);
-		scsi_slave_detach(SDp);
-		return 1;
+		goto out_put_disk;
 	}
 	memset(tpnt, 0, sizeof(Scsi_Tape));
 	tpnt->disk = disk;
@@ -3840,14 +3828,14 @@
 	    tpnt->driverfs_dev_r[mode].parent = &SDp->sdev_driverfs_dev;
 	    tpnt->driverfs_dev_r[mode].bus = &scsi_driverfs_bus_type;
 	    tpnt->driverfs_dev_r[mode].driver_data =
-			(void *)(long)__mkdev(MAJOR_NR, dev_num + (mode << 5));
+			(void *)(long)__mkdev(SCSI_TAPE_MAJOR, dev_num + (mode << 5));
 	    device_register(&tpnt->driverfs_dev_r[mode]);
 	    device_create_file(&tpnt->driverfs_dev_r[mode], 
 			       &dev_attr_type);
 	    device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
 	    tpnt->de_r[mode] =
 		devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
-				MAJOR_NR, dev_num + (mode << 5),
+				SCSI_TAPE_MAJOR, dev_num + (mode << 5),
 				S_IFCHR | S_IRUGO | S_IWUGO,
 				&st_fops, NULL);
 	    /*  No-rewind entry  */
@@ -3859,7 +3847,7 @@
 	    tpnt->driverfs_dev_n[mode].parent= &SDp->sdev_driverfs_dev;
 	    tpnt->driverfs_dev_n[mode].bus = &scsi_driverfs_bus_type;
 	    tpnt->driverfs_dev_n[mode].driver_data =
-			(void *)(long)__mkdev(MAJOR_NR, dev_num + (mode << 5) + 128);
+			(void *)(long)__mkdev(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128);
 	    device_register(&tpnt->driverfs_dev_n[mode]);
 	    device_create_file(&tpnt->driverfs_dev_n[mode], 
 			       &dev_attr_type);
@@ -3867,7 +3855,7 @@
 			       &dev_attr_kdev);
 	    tpnt->de_n[mode] =
 		devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
-				MAJOR_NR, dev_num + (mode << 5) + 128,
+				SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128,
 				S_IFCHR | S_IRUGO | S_IWUGO,
 				&st_fops, NULL);
 	}
@@ -3880,6 +3868,14 @@
 	       tape_name(tpnt), tpnt->try_dio ? "yes" : "no", tpnt->max_pfn);
 
 	return 0;
+
+out_put_disk:
+	put_disk(disk);
+out_buffer_free:
+	kfree(buffer);
+out_slave_detach:
+	scsi_slave_detach(SDp);
+	return 1;
 };
 
 static void st_detach(Scsi_Device * SDp)
@@ -3891,20 +3887,15 @@
 	for (i = 0; i < st_dev_max; i++) {
 		tpnt = scsi_tapes[i];
 		if (tpnt != NULL && tpnt->device == SDp) {
-			tpnt->device = NULL;
+			scsi_tapes[i] = 0;
+			st_nr_dev--;
+			write_unlock(&st_dev_arr_lock);
+			devfs_unregister_tape(tpnt->disk->number);
 			for (mode = 0; mode < ST_NBR_MODES; ++mode) {
 				devfs_unregister (tpnt->de_r[mode]);
 				tpnt->de_r[mode] = NULL;
 				devfs_unregister (tpnt->de_n[mode]);
 				tpnt->de_n[mode] = NULL;
-			}
-			devfs_unregister_tape(tpnt->disk->number);
-			scsi_tapes[i] = 0;
-			scsi_slave_detach(SDp);
-			st_nr_dev--;
-			write_unlock(&st_dev_arr_lock);
-
-			for (mode = 0; mode < ST_NBR_MODES; ++mode) {
 				device_remove_file(&tpnt->driverfs_dev_r[mode],
 						   &dev_attr_type);
 				device_remove_file(&tpnt->driverfs_dev_r[mode],
@@ -3916,11 +3907,14 @@
 						   &dev_attr_kdev);
 				device_unregister(&tpnt->driverfs_dev_n[mode]);
 			}
+			tpnt->device = NULL;
+
 			if (tpnt->buffer) {
 				tpnt->buffer->orig_frp_segs = 0;
 				normalize_buffer(tpnt->buffer);
 				kfree(tpnt->buffer);
 			}
+			scsi_slave_detach(SDp);
 			put_disk(tpnt->disk);
 			kfree(tpnt);
 			return;
@@ -3944,9 +3938,10 @@
 	if (register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) {
 		if (scsi_register_device(&st_template) == 0)
 			return 0;
+		unregister_chrdev(SCSI_TAPE_MAJOR, "st");
 	}
 
-	printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", MAJOR_NR);
+	printk(KERN_ERR "Unable to get major %d for SCSI tapes\n", SCSI_TAPE_MAJOR);
 	return 1;
 }
 
@@ -3959,8 +3954,9 @@
 	if (scsi_tapes != NULL) {
 		for (i=0; i < st_dev_max; ++i)
 			if (scsi_tapes[i]) {
-				put_disk(scsi_tapes[i]->disk);
-				kfree(scsi_tapes[i]);
+				printk(KERN_WARNING "st: scsi_tapes[] not "
+				    "empty after scsi_unregister_device\n");
+				st_detach(scsi_tapes[i]->device);
 			}
 		kfree(scsi_tapes);
 	}
diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
--- a/drivers/scsi/sym53c8xx.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/sym53c8xx.c	Wed Nov 27 14:36:31 2002
@@ -13525,7 +13525,7 @@
 	return DEF_DEPTH;
 }
 
-int sym53c8xx_slave_attach(Scsi_Device *device)
+int sym53c8xx_slave_configure(Scsi_Device *device)
 {
 	struct Scsi_Host *host = device->host;
 	ncb_p np;
diff -Nru a/drivers/scsi/sym53c8xx.h b/drivers/scsi/sym53c8xx.h
--- a/drivers/scsi/sym53c8xx.h	Wed Nov 27 14:36:29 2002
+++ b/drivers/scsi/sym53c8xx.h	Wed Nov 27 14:36:29 2002
@@ -74,7 +74,7 @@
 const char *sym53c8xx_info(struct Scsi_Host *host);
 int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int sym53c8xx_reset(Scsi_Cmnd *, unsigned int);
-int sym53c8xx_slave_attach(Scsi_Device *);
+int sym53c8xx_slave_configure(Scsi_Device *);
 
 #ifdef MODULE
 int sym53c8xx_release(struct Scsi_Host *);
@@ -90,7 +90,7 @@
 			release:        sym53c8xx_release,	\
 			info:           sym53c8xx_info, 	\
 			queuecommand:   sym53c8xx_queue_command,\
-			slave_attach:   sym53c8xx_slave_attach, \
+			slave_configure:sym53c8xx_slave_configure,\
 			abort:          sym53c8xx_abort,	\
 			reset:          sym53c8xx_reset,	\
 			can_queue:      SCSI_NCR_CAN_QUEUE,	\
diff -Nru a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h
--- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h	Wed Nov 27 14:36:32 2002
@@ -89,7 +89,7 @@
 int sym53c8xx_eh_bus_reset_handler(Scsi_Cmnd *);
 int sym53c8xx_eh_host_reset_handler(Scsi_Cmnd *);
 
-int sym53c8xx_slave_attach(Scsi_Device *);
+int sym53c8xx_slave_configure(Scsi_Device *);
 
 #ifdef MODULE
 int sym53c8xx_release(struct Scsi_Host *);
@@ -111,7 +111,7 @@
 	release:		sym53c8xx_release,			\
 	info:			sym53c8xx_info, 			\
 	queuecommand:		sym53c8xx_queue_command,		\
-	slave_attach:		sym53c8xx_slave_attach,			\
+	slave_configure:	sym53c8xx_slave_configure,		\
 	eh_abort_handler:	sym53c8xx_eh_abort_handler,		\
 	eh_device_reset_handler:sym53c8xx_eh_device_reset_handler,	\
 	eh_bus_reset_handler:	sym53c8xx_eh_bus_reset_handler,		\
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c	Wed Nov 27 14:36:32 2002
@@ -1328,7 +1328,7 @@
  * Linux entry point for device queue sizing.
  */
 int
-sym53c8xx_slave_attach(Scsi_Device *device)
+sym53c8xx_slave_configure(Scsi_Device *device)
 {
 	struct Scsi_Host *host = device->host;
 	hcb_p np;
diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c
--- a/drivers/scsi/t128.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/t128.c	Wed Nov 27 14:36:31 2002
@@ -111,15 +111,17 @@
 #include <linux/sched.h>
 #include <asm/io.h>
 #include <linux/blk.h>
+#include <linux/interrupt.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+
 #include "scsi.h"
 #include "hosts.h"
 #include "t128.h"
 #define AUTOPROBE_IRQ
 #include "NCR5380.h"
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
 
 static struct override {
     unsigned long address;
@@ -143,7 +145,7 @@
 
 #define NO_BASES (sizeof (bases) / sizeof (struct base))
 
-static const struct signature {
+static struct signature {
     const char *string;
     int offset;
 } signatures[] __initdata = {
diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
--- a/drivers/scsi/u14-34f.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/scsi/u14-34f.c	Wed Nov 27 14:36:28 2002
@@ -630,7 +630,7 @@
 static int max_queue_depth = MAX_CMD_PER_LUN;
 #endif
 
-static int u14_34f_slave_attach(Scsi_Device *dev) {
+static int u14_34f_slave_configure(Scsi_Device *dev) {
    int j, tqd, utqd;
    char *tag_suffix, *link_suffix;
    struct Scsi_Host *host = dev->host;
diff -Nru a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h
--- a/drivers/scsi/u14-34f.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/scsi/u14-34f.h	Wed Nov 27 14:36:31 2002
@@ -8,7 +8,7 @@
 static int u14_34f_eh_abort(Scsi_Cmnd *);
 static int u14_34f_eh_host_reset(Scsi_Cmnd *);
 static int u14_34f_bios_param(struct scsi_device *, struct block_device *, sector_t, int *);
-static int u14_34f_slave_attach(Scsi_Device *);
+static int u14_34f_slave_configure(Scsi_Device *);
 
 #define U14_34F_VERSION "8.00.00"
 
@@ -22,7 +22,7 @@
                 eh_bus_reset_handler:    NULL,                               \
                 eh_host_reset_handler:   u14_34f_eh_host_reset,              \
                 bios_param:              u14_34f_bios_param,                 \
-                slave_attach:            u14_34f_slave_attach,               \
+                slave_configure:         u14_34f_slave_configure,            \
                 this_id:                 7,                                  \
                 unchecked_isa_dma:       1,                                  \
                 use_clustering:          ENABLE_CLUSTERING                   \
diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
--- a/drivers/scsi/ultrastor.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/scsi/ultrastor.c	Wed Nov 27 14:36:30 2002
@@ -1047,7 +1047,7 @@
 	printk("Ux4F interrupt: bad MSCP address %x\n", (unsigned int) mscp);
 	/* A command has been lost.  Reset and report an error
 	   for all commands.  */
-	ultrastor_reset(NULL, 0);
+	ultrastor_host_reset(dev_id);
 	return;
     }
 #endif
diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
--- a/drivers/scsi/wd7000.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/scsi/wd7000.c	Wed Nov 27 14:36:32 2002
@@ -1434,23 +1434,21 @@
 	/*
 	 * Display driver information for each device attached to the board.
 	 */
-	scd = host->host_queue;
+	SPRINTF("\nAttached devices: %s\n", !list_empty(&host->my_devices) ?
+		       	"" : "none");
 
-	SPRINTF("\nAttached devices: %s\n", scd ? "" : "none");
+	list_for_each_entry (scd, &host->my_devices, siblings) {
+		SPRINTF("  [Channel: %02d, Id: %02d, Lun: %02d]  ", scd->channel, scd->id, scd->lun);
+		SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(short) scd->type] : "Unknown device");
 
-	for (; scd; scd = scd->next)
-		if (scd->host->host_no == hostno) {
-			SPRINTF("  [Channel: %02d, Id: %02d, Lun: %02d]  ", scd->channel, scd->id, scd->lun);
-			SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(short) scd->type] : "Unknown device");
+		for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++)
+			SPRINTF("%c", scd->vendor[i]);
+		SPRINTF(" ");
 
-			for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++)
-				SPRINTF("%c", scd->vendor[i]);
-			SPRINTF(" ");
-
-			for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++)
-				SPRINTF("%c", scd->model[i]);
-			SPRINTF("\n");
-		}
+		for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++)
+			SPRINTF("%c", scd->model[i]);
+		SPRINTF("\n");
+	}
 
 	SPRINTF("\n");
 
diff -Nru a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c
--- a/drivers/serial/8250_acorn.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/serial/8250_acorn.c	Wed Nov 27 14:36:31 2002
@@ -55,8 +55,6 @@
 	unsigned long cardaddr, address;
 	int port;
 
-	ecard_claim (ec);
-
 	info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
@@ -64,6 +62,8 @@
 	memset(info, 0, sizeof(struct serial_card_info));
 	info->num_ports = type->num_ports;
 
+	ecard_set_drvdata(ec, info);
+
 	cardaddr = ecard_address(ec, type->type, type->speed);
 
 	for (port = 0; port < info->num_ports; port ++) {
@@ -98,8 +98,6 @@
 	}
 
 	kfree(info);
-
-	ecard_release(ec);
 }
 
 static struct serial_card_type atomwide_type = {
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	Wed Nov 27 14:36:31 2002
+++ b/drivers/serial/Kconfig	Wed Nov 27 14:36:31 2002
@@ -365,7 +365,7 @@
 
 config V850E_NB85E_UART
 	bool "NEC V850E on-chip UART support"
-	depends on V850E_NB85E || V850E2_ANNA
+	depends on V850E_NB85E || V850E2_ANNA || V850E_AS85EP1
 	default y
 
 config V850E_NB85E_UART_CONSOLE
diff -Nru a/drivers/serial/nb85e_uart.c b/drivers/serial/nb85e_uart.c
--- a/drivers/serial/nb85e_uart.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/serial/nb85e_uart.c	Wed Nov 27 14:36:31 2002
@@ -25,10 +25,10 @@
 
 /* Initial UART state.  This may be overridden by machine-dependent headers. */
 #ifndef NB85E_UART_INIT_BAUD
-#define NB85E_UART_INIT_BAUD	38400
+#define NB85E_UART_INIT_BAUD	115200
 #endif
 #ifndef NB85E_UART_INIT_CFLAGS
-#define NB85E_UART_INIT_CFLAGS	(B38400 | CS8 | CREAD)
+#define NB85E_UART_INIT_CFLAGS	(B115200 | CS8 | CREAD)
 #endif
 
 /* A string used for prefixing printed descriptions; since the same UART
@@ -304,7 +304,7 @@
 		port->icount.tx++;
 
 		if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
-			uart_event (port, EVT_WRITE_WAKEUP);
+			uart_write_wakeup (port);
 	}
 
  no_xmit:
diff -Nru a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
--- a/drivers/usb/core/Kconfig	Wed Nov 27 14:36:31 2002
+++ b/drivers/usb/core/Kconfig	Wed Nov 27 14:36:31 2002
@@ -38,18 +38,6 @@
 
 	  Most users want to say Y here.
 
-config USB_LONG_TIMEOUT
-	bool "Long timeout for slow-responding devices (some MGE Ellipse UPSes)"
-	depends on USB
-	help
-	  This option makes the standard time out a bit longer.  Basically,
-	  some devices are just slow to respond, so this makes usb more
-	  patient.  There should be no harm in selecting this, but it is
-	  needed for some MGE Ellipse UPSes.
-
-	  If you have an MGE Ellipse UPS, or you see timeouts in HID
-	  transactions, say Y; otherwise say N.
-
 config USB_BANDWIDTH
 	bool "Enforce USB bandwidth allocation (EXPERIMENTAL)"
 	depends on USB && EXPERIMENTAL
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/usb/core/devio.c	Wed Nov 27 14:36:30 2002
@@ -53,6 +53,7 @@
         struct dev_state *ps;
 	struct task_struct *task;
 	unsigned int signr;
+	unsigned int intf;
 	void *userbuffer;
         void *userurb;
         struct urb *urb;
@@ -273,23 +274,47 @@
 	}
 }
 
-static void destroy_all_async(struct dev_state *ps)
+static void destroy_async (struct dev_state *ps, struct list_head *list)
 {
-        struct async *as;
-        unsigned long flags;
+	struct async *as;
+	unsigned long flags;
 
-        spin_lock_irqsave(&ps->lock, flags);
-        while (!list_empty(&ps->async_pending)) {
-                as = list_entry(ps->async_pending.next, struct async, asynclist);
-                list_del_init(&as->asynclist);
-                spin_unlock_irqrestore(&ps->lock, flags);
+	spin_lock_irqsave(&ps->lock, flags);
+	while (!list_empty(list)) {
+		as = list_entry(list->next, struct async, asynclist);
+		list_del_init(&as->asynclist);
+		spin_unlock_irqrestore(&ps->lock, flags);
                 /* usb_unlink_urb calls the completion handler with status == -ENOENT */
-                usb_unlink_urb(as->urb);
-                spin_lock_irqsave(&ps->lock, flags);
-        }
-        spin_unlock_irqrestore(&ps->lock, flags);
-        while ((as = async_getcompleted(ps)))
-                free_async(as);
+		usb_unlink_urb(as->urb);
+		spin_lock_irqsave(&ps->lock, flags);
+	}
+	spin_unlock_irqrestore(&ps->lock, flags);
+	while ((as = async_getcompleted(ps)))
+		free_async(as);
+}
+
+static void destroy_async_on_interface (struct dev_state *ps, unsigned int intf)
+{
+	struct async *as;
+	struct list_head *p, hitlist;
+	unsigned long flags;
+
+	INIT_LIST_HEAD(&hitlist);
+	spin_lock_irqsave(&ps->lock, flags);
+	for (p = ps->async_pending.next; p != &ps->async_pending; ) {
+		as = list_entry(p, struct async, asynclist);
+		p = p->next;
+
+		if (as->intf == intf)
+			list_move_tail(&as->asynclist, &hitlist);
+	}
+	spin_unlock_irqrestore(&ps->lock, flags);
+	destroy_async(ps, &hitlist);
+}
+
+extern __inline__ void destroy_all_async(struct dev_state *ps)
+{
+	        destroy_async(ps, &ps->async_pending);
 }
 
 /*
@@ -751,7 +776,7 @@
 	struct async *as;
 	struct usb_ctrlrequest *dr = NULL;
 	unsigned int u, totlen, isofrmlen;
-	int ret, interval = 0;
+	int ret, interval = 0, intf = -1;
 
 	if (copy_from_user(&uurb, arg, sizeof(uurb)))
 		return -EFAULT;
@@ -763,9 +788,9 @@
 	if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
 		return -EINVAL;
 	if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
-		if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
-			return ret;
-		if ((ret = checkintf(ps, ret)))
+		if ((intf = findintfep(ps->dev, uurb.endpoint)) < 0)
+			return intf;
+		if ((ret = checkintf(ps, intf)))
 			return ret;
 	}
 	switch(uurb.type) {
@@ -889,6 +914,7 @@
 	else
 		as->userbuffer = NULL;
 	as->signr = uurb.signr;
+	as->intf = intf;
 	as->task = current;
 	if (!(uurb.endpoint & USB_DIR_IN)) {
 		if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {
@@ -1035,7 +1061,10 @@
 		return -EFAULT;
 	if ((ret = findintfif(ps->dev, intf)) < 0)
 		return ret;
-	return releaseintf(ps, intf);
+	if ((ret = releaseintf(ps, intf)) < 0)
+		return ret;
+	destroy_async_on_interface (ps, intf);
+	return 0;
 }
 
 static int proc_ioctl (struct dev_state *ps, void *arg)
diff -Nru a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
--- a/drivers/usb/host/ohci-mem.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/usb/host/ohci-mem.c	Wed Nov 27 14:36:31 2002
@@ -14,7 +14,8 @@
  *	- data used only by the HCD ... kmalloc is fine
  *	- async and periodic schedules, shared by HC and HCD ... these
  *	  need to use pci_pool or pci_alloc_consistent
- *	- driver buffers, read/written by HC ... single shot DMA mapped 
+ *	- driver buffers, read/written by HC ... the hcd glue or the
+ *	  device driver provides us with dma addresses
  *
  * There's also PCI "register" data, which is memory mapped.
  * No memory seen by this driver is pagable.
@@ -41,95 +42,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* Recover a TD/ED using its collision chain */
-static inline void *
-dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
-{
-	struct hash_t * scan = entry->head;
-	while (scan && scan->dma != dma)
-		scan = scan->next;
-	return scan ? scan->virt : 0;
-}
-
-static inline struct td *
-dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
-{
-	td_dma &= TD_MASK;
-	return (struct td *) dma_to_ed_td(&(hc->td_hash [TD_HASH_FUNC(td_dma)]),
-				      td_dma);
-}
-
-// FIXME:  when updating the hashtables this way, mem_flags is unusable...
-
-/* Add a hash entry for a TD/ED; return true on success */
-static inline int
-hash_add_ed_td (
-	struct hash_list_t *entry,
-	void *virt,
-	dma_addr_t dma,
-	int mem_flags
-)
-{
-	struct hash_t * scan;
-	
-	scan = (struct hash_t *) kmalloc (sizeof *scan, mem_flags);
-	if (!scan)
-		return 0;
-	
-	if (!entry->tail) {
-		entry->head = entry->tail = scan;
-	} else {
-		entry->tail->next = scan;
-		entry->tail = scan;
-	}
-	
-	scan->virt = virt;
-	scan->dma = dma;
-	scan->next = NULL;
-	return 1;
-}
-
-static inline int
-hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags)
-{
-	return hash_add_ed_td (&(hc->td_hash [TD_HASH_FUNC (td->td_dma)]),
-			td, td->td_dma, mem_flags);
-}
-
-
-static inline void
-hash_free_ed_td (struct hash_list_t *entry, void *virt)
-{
-	struct hash_t *scan, *prev;
-	scan = prev = entry->head;
-
-	// Find and unlink hash entry
-	while (scan && scan->virt != virt) {
-		prev = scan;
-		scan = scan->next;
-	}
-	if (scan) {
-		if (scan == entry->head) {
-			if (entry->head == entry->tail)
-				entry->head = entry->tail = NULL;
-			else
-				entry->head = scan->next;
-		} else if (scan == entry->tail) {
-			entry->tail = prev;
-			prev->next = NULL;
-		} else
-			prev->next = scan->next;
-		kfree(scan);
-	}
-}
-
-static inline void
-hash_free_td (struct ohci_hcd *hc, struct td * td)
-{
-	hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td);
-}
-
-
 static int ohci_mem_init (struct ohci_hcd *ohci)
 {
 	ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev,
@@ -161,6 +73,21 @@
 	}
 }
 
+/*-------------------------------------------------------------------------*/
+
+/* ohci "done list" processing needs this mapping */
+static inline struct td *
+dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
+{
+	struct td *td;
+
+	td_dma &= TD_MASK;
+	td = hc->td_hash [TD_HASH_FUNC(td_dma)];
+	while (td && td->td_dma != td_dma)
+		td = td->td_hash;
+	return td;
+}
+
 /* TDs ... */
 static struct td *
 td_alloc (struct ohci_hcd *hc, int mem_flags)
@@ -170,12 +97,17 @@
 
 	td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
 	if (td) {
+		int	hash;
+
+		/* in case hc fetches it, make it look dead */
+		memset (td, 0, sizeof *td);
+		td->hwNextTD = cpu_to_le32 (dma);
 		td->td_dma = dma;
+
 		/* hash it for later reverse mapping */
-		if (!hash_add_td (hc, td, mem_flags)) {
-			pci_pool_free (hc->td_cache, td, dma);
-			return NULL;
-		}
+		hash = TD_HASH_FUNC (dma);
+		td->td_hash = hc->td_hash [hash];
+		hc->td_hash [hash] = td;
 	}
 	return td;
 }
@@ -183,10 +115,18 @@
 static void
 td_free (struct ohci_hcd *hc, struct td *td)
 {
-	hash_free_td (hc, td);
+	struct td	**prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
+
+	while (*prev && *prev != td)
+		prev = &(*prev)->td_hash;
+	if (*prev)
+		*prev = td->td_hash;
+	else
+		dev_dbg (*hc->hcd.controller, "bad hash for td %p\n", td);
 	pci_pool_free (hc->td_cache, td, td->td_dma);
 }
 
+/*-------------------------------------------------------------------------*/
 
 /* EDs ... */
 static struct ed *
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/usb/host/ohci.h	Wed Nov 27 14:36:32 2002
@@ -111,6 +111,7 @@
 	/* rest are purely for the driver's use */
   	__u8		index;
   	struct ed	*ed;
+  	struct td	*td_hash;	/* dma-->td hashtable */
   	struct td	*next_dl_td;
   	struct urb	*urb;
 
@@ -320,23 +321,9 @@
 
 #define URB_DEL 1
 
-
-/* Hash struct used for TD/ED hashing */
-struct hash_t {
-	void		*virt;
-	dma_addr_t	dma;
-	struct hash_t	*next; // chaining for collision cases
-};
-
-/* List of TD/ED hash entries */
-struct hash_list_t {
-	struct hash_t	*head;
-	struct hash_t	*tail;
-};
-
 #define TD_HASH_SIZE    64    /* power'o'two */
-
-#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE)
+// sizeof (struct td) ~= 64 == 2^6 ... 
+#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)
 
 
 /*
@@ -373,7 +360,7 @@
 	 */
 	struct pci_pool		*td_cache;
 	struct pci_pool		*ed_cache;
-	struct hash_list_t	td_hash [TD_HASH_SIZE];
+	struct td		*td_hash [TD_HASH_SIZE];
 
 	/*
 	 * driver state
diff -Nru a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
--- a/drivers/usb/media/Kconfig	Wed Nov 27 14:36:27 2002
+++ b/drivers/usb/media/Kconfig	Wed Nov 27 14:36:27 2002
@@ -120,15 +120,26 @@
 	tristate "USB Philips Cameras"
 	depends on USB && VIDEO_DEV
 	---help---
-	  Say Y or M here if you want to use one of these Philips USB webcams:
-	  PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
-	  the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
-	  by this driver and never will be.
+	  Say Y or M here if you want to use one of these Philips & OEM
+          webcams:
+           * Philips PCA645, PCA646
+           * Philips PCVC675, PCVC680, PCVC690
+           * Philips PCVC730, PCVC740, PCVC750
+	   * Askey VC010
+	   * Logitech QuickCam Pro 3000, 4000, 'Zoom' and 'Notebook'
+	   * Samsung MPC-C10, MPC-C30
+	   * Creative Webcam 5
+	   * SOTECT Afina Eye
+	   * Visionite VCS-UC300, VCS-UM100
+	   
+	  The PCA635, PCVC665 and PCVC720 are not supported by this driver
+	  and never will be, but the 665 and 720 are supported by other 
+	  drivers.
 
-	  This driver has an optional plugin, which is distributed as a binary
-	  module only.  It contains code that allow you to use higher
-	  resolutions and framerates but may not be distributed as source.
-	  But even without this plugin you can these cams for most
+	  This driver has an optional plugin (called PWCX), which is 
+	  distributed as a binary module only. It contains code that allow you 
+	  to use higher resolutions and framerates but may not be distributed 
+	  as source. But even without this plugin you can these cams for most
 	  applications.
 
 	  See <file:Documentation/usb/philips.txt> for more information and
diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
--- a/drivers/usb/media/ov511.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/usb/media/ov511.c	Wed Nov 27 14:36:28 2002
@@ -60,7 +60,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.62 for Linux 2.5"
+#define DRIVER_VERSION "v1.63 for Linux 2.5"
 #define EMAIL "mark@alpha.dyndns.org"
 #define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org> & Bret Wallach \
 	& Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \
@@ -121,6 +121,7 @@
 static int unit_video[OV511_MAX_UNIT_VIDEO];
 static int remove_zeros;
 static int mirror;
+static int ov518_color;
 
 MODULE_PARM(autobright, "i");
 MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
@@ -193,6 +194,8 @@
   "Remove zero-padding from uncompressed incoming data");
 MODULE_PARM(mirror, "i");
 MODULE_PARM_DESC(mirror, "Reverse image horizontally");
+MODULE_PARM(ov518_color, "i");
+MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)");
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -259,6 +262,7 @@
 	{ 100, "Lifeview RoboCam" },
 	{ 102, "AverMedia InterCam Elite" },
 	{ 112, "MediaForte MV300" },	/* or OV7110 evaluation kit */
+	{ 134, "Ezonics EZCam II" },
 	{ 192, "Webeye 2000B" },
 	{ 253, "Alpha Vision Tech. AlphaCam SE" },
 	{  -1, NULL }
@@ -293,6 +297,7 @@
 	{ -1, NULL }
 };
 
+#if defined(CONFIG_VIDEO_PROC_FS)
 static struct symbolic_list senlist[] = {
 	{ SEN_OV76BE,	"OV76BE" },
 	{ SEN_OV7610,	"OV7610" },
@@ -308,6 +313,7 @@
 	{ SEN_SAA7111A,	"SAA7111A" },
 	{ -1, NULL }
 };
+#endif
 
 /* URB error codes: */
 static struct symbolic_list urb_errlist[] = {
@@ -321,20 +327,6 @@
 };
 
 /**********************************************************************
- * Prototypes
- **********************************************************************/
-
-static void ov51x_clear_snapshot(struct usb_ov511 *);
-static inline int sensor_get_picture(struct usb_ov511 *,
-				     struct video_picture *);
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
-static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
-			       unsigned long);
-static int ov51x_check_snapshot(struct usb_ov511 *);
-#endif
-
-/**********************************************************************
  * Memory management
  **********************************************************************/
 
@@ -396,11 +388,19 @@
  * Based on the CPiA driver version 0.7.4 -claudio
  **********************************************************************/
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+#if defined(CONFIG_VIDEO_PROC_FS)
 
 static struct proc_dir_entry *ov511_proc_entry = NULL;
 extern struct proc_dir_entry *video_proc_entry;
 
+/* Prototypes */
+static void ov51x_clear_snapshot(struct usb_ov511 *);
+static int sensor_get_picture(struct usb_ov511 *, struct video_picture *);
+static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
+static int ov51x_check_snapshot(struct usb_ov511 *);
+static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
+			       unsigned long);
+
 static struct file_operations ov511_control_fops = {
 	.ioctl =	ov51x_control_ioctl,
 };
@@ -460,6 +460,8 @@
 		       symbolic(senlist, ov->sensor));
 	out += sprintf(out, "packet_size     : %d\n", ov->packet_size);
 	out += sprintf(out, "framebuffer     : 0x%p\n", ov->fbuf);
+	out += sprintf(out, "packet_numbering: %d\n", ov->packet_numbering);
+	out += sprintf(out, "topology        : %s\n", ov->usb_path);
 
 	len = out - page;
 	len -= off;
@@ -637,7 +639,12 @@
 
 	remove_proc_entry("ov511", video_proc_entry);
 }
-#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
+#else
+static inline void create_proc_ov511_cam(struct usb_ov511 *ov) { }
+static inline void destroy_proc_ov511_cam(struct usb_ov511 *ov) { }
+static inline void proc_ov511_create(void) { }
+static inline void proc_ov511_destroy(void) { }
+#endif /* #ifdef CONFIG_VIDEO_PROC_FS */
 
 /**********************************************************************
  *
@@ -1116,7 +1123,7 @@
  * when calling this. This should not be called from outside the i2c I/O
  * functions.
  */
-static inline int
+static int
 i2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave)
 {
 	int rc;
@@ -1357,7 +1364,7 @@
 	}
 }
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+#if defined(CONFIG_VIDEO_PROC_FS)
 /* Checks the status of the snapshot button. Returns 1 if it was pressed since
  * it was last cleared, and zero in all other cases (including errors) */
 static int
@@ -1970,7 +1977,7 @@
 
 /* -------------------------------------------------------------------------- */
 
-static inline int
+static int
 sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p)
 {
 	int rc;
@@ -2001,7 +2008,7 @@
 	return 0;
 }
 
-static inline int
+static int
 sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
 {
 	int rc;
@@ -2032,7 +2039,7 @@
 	return 0;
 }
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+#if defined(CONFIG_VIDEO_PROC_FS)
 // FIXME: Exposure range is only 0x00-0x7f in interlace mode
 /* Sets current exposure for sensor. This only has an effect if auto-exposure
  * is off */
@@ -2117,7 +2124,7 @@
 #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
 
 /* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */
-static inline void
+static void
 ov51x_led_control(struct usb_ov511 *ov, int enable)
 {
 	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
@@ -2198,7 +2205,7 @@
  * Unsupported: KS0127, KS0127B, SAA7111A
  * Returns: 0 for success
  */
-static inline int
+static int
 sensor_set_banding_filter(struct usb_ov511 *ov, int enable)
 {
 	int rc;
@@ -2226,7 +2233,7 @@
  * Unsupported: KS0127, KS0127B, SAA7111A
  * Returns: 0 for success
  */
-static inline int
+static int
 sensor_set_auto_brightness(struct usb_ov511 *ov, int enable)
 {
 	int rc;
@@ -2254,7 +2261,7 @@
  * Unsupported: KS0127, KS0127B, SAA7111A
  * Returns: 0 for success
  */
-static inline int
+static int
 sensor_set_auto_exposure(struct usb_ov511 *ov, int enable)
 {
 	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
@@ -2333,7 +2340,7 @@
 	return 0;
 }
 
-static inline int
+static int
 sensor_set_mirror(struct usb_ov511 *ov, int enable)
 {
 	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
@@ -2434,7 +2441,7 @@
 		i2c_w(ov, 0x14, qvga?0x24:0x04);
 		break;
 	case SEN_OV6630:
-		i2c_w(ov, 0x14, qvga?0xa4:0x84);
+		i2c_w(ov, 0x14, qvga?0xa0:0x80);
 		break;
 	default:
 		err("Invalid sensor");
@@ -2448,13 +2455,33 @@
 			/* these aren't valid on the OV6620/OV7620/6630? */
 			i2c_w_mask(ov, 0x0e, 0x40, 0x40);
 		}
-		i2c_w_mask(ov, 0x13, 0x20, 0x20);
+
+		if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518
+		    && ov518_color) {
+			i2c_w_mask(ov, 0x12, 0x00, 0x10);
+			i2c_w_mask(ov, 0x13, 0x00, 0x20);
+		} else {
+			i2c_w_mask(ov, 0x13, 0x20, 0x20);
+		}
 	} else {
 		if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV76BE) {
 			/* not valid on the OV6620/OV7620/6630? */
 			i2c_w_mask(ov, 0x0e, 0x00, 0x40);
 		}
-		i2c_w_mask(ov, 0x13, 0x00, 0x20);
+
+		/* The OV518 needs special treatment. Although both the OV518
+		 * and the OV6630 support a 16-bit video bus, only the 8 bit Y
+		 * bus is actually used. The UV bus is tied to ground.
+		 * Therefore, the OV6630 needs to be in 8-bit multiplexed
+		 * output mode */
+
+		if (ov->sensor == SEN_OV6630 && ov->bridge == BRG_OV518
+		    && ov518_color) {
+			i2c_w_mask(ov, 0x12, 0x10, 0x10);
+			i2c_w_mask(ov, 0x13, 0x20, 0x20);
+		} else {
+			i2c_w_mask(ov, 0x13, 0x00, 0x20);
+		}
 	}
 
 	/******** Clock programming ********/
@@ -2781,8 +2808,29 @@
 	reg_w(ov, 0x3d, 0);
 	reg_w(ov, 0x3e, 0);
 
-	reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80);
-	reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80);
+	if (ov->bridge == BRG_OV518 && ov518_color) {
+		/* OV518 needs U and V swapped */
+		i2c_w_mask(ov, 0x15, 0x00, 0x01);
+
+	 	if (mode == VIDEO_PALETTE_GREY) {
+			/* Set 16-bit input format (UV data are ignored) */
+			reg_w_mask(ov, 0x20, 0x00, 0x08);
+
+			/* Set 8-bit (4:0:0) output format */
+			reg_w_mask(ov, 0x28, 0x00, 0xf0);
+			reg_w_mask(ov, 0x38, 0x00, 0xf0);
+		} else {
+			/* Set 8-bit (YVYU) input format */
+			reg_w_mask(ov, 0x20, 0x08, 0x08);
+
+			/* Set 12-bit (4:2:0) output format */
+			reg_w_mask(ov, 0x28, 0x80, 0xf0);
+			reg_w_mask(ov, 0x38, 0x80, 0xf0);
+		}
+	} else {
+		reg_w(ov, 0x28, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80);
+		reg_w(ov, 0x38, (mode == VIDEO_PALETTE_GREY) ? 0x00:0x80);
+	}
 
 	hsegs = width / 16;
 	vsegs = height / 4;
@@ -3074,7 +3122,7 @@
 }
 
 /*
- * For RAW BW (YUV400) images, data shows up in 256 byte segments.
+ * For RAW BW (YUV 4:0:0) images, data show up in 256 byte segments.
  * The segments represent 4 squares of 8x8 pixels as follows:
  *
  *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
@@ -3105,7 +3153,7 @@
 }
 
 /*
- * For YUV4:2:0 images, the data shows up in 384 byte segments.
+ * For YUV 4:2:0 images, the data show up in 384 byte segments.
  * The first 64 bytes of each segment are U, the next 64 are V.  The U and
  * V are arranged as follows:
  *
@@ -3124,8 +3172,8 @@
  *           ...              ...                    ...
  *     56 57 ... 63   120 121 ... 127   ...  248 249 ... 255
  *
- * Note that the U and V data in one segment represents a 16 x 16 pixel
- * area, but the Y data represents a 32 x 8 pixel area. If the width is not an
+ * Note that the U and V data in one segment represent a 16 x 16 pixel
+ * area, but the Y data represent a 32 x 8 pixel area. If the width is not an
  * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the
  * next horizontal stripe.
  *
@@ -3133,7 +3181,7 @@
  * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
  * this puts the data on the standard output and can be analyzed with the
  * parseppm.c utility I wrote.  That's a much faster way for figuring out how
- * this data is scrambled.
+ * these data are scrambled.
  */
 
 /* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0.
@@ -4285,7 +4333,6 @@
 	}
 
 	file->private_data = NULL;
-
 	return 0;
 }
 
@@ -4752,7 +4799,7 @@
 	return rc;
 }
 
-static inline int
+static int
 ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
 {
 	struct video_device *vdev = file->private_data;
@@ -4882,7 +4929,7 @@
 	PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
 		count, frame->bytes_read);
 
-	/* If all data has been read... */
+	/* If all data have been read... */
 	if (frame->bytes_read
 	    >= get_frame_length(frame)) {
 		frame->bytes_read = 0;
@@ -4966,7 +5013,7 @@
 	.fops =		&ov511_fops,
 };
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+#if defined(CONFIG_VIDEO_PROC_FS)
 static int
 ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 		    unsigned long ularg)
@@ -5453,14 +5500,12 @@
 		{ OV511_I2C_BUS, 0x4f, 0x04 },
 // Do 50-53 have any effect?
 // Toggle 0x12[2] off and on here?
-		{ OV511_DONE_BUS, 0x0, 0x00 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },	/* END MARKER */
 	};
 
-	/* This chip is undocumented so many of these are guesses. OK=verified,
-	 * A=Added since 6620, U=unknown function (not a 6620 reg) */
 	static struct ov511_regvals aRegvalsNorm6x30[] = {
 	/*OK*/	{ OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
-	/*00?*/	{ OV511_I2C_BUS, 0x11, 0x01 },
+		{ OV511_I2C_BUS, 0x11, 0x00 },
 	/*OK*/	{ OV511_I2C_BUS, 0x03, 0x60 },
 	/*0A?*/	{ OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
 		{ OV511_I2C_BUS, 0x07, 0xa8 },
@@ -5468,16 +5513,8 @@
 	/*OK*/	{ OV511_I2C_BUS, 0x0c, 0x24 },
 	/*OK*/	{ OV511_I2C_BUS, 0x0d, 0x24 },
 	/*A*/	{ OV511_I2C_BUS, 0x0e, 0x20 },
-
-//	/*24?*/	{ OV511_I2C_BUS, 0x12, 0x28 }, /* Enable AGC */
-//		{ OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
-
-//	/*A*/	{ OV511_I2C_BUS, 0x13, 0x21 },
-//	/*A*/	{ OV511_I2C_BUS, 0x13, 0x25 }, /* Tristate Y and UV busses */
-
 //	/*04?*/	{ OV511_I2C_BUS, 0x14, 0x80 },
-		/* 0x16: 0x06 helps frame stability with moving objects */
-	/*03?*/	{ OV511_I2C_BUS, 0x16, 0x06 },
+		{ OV511_I2C_BUS, 0x16, 0x03 },
 //	/*OK*/	{ OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
 		// 21 & 22? The suggested values look wrong. Go with default
 	/*A*/	{ OV511_I2C_BUS, 0x23, 0xc0 },
@@ -5490,49 +5527,34 @@
 
 	/*OK*/	{ OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
 //	/*OK*/	{ OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
-//	/*U*/	{ OV511_I2C_BUS, 0x2c, 0xa0 },
 		{ OV511_I2C_BUS, 0x2d, 0x99 },
 //	/*A*/	{ OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620
 //	/*d2?*/	{ OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */
-//	/*U*/	{ OV511_I2C_BUS, 0x36, 0x8f }, // May not be necessary
-//	/*U*/	{ OV511_I2C_BUS, 0x37, 0x80 }, // May not be necessary
 //	/*8b?*/	{ OV511_I2C_BUS, 0x38, 0x83 },
 //	/*40?*/	{ OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7
 //		{ OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
 //		{ OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
 //		{ OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
-	/*OK*/	{ OV511_I2C_BUS, 0x3d, 0x80 },
+		{ OV511_I2C_BUS, 0x3d, 0x80 },
 //	/*A*/	{ OV511_I2C_BUS, 0x3f, 0x0e },
-//	/*U*/	{ OV511_I2C_BUS, 0x40, 0x00 },
-//	/*U*/	{ OV511_I2C_BUS, 0x41, 0x00 },
-//	/*U*/	{ OV511_I2C_BUS, 0x42, 0x80 },
-//	/*U*/	{ OV511_I2C_BUS, 0x43, 0x3f },
-//	/*U*/	{ OV511_I2C_BUS, 0x44, 0x80 },
-//	/*U*/	{ OV511_I2C_BUS, 0x45, 0x20 },
-//	/*U*/	{ OV511_I2C_BUS, 0x46, 0x20 },
-//	/*U*/	{ OV511_I2C_BUS, 0x47, 0x80 },
-//	/*U*/	{ OV511_I2C_BUS, 0x48, 0x7f },
-//	/*U*/	{ OV511_I2C_BUS, 0x49, 0x00 },
 
 		/* These next two registers (0x4a, 0x4b) are undocumented. They
 		 * control the color balance */
 //	/*OK?*/	{ OV511_I2C_BUS, 0x4a, 0x80 }, // Check these
 //	/*OK?*/	{ OV511_I2C_BUS, 0x4b, 0x80 },
-//	/*U*/	{ OV511_I2C_BUS, 0x4c, 0xd0 },
-	/*d2?*/	{ OV511_I2C_BUS, 0x4d, 0x10 }, /* This reduces noise a bit */
+		{ OV511_I2C_BUS, 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
 	/*c1?*/	{ OV511_I2C_BUS, 0x4e, 0x40 },
-	/*04?*/	{ OV511_I2C_BUS, 0x4f, 0x07 },
-//	/*U*/	{ OV511_I2C_BUS, 0x50, 0xff },
-	/*U*/	{ OV511_I2C_BUS, 0x54, 0x23 },
-//	/*U*/	{ OV511_I2C_BUS, 0x55, 0xff },
-//	/*U*/	{ OV511_I2C_BUS, 0x56, 0x12 },
-	/*U*/	{ OV511_I2C_BUS, 0x57, 0x81 },
-//	/*U*/	{ OV511_I2C_BUS, 0x58, 0x75 },
-	/*U*/	{ OV511_I2C_BUS, 0x59, 0x01 },
-	/*U*/	{ OV511_I2C_BUS, 0x5a, 0x2c },
-	/*U*/	{ OV511_I2C_BUS, 0x5b, 0x0f },
-//	/*U*/	{ OV511_I2C_BUS, 0x5c, 0x10 },
-		{ OV511_DONE_BUS, 0x0, 0x00 },
+
+		/* UV average mode, color killer: strongest */
+		{ OV511_I2C_BUS, 0x4f, 0x07 },
+
+		{ OV511_I2C_BUS, 0x54, 0x23 }, /* Max AGC gain: 18dB */
+		{ OV511_I2C_BUS, 0x57, 0x81 }, /* (default) */
+		{ OV511_I2C_BUS, 0x59, 0x01 }, /* AGC dark current comp: +1 */
+		{ OV511_I2C_BUS, 0x5a, 0x2c }, /* (undocumented) */
+		{ OV511_I2C_BUS, 0x5b, 0x0f }, /* AWB chrominance levels */
+//		{ OV511_I2C_BUS, 0x5c, 0x10 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },	/* END MARKER */
 	};
 
 	PDEBUG(4, "starting sensor configuration");
@@ -5553,16 +5575,19 @@
 		return -1;
 	}
 
-	if ((rc & 3) == 0)
+	if ((rc & 3) == 0) {
 		ov->sensor = SEN_OV6630;
-	else if ((rc & 3) == 1)
+		info("Sensor is an OV6630");
+	} else if ((rc & 3) == 1) {
 		ov->sensor = SEN_OV6620;
-	else if ((rc & 3) == 2)
+		info("Sensor is an OV6620");
+	} else if ((rc & 3) == 2) {
 		ov->sensor = SEN_OV6630;
-	else if ((rc & 3) == 3)
+		info("Sensor is an OV6630AE");
+	} else if ((rc & 3) == 3) {
 		ov->sensor = SEN_OV6630;
-
-	info("Sensor is an %s", symbolic(senlist, ov->sensor));
+		info("Sensor is an OV6630AF");
+	}
 
 	/* Set sensor-specific vars */
 	ov->maxwidth = 352;
@@ -5922,7 +5947,7 @@
 		{ OV511_REG_BUS, 0x5d,			0x03 },
 		{ OV511_REG_BUS, 0x24,			0x9f },
 		{ OV511_REG_BUS, 0x25,			0x90 },
-		{ OV511_REG_BUS, 0x20,			0x00 }, /* Was 0x08 */
+		{ OV511_REG_BUS, 0x20,			0x00 },
 		{ OV511_REG_BUS, 0x51,			0x04 },
 		{ OV511_REG_BUS, 0x71,			0x19 },
 		{ OV511_DONE_BUS, 0x0, 0x00 },
@@ -5935,7 +5960,7 @@
 		{ OV511_REG_BUS, 0x5d,			0x03 },
 		{ OV511_REG_BUS, 0x24,			0x9f },
 		{ OV511_REG_BUS, 0x25,			0x90 },
-		{ OV511_REG_BUS, 0x20,			0x60 }, /* Was 0x08 */
+		{ OV511_REG_BUS, 0x20,			0x60 },
 		{ OV511_REG_BUS, 0x51,			0x02 },
 		{ OV511_REG_BUS, 0x71,			0x19 },
 		{ OV511_REG_BUS, 0x40,			0xff },
@@ -6151,6 +6176,11 @@
 
 	ov->buf_state = BUF_NOT_ALLOCATED;
 
+	if (usb_make_path(dev, ov->usb_path, OV511_USB_PATH_LEN) < 0) {
+		err("usb_make_path error");
+		goto error_dealloc;
+	}
+
 	/* Allocate control transfer buffer. */
 	/* Must be kmalloc()'ed, for DMA compatibility */
 	ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL);
@@ -6212,20 +6242,16 @@
 		goto error;
 	}
 
-	info("Device registered on minor %d", ov->vdev.minor);
+	info("Device at %s registered to minor %d", ov->usb_path,
+	     ov->vdev.minor);
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
 	create_proc_ov511_cam(ov);
-#endif
 
 	dev_set_drvdata (&intf->dev, ov);
-     	return 0;
+	return 0;
 
 error:
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	/* Safe to call even if entry doesn't exist */
 	destroy_proc_ov511_cam(ov);
-#endif
 
 	if (ov->cbuf) {
 		down(&ov->cbuf_lock);
@@ -6274,12 +6300,9 @@
 		wake_up_interruptible(&ov->wq);
 
 	ov->streaming = 0;
-
 	ov51x_unlink_isoc(ov);
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
         destroy_proc_ov511_cam(ov);
-#endif
 
 	ov->dev = NULL;
 
@@ -6396,9 +6419,7 @@
 static int __init
 usb_ov511_init(void)
 {
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
         proc_ov511_create();
-#endif
 
 	if (usb_register(&ov511_driver) < 0)
 		return -1;
@@ -6414,9 +6435,7 @@
 	usb_deregister(&ov511_driver);
 	info("driver deregistered");
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
         proc_ov511_destroy();
-#endif
 }
 
 module_init(usb_ov511_init);
diff -Nru a/drivers/usb/media/ov511.h b/drivers/usb/media/ov511.h
--- a/drivers/usb/media/ov511.h	Wed Nov 27 14:36:29 2002
+++ b/drivers/usb/media/ov511.h	Wed Nov 27 14:36:29 2002
@@ -253,6 +253,9 @@
 /* Control transfers use up to 4 bytes */
 #define OV511_CBUF_SIZE		4
 
+/* Size of usb_make_path() buffer */
+#define OV511_USB_PATH_LEN	64
+
 /* Bridge types */
 enum {
 	BRG_UNKNOWN,
@@ -450,6 +453,7 @@
 	int customid;
 	char *desc;
 	unsigned char iface;
+	char usb_path[OV511_USB_PATH_LEN];
 
 	/* Determined by sensor type */
 	int maxwidth;
diff -Nru a/drivers/usb/media/pwc-ctrl.c b/drivers/usb/media/pwc-ctrl.c
--- a/drivers/usb/media/pwc-ctrl.c	Wed Nov 27 14:36:32 2002
+++ b/drivers/usb/media/pwc-ctrl.c	Wed Nov 27 14:36:32 2002
@@ -256,8 +256,10 @@
 
 	memcpy(buf, pEntry->mode, 3);	
 	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
-	if (ret < 0)
+	if (ret < 0) {
+		Debug("Failed to send video command... %d\n", ret);
 		return ret;
+	}
 	if (pEntry->compressed && pdev->decompressor != NULL)
 		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
 		
@@ -1103,12 +1105,7 @@
 	buf[0] = on_value;
 	buf[1] = off_value;
 
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_STATUS_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		LED_FORMATTER,
-		pdev->vcinterface,
-		&buf, 2, HZ / 2);
+	return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
 }
 
 int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
@@ -1122,13 +1119,7 @@
 		return 0;
 	}
 
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-   	        GET_STATUS_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		LED_FORMATTER,
-		pdev->vcinterface,
-		&buf, 2, HZ / 2);
-
+	ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2);
 	if (ret < 0)
 		return ret;
 	*on_value = buf[0] * 100;
@@ -1279,7 +1270,6 @@
 	ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-//Debug("pwc_get_dynamic_noise = %d\n", buf);
 	return buf;
 }
 
@@ -1363,12 +1353,10 @@
 
 	case VIDIOCPWCPROBE:
 	{
-		struct pwc_probe probe;
+		struct pwc_probe *probe = arg;
 		
-		strcpy(probe.name, pdev->vdev->name);
-		probe.type = pdev->type;
-		if (copy_to_user(arg, &probe, sizeof(probe)))
-			ret = -EFAULT;
+		strcpy(probe->name, pdev->vdev->name);
+		probe->type = pdev->type;
 		break;
 	}
 
diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c
--- a/drivers/usb/media/pwc-if.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/usb/media/pwc-if.c	Wed Nov 27 14:36:31 2002
@@ -1,6 +1,6 @@
 /* Linux driver for Philips webcam 
    USB and Video4Linux interface part.
-   (C) 1999-2001 Nemosoft Unv.
+   (C) 1999-2002 Nemosoft Unv.
 
    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
@@ -42,32 +42,31 @@
    - Alistar Moire: QuickCam 3000 Pro device/product ID
    - Tony Hoyle: Creative Labs Webcam 5 device/product ID
    - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
-   - Jk Fang: SOTEC device/product ID
+   - Jk Fang: SOTEC Afina Eye ID
+   - Xavier Roche: QuickCam Pro 4000 ID
+   - Jens Knudsen: QuickCam Zoom ID
+   - J. Debert: QuickCam for Notebooks ID
 */
 
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/wrapper.h>
-#include <linux/mm.h>
 #include <asm/io.h>
 
 #include "pwc.h"
 #include "pwc-ioctl.h"
 #include "pwc-uncompress.h"
 
-#if !defined(MAP_NR)
-#define MAP_NR(a) virt_to_page(a)
-#endif
-
 /* Function prototypes and driver templates */
 
 /* hotplug device table support */
 static struct usb_device_id pwc_device_table [] = {
-	{ USB_DEVICE(0x0471, 0x0302) },
+	{ USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
 	{ USB_DEVICE(0x0471, 0x0303) },
 	{ USB_DEVICE(0x0471, 0x0304) },
 	{ USB_DEVICE(0x0471, 0x0307) },
@@ -76,12 +75,17 @@
 	{ USB_DEVICE(0x0471, 0x0310) },
 	{ USB_DEVICE(0x0471, 0x0311) },
 	{ USB_DEVICE(0x0471, 0x0312) },
-	{ USB_DEVICE(0x069A, 0x0001) },
-	{ USB_DEVICE(0x046D, 0x08b0) },
-	{ USB_DEVICE(0x055D, 0x9000) },
+	{ USB_DEVICE(0x069A, 0x0001) }, /* Askey */
+	{ USB_DEVICE(0x046D, 0x08b0) }, /* Logitech QuickCam Pro 3000 */
+	{ USB_DEVICE(0x046D, 0x08b1) }, /* Logitech QuickCam for Notebooks */
+	{ USB_DEVICE(0x046D, 0x08b2) }, /* Logitech QuickCam Pro 4000 */
+	{ USB_DEVICE(0x046D, 0x08b3) }, /* Logitech QuickCam Zoom */
+	{ USB_DEVICE(0x055D, 0x9000) }, /* Samsung */
 	{ USB_DEVICE(0x055D, 0x9001) },
-	{ USB_DEVICE(0x041E, 0x400C) },
-	{ USB_DEVICE(0x04CC, 0x8116) },
+	{ USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
+	{ USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
+	{ USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
+	{ USB_DEVICE(0x0d81, 0x1900) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, pwc_device_table);
@@ -106,7 +110,7 @@
 static int default_mbufs = 2;	/* Default number of mmap() buffers */
        int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
 static int power_save = 0;
-static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
+static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
        int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
 static struct {
 	int type;
@@ -167,7 +171,7 @@
    succeeded. The pwc_device struct links back to both structures.
 
    When a device is unplugged while in use it will be removed from the 
-   list of known USB devices; I also de-register as a V4L device, but 
+   list of known USB devices; I also de-register it as a V4L device, but 
    unfortunately I can't free the memory since the struct is still in use
    by the file descriptor. This free-ing is then deferend until the first
    opportunity. Crude, but it works.
@@ -240,7 +244,7 @@
 	int i;
 	void *kbuf;
 
-	Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev);
+	Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
 
 	if (pdev == NULL)
 		return -ENXIO;
@@ -315,7 +319,9 @@
 	for (; i < MAX_IMAGES; i++)
 		pdev->image_ptr[i] = NULL;
 
-	Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n");
+	kbuf = NULL;
+	  
+	Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
 	return 0;
 }
 
@@ -369,6 +375,7 @@
 		rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
 	}
 	pdev->image_data = NULL;
+	
 	Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
 }
 
@@ -570,12 +577,10 @@
 	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
 }
 
-/* 2001-10-14: The YUV420 is still there, but you can only set it from within 
-   a program (YUV420P being the default) */
+/* 2002-10-11: YUV420P is the only palette remaining. */
 static int pwc_set_palette(struct pwc_device *pdev, int pal)
 {
-	if (   pal == VIDEO_PALETTE_YUV420
-            || pal == VIDEO_PALETTE_YUV420P
+	if (   pal == VIDEO_PALETTE_YUV420P
 #if PWC_DEBUG
             || pal == VIDEO_PALETTE_RAW
 #endif
@@ -613,7 +618,7 @@
 	}
 #endif
 	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
-		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n");
+		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
 		return;
 	}
 	if (urb->status != -EINPROGRESS && urb->status != 0) {
@@ -686,9 +691,22 @@
 #if PWC_DEBUG
 							Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
 #endif
-							pdev->drop_frames = 2;
+							pdev->drop_frames += 2;
 							pdev->vframes_error++;
 						}
+						if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+							if (ptr[0] & 0x01)
+								Info("Snapshot button pressed.\n");
+							else
+								Info("Snapshot button released.\n");
+						}
+						if ((ptr[0] ^ pdev->vmirror) & 0x02) {
+							if (ptr[0] & 0x02)
+								Info("Image is mirrored.\n");
+							else
+								Info("Image is normal.\n");
+						}
+						pdev->vmirror = ptr[0] & 0x03;
 						/* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
 						   after a short frame; this condition is filtered out specifically. A 4 byte
 						   frame doesn't make sense anyway.
@@ -705,7 +723,7 @@
 					/* In case we were instructed to drop the frame, do so silently.
 					   The buffer pointers are not updated either (but the counters are reset below).
 					 */
-					if (pdev->drop_frames)
+					if (pdev->drop_frames > 0)
 						pdev->drop_frames--;
 					else {
 						/* Check for underflow first */
@@ -741,17 +759,23 @@
 			} /* .. flen < last_packet_size */
 			pdev->vlast_packet_size = flen;
 		} /* ..status == 0 */
-#ifdef PWC_DEBUG
+#if PWC_DEBUG
 		/* This is normally not interesting to the user, unless you are really debugging something */
-		else 
-			Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+		else {
+			static int iso_error = 0;
+			iso_error++;
+			if (iso_error < 20)
+				Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+		}
 #endif			
 	}
 	if (awake)
 		wake_up_interruptible(&pdev->frameq);
 
 	urb->dev = pdev->udev;
-	usb_submit_urb(urb, GFP_ATOMIC);
+	i = usb_submit_urb(urb, GFP_ATOMIC);
+	if (i != 0)
+		Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
 }
 
 
@@ -762,7 +786,6 @@
 	int i, j, ret;
 
 	struct usb_host_interface *idesc;
-	int cur_alt;
 
 	if (pdev == NULL)
 		return -EFAULT;
@@ -770,12 +793,11 @@
 		return 0;
 	pdev->vsync = 0;
 	udev = pdev->udev;
-	
+
 	/* Get the current alternate interface, adjust packet size */
 	if (!udev->actconfig)
 		return -EFAULT;
-	cur_alt = udev->actconfig->interface[0].act_altsetting;
-	idesc = &udev->actconfig->interface[0].altsetting[cur_alt];
+	idesc = &udev->actconfig->interface[0].altsetting[pdev->valternate];
 	if (!idesc)
 		return -EFAULT;
 
@@ -792,7 +814,13 @@
 		return -ENFILE; /* Odd error, that should be noticable */
 	}
 
+	/* Set alternate interface */
 	ret = 0;
+	Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate);
+	ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+	if (ret < 0)
+		return ret;
+
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
 		if (urb == NULL) {
@@ -801,6 +829,7 @@
 			break;
 		}
 		pdev->sbuf[i].urb = urb;
+		Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
 	}
 	if (ret) {
 		/* De-allocate in reverse order */
@@ -812,8 +841,7 @@
 		}
 		return ret;
 	}
-	
-	
+
 	/* init URB structure */	
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		urb = pdev->sbuf[i].urb;
@@ -829,7 +857,7 @@
 		urb->start_frame = 0;
 		urb->number_of_packets = ISO_FRAMES_PER_DESC;
 		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
-			urb->iso_frame_desc[j].offset = j * pdev->vmax_packet_size;
+			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
 			urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
 		}
 	}
@@ -840,11 +868,12 @@
 		if (ret)
 			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
 		else
-			Trace(TRACE_OPEN, "pwc_isoc_init(): URB submitted.\n");
+			Trace(TRACE_OPEN, "URB 0x%p submitted.\n", pdev->sbuf[i].urb);
 	}
 
-	/* data should stream in now */
+	/* All is done... */
 	pdev->iso_init = 1;
+	Trace(TRACE_OPEN, "<< pwc_isoc_init()\n");
 	return 0;
 }
 
@@ -852,21 +881,34 @@
 {
 	int i;
 	
+	Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n");
 	if (pdev == NULL)
 		return;
-	if (!pdev->iso_init)
-		return;
+
+	/* Unlinking ISOC buffers one by one */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		struct urb *urb;
+
+		urb = pdev->sbuf[i].urb;
+		if (urb != 0) {
+			if (pdev->iso_init) {
+				Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
+				usb_unlink_urb(urb);
+			}
+			Trace(TRACE_MEMORY, "Freeing URB\n");
+			usb_free_urb(urb);
+			pdev->sbuf[i].urb = NULL;
+		}
+	}
+
 	/* Stop camera, but only if we are sure the camera is still there */
-	if (!pdev->unplugged)
+	if (!pdev->unplugged) {
+		Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
 		usb_set_interface(pdev->udev, 0, 0);
-	/* Unlinking ISOC buffers one by one */
-	for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
-		//pdev->sbuf[i].urb->next = NULL;
-		usb_unlink_urb(pdev->sbuf[i].urb);
-		usb_free_urb(pdev->sbuf[i].urb);
-		pdev->sbuf[i].urb = NULL;
 	}
+
 	pdev->iso_init = 0;
+	Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n");
 }
 
 int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
@@ -881,11 +923,10 @@
 	ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
 	if (ret) /* That failed... restore old mode (we know that worked) */
 		ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-	else /* Set (new) alternate interface */
-		ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
 	if (!ret)
-		ret = pwc_isoc_init(pdev);
-	pdev->drop_frames = 1; /* try to avoid garbage during switch */
+		if (pwc_isoc_init(pdev) < 0)
+			Info("Failed to restart ISOC transfer in pwc_try_video_mode.\n");
+	pdev->drop_frames++; /* try to avoid garbage during switch */
 	return ret;
 }
 
@@ -921,7 +962,7 @@
 	struct video_device *vdev = video_devdata(file);
 	struct pwc_device *pdev;
 
-	Trace(TRACE_OPEN, "video_open called(0x%p).\n", vdev);
+	Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
 	
 	pdev = (struct pwc_device *)vdev->priv;
 	if (pdev == NULL)
@@ -932,10 +973,30 @@
 	down(&pdev->modlock);
 	if (!pdev->usb_init) {
 		Trace(TRACE_OPEN, "Doing first time initialization.\n");
-		/* Reset camera */
-		if (usb_set_interface(pdev->udev, 0, 0))
-			Info("Failed to set alternate interface to 0.\n");
 		pdev->usb_init = 1;
+		
+		if (pwc_trace & TRACE_OPEN) {
+			/* Query CMOS sensor type */
+			const char *sensor_type = NULL;
+
+			i = pwc_get_cmos_sensor(pdev);
+			switch(i) {
+			case -1: /* Unknown, show nothing */; break;
+			case 0x00:  sensor_type = "Hyundai CMOS sensor"; break;
+			case 0x20:  sensor_type = "Sony CCD sensor + TDA8787"; break;
+			case 0x2E:  sensor_type = "Sony CCD sensor + Exas 98L59"; break;
+			case 0x2F:  sensor_type = "Sony CCD sensor + ADI 9804"; break;
+			case 0x30:  sensor_type = "Sharp CCD sensor + TDA8787"; break;
+			case 0x3E:  sensor_type = "Sharp CCD sensor + Exas 98L59"; break;
+			case 0x3F:  sensor_type = "Sharp CCD sensor + ADI 9804"; break;
+			case 0x40:  sensor_type = "UPA 1021 sensor"; break;
+			case 0x100: sensor_type = "VGA sensor"; break;
+			case 0x101: sensor_type = "PAL MR sensor"; break;
+			default:   sensor_type = "unknown type of sensor"; break;
+			}
+			if (sensor_type != NULL)
+				Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
+		}
 	}
 
 	/* Turn on camera */
@@ -1000,12 +1061,6 @@
 		return i;
 	}
 	
-	i = usb_set_interface(pdev->udev, 0, pdev->valternate);
-	if (i) {
-		Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
-		up(&pdev->modlock);
-		return -EINVAL;
-	}
 	i = pwc_isoc_init(pdev);
 	if (i) {
 		Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
@@ -1023,7 +1078,7 @@
 	if (pdev->decompressor != NULL)
 		pdev->decompressor->lock();
 	up(&pdev->modlock);
-	Trace(TRACE_OPEN, "video_open() returning 0.\n");
+	Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
 	return 0;
 }
 
@@ -1034,15 +1089,12 @@
 	struct pwc_device *pdev;
 	int i;
 
-	Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev);
+	Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
 
 	pdev = (struct pwc_device *)vdev->priv;
 	if (pdev->vopen == 0)
 		Info("video_close() called on closed device?\n");
 
-	/* Free isoc URBs */
-	pwc_isoc_cleanup(pdev);
-
 	/* Dump statistics, but only if a reasonable amount of frames were
 	   processed (to prevent endless log-entries in case of snap-shot
 	   programs) 
@@ -1050,15 +1102,14 @@
 	if (pdev->vframe_count > 20)
 		Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
 
-	if (!pdev->unplugged) {
-		/* Normal close: stop isochronuous and interrupt endpoint */
-		Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
-		usb_set_interface(pdev->udev, 0, 0);
+	/* Free isoc URBs, stop camera */
+	pwc_isoc_cleanup(pdev);
 
+	if (!pdev->unplugged) {
 		/* Turn LEDs off */
 		if (pwc_set_leds(pdev, 0, 0) < 0)
-			Info("Failed to set LED on/off time..\n");
-		/* Power down camere to save energy */
+			Info("Failed to set LED on/off time.\n");
+		/* Power down camera to save energy */
 		if (power_save) {
 			i = pwc_camera_power(pdev, 0);
 			if (i < 0) 
@@ -1077,6 +1128,7 @@
 	if (pdev->unplugged)
 		wake_up(&pdev->remove_ok);
 	file->private_data = NULL;
+	Trace(TRACE_OPEN, "<< video_close()\n");
 	return 0;
 }
 
@@ -1514,7 +1566,6 @@
 	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
 	pdev = vdev->priv;
 
-	/* FIXME - audit mmap during a read */		
 	pos = (unsigned long)pdev->image_data;
 	while (size > 0) {
 		page = kvirt_to_pa(pos);
@@ -1547,14 +1598,14 @@
 	int vendor_id, product_id, type_id;
 	int i, hint;
 	int video_nr = -1; /* default: use next available device */
-	char serial_number[30];
+	char serial_number[30], *name;
 
 	free_mem_leak();
 	
 	/* Check if we can handle this device */
-	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
-			udev->descriptor.idVendor, udev->descriptor.idProduct,
-			intf->altsetting->desc.bInterfaceNumber);
+	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", 
+		udev->descriptor.idVendor, udev->descriptor.idProduct, 
+		intf->altsetting->desc.bInterfaceNumber);
 
 	/* the interfaces are probed one by one. We are only interested in the
 	   video interface (0) now.
@@ -1570,38 +1621,47 @@
 		switch (product_id) {
 		case 0x0302:
 			Info("Philips PCA645VC USB webcam detected.\n");
+			name = "Philips 645 webcam";
 			type_id = 645;
 			break;
 		case 0x0303:
 			Info("Philips PCA646VC USB webcam detected.\n");
+			name = "Philips 646 webcam";
 			type_id = 646;
 			break;
 		case 0x0304:
 			Info("Askey VC010 type 2 USB webcam detected.\n");
+			name = "Askey VC010 webcam";
 			type_id = 646;
 			break;
 		case 0x0307:
 			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+			name = "Philips 675 webcam";
 			type_id = 675;
 			break;
 		case 0x0308:
 			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+			name = "Philips 680 webcam";
 			type_id = 680;
 			break;
 		case 0x030C:
 			Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+			name = "Philips 690 webcam";
 			type_id = 690;
 			break;
 		case 0x0310:
 			Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n");
+			name = "Philips 730 webcam";
 			type_id = 730;
 			break;
 		case 0x0311:
 			Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n");
+			name = "Philips 740 webcam";
 			type_id = 740;
 			break;
 		case 0x0312:
 			Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+			name = "Philips 750 webcam";
 			type_id = 750;
 			break;
 		default:
@@ -1613,6 +1673,7 @@
 		switch(product_id) {
 		case 0x0001:
 			Info("Askey VC010 type 1 USB webcam detected.\n");
+			name = "Askey VC010 webcam";
 			type_id = 645;
 			break;
 		default:
@@ -1623,9 +1684,25 @@
 	else if (vendor_id == 0x046d) {
 		switch(product_id) {
 		case 0x08b0:
-			Info("Logitech QuickCam 3000 Pro detected.\n");
+			Info("Logitech QuickCam Pro 3000 USB webcam detected.\n");
+			name = "Logitech QuickCam Pro 3000";
 			type_id = 730;
-        		break;
+			break;
+		case 0x08b1:
+			Info("Logitech QuickCam for Noteboos USB webcam detected.\n");
+			name = "Logitech QuickCam Notebook";
+			type_id = 740; /* ?? unknown sensor */
+			break;
+		case 0x08b2:
+			Info("Logitech QuickCam 4000 Pro USB webcam detected.\n");
+			name = "Logitech QuickCam Pro 4000";
+			type_id = 740; /* CCD sensor */
+			break;
+		case 0x08b3:
+			Info("Logitech QuickCam Zoom USB webcam detected.\n");
+			name = "Logitech QuickCam Zoom";
+			type_id = 740; /* ?? unknown sensor */
+			break;
         	default:
 			return -ENODEV;
         		break;
@@ -1639,10 +1716,12 @@
 		switch(product_id) {
 		case 0x9000:
 			Info("Samsung MPC-C10 USB webcam detected.\n");
+			name = "Samsung MPC-C10";
 			type_id = 675;
 			break;
 		case 0x9001:
 			Info("Samsung MPC-C30 USB webcam detected.\n");
+			name = "Samsung MPC-C30";
 			type_id = 675;
 			break;
 		default:
@@ -1654,6 +1733,7 @@
 		switch(product_id) {
 		case 0x400c:
 			Info("Creative Labs Webcam 5 detected.\n");
+			name = "Creative Labs Webcam 5";
 			type_id = 730;
 			break;
 		default:
@@ -1664,7 +1744,8 @@
 	else if (vendor_id == 0x04cc) { 
 		switch(product_id) {
 		case 0x8116:
-			Info("SOTEC CMS-001 USB webcam detected.\n");
+			Info("Sotec Afina Eye USB webcam detected.\n");
+			name = "Sotec Afina Eye";
 			type_id = 730;
 			break;  
 		default:
@@ -1672,7 +1753,25 @@
 			break;
 		}
 	}
-	else return -ENODEV; /* Not Philips, Askey, Logitech, Samsung, Creative or SOTEC, for sure. */
+	else if (vendor_id == 0x0d81) {
+		switch(product_id) {
+		case 0x1900:
+			Info("Visionite VCS-UC300 USB webcam detected.\n");
+			name = "Visionite VCS-UC300";
+			type_id = 740; /* CCD sensor */
+			break;
+		case 0x1910:
+			Info("Visionite VCS-UM100 USB webcam detected.\n");
+			name = "Visionite VCS-UM100";
+			type_id = 730; /* CMOS sensor */
+			break;
+		default:
+			return -ENODEV;
+			break;
+		}
+	}
+	else 
+		return -ENODEV; /* Not any of the know types; but the list keeps growing. */
 
 	memset(serial_number, 0, 30);
 	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
@@ -1706,7 +1805,7 @@
 		return -ENOMEM;
 	}
 	memcpy(vdev, &pwc_template, sizeof(pwc_template));
-	sprintf(vdev->name, "Philips %d webcam", pdev->type);
+	strcpy(vdev->name, name);
 	SET_MODULE_OWNER(vdev);
 	pdev->vdev = vdev;
 	vdev->priv = pdev;
@@ -1714,7 +1813,6 @@
 	pdev->release = udev->descriptor.bcdDevice;
 	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
 
-
 	/* Now search device_hint[] table for a match, so we can hint a node number. */
 	for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
 		if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
@@ -1761,40 +1859,41 @@
 	dev_set_drvdata (&intf->dev, NULL);
 	if (pdev == NULL) {
 		Err("pwc_disconnect() Called without private pointer.\n");
-		goto out_err;
+		goto disconnect_out;
 	}
 	if (pdev->udev == NULL) {
 		Err("pwc_disconnect() already called for %p\n", pdev);
-		goto out_err;
+		goto disconnect_out;
 	}
 	if (pdev->udev != interface_to_usbdev(intf)) {
 		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
-		goto out_err;
+		goto disconnect_out;
 	}
 #ifdef PWC_MAGIC	
 	if (pdev->magic != PWC_MAGIC) {
 		Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
-		goto out_err;
+		goto disconnect_out;
 	}
-#endif
-
+#endif	
+	
 	pdev->unplugged = 1;
 	if (pdev->vdev != NULL) {
-		video_unregister_device(pdev->vdev);
+		Trace(TRACE_PROBE, "Unregistering video device.\n");
+		video_unregister_device(pdev->vdev); 
 		if (pdev->vopen) {
 			Info("Disconnected while device/video is open!\n");
-
+			
 			/* Wake up any processes that might be waiting for
 			   a frame, let them return an error condition
 			 */
 			wake_up(&pdev->frameq);
-
+			
 			/* Wait until we get a 'go' from _close(). This used
 			   to have a gigantic race condition, since we kfree()
-			   stuff here, but we have to wait until close()
-			   is finished.
+			   stuff here, but we have to wait until close() 
+			   is finished. 
 			 */
-
+			   
 			Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
 			add_wait_queue(&pdev->remove_ok, &wait);
 			set_current_state(TASK_UNINTERRUPTIBLE);
@@ -1808,26 +1907,25 @@
 		}
 		else {
 			/* Normal disconnect; remove from available devices */
-			Trace(TRACE_PROBE, "Unregistering video device normally.\n");
 			kfree(pdev->vdev);
 			pdev->vdev = NULL;
 		}
 	}
 
+disconnect_out:
 	/* search device_hint[] table if we occupy a slot, by any chance */
 	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
 		if (device_hint[hint].pdev == pdev)
 			device_hint[hint].pdev = NULL;
 
 	pdev->udev = NULL;
-out_err:
 	unlock_kernel();
 	kfree(pdev);
 }
 
 
 /* *grunt* We have to do atoi ourselves :-( */
-static int pwc_atoi(char *s)
+static int pwc_atoi(const char *s)
 {
 	int k = 0;
 	
@@ -1872,7 +1970,7 @@
 MODULE_PARM(dev_hint, "0-10s");
 MODULE_PARM_DESC(dev_hint, "Device node hints");
 
-MODULE_DESCRIPTION("Philips USB webcam driver");
+MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
 MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
 MODULE_LICENSE("GPL");
 
@@ -1882,11 +1980,12 @@
 	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
 
 	Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
-	Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30, the Creative WebCam 5 and the SOTEC CMS-001.\n");
+	Info("Also supports the Askey VC010, various Logitech QuickCams, Samsung MPC-C10 and MPC-C30,\n");
+	Info("the Creative WebCam 5, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
 
 	if (fps) {
-		if (fps < 5 || fps > 30) {
-			Err("Framerate out of bounds (5-30).\n");
+		if (fps < 4 || fps > 30) {
+			Err("Framerate out of bounds (4-30).\n");
 			return -EINVAL;
 		}
 		default_fps = fps;
@@ -1938,9 +2037,9 @@
 	if (power_save)
 		Info("Enabling power save on open/close.\n");
 	if (leds[0] >= 0)
-		led_on = leds[0] / 100;
+		led_on = leds[0];
 	if (leds[1] >= 0)
-		led_off = leds[1] / 100;
+		led_off = leds[1];
 
 	/* Big device node whoopla. Basicly, it allows you to assign a 
 	   device node (/dev/videoX) to a camera, based on its type 
@@ -1999,7 +2098,7 @@
 					device_hint[i].serial_number[k] = '\0';
 				}
 			}
-#ifdef PWC_DEBUG		
+#if PWC_DEBUG		
 			Debug("device_hint[%d]:\n", i);
 			Debug("  type    : %d\n", device_hint[i].type);
 			Debug("  serial# : %s\n", device_hint[i].serial_number);
diff -Nru a/drivers/usb/media/pwc-misc.c b/drivers/usb/media/pwc-misc.c
--- a/drivers/usb/media/pwc-misc.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/usb/media/pwc-misc.c	Wed Nov 27 14:36:29 2002
@@ -1,6 +1,6 @@
 /* Linux driver for Philips webcam 
    Various miscellaneous functions and tables.
-   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+   (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
 
    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
diff -Nru a/drivers/usb/media/pwc-uncompress.c b/drivers/usb/media/pwc-uncompress.c
--- a/drivers/usb/media/pwc-uncompress.c	Wed Nov 27 14:36:30 2002
+++ b/drivers/usb/media/pwc-uncompress.c	Wed Nov 27 14:36:30 2002
@@ -1,6 +1,6 @@
 /* Linux driver for Philips webcam 
    Decompression frontend.
-   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+   (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
 
    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
@@ -77,7 +77,7 @@
 {
 	struct pwc_frame_buf *fbuf;
 	int n, line, col, stride;
-	void *yuv, *image, *dst;
+	void *yuv, *image;
 	u16 *src;
 	u16 *dsty, *dstu, *dstv;
 
@@ -114,19 +114,6 @@
 		   to get the desired output format/size.
 		 */
 		switch (pdev->vpalette) {
-		case VIDEO_PALETTE_YUV420:
-			/* Calculate byte offsets per line in image & view */
-			n   = (pdev->image.x * 3) / 2;
-			col = (pdev->view.x  * 3) / 2;
-			/* Offset into image */
-			dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2;
-			for (line = 0; line < pdev->image.y; line++) {
-				memcpy(dst, yuv, n);
-				yuv += n;
-				dst += col;
-			}
-			break;
-
 		case VIDEO_PALETTE_YUV420P:
 			/* 
 			 * We do some byte shuffling here to go from the 
@@ -163,17 +150,20 @@
 					dstu += (stride >> 1);
 			}
 			break;
+		default:
+			Err("Unsupported palette!");
+			break;
 		}
 	}
 	else { 
 		/* Compressed; the decompressor routines will write the data 
-		   in interlaced or planar format immediately.
+		   in planar format immediately.
 		 */
 		if (pdev->decompressor)
 			pdev->decompressor->decompress(
 				&pdev->image, &pdev->view, &pdev->offset,
-				yuv, image, 
-				pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0,
+				yuv, image,
+				1,
 				pdev->decompress_data, pdev->vbandlength);
 		else
 			return -ENXIO; /* No such device or address: missing decompressor */
diff -Nru a/drivers/usb/media/pwc-uncompress.h b/drivers/usb/media/pwc-uncompress.h
--- a/drivers/usb/media/pwc-uncompress.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/usb/media/pwc-uncompress.h	Wed Nov 27 14:36:28 2002
@@ -1,4 +1,4 @@
-/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+/* (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
 
    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
diff -Nru a/drivers/usb/media/pwc.h b/drivers/usb/media/pwc.h
--- a/drivers/usb/media/pwc.h	Wed Nov 27 14:36:31 2002
+++ b/drivers/usb/media/pwc.h	Wed Nov 27 14:36:31 2002
@@ -60,8 +60,8 @@
 
 /* Version block */
 #define PWC_MAJOR	8
-#define PWC_MINOR	7
-#define PWC_VERSION 	"8.7"
+#define PWC_MINOR	9
+#define PWC_VERSION 	"8.9"
 #define PWC_NAME 	"pwc"
 
 /* Turn certain features on/off */
@@ -130,7 +130,7 @@
    int vcinterface;		/* video control interface */
    int valternate;		/* alternate interface needed */
    int vframes, vsize;		/* frames-per-second & size (see PSZ_*) */
-   int vpalette;		/* YUV, RGB24, RGB32, etc */
+   int vpalette;		/* YUV */
    int vframe_count;		/* received frames */
    int vframes_dumped; 		/* counter for dumped frames */
    int vframes_error;		/* frames received in error */
@@ -140,7 +140,8 @@
    int vbandlength;		/* compressed band length; 0 is uncompressed */
    char vsnapshot;		/* snapshot mode */
    char vsync;			/* used by isoc handler */
-   
+   char vmirror;		/* for ToUCaM series */
+
    /* The image acquisition requires 3 to 4 steps:
       1. data is gathered in short packets from the USB controller
       2. data is synchronized and packed into a frame buffer
diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- a/drivers/usb/media/vicam.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/usb/media/vicam.c	Wed Nov 27 14:36:28 2002
@@ -1,7 +1,7 @@
 /*
  * USB ViCam WebCam driver
  * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
- *                    John Tyner (fill in email address)
+ *                    John Tyner (jtyner@cs.ucr.edu)
  *
  * Supports 3COM HomeConnect PC Digital WebCam
  *
@@ -29,7 +29,7 @@
  * Andy Armstrong who reverse engineered the color encoding and
  * Pavel Machek and Chris Cheney who worked on reverse engineering the
  *    camera controls and wrote the first generation driver.
- * */
+ */
 
 #include <linux/kernel.h>
 #include <linux/wrapper.h>
@@ -51,19 +51,25 @@
 #define DBG(fmn,args...) do {} while(0)
 #endif
 
-/* Version Information */
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org"
-#define DRIVER_DESC "ViCam WebCam Driver"
+#define DRIVER_AUTHOR           "Joe Burks, jburks@wavicle.org"
+#define DRIVER_DESC             "ViCam WebCam Driver"
 
 /* Define these values to match your device */
 #define USB_VICAM_VENDOR_ID	0x04c1
 #define USB_VICAM_PRODUCT_ID	0x009d
 
-#define VICAM_BYTES_PER_PIXEL 3
-#define VICAM_MAX_READ_SIZE (512*242+128)
-#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240)
-#define VICAM_FRAMES 2
+#define VICAM_BYTES_PER_PIXEL   3
+#define VICAM_MAX_READ_SIZE     (512*242+128)
+#define VICAM_MAX_FRAME_SIZE    (VICAM_BYTES_PER_PIXEL*320*240)
+#define VICAM_FRAMES            2
+
+#define VICAM_HEADER_SIZE       64
+
+#define clamp( x, l, h )        max_t( __typeof__( x ),         \
+                                       ( l ),                   \
+                                       min_t( __typeof__( x ),  \
+                                              ( h ),            \
+                                              ( x ) ) )
 
 /* Not sure what all the bytes in these char
  * arrays do, but they're necessary to make
@@ -408,7 +414,8 @@
 	struct video_device vdev;	// v4l video device
 	struct usb_device *udev;	// usb device
 
-	struct semaphore busy_lock;	// guard against SMP multithreading
+	/* guard against simultaneous accesses to the camera */
+	struct semaphore cam_lock;
 
 	int is_initialized;
 	u8 open_count;
@@ -424,17 +431,21 @@
 static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
 static void vicam_disconnect(struct usb_interface *intf);
 static void read_frame(struct vicam_camera *cam, int framenum);
+static void vicam_decode_color(const u8 *, u8 *);
 
-static int
-send_control_msg(struct usb_device *udev, u8 request, u16 value, u16 index,
-		 unsigned char *cp, u16 size)
+static int __send_control_msg(struct vicam_camera *cam,
+			      u8 request,
+			      u16 value,
+			      u16 index,
+			      unsigned char *cp,
+			      u16 size)
 {
 	int status;
 
 	/* cp must be memory that has been allocated by kmalloc */
 
-	status = usb_control_msg(udev,
-				 usb_sndctrlpipe(udev, 0),
+	status = usb_control_msg(cam->udev,
+				 usb_sndctrlpipe(cam->udev, 0),
 				 request,
 				 USB_DIR_OUT | USB_TYPE_VENDOR |
 				 USB_RECIP_DEVICE, value, index,
@@ -450,6 +461,22 @@
 	return status;
 }
 
+static int send_control_msg(struct vicam_camera *cam,
+			    u8 request,
+			    u16 value,
+			    u16 index,
+			    unsigned char *cp,
+			    u16 size)
+{
+	int status = -ENODEV;
+	down(&cam->cam_lock);
+	if (cam->udev) {
+		status = __send_control_msg(cam, request, value,
+					    index, cp, size);
+	}
+	up(&cam->cam_lock);
+	return status;
+}
 static int
 initialize_camera(struct vicam_camera *cam)
 {
@@ -465,14 +492,13 @@
 		{ .data = setup3, .size = sizeof(setup3) },
 		{ .data = NULL, .size = 0 }
 	};
-	
-	struct usb_device *udev = cam->udev;
+
 	int err, i;
 
 	for (i = 0, err = 0; firmware[i].data && !err; i++) {
 		memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size);
 
-		err = send_control_msg(udev, 0xff, 0, 0,
+		err = send_control_msg(cam, 0xff, 0, 0,
 				       cam->cntrlbuf, firmware[i].size);
 	}
 
@@ -484,11 +510,11 @@
 {
 	int status;
 
-	if ((status = send_control_msg(cam->udev, 0x50, state, 0, NULL, 0)) < 0)
+	if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
 		return status;
 
 	if (state) {
-		send_control_msg(cam->udev, 0x55, 1, 0, NULL, 0);
+		send_control_msg(cam, 0x55, 1, 0, NULL, 0);
 	}
 
 	return 0;
@@ -504,10 +530,6 @@
 	if (!cam)
 		return -ENODEV;
 
-	/* make this _really_ smp-safe */
-	if (down_interruptible(&cam->busy_lock))
-		return -EINTR;
-
 	switch (ioctlnr) {
 		/* query capabilites */
 	case VIDIOCGCAP:
@@ -694,6 +716,9 @@
 			DBG("VIDIOCSYNC: %d\n", frame);
 
 			read_frame(cam, frame);
+			vicam_decode_color(cam->raw_image,
+					   cam->framebuf +
+					   frame * VICAM_MAX_FRAME_SIZE );
 
 			break;
 		}
@@ -724,7 +749,6 @@
 		break;
 	}
 
-	up(&cam->busy_lock);
 	return retval;
 }
 
@@ -741,26 +765,25 @@
 		       "vicam video_device improperly initialized");
 	}
 
-	if ( down_interruptible(&cam->busy_lock) )
-		return -EINTR;
+	/* the videodev_lock held above us protects us from
+	 * simultaneous opens...for now. we probably shouldn't
+	 * rely on this fact forever.
+	 */
 
 	if (cam->open_count > 0) {
 		printk(KERN_INFO
 		       "vicam_open called on already opened camera");
-		up(&cam->busy_lock);
 		return -EBUSY;
 	}
 
 	cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
 	if (!cam->raw_image) {
-		up(&cam->busy_lock);
 		return -ENOMEM;
 	}
 
 	cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
 	if (!cam->framebuf) {
 		kfree(cam->raw_image);
-		up(&cam->busy_lock);
 		return -ENOMEM;
 	}
 
@@ -768,7 +791,6 @@
 	if (!cam->cntrlbuf) {
 		kfree(cam->raw_image);
 		rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
-		up(&cam->busy_lock);
 		return -ENOMEM;
 	}
 
@@ -785,8 +807,6 @@
 	cam->needsDummyRead = 1;
 	cam->open_count++;
 
-	up(&cam->busy_lock);
-
 	file->private_data = cam;	
 	
 	return 0;
@@ -796,118 +816,105 @@
 vicam_close(struct inode *inode, struct file *file)
 {
 	struct vicam_camera *cam = file->private_data;
+	int open_count;
+	struct usb_device *udev;
+
 	DBG("close\n");
+
+	/* it's not the end of the world if
+	 * we fail to turn the camera off.
+	 */
+
 	set_camera_power(cam, 0);
 
 	kfree(cam->raw_image);
 	rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
 	kfree(cam->cntrlbuf);
 
+	down(&cam->cam_lock);
+
 	cam->open_count--;
+	open_count = cam->open_count;
+	udev = cam->udev;
+
+	up(&cam->cam_lock);
+
+	if (!open_count && !udev) {
+		kfree(cam);
+	}
 
 	return 0;
 }
 
-inline int pin(int x)
+static void vicam_decode_color(const u8 *data, u8 *rgb)
 {
-	return((x > 255) ? 255 : ((x < 0) ? 0 : x));
-}
+	/* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
+	 * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
+	 */
 
-inline void writepixel(char *rgb, int Y, int Cr, int Cb)
-{
-	Y = 1160 * (Y - 16);
-	
-	rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 );
-	rgb[1] = pin( ( ( Y - (  392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 );
-	rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 );
-}
-
-#define DATA_HEADER_SIZE 64
-
-// --------------------------------------------------------------------------------
-//	vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
-//
-//   Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
-// --------------------------------------------------------------------------------
-
-static void vicam_decode_color( char *data, char *rgb)
-{
-	int x,y;
-	int Cr, Cb;
-	int sign;
-	int prevX, nextX, prevY, nextY;
-	int skip;
-	unsigned char *src;
-	unsigned char *dst;
+	int i, prevY, nextY;
 
 	prevY = 512;
 	nextY = 512;
 
-	src = data + DATA_HEADER_SIZE;
-	dst = rgb;
-
-	for(y = 1; y < 241; y += 2)
-	{
-		// even line
-		sign = 1;
-		prevX = 1;
-		nextX = 1;
-
-		skip = 0;
+	data += VICAM_HEADER_SIZE;
 
-		dst = rgb + (y-1)*320*3;
-		
-		for(x = 0; x < 512; x++)
-		{
-			if(x == 512-1)
-				nextX = -1;
-
-			Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1;
-			Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2;
+	for( i = 0; i < 240; i++, data += 512 ) {
+		const int y = ( i * 242 ) / 240;
 
-			writepixel(
-					dst + ((x*5)>>3)*3,
-					src[0] + (sign * (Cr >> 1)),
-					Cr,
-					Cb);
+		int j, prevX, nextX;
+		int Y, Cr, Cb;
 
-			src++;
-			sign *= -1;
-			prevX = -1;
-		}
-
-		prevY = -512;
-
-		if(y == (242 - 2))
+		if ( y == 242 - 1 ) {
 			nextY = -512;
+		}
 
-		// odd line
-		sign = 1;
 		prevX = 1;
 		nextX = 1;
 
-		skip = 0;
+		for ( j = 0; j < 320; j++, rgb += 3 ) {
+			const int x = ( j * 512 ) / 320;
+			const u8 * const src = &data[x];
 
-		dst = rgb + (y)*320*3;
-		
-		for(x = 0; x < 512; x++)
-		{
-			if(x == 512-1)
+			if ( x == 512 - 1 ) {
 				nextX = -1;
-			
-			Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2;
-			Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1;
+			}
 
-			writepixel(
-					dst + ((x * 5)>>3)*3,
-					src[0] - (sign * (Cb >> 1)),
-					Cr,
-					Cb);
+			Cr = ( src[prevX] - src[0] ) +
+				( src[nextX] - src[0] );
+			Cr /= 2;
+
+			Cb = ( src[prevY] - src[prevX + prevY] ) +
+				( src[prevY] - src[nextX + prevY] ) +
+				( src[nextY] - src[prevX + nextY] ) +
+				( src[nextY] - src[nextX + nextY] );
+			Cb /= 4;
+
+			Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
+
+			if ( i & 1 ) {
+				int Ct = Cr;
+				Cr = Cb;
+				Cb = Ct;
+			}
+
+			if ( ( x ^ i ) & 1 ) {
+				Cr = -Cr;
+				Cb = -Cb;
+			}
+
+			rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
+					500 ) / 900, 0, 255 );
+			rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
+					  ( 813 * Cr ) ) +
+					  500 ) / 1000, 0, 255 );
+			rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
+					500 ) / 1300, 0, 255 );
 
-			src++;
-			sign *= -1;
 			prevX = -1;
 		}
+
+		prevY = -512;
 	}
 }
 
@@ -953,12 +960,18 @@
 	request[8] = 0;
 	// bytes 9-15 do not seem to affect exposure or image quality
 
-	n = send_control_msg(cam->udev, 0x51, 0x80, 0, request, 16);
+	down(&cam->cam_lock);
+
+	if (!cam->udev) {
+		goto done;
+	}
+
+	n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
 
 	if (n < 0) {
 		printk(KERN_ERR
 		       " Problem sending frame capture control message");
-		return;
+		goto done;
 	}
 
 	n = usb_bulk_msg(cam->udev,
@@ -971,9 +984,8 @@
 		       n);
 	}
 
-	vicam_decode_color(cam->raw_image,
-			 cam->framebuf +
-			 framenum * VICAM_MAX_FRAME_SIZE );
+ done:
+	up(&cam->cam_lock);
 }
 
 static int
@@ -983,17 +995,16 @@
 
 	DBG("read %d bytes.\n", (int) count);
 
-	if ( down_interruptible(&cam->busy_lock) )
-		return -EINTR;
-
 	if (*ppos >= VICAM_MAX_FRAME_SIZE) {
 		*ppos = 0;
-		up(&cam->busy_lock);
 		return 0;
 	}
 
 	if (*ppos == 0) {
 		read_frame(cam, 0);
+		vicam_decode_color(cam->raw_image,
+				   cam->framebuf +
+				   0 * VICAM_MAX_FRAME_SIZE);
 	}
 
 	count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
@@ -1008,8 +1019,6 @@
 		*ppos = 0;
 	}
 
-	up(&cam->busy_lock);
-
 	return count;
 }
 
@@ -1034,10 +1043,6 @@
 	 return -EINVAL;
 	 */
 
-	/* make this _really_ smp-safe */
-	if (down_interruptible(&cam->busy_lock))
-		return -EINTR;
-
 	pos = (unsigned long)cam->framebuf;
 	while (size > 0) {
 		page = kvirt_to_pa(pos);
@@ -1052,8 +1057,6 @@
 			size = 0;
 	}
 
-	up(&cam->busy_lock);
-
 	return 0;
 }
 
@@ -1285,7 +1288,7 @@
 
 	cam->shutter_speed = 15;
 
-	init_MUTEX(&cam->busy_lock);
+	init_MUTEX(&cam->cam_lock);
 
 	memcpy(&cam->vdev, &vicam_template,
 	       sizeof (vicam_template));
@@ -1312,17 +1315,43 @@
 static void
 vicam_disconnect(struct usb_interface *intf)
 {
+	int open_count;
 	struct vicam_camera *cam = dev_get_drvdata(&intf->dev);
-
 	dev_set_drvdata ( &intf->dev, NULL );
-	
-	cam->udev = NULL;
-	
+
+	/* we must unregister the device before taking its
+	 * cam_lock. This is because the video open call
+	 * holds the same lock as video unregister. if we
+	 * unregister inside of the cam_lock and open also
+	 * uses the cam_lock, we get deadlock.
+	 */
+
 	video_unregister_device(&cam->vdev);
 
+	/* stop the camera from being used */
+
+	down(&cam->cam_lock);
+
+	/* mark the camera as gone */
+
+	cam->udev = NULL;
+
 	vicam_destroy_proc_entry(cam);
 
-	kfree(cam);
+	/* the only thing left to do is synchronize with
+	 * our close/release function on who should release
+	 * the camera memory. if there are any users using the
+	 * camera, it's their job. if there are no users,
+	 * it's ours.
+	 */
+
+	open_count = cam->open_count;
+
+	up(&cam->cam_lock);
+
+	if (!open_count) {
+		kfree(cam);
+	}
 
 	printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
 }
diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
--- a/drivers/usb/misc/tiglusb.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/usb/misc/tiglusb.c	Wed Nov 27 14:36:27 2002
@@ -185,7 +185,7 @@
 
 	pipe = usb_rcvbulkpipe (s->dev, 1);
 	result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
-			       &bytes_read, HZ / (timeout / 10));
+			       &bytes_read, HZ * 10 / timeout);
 	if (result == -ETIMEDOUT) {	/* NAK */
 		ret = result;
 		if (!bytes_read) {
@@ -242,7 +242,7 @@
 
 	pipe = usb_sndbulkpipe (s->dev, 2);
 	result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write,
-			       &bytes_written, HZ / (timeout / 10));
+			       &bytes_written, HZ * 10 / timeout);
 
 	if (result == -ETIMEDOUT) {	/* NAK */
 		warn ("tiglusb_write, NAK received.");
@@ -453,6 +453,8 @@
 	if (ints[0] > 0) {
 		timeout = ints[1];
 	}
+	if (!timeout)
+		timeout = TIMAXTIME;
 
 	return 1;
 }
@@ -494,6 +496,9 @@
 
 	info (DRIVER_DESC ", " DRIVER_VERSION);
 
+	if (!timeout)
+		timeout = TIMAXTIME;
+
 	return 0;
 }
 
@@ -516,6 +521,6 @@
 MODULE_LICENSE (DRIVER_LICENSE);
 
 MODULE_PARM (timeout, "i");
-MODULE_PARM_DESC (timeout, "Timeout (default=1.5 seconds)");
+MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)");
 
 /* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
--- a/drivers/usb/serial/Kconfig	Wed Nov 27 14:36:31 2002
+++ b/drivers/usb/serial/Kconfig	Wed Nov 27 14:36:31 2002
@@ -400,5 +400,10 @@
 	  The module will be called omninet.o. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt>.
 
+config USB_EZUSB
+	bool
+	depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
+	default y
+
 endmenu
 
diff -Nru a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
--- a/drivers/usb/serial/Makefile	Wed Nov 27 14:36:28 2002
+++ b/drivers/usb/serial/Makefile	Wed Nov 27 14:36:28 2002
@@ -7,6 +7,7 @@
 obj-$(CONFIG_USB_SERIAL)			+= usbserial.o
 
 usbserial-obj-$(CONFIG_USB_SERIAL_CONSOLE)	+= console.o
+usbserial-obj-$(CONFIG_USB_EZUSB)		+= ezusb.o
 
 obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o
 obj-$(CONFIG_USB_SERIAL_IPAQ)			+= ipaq.o
@@ -29,9 +30,9 @@
 obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
 
 # Objects that export symbols.
-export-objs	:= usb-serial.o
+export-objs	:= usb-serial.o ezusb.o
 
-usbserial-objs	:= usb-serial.o $(usbserial-obj-y)
+usbserial-objs	:= usb-serial.o generic.o $(usbserial-obj-y)
 
 include $(TOPDIR)/Rules.make
 
diff -Nru a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/serial/ezusb.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,67 @@
+/*
+ * EZ-USB specific functions used by some of the USB to Serial drivers.
+ *
+ * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+	static int debug = 1;
+#else
+	static int debug;
+#endif
+
+#include "usb-serial.h"
+
+/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
+#define CPUCS_REG    0x7F92
+
+int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
+{
+	int result;
+	unsigned char *transfer_buffer;
+
+	/* dbg("ezusb_writememory %x, %d", address, length); */
+	if (!serial->dev) {
+		dbg("%s - no physical device present, failing.", __FUNCTION__);
+		return -ENODEV;
+	}
+
+	transfer_buffer =  kmalloc (length, GFP_KERNEL);
+	if (!transfer_buffer) {
+		err("%s - kmalloc(%d) failed.", __FUNCTION__, length);
+		return -ENOMEM;
+	}
+	memcpy (transfer_buffer, data, length);
+	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3*HZ);
+	kfree (transfer_buffer);
+	return result;
+}
+
+int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+{
+	int	response;
+	dbg("%s - %d", __FUNCTION__, reset_bit);
+	response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+	if (response < 0) {
+		err("%s- %d failed", __FUNCTION__, reset_bit);
+	}
+	return response;
+}
+
+
+EXPORT_SYMBOL(ezusb_writememory);
+EXPORT_SYMBOL(ezusb_set_reset);
+
diff -Nru a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/serial/generic.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,304 @@
+/*
+ * USB Serial Converter Generic functions
+ *
+ * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+	static int debug = 1;
+#else
+	static int debug;
+#endif
+
+#include "usb-serial.h"
+
+	
+#ifdef CONFIG_USB_SERIAL_GENERIC
+static __u16 vendor  = 0x05f9;
+static __u16 product = 0xffff;
+
+MODULE_PARM(vendor, "h");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "h");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+
+static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
+
+/* All of the device info needed for the Generic Serial Converter */
+struct usb_serial_device_type usb_serial_generic_device = {
+	.owner =		THIS_MODULE,
+	.name =			"Generic",
+	.id_table =		generic_device_ids,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		NUM_DONT_CARE,
+	.num_bulk_out =		NUM_DONT_CARE,
+	.num_ports =		1,
+	.shutdown =		usb_serial_generic_shutdown,
+};
+#endif
+
+int usb_serial_generic_register (int _debug)
+{
+	int retval = 0;
+
+	debug = _debug;
+#ifdef CONFIG_USB_SERIAL_GENERIC
+	generic_device_ids[0].idVendor = vendor;
+	generic_device_ids[0].idProduct = product;
+	generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
+
+	/* register our generic driver with ourselves */
+	retval = usb_serial_register (&usb_serial_generic_device);
+#endif
+	return retval;
+}
+
+void usb_serial_generic_deregister (void)
+{
+#ifdef CONFIG_USB_SERIAL_GENERIC
+	/* remove our generic driver */
+	usb_serial_deregister (&usb_serial_generic_device);
+#endif
+}
+
+int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
+{
+	struct usb_serial *serial = port->serial;
+	int result = 0;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return -ENODEV;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* force low_latency on so that our tty_push actually forces the data through, 
+	   otherwise it is scheduled, and with high data rates (like with OHCI) data
+	   can get lost. */
+	if (port->tty)
+		port->tty->low_latency = 1;
+
+	/* if we have a bulk interrupt, start reading from it */
+	if (serial->num_bulk_in) {
+		/* Start reading from the device */
+		usb_fill_bulk_urb (port->read_urb, serial->dev,
+				   usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+				   port->read_urb->transfer_buffer,
+				   port->read_urb->transfer_buffer_length,
+				   ((serial->type->read_bulk_callback) ?
+				     serial->type->read_bulk_callback :
+				     usb_serial_generic_read_bulk_callback),
+				   port);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+		if (result)
+			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+	}
+
+	return result;
+}
+
+static void generic_cleanup (struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (serial->dev) {
+		/* shutdown any bulk reads that might be going on */
+		if (serial->num_bulk_out)
+			usb_unlink_urb (port->write_urb);
+		if (serial->num_bulk_in)
+			usb_unlink_urb (port->read_urb);
+	}
+}
+
+void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
+{
+	dbg("%s - port %d", __FUNCTION__, port->number);
+	generic_cleanup (port);
+}
+
+int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = port->serial;
+	int result;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (count == 0) {
+		dbg("%s - write request of 0 bytes", __FUNCTION__);
+		return (0);
+	}
+
+	/* only do something if we have a bulk out endpoint */
+	if (serial->num_bulk_out) {
+		if (port->write_urb->status == -EINPROGRESS) {
+			dbg("%s - already writing", __FUNCTION__);
+			return (0);
+		}
+
+		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+		if (from_user) {
+			if (copy_from_user(port->write_urb->transfer_buffer, buf, count))
+				return -EFAULT;
+		}
+		else {
+			memcpy (port->write_urb->transfer_buffer, buf, count);
+		}
+
+		usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+
+		/* set up our urb */
+		usb_fill_bulk_urb (port->write_urb, serial->dev,
+				   usb_sndbulkpipe (serial->dev,
+						    port->bulk_out_endpointAddress),
+				   port->write_urb->transfer_buffer, count,
+				   ((serial->type->write_bulk_callback) ? 
+				     serial->type->write_bulk_callback :
+				     usb_serial_generic_write_bulk_callback), port);
+
+		/* send the data out the bulk port */
+		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (result)
+			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+		else
+			result = count;
+
+		return result;
+	}
+
+	/* no bulk out, so return 0 bytes written */
+	return (0);
+}
+
+int usb_serial_generic_write_room (struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	int room = 0;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+	
+	if (serial->num_bulk_out) {
+		if (port->write_urb->status != -EINPROGRESS)
+			room = port->bulk_out_size;
+	}
+
+	dbg("%s - returns %d", __FUNCTION__, room);
+	return (room);
+}
+
+int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
+{
+	struct usb_serial *serial = port->serial;
+	int chars = 0;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (serial->num_bulk_out) {
+		if (port->write_urb->status == -EINPROGRESS)
+			chars = port->write_urb->transfer_buffer_length;
+	}
+
+	dbg("%s - returns %d", __FUNCTION__, chars);
+	return (chars);
+}
+
+void usb_serial_generic_read_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+	struct tty_struct *tty;
+	unsigned char *data = urb->transfer_buffer;
+	int i;
+	int result;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (!serial) {
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+		return;
+	}
+
+	if (urb->status) {
+		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+		return;
+	}
+
+	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+
+	tty = port->tty;
+	if (tty && urb->actual_length) {
+		for (i = 0; i < urb->actual_length ; ++i) {
+			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
+			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(tty);
+			}
+			/* this doesn't actually push the data through unless tty->low_latency is set */
+			tty_insert_flip_char(tty, data[i], 0);
+		}
+	  	tty_flip_buffer_push(tty);
+	}
+
+	/* Continue trying to always read  */
+	usb_fill_bulk_urb (port->read_urb, serial->dev,
+			   usb_rcvbulkpipe (serial->dev,
+				   	    port->bulk_in_endpointAddress),
+			   port->read_urb->transfer_buffer,
+			   port->read_urb->transfer_buffer_length,
+			   ((serial->type->read_bulk_callback) ? 
+			     serial->type->read_bulk_callback : 
+			     usb_serial_generic_read_bulk_callback), port);
+	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+	if (result)
+		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+}
+
+void usb_serial_generic_write_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	if (!serial) {
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+		return;
+	}
+
+	if (urb->status) {
+		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+		return;
+	}
+
+	usb_serial_port_softint((void *)port);
+
+	schedule_work(&port->work);
+}
+
+void usb_serial_generic_shutdown (struct usb_serial *serial)
+{
+	int i;
+
+	dbg("%s", __FUNCTION__);
+
+	/* stop reads and writes on all ports */
+	for (i=0; i < serial->num_ports; ++i) {
+		generic_cleanup (&serial->port[i]);
+	}
+}
+
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/usb/serial/ipaq.c	Wed Nov 27 14:36:31 2002
@@ -9,6 +9,10 @@
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
  *
+ * (26/11/2002) ganesh
+ * 	Added insmod options to specify product and vendor id.
+ * 	Use modprobe ipaq vendor=0xfoo product=0xbar
+ *
  * (26/7/2002) ganesh
  * 	Fixed up broken error handling in ipaq_open. Retry the "kickstart"
  * 	packet much harder - this drastically reduces connection failures.
@@ -63,10 +67,13 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.2"
+
+#define DRIVER_VERSION "v0.4"
 #define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
 #define DRIVER_DESC "USB Compaq iPAQ, HP Jornada, Casio EM500 driver"
 
+static int	product, vendor;
+
 /* Function prototypes for an ipaq */
 static int  ipaq_open (struct usb_serial_port *port, struct file *filp);
 static void ipaq_close (struct usb_serial_port *port, struct file *filp);
@@ -85,6 +92,8 @@
 
 
 static struct usb_device_id ipaq_id_table [] = {
+	/* The first entry is a placeholder for the insmod-specified device */
+	{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) },
 	{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) },
 	{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_548_ID) },
 	{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) },
@@ -521,9 +530,14 @@
 
 static int __init ipaq_init(void)
 {
+	spin_lock_init(&write_list_lock);
 	usb_serial_register(&ipaq_device);
-	usb_register(&ipaq_driver);
 	info(DRIVER_DESC " " DRIVER_VERSION);
+	if (vendor) {
+		ipaq_id_table[0].idVendor = vendor;
+		ipaq_id_table[0].idProduct = product;
+	}
+	usb_register(&ipaq_driver);
 
 	return 0;
 }
@@ -546,3 +560,8 @@
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
+MODULE_PARM(vendor, "h");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "h");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
--- a/drivers/usb/serial/keyspan.c	Wed Nov 27 14:36:27 2002
+++ b/drivers/usb/serial/keyspan.c	Wed Nov 27 14:36:27 2002
@@ -346,7 +346,7 @@
 		if (this_urb->status == -EINPROGRESS) {
 			if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
 				break;
-			if (jiffies - p_priv->tx_start_time[flip] < 10 * HZ)
+			if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
 				break;
 			this_urb->transfer_flags |= URB_ASYNC_UNLINK;
 			usb_unlink_urb(this_urb);
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c	Wed Nov 27 14:36:29 2002
+++ b/drivers/usb/serial/usb-serial.c	Wed Nov 27 14:36:29 2002
@@ -345,41 +345,12 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.7"
+#define DRIVER_VERSION "v1.8"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
 #define DRIVER_DESC "USB Serial Driver core"
 
-/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
-/* need to always compile these in, as some of the other devices use these functions as their own. */
-/* if a driver does not provide a function pointer, the generic function will be called. */
-int usb_serial_generic_open		(struct usb_serial_port *port, struct file *filp);
-int usb_serial_generic_write		(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
-static void generic_close		(struct usb_serial_port *port, struct file *filp);
-static int  generic_write_room		(struct usb_serial_port *port);
-static int  generic_chars_in_buffer	(struct usb_serial_port *port);
-static void generic_read_bulk_callback	(struct urb *urb);
-static void generic_write_bulk_callback	(struct urb *urb);
-static void generic_shutdown		(struct usb_serial *serial);
-
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
-static __u16	vendor	= 0x05f9;
-static __u16	product	= 0xffff;
-
-static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
-
-/* All of the device info needed for the Generic Serial Converter */
-static struct usb_serial_device_type generic_device = {
-	.owner =		THIS_MODULE,
-	.name =			"Generic",
-	.id_table =		generic_device_ids,
-	.num_interrupt_in =	NUM_DONT_CARE,
-	.num_bulk_in =		NUM_DONT_CARE,
-	.num_bulk_out =		NUM_DONT_CARE,
-	.num_ports =		1,
-	.shutdown =		generic_shutdown,
-};
-
 /* we want to look at all devices, as the vendor/product id can change
  * depending on the command line argument */
 static struct usb_device_id generic_serial_ids[] = {
@@ -387,27 +358,6 @@
 	{}
 };
 
-static int generic_register (void)
-{
-	generic_device_ids[0].idVendor = vendor;
-	generic_device_ids[0].idProduct = product;
-	generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
-
-	/* register our generic driver with ourselves */
-	return usb_serial_register (&generic_device);
-}
-
-static void generic_deregister (void)
-{
-	/* remove our generic driver */
-	usb_serial_deregister (&generic_device);
-}
-
-#else
-
-static inline int generic_register (void) { return 0; }
-static inline void generic_deregister (void) { }
-
 #endif /* CONFIG_USB_SERIAL_GENERIC */
 
 /* Driver structure we register with the USB core */
@@ -488,45 +438,6 @@
 	return;
 }
 
-#ifdef USES_EZUSB_FUNCTIONS
-/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
-#define CPUCS_REG    0x7F92
-
-int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
-{
-	int result;
-	unsigned char *transfer_buffer;
-
-	/* dbg("ezusb_writememory %x, %d", address, length); */
-	if (!serial->dev) {
-		dbg("%s - no physical device present, failing.", __FUNCTION__);
-		return -ENODEV;
-	}
-
-	transfer_buffer =  kmalloc (length, GFP_KERNEL);
-	if (!transfer_buffer) {
-		err("%s - kmalloc(%d) failed.", __FUNCTION__, length);
-		return -ENOMEM;
-	}
-	memcpy (transfer_buffer, data, length);
-	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3*HZ);
-	kfree (transfer_buffer);
-	return result;
-}
-
-int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
-{
-	int	response;
-	dbg("%s - %d", __FUNCTION__, reset_bit);
-	response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
-	if (response < 0) {
-		err("%s- %d failed", __FUNCTION__, reset_bit);
-	}
-	return response;
-}
-
-#endif	/* USES_EZUSB_FUNCTIONS */
-
 /*****************************************************************************
  * Driver tty interface functions
  *****************************************************************************/
@@ -593,7 +504,7 @@
 		if (port->serial->type->close)
 			port->serial->type->close(port, filp);
 		else
-			generic_close(port, filp);
+			usb_serial_generic_close(port, filp);
 		port->open_count = 0;
 	}
 
@@ -672,7 +583,7 @@
 	if (serial->type->write_room)
 		retval = serial->type->write_room(port);
 	else
-		retval = generic_write_room(port);
+		retval = usb_serial_generic_write_room(port);
 
 exit:
 	up (&port->sem);
@@ -701,7 +612,7 @@
 	if (serial->type->chars_in_buffer)
 		retval = serial->type->chars_in_buffer(port);
 	else
-		retval = generic_chars_in_buffer(port);
+		retval = usb_serial_generic_chars_in_buffer(port);
 
 exit:
 	up (&port->sem);
@@ -844,7 +755,7 @@
 	if (serial->type->shutdown)
 		serial->type->shutdown(serial);
 	else
-		generic_shutdown(serial);
+		usb_serial_generic_shutdown(serial);
 }
 
 static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
@@ -889,235 +800,6 @@
 	return ((count < begin+length-off) ? count : begin+length-off);
 }
 
-/*****************************************************************************
- * generic devices specific driver functions
- *****************************************************************************/
-int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
-{
-	struct usb_serial *serial = port->serial;
-	int result = 0;
-
-	if (port_paranoia_check (port, __FUNCTION__))
-		return -ENODEV;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	/* force low_latency on so that our tty_push actually forces the data through, 
-	   otherwise it is scheduled, and with high data rates (like with OHCI) data
-	   can get lost. */
-	if (port->tty)
-		port->tty->low_latency = 1;
-
-	/* if we have a bulk interrupt, start reading from it */
-	if (serial->num_bulk_in) {
-		/* Start reading from the device */
-		usb_fill_bulk_urb (port->read_urb, serial->dev,
-				   usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-				   port->read_urb->transfer_buffer,
-				   port->read_urb->transfer_buffer_length,
-				   ((serial->type->read_bulk_callback) ?
-				     serial->type->read_bulk_callback :
-				     generic_read_bulk_callback),
-				   port);
-		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (result)
-			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-	}
-
-	return result;
-}
-
-static void generic_cleanup (struct usb_serial_port *port)
-{
-	struct usb_serial *serial = port->serial;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	if (serial->dev) {
-		/* shutdown any bulk reads that might be going on */
-		if (serial->num_bulk_out)
-			usb_unlink_urb (port->write_urb);
-		if (serial->num_bulk_in)
-			usb_unlink_urb (port->read_urb);
-	}
-}
-
-static void generic_close (struct usb_serial_port *port, struct file * filp)
-{
-	dbg("%s - port %d", __FUNCTION__, port->number);
-	generic_cleanup (port);
-}
-
-int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
-{
-	struct usb_serial *serial = port->serial;
-	int result;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	if (count == 0) {
-		dbg("%s - write request of 0 bytes", __FUNCTION__);
-		return (0);
-	}
-
-	/* only do something if we have a bulk out endpoint */
-	if (serial->num_bulk_out) {
-		if (port->write_urb->status == -EINPROGRESS) {
-			dbg("%s - already writing", __FUNCTION__);
-			return (0);
-		}
-
-		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-
-		if (from_user) {
-			if (copy_from_user(port->write_urb->transfer_buffer, buf, count))
-				return -EFAULT;
-		}
-		else {
-			memcpy (port->write_urb->transfer_buffer, buf, count);
-		}
-
-		usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
-
-		/* set up our urb */
-		usb_fill_bulk_urb (port->write_urb, serial->dev,
-				   usb_sndbulkpipe (serial->dev,
-						    port->bulk_out_endpointAddress),
-				   port->write_urb->transfer_buffer, count,
-				   ((serial->type->write_bulk_callback) ? 
-				     serial->type->write_bulk_callback :
-				     generic_write_bulk_callback), port);
-
-		/* send the data out the bulk port */
-		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
-		if (result)
-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
-		else
-			result = count;
-
-		return result;
-	}
-
-	/* no bulk out, so return 0 bytes written */
-	return (0);
-}
-
-static int generic_write_room (struct usb_serial_port *port)
-{
-	struct usb_serial *serial = port->serial;
-	int room = 0;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-	
-	if (serial->num_bulk_out) {
-		if (port->write_urb->status != -EINPROGRESS)
-			room = port->bulk_out_size;
-	}
-
-	dbg("%s - returns %d", __FUNCTION__, room);
-	return (room);
-}
-
-static int generic_chars_in_buffer (struct usb_serial_port *port)
-{
-	struct usb_serial *serial = port->serial;
-	int chars = 0;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	if (serial->num_bulk_out) {
-		if (port->write_urb->status == -EINPROGRESS)
-			chars = port->write_urb->transfer_buffer_length;
-	}
-
-	dbg("%s - returns %d", __FUNCTION__, chars);
-	return (chars);
-}
-
-static void generic_read_bulk_callback (struct urb *urb)
-{
-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
-	struct tty_struct *tty;
-	unsigned char *data = urb->transfer_buffer;
-	int i;
-	int result;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	if (!serial) {
-		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
-		return;
-	}
-
-	if (urb->status) {
-		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
-		return;
-	}
-
-	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
-
-	tty = port->tty;
-	if (tty && urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless tty->low_latency is set */
-			tty_insert_flip_char(tty, data[i], 0);
-		}
-	  	tty_flip_buffer_push(tty);
-	}
-
-	/* Continue trying to always read  */
-	usb_fill_bulk_urb (port->read_urb, serial->dev,
-			   usb_rcvbulkpipe (serial->dev,
-				   	    port->bulk_in_endpointAddress),
-			   port->read_urb->transfer_buffer,
-			   port->read_urb->transfer_buffer_length,
-			   ((serial->type->read_bulk_callback) ? 
-			     serial->type->read_bulk_callback : 
-			     generic_read_bulk_callback), port);
-	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-	if (result)
-		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-}
-
-static void generic_write_bulk_callback (struct urb *urb)
-{
-	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	if (!serial) {
-		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
-		return;
-	}
-
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
-		return;
-	}
-
-	usb_serial_port_softint((void *)port);
-
-	schedule_work(&port->work);
-}
-
-static void generic_shutdown (struct usb_serial *serial)
-{
-	int i;
-
-	dbg("%s", __FUNCTION__);
-
-	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
-		generic_cleanup (&serial->port[i]);
-	}
-}
-
 void usb_serial_port_softint(void *private)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)private;
@@ -1268,7 +950,6 @@
 	     (dev->descriptor.idProduct == PL2303_PRODUCT_ID)) ||
 	    ((dev->descriptor.idVendor == ATEN_VENDOR_ID) &&
 	     (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) {
-		//if (ifnum == 1) {
 		if (interface != &dev->actconfig->interface[0]) {
 			/* check out the endpoints of the other interface*/
 			//interface = &dev->actconfig->interface[ifnum ^ 1];
@@ -1303,7 +984,7 @@
 	info("%s converter detected", type->name);
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
-	if (type == &generic_device) {
+	if (type == &usb_serial_generic_device) {
 		num_ports = num_bulk_out;
 		if (num_ports == 0) {
 			err("Generic device with no bulk out, not allowed.");
@@ -1359,7 +1040,7 @@
 				   port->bulk_in_buffer, buffer_size,
 				   ((serial->type->read_bulk_callback) ? 
 				     serial->type->read_bulk_callback : 
-				     generic_read_bulk_callback),
+				     usb_serial_generic_read_bulk_callback),
 				   port);
 	}
 
@@ -1385,7 +1066,7 @@
 				   port->bulk_out_buffer, buffer_size, 
 				   ((serial->type->write_bulk_callback) ? 
 				     serial->type->write_bulk_callback : 
-				     generic_write_bulk_callback),
+				     usb_serial_generic_write_bulk_callback),
 				   port);
 	}
 
@@ -1504,10 +1185,10 @@
 			port = &serial->port[i];
 			down (&port->sem);
 			if (port->tty != NULL) {
+				port->tty->driver_data = NULL;
 				while (port->open_count > 0) {
 					__serial_close(port, NULL);
 				}
-				port->tty->driver_data = NULL;
 			}
 			up (&port->sem);
 		}
@@ -1607,7 +1288,7 @@
 	}
 
 	/* register the generic driver, if we should */
-	result = generic_register();
+	result = usb_serial_generic_register(debug);
 	if (result < 0) {
 		err("%s - registering generic driver failed", __FUNCTION__);
 		goto exit;
@@ -1637,7 +1318,7 @@
 	tty_unregister_driver(&serial_tty_driver);
 
 exit_generic:
-	generic_deregister();
+	usb_serial_generic_deregister();
 
 exit:
 	err ("%s - returning with error %d", __FUNCTION__, result);
@@ -1649,7 +1330,7 @@
 {
 	usb_serial_console_exit();
 
-	generic_deregister();
+	usb_serial_generic_deregister();
 
 	usb_deregister(&usb_serial_driver);
 	tty_unregister_driver(&serial_tty_driver);
@@ -1699,12 +1380,6 @@
 EXPORT_SYMBOL(usb_serial_probe);
 EXPORT_SYMBOL(usb_serial_disconnect);
 EXPORT_SYMBOL(usb_serial_port_softint);
-#ifdef USES_EZUSB_FUNCTIONS
-	EXPORT_SYMBOL(ezusb_writememory);
-	EXPORT_SYMBOL(ezusb_set_reset);
-#endif
-
-
 
 
 /* Module information */
@@ -1714,11 +1389,3 @@
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-#ifdef CONFIG_USB_SERIAL_GENERIC
-MODULE_PARM(vendor, "h");
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-MODULE_PARM(product, "h");
-MODULE_PARM_DESC(product, "User specified USB idProduct");
-#endif
diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h	Wed Nov 27 14:36:32 2002
+++ b/drivers/usb/serial/usb-serial.h	Wed Nov 27 14:36:32 2002
@@ -237,24 +237,8 @@
 extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
 extern void usb_serial_disconnect(struct usb_interface *iface);
 
-/* determine if we should include the EzUSB loader functions */
-#undef USES_EZUSB_FUNCTIONS
-#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE)
-	#define USES_EZUSB_FUNCTIONS
-#endif
-#if defined(CONFIG_USB_SERIAL_XIRCOM) || defined(CONFIG_USB_SERIAL_XIRCOM_MODULE)
-	#define USES_EZUSB_FUNCTIONS
-#endif
-#if defined(CONFIG_USB_SERIAL_KEYSPAN) || defined(CONFIG_USB_SERIAL_KEYSPAN_MODULE)
-	#define USES_EZUSB_FUNCTIONS
-#endif
-#if defined(CONFIG_USB_SERIAL_WHITEHEAT) || defined(CONFIG_USB_SERIAL_WHITEHEAT_MODULE)
-	#define USES_EZUSB_FUNCTIONS
-#endif
-#ifdef USES_EZUSB_FUNCTIONS
 extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest);
 extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
-#endif
 
 /* USB Serial console functions */
 #ifdef CONFIG_USB_SERIAL_CONSOLE
@@ -265,10 +249,20 @@
 static inline void usb_serial_console_exit (void) { }
 #endif
 
-/* Functions needed by the usb serial console code */
+/* Functions needed by other parts of the usbserial core */
 extern struct usb_serial *usb_serial_get_by_minor (unsigned int minor);
 extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_write_room (struct usb_serial_port *port);
+extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
+extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
+extern void usb_serial_generic_write_bulk_callback (struct urb *urb);
+extern void usb_serial_generic_shutdown (struct usb_serial *serial);
+extern int usb_serial_generic_register (int debug);
+extern void usb_serial_generic_deregister (void);
+
+extern struct usb_serial_device_type usb_serial_generic_device;
 
 /* 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 -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/usb/serial/visor.c	Wed Nov 27 14:36:28 2002
@@ -186,6 +186,7 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
@@ -209,6 +210,7 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
diff -Nru a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
--- a/drivers/usb/serial/visor.h	Wed Nov 27 14:36:28 2002
+++ b/drivers/usb/serial/visor.h	Wed Nov 27 14:36:28 2002
@@ -28,6 +28,7 @@
 #define PALM_M125_ID			0x0040
 #define PALM_M130_ID			0x0050
 #define PALM_TUNGSTEN_T_ID		0x0060
+#define PALM_TUNGSTEN_Z_ID		0x0031
 #define PALM_ZIRE_ID			0x0070
 
 #define SONY_VENDOR_ID			0x054C
diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
--- a/drivers/usb/serial/whiteheat.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/usb/serial/whiteheat.c	Wed Nov 27 14:36:28 2002
@@ -202,10 +202,23 @@
 #define THROTTLED		0x01
 #define ACTUALLY_THROTTLED	0x02
 
+static int urb_pool_size = 8;
+
+struct whiteheat_urb_wrap {
+	struct list_head	list;
+	struct urb		*urb;
+};
+
 struct whiteheat_private {
 	spinlock_t		lock;
 	__u8			flags;
 	__u8			mcr;
+	struct list_head	rx_urbs_free;
+	struct list_head	rx_urbs_submitted;
+	struct list_head	rx_urb_q;
+	struct work_struct	rx_work;
+	struct list_head	tx_urbs_free;
+	struct list_head	tx_urbs_submitted;
 };
 
 
@@ -215,6 +228,11 @@
 static void command_port_write_callback(struct urb *urb);
 static void command_port_read_callback(struct urb *urb);
 
+static int start_port_read(struct usb_serial_port *port);
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
+static struct list_head *list_first(struct list_head *head);
+static void rx_data_softint(void *private);
+
 static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize);
 static int firm_open(struct usb_serial_port *port);
 static int firm_close(struct usb_serial_port *port);
@@ -330,6 +348,11 @@
 	__u8 command[2] = { WHITEHEAT_GET_HW_INFO, 0 };
 	__u8 result[sizeof(*hw_info) + 1];
 	int i;
+	int j;
+	struct urb *urb;
+	int buf_size;
+	struct whiteheat_urb_wrap *wrap;
+	struct list_head *tmp;
 
 	command_port = &serial->port[COMMAND_PORT];
 
@@ -373,18 +396,80 @@
 		port = &serial->port[i];
 
 		info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
-		if (info == NULL)
-			goto no_memory;
+		if (info == NULL) {
+			err("%s: Out of memory for port structures\n", serial->type->name);
+			goto no_private;
+		}
 
 		spin_lock_init(&info->lock);
 		info->flags = 0;
 		info->mcr = 0;
+		INIT_WORK(&info->rx_work, rx_data_softint, port);
+
+		INIT_LIST_HEAD(&info->rx_urbs_free);
+		INIT_LIST_HEAD(&info->rx_urbs_submitted);
+		INIT_LIST_HEAD(&info->rx_urb_q);
+		INIT_LIST_HEAD(&info->tx_urbs_free);
+		INIT_LIST_HEAD(&info->tx_urbs_submitted);
+
+		for (j = 0; j < urb_pool_size; j++) {
+			urb = usb_alloc_urb(0, GFP_KERNEL);
+			if (!urb) {
+				err("No free urbs available");
+				goto no_rx_urb;
+			}
+			buf_size = port->read_urb->transfer_buffer_length;
+			urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
+			if (!urb->transfer_buffer) {
+				err("Couldn't allocate urb buffer");
+				goto no_rx_buf;
+			}
+			wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
+			if (!wrap) {
+				err("Couldn't allocate urb wrapper");
+				goto no_rx_wrap;
+			}
+			usb_fill_bulk_urb(urb, serial->dev,
+					usb_rcvbulkpipe(serial->dev,
+						port->bulk_in_endpointAddress),
+					urb->transfer_buffer, buf_size,
+					whiteheat_read_callback, port);
+			wrap->urb = urb;
+			list_add(&wrap->list, &info->rx_urbs_free);
+
+			urb = usb_alloc_urb(0, GFP_KERNEL);
+			if (!urb) {
+				err("No free urbs available");
+				goto no_tx_urb;
+			}
+			buf_size = port->write_urb->transfer_buffer_length;
+			urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL);
+			if (!urb->transfer_buffer) {
+				err("Couldn't allocate urb buffer");
+				goto no_tx_buf;
+			}
+			wrap = kmalloc(sizeof(*wrap), GFP_KERNEL);
+			if (!wrap) {
+				err("Couldn't allocate urb wrapper");
+				goto no_tx_wrap;
+			}
+			usb_fill_bulk_urb(urb, serial->dev,
+					usb_sndbulkpipe(serial->dev,
+						port->bulk_out_endpointAddress),
+					urb->transfer_buffer, buf_size,
+					whiteheat_write_callback, port);
+			wrap->urb = urb;
+			list_add(&wrap->list, &info->tx_urbs_free);
+		}
+
 		port->private = info;
 	}
 
 	command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
-	if (command_info == NULL)
-		goto no_memory;
+	if (command_info == NULL) {
+		err("%s: Out of memory for port structures\n", serial->type->name);
+		goto no_command_private;
+	}
 
 	spin_lock_init(&command_info->lock);
 	command_info->port_running = 0;
@@ -402,12 +487,35 @@
 	err("%s: please contact support@connecttech.com\n", serial->type->name);
 	return -ENODEV;
 
-no_memory:
-	for (i--; i >= 0; i--) {
+no_command_private:
+	for (i = serial->num_ports - 1; i >= 0; i--) {
 		port = &serial->port[i];
-		kfree(port->private);
+		info = port->private;
+		for (j = urb_pool_size - 1; j >= 0; j--) {
+			tmp = list_first(&info->tx_urbs_free);
+			list_del(tmp);
+			wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+			urb = wrap->urb;
+			kfree(wrap);
+no_tx_wrap:
+			kfree(urb->transfer_buffer);
+no_tx_buf:
+			usb_free_urb(urb);
+no_tx_urb:
+			tmp = list_first(&info->rx_urbs_free);
+			list_del(tmp);
+			wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+			urb = wrap->urb;
+			kfree(wrap);
+no_rx_wrap:
+			kfree(urb->transfer_buffer);
+no_rx_buf:
+			usb_free_urb(urb);
+no_rx_urb:
+		}
+		kfree(info);
+no_private:
 	}
-	err("%s: Out of memory for port structures\n", serial->type->name);
 	return -ENOMEM;
 }
 
@@ -416,6 +524,11 @@
 {
 	struct usb_serial_port *command_port;
 	struct usb_serial_port *port;
+	struct whiteheat_private *info;
+	struct whiteheat_urb_wrap *wrap;
+	struct urb *urb;
+	struct list_head *tmp;
+	struct list_head *tmp2;
 	int i;
 
 	dbg("%s", __FUNCTION__);
@@ -423,12 +536,27 @@
 	/* free up our private data for our command port */
 	command_port = &serial->port[COMMAND_PORT];
 	kfree (command_port->private);
-	command_port->private = NULL;
 
 	for (i = 0; i < serial->num_ports; i++) {
 		port = &serial->port[i];
-		kfree(port->private);
-		port->private = NULL;
+		info = port->private;
+		list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
+			list_del(tmp);
+			wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+			urb = wrap->urb;
+			kfree(wrap);
+			kfree(urb->transfer_buffer);
+			usb_free_urb(urb);
+		}
+		list_for_each_safe(tmp, tmp2, &info->tx_urbs_free) {
+			list_del(tmp);
+			wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+			urb = wrap->urb;
+			kfree(wrap);
+			kfree(urb->transfer_buffer);
+			usb_free_urb(urb);
+		}
+		kfree(info);
 	}
 
 	return;
@@ -446,6 +574,9 @@
 	if (retval)
 		goto exit;
 
+	if (port->tty)
+		port->tty->low_latency = 1;
+
 	/* send an open port command */
 	retval = firm_open(port);
 	if (retval) {
@@ -469,8 +600,7 @@
 	usb_clear_halt(port->serial->dev, port->write_urb->pipe);
 
 	/* Start reading from the device */
-	port->read_urb->dev = port->serial->dev;
-	retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	retval = start_port_read(port);
 	if (retval) {
 		err("%s - failed submitting read urb, error %d", __FUNCTION__, retval);
 		firm_close(port);
@@ -486,6 +616,13 @@
 
 static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
 {
+	struct whiteheat_private *info = port->private;
+	struct whiteheat_urb_wrap *wrap;
+	struct urb *urb;
+	struct list_head *tmp;
+	struct list_head *tmp2;
+	unsigned long flags;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	/* filp is NULL when called from usb_serial_disconnect */
@@ -515,8 +652,26 @@
 	firm_close(port);
 
 	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (port->write_urb);
-	usb_unlink_urb (port->read_urb);
+	spin_lock_irqsave(&info->lock, flags);
+	list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
+		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+		urb = wrap->urb;
+		usb_unlink_urb(urb);
+		list_del(tmp);
+		list_add(tmp, &info->rx_urbs_free);
+	}
+	list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
+		list_del(tmp);
+		list_add(tmp, &info->rx_urbs_free);
+	}
+	list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
+		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+		urb = wrap->urb;
+		usb_unlink_urb(urb);
+		list_del(tmp);
+		list_add(tmp, &info->tx_urbs_free);
+	}
+	spin_unlock_irqrestore(&info->lock, flags);
 
 	stop_command_port(port->serial);
 
@@ -527,7 +682,14 @@
 static int whiteheat_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
+	struct whiteheat_private *info = port->private;
+	struct whiteheat_urb_wrap *wrap;
+	struct urb *urb;
 	int result;
+	int bytes;
+	int sent = 0;
+	unsigned long flags;
+	struct list_head *tmp;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -536,43 +698,65 @@
 		return (0);
 	}
 
-	if (port->write_urb->status == -EINPROGRESS) {
-		dbg ("%s - already writing", __FUNCTION__);
-		return (0);
-	}
-
-	count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+	while (count) {
+		spin_lock_irqsave(&info->lock, flags);
+		if (list_empty(&info->tx_urbs_free)) {
+			spin_unlock_irqrestore(&info->lock, flags);
+			break;
+		}
+		tmp = list_first(&info->tx_urbs_free);
+		list_del(tmp);
+		spin_unlock_irqrestore(&info->lock, flags);
 
-	if (from_user) {
-		if (copy_from_user(port->write_urb->transfer_buffer, buf, count))
-			return -EFAULT;
-	}
-	else {
-		memcpy (port->write_urb->transfer_buffer, buf, count);
-	}
+		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+		urb = wrap->urb;
+		bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+		if (from_user) {
+			if (copy_from_user(urb->transfer_buffer, buf + sent, bytes))
+				return -EFAULT;
+		} else {
+			memcpy (urb->transfer_buffer, buf + sent, bytes);
+		}
 
-	usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+		usb_serial_debug_data (__FILE__, __FUNCTION__, bytes, urb->transfer_buffer);
 
-	port->write_urb->dev = serial->dev;
-	port->write_urb->transfer_buffer_length = count;
-	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
-	if (result)
-		err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
-	else
-		result = count;
+		urb->dev = serial->dev;
+		urb->transfer_buffer_length = bytes;
+		result = usb_submit_urb(urb, GFP_ATOMIC);
+		if (result) {
+			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+			sent = result;
+			spin_lock_irqsave(&info->lock, flags);
+			list_add(tmp, &info->tx_urbs_free);
+			spin_unlock_irqrestore(&info->lock, flags);
+			break;
+		} else {
+			sent += bytes;
+			count -= bytes;
+			spin_lock_irqsave(&info->lock, flags);
+			list_add(tmp, &info->tx_urbs_submitted);
+			spin_unlock_irqrestore(&info->lock, flags);
+		}
+	}
 
-	return result;
+	return sent;
 }
 
 
 static int whiteheat_write_room(struct usb_serial_port *port)
 {
+	struct whiteheat_private *info = port->private;
+	struct list_head *tmp;
 	int room = 0;
+	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	
-	if (port->write_urb->status != -EINPROGRESS)
-		room = port->bulk_out_size;
+	spin_lock_irqsave(&info->lock, flags);
+	list_for_each(tmp, &info->tx_urbs_free)
+		room++;
+	spin_unlock_irqrestore(&info->lock, flags);
+	room *= port->bulk_out_size;
 
 	dbg("%s - returns %d", __FUNCTION__, room);
 	return (room);
@@ -715,12 +899,20 @@
 
 static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
 {
+	struct whiteheat_private *info = port->private;
+	struct list_head *tmp;
+	struct whiteheat_urb_wrap *wrap;
 	int chars = 0;
+	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	if (port->write_urb->status == -EINPROGRESS)
-		chars = port->write_urb->transfer_buffer_length;
+	spin_lock_irqsave(&info->lock, flags);
+	list_for_each(tmp, &info->tx_urbs_submitted) {
+		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+		chars += wrap->urb->transfer_buffer_length;
+	}
+	spin_unlock_irqrestore(&info->lock, flags);
 
 	dbg ("%s - returns %d", __FUNCTION__, chars);
 	return (chars);
@@ -745,25 +937,19 @@
 static void whiteheat_unthrottle (struct usb_serial_port *port)
 {
 	struct whiteheat_private *info = (struct whiteheat_private *)port->private;
-	int result;
+	int actually_throttled;
 	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	spin_lock_irqsave(&info->lock, flags);
-
-	if (info->flags & ACTUALLY_THROTTLED) {
-		/* Continue trying to always read  */
-		port->read_urb->dev = port->serial->dev;
-		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-		if (result)
-			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
-	}
-
+	actually_throttled = info->flags & ACTUALLY_THROTTLED;
 	info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
-
 	spin_unlock_irqrestore(&info->lock, flags);
 
+	if (actually_throttled)
+		rx_data_softint(port);
+
 	return;
 }
 
@@ -846,53 +1032,50 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
-	struct tty_struct *tty;
+	struct whiteheat_urb_wrap *wrap;
 	unsigned char *data = urb->transfer_buffer;
-	int i;
-	int result;
 	struct whiteheat_private *info = (struct whiteheat_private *)port->private;
-	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	spin_lock(&info->lock);
+	wrap = urb_to_wrap(urb, &info->rx_urbs_submitted);
+	if (!wrap) {
+		spin_unlock(&info->lock);
+		err("%s - Not my urb!", __FUNCTION__);
+		return;
+	}
+	list_del(&wrap->list);
+	spin_unlock(&info->lock);
+
 	if (!serial) {
 		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+		spin_lock(&info->lock);
+		list_add(&wrap->list, &info->rx_urbs_free);
+		spin_unlock(&info->lock);
 		return;
 	}
 
 	if (urb->status) {
 		dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+		spin_lock(&info->lock);
+		list_add(&wrap->list, &info->rx_urbs_free);
+		spin_unlock(&info->lock);
 		return;
 	}
 
 	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 
-	tty = port->tty;
-	if (tty && urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* this doesn't actually push the data through unless tty->low_latency is set */
-			tty_insert_flip_char(tty, data[i], 0);
-		}
-	  	tty_flip_buffer_push(tty);
-	}
-
-	spin_lock_irqsave(&info->lock, flags);
+	spin_lock(&info->lock);
+	list_add_tail(&wrap->list, &info->rx_urb_q);
 	if (info->flags & THROTTLED) {
 		info->flags |= ACTUALLY_THROTTLED;
-		spin_unlock_irqrestore(&info->lock, flags);
+		spin_unlock(&info->lock);
 		return;
 	}
-	spin_unlock_irqrestore(&info->lock, flags);
+	spin_unlock(&info->lock);
 
-	/* Continue trying to always read  */
-	port->read_urb->dev = serial->dev;
-	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-	if (result)
-		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+	schedule_work(&info->rx_work);
 }
 
 
@@ -900,9 +1083,22 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+	struct whiteheat_private *info = port->private;
+	struct whiteheat_urb_wrap *wrap;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	spin_lock(&info->lock);
+	wrap = urb_to_wrap(urb, &info->tx_urbs_submitted);
+	if (!wrap) {
+		spin_unlock(&info->lock);
+		err("%s - Not my urb!", __FUNCTION__);
+		return;
+	}
+	list_del(&wrap->list);
+	list_add(&wrap->list, &info->tx_urbs_free);
+	spin_unlock(&info->lock);
+
 	if (!serial) {
 		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
 		return;
@@ -1176,6 +1372,122 @@
 }
 
 
+static int start_port_read(struct usb_serial_port *port) {
+	struct whiteheat_private *info = port->private;
+	struct whiteheat_urb_wrap *wrap;
+	struct urb *urb;
+	int retval = 0;
+	unsigned long flags;
+	struct list_head *tmp;
+	struct list_head *tmp2;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
+		list_del(tmp);
+		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+		urb = wrap->urb;
+		urb->dev = port->serial->dev;
+		retval = usb_submit_urb(urb, GFP_KERNEL);
+		if (retval) {
+			list_add(tmp, &info->rx_urbs_free);
+			list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
+				wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+				urb = wrap->urb;
+				usb_unlink_urb(urb);
+				list_del(tmp);
+				list_add(tmp, &info->rx_urbs_free);
+			}
+			break;
+		}
+		list_add(tmp, &info->rx_urbs_submitted);
+	}
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	return retval;
+}
+
+
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head) {
+	struct whiteheat_urb_wrap *wrap;
+	struct list_head *tmp;
+
+	list_for_each(tmp, head) {
+		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+		if (wrap->urb == urb)
+			return wrap;
+	}
+
+	return NULL;
+}
+
+
+static struct list_head *list_first(struct list_head *head) {
+	return head->next;
+}
+
+
+static void rx_data_softint(void *private) {
+	struct usb_serial_port *port = (struct usb_serial_port *)private;
+	struct whiteheat_private *info = port->private;
+	struct tty_struct *tty = port->tty;
+	struct whiteheat_urb_wrap *wrap;
+	struct urb *urb;
+	unsigned long flags;
+	struct list_head *tmp;
+	struct list_head *tmp2;
+	int result;
+	int sent = 0;
+
+	spin_lock_irqsave(&info->lock, flags);
+	if (info->flags & THROTTLED) {
+		spin_unlock_irqrestore(&info->lock, flags);
+		return;
+	}
+
+	list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
+		list_del(tmp);
+		spin_unlock_irqrestore(&info->lock, flags);
+
+		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
+		urb = wrap->urb;
+
+		if (tty && urb->actual_length) {
+			if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) {
+				spin_lock_irqsave(&info->lock, flags);
+				list_add(tmp, &info->rx_urb_q);
+				spin_unlock_irqrestore(&info->lock, flags);
+				tty_flip_buffer_push(tty);
+				schedule_work(&info->rx_work);
+				return;
+			}
+
+			memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length);
+			tty->flip.char_buf_ptr += urb->actual_length;
+			tty->flip.count += urb->actual_length;
+			sent += urb->actual_length;
+		}
+
+		urb->dev = port->serial->dev;
+		result = usb_submit_urb(urb, GFP_ATOMIC);
+		if (result) {
+			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+			spin_lock_irqsave(&info->lock, flags);
+			list_add(tmp, &info->rx_urbs_free);
+			continue;
+		}
+
+		spin_lock_irqsave(&info->lock, flags);
+		list_add(tmp, &info->rx_urbs_submitted);
+	}
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	if (sent)
+		tty_flip_buffer_push(tty);
+}
+
+
 /*****************************************************************************
  * Connect Tech's White Heat module functions
  *****************************************************************************/
@@ -1203,6 +1515,9 @@
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
+
+MODULE_PARM(urb_pool_size, "i");
+MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering");
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -Nru a/drivers/video/68328fb.c b/drivers/video/68328fb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/video/68328fb.c	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,986 @@
+/*
+ * linux/arch/m68knommu/console/68328fb.c -- Low level implementation of the
+ *                                           mc68328 LCD frame buffer device
+ *
+ *    Copyright (C) 1998,1999 Kenneth Albanowski <kjahds@kjahds.com>,
+ *                            The Silver Hammer Group, Ltd.
+ *
+ *
+ * This file is based on the Amiga CyberVision frame buffer device (Cyberfb.c):
+ *
+ *    Copyright (C) 1996 Martin Apel
+ *                       Geert Uytterhoeven
+ *
+ *
+ * This file is based on the Amiga frame buffer device (amifb.c):
+ *
+ *    Copyright (C) 1995 Geert Uytterhoeven
+ *
+ *
+ * History:
+ *   - 17 Feb 98: Original version by Kenneth Albanowski <kjahds@kjahds.com>
+ *
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <linux/fb.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+
+
+#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
+
+struct mc68328_fb_par {
+   int xres;
+   int yres;
+   int bpp;
+};
+
+static struct mc68328_fb_par current_par;
+
+static int current_par_valid = 0;
+static int currcon = 0;
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+
+static int node;        /* node of the /dev/fb?current file */
+
+
+   /*
+    *    Switch for Chipset Independency
+    */
+
+static struct fb_hwswitch {
+
+   /* Initialisation */
+
+   int (*init)(void);
+
+   /* Display Control */
+
+   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct mc68328_fb_par *par);
+   int (*decode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);
+   int (*encode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);
+   int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
+                    u_int *transp);
+   int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
+                    u_int transp);
+   void (*blank)(int blank);
+} *fbhw;
+
+
+   /*
+    *    Frame Buffer Name
+    */
+
+static char mc68328_fb_name[16] = "mc68328";
+
+
+   /*
+    *    mc68328vision Graphics Board
+    */
+
+#define CYBER8_WIDTH 1152
+#define CYBER8_HEIGHT 886
+#define CYBER8_PIXCLOCK 12500    /* ++Geert: Just a guess */
+
+#define CYBER16_WIDTH 800
+#define CYBER16_HEIGHT 600
+#define CYBER16_PIXCLOCK 25000   /* ++Geert: Just a guess */
+
+#define PALM_WIDTH 160
+#define PALM_HEIGHT 160
+
+
+/*static int mc68328Key = 0;
+static u_char mc68328_colour_table [256][4];*/
+static unsigned long mc68328Mem;
+static unsigned long mc68328Size;
+
+
+   /*
+    *    Predefined Video Mode Names
+    */
+
+static char *mc68328_fb_modenames[] = {
+
+   /*
+    *    Autodetect (Default) Video Mode
+    */
+
+   "default",
+
+   /*
+    *    Predefined Video Modes
+    */
+    
+   "Palm",            /* Palm Pilot devices, 1.0 and higher */
+   "Palm Grey",            /* Palm Pilot devices, 1.0 and higher */
+
+   /*
+    *    Dummy Video Modes
+    */
+
+   "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+   "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+   "dummy", "dummy", "dummy", "dummy",
+
+   /*
+    *    User Defined Video Modes
+    *
+    *    This doesn't work yet!!
+    */
+
+   "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"
+};
+
+
+   /*
+    *    Predefined Video Mode Definitions
+    */
+
+static struct fb_var_screeninfo mc68328_fb_predefined[] = {
+
+   /*
+    *    Autodetect (Default) Video Mode
+    */
+
+   { 0, },
+
+   /*
+    *    Predefined Video Modes
+    */
+    
+   {
+      /* Palm */
+      PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT, 
+      0, 0, 
+      1, -1,
+      {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0},
+      0, 0, 
+      -1, -1, /* phys height, width */
+      FB_ACCEL_NONE, 
+      0, 0, 0, 0, 0, 0, 0, /* timing */
+      0, /* sync */
+      FB_VMODE_NONINTERLACED
+   },
+   {
+      /* Palm Grey */
+      PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT, 
+      0, 0, 
+      2, -1,
+      {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
+      0, 0, 
+      -1, -1, /* phys height, width */
+      FB_ACCEL_NONE, 
+      0, 0, 0, 0, 0, 0, 0, /* timing */
+      0, /* sync */
+      FB_VMODE_NONINTERLACED
+   },
+
+   /*
+    *    Dummy Video Modes
+    */
+
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+   { 0, }, { 0, },
+
+   /*
+    *    User Defined Video Modes
+    */
+
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
+};
+
+
+#define NUM_TOTAL_MODES    arraysize(mc68328_fb_predefined)
+#define NUM_PREDEF_MODES   (3)
+
+
+static int mc68328fb_inverse = 0;
+static int mc68328fb_mode = 0;
+static int mc68328fbCursorMode = 0;
+
+
+   /*
+    *    Some default modes
+    */
+
+#define PALM_DEFMODE     (1)
+#define CYBER16_DEFMODE    (2)
+
+
+   /*
+    *    Interface used by the world
+    */
+
+static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+		struct fb_info *info);
+static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con,
+		struct fb_info *info);
+static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con,
+		struct fb_info *info);
+static int mc68328_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+		struct fb_info *info);
+static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con,
+		struct fb_info *info);
+static int mc68328_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		u_long arg, int con, struct fb_info *info);
+
+
+   /*
+    *    Interface to the low level console driver
+    */
+
+int mc68328_fb_init(void);
+static int mc68328fb_switch(int con, struct fb_info *info);
+static int mc68328fb_updatevar(int con);
+static void mc68328fb_blank(int blank);
+
+
+   /*
+    *    Accelerated Functions used by the low level console driver
+    */
+
+void mc68328_WaitQueue(u_short fifo);
+void mc68328_WaitBlit(void);
+void mc68328_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
+                  u_short width, u_short height, u_short mode);
+void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height,
+                    u_short mode, u_short color);
+void mc68328_MoveCursor(u_short x, u_short y);
+
+
+   /*
+    *   Hardware Specific Routines
+    */
+
+static int mc68328_init(void);
+static int mc68328_encode_fix(struct fb_fix_screeninfo *fix,
+                          struct mc68328_fb_par *par);
+static int mc68328_decode_var(struct fb_var_screeninfo *var,
+                          struct mc68328_fb_par *par);
+static int mc68328_encode_var(struct fb_var_screeninfo *var,
+                          struct mc68328_fb_par *par);
+static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp);
+static int mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp);
+static void mc68328_blank(int blank);
+
+
+   /*
+    *    Internal routines
+    */
+
+static void mc68328_fb_get_par(struct mc68328_fb_par *par);
+static void mc68328_fb_set_par(struct mc68328_fb_par *par);
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
+static struct fb_cmap *get_default_colormap(int bpp);
+static void memcpy_fs(int fsfromto, void *to, void *from, int len);
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
+static void mc68328_fb_set_disp(int con, struct fb_info *info);
+static int get_video_mode(const char *name);
+
+
+/* -------------------- Hardware specific routines -------------------------- */
+
+
+   /*
+    *    Initialization
+    *
+    *    Set the default video mode for this chipset. If a video mode was
+    *    specified on the command line, it will override the default mode.
+    */
+
+static int mc68328_init(void)
+{
+	/*int i;
+	char size;
+	volatile u_long *CursorBase;
+	unsigned long board_addr;
+	struct ConfigDev *cd;*/
+
+	if (mc68328fb_mode == -1)
+		mc68328fb_mode = PALM_DEFMODE;
+
+	mc68328Mem = (*(volatile unsigned long*)0xFFFFFA00);
+	/*kernel_map (board_addr + 0x01400000, 0x00400000,*/
+	mc68328Size = 160*160/8;
+
+	return (0);
+}
+
+
+   /*
+    *    This function should fill in the `fix' structure based on the
+    *    values in the `par' structure.
+    */
+
+static int mc68328_encode_fix(struct fb_fix_screeninfo *fix,
+                          struct mc68328_fb_par *par)
+{
+   int i;
+
+   strcpy(fix->id, mc68328_fb_name);
+   fix->smem_start = mc68328Mem;
+   fix->smem_len = mc68328Size;
+
+   fix->type = FB_TYPE_PACKED_PIXELS;
+   fix->type_aux = 0;
+   if (par->bpp == 1)
+      fix->visual = FB_VISUAL_MONO01;
+   else
+      fix->visual = FB_VISUAL_DIRECTCOLOR;
+
+   fix->xpanstep = 0;
+   fix->ypanstep = 0;
+   fix->ywrapstep = 0;
+
+   for (i = 0; i < arraysize(fix->reserved); i++)
+      fix->reserved[i] = 0;
+
+   fix->accel = FB_ACCEL_NONE;
+
+   return(0);
+}
+
+
+   /*
+    *    Get the video params out of `var'. If a value doesn't fit, round
+    *    it up, if it's too big, return -EINVAL.
+    */
+
+static int mc68328_decode_var(struct fb_var_screeninfo *var,
+                          struct mc68328_fb_par *par)
+{
+   par->xres = PALM_WIDTH;
+   par->yres = PALM_HEIGHT;
+   par->bpp = 1;
+   return(0);
+}
+
+
+   /*
+    *    Fill the `var' structure based on the values in `par' and maybe
+    *    other values read out of the hardware.
+    */
+
+static int mc68328_encode_var(struct fb_var_screeninfo *var,
+                          struct mc68328_fb_par *par)
+{
+   int i;
+
+   var->xres = par->xres;
+   var->yres = par->yres;
+   var->xres_virtual = par->xres;
+   var->yres_virtual = par->yres;
+   var->xoffset = 0;
+   var->yoffset = 0;
+
+   var->bits_per_pixel = par->bpp;
+   var->grayscale = -1;
+
+   var->red.offset = 0;
+   var->red.length = par->bpp;
+   var->red.msb_right = 0;
+   var->blue = var->green = var->red;
+
+   var->transp.offset = 0;
+   var->transp.length = 0;
+   var->transp.msb_right = 0;
+
+   var->nonstd = 0;
+   var->activate = 0;
+
+   var->height = -1;
+   var->width = -1;
+   var->vmode = FB_VMODE_NONINTERLACED;
+
+   /* Dummy values */
+
+   var->pixclock = 0;
+   var->sync = 0;
+   var->left_margin = 0;
+   var->right_margin = 0;
+   var->upper_margin = 0;
+   var->lower_margin = 0;
+   var->hsync_len = 0;
+   var->vsync_len = 0;
+
+   for (i = 0; i < arraysize(var->reserved); i++)
+      var->reserved[i] = 0;
+
+   return(0);
+}
+
+
+   /*
+    *    Set a single color register. The values supplied are already
+    *    rounded down to the hardware's capabilities (according to the
+    *    entries in the var structure). Return != 0 for invalid regno.
+    */
+
+static int mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp)
+{
+	return 1;
+#if 0
+if (regno > 255)
+  return (1);
+
+*(mc68328Regs + 0x3c8) = (char)regno;
+mc68328_colour_table [regno][0] = red & 0xff;
+mc68328_colour_table [regno][1] = green & 0xff;
+mc68328_colour_table [regno][2] = blue & 0xff;
+mc68328_colour_table [regno][3] = transp;
+
+*(mc68328Regs + 0x3c9) = (red & 0xff) >> 2;
+*(mc68328Regs + 0x3c9) = (green & 0xff) >> 2;
+*(mc68328Regs + 0x3c9) = (blue & 0xff) >> 2;
+
+return (0);
+#endif
+}
+
+
+   /*
+    *    Read a single color register and split it into
+    *    colors/transparent. Return != 0 for invalid regno.
+    */
+
+static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp)
+{
+	return 1;
+#if 0
+if (regno >= 256)
+  return (1);
+*red    = mc68328_colour_table [regno][0];
+*green  = mc68328_colour_table [regno][1];
+*blue   = mc68328_colour_table [regno][2];
+*transp = mc68328_colour_table [regno][3];
+return (0);
+#endif
+}
+
+
+   /*
+    *    (Un)Blank the screen
+    */
+
+void mc68328_blank(int blank)
+{
+#if 0
+	if (blank)
+		(*(volatile unsigned char*)0xFFFFFA27) &= ~128;
+	else
+		(*(volatile unsigned char*)0xFFFFFA27) |= 128;
+#endif
+}
+
+
+/**************************************************************
+ * We are waiting for "fifo" FIFO-slots empty
+ */
+void mc68328_WaitQueue (u_short fifo)
+{
+}
+
+/**************************************************************
+ * We are waiting for Hardware (Graphics Engine) not busy
+ */
+void mc68328_WaitBlit (void)
+{
+}
+
+/**************************************************************
+ * BitBLT - Through the Plane
+ */
+void mc68328_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty,
+                   u_short width, u_short height, u_short mode)
+{
+#if 0
+u_short blitcmd = S3_BITBLT;
+
+/* Set drawing direction */
+/* -Y, X maj, -X (default) */
+if (curx > destx)
+  blitcmd |= 0x0020;  /* Drawing direction +X */
+else
+  {
+  curx  += (width - 1);
+  destx += (width - 1);
+  }
+
+if (cury > desty)
+  blitcmd |= 0x0080;  /* Drawing direction +Y */
+else
+  {
+  cury  += (height - 1);
+  desty += (height - 1);
+  }
+
+mc68328_WaitQueue (0x8000);
+
+*((u_short volatile *)(mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
+*((u_short volatile *)(mc68328Regs + S3_FRGD_MIX)) = (0x0060 | mode);
+
+*((u_short volatile *)(mc68328Regs + S3_CUR_X)) = curx;
+*((u_short volatile *)(mc68328Regs + S3_CUR_Y)) = cury;
+
+*((u_short volatile *)(mc68328Regs + S3_DESTX_DIASTP)) = destx;
+*((u_short volatile *)(mc68328Regs + S3_DESTY_AXSTP)) = desty;
+
+*((u_short volatile *)(mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1;
+*((u_short volatile *)(mc68328Regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
+
+*((u_short volatile *)(mc68328Regs + S3_CMD)) = blitcmd;
+#endif
+}
+
+/**************************************************************
+ * Rectangle Fill Solid
+ */
+void mc68328_RectFill (u_short x, u_short y, u_short width, u_short height,
+                     u_short mode, u_short color)
+{
+#if 0
+u_short blitcmd = S3_FILLEDRECT;
+
+mc68328_WaitQueue (0x8000);
+
+*((u_short volatile *)(mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
+*((u_short volatile *)(mc68328Regs + S3_FRGD_MIX)) = (0x0020 | mode);
+
+*((u_short volatile *)(mc68328Regs + S3_MULT_MISC)) = 0xe000;
+*((u_short volatile *)(mc68328Regs + S3_FRGD_COLOR)) = color;
+
+*((u_short volatile *)(mc68328Regs + S3_CUR_X)) = x;
+*((u_short volatile *)(mc68328Regs + S3_CUR_Y)) = y;
+
+*((u_short volatile *)(mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1;
+*((u_short volatile *)(mc68328Regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
+
+*((u_short volatile *)(mc68328Regs + S3_CMD)) = blitcmd;
+#endif
+}
+
+
+/**************************************************************
+ * Move cursor to x, y
+ */
+void mc68328_MoveCursor (u_short x, u_short y)
+{
+	(*(volatile unsigned short*)0xFFFFFA18) = (mc68328fbCursorMode << 14) | x;
+	(*(volatile unsigned short*)0xFFFFFA1A) = y;
+#if 0
+*(mc68328Regs + S3_CRTC_ADR)  = 0x39;
+*(mc68328Regs + S3_CRTC_DATA) = 0xa0;
+
+*(mc68328Regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
+*(mc68328Regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
+*(mc68328Regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
+*(mc68328Regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
+
+*(mc68328Regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
+*(mc68328Regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
+*(mc68328Regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
+*(mc68328Regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
+#endif
+}
+
+
+/* -------------------- Interfaces to hardware functions -------------------- */
+
+
+static struct fb_hwswitch mc68328_switch = {
+   mc68328_init, mc68328_encode_fix, mc68328_decode_var, mc68328_encode_var,
+   mc68328_getcolreg, mc68328_setcolreg, mc68328_blank
+};
+
+
+/* -------------------- Generic routines ------------------------------------ */
+
+
+   /*
+    *    Fill the hardware's `par' structure.
+    */
+
+static void mc68328_fb_get_par(struct mc68328_fb_par *par)
+{
+   if (current_par_valid)
+      *par = current_par;
+   else
+      fbhw->decode_var(&mc68328_fb_predefined[mc68328fb_mode], par);
+}
+
+
+static void mc68328_fb_set_par(struct mc68328_fb_par *par)
+{
+   current_par = *par;
+   current_par_valid = 1;
+}
+
+
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+{
+   int err, activate;
+   struct mc68328_fb_par par;
+
+   if ((err = fbhw->decode_var(var, &par)))
+      return(err);
+   activate = var->activate;
+   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
+      mc68328_fb_set_par(&par);
+   fbhw->encode_var(var, &par);
+   var->activate = activate;
+   return(0);
+}
+
+
+   /*
+    *    Default Colormaps
+    */
+
+static u_short red16[] =
+   { 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000,
+     0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff};
+static u_short green16[] =
+   { 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000,
+     0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff};
+static u_short blue16[] =
+   { 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000,
+     0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff};
+
+
+static struct fb_cmap default_16_colors =
+   { 0, 16, red16, green16, blue16, NULL };
+
+
+static struct fb_cmap *get_default_colormap(int bpp)
+{
+   return(&default_16_colors);
+}
+
+
+#define CNVT_TOHW(val,width)     ((((val)<<(width))+0x7fff-(val))>>16)
+#define CNVT_FROMHW(val,width)   (((width) ? ((((val)<<16)-(val)) / \
+                                              ((1<<(width))-1)) : 0))
+
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+   switch (fsfromto) {
+      case 0:
+         memcpy(to, from, len);
+         return;
+      case 1:
+         copy_from_user(to, from, len);
+         return;
+      case 2:
+         copy_to_user(to, from, len);
+         return;
+   }
+}
+
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+   int size;
+   int tooff = 0, fromoff = 0;
+
+   if (to->start > from->start)
+      fromoff = to->start-from->start;
+   else
+      tooff = from->start-to->start;
+   size = to->len-tooff;
+   if (size > from->len-fromoff)
+      size = from->len-fromoff;
+   if (size < 0)
+      return;
+   size *= sizeof(u_short);
+   memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+   memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+   memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+   if (from->transp && to->transp)
+      memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
+}
+
+
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+   int size = len*sizeof(u_short);
+
+   if (cmap->len != len) {
+      if (cmap->red)
+         kfree(cmap->red);
+      if (cmap->green)
+         kfree(cmap->green);
+      if (cmap->blue)
+         kfree(cmap->blue);
+      if (cmap->transp)
+         kfree(cmap->transp);
+      cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
+      cmap->len = 0;
+      if (!len)
+         return(0);
+      if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
+         return(-1);
+      if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
+         return(-1);
+      if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
+         return(-1);
+      if (transp) {
+         if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
+            return(-1);
+      } else
+         cmap->transp = NULL;
+   }
+   cmap->start = 0;
+   cmap->len = len;
+   copy_cmap(get_default_colormap(len), cmap, 0);
+   return(0);
+}
+
+
+   /*
+    *    Get the Fixed Part of the Display
+    */
+
+static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+   struct mc68328_fb_par par;
+   int error = 0;
+
+   if (con == -1)
+      mc68328_fb_get_par(&par);
+   else
+      error = fbhw->decode_var(&disp[con].var, &par);
+   return(error ? error : fbhw->encode_fix(fix, &par));
+}
+
+
+   /*
+    *    Get the User Defined Part of the Display
+    */
+
+static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+   struct mc68328_fb_par par;
+   int error = 0;
+
+   if (con == -1) {
+      mc68328_fb_get_par(&par);
+      error = fbhw->encode_var(var, &par);
+   } else
+      *var = disp[con].var;
+   return(error);
+}
+
+
+static void mc68328_fb_set_disp(int con, struct fb_info *info)
+{
+   struct fb_fix_screeninfo fix;
+
+   mc68328_fb_get_fix(&fix, con, info);
+   if (con == -1)
+      con = 0;
+   info->screen_base = (u_char *)fix.smem_start;
+   disp[con].visual = fix.visual;
+   disp[con].type = fix.type;
+   disp[con].type_aux = fix.type_aux;
+   disp[con].ypanstep = fix.ypanstep;
+   disp[con].ywrapstep = fix.ywrapstep;
+   disp[con].can_soft_blank = 1;
+   disp[con].inverse = mc68328fb_inverse;
+}
+
+
+   /*
+    *    Set the User Defined Part of the Display
+    */
+
+static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+   int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
+
+   if ((err = do_fb_set_var(var, con == currcon)))
+      return(err);
+   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+      oldxres = disp[con].var.xres;
+      oldyres = disp[con].var.yres;
+      oldvxres = disp[con].var.xres_virtual;
+      oldvyres = disp[con].var.yres_virtual;
+      oldbpp = disp[con].var.bits_per_pixel;
+      disp[con].var = *var;
+      if (oldxres != var->xres || oldyres != var->yres ||
+          oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+          oldbpp != var->bits_per_pixel) {
+         mc68328_fb_set_disp(con, info);
+         (*fb_info.changevar)(con);
+         alloc_cmap(&disp[con].cmap, 0, 0);
+         do_install_cmap(con, info);
+      }
+   }
+   var->activate = 0;
+   return(0);
+}
+
+
+   /*
+    *    Get the Colormap
+    */
+
+static int mc68328_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+{
+   if (con == currcon) /* current console? */
+      return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
+   else if (disp[con].cmap.len) /* non default colormap? */
+      copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
+   else
+      copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
+                kspc ? 0 : 2);
+   return(0);
+}
+
+
+
+   /*
+    *    Pan or Wrap the Display
+    *
+    *    This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+    */
+
+static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+   return(-EINVAL);
+}
+
+
+   /*
+    *    mc68328 Frame Buffer Specific ioctls
+    */
+
+static int mc68328_fb_ioctl(struct inode *inode, struct file *file,
+                          u_int cmd, u_long arg, int con, struct fb_info *info)
+{
+   return(-EINVAL);
+}
+
+
+static struct fb_ops mc68328_fb_ops = {
+	owner:		THIS_MODULE,
+	fb_get_fix:	mc68328_fb_get_fix,
+	fb_get_var:	mc68328_fb_get_var,
+	fb_set_var:	mc68328_fb_set_var,
+	fb_get_cmap:	mc68328_fb_get_cmap,
+	fb_set_cmap:	gen_set_cmap,
+	fb_pan_display:	mc68328_fb_pan_display,
+	fb_ioctl:	mc68328_fb_ioctl,
+};
+
+
+   /*
+    *    Initialization
+    */
+
+int __init mc68328_fb_init(void)
+{
+   int err;
+   struct mc68328_fb_par par;
+
+   fbhw = &mc68328_switch;
+
+   err = register_framebuffer(&fb_info);
+   if (err < 0)
+      panic("Cannot register frame buffer\n");
+
+   fbhw->init();
+   fbhw->decode_var(&mc68328_fb_predefined[mc68328fb_mode], &par);
+   fbhw->encode_var(&mc68328_fb_predefined[0], &par);
+
+   strcpy(fb_info.modename, mc68328_fb_name);
+   fb_info.disp = disp;
+   fb_info.switch_con = &mc68328fb_switch;
+   fb_info.updatevar = &mc68328fb_updatevar;
+
+   do_fb_set_var(&mc68328_fb_predefined[0], 1);
+   mc68328_fb_get_var(&disp[0].var, -1, &fb_info);
+   mc68328_fb_set_disp(-1, &fb_info);
+   do_install_cmap(0, &fb_info);
+   return(0);
+}
+
+
+static int mc68328fb_switch(int con, struct fb_info *info)
+{
+   /* Do we have to save the colormap? */
+   if (disp[currcon].cmap.len)
+      fb_get_cmap(&disp[currcon].cmap, 1, &disp[currcon].var, info);
+
+   do_fb_set_var(&disp[con].var, 1);
+   currcon = con;
+   /* Install new colormap */
+   do_install_cmap(con, info);
+   return(0);
+}
+
+
+   /*
+    *    Update the `var' structure (called by fbcon.c)
+    *
+    *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+    *    Since it's called by a kernel driver, no range checking is done.
+    */
+
+static int mc68328fb_updatevar(int con)
+{
+   return(0);
+}
+
+
+   /*
+    *    Blank the display.
+    */
+
+static void mc68328fb_blank(int blank)
+{
+   fbhw->blank(blank);
+}
+
+
+   /*
+    *    Get a Video Mode
+    */
+
+static int get_video_mode(const char *name)
+{
+   int i;
+
+   for (i = 1; i < NUM_PREDEF_MODES; i++)
+      if (!strcmp(name, mc68328_fb_modenames[i]))
+         return(i);
+   return(0);
+}
diff -Nru a/drivers/video/fbcon.c b/drivers/video/fbcon.c
--- a/drivers/video/fbcon.c	Wed Nov 27 14:36:31 2002
+++ b/drivers/video/fbcon.c	Wed Nov 27 14:36:31 2002
@@ -230,8 +230,9 @@
 
 static void cursor_timer_handler(unsigned long dev_addr);
 
-static struct timer_list cursor_timer =
-		TIMER_INITIALIZER(cursor_timer_handler, 0, 0);
+static struct timer_list cursor_timer = {
+    function: cursor_timer_handler
+};
 
 static void cursor_timer_handler(unsigned long dev_addr)
 {
diff -Nru a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
--- a/drivers/video/vga16fb.c	Wed Nov 27 14:36:28 2002
+++ b/drivers/video/vga16fb.c	Wed Nov 27 14:36:28 2002
@@ -22,6 +22,7 @@
 #include <linux/selection.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 
 #include <asm/io.h>
 
@@ -81,22 +82,33 @@
 /* --------------------------------------------------------------------- */
 
 static struct fb_var_screeninfo vga16fb_defined = {
-	640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/
-	0,0,		/* virtual -> visible no offset */
-	4,		/* depth -> load bits_per_pixel */
-	0,		/* greyscale ? */
-	{0,0,0},	/* R */
-	{0,0,0},	/* G */
-	{0,0,0},	/* B */
-	{0,0,0},	/* transparency */
-	0,		/* standard pixel format */
-	FB_ACTIVATE_NOW,
-	-1,-1,
-	0,
-	39721, 48, 16, 39, 8,
-	96, 2, 0,	/* No sync info */
-	FB_VMODE_NONINTERLACED,
-	{0,0,0,0,0,0}
+        .xres           = 640,
+        .yres           = 480,
+        .xres_virtual   = 640,
+        .yres_virtual   = 480,
+        .bits_per_pixel = 4,
+        .activate       = FB_ACTIVATE_NOW,
+        .height         = -1,
+        .width          = -1,
+        .pixclock       = 39721,
+        .left_margin    = 48,
+        .right_margin   = 16,
+        .upper_margin   = 39,
+        .lower_margin   = 8,
+        .hsync_len      = 96,
+        .vsync_len      = 2,
+        .vmode          = FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo vga16fb_fix __initdata = {
+        .id             = "VGA16 VGA",
+        .smem_start     = VGA_FB_PHYS,
+        .smem_len       = VGA_FB_PHYS_LEN,
+        .type           = FB_TYPE_VGA_PLANES,
+        .visual         = FB_VISUAL_PSEUDOCOLOR,
+        .xpanstep       = 8,
+        .ypanstep       = 1,
+        .line_length    = 640 / 8,
 };
 
 static struct display disp;
@@ -121,69 +133,22 @@
 #endif
 }
 
-static int vga16fb_update_var(int con, struct fb_info *info)
-{
-	vga16fb_pan_var(info, &fb_display[con].var);
-	return 0;
-}
-
-static int vga16fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info)
-{
-	struct display *p;
-
-	if (con < 0)
-		p = &disp;
-	else
-		p = fb_display + con;
-
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id,"VGA16 VGA");
-
-	fix->smem_start = VGA_FB_PHYS;
-	fix->smem_len = VGA_FB_PHYS_LEN;
-	fix->type = FB_TYPE_VGA_PLANES;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	fix->xpanstep  = 8;
-	fix->ypanstep  = 1;
-	fix->ywrapstep = 0;
-	fix->line_length = p->var.xres_virtual / 8;
-	return 0;
-}
-
-static int vga16fb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
-{
-	if(con==-1)
-		memcpy(var, &vga16fb_defined, sizeof(struct fb_var_screeninfo));
-	else
-		*var=fb_display[con].var;
-	return 0;
-}
-
 static void vga16fb_set_disp(int con, struct vga16fb_info *info)
 {
-	struct fb_fix_screeninfo fix;
-	struct display *display;
-
-	if (con < 0)
-		display = &disp;
-	else
-		display = fb_display + con;
+        struct display *display = (con < 0) ? info->fb_info.disp : (fb_display + con);
 
-	
-	vga16fb_get_fix(&fix, con, &info->fb_info);
-
-	display->visual = fix.visual;
-	display->type = fix.type;
-	display->type_aux = fix.type_aux;
-	display->ypanstep = fix.ypanstep;
-	display->ywrapstep = fix.ywrapstep;
-	display->line_length = fix.line_length;
-	display->next_line = fix.line_length;
 	display->can_soft_blank = 1;
+        display->dispsw_data = NULL;
+        display->var = info->fb_info.var;
 	display->inverse = 0;
 
+        /*
+         * If we are setting all the virtual consoles, also set
+         * the defaults used to create new consoles.
+         */
+        if (con < 0 || info->fb_info.var.activate & FB_ACTIVATE_ALL)
+                info->fb_info.disp->var = info->fb_info.var;
+
 	if (info->isVGA)
 		display->dispsw = &fbcon_vga_planes;
 	else
@@ -500,13 +465,9 @@
 {
 	struct vga16fb_info *info = (struct vga16fb_info*)fb;
 	struct vga16fb_par par;
-	struct display *display;
+        struct display *display = (con < 0) ? fb->disp : (fb_display + con);
 	int err;
 
-	if (con < 0)
-		display = fb->disp;
-	else
-		display = fb_display + con;
 	if ((err = vga16fb_decode_var(var, &par, info)) != 0)
 		return err;
 	vga16fb_encode_var(var, &par, info);
@@ -552,25 +513,6 @@
 	outb_p(0x20, 0x3C0); /* unblank screen */
 }
 
-static int vga16_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			  unsigned *blue, unsigned *transp,
-			  struct fb_info *fb_info)
-{
-	/*
-	 *  Read a single color register and split it into colors/transparent.
-	 *  Return != 0 for invalid regno.
-	 */
-
-	if (regno >= 16)
-		return 1;
-
-	*red   = palette[regno].red;
-	*green = palette[regno].green;
-	*blue  = palette[regno].blue;
-	*transp = 0;
-	return 0;
-}
-
 static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
 {
 	outb(regno,       dac_reg);
@@ -615,19 +557,6 @@
 	return 0;
 }
 
-static int vga16fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			   struct fb_info *info)
-{
-	if (con == info->currcon) /* current console? */
-		return fb_get_cmap(cmap, kspc, vga16_getcolreg, info);
-	else if (fb_display[con].cmap.len) /* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(16),
-		     cmap, kspc ? 0 : 2);
-	return 0;
-}
-
 static int vga16fb_pan_display(struct fb_var_screeninfo *var, int con,
 			       struct fb_info *info) 
 {
@@ -811,10 +740,8 @@
 
 static struct fb_ops vga16fb_ops = {
 	.owner =	THIS_MODULE,
-	.fb_get_fix =	vga16fb_get_fix,
-	.fb_get_var =	vga16fb_get_var,
 	.fb_set_var =	vga16fb_set_var,
-	.fb_get_cmap =	vga16fb_get_cmap,
+	.fb_get_cmap =	gen_get_cmap,
 	.fb_set_cmap =	gen_set_cmap,
 	.fb_setcolreg =	vga16fb_setcolreg,
 	.fb_pan_display =vga16fb_pan_display,
@@ -839,27 +766,6 @@
 	return 0;
 }
 
-static int vga16fb_switch(int con, struct fb_info *fb)
-{
-	struct vga16fb_par par;
-	struct vga16fb_info *info = (struct vga16fb_info*)fb;
-
-	/* Do we have to save the colormap? */
-	if (fb_display[fb->currcon].cmap.len)
-		fb_get_cmap(&fb_display[fb->currcon].cmap, 1, vga16_getcolreg,
-			    fb);
-	
-	fb->currcon = con;
-	vga16fb_decode_var(&fb_display[con].var, &par, info);
-	vga16fb_set_par(&par, info);
-	vga16fb_set_disp(con, info);
-
-	/* Install new colormap */
-	do_install_cmap(con, fb);
-/*	vga16fb_update_var(con, fb); */
-	return 1;
-}
-
 int __init vga16fb_init(void)
 {
 	int i,j;
@@ -895,18 +801,21 @@
 
 	disp.var = vga16fb_defined;
 
-	/* name should not depend on EGA/VGA */
-	strcpy(vga16fb.fb_info.modename, "VGA16 VGA");
+	strcpy(vga16fb.fb_info.modename, vga16fb_fix.id);
 	vga16fb.fb_info.changevar = NULL;
 	vga16fb.fb_info.node = NODEV;
+        vga16fb.fb_info.var = vga16fb_defined;
+        vga16fb.fb_info.fix = vga16fb_fix;
 	vga16fb.fb_info.fbops = &vga16fb_ops;
 	vga16fb.fb_info.screen_base = vga16fb.video_vbase;
 	vga16fb.fb_info.disp=&disp;
 	vga16fb.fb_info.currcon = -1;
-	vga16fb.fb_info.switch_con=&vga16fb_switch;
-	vga16fb.fb_info.updatevar=&vga16fb_update_var;
+	vga16fb.fb_info.switch_con=&gen_switch;
+	vga16fb.fb_info.updatevar=&gen_update_var;
 	vga16fb.fb_info.flags=FBINFO_FLAG_DEFAULT;
 	vga16fb_set_disp(-1, &vga16fb);
+
+	fb_alloc_cmap(&vga16fb.fb_info.cmap, 16, 0);
 
 	if (register_framebuffer(&vga16fb.fb_info)<0) {
 		iounmap(vga16fb.video_vbase);
diff -Nru a/fs/attr.c b/fs/attr.c
--- a/fs/attr.c	Wed Nov 27 14:36:28 2002
+++ b/fs/attr.c	Wed Nov 27 14:36:28 2002
@@ -157,13 +157,12 @@
 		return 0;
 
 	if (inode->i_op && inode->i_op->setattr) {
-		error = security_ops->inode_setattr(dentry, attr);
-		if (!error)
+		if (!(error = security_inode_setattr(dentry, attr)))
 			error = inode->i_op->setattr(dentry, attr);
 	} else {
 		error = inode_change_ok(inode, attr);
 		if (!error)
-			error = security_ops->inode_setattr(dentry, attr);
+			error = security_inode_setattr(dentry, attr);
 		if (!error) {
 			if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
 			    (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Wed Nov 27 14:36:30 2002
+++ b/fs/binfmt_elf.c	Wed Nov 27 14:36:30 2002
@@ -1218,16 +1218,9 @@
 	/* Set up header */
 	fill_elf_header(&elf, segs+1); /* including notes section*/
 
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
 	has_dumped = 1;
 	current->flags |= PF_DUMPCORE;
 
-	DUMP_WRITE(&elf, sizeof(elf));
-	offset += sizeof(elf);				/* Elf header */
-	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */
-
 	/*
 	 * Set up the notes in similar form to SVR4 core dumps made
 	 * with info from their /proc.
@@ -1254,6 +1247,13 @@
 	numnote --;
 #endif	
   
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	DUMP_WRITE(&elf, sizeof(elf));
+	offset += sizeof(elf);				/* Elf header */
+	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */
+
 	/* Write notes phdr entry */
 	{
 		struct elf_phdr phdr;
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Wed Nov 27 14:36:32 2002
+++ b/fs/block_dev.c	Wed Nov 27 14:36:32 2002
@@ -703,13 +703,13 @@
 	struct gendisk *disk = bdev->bd_disk;
 
 	down(&bdev->bd_sem);
-	lock_kernel();
 	switch (kind) {
 	case BDEV_FILE:
 	case BDEV_FS:
 		sync_blockdev(bd_inode->i_bdev);
 		break;
 	}
+	lock_kernel();
 	if (!--bdev->bd_openers)
 		kill_bdev(bdev);
 	if (bdev->bd_contains == bdev) {
diff -Nru a/fs/dquot.c b/fs/dquot.c
--- a/fs/dquot.c	Wed Nov 27 14:36:31 2002
+++ b/fs/dquot.c	Wed Nov 27 14:36:31 2002
@@ -70,6 +70,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 
@@ -1306,8 +1307,7 @@
 	error = -EIO;
 	if (!f->f_op || !f->f_op->read || !f->f_op->write)
 		goto out_f;
-	error = security_ops->quota_on(f);
-	if (error)
+	if ((error = security_quota_on(f)))
 		goto out_f;
 	inode = f->f_dentry->d_inode;
 	error = -EACCES;
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	Wed Nov 27 14:36:29 2002
+++ b/fs/exec.c	Wed Nov 27 14:36:29 2002
@@ -44,6 +44,7 @@
 #include <linux/proc_fs.h>
 #include <linux/ptrace.h>
 #include <linux/mount.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -840,8 +841,7 @@
 	}
 
 	/* fill in binprm security blob */
-	retval = security_ops->bprm_set_security(bprm);
-	if (retval)
+	if ((retval = security_bprm_set(bprm)))
 		return retval;
 
 	memset(bprm->buf,0,BINPRM_BUF_SIZE);
@@ -889,7 +889,7 @@
 	if(do_unlock)
 		unlock_kernel();
 
-	security_ops->bprm_compute_creds(bprm);
+	security_bprm_compute_creds(bprm);
 }
 
 void remove_arg_zero(struct linux_binprm *bprm)
@@ -958,8 +958,7 @@
 	    }
 	}
 #endif
-	retval = security_ops->bprm_check_security(bprm);
-	if (retval) 
+	if ((retval = security_bprm_check(bprm)))
 		return retval;
 
 	/* kernel module loader fixup */
@@ -1055,8 +1054,7 @@
 	if ((retval = bprm.envc) < 0)
 		goto out_mm;
 
-	retval = security_ops->bprm_alloc_security(&bprm);
-	if (retval) 
+	if ((retval = security_bprm_alloc(&bprm)))
 		goto out;
 
 	retval = prepare_binprm(&bprm);
@@ -1081,7 +1079,7 @@
 		free_arg_pages(&bprm);
 
 		/* execve success */
-		security_ops->bprm_free_security(&bprm);
+		security_bprm_free(&bprm);
 		return retval;
 	}
 
@@ -1094,7 +1092,7 @@
 	}
 
 	if (bprm.security)
-		security_ops->bprm_free_security(&bprm);
+		security_bprm_free(&bprm);
 
 out_mm:
 	mmdrop(bprm.mm);
diff -Nru a/fs/fcntl.c b/fs/fcntl.c
--- a/fs/fcntl.c	Wed Nov 27 14:36:27 2002
+++ b/fs/fcntl.c	Wed Nov 27 14:36:27 2002
@@ -274,8 +274,7 @@
 {
 	int err;
 	
-	err = security_ops->file_set_fowner(filp);
-	if (err)
+	if ((err = security_file_set_fowner(filp)))
 		return err;
 
 	f_modown(filp, arg, current->uid, current->euid, force);
@@ -368,8 +367,7 @@
 	if (!filp)
 		goto out;
 
-	err = security_ops->file_fcntl(filp, cmd, arg);
-	if (err) {
+	if ((err = security_file_fcntl(filp, cmd, arg))) {
 		fput(filp);
 		return err;
 	}
@@ -392,8 +390,7 @@
 	if (!filp)
 		goto out;
 
-	err = security_ops->file_fcntl(filp, cmd, arg);
-	if (err) {
+	if ((err = security_file_fcntl(filp, cmd, arg))) {
 		fput(filp);
 		return err;
 	}
@@ -444,7 +441,7 @@
 	if (!sigio_perm(p, fown))
 		return;
 
-	if (security_ops->file_send_sigiotask(p, fown, fd, reason))
+	if (security_file_send_sigiotask(p, fown, fd, reason))
 		return;
 
 	switch (fown->signum) {
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	Wed Nov 27 14:36:27 2002
+++ b/fs/file_table.c	Wed Nov 27 14:36:27 2002
@@ -18,7 +18,9 @@
 
 
 /* sysctl tunables... */
-struct files_stat_struct files_stat = {0, 0, NR_FILE};
+struct files_stat_struct files_stat = {
+	.max_files = NR_FILE
+};
 
 /* Here the new files go */
 static LIST_HEAD(anon_list);
@@ -46,7 +48,7 @@
 		files_stat.nr_free_files--;
 	new_one:
 		memset(f, 0, sizeof(*f));
-		if (security_ops->file_alloc_security(f)) {
+		if (security_file_alloc(f)) {
 			list_add(&f->f_list, &free_list);
 			files_stat.nr_free_files++;
 			file_list_unlock();
@@ -134,7 +136,7 @@
 
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
-	security_ops->file_free_security(file);
+	security_file_free(file);
 	fops_put(file->f_op);
 	if (file->f_mode & FMODE_WRITE)
 		put_write_access(inode);
@@ -167,7 +169,7 @@
 void put_filp(struct file *file)
 {
 	if(atomic_dec_and_test(&file->f_count)) {
-		security_ops->file_free_security(file);
+		security_file_free(file);
 		file_list_lock();
 		list_del(&file->f_list);
 		list_add(&file->f_list, &free_list);
diff -Nru a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
--- a/fs/hpfs/hpfs_fn.h	Wed Nov 27 14:36:30 2002
+++ b/fs/hpfs/hpfs_fn.h	Wed Nov 27 14:36:30 2002
@@ -75,7 +75,7 @@
 
 /* The b-tree down pointer from a dir entry */
 
-extern inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
+static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
 {
   CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n"));
   return *(dnode_secno *) ((void *) de + de->length - 4);
@@ -83,14 +83,14 @@
 
 /* The first dir entry in a dnode */
 
-extern inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode)
+static inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode)
 {
   return (void *) dnode->dirent;
 }
 
 /* The end+1 of the dir entries */
 
-extern inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode)
+static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode)
 {
   CHKCOND(dnode->first_free>=0x14 && dnode->first_free<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %d\n",(int)dnode->first_free));
   return (void *) dnode + dnode->first_free;
@@ -98,58 +98,60 @@
 
 /* The dir entry after dir entry de */
 
-extern inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de)
+static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de)
 {
   CHKCOND(de->length>=0x20 && de->length<0x800,("HPFS: de_next_de: de->length = %d\n",(int)de->length));
   return (void *) de + de->length;
 }
 
-extern inline struct extended_attribute *fnode_ea(struct fnode *fnode)
+static inline struct extended_attribute *fnode_ea(struct fnode *fnode)
 {
 	return (struct extended_attribute *)((char *)fnode + fnode->ea_offs);
 }
 
-extern inline struct extended_attribute *fnode_end_ea(struct fnode *fnode)
+static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode)
 {
 	return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->ea_size_s);
 }
 
-extern inline struct extended_attribute *next_ea(struct extended_attribute *ea)
+static inline struct extended_attribute *next_ea(struct extended_attribute *ea)
 {
 	return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea->valuelen);
 }
 
-extern inline secno ea_sec(struct extended_attribute *ea)
+static inline secno ea_sec(struct extended_attribute *ea)
 {
 	return *(secno *)((char *)ea + 9 + ea->namelen);
 }
 
-extern inline secno ea_len(struct extended_attribute *ea)
+static inline secno ea_len(struct extended_attribute *ea)
 {
 	return *(secno *)((char *)ea + 5 + ea->namelen);
 }
 
-extern inline char *ea_data(struct extended_attribute *ea)
+static inline char *ea_data(struct extended_attribute *ea)
 {
 	return (char *)((char *)ea + 5 + ea->namelen);
 }
 
-extern inline unsigned de_size(int namelen, secno down_ptr)
+static inline unsigned de_size(int namelen, secno down_ptr)
 {
 	return ((0x1f + namelen + 3) & ~3) + (down_ptr ? 4 : 0);
 }
 
-extern inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src)
+static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src)
 {
-	int a = dst->down;
-	int n = dst->not_8x3;
+	int a;
+	int n;
 	if (!dst || !src) return;
+	a = dst->down;
+	n = dst->not_8x3;
 	memcpy((char *)dst + 2, (char *)src + 2, 28);
 	dst->down = a;
 	dst->not_8x3 = n;
 }
 
-extern inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)
+static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)
 {
 	int i;
 	if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n;
@@ -314,13 +316,13 @@
  * local time (HPFS) to GMT (Unix)
  */
 
-extern inline time_t local_to_gmt(struct super_block *s, time_t t)
+static inline time_t local_to_gmt(struct super_block *s, time_t t)
 {
 	extern struct timezone sys_tz;
 	return t + sys_tz.tz_minuteswest * 60 + hpfs_sb(s)->sb_timeshift;
 }
 
-extern inline time_t gmt_to_local(struct super_block *s, time_t t)
+static inline time_t gmt_to_local(struct super_block *s, time_t t)
 {
 	extern struct timezone sys_tz;
 	return t - sys_tz.tz_minuteswest * 60 - hpfs_sb(s)->sb_timeshift;
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Wed Nov 27 14:36:32 2002
+++ b/fs/inode.c	Wed Nov 27 14:36:32 2002
@@ -119,7 +119,7 @@
 		inode->i_bdev = NULL;
 		inode->i_cdev = NULL;
 		inode->i_security = NULL;
-		if (security_ops->inode_alloc_security(inode)) {
+		if (security_inode_alloc(inode)) {
 			if (inode->i_sb->s_op->destroy_inode)
 				inode->i_sb->s_op->destroy_inode(inode);
 			else
@@ -145,7 +145,7 @@
 {
 	if (inode_has_buffers(inode))
 		BUG();
-	security_ops->inode_free_security(inode);
+	security_inode_free(inode);
 	if (inode->i_sb->s_op->destroy_inode)
 		inode->i_sb->s_op->destroy_inode(inode);
 	else
@@ -935,7 +935,7 @@
 	if (inode->i_data.nrpages)
 		truncate_inode_pages(&inode->i_data, 0);
 
-	security_ops->inode_delete(inode);
+	security_inode_delete(inode);
 
 	if (op && op->delete_inode) {
 		void (*delete)(struct inode *) = op->delete_inode;
diff -Nru a/fs/ioctl.c b/fs/ioctl.c
--- a/fs/ioctl.c	Wed Nov 27 14:36:28 2002
+++ b/fs/ioctl.c	Wed Nov 27 14:36:28 2002
@@ -59,8 +59,7 @@
 		goto out;
 	error = 0;
 
-	error = security_ops->file_ioctl(filp, cmd, arg);
-        if (error) {
+	if ((error = security_file_ioctl(filp, cmd, arg))) {
                 fput(filp);
                 goto out;
         }
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Wed Nov 27 14:36:32 2002
+++ b/fs/locks.c	Wed Nov 27 14:36:32 2002
@@ -122,6 +122,7 @@
 #include <linux/timer.h>
 #include <linux/time.h>
 #include <linux/fs.h>
+#include <linux/security.h>
 
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -1184,8 +1185,7 @@
 		return -EACCES;
 	if (!S_ISREG(inode->i_mode))
 		return -EINVAL;
-	error = security_ops->file_lock(filp, arg);
-	if (error)
+	if ((error = security_file_lock(filp, arg)))
 		return error;
 
 	lock_kernel();
@@ -1298,8 +1298,7 @@
 	if (error)
 		goto out_putf;
 
-	error = security_ops->file_lock(filp, cmd);
-	if (error)
+	if ((error = security_file_lock(filp, cmd)))
 		goto out_free;
 
 	for (;;) {
@@ -1450,8 +1449,7 @@
 		goto out;
 	}
 
-	error = security_ops->file_lock(filp, file_lock->fl_type);
-	if (error)
+	if ((error = security_file_lock(filp, file_lock->fl_type)))
 		goto out;
 
 	if (filp->f_op && filp->f_op->lock != NULL) {
@@ -1590,8 +1588,7 @@
 		goto out;
 	}
 
-	error = security_ops->file_lock(filp, file_lock->fl_type);
-	if (error)
+	if ((error = security_file_lock(filp, file_lock->fl_type)))
 		goto out;
 
 	if (filp->f_op && filp->f_op->lock != NULL) {
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Wed Nov 27 14:36:28 2002
+++ b/fs/namei.c	Wed Nov 27 14:36:28 2002
@@ -218,7 +218,7 @@
 	if (retval)
 		return retval;
 
-	return security_ops->inode_permission(inode, mask);
+	return security_inode_permission(inode, mask);
 }
 
 /*
@@ -340,7 +340,7 @@
 
 	return -EACCES;
 ok:
-	return security_ops->inode_permission_lite(inode, MAY_EXEC);
+	return security_inode_permission_lite(inode, MAY_EXEC);
 }
 
 /*
@@ -374,7 +374,7 @@
 				dput(dentry);
 			else {
 				result = dentry;
-				security_ops->inode_post_lookup(dir, result);
+				security_inode_post_lookup(dir, result);
 			}
 		}
 		up(&dir->i_sem);
@@ -413,8 +413,7 @@
 		current->state = TASK_RUNNING;
 		schedule();
 	}
-	err = security_ops->inode_follow_link(dentry, nd);
-	if (err)
+	if ((err = security_inode_follow_link(dentry, nd)))
 		goto loop;
 	current->link_count++;
 	current->total_link_count++;
@@ -918,7 +917,7 @@
 		dentry = inode->i_op->lookup(inode, new);
 		if (!dentry) {
 			dentry = new;
-			security_ops->inode_post_lookup(inode, dentry);
+			security_inode_post_lookup(inode, dentry);
 		} else
 			dput(new);
 	}
@@ -1125,14 +1124,13 @@
 		return -EACCES;	/* shouldn't it be ENOSYS? */
 	mode &= S_IALLUGO;
 	mode |= S_IFREG;
-	error = security_ops->inode_create(dir, dentry, mode);
-	if (error)
+	if ((error = security_inode_create(dir, dentry, mode)))
 		return error;
 	DQUOT_INIT(dir);
 	error = dir->i_op->create(dir, dentry, mode);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_post_create(dir, dentry, mode);
+		security_inode_post_create(dir, dentry, mode);
 	}
 	return error;
 }
@@ -1345,8 +1343,7 @@
 	 * stored in nd->last.name and we will have to putname() it when we
 	 * are done. Procfs-like symlinks just set LAST_BIND.
 	 */
-	error = security_ops->inode_follow_link(dentry, nd);
-	if (error)
+	if ((error = security_inode_follow_link(dentry, nd)))
 		goto exit_dput;
 	UPDATE_ATIME(dentry->d_inode);
 	error = dentry->d_inode->i_op->follow_link(dentry, nd);
@@ -1411,15 +1408,14 @@
 	if (!dir->i_op || !dir->i_op->mknod)
 		return -EPERM;
 
-	error = security_ops->inode_mknod(dir, dentry, mode, dev);
-	if (error)
+	if ((error = security_inode_mknod(dir, dentry, mode, dev)))
 		return error;
 
 	DQUOT_INIT(dir);
 	error = dir->i_op->mknod(dir, dentry, mode, dev);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_post_mknod(dir, dentry, mode, dev);
+		security_inode_post_mknod(dir, dentry, mode, dev);
 	}
 	return error;
 }
@@ -1480,15 +1476,14 @@
 		return -EPERM;
 
 	mode &= (S_IRWXUGO|S_ISVTX);
-	error = security_ops->inode_mkdir(dir, dentry, mode);
-	if (error)
+	if ((error = security_inode_mkdir(dir, dentry, mode)))
 		return error;
 
 	DQUOT_INIT(dir);
 	error = dir->i_op->mkdir(dir, dentry, mode);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_post_mkdir(dir,dentry, mode);
+		security_inode_post_mkdir(dir,dentry, mode);
 	}
 	return error;
 }
@@ -1573,8 +1568,7 @@
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
-		error = security_ops->inode_rmdir(dir, dentry);
-		if (!error) {
+		if (!(error = security_inode_rmdir(dir, dentry))) {
 			error = dir->i_op->rmdir(dir, dentry);
 			if (!error)
 				dentry->d_inode->i_flags |= S_DEAD;
@@ -1647,10 +1641,8 @@
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
-		error = security_ops->inode_unlink(dir, dentry);
-		if (!error) {
+		if (!(error = security_inode_unlink(dir, dentry)))
 			error = dir->i_op->unlink(dir, dentry);
-		}
 	}
 	up(&dentry->d_inode->i_sem);
 	if (!error) {
@@ -1712,15 +1704,14 @@
 	if (!dir->i_op || !dir->i_op->symlink)
 		return -EPERM;
 
-	error = security_ops->inode_symlink(dir, dentry, oldname);
-	if (error)
+	if ((error = security_inode_symlink(dir, dentry, oldname)))
 		return error;
 
 	DQUOT_INIT(dir);
 	error = dir->i_op->symlink(dir, dentry, oldname);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_post_symlink(dir, dentry, oldname);
+		security_inode_post_symlink(dir, dentry, oldname);
 	}
 	return error;
 }
@@ -1783,8 +1774,7 @@
 	if (S_ISDIR(old_dentry->d_inode->i_mode))
 		return -EPERM;
 
-	error = security_ops->inode_link(old_dentry, dir, new_dentry);
-	if (error)
+	if ((error = security_inode_link(old_dentry, dir, new_dentry)))
 		return error;
 
 	down(&old_dentry->d_inode->i_sem);
@@ -1793,7 +1783,7 @@
 	up(&old_dentry->d_inode->i_sem);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
-		security_ops->inode_post_link(old_dentry, dir, new_dentry);
+		security_inode_post_link(old_dentry, dir, new_dentry);
 	}
 	return error;
 }
@@ -1892,8 +1882,7 @@
 			return error;
 	}
 
-	error = security_ops->inode_rename(old_dir, old_dentry, new_dir, new_dentry);
-	if (error)
+	if ((error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry)))
 		return error;
 
 	target = new_dentry->d_inode;
@@ -1915,8 +1904,8 @@
 	}
 	if (!error) {
 		d_move(old_dentry,new_dentry);
-		security_ops->inode_post_rename(old_dir, old_dentry,
-							new_dir, new_dentry);
+		security_inode_post_rename(old_dir, old_dentry,
+					   new_dir, new_dentry);
 	}
 	return error;
 }
@@ -1927,8 +1916,7 @@
 	struct inode *target;
 	int error;
 
-	error = security_ops->inode_rename(old_dir, old_dentry, new_dir, new_dentry);
-	if (error)
+	if ((error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry)))
 		return error;
 
 	dget(new_dentry);
@@ -1943,7 +1931,7 @@
 		/* The following d_move() should become unconditional */
 		if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME))
 			d_move(old_dentry, new_dentry);
-		security_ops->inode_post_rename(old_dir, old_dentry, new_dir, new_dentry);
+		security_inode_post_rename(old_dir, old_dentry, new_dir, new_dentry);
 	}
 	if (target)
 		up(&target->i_sem);
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	Wed Nov 27 14:36:31 2002
+++ b/fs/namespace.c	Wed Nov 27 14:36:31 2002
@@ -19,6 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/namespace.h>
 #include <linux/namei.h>
+#include <linux/security.h>
 #include <linux/mount.h>
 #include <asm/uaccess.h>
 
@@ -288,8 +289,7 @@
 	struct super_block * sb = mnt->mnt_sb;
 	int retval = 0;
 
-	retval = security_ops->sb_umount(mnt, flags);
-	if (retval)
+	if ((retval = security_sb_umount(mnt, flags)))
 		return retval;
 
 	/*
@@ -341,7 +341,7 @@
 		DQUOT_OFF(sb);
 		acct_auto_close(sb);
 		unlock_kernel();
-		security_ops->sb_umount_close(mnt);
+		security_sb_umount_close(mnt);
 		spin_lock(&dcache_lock);
 	}
 	retval = -EBUSY;
@@ -352,7 +352,7 @@
 	}
 	spin_unlock(&dcache_lock);
 	if (retval)
-		security_ops->sb_umount_busy(mnt);
+		security_sb_umount_busy(mnt);
 	up_write(&current->namespace->sem);
 	return retval;
 }
@@ -470,8 +470,7 @@
 	if (IS_DEADDIR(nd->dentry->d_inode))
 		goto out_unlock;
 
-	err = security_ops->sb_check_sb(mnt, nd);
-	if (err)
+	if ((err = security_sb_check_sb(mnt, nd)))
 		goto out_unlock;
 
 	spin_lock(&dcache_lock);
@@ -487,7 +486,7 @@
 out_unlock:
 	up(&nd->dentry->d_inode->i_sem);
 	if (!err)
-		security_ops->sb_post_addmount(mnt, nd);
+		security_sb_post_addmount(mnt, nd);
 	return err;
 }
 
@@ -558,7 +557,7 @@
 		nd->mnt->mnt_flags=mnt_flags;
 	up_write(&sb->s_umount);
 	if (!err)
-		security_ops->sb_post_remount(nd->mnt, flags, data);
+		security_sb_post_remount(nd->mnt, flags, data);
 	return err;
 }
 
@@ -741,8 +740,7 @@
 	if (retval)
 		return retval;
 
-	retval = security_ops->sb_mount(dev_name, &nd, type_page, flags, data_page);
-	if (retval)
+	if ((retval = security_sb_mount(dev_name, &nd, type_page, flags, data_page)))
 		goto dput_out;
 
 	if (flags & MS_REMOUNT)
@@ -987,8 +985,7 @@
 	if (error)
 		goto out1;
 
-	error = security_ops->sb_pivotroot(&old_nd, &new_nd);
-	if (error) {
+	if ((error = security_sb_pivotroot(&old_nd, &new_nd))) {
 		path_release(&old_nd);
 		goto out1;
 	}
@@ -1037,7 +1034,7 @@
 	attach_mnt(new_nd.mnt, &root_parent);
 	spin_unlock(&dcache_lock);
 	chroot_fs_refs(&user_nd, &new_nd);
-	security_ops->sb_post_pivotroot(&user_nd, &new_nd);
+	security_sb_post_pivotroot(&user_nd, &new_nd);
 	error = 0;
 	path_release(&root_parent);
 	path_release(&parent_nd);
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	Wed Nov 27 14:36:30 2002
+++ b/fs/nfsd/export.c	Wed Nov 27 14:36:30 2002
@@ -21,6 +21,7 @@
 #include <linux/in.h>
 #include <linux/seq_file.h>
 #include <linux/rwsem.h>
+#include <linux/dcache.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
 
diff -Nru a/fs/open.c b/fs/open.c
--- a/fs/open.c	Wed Nov 27 14:36:27 2002
+++ b/fs/open.c	Wed Nov 27 14:36:27 2002
@@ -31,8 +31,7 @@
 		retval = -ENOSYS;
 		if (sb->s_op && sb->s_op->statfs) {
 			memset(buf, 0, sizeof(struct statfs));
-			retval = security_ops->sb_statfs(sb);
-			if (retval)
+			if ((retval = security_sb_statfs(sb)))
 				return retval;
 			retval = sb->s_op->statfs(sb, buf);
 		}
diff -Nru a/fs/partitions/ldm.c b/fs/partitions/ldm.c
--- a/fs/partitions/ldm.c	Wed Nov 27 14:36:29 2002
+++ b/fs/partitions/ldm.c	Wed Nov 27 14:36:29 2002
@@ -560,10 +560,8 @@
 		return FALSE;
 	}
 
-	if (*(u16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC)) {
-		ldm_debug ("No MS-DOS partition table found.");
+	if (*(u16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
 		goto out;
-	}
 
 	p = (struct partition*)(data + 0x01BE);
 	for (i = 0; i < 4; i++, p++)
@@ -573,9 +571,8 @@
 		}
 
 	if (result)
-		ldm_debug ("Parsed partition table successfully.");
-	else
-		ldm_debug ("Found an MS-DOS partition table, not a dynamic disk.");
+		ldm_debug ("Found W2K dynamic disk partition type.");
+
 out:
 	put_dev_sector (sect);
 	return result;
@@ -585,9 +582,10 @@
  * ldm_get_disk_objid - Search a linked list of vblk's for a given Disk Id
  * @ldb:  Cache of the database structures
  *
- * The LDM Database contains a list of all partitions on all dynamic disks.  The
- * primary PRIVHEAD, at the beginning of the physical disk, tells us the GUID of
- * this disk.  This function searches for the GUID in a linked list of vblk's.
+ * The LDM Database contains a list of all partitions on all dynamic disks.
+ * The primary PRIVHEAD, at the beginning of the physical disk, tells us
+ * the GUID of this disk.  This function searches for the GUID in a linked
+ * list of vblk's.
  *
  * Return:  Pointer, A matching vblk was found
  *          NULL,    No match, or an error
diff -Nru a/fs/proc/array.c b/fs/proc/array.c
--- a/fs/proc/array.c	Wed Nov 27 14:36:31 2002
+++ b/fs/proc/array.c	Wed Nov 27 14:36:31 2002
@@ -126,9 +126,9 @@
 	"R (running)",		/*  0 */
 	"S (sleeping)",		/*  1 */
 	"D (disk sleep)",	/*  2 */
-	"Z (zombie)",		/*  4 */
 	"T (stopped)",		/*  8 */
-	"W (paging)"		/* 16 */
+	"Z (zombie)",		/*  4 */
+	"X (dead)"		/* 16 */
 };
 
 static inline const char * get_task_state(struct task_struct *tsk)
@@ -597,25 +597,3 @@
 out:
 	return retval;
 }
-
-#ifdef CONFIG_SMP
-int proc_pid_cpu(struct task_struct *task, char * buffer)
-{
-	int i, len;
-
-	len = sprintf(buffer,
-		"cpu  %lu %lu\n",
-		jiffies_to_clock_t(task->utime),
-		jiffies_to_clock_t(task->stime));
-		
-	for (i = 0 ; i < NR_CPUS; i++) {
-		if (cpu_online(i))
-		len += sprintf(buffer + len, "cpu%d %lu %lu\n",
-			i,
-			jiffies_to_clock_t(task->per_cpu_utime[i]),
-			jiffies_to_clock_t(task->per_cpu_stime[i]));
-
-	}
-	return len;
-}
-#endif
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	Wed Nov 27 14:36:31 2002
+++ b/fs/proc/base.c	Wed Nov 27 14:36:31 2002
@@ -30,6 +30,7 @@
 #include <linux/smp_lock.h>
 #include <linux/kallsyms.h>
 #include <linux/mount.h>
+#include <linux/security.h>
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -54,7 +55,6 @@
 	PROC_PID_STAT,
 	PROC_PID_STATM,
 	PROC_PID_MAPS,
-	PROC_PID_CPU,
 	PROC_PID_MOUNTS,
 	PROC_PID_WCHAN,
 	PROC_PID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
@@ -75,9 +75,6 @@
   E(PROC_PID_CMDLINE,	"cmdline",	S_IFREG|S_IRUGO),
   E(PROC_PID_STAT,	"stat",		S_IFREG|S_IRUGO),
   E(PROC_PID_STATM,	"statm",	S_IFREG|S_IRUGO),
-#ifdef CONFIG_SMP
-  E(PROC_PID_CPU,	"cpu",		S_IFREG|S_IRUGO),
-#endif
   E(PROC_PID_MAPS,	"maps",		S_IFREG|S_IRUGO),
   E(PROC_PID_MEM,	"mem",		S_IFREG|S_IRUSR|S_IWUSR),
   E(PROC_PID_CWD,	"cwd",		S_IFLNK|S_IRWXUGO),
@@ -420,7 +417,7 @@
 };
 
 #define MAY_PTRACE(p) \
-(p==current||(p->parent==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED&&security_ops->ptrace(current,p)==0))
+(p==current||(p->parent==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED&&security_ptrace(current,p)==0))
 
 
 static int mem_open(struct inode* inode, struct file* file)
@@ -1029,12 +1026,7 @@
 		case PROC_PID_MAPS:
 			inode->i_fop = &proc_maps_operations;
 			break;
-#ifdef CONFIG_SMP
-		case PROC_PID_CPU:
-			inode->i_fop = &proc_info_file_operations;
-			ei->op.proc_read = proc_pid_cpu;
-			break;
-#endif
+
 		case PROC_PID_MEM:
 			inode->i_op = &proc_mem_inode_operations;
 			inode->i_fop = &proc_mem_operations;
diff -Nru a/fs/proc/inode.c b/fs/proc/inode.c
--- a/fs/proc/inode.c	Wed Nov 27 14:36:31 2002
+++ b/fs/proc/inode.c	Wed Nov 27 14:36:31 2002
@@ -73,7 +73,7 @@
 	de = PROC_I(inode)->pde;
 	if (de) {
 		if (de->owner)
-			__MOD_DEC_USE_COUNT(de->owner);
+			module_put(de->owner);
 		de_put(de);
 	}
 }
@@ -200,8 +200,8 @@
 			inode->i_size = de->size;
 		if (de->nlink)
 			inode->i_nlink = de->nlink;
-		if (de->owner)
-			__MOD_INC_USE_COUNT(de->owner);
+		if (!try_module_get(de->owner))
+			goto out_fail;
 		if (de->proc_iops)
 			inode->i_op = de->proc_iops;
 		if (de->proc_fops)
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Wed Nov 27 14:36:28 2002
+++ b/fs/proc/proc_misc.c	Wed Nov 27 14:36:28 2002
@@ -602,7 +602,7 @@
 		proc_root_kcore->size =
 				(size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
 	}
-	if (prof_shift) {
+	if (prof_on) {
 		entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL);
 		if (entry) {
 			entry->proc_fops = &proc_profile_operations;
diff -Nru a/fs/qnx4/inode.c b/fs/qnx4/inode.c
--- a/fs/qnx4/inode.c	Wed Nov 27 14:36:31 2002
+++ b/fs/qnx4/inode.c	Wed Nov 27 14:36:31 2002
@@ -324,6 +324,10 @@
 					if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
 						found = 1;
 						qnx4_sb(sb)->BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
+						if (!qnx4_sb(sb)->BitMap) {
+							brelse (bh);
+							return "not enough memory for bitmap inode";
+						}
 						memcpy( qnx4_sb(sb)->BitMap, rootdir, sizeof( struct qnx4_inode_entry ) );	/* keep bitmap inode known */
 						break;
 					}
diff -Nru a/fs/quota.c b/fs/quota.c
--- a/fs/quota.c	Wed Nov 27 14:36:32 2002
+++ b/fs/quota.c	Wed Nov 27 14:36:32 2002
@@ -98,7 +98,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-	return security_ops->quotactl (cmd, type, id, sb);
+	return security_quotactl (cmd, type, id, sb);
 }
 
 /* Resolve device pathname to superblock */
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	Wed Nov 27 14:36:31 2002
+++ b/fs/read_write.c	Wed Nov 27 14:36:31 2002
@@ -193,8 +193,7 @@
 
 	ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count);
 	if (!ret) {
-		ret = security_ops->file_permission (file, MAY_READ);
-		if (!ret) {
+		if (!(ret = security_file_permission (file, MAY_READ))) {
 			if (file->f_op->read)
 				ret = file->f_op->read(file, buf, count, pos);
 			else
@@ -233,8 +232,7 @@
 
 	ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count);
 	if (!ret) {
-		ret = security_ops->file_permission (file, MAY_WRITE);
-		if (!ret) {
+		if (!(ret = security_file_permission (file, MAY_WRITE))) {
 			if (file->f_op->write)
 				ret = file->f_op->write(file, buf, count, pos);
 			else
diff -Nru a/fs/readdir.c b/fs/readdir.c
--- a/fs/readdir.c	Wed Nov 27 14:36:30 2002
+++ b/fs/readdir.c	Wed Nov 27 14:36:30 2002
@@ -11,6 +11,7 @@
 #include <linux/file.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 
@@ -21,8 +22,7 @@
 	if (!file->f_op || !file->f_op->readdir)
 		goto out;
 
-	res = security_ops->file_permission(file, MAY_READ);
-	if (res)
+	if ((res = security_file_permission(file, MAY_READ)))
 		goto out;
 
 	down(&inode->i_sem);
diff -Nru a/fs/stat.c b/fs/stat.c
--- a/fs/stat.c	Wed Nov 27 14:36:28 2002
+++ b/fs/stat.c	Wed Nov 27 14:36:28 2002
@@ -38,8 +38,7 @@
 	struct inode *inode = dentry->d_inode;
 	int retval;
 
-	retval = security_ops->inode_getattr(mnt, dentry);
-	if (retval)
+	if ((retval = security_inode_getattr(mnt, dentry)))
 		return retval;
 
 	if (inode->i_op->getattr)
@@ -242,8 +241,7 @@
 
 		error = -EINVAL;
 		if (inode->i_op && inode->i_op->readlink) {
-			error = security_ops->inode_readlink(nd.dentry);
-			if (!error) {
+			if (!(error = security_inode_readlink(nd.dentry))) {
 				UPDATE_ATIME(inode);
 				error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
 			}
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	Wed Nov 27 14:36:30 2002
+++ b/fs/super.c	Wed Nov 27 14:36:30 2002
@@ -29,9 +29,9 @@
 #include <linux/namei.h>
 #include <linux/buffer_head.h>		/* for fsync_super() */
 #include <linux/mount.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 
-#include <linux/security.h>
 
 void get_filesystem(struct file_system_type *fs);
 void put_filesystem(struct file_system_type *fs);
@@ -51,7 +51,7 @@
 	struct super_block *s = kmalloc(sizeof(struct super_block),  GFP_USER);
 	if (s) {
 		memset(s, 0, sizeof(struct super_block));
-		if (security_ops->sb_alloc_security(s)) {
+		if (security_sb_alloc(s)) {
 			kfree(s);
 			s = NULL;
 			goto out;
@@ -85,7 +85,7 @@
  */
 static inline void destroy_super(struct super_block *s)
 {
-	security_ops->sb_free_security(s);
+	security_sb_free(s);
 	kfree(s);
 }
 
diff -Nru a/fs/xattr.c b/fs/xattr.c
--- a/fs/xattr.c	Wed Nov 27 14:36:29 2002
+++ b/fs/xattr.c	Wed Nov 27 14:36:29 2002
@@ -13,6 +13,7 @@
 #include <linux/file.h>
 #include <linux/xattr.h>
 #include <linux/namei.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 
 /*
@@ -85,9 +86,7 @@
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
-		error = security_ops->inode_setxattr(d, kname, kvalue,
-				size, flags);
-		if (error)
+		if ((error = security_inode_setxattr(d, kname, kvalue, size, flags)))
 			goto out;
 		down(&d->d_inode->i_sem);
 		error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
@@ -163,8 +162,7 @@
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
-		error = security_ops->inode_getxattr(d, kname);
-		if (error)
+		if ((error = security_inode_getxattr(d, kname)))
 			goto out;
 		down(&d->d_inode->i_sem);
 		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
@@ -236,8 +234,7 @@
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
-		error = security_ops->inode_listxattr(d);
-		if (error)
+		if ((error = security_inode_listxattr(d)))
 			goto out;
 		down(&d->d_inode->i_sem);
 		error = d->d_inode->i_op->listxattr(d, klist, size);
@@ -311,8 +308,7 @@
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
-		error = security_ops->inode_removexattr(d, kname);
-		if (error)
+		if ((error = security_inode_removexattr(d, kname)))
 			goto out;
 		down(&d->d_inode->i_sem);
 		error = d->d_inode->i_op->removexattr(d, kname);
diff -Nru a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h
--- a/include/asm-alpha/processor.h	Wed Nov 27 14:36:32 2002
+++ b/include/asm-alpha/processor.h	Wed Nov 27 14:36:32 2002
@@ -30,7 +30,6 @@
  * Bus types
  */
 #define EISA_bus 1
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
 #define MCA_bus 0
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
--- a/include/asm-alpha/unistd.h	Wed Nov 27 14:36:29 2002
+++ b/include/asm-alpha/unistd.h	Wed Nov 27 14:36:29 2002
@@ -317,7 +317,7 @@
 #define __NR_getdents64			377
 #define __NR_gettid			378
 #define __NR_readahead			379
-#define __NR_security			380 /* syscall for security modules */
+/* 380 is unused */
 #define __NR_tkill			381
 #define __NR_setxattr			382
 #define __NR_lsetxattr			383
diff -Nru a/include/asm-arm/arch-shark/ide.h b/include/asm-arm/arch-shark/ide.h
--- a/include/asm-arm/arch-shark/ide.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-arm/arch-shark/ide.h	Wed Nov 27 14:36:31 2002
@@ -42,6 +42,6 @@
 
 	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
 	hw.irq = 14;
-	ide_register_hw(&hw);
+	ide_register_hw(&hw,NULL);
 }
 
diff -Nru a/include/asm-arm/arch-shark/irqs.h b/include/asm-arm/arch-shark/irqs.h
--- a/include/asm-arm/arch-shark/irqs.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-arm/arch-shark/irqs.h	Wed Nov 27 14:36:31 2002
@@ -7,5 +7,6 @@
 #define NR_IRQS			16
 
 #define IRQ_ISA_KEYBOARD	 1
+#define RTC_IRQ			 8
 #define AUX_IRQ			12
 #define IRQ_HARDDISK            14
diff -Nru a/include/asm-arm/arch-shark/memory.h b/include/asm-arm/arch-shark/memory.h
--- a/include/asm-arm/arch-shark/memory.h	Wed Nov 27 14:36:32 2002
+++ b/include/asm-arm/arch-shark/memory.h	Wed Nov 27 14:36:32 2002
@@ -38,6 +38,4 @@
 #define __bus_to_virt__is_a_macro
 #define __bus_to_virt(x)	__phys_to_virt(x)
 
-#define isa_virt_to_bus		virt_to_bus
-
 #endif
diff -Nru a/include/asm-arm/arch-shark/timex.h b/include/asm-arm/arch-shark/timex.h
--- a/include/asm-arm/arch-shark/timex.h	Wed Nov 27 14:36:29 2002
+++ b/include/asm-arm/arch-shark/timex.h	Wed Nov 27 14:36:29 2002
@@ -3,3 +3,5 @@
  *
  * by Alexander Schulz
  */
+
+#define CLOCK_TICK_RATE 1193180
diff -Nru a/include/asm-arm/proc-armv/elf.h b/include/asm-arm/proc-armv/elf.h
--- a/include/asm-arm/proc-armv/elf.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-arm/proc-armv/elf.h	Wed Nov 27 14:36:31 2002
@@ -13,7 +13,7 @@
 
 #define ELF_THUMB_OK(x) \
 	(( (elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 1) == 1) || \
-	 (!(elf_hwcap & HWCAP_THUMB) && ((x)->e_entry & 3) == 0))
+	 ((x)->e_entry & 3) == 0)
 
 #define ELF_26BIT_OK(x) \
 	(( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \
diff -Nru a/include/asm-arm/suspend.h b/include/asm-arm/suspend.h
--- a/include/asm-arm/suspend.h	Wed Nov 27 14:36:29 2002
+++ b/include/asm-arm/suspend.h	Wed Nov 27 14:36:29 2002
@@ -1,4 +1,4 @@
-#ifdef _ASMARM_SUSPEND_H
+#ifndef _ASMARM_SUSPEND_H
 #define _ASMARM_SUSPEND_H
 
 #endif
diff -Nru a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
--- a/include/asm-arm/unistd.h	Wed Nov 27 14:36:32 2002
+++ b/include/asm-arm/unistd.h	Wed Nov 27 14:36:32 2002
@@ -247,7 +247,7 @@
 #define __NR_madvise			(__NR_SYSCALL_BASE+220)
 #define __NR_fcntl64			(__NR_SYSCALL_BASE+221)
 					/* 222 for tux */
-#define __NR_security			(__NR_SYSCALL_BASE+223)
+					/* 223 is unused */
 #define __NR_gettid			(__NR_SYSCALL_BASE+224)
 #define __NR_readahead			(__NR_SYSCALL_BASE+225)
 #define __NR_setxattr			(__NR_SYSCALL_BASE+226)
diff -Nru a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
--- a/include/asm-cris/unistd.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-cris/unistd.h	Wed Nov 27 14:36:31 2002
@@ -227,7 +227,7 @@
 #define __NR_madvise		219
 #define __NR_getdents64		220
 #define __NR_fcntl64		221
-#define __NR_security           223     /* syscall for security modules */
+/* 223 is unused */
 #define __NR_gettid             224
 #define __NR_readahead          225
 #define __NR_tkill              226
diff -Nru a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
--- a/include/asm-i386/io_apic.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-i386/io_apic.h	Wed Nov 27 14:36:31 2002
@@ -120,9 +120,14 @@
 /*
  * Re-write a value: to be used for read-modify-write
  * cycles where the read already set up the index register.
+ *
+ * Older SiS APIC requires we rewrite the index regiser
  */
-static inline void io_apic_modify(unsigned int apic, unsigned int value)
+extern int sis_apic_bug;
+static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
 {
+	if (sis_apic_bug)
+		*IO_APIC_BASE(apic) = reg;
 	*(IO_APIC_BASE(apic)+4) = value;
 }
 
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-i386/pgtable.h	Wed Nov 27 14:36:31 2002
@@ -256,7 +256,7 @@
 
 /* Find an entry in the third-level page table.. */
 #define __pte_offset(address) \
-		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
 	((pte_t *) pmd_page_kernel(*(dir)) +  __pte_offset(address))
 
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	Wed Nov 27 14:36:27 2002
+++ b/include/asm-i386/processor.h	Wed Nov 27 14:36:27 2002
@@ -221,6 +221,9 @@
 /*
  *      NSC/Cyrix CPU configuration register indexes
  */
+
+#define CX86_PCR0 0x20
+#define CX86_GCR  0xb8
 #define CX86_CCR0 0xc0
 #define CX86_CCR1 0xc1
 #define CX86_CCR2 0xc2
@@ -229,6 +232,7 @@
 #define CX86_CCR5 0xe9
 #define CX86_CCR6 0xea
 #define CX86_CCR7 0xeb
+#define CX86_PCR1 0xf0
 #define CX86_DIR0 0xfe
 #define CX86_DIR1 0xff
 #define CX86_ARR_BASE 0xc4
diff -Nru a/include/asm-i386/string-486.h b/include/asm-i386/string-486.h
--- a/include/asm-i386/string-486.h	Wed Nov 27 14:36:28 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,617 +0,0 @@
-#ifndef _I386_STRING_I486_H_
-#define _I386_STRING_I486_H_
-
-/*
- * This string-include defines all string functions as inline
- * functions. Use gcc. It also assumes ds=es=data space, this should be
- * normal. Most of the string-functions are rather heavily hand-optimized,
- * see especially strsep,strstr,str[c]spn. They should work, but are not
- * very easy to understand. Everything is done entirely within the register
- * set, making the functions fast and clean. 
- *
- *		Copyright (C) 1991, 1992 Linus Torvalds
- *		Revised and optimized for i486/pentium
- *		1994/03/15 by Alberto Vignani/Davide Parodi @crf.it
- *
- *	Split into 2 CPU specific files by Alan Cox to keep #ifdef noise down.
- *
- *	1999/10/5	Proper register args for newer GCCs and minor bugs
- *			fixed - Petko Manolov (petkan@spct.net)
- *	1999/10/14	3DNow memscpy() added - Petkan
- *	2000/05/09	extern changed to static in function definitions
- *			and a few cleanups - Petkan
- */
-
-#define __HAVE_ARCH_STRCPY
-static inline char * strcpy(char * dest,const char *src)
-{
-register char *tmp= (char *)dest;
-register char dummy;
-__asm__ __volatile__(
-	"\n1:\t"
-	"movb (%0),%2\n\t"
-	"incl %0\n\t"
-	"movb %2,(%1)\n\t"
-	"incl %1\n\t"
-	"testb %2,%2\n\t"
-	"jne 1b"
-	:"=r" (src), "=r" (tmp), "=q" (dummy)
-	:"0" (src), "1" (tmp)
-	:"memory");
-return dest;
-}
-
-#define __HAVE_ARCH_STRNCPY
-static inline char * strncpy(char * dest,const char *src,size_t count)
-{
-register char *tmp= (char *)dest;
-register char dummy;
-if (count) {
-__asm__ __volatile__(
-	"\n1:\t"
-	"movb (%0),%2\n\t"
-	"incl %0\n\t"
-	"movb %2,(%1)\n\t"
-	"incl %1\n\t"
-	"decl %3\n\t"
-	"je 3f\n\t"
-	"testb %2,%2\n\t"
-	"jne 1b\n\t"
-	"2:\tmovb %2,(%1)\n\t"
-	"incl %1\n\t"
-	"decl %3\n\t"
-	"jne 2b\n\t"
-	"3:"
-	:"=r" (src), "=r" (tmp), "=q" (dummy), "=r" (count)
-	:"0" (src), "1" (tmp), "3" (count)
-	:"memory");
-    } /* if (count) */
-return dest;
-}
-
-#define __HAVE_ARCH_STRCAT
-static inline char * strcat(char * dest,const char * src)
-{
-register char *tmp = (char *)(dest-1);
-register char dummy;
-__asm__ __volatile__(
-	"\n1:\tincl %1\n\t"
-	"cmpb $0,(%1)\n\t"
-	"jne 1b\n"
-	"2:\tmovb (%2),%b0\n\t"
-	"incl %2\n\t"
-	"movb %b0,(%1)\n\t"
-	"incl %1\n\t"
-	"testb %b0,%b0\n\t"
-	"jne 2b\n"
-	:"=q" (dummy), "=r" (tmp), "=r" (src)
-	:"1"  (tmp), "2"  (src)
-	:"memory");
-return dest;
-}
-
-#define __HAVE_ARCH_STRNCAT
-static inline char * strncat(char * dest,const char * src,size_t count)
-{
-register char *tmp = (char *)(dest-1);
-register char dummy;
-__asm__ __volatile__(
-	"\n1:\tincl %1\n\t"
-	"cmpb $0,(%1)\n\t"
-	"jne 1b\n"
-	"2:\tdecl %3\n\t"
-	"js 3f\n\t"
-	"movb (%2),%b0\n\t"
-	"incl %2\n\t"
-	"movb %b0,(%1)\n\t"
-	"incl %1\n\t"
-	"testb %b0,%b0\n\t"
-	"jne 2b\n"
-	"3:\txorb %0,%0\n\t"
-	"movb %b0,(%1)\n\t"
-	:"=q" (dummy), "=r" (tmp), "=r" (src), "=r" (count)
-	:"1"  (tmp), "2"  (src), "3"  (count)
-	:"memory");
-return dest;
-}
-
-#define __HAVE_ARCH_STRCMP
-static inline int strcmp(const char * cs,const char * ct)
-{
-register int __res;
-__asm__ __volatile__(
-	"\n1:\tmovb (%1),%b0\n\t"
-	"incl %1\n\t"
-	"cmpb %b0,(%2)\n\t"
-	"jne 2f\n\t"
-	"incl %2\n\t"
-	"testb %b0,%b0\n\t"
-	"jne 1b\n\t"
-	"xorl %0,%0\n\t"
-	"jmp 3f\n"
-	"2:\tmovl $1,%0\n\t"
-	"jb 3f\n\t"
-	"negl %0\n"
-	"3:"
-	:"=q" (__res), "=r" (cs), "=r" (ct)
-	:"1" (cs), "2" (ct)
-	: "memory" );
-return __res;
-}
-
-#define __HAVE_ARCH_STRNCMP
-static inline int strncmp(const char * cs,const char * ct,size_t count)
-{
-register int __res;
-__asm__ __volatile__(
-	"\n1:\tdecl %3\n\t"
-	"js 2f\n\t"
-	"movb (%1),%b0\n\t"
-	"incl %1\n\t"
-	"cmpb %b0,(%2)\n\t"
-	"jne 3f\n\t"
-	"incl %2\n\t"
-	"testb %b0,%b0\n\t"
-	"jne 1b\n"
-	"2:\txorl %0,%0\n\t"
-	"jmp 4f\n"
-	"3:\tmovl $1,%0\n\t"
-	"jb 4f\n\t"
-	"negl %0\n"
-	"4:"
-	:"=q" (__res), "=r" (cs), "=r" (ct), "=r" (count)
-	:"1"  (cs), "2"  (ct),  "3" (count));
-return __res;
-}
-
-#define __HAVE_ARCH_STRCHR
-static inline char * strchr(const char * s, int c)
-{
-register char * __res;
-__asm__ __volatile__(
-	"movb %%al,%%ah\n"
-	"1:\tmovb (%1),%%al\n\t"
-	"cmpb %%ah,%%al\n\t"
-	"je 2f\n\t"
-	"incl %1\n\t"
-	"testb %%al,%%al\n\t"
-	"jne 1b\n\t"
-	"xorl %1,%1\n"
-	"2:\tmovl %1,%0\n\t"
-	:"=a" (__res), "=r" (s)
-	:"0" (c),      "1"  (s));
-return __res;
-}
-
-#define __HAVE_ARCH_STRRCHR
-static inline char * strrchr(const char * s, int c)
-{
-int	d0, d1;
-register char * __res;
-__asm__ __volatile__(
-	"movb %%al,%%ah\n"
-	"1:\tlodsb\n\t"
-	"cmpb %%ah,%%al\n\t"
-	"jne 2f\n\t"
-	"leal -1(%%esi),%0\n"
-	"2:\ttestb %%al,%%al\n\t"
-	"jne 1b"
-	:"=d" (__res), "=&S" (d0), "=&a" (d1)
-	:"0" (0), "1" (s), "2" (c));
-return __res;
-}
-
-
-#define __HAVE_ARCH_STRCSPN
-static inline size_t strcspn(const char * cs, const char * ct)
-{
-int	d0, d1;
-register char * __res;
-__asm__ __volatile__(
-	"movl %6,%%edi\n\t"
-	"repne\n\t"
-	"scasb\n\t"
-	"notl %%ecx\n\t"
-	"decl %%ecx\n\t"
-	"movl %%ecx,%%edx\n"
-	"1:\tlodsb\n\t"
-	"testb %%al,%%al\n\t"
-	"je 2f\n\t"
-	"movl %6,%%edi\n\t"
-	"movl %%edx,%%ecx\n\t"
-	"repne\n\t"
-	"scasb\n\t"
-	"jne 1b\n"
-	"2:\tdecl %0"
-	:"=S" (__res), "=&a" (d0), "=&c" (d1)
-	:"0" (cs), "1" (0), "2" (0xffffffff), "g" (ct)
-	:"dx", "di");
-return __res-cs;
-}
-
-
-#define __HAVE_ARCH_STRLEN
-static inline size_t strlen(const char * s)
-{
-/*
- * slightly slower on a 486, but with better chances of
- * register allocation
- */
-register char dummy, *tmp= (char *)s;
-__asm__ __volatile__(
-	"\n1:\t"
-	"movb\t(%0),%1\n\t"
-	"incl\t%0\n\t"
-	"testb\t%1,%1\n\t"
-	"jne\t1b"
-	:"=r" (tmp),"=q" (dummy)
-	:"0" (s)
-	: "memory" );
-return (tmp-s-1);
-}
-
-/* Added by Gertjan van Wingerde to make minix and sysv module work */
-#define __HAVE_ARCH_STRNLEN
-static inline size_t strnlen(const char * s, size_t count)
-{
-int	d0;
-register int __res;
-__asm__ __volatile__(
-	"movl %3,%0\n\t"
-	"jmp 2f\n"
-	"1:\tcmpb $0,(%0)\n\t"
-	"je 3f\n\t"
-	"incl %0\n"
-	"2:\tdecl %2\n\t"
-	"cmpl $-1,%2\n\t"
-	"jne 1b\n"
-	"3:\tsubl %3,%0"
-	:"=a" (__res), "=&d" (d0)
-	:"1" (count), "c" (s));
-return __res;
-}
-/* end of additional stuff */
-
-
-/*
- *	These ought to get tweaked to do some cache priming.
- */
- 
-static inline void * __memcpy_by4(void * to, const void * from, size_t n)
-{
-register void *tmp = (void *)to;
-register int dummy1,dummy2;
-__asm__ __volatile__ (
-	"\n1:\tmovl (%2),%0\n\t"
-	"addl $4,%2\n\t"
-	"movl %0,(%1)\n\t"
-	"addl $4,%1\n\t"
-	"decl %3\n\t"
-	"jnz 1b"
-	:"=r" (dummy1), "=r" (tmp), "=r" (from), "=r" (dummy2) 
-	:"1" (tmp), "2" (from), "3" (n/4)
-	:"memory");
-return (to);
-}
-
-static inline void * __memcpy_by2(void * to, const void * from, size_t n)
-{
-register void *tmp = (void *)to;
-register int dummy1,dummy2;
-__asm__ __volatile__ (
-	"shrl $1,%3\n\t"
-	"jz 2f\n"                 /* only a word */
-	"1:\tmovl (%2),%0\n\t"
-	"addl $4,%2\n\t"
-	"movl %0,(%1)\n\t"
-	"addl $4,%1\n\t"
-	"decl %3\n\t"
-	"jnz 1b\n"
-	"2:\tmovw (%2),%w0\n\t"
-	"movw %w0,(%1)"
-	:"=r" (dummy1), "=r" (tmp), "=r" (from), "=r" (dummy2) 
-	:"1" (tmp), "2" (from), "3" (n/2)
-	:"memory");
-return (to);
-}
-
-static inline void * __memcpy_g(void * to, const void * from, size_t n)
-{
-int	d0, d1, d2;
-register void *tmp = (void *)to;
-__asm__ __volatile__ (
-	"shrl $1,%%ecx\n\t"
-	"jnc 1f\n\t"
-	"movsb\n"
-	"1:\tshrl $1,%%ecx\n\t"
-	"jnc 2f\n\t"
-	"movsw\n"
-	"2:\trep\n\t"
-	"movsl"
-	:"=&c" (d0), "=&D" (d1), "=&S" (d2)
-	:"0" (n), "1" ((long) tmp), "2" ((long) from)
-	:"memory");
-return (to);
-}
-
-#define __memcpy_c(d,s,count) \
-((count%4==0) ? \
- __memcpy_by4((d),(s),(count)) : \
- ((count%2==0) ? \
-  __memcpy_by2((d),(s),(count)) : \
-  __memcpy_g((d),(s),(count))))
-  
-#define __memcpy(d,s,count) \
-(__builtin_constant_p(count) ? \
- __memcpy_c((d),(s),(count)) : \
- __memcpy_g((d),(s),(count)))
- 
-#define __HAVE_ARCH_MEMCPY
-
-#include <linux/config.h>
-
-#ifdef CONFIG_X86_USE_3DNOW
-
-#include <asm/mmx.h>
-
-/*
-**      This CPU favours 3DNow strongly (eg AMD K6-II, K6-III, Athlon)
-*/
-
-static inline void * __constant_memcpy3d(void * to, const void * from, size_t len)
-{
-	if (len < 512)
-		return __memcpy_c(to, from, len);
-	return _mmx_memcpy(to, from, len);
-}
-
-static inline void *__memcpy3d(void *to, const void *from, size_t len)
-{
-	if(len < 512)
-		return __memcpy_g(to, from, len);
-	return _mmx_memcpy(to, from, len);
-}
-
-#define memcpy(d, s, count) \
-(__builtin_constant_p(count) ? \
- __constant_memcpy3d((d),(s),(count)) : \
- __memcpy3d((d),(s),(count)))
- 
-#else /* CONFIG_X86_USE_3DNOW */
-
-/*
-**	Generic routines
-*/
-
-
-#define memcpy(d, s, count) __memcpy(d, s, count)
-
-#endif /* CONFIG_X86_USE_3DNOW */ 
-
-
-extern void __struct_cpy_bug( void );
-
-#define struct_cpy(x,y)				\
-({						\
-	if (sizeof(*(x)) != sizeof(*(y)))	\
-		__struct_cpy_bug;		\
-	memcpy(x, y, sizeof(*(x)));		\
-})
-
-
-#define __HAVE_ARCH_MEMMOVE
-static inline void * memmove(void * dest,const void * src, size_t n)
-{
-int	d0, d1, d2;
-register void *tmp = (void *)dest;
-if (dest<src)
-__asm__ __volatile__ (
-	"rep\n\t"
-	"movsb"
-	:"=&c" (d0), "=&S" (d1), "=&D" (d2)
-	:"0" (n), "1" (src), "2" (tmp)
-	:"memory");
-else
-__asm__ __volatile__ (
-	"std\n\t"
-	"rep\n\t"
-	"movsb\n\t"
-	"cld"
-	:"=&c" (d0), "=&S" (d1), "=&D" (d2)
-	:"0" (n), "1" (n-1+(const char *)src), "2" (n-1+(char *)tmp)
-	:"memory");
-return dest;
-}
-
-
-#define	__HAVE_ARCH_MEMCMP
-static inline int memcmp(const void * cs,const void * ct,size_t count)
-{
-int	d0, d1, d2;
-register int __res;
-__asm__ __volatile__(
-	"repe\n\t"
-	"cmpsb\n\t"
-	"je 1f\n\t"
-	"sbbl %0,%0\n\t"
-	"orb $1,%b0\n"
-	"1:"
-	:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
-	:"0" (0), "1" (cs), "2" (ct), "3" (count));
-return __res;
-}
-
-
-#define __HAVE_ARCH_MEMCHR
-static inline void * memchr(const void * cs,int c,size_t count)
-{
-int	d0;
-register void * __res;
-if (!count)
-	return NULL;
-__asm__ __volatile__(
-	"repne\n\t"
-	"scasb\n\t"
-	"je 1f\n\t"
-	"movl $1,%0\n"
-	"1:\tdecl %0"
-	:"=D" (__res), "=&c" (d0)
-	:"a" (c), "0" (cs), "1" (count));
-return __res;
-}
-
-#define __memset_cc(s,c,count) \
-((count%4==0) ? \
- __memset_cc_by4((s),(c),(count)) : \
- ((count%2==0) ? \
-  __memset_cc_by2((s),(c),(count)) : \
-  __memset_cg((s),(c),(count))))
-
-#define __memset_gc(s,c,count) \
-((count%4==0) ? \
- __memset_gc_by4((s),(c),(count)) : \
- ((count%2==0) ? \
-  __memset_gc_by2((s),(c),(count)) : \
-  __memset_gg((s),(c),(count))))
-
-#define __HAVE_ARCH_MEMSET
-#define memset(s,c,count) \
-(__builtin_constant_p(c) ? \
- (__builtin_constant_p(count) ? \
-  __memset_cc((s),(c),(count)) : \
-  __memset_cg((s),(c),(count))) : \
- (__builtin_constant_p(count) ? \
-  __memset_gc((s),(c),(count)) : \
-  __memset_gg((s),(c),(count))))
-
-static inline void * __memset_cc_by4(void * s, char c, size_t count)
-{
-/*
- * register char *tmp = s;
- */
-register char *tmp = (char *)s;
-register int  dummy;
-__asm__ __volatile__ (
-	"\n1:\tmovl %2,(%0)\n\t"
-	"addl $4,%0\n\t"
-	"decl %1\n\t"
-	"jnz 1b"
-	:"=r" (tmp), "=r" (dummy)
-	:"q" (0x01010101UL * (unsigned char) c), "0" (tmp), "1" (count/4)
-	:"memory");
-return s;
-}
-
-static inline void * __memset_cc_by2(void * s, char c, size_t count)
-{
-register void *tmp = (void *)s;
-register int  dummy;
-__asm__ __volatile__ (
-	"shrl $1,%1\n\t"          /* may be divisible also by 4 */
-	"jz 2f\n"
-	"\n1:\tmovl %2,(%0)\n\t"
-	"addl $4,%0\n\t"
-	"decl %1\n\t"
-	"jnz 1b\n"
-	"2:\tmovw %w2,(%0)"
-	:"=r" (tmp), "=r" (dummy)
-	:"q" (0x01010101UL * (unsigned char) c), "0" (tmp), "1" (count/2)
-	:"memory");
-return s;
-}
-
-static inline void * __memset_gc_by4(void * s, char c, size_t count)
-{
-register void *tmp = (void *)s;
-register int dummy;
-__asm__ __volatile__ (
-	"movb %b0,%h0\n"
-	"pushw %w0\n\t"
-	"shll $16,%0\n\t"
-	"popw %w0\n"
-	"1:\tmovl %0,(%1)\n\t"
-	"addl $4,%1\n\t"
-	"decl %2\n\t"
-	"jnz 1b\n"
-	:"=q" (c), "=r" (tmp), "=r" (dummy)
-	:"0" ((unsigned) c),  "1"  (tmp), "2" (count/4)
-	:"memory");
-return s;
-}
-
-static inline void * __memset_gc_by2(void * s, char c, size_t count)
-{
-register void *tmp = (void *)s;
-register int dummy1,dummy2;
-__asm__ __volatile__ (
-	"movb %b0,%h0\n\t"
-	"shrl $1,%2\n\t"          /* may be divisible also by 4 */
-	"jz 2f\n\t"
-	"pushw %w0\n\t"
-	"shll $16,%0\n\t"
-	"popw %w0\n"
-	"1:\tmovl %0,(%1)\n\t"
-	"addl $4,%1\n\t"
-	"decl %2\n\t"
-	"jnz 1b\n"
-	"2:\tmovw %w0,(%1)"
-	:"=q" (dummy1), "=r" (tmp), "=r" (dummy2)
-	:"0" ((unsigned) c),  "1"  (tmp), "2" (count/2)
-	:"memory");
-return s;
-}
-
-static inline void * __memset_cg(void * s, char c, size_t count)
-{
-int	d0, d1;
-register void *tmp = (void *)s;
-__asm__ __volatile__ (
-	"shrl $1,%%ecx\n\t"
-	"rep\n\t"
-	"stosw\n\t"
-	"jnc 1f\n\t"
-	"movb %%al,(%%edi)\n"
-	"1:"
-	:"=&c" (d0), "=&D" (d1) 
-	:"a" (0x0101U * (unsigned char) c), "0" (count), "1" (tmp)
-	:"memory");
-return s;
-}
-
-static inline void * __memset_gg(void * s,char c,size_t count)
-{
-int	d0, d1, d2;
-register void *tmp = (void *)s;
-__asm__ __volatile__ (
-	"movb %%al,%%ah\n\t"
-	"shrl $1,%%ecx\n\t"
-	"rep\n\t"
-	"stosw\n\t"
-	"jnc 1f\n\t"
-	"movb %%al,(%%edi)\n"
-	"1:"
-	:"=&c" (d0), "=&D" (d1), "=&D" (d2)
-	:"0" (count), "1" (tmp), "2" (c)
-	:"memory");
-return s;
-}
-
-
-/*
- * find the first occurrence of byte 'c', or 1 past the area if none
- */
-#define __HAVE_ARCH_MEMSCAN
-static inline void * memscan(void * addr, int c, size_t size)
-{
-	if (!size)
-		return addr;
-	__asm__("repnz; scasb
-		jnz 1f
-		dec %%edi
-1:		"
-		: "=D" (addr), "=c" (size)
-		: "0" (addr), "1" (size), "a" (c));
-	return addr;
-}
-
-#endif
diff -Nru a/include/asm-i386/string.h b/include/asm-i386/string.h
--- a/include/asm-i386/string.h	Wed Nov 27 14:36:32 2002
+++ b/include/asm-i386/string.h	Wed Nov 27 14:36:32 2002
@@ -8,13 +8,7 @@
  * byte string operations. But on a 386 or a PPro the
  * byte string ops are faster than doing it by hand
  * (MUCH faster on a Pentium).
- *
- * Also, the byte strings actually work correctly. Forget
- * the i486 routines for now as they may be broken..
  */
-#if FIXED_486_STRING && defined(CONFIG_X86_USE_STRING_486)
-#include <asm/string-486.h>
-#else
 
 /*
  * This string-include defines all string functions as inline
@@ -525,7 +519,6 @@
 	return addr;
 }
 
-#endif /* CONFIG_X86_USE_STRING_486 */
 #endif /* __KERNEL__ */
 
 #endif
diff -Nru a/include/asm-i386/system.h b/include/asm-i386/system.h
--- a/include/asm-i386/system.h	Wed Nov 27 14:36:27 2002
+++ b/include/asm-i386/system.h	Wed Nov 27 14:36:27 2002
@@ -150,6 +150,11 @@
  * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
  * might have an implicit FPU-save as a cost, so it's not
  * clear which path to go.)
+ *
+ * cmpxchg8b must be used with the lock prefix here to allow
+ * the instruction to be executed atomically, see page 3-102
+ * of the instruction set reference 24319102.pdf. We need
+ * the reader side to see the coherent 64bit value.
  */
 static inline void __set_64bit (unsigned long long * ptr,
 		unsigned int low, unsigned int high)
@@ -158,7 +163,7 @@
 		"\n1:\t"
 		"movl (%0), %%eax\n\t"
 		"movl 4(%0), %%edx\n\t"
-		"cmpxchg8b (%0)\n\t"
+		"lock cmpxchg8b (%0)\n\t"
 		"jnz 1b"
 		: /* no outputs */
 		:	"D"(ptr),
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-i386/unistd.h	Wed Nov 27 14:36:31 2002
@@ -227,7 +227,7 @@
 #define __NR_madvise1		219	/* delete when C lib stub is removed */
 #define __NR_getdents64		220
 #define __NR_fcntl64		221
-#define __NR_security		223	/* syscall for security modules */
+/* 223 is unused */
 #define __NR_gettid		224
 #define __NR_readahead		225
 #define __NR_setxattr		226
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-ia64/processor.h	Wed Nov 27 14:36:28 2002
@@ -49,7 +49,6 @@
  * Bus types
  */
 #define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
 #define MCA_bus 0
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	Wed Nov 27 14:36:27 2002
+++ b/include/asm-ia64/unistd.h	Wed Nov 27 14:36:27 2002
@@ -222,7 +222,7 @@
 #define __NR_futex			1230
 #define __NR_sched_setaffinity		1231
 #define __NR_sched_getaffinity		1232
-#define __NR_security			1233
+/* 1233 currently unused */
 #define __NR_alloc_hugepages		1234
 #define __NR_free_hugepages		1235
 #define __NR_exit_group			1236
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-ppc/unistd.h	Wed Nov 27 14:36:28 2002
@@ -228,7 +228,7 @@
 #define __NR_futex		221
 #define __NR_sched_setaffinity	222
 #define __NR_sched_getaffinity	223
-#define __NR_security		224
+/* 224 currently unused */
 #define __NR_tuxcall		225
 #define __NR_sendfile64		226
 #define __NR_io_setup		227
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	Wed Nov 27 14:36:27 2002
+++ b/include/asm-ppc64/unistd.h	Wed Nov 27 14:36:27 2002
@@ -233,7 +233,7 @@
 #define __NR_futex		221
 #define __NR_sched_setaffinity	222     
 #define __NR_sched_getaffinity	223
-#define __NR_security		224
+/* 224 currently unused */
 #define __NR_tuxcall		225
 #define __NR_sendfile64		226
 #define __NR_io_setup		227
diff -Nru a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
--- a/include/asm-s390/unistd.h	Wed Nov 27 14:36:32 2002
+++ b/include/asm-s390/unistd.h	Wed Nov 27 14:36:32 2002
@@ -231,7 +231,9 @@
 #define __NR_futex		238
 #define __NR_sched_setaffinity	239
 #define __NR_sched_getaffinity	240
-#define __NR_security		241	/* syscall for security modules */
+/*
+ * Number 241 is currently unused
+ */
 /*
  * Number 242 is reserved for tux
  */
diff -Nru a/include/asm-s390x/unistd.h b/include/asm-s390x/unistd.h
--- a/include/asm-s390x/unistd.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-s390x/unistd.h	Wed Nov 27 14:36:31 2002
@@ -198,7 +198,9 @@
 #define __NR_futex		238
 #define __NR_sched_setaffinity	239
 #define __NR_sched_getaffinity	240
-#define __NR_security		241	/* syscall for security modules */
+/*
+ * Number 241 is currently unused
+ */
 /*
  * Number 242 is reserved for tux
  */
diff -Nru a/include/asm-sh/processor.h b/include/asm-sh/processor.h
--- a/include/asm-sh/processor.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-sh/processor.h	Wed Nov 27 14:36:28 2002
@@ -143,7 +143,6 @@
  * Bus types
  */
 #define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
 #define MCA_bus 0
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
diff -Nru a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
--- a/include/asm-sparc/elf.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-sparc/elf.h	Wed Nov 27 14:36:31 2002
@@ -32,11 +32,9 @@
 	memcpy(&dest[0], &src->u_regs[0],		\
 	       sizeof(unsigned long) * 16);		\
 	/* Don't try this at home kids... */		\
-	set_fs(USER_DS);				\
 	sp = (unsigned long *) src->u_regs[14];		\
 	copy_from_user(&dest[16], sp,			\
 		       sizeof(unsigned long) * 16);	\
-	set_fs(KERNEL_DS);				\
 	dest[32] = src->psr;				\
 	dest[33] = src->pc;				\
 	dest[34] = src->npc;				\
@@ -56,6 +54,9 @@
 	unsigned char	pr_en;
 	unsigned int	pr_q[64];
 } elf_fpregset_t;
+
+#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs)	\
+	({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread_info->kregs); 1; })
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
diff -Nru a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
--- a/include/asm-sparc/processor.h	Wed Nov 27 14:36:32 2002
+++ b/include/asm-sparc/processor.h	Wed Nov 27 14:36:32 2002
@@ -28,7 +28,6 @@
  * Bus types
  */
 #define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
 #define MCA_bus 0
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
diff -Nru a/include/asm-sparc/system.h b/include/asm-sparc/system.h
--- a/include/asm-sparc/system.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-sparc/system.h	Wed Nov 27 14:36:31 2002
@@ -169,7 +169,7 @@
 	"nop\n\t"									\
 	"nop\n\t"									\
 	"jmpl	%%o7 + 0x8, %%g0\n\t"							\
-	" ld	[%%g3 + %5], %0\n\t"								\
+	" ld	[%%g3 + %5], %0\n\t"							\
         : "=&r" (last)									\
         : "r" (&(current_set[hard_smp_processor_id()])),	\
 	  "r" ((next)->thread_info),				\
@@ -177,9 +177,10 @@
 	  "i" (TI_KSP),						\
 	  "i" (TI_TASK),					\
 	  "r" (task_pc)									\
-	: "g1", "g2", "g3", "g4", "g5", "g7", "l0", "l1",				\
-	"l4", "l5", "l6", "l7", "i0", "i1", "i2", "i3", "i4", "i5", "o0", "o1", "o2",	\
-	"o3");										\
+	:       "g1", "g2", "g3", "g4", "g5",       "g7",	\
+	  "l0", "l1",       "l3", "l4", "l5", "l6", "l7",	\
+	  "i0", "i1", "i2", "i3", "i4", "i5",			\
+	  "o0", "o1", "o2", "o3");				\
 here:;  } while(0)
 
 /*
diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
--- a/include/asm-sparc/unistd.h	Wed Nov 27 14:36:27 2002
+++ b/include/asm-sparc/unistd.h	Wed Nov 27 14:36:27 2002
@@ -171,7 +171,7 @@
 #define __NR_poll               153 /* Common                                      */
 #define __NR_getdents64		154 /* Linux specific				   */
 #define __NR_fcntl64		155 /* Linux sparc32 Specific                      */
-#define __NR_security           156 /* getdirentries under SunOS                   */
+/* #define __NR_getdirentires 	156    SunOS Specific                              */
 #define __NR_statfs             157 /* Common                                      */
 #define __NR_fstatfs            158 /* Common                                      */
 #define __NR_umount             159 /* Common                                      */
diff -Nru a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
--- a/include/asm-sparc64/elf.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-sparc64/elf.h	Wed Nov 27 14:36:28 2002
@@ -42,13 +42,11 @@
 	for(i = 0; i < 16; i++)				\
 		dest[i] = src->u_regs[i];		\
 	/* Don't try this at home kids... */		\
-	set_fs(USER_DS);				\
 	sp = (unsigned long *)				\
 	 ((src->u_regs[14] + STACK_BIAS)		\
 	  & 0xfffffffffffffff8UL);			\
 	for(i = 0; i < 16; i++)				\
 		__get_user(dest[i+16], &sp[i]);		\
-	set_fs(KERNEL_DS);				\
 	dest[32] = src->tstate;				\
 	dest[33] = src->tpc;				\
 	dest[34] = src->tnpc;				\
@@ -62,6 +60,9 @@
 	unsigned long	pr_fprs;
 } elf_fpregset_t;
 #endif
+
+#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs)	\
+	({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread_info->kregs); 1; })
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
diff -Nru a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
--- a/include/asm-sparc64/parport.h	Wed Nov 27 14:36:27 2002
+++ b/include/asm-sparc64/parport.h	Wed Nov 27 14:36:27 2002
@@ -130,7 +130,7 @@
 				unsigned long base = edev->resource[0].start;
 				unsigned long config = edev->resource[1].start;
 
-				spin_lock_init(&sparc_ebus_dmas[count].info);
+				spin_lock_init(&sparc_ebus_dmas[count].info.lock);
 				sparc_ebus_dmas[count].info.regs =
 					edev->resource[2].start;
 				if (!sparc_ebus_dmas[count].info.regs)
diff -Nru a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
--- a/include/asm-sparc64/processor.h	Wed Nov 27 14:36:27 2002
+++ b/include/asm-sparc64/processor.h	Wed Nov 27 14:36:27 2002
@@ -25,7 +25,6 @@
 
 /* Bus types */
 #define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
 #define MCA_bus 0
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-sparc64/unistd.h	Wed Nov 27 14:36:28 2002
@@ -171,7 +171,7 @@
 #define __NR_poll               153 /* Common                                      */
 #define __NR_getdents64		154 /* Linux specific				   */
 /* #define __NR_fcntl64         155    Linux sparc32 Specific                      */
-#define __NR_security           156 /* getdirentries under SunOS                   */
+/* #define __NR_getdirentries   156    SunOS Specific                              */
 #define __NR_statfs             157 /* Common                                      */
 #define __NR_fstatfs            158 /* Common                                      */
 #define __NR_umount             159 /* Common                                      */
diff -Nru a/include/asm-v850/anna.h b/include/asm-v850/anna.h
--- a/include/asm-v850/anna.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-v850/anna.h	Wed Nov 27 14:36:28 2002
@@ -127,6 +127,22 @@
 				     unsigned cflags, unsigned baud);
 #endif
 
+/* This board supports RTS/CTS for the on-chip UART, but only for channel 1. */
+
+/* CTS for UART channel 1 is pin P37 (bit 7 of port 3).  */
+#define NB85E_UART_CTS(chan)	((chan) == 1 ? !(ANNA_PORT_IO(3) & 0x80) : 1)
+/* RTS for UART channel 1 is pin P07 (bit 7 of port 0).  */
+#define NB85E_UART_SET_RTS(chan, val)					      \
+   do {									      \
+	   if (chan == 1) {						      \
+		   unsigned old = ANNA_PORT_IO(0); 			      \
+		   if (val)						      \
+			   ANNA_PORT_IO(0) = old & ~0x80;		      \
+		   else							      \
+			   ANNA_PORT_IO(0) = old | 0x80;		      \
+	   }								      \
+   } while (0)
+
 
 /* Timer C details.  */
 #define NB85E_TIMER_C_BASE_ADDR		0xFFFFF600
diff -Nru a/include/asm-v850/as85ep1.h b/include/asm-v850/as85ep1.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/as85ep1.h	Wed Nov 27 14:36:32 2002
@@ -0,0 +1,160 @@
+/*
+ * include/asm-v850/as85ep1.h -- AS85EP1 evaluation CPU chip/board
+ *
+ *  Copyright (C) 2001,2002  NEC Corporation
+ *  Copyright (C) 2001,2002  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_AS85EP1_H__
+#define __V850_AS85EP1_H__
+
+
+#define CPU_ARCH 	"v850e"
+#define CPU_MODEL	"as85ep1"
+#define CPU_MODEL_LONG	"NEC V850E/AS85EP1"
+#define PLATFORM	"AS85EP1"
+#define PLATFORM_LONG	"NEC V850E/AS85EP1 evaluation board"
+
+#define CPU_CLOCK_FREQ	96000000 /*  96MHz */
+#define SYS_CLOCK_FREQ	CPU_CLOCK_FREQ
+
+
+/* 1MB of static RAM.  */
+#define SRAM_ADDR	0x00400000
+#define SRAM_SIZE	0x00100000 /* 1MB */
+/* About 58MB of DRAM.  This can actually be at one of two positions,
+   determined by jump JP3; we have to use the first position because the
+   second is partially out of processor instruction addressing range
+   (though in the second position there's actually 64MB available).  */
+#define SDRAM_ADDR	0x00600000
+#define SDRAM_SIZE	0x039F8000 /* approx 58MB */
+
+/* For <asm/page.h> */
+#define PAGE_OFFSET 	SRAM_ADDR
+
+/* We use on-chip RAM, for a few miscellaneous variables that must be
+   accessible using a load instruction relative to R0.  The AS85EP1 chip
+   16K of internal RAM located slightly before I/O space.  */
+#define R0_RAM_ADDR	0xFFFF8000
+
+
+/* AS85EP1 specific control registers.  */
+#define AS85EP1_CSC_ADDR(n)	(0xFFFFF060 + (n) * 2)
+#define AS85EP1_CSC(n)		(*(volatile u16 *)AS85EP1_CSC_ADDR(n))
+#define AS85EP1_BSC_ADDR	0xFFFFF066
+#define AS85EP1_BSC		(*(volatile u16 *)AS85EP1_BSC_ADDR)
+#define AS85EP1_BCT_ADDR(n)	(0xFFFFF480 + (n) * 2)
+#define AS85EP1_BCT(n)		(*(volatile u16 *)AS85EP1_BCT_ADDR(n))
+#define AS85EP1_DWC_ADDR(n)	(0xFFFFF484 + (n) * 2)
+#define AS85EP1_DWC(n)		(*(volatile u16 *)AS85EP1_DWC_ADDR(n))
+#define AS85EP1_BCC_ADDR	0xFFFFF488
+#define AS85EP1_BCC		(*(volatile u16 *)AS85EP1_BCC_ADDR)
+#define AS85EP1_ASC_ADDR	0xFFFFF48A
+#define AS85EP1_ASC		(*(volatile u16 *)AS85EP1_ASC_ADDR)
+#define AS85EP1_BCP_ADDR	0xFFFFF48C
+#define AS85EP1_BCP		(*(volatile u16 *)AS85EP1_BCP_ADDR)
+#define AS85EP1_LBS_ADDR	0xFFFFF48E
+#define AS85EP1_LBS		(*(volatile u16 *)AS85EP1_LBS_ADDR)
+#define AS85EP1_BMC_ADDR	0xFFFFF498
+#define AS85EP1_BMC		(*(volatile u16 *)AS85EP1_BMC_ADDR)
+#define AS85EP1_PRC_ADDR	0xFFFFF49A
+#define AS85EP1_PRC		(*(volatile u16 *)AS85EP1_PRC_ADDR)
+#define AS85EP1_SCR_ADDR(n)	(0xFFFFF4A0 + (n) * 4)
+#define AS85EP1_SCR(n)		(*(volatile u16 *)AS85EP1_SCR_ADDR(n))
+#define AS85EP1_RFS_ADDR(n)	(0xFFFFF4A2 + (n) * 4)
+#define AS85EP1_RFS(n)		(*(volatile u16 *)AS85EP1_RFS_ADDR(n))
+#define AS85EP1_IRAMM_ADDR	0xFFFFF80A
+#define AS85EP1_IRAMM		(*(volatile u8 *)AS85EP1_IRAMM_ADDR)
+
+
+
+/* I/O port P0-P13. */
+/* Direct I/O.  Bits 0-7 are pins Pn0-Pn7.  */
+#define AS85EP1_PORT_IO_ADDR(n)	(0xFFFFF400 + (n) * 2)
+#define AS85EP1_PORT_IO(n)	(*(volatile u8 *)AS85EP1_PORT_IO_ADDR(n))
+/* Port mode (for direct I/O, 0 = output, 1 = input).  */
+#define AS85EP1_PORT_PM_ADDR(n)	(0xFFFFF420 + (n) * 2)
+#define AS85EP1_PORT_PM(n)	(*(volatile u8 *)AS85EP1_PORT_PM_ADDR(n))
+/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
+#define AS85EP1_PORT_PMC_ADDR(n) (0xFFFFF440 + (n) * 2)
+#define AS85EP1_PORT_PMC(n)	(*(volatile u8 *)AS85EP1_PORT_PMC_ADDR(n))
+
+
+/* NB85E-style interrupt system.  */
+#include <asm/nb85e_intc.h>
+
+/* Hardware-specific interrupt numbers (in the kernel IRQ namespace).  */
+#define IRQ_INTCCC(n)	(0x0C + (n))
+#define IRQ_INTCCC_NUM	8
+#define IRQ_INTCMD(n)	(0x14 + (n)) /* interval timer interrupts 0-5 */
+#define IRQ_INTCMD_NUM	6
+#define IRQ_INTSRE(n)	(0x1E + (n)*3) /* UART 0-1 reception error */
+#define IRQ_INTSRE_NUM	2
+#define IRQ_INTSR(n)	(0x1F + (n)*3) /* UART 0-1 reception completion */
+#define IRQ_INTSR_NUM	2
+#define IRQ_INTST(n)	(0x20 + (n)*3) /* UART 0-1 transmission completion */
+#define IRQ_INTST_NUM	2
+
+#define NUM_CPU_IRQS	64
+
+#ifndef __ASSEMBLY__
+/* Initialize chip interrupts.  */
+extern void as85ep1_init_irqs (void);
+#endif
+
+
+/* AS85EP1 UART details (basically the same as the V850E/MA1, but 2 channels).  */
+#define NB85E_UART_NUM_CHANNELS		2
+#define NB85E_UART_BASE_FREQ		(SYS_CLOCK_FREQ / 4)
+#define NB85E_UART_CHIP_NAME 		"V850E/NA85E"
+
+/* This is a function that gets called before configuring the UART.  */
+#define NB85E_UART_PRE_CONFIGURE	as85ep1_uart_pre_configure
+#ifndef __ASSEMBLY__
+extern void as85ep1_uart_pre_configure (unsigned chan,
+					unsigned cflags, unsigned baud);
+#endif
+
+/* This board supports RTS/CTS for the on-chip UART, but only for channel 1. */
+
+/* CTS for UART channel 1 is pin P54 (bit 4 of port 5).  */
+#define NB85E_UART_CTS(chan)   ((chan) == 1 ? !(AS85EP1_PORT_IO(5) & 0x10) : 1)
+/* RTS for UART channel 1 is pin P53 (bit 3 of port 5).  */
+#define NB85E_UART_SET_RTS(chan, val)					      \
+   do {									      \
+	   if (chan == 1) {						      \
+		   unsigned old = AS85EP1_PORT_IO(5); 			      \
+		   if (val)						      \
+			   AS85EP1_PORT_IO(5) = old & ~0x8;		      \
+		   else							      \
+			   AS85EP1_PORT_IO(5) = old | 0x8;		      \
+	   }								      \
+   } while (0)
+
+
+/* Timer C details.  */
+#define NB85E_TIMER_C_BASE_ADDR		0xFFFFF600
+
+/* Timer D details (the AS85EP1 actually has 5 of these; should change later). */
+#define NB85E_TIMER_D_BASE_ADDR		0xFFFFF540
+#define NB85E_TIMER_D_TMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x0)
+#define NB85E_TIMER_D_CMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x2)
+#define NB85E_TIMER_D_TMCD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x4)
+
+#define NB85E_TIMER_D_BASE_FREQ		SYS_CLOCK_FREQ
+#define NB85E_TIMER_D_TMCD_CS_MIN	2 /* min 2^2 divider */
+
+
+/* For <asm/param.h> */
+#ifndef HZ
+#define HZ	100
+#endif
+
+
+#endif /* __V850_AS85EP1_H__ */
diff -Nru a/include/asm-v850/asm.h b/include/asm-v850/asm.h
--- a/include/asm-v850/asm.h	Wed Nov 27 14:36:30 2002
+++ b/include/asm-v850/asm.h	Wed Nov 27 14:36:30 2002
@@ -16,10 +16,17 @@
    .globl name;								      \
    .type  name,@function;						      \
    name
+#define G_DATA(name)							      \
+   .globl name;								      \
+   .type  name,@object;							      \
+   name
 #define END(name)							      \
    .size  name,.-name
 
 #define L_ENTRY(name)							      \
    .align 4;								      \
    .type  name,@function;						      \
+   name
+#define L_DATA(name)							      \
+   .type  name,@object;							      \
    name
diff -Nru a/include/asm-v850/clinkage.h b/include/asm-v850/clinkage.h
--- a/include/asm-v850/clinkage.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-v850/clinkage.h	Wed Nov 27 14:36:31 2002
@@ -20,6 +20,7 @@
 #define C_SYMBOL_NAME(name) 	macrology_paste(_, name)
 #define C_SYMBOL_STRING(name)	macrology_stringify(C_SYMBOL_NAME(name))
 #define C_ENTRY(name)		G_ENTRY(C_SYMBOL_NAME(name))
+#define C_DATA(name)		G_DATA(C_SYMBOL_NAME(name))
 #define C_END(name)		END(C_SYMBOL_NAME(name))
 
 #endif /* __V850_CLINKAGE_H__ */
diff -Nru a/include/asm-v850/elf.h b/include/asm-v850/elf.h
--- a/include/asm-v850/elf.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-v850/elf.h	Wed Nov 27 14:36:31 2002
@@ -19,7 +19,8 @@
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x) ( (x)->e_machine == EM_CYGNUS_V850 )
+#define elf_check_arch(x)  \
+  ((x)->e_machine == EM_V850 || (x)->e_machine == EM_CYGNUS_V850)
 
 /*
  * These are used to set parameters in the core dumps.
diff -Nru a/include/asm-v850/fpga85e2c.h b/include/asm-v850/fpga85e2c.h
--- a/include/asm-v850/fpga85e2c.h	Wed Nov 27 14:36:30 2002
+++ b/include/asm-v850/fpga85e2c.h	Wed Nov 27 14:36:30 2002
@@ -19,8 +19,11 @@
 #include <asm/clinkage.h>
 
 
-#define CPU_ARCH		"v850e2"
-#define CPU_MODEL		"FPGA NA85E2C/V850E2"
+#define CPU_ARCH 	"v850e2"
+#define CPU_MODEL	"v850e2/fpga85e2c"
+#define CPU_MODEL_LONG	"NEC V850E2/NA85E2C"
+#define PLATFORM	"fpga85e2c"
+#define PLATFORM_LONG	"NA85E2C FPGA implementation"
 
 
 /* `external ram'.  */
diff -Nru a/include/asm-v850/gbus_int.h b/include/asm-v850/gbus_int.h
--- a/include/asm-v850/gbus_int.h	Wed Nov 27 14:36:30 2002
+++ b/include/asm-v850/gbus_int.h	Wed Nov 27 14:36:30 2002
@@ -65,7 +65,7 @@
 /* Return true if interrupt handling for interrupt IRQ is enabled.  */
 extern int gbus_int_irq_enabled (unsigned irq);
 /* Disable all GBUS irqs.  */
-extern int gbus_int_disable_irqs (void);
+extern void gbus_int_disable_irqs (void);
 /* Clear any pending interrupts for IRQ.  */
 extern void gbus_int_clear_pending_irq (unsigned irq);
 /* Return true if interrupt IRQ is pending (but disabled).  */
diff -Nru a/include/asm-v850/hardirq.h b/include/asm-v850/hardirq.h
--- a/include/asm-v850/hardirq.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-v850/hardirq.h	Wed Nov 27 14:36:28 2002
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/threads.h>
+#include <linux/cache.h>
 
 typedef struct {
 	unsigned int __softirq_pending;
diff -Nru a/include/asm-v850/irq.h b/include/asm-v850/irq.h
--- a/include/asm-v850/irq.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-v850/irq.h	Wed Nov 27 14:36:31 2002
@@ -52,6 +52,17 @@
    interrupt.  */
 extern unsigned int handle_irq (int irq, struct pt_regs *regs);
 
+
+/* Enable interrupt handling on an irq.  */
+extern void enable_irq(unsigned int irq);
+
+/* Disable an irq and wait for completion.  */
+extern void disable_irq (unsigned int irq);
+
+/* Disable an irq without waiting. */
+extern void disable_irq_nosync (unsigned int irq);
+
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __V850_IRQ_H__ */
diff -Nru a/include/asm-v850/machdep.h b/include/asm-v850/machdep.h
--- a/include/asm-v850/machdep.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-v850/machdep.h	Wed Nov 27 14:36:28 2002
@@ -24,9 +24,12 @@
 #include <asm/teg.h>
 #endif
 
-/* Anna is both a chip _and_ a platform, so put it in the middle... */
+/* These are both chips _and_ platforms, so put them in the middle... */
 #ifdef CONFIG_V850E2_ANNA
 #include <asm/anna.h>
+#endif
+#ifdef CONFIG_V850E_AS85EP1
+#include <asm/as85ep1.h>
 #endif
 
 /* platforms */
diff -Nru a/include/asm-v850/module.h b/include/asm-v850/module.h
--- a/include/asm-v850/module.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-v850/module.h	Wed Nov 27 14:36:28 2002
@@ -3,20 +3,40 @@
  *
  *  Copyright (C) 2001,02  NEC Corporation
  *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001  Rusty Russell
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
  * archive for more details.
  *
  * Written by Miles Bader <miles@gnu.org>
+ *
+ * Derived in part from include/asm-ppc/module.h
  */
 
 #ifndef __V850_MODULE_H__
 #define __V850_MODULE_H__
 
-#define arch_init_modules(x)	((void)0)
-#define module_arch_init(x)	(0)
-#define module_map(sz)		vmalloc (sz)
-#define module_unmap(sz)	vfree (sz)
+#define MODULE_SYMBOL_PREFIX "_"
+
+struct v850_plt_entry
+{
+	/* Indirect jump instruction sequence (6-byte mov + 2-byte jr).  */
+	unsigned long tramp[2];
+};
+
+struct mod_arch_specific
+{
+	/* How much of the core is actually taken up with core (then
+           we know the rest is for the PLT).  */
+	unsigned int core_plt_offset;
+
+	/* Same for init.  */
+	unsigned int init_plt_offset;
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
 
 #endif /* __V850_MODULE_H__ */
diff -Nru a/include/asm-v850/nb85e_uart.h b/include/asm-v850/nb85e_uart.h
--- a/include/asm-v850/nb85e_uart.h	Wed Nov 27 14:36:32 2002
+++ b/include/asm-v850/nb85e_uart.h	Wed Nov 27 14:36:32 2002
@@ -43,6 +43,9 @@
 #define NB85E_UART_BRGC_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x7)
 #endif
 
+#ifndef NB85E_UART_CKSR_MAX_FREQ
+#define NB85E_UART_CKSR_MAX_FREQ (25*1000*1000)
+#endif
 
 /* UART config registers.  */
 #define NB85E_UART_ASIM(n)	(*(volatile u8 *)NB85E_UART_ASIM_ADDR(n))
@@ -81,7 +84,6 @@
 /* UART baud-rate generator control registers.  */
 #define NB85E_UART_CKSR(n)	(*(volatile u8 *)NB85E_UART_CKSR_ADDR(n))
 #define NB85E_UART_CKSR_MAX	11
-#define NB85E_UART_CKSR_MAX_FREQ (25*1000*1000)
 #define NB85E_UART_BRGC(n)	(*(volatile u8 *)NB85E_UART_BRGC_ADDR(n))
 
 
diff -Nru a/include/asm-v850/percpu.h b/include/asm-v850/percpu.h
--- a/include/asm-v850/percpu.h	Wed Nov 27 14:36:30 2002
+++ b/include/asm-v850/percpu.h	Wed Nov 27 14:36:30 2002
@@ -3,4 +3,12 @@
 
 #include <asm-generic/percpu.h>
 
+/* This is a stupid hack to satisfy some grotty implicit include-file
+   dependency; basically, <linux/smp.h> uses BUG_ON, which calls BUG, but
+   doesn't include the necessary headers to define it.  In the twisted
+   festering mess of includes this must all be resolved somehow on other
+   platforms, but I haven't the faintest idea how, and don't care; here will
+   do, even though doesn't actually make any sense.  */
+#include <asm/page.h>
+
 #endif /* __V850_PERCPU_H__ */
diff -Nru a/include/asm-v850/processor.h b/include/asm-v850/processor.h
--- a/include/asm-v850/processor.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-v850/processor.h	Wed Nov 27 14:36:28 2002
@@ -30,6 +30,12 @@
  */
 #define TASK_SIZE	(0xFFFFFFFF)
 
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.  We won't be using it.
+ */
+#define TASK_UNMAPPED_BASE	0
+
 
 #ifndef __ASSEMBLY__
 
diff -Nru a/include/asm-v850/sim.h b/include/asm-v850/sim.h
--- a/include/asm-v850/sim.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-v850/sim.h	Wed Nov 27 14:36:28 2002
@@ -16,7 +16,10 @@
 
 
 #define CPU_ARCH		"v850e"
-#define CPU_MODEL		"GDB/v850e simulator"
+#define CPU_MODEL		"v850e"
+#define CPU_MODEL_LONG		"NEC V850E"
+#define PLATFORM		"gdb/v850e"
+#define PLATFORM_LONG		"GDB V850E simulator"
 
 
 /* We use a wierd value for RAM, not just 0, for testing purposes.
diff -Nru a/include/asm-v850/sim85e2c.h b/include/asm-v850/sim85e2c.h
--- a/include/asm-v850/sim85e2c.h	Wed Nov 27 14:36:28 2002
+++ b/include/asm-v850/sim85e2c.h	Wed Nov 27 14:36:28 2002
@@ -16,8 +16,11 @@
 #define __V850_SIM85E2C_H__
 
 
-#define CPU_ARCH		"v850e2"
-#define CPU_MODEL		"sim85e2c simulator"
+#define CPU_ARCH 	"v850e2"
+#define CPU_MODEL	"v850e2"
+#define CPU_MODEL_LONG	"NEC V850E2"
+#define PLATFORM	"sim85e2c"
+#define PLATFORM_LONG	"SIM85E2C V850E2 simulator"
 
 
 /* Various memory areas supported by the simulator.
diff -Nru a/include/asm-v850/stat.h b/include/asm-v850/stat.h
--- a/include/asm-v850/stat.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-v850/stat.h	Wed Nov 27 14:36:31 2002
@@ -46,13 +46,13 @@
 	unsigned long	__unused4; /* future possible st_blocks high bits */
 
 	unsigned long	st_atime;
-	unsigned long	__unused5;
+	unsigned long	st_atime_nsec;
 
 	unsigned long	st_mtime;
-	unsigned long	__unused6;
+	unsigned long	st_mtime_nsec;
 
 	unsigned long	st_ctime;
-	unsigned long	__unused7; /* high 32 bits of ctime someday */
+	unsigned long	st_ctime_nsec;
 
 	unsigned long	__unused8;
 };
diff -Nru a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h
--- a/include/asm-v850/unistd.h	Wed Nov 27 14:36:32 2002
+++ b/include/asm-v850/unistd.h	Wed Nov 27 14:36:32 2002
@@ -239,11 +239,18 @@
 #define SYSCALL_SHORT_CLOBBERS	SYSCALL_CLOBBERS, "r13", "r14"
 
 
+/* User programs sometimes end up including this header file
+   (indirectly, via uClibc header files), so I'm a bit nervous just
+   including <linux/compiler.h>.  */
+#if !defined(__builtin_expect) && __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#define __builtin_expect(x, expected_value) (x)
+#endif
+
 #define __syscall_return(type, res)					      \
   do {									      \
 	  /* user-visible error numbers are in the range -1 - -124:	      \
 	     see <asm-v850/errno.h> */					      \
-	  if ((unsigned long)(res) >= (unsigned long)(-125)) {		      \
+	  if (__builtin_expect ((unsigned long)(res) >= (unsigned long)(-125), 0)) { \
 		  errno = -(res);					      \
 		  res = -1;						      \
 	  }								      \
@@ -340,6 +347,30 @@
   __syscall_return (type, __ret);					      \
 }
 
+#if __GNUC__ < 3
+/* In older versions of gcc, `asm' statements with more than 10
+   input/output arguments produce a fatal error.  To work around this
+   problem, we use two versions, one for gcc-3.x and one for earlier
+   versions of gcc (the `earlier gcc' version doesn't work with gcc-3.x
+   because gcc-3.x doesn't allow clobbers to also be input arguments).  */
+#define __SYSCALL6_TRAP(syscall, ret, a, b, c, d, e, f)			      \
+  __asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP			      \
+			: "=r" (ret), "=r" (syscall)			      \
+			: "1" (syscall),				      \
+			"r" (a), "r" (b), "r" (c), "r" (d),		      \
+ 			"r" (e), "r" (f)				      \
+			: SYSCALL_CLOBBERS, SYSCALL_ARG4, SYSCALL_ARG5);
+#else /* __GNUC__ >= 3 */
+#define __SYSCALL6_TRAP(syscall, ret, a, b, c, d, e, f)			      \
+  __asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP			      \
+			: "=r" (ret), "=r" (syscall),			      \
+ 			"=r" (e), "=r" (f)				      \
+			: "1" (syscall),				      \
+			"r" (a), "r" (b), "r" (c), "r" (d),		      \
+			"2" (e), "3" (f)				      \
+			: SYSCALL_CLOBBERS);
+#endif
+
 #define _syscall6(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \
 type name (atype a, btype b, ctype c, dtype d, etype e, ftype f)	      \
 {									      \
@@ -351,13 +382,7 @@
   register etype __f __asm__ (SYSCALL_ARG5) = f;			      \
   register unsigned long __syscall __asm__ (SYSCALL_NUM) = __NR_##name;	      \
   register unsigned long __ret __asm__ (SYSCALL_RET);			      \
-  __asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP			      \
-			: "=r" (__ret), "=r" (__syscall), 		      \
- 			"=r" (__e), "=r" (__f)				      \
-			: "1" (__syscall),				      \
-			"r" (__a), "r" (__b), "r" (__c), "r" (__d),	      \
-			"2" (__e), "3" (__f)				      \
-			: SYSCALL_CLOBBERS);				      \
+  __SYSCALL6_TRAP(__syscall, __ret, __a, __b, __c, __d, __e, __f);	      \
   __syscall_return (type, __ret);					      \
 }
 		
@@ -398,8 +423,8 @@
 /*
  * "Conditional" syscalls
  */
-#define cond_syscall(name)						\
-  asm (".weak\t" C_SYMBOL_STRING(name) ";"				\
+#define cond_syscall(name)						      \
+  asm (".weak\t" C_SYMBOL_STRING(name) ";"				      \
        ".set\t" C_SYMBOL_STRING(name) "," C_SYMBOL_STRING(sys_ni_syscall));
 #if 0
 /* This doesn't work if there's a function prototype for NAME visible,
diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
--- a/include/asm-x86_64/unistd.h	Wed Nov 27 14:36:31 2002
+++ b/include/asm-x86_64/unistd.h	Wed Nov 27 14:36:31 2002
@@ -426,8 +426,7 @@
 #define __NR_tuxcall      		184 /* reserved for tux */
 __SYSCALL(__NR_tuxcall, sys_ni_syscall)
 
-#define __NR_security			185 /* reserved for LSM/security */
-__SYSCALL(__NR_security, sys_ni_syscall)
+/* 165 currently unused */
 
 #define __NR_gettid		186
 __SYSCALL(__NR_gettid, sys_gettid)
diff -Nru a/include/linux/dvb/ca.h b/include/linux/dvb/ca.h
--- a/include/linux/dvb/ca.h	Wed Nov 27 14:36:32 2002
+++ b/include/linux/dvb/ca.h	Wed Nov 27 14:36:32 2002
@@ -26,7 +26,7 @@
 
 /* slot interface types and info */
 
-typedef struct ca_slot_info_s {
+typedef struct ca_slot_info {
         int num;               /* slot number */
 
         int type;              /* CA interface this slot supports */
@@ -43,7 +43,7 @@
 
 /* descrambler types and info */
 
-typedef struct ca_descr_info_s {
+typedef struct ca_descr_info {
         unsigned int num;          /* number of available descramblers (keys) */ 
         unsigned int type;         /* type of supported scrambling system */
 #define CA_ECD           1
@@ -51,29 +51,29 @@
 #define CA_DSS           4
 } ca_descr_info_t;
 
-typedef struct ca_cap_s {
+typedef struct ca_caps {
         unsigned int slot_num;     /* total number of CA card and module slots */
         unsigned int slot_type;    /* OR of all supported types */
         unsigned int descr_num;    /* total number of descrambler slots (keys) */
         unsigned int descr_type;   /* OR of all supported types */
-} ca_cap_t;
+} ca_caps_t;
 
 /* a message to/from a CI-CAM */
-typedef struct ca_msg_s {   
+typedef struct ca_msg {   
         unsigned int index;         
         unsigned int type;
         unsigned int length;
         unsigned char msg[256];
 } ca_msg_t;
 
-typedef struct ca_descr_s {
+typedef struct ca_descr {
         unsigned int index;    
         unsigned int parity;
         unsigned char cw[8];
 } ca_descr_t;
 
 #define CA_RESET          _IO('o', 128)
-#define CA_GET_CAP        _IOR('o', 129, ca_cap_t)
+#define CA_GET_CAP        _IOR('o', 129, ca_caps_t)
 #define CA_GET_SLOT_INFO  _IOR('o', 130, ca_slot_info_t)
 #define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
 #define CA_GET_MSG        _IOR('o', 132, ca_msg_t)
diff -Nru a/include/linux/dvb/osd.h b/include/linux/dvb/osd.h
--- a/include/linux/dvb/osd.h	Wed Nov 27 14:36:31 2002
+++ b/include/linux/dvb/osd.h	Wed Nov 27 14:36:31 2002
@@ -26,7 +26,7 @@
 
 typedef enum {
 	// All functions return -2 on "not open"
-	OSD_Close = 1,		// ()
+  OSD_Close=1,    // ()
 	// Disables OSD and releases the buffers
 	// returns 0 on success
 	OSD_Open,		// (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0))
@@ -108,3 +108,4 @@
 #define OSD_SEND_CMD       _IOW('o', 160, osd_cmd_t)
 
 #endif
+
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Wed Nov 27 14:36:29 2002
+++ b/include/linux/ide.h	Wed Nov 27 14:36:29 2002
@@ -299,9 +299,9 @@
 
 typedef struct ide_io_ops_s {
 	/* insert io operations here! */
-	void (*OUTB)(u8 addr, ide_ioreg_t port);
-	void (*OUTW)(u16 addr, ide_ioreg_t port);
-	void (*OUTL)(u32 addr, ide_ioreg_t port);
+	void (*OUTB)(u8 value, ide_ioreg_t port);
+	void (*OUTW)(u16 value, ide_ioreg_t port);
+	void (*OUTL)(u32 value, ide_ioreg_t port);
 	void (*OUTSW)(ide_ioreg_t port, void *addr, u32 count);
 	void (*OUTSL)(ide_ioreg_t port, void *addr, u32 count);
 
@@ -740,6 +740,7 @@
 	u8	nice1;			/* give potential excess bandwidth */
 
 	unsigned present	: 1;	/* drive is physically present */
+	unsigned dead		: 1;	/* device ejected hint */
 	unsigned noprobe 	: 1;	/* from:  hdx=noprobe */
 	unsigned removable	: 1;	/* 1 if need to do check_media_change */
 	unsigned is_flash	: 1;	/* 1 if probed as flash */
@@ -756,6 +757,7 @@
 	unsigned remap_0_to_1	: 2;	/* 0=remap if ezdrive, 1=remap, 2=noremap */
 	unsigned ata_flash	: 1;	/* 1=present, 0=default */
 	unsigned blocked        : 1;	/* 1=powermanagment told us not to do anything, so sleep nicely */
+	unsigned vdma		: 1;	/* 1=doing PIO over DMA 0=doing normal DMA */
 	unsigned queue_setup	: 1;
 	unsigned addressing;		/*      : 3;
 					 *  0=28-bit
@@ -1189,9 +1191,7 @@
 	unsigned supports_dma		: 1;
 	unsigned supports_dsc_overlap	: 1;
 	int		(*cleanup)(ide_drive_t *);
-	int		(*standby)(ide_drive_t *);
-	int		(*suspend)(ide_drive_t *);
-	int		(*resume)(ide_drive_t *);
+	int		(*shutdown)(ide_drive_t *);
 	int		(*flushcache)(ide_drive_t *);
 	ide_startstop_t	(*do_request)(ide_drive_t *, struct request *, sector_t);
 	int		(*end_request)(ide_drive_t *, int, int);
@@ -1599,6 +1599,8 @@
 extern void ide_scan_pcibus(int scan_direction) __init;
 extern int ide_pci_register_driver(struct pci_driver *driver);
 extern void ide_pci_unregister_driver(struct pci_driver *driver);
+extern void ide_pci_setup_ports(struct pci_dev *dev, struct ide_pci_device_s *d, int autodma, int pciirq, ata_index_t *index);
+extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d);
 
 extern void default_hwif_iops(ide_hwif_t *);
 extern void default_hwif_mmiops(ide_hwif_t *);
@@ -1647,6 +1649,7 @@
 	u16			device;
 	char			*name;
 	void			(*init_setup)(struct pci_dev *, struct ide_pci_device_s *);
+	void			(*init_setup_dma)(struct pci_dev *, struct ide_pci_device_s *, ide_hwif_t *);
 	unsigned int		(*init_chipset)(struct pci_dev *, const char *);
 	void			(*init_iops)(ide_hwif_t *);
 	void                    (*init_hwif)(ide_hwif_t *);
@@ -1657,6 +1660,7 @@
 	u8			bootable;
 	unsigned int		extra;
 	struct ide_pci_device_s	*next;
+	u8			isa_ports; 	/* Uses ISA control ports not PCI ones */
 } ide_pci_device_t;
 
 extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
@@ -1664,6 +1668,8 @@
 
 #define BAD_DMA_DRIVE		0
 #define GOOD_DMA_DRIVE		1
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 extern int ide_build_dmatable(ide_drive_t *, struct request *);
 extern void ide_destroy_dmatable(ide_drive_t *);
 extern ide_startstop_t ide_dma_intr(ide_drive_t *);
@@ -1708,6 +1714,10 @@
 }
 #endif
 
+#else
+static inline void ide_release_dma(ide_hwif_t *drive) {;}
+#endif
+
 extern void hwif_unregister(ide_hwif_t *);
 
 extern void export_ide_init_queue(ide_drive_t *);
@@ -1730,6 +1740,7 @@
 extern int ide_dma_enable(ide_drive_t *drive);
 extern char *ide_xfer_verbose(u8 xfer_rate);
 extern void ide_toggle_bounce(ide_drive_t *drive, int on);
+extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
 
 extern spinlock_t ide_lock;
 
diff -Nru a/include/linux/isdnif.h b/include/linux/isdnif.h
--- a/include/linux/isdnif.h	Wed Nov 27 14:36:27 2002
+++ b/include/linux/isdnif.h	Wed Nov 27 14:36:27 2002
@@ -166,17 +166,8 @@
 #define ISDN_CMD_HANGUP   4       /* Hangup                                */
 #define ISDN_CMD_CLREAZ   5       /* Clear EAZ(s) of channel               */
 #define ISDN_CMD_SETEAZ   6       /* Set EAZ(s) of channel                 */
-#define ISDN_CMD_GETEAZ   7       /* Get EAZ(s) of channel                 */
-#define ISDN_CMD_SETSIL   8       /* Set Service-Indicator-List of channel */
-#define ISDN_CMD_GETSIL   9       /* Get Service-Indicator-List of channel */
 #define ISDN_CMD_SETL2   10       /* Set B-Chan. Layer2-Parameter          */
-#define ISDN_CMD_GETL2   11       /* Get B-Chan. Layer2-Parameter          */
 #define ISDN_CMD_SETL3   12       /* Set B-Chan. Layer3-Parameter          */
-#define ISDN_CMD_GETL3   13       /* Get B-Chan. Layer3-Parameter          */
-#define ISDN_CMD_LOCK    14       /* Signal usage by upper levels          */
-#define ISDN_CMD_UNLOCK  15       /* Release usage-lock                    */
-#define ISDN_CMD_SUSPEND 16       /* Suspend connection                    */
-#define ISDN_CMD_RESUME  17       /* Resume connection                     */
 #define ISDN_CMD_PROCEED 18       /* Proceed with call establishment       */
 #define ISDN_CMD_ALERT   19       /* Alert after Proceeding                */
 #define ISDN_CMD_REDIR   20       /* Redir a incoming call                 */
@@ -423,6 +414,8 @@
  *
  */
 typedef struct {
+  struct module *owner;
+
   /* Number of channels supported by this driver
    */
   int channels;
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	Wed Nov 27 14:36:27 2002
+++ b/include/linux/kernel.h	Wed Nov 27 14:36:27 2002
@@ -40,7 +40,7 @@
 
 struct completion;
 
-#ifdef CONFIG_DEBUG_KERNEL
+#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
 void __might_sleep(char *file, int line);
 #define might_sleep() __might_sleep(__FILE__, __LINE__)
 #else
diff -Nru a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
--- a/include/linux/kernel_stat.h	Wed Nov 27 14:36:32 2002
+++ b/include/linux/kernel_stat.h	Wed Nov 27 14:36:32 2002
@@ -35,23 +35,16 @@
 
 extern unsigned long nr_context_switches(void);
 
-/*
- * Maybe we need to smp-ify kernel_stat some day. It would be nice to do
- * that without having to modify all the code that increments the stats.
- */
-#define KERNEL_STAT_INC(x) kstat.x++
-#define KERNEL_STAT_ADD(x, y) kstat.x += y
-
 #if !defined(CONFIG_ARCH_S390)
 /*
  * Number of interrupts per specific IRQ source, since bootup
  */
-static inline int kstat_irqs (int irq)
+static inline int kstat_irqs(int irq)
 {
 	int i, sum=0;
 
-	for (i = 0 ; i < NR_CPUS ; i++) 
-		if (cpu_possible(i)) 
+	for (i = 0; i < NR_CPUS; i++)
+		if (cpu_possible(i))
 			sum += kstat_cpu(i).irqs[irq];
 
 	return sum;
diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h
--- a/include/linux/page-flags.h	Wed Nov 27 14:36:31 2002
+++ b/include/linux/page-flags.h	Wed Nov 27 14:36:31 2002
@@ -6,6 +6,7 @@
 #define PAGE_FLAGS_H
 
 #include <linux/percpu.h>
+#include <linux/cache.h>
 
 /*
  * Various page->flags bits:
@@ -106,7 +107,7 @@
 	unsigned long kswapd_steal;
 	unsigned long pageoutrun;
 	unsigned long allocstall;
-};
+} ____cacheline_aligned;
 
 DECLARE_PER_CPU(struct page_state, page_states);
 
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Wed Nov 27 14:36:29 2002
+++ b/include/linux/pci_ids.h	Wed Nov 27 14:36:29 2002
@@ -165,6 +165,7 @@
 #define PCI_DEVICE_ID_LSI_53C1010_33	0x0020
 #define PCI_DEVICE_ID_LSI_53C1010_66	0x0021
 #define PCI_DEVICE_ID_LSI_53C1030	0x0030
+#define PCI_DEVICE_ID_LSI_1030_53C1035	0x0032
 #define PCI_DEVICE_ID_LSI_53C1035	0x0040
 #define PCI_DEVICE_ID_NCR_53C875J	0x008f
 #define PCI_DEVICE_ID_LSI_FC909		0x0621
@@ -172,6 +173,8 @@
 #define PCI_DEVICE_ID_LSI_FC929_LAN	0x0623
 #define PCI_DEVICE_ID_LSI_FC919		0x0624
 #define PCI_DEVICE_ID_LSI_FC919_LAN	0x0625
+#define PCI_DEVICE_ID_LSI_FC929X	0x0626
+#define PCI_DEVICE_ID_LSI_FC919X	0x0628
 #define PCI_DEVICE_ID_NCR_YELLOWFIN	0x0701
 #define PCI_DEVICE_ID_LSI_61C102	0x0901
 #define PCI_DEVICE_ID_LSI_63C815	0x1000
@@ -265,6 +268,8 @@
 #define PCI_DEVICE_ID_ATI_RADEON_RB	0x5145
 #define PCI_DEVICE_ID_ATI_RADEON_RC	0x5146
 #define PCI_DEVICE_ID_ATI_RADEON_RD	0x5147
+/* RadeonIGP */
+#define PCI_DEVICE_ID_ATI_RADEON_IGP	0xCAB0
 
 #define PCI_VENDOR_ID_VLSI		0x1004
 #define PCI_DEVICE_ID_VLSI_82C592	0x0005
@@ -456,14 +461,31 @@
 #define PCI_DEVICE_ID_MIRO_36050	0x5601
 
 #define PCI_VENDOR_ID_NEC		0x1033
-#define PCI_DEVICE_ID_NEC_PCX2		0x0046
+#define PCI_DEVICE_ID_NEC_CBUS_1	0x0001 /* PCI-Cbus Bridge */
+#define PCI_DEVICE_ID_NEC_LOCAL		0x0002 /* Local Bridge */
+#define PCI_DEVICE_ID_NEC_ATM		0x0003 /* ATM LAN Controller */
+#define PCI_DEVICE_ID_NEC_R4000		0x0004 /* R4000 Bridge */
+#define PCI_DEVICE_ID_NEC_486		0x0005 /* 486 Like Peripheral Bus Bridge */
+#define PCI_DEVICE_ID_NEC_ACCEL_1	0x0006 /* Graphic Accelerator */
+#define PCI_DEVICE_ID_NEC_UXBUS		0x0007 /* UX-Bus Bridge */
+#define PCI_DEVICE_ID_NEC_ACCEL_2	0x0008 /* Graphic Accelerator */
+#define PCI_DEVICE_ID_NEC_GRAPH		0x0009 /* PCI-CoreGraph Bridge */
+#define PCI_DEVICE_ID_NEC_VL		0x0016 /* PCI-VL Bridge */
+#define PCI_DEVICE_ID_NEC_STARALPHA2	0x002c /* STAR ALPHA2 */
+#define PCI_DEVICE_ID_NEC_CBUS_2	0x002d /* PCI-Cbus Bridge */
+#define PCI_DEVICE_ID_NEC_USB		0x0035 /* PCI-USB Host */
+#define PCI_DEVICE_ID_NEC_CBUS_3	0x003b
+#define PCI_DEVICE_ID_NEC_PCX2		0x0046 /* PowerVR */
 #define PCI_DEVICE_ID_NEC_NILE4		0x005a
 #define PCI_DEVICE_ID_NEC_VRC5476       0x009b
 #define PCI_DEVICE_ID_NEC_VRC5477_AC97  0x00a6
+#define PCI_DEVICE_ID_NEC_PC9821CS01    0x800c /* PC-9821-CS01 */
+#define PCI_DEVICE_ID_NEC_PC9821NRB06   0x800d /* PC-9821NR-B06 */
 
 #define PCI_VENDOR_ID_FD		0x1036
 #define PCI_DEVICE_ID_FD_36C70		0x0000
 
+#define PCI_VENDOR_ID_SIS		0x1039
 #define PCI_VENDOR_ID_SI		0x1039
 #define PCI_DEVICE_ID_SI_5591_AGP	0x0001
 #define PCI_DEVICE_ID_SI_6202		0x0002
@@ -1238,6 +1260,8 @@
 #define PCI_DEVICE_ID_ATT_L56XMF	0x0440
 #define PCI_DEVICE_ID_ATT_VENUS_MODEM	0x480
 
+#define PCI_VENDOR_ID_NEC2		0x11c3 /* NEC (2nd) */
+
 #define PCI_VENDOR_ID_SPECIALIX		0x11cb
 #define PCI_DEVICE_ID_SPECIALIX_IO8	0x2000
 #define PCI_DEVICE_ID_SPECIALIX_XIO	0x4000
@@ -1883,4 +1907,3 @@
 
 #define PCI_VENDOR_ID_HINT		0x3388
 #define PCI_DEVICE_ID_HINT_VXPROII_IDE	0x8013
-
diff -Nru a/include/linux/profile.h b/include/linux/profile.h
--- a/include/linux/profile.h	Wed Nov 27 14:36:30 2002
+++ b/include/linux/profile.h	Wed Nov 27 14:36:30 2002
@@ -17,6 +17,7 @@
 extern unsigned int * prof_buffer;
 extern unsigned long prof_len;
 extern unsigned long prof_shift;
+extern int prof_on;
 
 
 enum profile_type {
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Wed Nov 27 14:36:27 2002
+++ b/include/linux/sched.h	Wed Nov 27 14:36:27 2002
@@ -342,7 +342,6 @@
 	struct timer_list real_timer;
 	unsigned long utime, stime, cutime, cstime;
 	unsigned long start_time;
-	long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 	unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
 	int swappable:1;
@@ -539,9 +538,11 @@
 		: on_sig_stack(sp) ? SS_ONSTACK : 0);
 }
 
-/* capable prototype and code moved to security.[hc] */
-#include <linux/security.h>
-#if 0
+
+#ifdef CONFIG_SECURITY
+/* code is in security.c */
+extern int capable(int cap);
+#else
 static inline int capable(int cap)
 {
 	if (cap_raised(current->cap_effective, cap)) {
@@ -550,7 +551,7 @@
 	}
 	return 0;
 }
-#endif	/* if 0 */
+#endif
 
 /*
  * Routines for handling mm_structs
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Wed Nov 27 14:36:31 2002
+++ b/include/linux/security.h	Wed Nov 27 14:36:31 2002
@@ -22,8 +22,6 @@
 #ifndef __LINUX_SECURITY_H
 #define __LINUX_SECURITY_H
 
-#ifdef __KERNEL__
-
 #include <linux/fs.h>
 #include <linux/binfmts.h>
 #include <linux/signal.h>
@@ -32,6 +30,23 @@
 #include <linux/sysctl.h>
 #include <linux/shm.h>
 #include <linux/msg.h>
+#include <linux/sched.h>
+
+
+/*
+ * These functions are in security/capability.c and are used
+ * as the default capabilities functions
+ */
+extern int cap_capable (struct task_struct *tsk, int cap);
+extern int cap_ptrace (struct task_struct *parent, struct task_struct *child);
+extern int cap_capget (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
+extern int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
+extern void cap_capset_set (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
+extern int cap_bprm_set_security (struct linux_binprm *bprm);
+extern void cap_bprm_compute_creds (struct linux_binprm *bprm);
+extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
+extern void cap_task_kmod_set_label (void);
+extern void cap_task_reparent_to_init (struct task_struct *p);
 
 /*
  * Values used in the task_security_ops calls
@@ -48,6 +63,9 @@
 /* setfsuid or setfsgid, id0 == fsuid or fsgid */
 #define LSM_SETID_FS	8
 
+
+#ifdef CONFIG_SECURITY
+
 /* forward declares to avoid warnings */
 struct sk_buff;
 struct net_device;
@@ -667,21 +685,6 @@
  *	@tsk contains the task_struct for the process.
  *	@cap contains the capability <include/linux/capability.h>.
  *	Return 0 if the capability is granted for @tsk.
- * @sys_security:
- *	Security modules may use this hook to implement new system calls for
- *	security-aware applications.  The interface is similar to socketcall,
- *	but with an @id parameter to help identify the security module whose
- *	call is being invoked.  The module is responsible for interpreting the
- *	parameters, and must copy in the @args array from user space if it is
- *	used.
- *	The recommended convention for creating the hexadecimal @id value is
- *	echo "Name_of_module" | md5sum | cut -c -8; by using this convention,
- *	there is no need for a central registry.
- *	@id contains the security module identifier.
- *	@call contains the call value.
- *	@args contains the call arguments (user space pointer).
- *	The module should return -ENOSYS if it does not implement any new
- *	system calls.
  *
  * @register_security:
  * 	allow module stacking.
@@ -709,8 +712,6 @@
 			    kernel_cap_t * permitted);
 	int (*acct) (struct file * file);
 	int (*capable) (struct task_struct * tsk, int cap);
-	int (*sys_security) (unsigned int id, unsigned call,
-			     unsigned long *args);
 	int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
 	int (*quota_on) (struct file * f);
 
@@ -843,6 +844,526 @@
 	                            struct security_operations *ops);
 };
 
+/* global variables */
+extern struct security_operations *security_ops;
+
+/* inline stuff */
+static inline int security_ptrace (struct task_struct * parent, struct task_struct * child)
+{
+	return security_ops->ptrace (parent, child);
+}
+
+static inline int security_capget (struct task_struct *target,
+				   kernel_cap_t *effective,
+				   kernel_cap_t *inheritable,
+				   kernel_cap_t *permitted)
+{
+	return security_ops->capget (target, effective, inheritable, permitted);
+}
+
+static inline int security_capset_check (struct task_struct *target,
+					 kernel_cap_t *effective,
+					 kernel_cap_t *inheritable,
+					 kernel_cap_t *permitted)
+{
+	return security_ops->capset_check (target, effective, inheritable, permitted);
+}
+
+static inline void security_capset_set (struct task_struct *target,
+					kernel_cap_t *effective,
+					kernel_cap_t *inheritable,
+					kernel_cap_t *permitted)
+{
+	security_ops->capset_set (target, effective, inheritable, permitted);
+}
+
+static inline int security_acct (struct file *file)
+{
+	return security_ops->acct (file);
+}
+
+static inline int security_quotactl (int cmds, int type, int id,
+				     struct super_block *sb)
+{
+	return security_ops->quotactl (cmds, type, id, sb);
+}
+
+static inline int security_quota_on (struct file * file)
+{
+	return security_ops->quota_on (file);
+}
+
+static inline int security_bprm_alloc (struct linux_binprm *bprm)
+{
+	return security_ops->bprm_alloc_security (bprm);
+}
+static inline void security_bprm_free (struct linux_binprm *bprm)
+{
+	security_ops->bprm_free_security (bprm);
+}
+static inline void security_bprm_compute_creds (struct linux_binprm *bprm)
+{
+	security_ops->bprm_compute_creds (bprm);
+}
+static inline int security_bprm_set (struct linux_binprm *bprm)
+{
+	return security_ops->bprm_set_security (bprm);
+}
+static inline int security_bprm_check (struct linux_binprm *bprm)
+{
+	return security_ops->bprm_check_security (bprm);
+}
+
+static inline int security_sb_alloc (struct super_block *sb)
+{
+	return security_ops->sb_alloc_security (sb);
+}
+
+static inline void security_sb_free (struct super_block *sb)
+{
+	security_ops->sb_free_security (sb);
+}
+
+static inline int security_sb_statfs (struct super_block *sb)
+{
+	return security_ops->sb_statfs (sb);
+}
+
+static inline int security_sb_mount (char *dev_name, struct nameidata *nd,
+				    char *type, unsigned long flags,
+				    void *data)
+{
+	return security_ops->sb_mount (dev_name, nd, type, flags, data);
+}
+
+static inline int security_sb_check_sb (struct vfsmount *mnt,
+					struct nameidata *nd)
+{
+	return security_ops->sb_check_sb (mnt, nd);
+}
+
+static inline int security_sb_umount (struct vfsmount *mnt, int flags)
+{
+	return security_ops->sb_umount (mnt, flags);
+}
+
+static inline void security_sb_umount_close (struct vfsmount *mnt)
+{
+	security_ops->sb_umount_close (mnt);
+}
+
+static inline void security_sb_umount_busy (struct vfsmount *mnt)
+{
+	security_ops->sb_umount_busy (mnt);
+}
+
+static inline void security_sb_post_remount (struct vfsmount *mnt,
+					     unsigned long flags, void *data)
+{
+	security_ops->sb_post_remount (mnt, flags, data);
+}
+
+static inline void security_sb_post_mountroot (void)
+{
+	security_ops->sb_post_mountroot ();
+}
+
+static inline void security_sb_post_addmount (struct vfsmount *mnt,
+					      struct nameidata *mountpoint_nd)
+{
+	security_ops->sb_post_addmount (mnt, mountpoint_nd);
+}
+
+static inline int security_sb_pivotroot (struct nameidata *old_nd,
+					 struct nameidata *new_nd)
+{
+	return security_ops->sb_pivotroot (old_nd, new_nd);
+}
+
+static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
+					       struct nameidata *new_nd)
+{
+	security_ops->sb_post_pivotroot (old_nd, new_nd);
+}
+
+static inline int security_inode_alloc (struct inode *inode)
+{
+	return security_ops->inode_alloc_security (inode);
+}
+
+static inline void security_inode_free (struct inode *inode)
+{
+	security_ops->inode_free_security (inode);
+}
+	
+static inline int security_inode_create (struct inode *dir,
+					 struct dentry *dentry,
+					 int mode)
+{
+	return security_ops->inode_create (dir, dentry, mode);
+}
+
+static inline void security_inode_post_create (struct inode *dir,
+					       struct dentry *dentry,
+					       int mode)
+{
+	security_ops->inode_post_create (dir, dentry, mode);
+}
+
+static inline int security_inode_link (struct dentry *old_dentry,
+				       struct inode *dir,
+				       struct dentry *new_dentry)
+{
+	return security_ops->inode_link (old_dentry, dir, new_dentry);
+}
+
+static inline void security_inode_post_link (struct dentry *old_dentry,
+					     struct inode *dir,
+					     struct dentry *new_dentry)
+{
+	security_ops->inode_post_link (old_dentry, dir, new_dentry);
+}
+
+static inline int security_inode_unlink (struct inode *dir,
+					 struct dentry *dentry)
+{
+	return security_ops->inode_unlink (dir, dentry);
+}
+
+static inline int security_inode_symlink (struct inode *dir,
+					  struct dentry *dentry,
+					  const char *old_name)
+{
+	return security_ops->inode_symlink (dir, dentry, old_name);
+}
+
+static inline void security_inode_post_symlink (struct inode *dir,
+						struct dentry *dentry,
+						const char *old_name)
+{
+	security_ops->inode_post_symlink (dir, dentry, old_name);
+}
+
+static inline int security_inode_mkdir (struct inode *dir,
+					struct dentry *dentry,
+					int mode)
+{
+	return security_ops->inode_mkdir (dir, dentry, mode);
+}
+
+static inline void security_inode_post_mkdir (struct inode *dir,
+					      struct dentry *dentry,
+					      int mode)
+{
+	security_ops->inode_post_mkdir (dir, dentry, mode);
+}
+
+static inline int security_inode_rmdir (struct inode *dir,
+					struct dentry *dentry)
+{
+	return security_ops->inode_rmdir (dir, dentry);
+}
+
+static inline int security_inode_mknod (struct inode *dir,
+					struct dentry *dentry,
+					int mode, dev_t dev)
+{
+	return security_ops->inode_mknod (dir, dentry, mode, dev);
+}
+
+static inline void security_inode_post_mknod (struct inode *dir,
+					      struct dentry *dentry,
+					      int mode, dev_t dev)
+{
+	security_ops->inode_post_mknod (dir, dentry, mode, dev);
+}
+
+static inline int security_inode_rename (struct inode *old_dir,
+					 struct dentry *old_dentry,
+					 struct inode *new_dir,
+					 struct dentry *new_dentry)
+{
+	return security_ops->inode_rename (old_dir, old_dentry,
+					   new_dir, new_dentry);
+}
+
+static inline void security_inode_post_rename (struct inode *old_dir,
+					       struct dentry *old_dentry,
+					       struct inode *new_dir,
+					       struct dentry *new_dentry)
+{
+	security_ops->inode_post_rename (old_dir, old_dentry,
+						new_dir, new_dentry);
+}
+
+static inline int security_inode_readlink (struct dentry *dentry)
+{
+	return security_ops->inode_readlink (dentry);
+}
+
+static inline int security_inode_follow_link (struct dentry *dentry,
+					      struct nameidata *nd)
+{
+	return security_ops->inode_follow_link (dentry, nd);
+}
+
+static inline int security_inode_permission (struct inode *inode, int mask)
+{
+	return security_ops->inode_permission (inode, mask);
+}
+
+static inline int security_inode_permission_lite (struct inode *inode,
+						  int mask)
+{
+	return security_ops->inode_permission_lite (inode, mask);
+}
+
+static inline int security_inode_setattr (struct dentry *dentry,
+					  struct iattr *attr)
+{
+	return security_ops->inode_setattr (dentry, attr);
+}
+
+static inline int security_inode_getattr (struct vfsmount *mnt,
+					  struct dentry *dentry)
+{
+	return security_ops->inode_getattr (mnt, dentry);
+}
+
+static inline void security_inode_post_lookup (struct inode *inode,
+					       struct dentry *dentry)
+{
+	security_ops->inode_post_lookup (inode, dentry);
+}
+
+static inline void security_inode_delete (struct inode *inode)
+{
+	security_ops->inode_delete (inode);
+}
+
+static inline int security_inode_setxattr (struct dentry *dentry, char *name,
+					   void *value, size_t size, int flags)
+{
+	return security_ops->inode_setxattr (dentry, name, value, size, flags);
+}
+
+static inline int security_inode_getxattr (struct dentry *dentry, char *name)
+{
+	return security_ops->inode_getxattr (dentry, name);
+}
+
+static inline int security_inode_listxattr (struct dentry *dentry)
+{
+	return security_ops->inode_listxattr (dentry);
+}
+
+static inline int security_inode_removexattr (struct dentry *dentry, char *name)
+{
+	return security_ops->inode_removexattr (dentry, name);
+}
+
+static inline int security_file_permission (struct file *file, int mask)
+{
+	return security_ops->file_permission (file, mask);
+}
+
+static inline int security_file_alloc (struct file *file)
+{
+	return security_ops->file_alloc_security (file);
+}
+
+static inline void security_file_free (struct file *file)
+{
+	security_ops->file_free_security (file);
+}
+
+static inline int security_file_ioctl (struct file *file, unsigned int cmd,
+				       unsigned long arg)
+{
+	return security_ops->file_ioctl (file, cmd, arg);
+}
+
+static inline int security_file_mmap (struct file *file, unsigned long prot,
+				      unsigned long flags)
+{
+	return security_ops->file_mmap (file, prot, flags);
+}
+
+static inline int security_file_mprotect (struct vm_area_struct *vma,
+					  unsigned long prot)
+{
+	return security_ops->file_mprotect (vma, prot);
+}
+
+static inline int security_file_lock (struct file *file, unsigned int cmd)
+{
+	return security_ops->file_lock (file, cmd);
+}
+
+static inline int security_file_fcntl (struct file *file, unsigned int cmd,
+				       unsigned long arg)
+{
+	return security_ops->file_fcntl (file, cmd, arg);
+}
+
+static inline int security_file_set_fowner (struct file *file)
+{
+	return security_ops->file_set_fowner (file);
+}
+
+static inline int security_file_send_sigiotask (struct task_struct *tsk,
+						struct fown_struct *fown,
+						int fd, int reason)
+{
+	return security_ops->file_send_sigiotask (tsk, fown, fd, reason);
+}
+
+static inline int security_file_receive (struct file *file)
+{
+	return security_ops->file_receive (file);
+}
+
+static inline int security_task_create (unsigned long clone_flags)
+{
+	return security_ops->task_create (clone_flags);
+}
+
+static inline int security_task_alloc (struct task_struct *p)
+{
+	return security_ops->task_alloc_security (p);
+}
+
+static inline void security_task_free (struct task_struct *p)
+{
+	security_ops->task_free_security (p);
+}
+
+static inline int security_task_setuid (uid_t id0, uid_t id1, uid_t id2,
+					int flags)
+{
+	return security_ops->task_setuid (id0, id1, id2, flags);
+}
+
+static inline int security_task_post_setuid (uid_t old_ruid, uid_t old_euid,
+					     uid_t old_suid, int flags)
+{
+	return security_ops->task_post_setuid (old_ruid, old_euid, old_suid, flags);
+}
+
+static inline int security_task_setgid (gid_t id0, gid_t id1, gid_t id2,
+					int flags)
+{
+	return security_ops->task_setgid (id0, id1, id2, flags);
+}
+
+static inline int security_task_setpgid (struct task_struct *p, pid_t pgid)
+{
+	return security_ops->task_setpgid (p, pgid);
+}
+
+static inline int security_task_getpgid (struct task_struct *p)
+{
+	return security_ops->task_getpgid (p);
+}
+
+static inline int security_task_getsid (struct task_struct *p)
+{
+	return security_ops->task_getsid (p);
+}
+
+static inline int security_task_setgroups (int gidsetsize, gid_t *grouplist)
+{
+	return security_ops->task_setgroups (gidsetsize, grouplist);
+}
+
+static inline int security_task_setnice (struct task_struct *p, int nice)
+{
+	return security_ops->task_setnice (p, nice);
+}
+
+static inline int security_task_setrlimit (unsigned int resource,
+					   struct rlimit *new_rlim)
+{
+	return security_ops->task_setrlimit (resource, new_rlim);
+}
+
+static inline int security_task_setscheduler (struct task_struct *p,
+					      int policy,
+					      struct sched_param *lp)
+{
+	return security_ops->task_setscheduler (p, policy, lp);
+}
+
+static inline int security_task_getscheduler (struct task_struct *p)
+{
+	return security_ops->task_getscheduler (p);
+}
+
+static inline int security_task_kill (struct task_struct *p,
+				      struct siginfo *info, int sig)
+{
+	return security_ops->task_kill (p, info, sig);
+}
+
+static inline int security_task_wait (struct task_struct *p)
+{
+	return security_ops->task_wait (p);
+}
+
+static inline int security_task_prctl (int option, unsigned long arg2,
+				       unsigned long arg3,
+				       unsigned long arg4,
+				       unsigned long arg5)
+{
+	return security_ops->task_prctl (option, arg2, arg3, arg4, arg5);
+}
+
+static inline void security_task_kmod_set_label (void)
+{
+	security_ops->task_kmod_set_label ();
+}
+
+static inline void security_task_reparent_to_init (struct task_struct *p)
+{
+	security_ops->task_reparent_to_init (p);
+}
+
+static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
+					   short flag)
+{
+	return security_ops->ipc_permission (ipcp, flag);
+}
+
+static inline int security_msg_queue_alloc (struct msg_queue *msq)
+{
+	return security_ops->msg_queue_alloc_security (msq);
+}
+
+static inline void security_msg_queue_free (struct msg_queue *msq)
+{
+	security_ops->msg_queue_free_security (msq);
+}
+
+static inline int security_shm_alloc (struct shmid_kernel *shp)
+{
+	return security_ops->shm_alloc_security (shp);
+}
+
+static inline void security_shm_free (struct shmid_kernel *shp)
+{
+	security_ops->shm_free_security (shp);
+}
+
+static inline int security_sem_alloc (struct sem_array *sma)
+{
+	return security_ops->sem_alloc_security (sma);
+}
+
+static inline void security_sem_free (struct sem_array *sma)
+{
+	security_ops->sem_free_security (sma);
+}
+
 
 /* prototypes */
 extern int security_scaffolding_startup	(void);
@@ -850,13 +1371,496 @@
 extern int unregister_security	(struct security_operations *ops);
 extern int mod_reg_security	(const char *name, struct security_operations *ops);
 extern int mod_unreg_security	(const char *name, struct security_operations *ops);
-extern int capable		(int cap);
 
-/* global variables */
-extern struct security_operations *security_ops;
+
+#else /* CONFIG_SECURITY */
+
+/*
+ * This is the default capabilities functionality.  Most of these functions
+ * are just stubbed out, but a few must call the proper capable code.
+ */
+
+static inline int security_scaffolding_startup (void)
+{
+	return 0;
+}
+
+static inline int security_ptrace (struct task_struct *parent, struct task_struct * child)
+{
+	return cap_ptrace (parent, child);
+}
+
+static inline int security_capget (struct task_struct *target,
+				   kernel_cap_t *effective,
+				   kernel_cap_t *inheritable,
+				   kernel_cap_t *permitted)
+{
+	return cap_capget (target, effective, inheritable, permitted);
+}
+
+static inline int security_capset_check (struct task_struct *target,
+					 kernel_cap_t *effective,
+					 kernel_cap_t *inheritable,
+					 kernel_cap_t *permitted)
+{
+	return cap_capset_check (target, effective, inheritable, permitted);
+}
+
+static inline void security_capset_set (struct task_struct *target,
+					kernel_cap_t *effective,
+					kernel_cap_t *inheritable,
+					kernel_cap_t *permitted)
+{
+	cap_capset_set (target, effective, inheritable, permitted);
+}
+
+static inline int security_acct (struct file *file)
+{
+	return 0;
+}
+
+static inline int security_quotactl (int cmds, int type, int id,
+				     struct super_block * sb)
+{
+	return 0;
+}
+
+static inline int security_quota_on (struct file * file)
+{
+	return 0;
+}
+
+static inline int security_bprm_alloc (struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static inline void security_bprm_free (struct linux_binprm *bprm)
+{ }
+
+static inline void security_bprm_compute_creds (struct linux_binprm *bprm)
+{ 
+	cap_bprm_compute_creds (bprm);
+}
+
+static inline int security_bprm_set (struct linux_binprm *bprm)
+{
+	return cap_bprm_set_security (bprm);
+}
+
+static inline int security_bprm_check (struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static inline int security_sb_alloc (struct super_block *sb)
+{
+	return 0;
+}
+
+static inline void security_sb_free (struct super_block *sb)
+{ }
+
+static inline int security_sb_statfs (struct super_block *sb)
+{
+	return 0;
+}
+
+static inline int security_sb_mount (char *dev_name, struct nameidata *nd,
+				    char *type, unsigned long flags,
+				    void *data)
+{
+	return 0;
+}
+
+static inline int security_sb_check_sb (struct vfsmount *mnt,
+					struct nameidata *nd)
+{
+	return 0;
+}
+
+static inline int security_sb_umount (struct vfsmount *mnt, int flags)
+{
+	return 0;
+}
+
+static inline void security_sb_umount_close (struct vfsmount *mnt)
+{ }
+
+static inline void security_sb_umount_busy (struct vfsmount *mnt)
+{ }
+
+static inline void security_sb_post_remount (struct vfsmount *mnt,
+					     unsigned long flags, void *data)
+{ }
+
+static inline void security_sb_post_mountroot (void)
+{ }
+
+static inline void security_sb_post_addmount (struct vfsmount *mnt,
+					      struct nameidata *mountpoint_nd)
+{ }
+
+static inline int security_sb_pivotroot (struct nameidata *old_nd,
+					 struct nameidata *new_nd)
+{
+	return 0;
+}
+
+static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
+					       struct nameidata *new_nd)
+{ }
+
+static inline int security_inode_alloc (struct inode *inode)
+{
+	return 0;
+}
+
+static inline void security_inode_free (struct inode *inode)
+{ }
+	
+static inline int security_inode_create (struct inode *dir,
+					 struct dentry *dentry,
+					 int mode)
+{
+	return 0;
+}
+
+static inline void security_inode_post_create (struct inode *dir,
+					       struct dentry *dentry,
+					       int mode)
+{ }
+
+static inline int security_inode_link (struct dentry *old_dentry,
+				       struct inode *dir,
+				       struct dentry *new_dentry)
+{
+	return 0;
+}
+
+static inline void security_inode_post_link (struct dentry *old_dentry,
+					     struct inode *dir,
+					     struct dentry *new_dentry)
+{ }
+
+static inline int security_inode_unlink (struct inode *dir,
+					 struct dentry *dentry)
+{
+	return 0;
+}
+
+static inline int security_inode_symlink (struct inode *dir,
+					  struct dentry *dentry,
+					  const char *old_name)
+{
+	return 0;
+}
+
+static inline void security_inode_post_symlink (struct inode *dir,
+						struct dentry *dentry,
+						const char *old_name)
+{ }
+
+static inline int security_inode_mkdir (struct inode *dir,
+					struct dentry *dentry,
+					int mode)
+{
+	return 0;
+}
+
+static inline void security_inode_post_mkdir (struct inode *dir,
+					      struct dentry *dentry,
+					      int mode)
+{ }
+
+static inline int security_inode_rmdir (struct inode *dir,
+					struct dentry *dentry)
+{
+	return 0;
+}
+
+static inline int security_inode_mknod (struct inode *dir,
+					struct dentry *dentry,
+					int mode, dev_t dev)
+{
+	return 0;
+}
+
+static inline void security_inode_post_mknod (struct inode *dir,
+					      struct dentry *dentry,
+					      int mode, dev_t dev)
+{ }
+
+static inline int security_inode_rename (struct inode *old_dir,
+					 struct dentry *old_dentry,
+					 struct inode *new_dir,
+					 struct dentry *new_dentry)
+{
+	return 0;
+}
+
+static inline void security_inode_post_rename (struct inode *old_dir,
+					       struct dentry *old_dentry,
+					       struct inode *new_dir,
+					       struct dentry *new_dentry)
+{ }
+
+static inline int security_inode_readlink (struct dentry *dentry)
+{
+	return 0;
+}
+
+static inline int security_inode_follow_link (struct dentry *dentry,
+					      struct nameidata *nd)
+{
+	return 0;
+}
+
+static inline int security_inode_permission (struct inode *inode, int mask)
+{
+	return 0;
+}
+
+static inline int security_inode_permission_lite (struct inode *inode,
+						  int mask)
+{
+	return 0;
+}
+
+static inline int security_inode_setattr (struct dentry *dentry,
+					  struct iattr *attr)
+{
+	return 0;
+}
+
+static inline int security_inode_getattr (struct vfsmount *mnt,
+					  struct dentry *dentry)
+{
+	return 0;
+}
+
+static inline void security_inode_post_lookup (struct inode *inode,
+					       struct dentry *dentry)
+{ }
+
+static inline void security_inode_delete (struct inode *inode)
+{ }
+
+static inline int security_inode_setxattr (struct dentry *dentry, char *name,
+					   void *value, size_t size, int flags)
+{
+	return 0;
+}
+
+static inline int security_inode_getxattr (struct dentry *dentry, char *name)
+{
+	return 0;
+}
+
+static inline int security_inode_listxattr (struct dentry *dentry)
+{
+	return 0;
+}
+
+static inline int security_inode_removexattr (struct dentry *dentry, char *name)
+{
+	return 0;
+}
+
+static inline int security_file_permission (struct file *file, int mask)
+{
+	return 0;
+}
+
+static inline int security_file_alloc (struct file *file)
+{
+	return 0;
+}
+
+static inline void security_file_free (struct file *file)
+{ }
+
+static inline int security_file_ioctl (struct file *file, unsigned int cmd,
+				       unsigned long arg)
+{
+	return 0;
+}
+
+static inline int security_file_mmap (struct file *file, unsigned long prot,
+				      unsigned long flags)
+{
+	return 0;
+}
+
+static inline int security_file_mprotect (struct vm_area_struct *vma,
+					  unsigned long prot)
+{
+	return 0;
+}
+
+static inline int security_file_lock (struct file *file, unsigned int cmd)
+{
+	return 0;
+}
+
+static inline int security_file_fcntl (struct file *file, unsigned int cmd,
+				       unsigned long arg)
+{
+	return 0;
+}
+
+static inline int security_file_set_fowner (struct file *file)
+{
+	return 0;
+}
+
+static inline int security_file_send_sigiotask (struct task_struct *tsk,
+						struct fown_struct *fown,
+						int fd, int reason)
+{
+	return 0;
+}
+
+static inline int security_file_receive (struct file *file)
+{
+	return 0;
+}
+
+static inline int security_task_create (unsigned long clone_flags)
+{
+	return 0;
+}
+
+static inline int security_task_alloc (struct task_struct *p)
+{
+	return 0;
+}
+
+static inline void security_task_free (struct task_struct *p)
+{ }
+
+static inline int security_task_setuid (uid_t id0, uid_t id1, uid_t id2,
+					int flags)
+{
+	return 0;
+}
+
+static inline int security_task_post_setuid (uid_t old_ruid, uid_t old_euid,
+					     uid_t old_suid, int flags)
+{
+	return cap_task_post_setuid (old_ruid, old_euid, old_suid, flags);
+}
+
+static inline int security_task_setgid (gid_t id0, gid_t id1, gid_t id2,
+					int flags)
+{
+	return 0;
+}
+
+static inline int security_task_setpgid (struct task_struct *p, pid_t pgid)
+{
+	return 0;
+}
+
+static inline int security_task_getpgid (struct task_struct *p)
+{
+	return 0;
+}
+
+static inline int security_task_getsid (struct task_struct *p)
+{
+	return 0;
+}
+
+static inline int security_task_setgroups (int gidsetsize, gid_t *grouplist)
+{
+	return 0;
+}
+
+static inline int security_task_setnice (struct task_struct *p, int nice)
+{
+	return 0;
+}
+
+static inline int security_task_setrlimit (unsigned int resource,
+					   struct rlimit *new_rlim)
+{
+	return 0;
+}
+
+static inline int security_task_setscheduler (struct task_struct *p,
+					      int policy,
+					      struct sched_param *lp)
+{
+	return 0;
+}
+
+static inline int security_task_getscheduler (struct task_struct *p)
+{
+	return 0;
+}
+
+static inline int security_task_kill (struct task_struct *p,
+				      struct siginfo *info, int sig)
+{
+	return 0;
+}
+
+static inline int security_task_wait (struct task_struct *p)
+{
+	return 0;
+}
+
+static inline int security_task_prctl (int option, unsigned long arg2,
+				       unsigned long arg3,
+				       unsigned long arg4,
+				       unsigned long arg5)
+{
+	return 0;
+}
+
+static inline void security_task_kmod_set_label (void)
+{
+	cap_task_kmod_set_label ();
+}
+
+static inline void security_task_reparent_to_init (struct task_struct *p)
+{
+	cap_task_reparent_to_init (p);
+}
+
+static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
+					   short flag)
+{
+	return 0;
+}
+
+static inline int security_msg_queue_alloc (struct msg_queue *msq)
+{
+	return 0;
+}
+
+static inline void security_msg_queue_free (struct msg_queue *msq)
+{ }
+
+static inline int security_shm_alloc (struct shmid_kernel *shp)
+{
+	return 0;
+}
+
+static inline void security_shm_free (struct shmid_kernel *shp)
+{ }
+
+static inline int security_sem_alloc (struct sem_array *sma)
+{
+	return 0;
+}
+
+static inline void security_sem_free (struct sem_array *sma)
+{ }
 
 
-#endif /* __KERNEL__ */
+#endif	/* CONFIG_SECURITY */
 
 #endif /* ! __LINUX_SECURITY_H */
 
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	Wed Nov 27 14:36:27 2002
+++ b/include/linux/serial_core.h	Wed Nov 27 14:36:27 2002
@@ -55,6 +55,10 @@
 #define PORT_SUNZILOG	38
 #define PORT_SUNSAB	39
 
+/* NEC v850.  */
+#define PORT_NB85E_UART	40
+
+
 #ifdef __KERNEL__
 
 #include <linux/config.h>
diff -Nru a/include/linux/serio.h b/include/linux/serio.h
--- a/include/linux/serio.h	Wed Nov 27 14:36:30 2002
+++ b/include/linux/serio.h	Wed Nov 27 14:36:30 2002
@@ -97,6 +97,7 @@
 #define SERIO_8042	0x01000000UL
 #define SERIO_RS232	0x02000000UL
 #define SERIO_HIL_MLC	0x03000000UL
+#define SERIO_PC9800	0x04000000UL
 
 #define SERIO_PROTO	0xFFUL
 #define SERIO_MSC	0x01
diff -Nru a/include/linux/soundmodem.h b/include/linux/soundmodem.h
--- a/include/linux/soundmodem.h	Wed Nov 27 14:36:32 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,90 +0,0 @@
-/*
- * The Linux soundcard driver for 1200 baud and 9600 baud packet radio
- * (C) 1996-1998 by Thomas Sailer, HB9JNX/AE4WA
- */
-
-#ifndef _SOUNDMODEM_H
-#define _SOUNDMODEM_H
-
-/* -------------------------------------------------------------------- */
-/*
- * structs for the IOCTL commands
- */
-
-struct sm_debug_data {
-	unsigned int int_rate;
-	unsigned int mod_cycles;
-	unsigned int demod_cycles;
-	unsigned int dma_residue;
-};
-
-struct sm_diag_data {
-	unsigned int mode;
-	unsigned int flags;
-	unsigned int samplesperbit;
-	unsigned int datalen;
-	short *data;
-};
-
-struct sm_mixer_data {
-	unsigned int mixer_type;
-	unsigned int sample_rate;
-	unsigned int bit_rate;
-	unsigned int reg;
-	unsigned int data;
-};
-
-struct sm_config {
-	int hardware;
-	int mode;
-};
-
-struct sm_ioctl {
-	int cmd;
-	union {
-		struct sm_config cfg;
-		struct sm_diag_data diag;	
-		struct sm_mixer_data mix;
-		struct sm_debug_data dbg;
-	} data;
-};
-
-/* -------------------------------------------------------------------- */
-
-/*
- * diagnose modes
- */
-#define SM_DIAGMODE_OFF            0
-#define SM_DIAGMODE_INPUT          1
-#define SM_DIAGMODE_DEMOD          2
-#define SM_DIAGMODE_CONSTELLATION  3
-
-/*
- * diagnose flags
- */
-#define SM_DIAGFLAG_DCDGATE    (1<<0)
-#define SM_DIAGFLAG_VALID      (1<<1)
-
-/*
- * mixer types
- */
-#define SM_MIXER_INVALID       0
-#define SM_MIXER_AD1848        0x10
-#define SM_MIXER_CRYSTAL       0x11
-#define SM_MIXER_CT1335        0x20
-#define SM_MIXER_CT1345        0x21
-#define SM_MIXER_CT1745        0x22
-
-/*
- * ioctl values
- */
-#define SMCTL_DIAGNOSE         0x82
-#define SMCTL_GETMIXER         0x83
-#define SMCTL_SETMIXER         0x84
-#define SMCTL_GETDEBUG         0x85
-
-/* -------------------------------------------------------------------- */
-
-#endif /* _SOUNDMODEM_H */
-
-/* --------------------------------------------------------------------- */
diff -Nru a/include/linux/swap.h b/include/linux/swap.h
--- a/include/linux/swap.h	Wed Nov 27 14:36:27 2002
+++ b/include/linux/swap.h	Wed Nov 27 14:36:27 2002
@@ -121,6 +121,7 @@
 	int prio;			/* swap priority */
 	int pages;
 	unsigned long max;
+	unsigned long inuse_pages;
 	int next;			/* next entry on swap list */
 };
 
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Wed Nov 27 14:36:30 2002
+++ b/include/linux/usb.h	Wed Nov 27 14:36:30 2002
@@ -901,14 +901,11 @@
 /*
  * timeouts, in seconds, used for sending/receiving control messages
  * they typically complete within a few frames (msec) after they're issued
+ * USB identifies 5 second timeouts, maybe more in a few cases, and a few
+ * slow devices (like some MGE Ellipse UPSes) actually push that limit.
  */
-#ifdef CONFIG_USB_LONG_TIMEOUT
-#define USB_CTRL_GET_TIMEOUT	4
-#else
-#define USB_CTRL_GET_TIMEOUT	3
-#endif
-
-#define USB_CTRL_SET_TIMEOUT	3
+#define USB_CTRL_GET_TIMEOUT	5
+#define USB_CTRL_SET_TIMEOUT	5
 
 
 /**
diff -Nru a/include/net/irda/vlsi_ir.h b/include/net/irda/vlsi_ir.h
--- a/include/net/irda/vlsi_ir.h	Wed Nov 27 14:36:31 2002
+++ b/include/net/irda/vlsi_ir.h	Wed Nov 27 14:36:31 2002
@@ -27,26 +27,6 @@
 #ifndef IRDA_VLSI_FIR_H
 #define IRDA_VLSI_FIR_H
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,4)
-#ifdef CONFIG_PROC_FS
-/* PDE() introduced in 2.5.4 */
-#define PDE(inode) ((inode)->u.generic_ip)
-#endif
-#endif
-
-/*
- * #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,xx)
- *
- * missing pci-dma api call to give streaming dma buffer back to hw
- * patch floating on lkml - probably present in 2.5.26 or later
- * otherwise defining it as noop is ok, since the vlsi-ir is only
- * used on two oldish x86-based notebooks which are cache-coherent
- */
-#define pci_dma_prep_single(dev, addr, size, direction)	/* nothing */
-/*
- * #endif
- */
-
 /* ================================================================ */
 
 /* non-standard PCI registers */
diff -Nru a/init/do_mounts.c b/init/do_mounts.c
--- a/init/do_mounts.c	Wed Nov 27 14:36:29 2002
+++ b/init/do_mounts.c	Wed Nov 27 14:36:29 2002
@@ -13,6 +13,7 @@
 #include <linux/suspend.h>
 #include <linux/root_dev.h>
 #include <linux/mount.h>
+#include <linux/security.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
@@ -595,7 +596,8 @@
 
 #ifdef CONFIG_BLK_DEV_RAM
 	int in_fd, out_fd;
-	int nblocks, rd_blocks, devblocks, i;
+	unsigned long rd_blocks, devblocks;
+	int nblocks, i;
 	char *buf;
 	unsigned short rotate = 0;
 #if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES)
@@ -887,7 +889,7 @@
 	sys_umount("/dev", 0);
 	sys_mount(".", "/", NULL, MS_MOVE, NULL);
 	sys_chroot(".");
-	security_ops->sb_post_mountroot();
+	security_sb_post_mountroot();
 	mount_devfs_fs ();
 }
 
diff -Nru a/ipc/msg.c b/ipc/msg.c
--- a/ipc/msg.c	Wed Nov 27 14:36:27 2002
+++ b/ipc/msg.c	Wed Nov 27 14:36:27 2002
@@ -101,15 +101,14 @@
 	msq->q_perm.key = key;
 
 	msq->q_perm.security = NULL;
-	retval = security_ops->msg_queue_alloc_security(msq);
-	if (retval) {
+	if ((retval = security_msg_queue_alloc(msq))) {
 		ipc_rcu_free(msq, sizeof(*msq));
 		return retval;
 	}
 
 	id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni);
 	if(id == -1) {
-		security_ops->msg_queue_free_security(msq);
+		security_msg_queue_free(msq);
 		ipc_rcu_free(msq, sizeof(*msq));
 		return -ENOSPC;
 	}
@@ -281,7 +280,7 @@
 		free_msg(msg);
 	}
 	atomic_sub(msq->q_cbytes, &msg_bytes);
-	security_ops->msg_queue_free_security(msq);
+	security_msg_queue_free(msq);
 	ipc_rcu_free(msq, sizeof(struct msg_queue));
 }
 
diff -Nru a/ipc/sem.c b/ipc/sem.c
--- a/ipc/sem.c	Wed Nov 27 14:36:29 2002
+++ b/ipc/sem.c	Wed Nov 27 14:36:29 2002
@@ -136,15 +136,14 @@
 	sma->sem_perm.key = key;
 
 	sma->sem_perm.security = NULL;
-	retval = security_ops->sem_alloc_security(sma);
-	if (retval) {
+	if ((retval = security_sem_alloc(sma))) {
 		ipc_rcu_free(sma, size);
 		return retval;
 	}
 
 	id = ipc_addid(&sem_ids, &sma->sem_perm, sc_semmni);
 	if(id == -1) {
-		security_ops->sem_free_security(sma);
+		security_sem_free(sma);
 		ipc_rcu_free(sma, size);
 		return -ENOSPC;
 	}
@@ -427,7 +426,7 @@
 
 	used_sems -= sma->sem_nsems;
 	size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem);
-	security_ops->sem_free_security(sma);
+	security_sem_free(sma);
 	ipc_rcu_free(sma, size);
 }
 
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	Wed Nov 27 14:36:30 2002
+++ b/ipc/shm.c	Wed Nov 27 14:36:30 2002
@@ -116,7 +116,7 @@
 	if (!is_file_hugepages(shp->shm_file))
 		shmem_lock(shp->shm_file, 0);
 	fput (shp->shm_file);
-	security_ops->shm_free_security(shp);
+	security_shm_free(shp);
 	ipc_rcu_free(shp, sizeof(struct shmid_kernel));
 }
 
@@ -188,8 +188,7 @@
 	shp->shm_flags = (shmflg & S_IRWXUGO);
 
 	shp->shm_perm.security = NULL;
-	error = security_ops->shm_alloc_security(shp);
-	if (error) {
+	if ((error = security_shm_alloc(shp))) {
 		ipc_rcu_free(shp, sizeof(*shp));
 		return error;
 	}
@@ -229,7 +228,7 @@
 no_id:
 	fput(file);
 no_file:
-	security_ops->shm_free_security(shp);
+	security_shm_free(shp);
 	ipc_rcu_free(shp, sizeof(*shp));
 	return error;
 }
diff -Nru a/ipc/util.c b/ipc/util.c
--- a/ipc/util.c	Wed Nov 27 14:36:29 2002
+++ b/ipc/util.c	Wed Nov 27 14:36:29 2002
@@ -364,7 +364,7 @@
 	    !capable(CAP_IPC_OWNER))
 		return -1;
 
-	return security_ops->ipc_permission(ipcp, flag);
+	return security_ipc_permission(ipcp, flag);
 }
 
 /*
diff -Nru a/kernel/acct.c b/kernel/acct.c
--- a/kernel/acct.c	Wed Nov 27 14:36:30 2002
+++ b/kernel/acct.c	Wed Nov 27 14:36:30 2002
@@ -49,6 +49,7 @@
 #include <linux/acct.h>
 #include <linux/file.h>
 #include <linux/tty.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 
 /*
@@ -222,8 +223,7 @@
 		}
 	}
 
-	error = security_ops->acct(file);
-	if (error)
+	if ((error = security_acct(file)))
 		return error;
 
 	spin_lock(&acct_globals.lock);
diff -Nru a/kernel/capability.c b/kernel/capability.c
--- a/kernel/capability.c	Wed Nov 27 14:36:27 2002
+++ b/kernel/capability.c	Wed Nov 27 14:36:27 2002
@@ -8,6 +8,7 @@
  */ 
 
 #include <linux/mm.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 
 unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
@@ -63,7 +64,7 @@
      } else
 	     target = current;
 
-     ret = security_ops->capget(target, &data.effective, &data.inheritable, &data.permitted);
+     ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted);
 
 out:
      read_unlock(&tasklist_lock); 
@@ -88,7 +89,7 @@
      do_each_thread(g, target) {
              if (target->pgrp != pgrp)
                      continue;
-	     security_ops->capset_set(target, effective, inheritable, permitted);
+	     security_capset_set(target, effective, inheritable, permitted);
      } while_each_thread(g, target);
 }
 
@@ -105,7 +106,7 @@
      do_each_thread(g, target) {
              if (target == current || target->pid == 1)
                      continue;
-	     security_ops->capset_set(target, effective, inheritable, permitted);
+	     security_capset_set(target, effective, inheritable, permitted);
      } while_each_thread(g, target);
 }
 
@@ -163,7 +164,7 @@
 
      ret = -EPERM;
 
-     if (security_ops->capset_check(target, &effective, &inheritable, &permitted))
+     if (security_capset_check(target, &effective, &inheritable, &permitted))
 	     goto out;
 
      if (!cap_issubset(inheritable, cap_combine(target->cap_inheritable,
@@ -190,7 +191,7 @@
              else            /* all procs in process group */
                      cap_set_pg(-pid, &effective, &inheritable, &permitted);
      } else {
-	     security_ops->capset_set(target, &effective, &inheritable, &permitted);
+	     security_capset_set(target, &effective, &inheritable, &permitted);
      }
 
 out:
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Wed Nov 27 14:36:31 2002
+++ b/kernel/exit.c	Wed Nov 27 14:36:31 2002
@@ -68,7 +68,7 @@
 		wait_task_inactive(p);
 
 	atomic_dec(&p->user->processes);
-	security_ops->task_free_security(p);
+	security_task_free(p);
 	free_uid(p->user);
 	write_lock_irq(&tasklist_lock);
 	if (unlikely(p->ptrace))
@@ -249,7 +249,7 @@
 	/* cpus_allowed? */
 	/* rt_priority? */
 	/* signals? */
-	security_ops->task_reparent_to_init(current);
+	security_task_reparent_to_init(current);
 	memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim)));
 	current->user = INIT_USER;
 
@@ -636,11 +636,11 @@
 {
 	struct task_struct *tsk = current;
 
-	if (in_interrupt())
+	if (unlikely(in_interrupt()))
 		panic("Aiee, killing interrupt handler!");
-	if (!tsk->pid)
+	if (unlikely(!tsk->pid))
 		panic("Attempted to kill the idle task!");
-	if (tsk->pid == 1)
+	if (unlikely(tsk->pid == 1))
 		panic("Attempted to kill init!");
 	tsk->flags |= PF_EXITING;
 	del_timer_sync(&tsk->real_timer);
@@ -787,7 +787,7 @@
 	if (current->tgid != p->tgid && delay_group_leader(p))
 		return 2;
 
-	if (security_ops->task_wait(p))
+	if (security_task_wait(p))
 		return 0;
 
 	return 1;
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Wed Nov 27 14:36:27 2002
+++ b/kernel/fork.c	Wed Nov 27 14:36:27 2002
@@ -717,8 +717,7 @@
 	if ((clone_flags & CLONE_DETACHED) && !(clone_flags & CLONE_THREAD))
 		return ERR_PTR(-EINVAL);
 
-	retval = security_ops->task_create(clone_flags);
-	if (retval)
+	if ((retval = security_task_create(clone_flags)))
 		goto fork_out;
 
 	retval = -ENOMEM;
@@ -795,15 +794,6 @@
 	p->tty_old_pgrp = 0;
 	p->utime = p->stime = 0;
 	p->cutime = p->cstime = 0;
-#ifdef CONFIG_SMP
-	{
-		int i;
-
-		/* ?? should we just memset this ?? */
-		for(i = 0; i < NR_CPUS; i++)
-			p->per_cpu_utime[i] = p->per_cpu_stime[i] = 0;
-	}
-#endif
 	p->array = NULL;
 	p->lock_depth = -1;		/* -1 = no lock */
 	p->start_time = jiffies;
@@ -811,7 +801,7 @@
 
 	p->core_waiter = 0;
 	retval = -ENOMEM;
-	if (security_ops->task_alloc_security(p))
+	if (security_task_alloc(p))
 		goto bad_fork_cleanup;
 	/* copy all the process information */
 	if (copy_semundo(clone_flags, p))
@@ -964,7 +954,7 @@
 bad_fork_cleanup_semundo:
 	exit_semundo(p);
 bad_fork_cleanup_security:
-	security_ops->task_free_security(p);
+	security_task_free(p);
 bad_fork_cleanup:
 	if (p->pid > 0)
 		free_pidmap(p->pid);
diff -Nru a/kernel/kmod.c b/kernel/kmod.c
--- a/kernel/kmod.c	Wed Nov 27 14:36:28 2002
+++ b/kernel/kmod.c	Wed Nov 27 14:36:28 2002
@@ -29,6 +29,7 @@
 #include <linux/completion.h>
 #include <linux/file.h>
 #include <linux/workqueue.h>
+#include <linux/security.h>
 #include <linux/mount.h>
 #include <asm/uaccess.h>
 
@@ -134,7 +135,7 @@
 	/* Give kmod all effective privileges.. */
 	curtask->euid = curtask->fsuid = 0;
 	curtask->egid = curtask->fsgid = 0;
-	security_ops->task_kmod_set_label();
+	security_task_kmod_set_label();
 
 	/* Allow execve args to be in kernel space. */
 	set_fs(KERNEL_DS);
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Wed Nov 27 14:36:27 2002
+++ b/kernel/ksyms.c	Wed Nov 27 14:36:27 2002
@@ -481,7 +481,7 @@
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
 EXPORT_SYMBOL(do_settimeofday);
-#ifdef CONFIG_DEBUG_KERNEL
+#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
 EXPORT_SYMBOL(__might_sleep);
 #endif
 #if !defined(__ia64__)
diff -Nru a/kernel/profile.c b/kernel/profile.c
--- a/kernel/profile.c	Wed Nov 27 14:36:32 2002
+++ b/kernel/profile.c	Wed Nov 27 14:36:32 2002
@@ -14,12 +14,16 @@
 unsigned int * prof_buffer;
 unsigned long prof_len;
 unsigned long prof_shift;
+int prof_on;
 
 int __init profile_setup(char * str)
 {
 	int par;
-	if (get_option(&str,&par))
+	if (get_option(&str,&par)) {
 		prof_shift = par;
+		prof_on = 1;
+		printk(KERN_INFO "kernel profiling enabled\n");
+	}
 	return 1;
 }
 
@@ -28,7 +32,7 @@
 {
 	unsigned int size;
  
-	if (!prof_shift) 
+	if (!prof_on) 
 		return;
  
 	/* only text is profiled */
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	Wed Nov 27 14:36:32 2002
+++ b/kernel/ptrace.c	Wed Nov 27 14:36:32 2002
@@ -14,6 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 #include <linux/ptrace.h>
+#include <linux/security.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -100,8 +101,7 @@
 	/* the same process cannot be attached many times */
 	if (task->ptrace & PT_PTRACED)
 		goto bad;
-	retval = security_ops->ptrace(current, task);
-	if (retval)
+	if ((retval = security_ptrace(current, task)))
 		goto bad;
 
 	/* Go */
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Wed Nov 27 14:36:31 2002
+++ b/kernel/sched.c	Wed Nov 27 14:36:31 2002
@@ -1348,8 +1348,7 @@
 	if (nice > 19)
 		nice = 19;
 
-	retval = security_ops->task_setnice(current, nice);
-	if (retval)
+	if ((retval = security_task_setnice(current, nice)))
 		return retval;
 
 	set_user_nice(current, nice);
@@ -1470,8 +1469,7 @@
 	    !capable(CAP_SYS_NICE))
 		goto out_unlock;
 
-	retval = security_ops->task_setscheduler(p, policy, &lp);
-	if (retval)
+	if ((retval = security_task_setscheduler(p, policy, &lp)))
 		goto out_unlock;
 
 	array = p->array;
@@ -1534,8 +1532,7 @@
 	read_lock(&tasklist_lock);
 	p = find_process_by_pid(pid);
 	if (p) {
-		retval = security_ops->task_getscheduler(p);
-		if (!retval)
+		if (!(retval = security_task_getscheduler(p)))
 			retval = p->policy;
 	}
 	read_unlock(&tasklist_lock);
@@ -1564,8 +1561,7 @@
 	if (!p)
 		goto out_unlock;
 
-	retval = security_ops->task_getscheduler(p);
-	if (retval)
+	if ((retval = security_task_getscheduler(p)))
 		goto out_unlock;
 
 	lp.sched_priority = p->rt_priority;
@@ -1824,8 +1820,7 @@
 	if (!p)
 		goto out_unlock;
 
-	retval = security_ops->task_getscheduler(p);
-	if (retval)
+	if ((retval = security_task_getscheduler(p)))
 		goto out_unlock;
 
 	jiffies_to_timespec(p->policy & SCHED_FIFO ?
@@ -2253,7 +2248,7 @@
 	enter_lazy_tlb(&init_mm, current, smp_processor_id());
 }
 
-#ifdef CONFIG_DEBUG_KERNEL
+#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
 void __might_sleep(char *file, int line)
 {
 #if defined(in_atomic)
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	Wed Nov 27 14:36:29 2002
+++ b/kernel/signal.c	Wed Nov 27 14:36:29 2002
@@ -18,6 +18,7 @@
 #include <linux/fs.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
+#include <linux/security.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/siginfo.h>
@@ -738,8 +739,7 @@
 	ret = -EPERM;
 	if (bad_signal(sig, info, t))
 		goto out;
-	ret = security_ops->task_kill(t, info, sig);
-	if (ret)
+	if ((ret = security_task_kill(t, info, sig)))
 		goto out;
 
 	/* The null signal is a permissions and process existence probe.
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Wed Nov 27 14:36:27 2002
+++ b/kernel/sys.c	Wed Nov 27 14:36:27 2002
@@ -390,6 +390,7 @@
 		device_shutdown();
 		printk(KERN_EMERG "System halted.\n");
 		machine_halt();
+		unlock_kernel();
 		do_exit(0);
 		break;
 
@@ -399,6 +400,7 @@
 		device_shutdown();
 		printk(KERN_EMERG "Power down.\n");
 		machine_power_off();
+		unlock_kernel();
 		do_exit(0);
 		break;
 
@@ -483,8 +485,7 @@
 	int new_egid = old_egid;
 	int retval;
 
-	retval = security_ops->task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
-	if (retval)
+	if ((retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE)))
 		return retval;
 
 	if (rgid != (gid_t) -1) {
@@ -529,8 +530,7 @@
 	int old_egid = current->egid;
 	int retval;
 
-	retval = security_ops->task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
-	if (retval)
+	if ((retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID)))
 		return retval;
 
 	if (capable(CAP_SETGID))
@@ -603,8 +603,7 @@
 	int old_ruid, old_euid, old_suid, new_ruid, new_euid;
 	int retval;
 
-	retval = security_ops->task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
-	if (retval)
+	if ((retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE)))
 		return retval;
 
 	new_ruid = old_ruid = current->uid;
@@ -642,7 +641,7 @@
 		current->suid = current->euid;
 	current->fsuid = current->euid;
 
-	return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
+	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
 }
 
 
@@ -664,8 +663,7 @@
 	int old_ruid, old_suid, new_ruid, new_suid;
 	int retval;
 
-	retval = security_ops->task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
-	if (retval)
+	if ((retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID)))
 		return retval;
 
 	old_ruid = new_ruid = current->uid;
@@ -687,7 +685,7 @@
 	current->fsuid = current->euid = uid;
 	current->suid = new_suid;
 
-	return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
+	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
 }
 
 
@@ -702,8 +700,7 @@
 	int old_suid = current->suid;
 	int retval;
 
-	retval = security_ops->task_setuid(ruid, euid, suid, LSM_SETID_RES);
-	if (retval)
+	if ((retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES)))
 		return retval;
 
 	if (!capable(CAP_SETUID)) {
@@ -733,7 +730,7 @@
 	if (suid != (uid_t) -1)
 		current->suid = suid;
 
-	return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
+	return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
 }
 
 asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
@@ -754,8 +751,7 @@
 {
 	int retval;
 
-	retval = security_ops->task_setgid(rgid, egid, sgid, LSM_SETID_RES);
-	if (retval)
+	if ((retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES)))
 		return retval;
 
 	if (!capable(CAP_SETGID)) {
@@ -808,8 +804,7 @@
 	int old_fsuid;
 	int retval;
 
-	retval = security_ops->task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
-	if (retval)
+	if ((retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)))
 		return retval;
 
 	old_fsuid = current->fsuid;
@@ -825,8 +820,7 @@
 		current->fsuid = uid;
 	}
 
-	retval = security_ops->task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
-	if (retval)
+	if ((retval = security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)))
 		return retval;
 
 	return old_fsuid;
@@ -840,8 +834,7 @@
 	int old_fsgid;
 	int retval;
 
-	retval = security_ops->task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS);
-	if (retval)
+	if ((retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS)))
 		return retval;
 
 	old_fsgid = current->fsgid;
@@ -966,8 +959,7 @@
 
 		retval = -ESRCH;
 		if (p) {
-			retval = security_ops->task_getpgid(p);
-			if (!retval)
+			if (!(retval = security_task_getpgid(p)))
 				retval = p->pgrp;
 		}
 		read_unlock(&tasklist_lock);
@@ -994,8 +986,7 @@
 
 		retval = -ESRCH;
 		if(p) {
-			retval = security_ops->task_getsid(p);
-			if (!retval)
+			if (!(retval = security_task_getsid(p)))
 				retval = p->session;
 		}
 		read_unlock(&tasklist_lock);
@@ -1076,8 +1067,7 @@
 		return -EINVAL;
 	if(copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t)))
 		return -EFAULT;
-	retval = security_ops->task_setgroups(gidsetsize, groups);
-	if (retval)
+	if ((retval = security_task_setgroups(gidsetsize, groups)))
 		return retval;
 	memcpy(current->groups, groups, gidsetsize * sizeof(gid_t));
 	current->ngroups = gidsetsize;
@@ -1199,7 +1189,7 @@
 			? -EFAULT : 0;
 }
 
-#if !defined(__ia64__) 
+#if !defined(__ia64__) && !defined(CONFIG_V850)
 
 /*
  *	Back compatibility for getrlimit. Needed for some apps.
@@ -1240,8 +1230,7 @@
 			return -EPERM;
 	}
 
-	retval = security_ops->task_setrlimit(resource, &new_rlim);
-	if (retval)
+	if ((retval = security_task_setrlimit(resource, &new_rlim)))
 		return retval;
 
 	*old_rlim = new_rlim;
@@ -1315,8 +1304,7 @@
 	int error = 0;
 	int sig;
 
-	error = security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
-	if (error)
+	if ((error = security_task_prctl(option, arg2, arg3, arg4, arg5)))
 		return error;
 
 	switch (option) {
diff -Nru a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c	Wed Nov 27 14:36:28 2002
+++ b/kernel/timer.c	Wed Nov 27 14:36:28 2002
@@ -694,8 +694,6 @@
 void update_one_process(struct task_struct *p, unsigned long user,
 			unsigned long system, int cpu)
 {
-	p->per_cpu_utime[cpu] += user;
-	p->per_cpu_stime[cpu] += system;
 	do_process_times(p, user, system);
 	do_it_virt(p, user);
 	do_it_prof(p);
diff -Nru a/kernel/uid16.c b/kernel/uid16.c
--- a/kernel/uid16.c	Wed Nov 27 14:36:30 2002
+++ b/kernel/uid16.c	Wed Nov 27 14:36:30 2002
@@ -140,8 +140,7 @@
 		return -EFAULT;
 	for (i = 0 ; i < gidsetsize ; i++)
 		new_groups[i] = (gid_t)groups[i];
-	i = security_ops->task_setgroups(gidsetsize, new_groups);
-	if (i)
+	if ((i = security_task_setgroups(gidsetsize, new_groups)))
 		return i;
 	memcpy(current->groups, new_groups, gidsetsize * sizeof(gid_t));
 	current->ngroups = gidsetsize;
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Wed Nov 27 14:36:28 2002
+++ b/mm/filemap.c	Wed Nov 27 14:36:28 2002
@@ -174,9 +174,11 @@
 int filemap_fdatawait(struct address_space * mapping)
 {
 	int ret = 0;
+	int progress;
 
+restart:
+	progress = 0;
 	write_lock(&mapping->page_lock);
-
         while (!list_empty(&mapping->locked_pages)) {
 		struct page *page;
 
@@ -187,9 +189,18 @@
 		else
 			list_add(&page->list, &mapping->clean_pages);
 
-		if (!PageWriteback(page))
+		if (!PageWriteback(page)) {
+			if (++progress > 32) {
+				if (need_resched()) {
+					write_unlock(&mapping->page_lock);
+					__cond_resched();
+					goto restart;
+				}
+			}
 			continue;
+		}
 
+		progress = 0;
 		page_cache_get(page);
 		write_unlock(&mapping->page_lock);
 
@@ -559,6 +570,7 @@
 				break;
 		}
 
+		cond_resched();
 		page_cache_readahead(mapping, ra, filp, index);
 
 		nr = nr - offset;
@@ -1770,6 +1782,7 @@
 		if (status < 0)
 			break;
 		balance_dirty_pages_ratelimited(mapping);
+		cond_resched();
 	} while (count);
 	*ppos = pos;
 
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Wed Nov 27 14:36:31 2002
+++ b/mm/mmap.c	Wed Nov 27 14:36:31 2002
@@ -504,8 +504,7 @@
 		}
 	}
 
-	error = security_ops->file_mmap(file, prot, flags);
-	if (error)
+	if ((error = security_file_mmap(file, prot, flags)))
 		return error;
 		
 	/* Clear old maps */
diff -Nru a/mm/mprotect.c b/mm/mprotect.c
--- a/mm/mprotect.c	Wed Nov 27 14:36:29 2002
+++ b/mm/mprotect.c	Wed Nov 27 14:36:29 2002
@@ -263,8 +263,7 @@
 			goto out;
 		}
 
-		error = security_ops->file_mprotect(vma, prot);
-		if (error)
+		if ((error = security_file_mprotect(vma, prot)))
 			goto out;
 
 		if (vma->vm_end > end) {
diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c
--- a/mm/page-writeback.c	Wed Nov 27 14:36:31 2002
+++ b/mm/page-writeback.c	Wed Nov 27 14:36:31 2002
@@ -229,8 +229,8 @@
 		wbc.nr_to_write = MAX_WRITEBACK_PAGES;
 		writeback_inodes(&wbc);
 		min_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
-		if (wbc.nr_to_write == MAX_WRITEBACK_PAGES) {
-			/* Wrote nothing */
+		if (wbc.nr_to_write > 0) {
+			/* Wrote less than expected */
 			if (wbc.encountered_congestion)
 				blk_congestion_wait(WRITE, HZ/10);
 			else
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	Wed Nov 27 14:36:28 2002
+++ b/mm/swapfile.c	Wed Nov 27 14:36:28 2002
@@ -93,6 +93,7 @@
 			si->highest_bit = 0;
 		}
 		si->swap_map[offset] = 1;
+		si->inuse_pages++;
 		nr_swap_pages--;
 		si->cluster_next = offset+1;
 		return offset;
@@ -208,6 +209,7 @@
 			if (offset > p->highest_bit)
 				p->highest_bit = offset;
 			nr_swap_pages++;
+			p->inuse_pages--;
 		}
 	}
 	return count;
@@ -668,12 +670,9 @@
 		 * report them; but do report if we reset SWAP_MAP_MAX.
 		 */
 		if (*swap_map == SWAP_MAP_MAX) {
-			swap_list_lock();
 			swap_device_lock(si);
-			nr_swap_pages++;
 			*swap_map = 1;
 			swap_device_unlock(si);
-			swap_list_unlock();
 			reset_overflow = 1;
 		}
 
@@ -961,13 +960,20 @@
 	unsigned short *swap_map;
 	struct file *swap_file, *victim;
 	struct address_space *mapping;
+	char * pathname;
 	int i, type, prev;
 	int err;
 	
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	victim = filp_open(specialfile, O_RDWR, 0);
+	pathname = getname(specialfile);
+	err = PTR_ERR(pathname);
+	if (IS_ERR(pathname))
+		goto out;
+
+	victim = filp_open(pathname, O_RDWR, 0);
+	putname(pathname);
 	err = PTR_ERR(victim);
 	if (IS_ERR(victim))
 		goto out;
@@ -1097,7 +1103,6 @@
 static int swap_show(struct seq_file *swap, void *v)
 {
 	struct swap_info_struct *ptr = v;
-	int j, usedswap;
 	struct file *file;
 	char *path;
 
@@ -1107,20 +1112,12 @@
 	file = ptr->swap_file;
 	path = d_path(file->f_dentry, file->f_vfsmnt, swap->private, PAGE_SIZE);
 
-	for (j = 0, usedswap = 0; j < ptr->max; ++j)
-		switch (ptr->swap_map[j]) {
-			case SWAP_MAP_BAD:
-			case 0:
-				continue;
-			default:
-				usedswap++;
-		}
-	seq_printf(swap, "%-39s %s\t%d\t%d\t%d\n",
+	seq_printf(swap, "%-39s %s\t%d\t%ld\t%d\n",
 		       path,
 		       S_ISBLK(file->f_dentry->d_inode->i_mode) ?
 				"partition" : "file\t",
 		       ptr->pages << (PAGE_SHIFT - 10),
-		       usedswap << (PAGE_SHIFT - 10),
+		       ptr->inuse_pages << (PAGE_SHIFT - 10),
 		       ptr->prio);
 	return 0;
 }
@@ -1203,6 +1200,7 @@
 	p->lowest_bit = 0;
 	p->highest_bit = 0;
 	p->cluster_nr = 0;
+	p->inuse_pages = 0;
 	p->sdev_lock = SPIN_LOCK_UNLOCKED;
 	p->next = -1;
 	if (swap_flags & SWAP_FLAG_PREFER) {
@@ -1412,19 +1410,10 @@
 
 	swap_list_lock();
 	for (i = 0; i < nr_swapfiles; i++) {
-		unsigned int j;
 		if (!(swap_info[i].flags & SWP_USED) ||
 		     (swap_info[i].flags & SWP_WRITEOK))
 			continue;
-		for (j = 0; j < swap_info[i].max; ++j) {
-			switch (swap_info[i].swap_map[j]) {
-				case 0:
-				case SWAP_MAP_BAD:
-					continue;
-				default:
-					nr_to_be_unused++;
-			}
-		}
+		nr_to_be_unused += swap_info[i].inuse_pages;
 	}
 	val->freeswap = nr_swap_pages + nr_to_be_unused;
 	val->totalswap = total_swap_pages + nr_to_be_unused;
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	Wed Nov 27 14:36:28 2002
+++ b/mm/vmscan.c	Wed Nov 27 14:36:28 2002
@@ -155,10 +155,18 @@
 		do_div(delta, pages + 1);
 		shrinker->nr += delta;
 		if (shrinker->nr > SHRINK_BATCH) {
-			long nr = shrinker->nr;
+			long nr_to_scan = shrinker->nr;
 
 			shrinker->nr = 0;
-			(*shrinker->shrinker)(nr, gfp_mask);
+			while (nr_to_scan) {
+				long this_scan = nr_to_scan;
+
+				if (this_scan > 128)
+					this_scan = 128;
+				(*shrinker->shrinker)(this_scan, gfp_mask);
+				nr_to_scan -= this_scan;
+				cond_resched();
+			}
 		}
 	}
 	up(&shrinker_sem);
@@ -208,6 +216,8 @@
 	struct pagevec freed_pvec;
 	int pgactivate = 0;
 	int ret = 0;
+
+	cond_resched();
 
 	pagevec_init(&freed_pvec, 1);
 	while (!list_empty(page_list)) {
diff -Nru a/net/atm/common.c b/net/atm/common.c
--- a/net/atm/common.c	Wed Nov 27 14:36:32 2002
+++ b/net/atm/common.c	Wed Nov 27 14:36:32 2002
@@ -287,7 +287,7 @@
 	if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC)
 		clear_bit(ATM_VF_PARTIAL,&vcc->flags);
 	else if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) return -EINVAL;
-	printk(KERN_DEBUG "atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
+	DPRINTK("atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
 	    "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n",
 	    vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr,
 	    vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu,
diff -Nru a/net/atm/proc.c b/net/atm/proc.c
--- a/net/atm/proc.c	Wed Nov 27 14:36:28 2002
+++ b/net/atm/proc.c	Wed Nov 27 14:36:28 2002
@@ -549,9 +549,12 @@
 	digits = 0;
 	for (num = dev->number; num; num /= 10) digits++;
 	if (!digits) digits++;
-	dev->proc_name = kmalloc(strlen(dev->type)+digits+2,GFP_KERNEL);
-	if (!dev->proc_name) goto fail1;
+
+	dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_KERNEL);
+	if (!dev->proc_name)
+		goto fail1;
 	sprintf(dev->proc_name,"%s:%d",dev->type, dev->number);
+
 	dev->proc_entry = create_proc_entry(dev->proc_name, 0, atm_proc_root);
 	if (!dev->proc_entry)
 		goto fail0;
diff -Nru a/net/core/scm.c b/net/core/scm.c
--- a/net/core/scm.c	Wed Nov 27 14:36:29 2002
+++ b/net/core/scm.c	Wed Nov 27 14:36:29 2002
@@ -217,8 +217,7 @@
 	for (i=0, cmfptr=(int*)CMSG_DATA(cm); i<fdmax; i++, cmfptr++)
 	{
 		int new_fd;
-		err = security_ops->file_receive(fp[i]);
-		if (err)
+		if ((err = security_file_receive(fp[i])))
 			break;
 		err = get_unused_fd();
 		if (err < 0)
diff -Nru a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
--- a/net/decnet/af_decnet.c	Wed Nov 27 14:36:30 2002
+++ b/net/decnet/af_decnet.c	Wed Nov 27 14:36:30 2002
@@ -797,7 +797,7 @@
 	 * dn_prot_sock ? Would be nice if the capable call would go there
 	 * too.
 	 */
-	if (security_ops->dn_prot_sock(saddr) &&
+	if (security_dn_prot_sock(saddr) &&
 	    !capable(CAP_NET_BIND_SERVICE) || 
 	    saddr->sdn_objnum || (saddr->sdn_flags & SDF_WILD))
 		return -EACCES;
diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
--- a/net/unix/af_unix.c	Wed Nov 27 14:36:31 2002
+++ b/net/unix/af_unix.c	Wed Nov 27 14:36:31 2002
@@ -90,6 +90,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/stat.h>
+#include <linux/dcache.h>
 #include <linux/namei.h>
 #include <linux/socket.h>
 #include <linux/un.h>
diff -Nru a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
--- a/net/wanrouter/wanmain.c	Wed Nov 27 14:36:31 2002
+++ b/net/wanrouter/wanmain.c	Wed Nov 27 14:36:31 2002
@@ -124,14 +124,6 @@
  */
 
 /*
- * 	Kernel loadable module interface.
- */
-#ifdef MODULE
-int init_module (void);
-void cleanup_module (void);
-#endif
-
-/*
  *	WAN device IOCTL handlers
  */
 
diff -Nru a/scripts/lxdialog/util.c b/scripts/lxdialog/util.c
--- a/scripts/lxdialog/util.c	Wed Nov 27 14:36:30 2002
+++ b/scripts/lxdialog/util.c	Wed Nov 27 14:36:30 2002
@@ -348,7 +348,7 @@
 		c = tolower(string[i]);
 
 		if (strchr("<[(", c)) ++in_paren;
-		if (strchr(">])", c)) --in_paren;
+		if (strchr(">])", c) && in_paren > 0) --in_paren;
 
 		if ((! in_paren) && isalpha(c) && 
 		     strchr(exempt, c) == 0)
diff -Nru a/security/Kconfig b/security/Kconfig
--- a/security/Kconfig	Wed Nov 27 14:36:31 2002
+++ b/security/Kconfig	Wed Nov 27 14:36:31 2002
@@ -4,9 +4,20 @@
 
 menu "Security options"
 
+config SECURITY
+	bool "Enable different security models"
+	help
+	  This allows you to choose different security modules to be
+	  configured into your kernel.
+
+	  If this option is not selected, the default Linux security
+	  model will be used.
+
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_CAPABILITIES
-	bool
-	default y
+	tristate "Default Linux Capabilities"
+	depends on SECURITY!=n
 	help
 	  This enables the "default" Linux capabilities functionality.
 	  If you are unsure how to answer this question, answer Y.
diff -Nru a/security/Makefile b/security/Makefile
--- a/security/Makefile	Wed Nov 27 14:36:31 2002
+++ b/security/Makefile	Wed Nov 27 14:36:31 2002
@@ -3,11 +3,15 @@
 #
 
 # Objects that export symbols
-export-objs	:= security.o
+export-objs	:= security.o capability.o
 
-# Object file lists
-obj-y		:= security.o dummy.o
+# if we don't select a security model, use the default capabilities
+ifneq ($(CONFIG_SECURITY),y)
+obj-y		+= capability.o
+endif
 
+# Object file lists
+obj-$(CONFIG_SECURITY)			+= security.o dummy.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= capability.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/security/capability.c b/security/capability.c
--- a/security/capability.c	Wed Nov 27 14:36:29 2002
+++ b/security/capability.c	Wed Nov 27 14:36:29 2002
@@ -19,10 +19,7 @@
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 
-/* flag to keep track of how we were registered */
-static int secondary;
-
-static int cap_capable (struct task_struct *tsk, int cap)
+int cap_capable (struct task_struct *tsk, int cap)
 {
 	/* Derived from include/linux/sched.h:capable. */
 	if (cap_raised (tsk->cap_effective, cap))
@@ -31,23 +28,7 @@
 		return -EPERM;
 }
 
-static int cap_sys_security (unsigned int id, unsigned int call,
-			     unsigned long *args)
-{
-	return -ENOSYS;
-}
-
-static int cap_quotactl (int cmds, int type, int id, struct super_block *sb)
-{
-	return 0;
-}
-
-static int cap_quota_on (struct file *f)
-{
-	return 0;
-}
-
-static int cap_ptrace (struct task_struct *parent, struct task_struct *child)
+int cap_ptrace (struct task_struct *parent, struct task_struct *child)
 {
 	/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
 	if (!cap_issubset (child->cap_permitted, current->cap_permitted) &&
@@ -57,8 +38,8 @@
 		return 0;
 }
 
-static int cap_capget (struct task_struct *target, kernel_cap_t * effective,
-		       kernel_cap_t * inheritable, kernel_cap_t * permitted)
+int cap_capget (struct task_struct *target, kernel_cap_t *effective,
+		kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
 	/* Derived from kernel/capability.c:sys_capget. */
 	*effective = cap_t (target->cap_effective);
@@ -67,10 +48,8 @@
 	return 0;
 }
 
-static int cap_capset_check (struct task_struct *target,
-			     kernel_cap_t * effective,
-			     kernel_cap_t * inheritable,
-			     kernel_cap_t * permitted)
+int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
+		      kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
 	/* Derived from kernel/capability.c:sys_capset. */
 	/* verify restrictions on target's new Inheritable set */
@@ -95,27 +74,15 @@
 	return 0;
 }
 
-static void cap_capset_set (struct task_struct *target,
-			    kernel_cap_t * effective,
-			    kernel_cap_t * inheritable,
-			    kernel_cap_t * permitted)
+void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
+		     kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
 	target->cap_effective = *effective;
 	target->cap_inheritable = *inheritable;
 	target->cap_permitted = *permitted;
 }
 
-static int cap_acct (struct file *file)
-{
-	return 0;
-}
-
-static int cap_bprm_alloc_security (struct linux_binprm *bprm)
-{
-	return 0;
-}
-
-static int cap_bprm_set_security (struct linux_binprm *bprm)
+int cap_bprm_set_security (struct linux_binprm *bprm)
 {
 	/* Copied from fs/exec.c:prepare_binprm. */
 
@@ -143,23 +110,13 @@
 	return 0;
 }
 
-static int cap_bprm_check_security (struct linux_binprm *bprm)
-{
-	return 0;
-}
-
-static void cap_bprm_free_security (struct linux_binprm *bprm)
-{
-	return;
-}
-
 /* Copied from fs/exec.c */
 static inline int must_not_trace_exec (struct task_struct *p)
 {
 	return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
 }
 
-static void cap_bprm_compute_creds (struct linux_binprm *bprm)
+void cap_bprm_compute_creds (struct linux_binprm *bprm)
 {
 	/* Derived from fs/exec.c:compute_creds. */
 	kernel_cap_t new_permitted, working;
@@ -204,6 +161,154 @@
 	current->keep_capabilities = 0;
 }
 
+/* moved from kernel/sys.c. */
+/* 
+ * cap_emulate_setxuid() fixes the effective / permitted capabilities of
+ * a process after a call to setuid, setreuid, or setresuid.
+ *
+ *  1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
+ *  {r,e,s}uid != 0, the permitted and effective capabilities are
+ *  cleared.
+ *
+ *  2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
+ *  capabilities of the process are cleared.
+ *
+ *  3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
+ *  capabilities are set to the permitted capabilities.
+ *
+ *  fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should 
+ *  never happen.
+ *
+ *  -astor 
+ *
+ * cevans - New behaviour, Oct '99
+ * A process may, via prctl(), elect to keep its capabilities when it
+ * calls setuid() and switches away from uid==0. Both permitted and
+ * effective sets will be retained.
+ * Without this change, it was impossible for a daemon to drop only some
+ * of its privilege. The call to setuid(!=0) would drop all privileges!
+ * Keeping uid 0 is not an option because uid 0 owns too many vital
+ * files..
+ * Thanks to Olaf Kirch and Peter Benie for spotting this.
+ */
+static inline void cap_emulate_setxuid (int old_ruid, int old_euid,
+					int old_suid)
+{
+	if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
+	    (current->uid != 0 && current->euid != 0 && current->suid != 0) &&
+	    !current->keep_capabilities) {
+		cap_clear (current->cap_permitted);
+		cap_clear (current->cap_effective);
+	}
+	if (old_euid == 0 && current->euid != 0) {
+		cap_clear (current->cap_effective);
+	}
+	if (old_euid != 0 && current->euid == 0) {
+		current->cap_effective = current->cap_permitted;
+	}
+}
+
+int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
+			  int flags)
+{
+	switch (flags) {
+	case LSM_SETID_RE:
+	case LSM_SETID_ID:
+	case LSM_SETID_RES:
+		/* Copied from kernel/sys.c:setreuid/setuid/setresuid. */
+		if (!issecure (SECURE_NO_SETUID_FIXUP)) {
+			cap_emulate_setxuid (old_ruid, old_euid, old_suid);
+		}
+		break;
+	case LSM_SETID_FS:
+		{
+			uid_t old_fsuid = old_ruid;
+
+			/* Copied from kernel/sys.c:setfsuid. */
+
+			/*
+			 * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
+			 *          if not, we might be a bit too harsh here.
+			 */
+
+			if (!issecure (SECURE_NO_SETUID_FIXUP)) {
+				if (old_fsuid == 0 && current->fsuid != 0) {
+					cap_t (current->cap_effective) &=
+					    ~CAP_FS_MASK;
+				}
+				if (old_fsuid != 0 && current->fsuid == 0) {
+					cap_t (current->cap_effective) |=
+					    (cap_t (current->cap_permitted) &
+					     CAP_FS_MASK);
+				}
+			}
+			break;
+		}
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void cap_task_kmod_set_label (void)
+{
+	cap_set_full (current->cap_effective);
+	return;
+}
+
+void cap_task_reparent_to_init (struct task_struct *p)
+{
+	p->cap_effective = CAP_INIT_EFF_SET;
+	p->cap_inheritable = CAP_INIT_INH_SET;
+	p->cap_permitted = CAP_FULL_SET;
+	p->keep_capabilities = 0;
+	return;
+}
+
+EXPORT_SYMBOL(cap_capable);
+EXPORT_SYMBOL(cap_ptrace);
+EXPORT_SYMBOL(cap_capget);
+EXPORT_SYMBOL(cap_capset_check);
+EXPORT_SYMBOL(cap_capset_set);
+EXPORT_SYMBOL(cap_bprm_set_security);
+EXPORT_SYMBOL(cap_bprm_compute_creds);
+EXPORT_SYMBOL(cap_task_post_setuid);
+EXPORT_SYMBOL(cap_task_kmod_set_label);
+EXPORT_SYMBOL(cap_task_reparent_to_init);
+
+#ifdef CONFIG_SECURITY
+
+static int cap_quotactl (int cmds, int type, int id, struct super_block *sb)
+{
+	return 0;
+}
+
+static int cap_quota_on (struct file *f)
+{
+	return 0;
+}
+
+static int cap_acct (struct file *file)
+{
+	return 0;
+}
+
+static int cap_bprm_alloc_security (struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static int cap_bprm_check_security (struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static void cap_bprm_free_security (struct linux_binprm *bprm)
+{
+	return;
+}
+
 static int cap_sb_alloc_security (struct super_block *sb)
 {
 	return 0;
@@ -507,96 +612,6 @@
 	return 0;
 }
 
-/* moved from kernel/sys.c. */
-/* 
- * cap_emulate_setxuid() fixes the effective / permitted capabilities of
- * a process after a call to setuid, setreuid, or setresuid.
- *
- *  1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
- *  {r,e,s}uid != 0, the permitted and effective capabilities are
- *  cleared.
- *
- *  2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
- *  capabilities of the process are cleared.
- *
- *  3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
- *  capabilities are set to the permitted capabilities.
- *
- *  fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should 
- *  never happen.
- *
- *  -astor 
- *
- * cevans - New behaviour, Oct '99
- * A process may, via prctl(), elect to keep its capabilities when it
- * calls setuid() and switches away from uid==0. Both permitted and
- * effective sets will be retained.
- * Without this change, it was impossible for a daemon to drop only some
- * of its privilege. The call to setuid(!=0) would drop all privileges!
- * Keeping uid 0 is not an option because uid 0 owns too many vital
- * files..
- * Thanks to Olaf Kirch and Peter Benie for spotting this.
- */
-static inline void cap_emulate_setxuid (int old_ruid, int old_euid,
-					int old_suid)
-{
-	if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
-	    (current->uid != 0 && current->euid != 0 && current->suid != 0) &&
-	    !current->keep_capabilities) {
-		cap_clear (current->cap_permitted);
-		cap_clear (current->cap_effective);
-	}
-	if (old_euid == 0 && current->euid != 0) {
-		cap_clear (current->cap_effective);
-	}
-	if (old_euid != 0 && current->euid == 0) {
-		current->cap_effective = current->cap_permitted;
-	}
-}
-
-static int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
-				 int flags)
-{
-	switch (flags) {
-	case LSM_SETID_RE:
-	case LSM_SETID_ID:
-	case LSM_SETID_RES:
-		/* Copied from kernel/sys.c:setreuid/setuid/setresuid. */
-		if (!issecure (SECURE_NO_SETUID_FIXUP)) {
-			cap_emulate_setxuid (old_ruid, old_euid, old_suid);
-		}
-		break;
-	case LSM_SETID_FS:
-		{
-			uid_t old_fsuid = old_ruid;
-
-			/* Copied from kernel/sys.c:setfsuid. */
-
-			/*
-			 * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
-			 *          if not, we might be a bit too harsh here.
-			 */
-
-			if (!issecure (SECURE_NO_SETUID_FIXUP)) {
-				if (old_fsuid == 0 && current->fsuid != 0) {
-					cap_t (current->cap_effective) &=
-					    ~CAP_FS_MASK;
-				}
-				if (old_fsuid != 0 && current->fsuid == 0) {
-					cap_t (current->cap_effective) |=
-					    (cap_t (current->cap_permitted) &
-					     CAP_FS_MASK);
-				}
-			}
-			break;
-		}
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static int cap_task_setgid (gid_t id0, gid_t id1, gid_t id2, int flags)
 {
 	return 0;
@@ -659,21 +674,6 @@
 	return 0;
 }
 
-static void cap_task_kmod_set_label (void)
-{
-	cap_set_full (current->cap_effective);
-	return;
-}
-
-static void cap_task_reparent_to_init (struct task_struct *p)
-{
-	p->cap_effective = CAP_INIT_EFF_SET;
-	p->cap_inheritable = CAP_INIT_INH_SET;
-	p->cap_permitted = CAP_FULL_SET;
-	p->keep_capabilities = 0;
-	return;
-}
-
 static int cap_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
 {
 	return 0;
@@ -726,7 +726,6 @@
 	.capset_set =			cap_capset_set,
 	.acct =				cap_acct,
 	.capable =			cap_capable,
-	.sys_security =			cap_sys_security,
 	.quotactl =			cap_quotactl,
 	.quota_on =			cap_quota_on,
 
@@ -832,6 +831,10 @@
 #define MY_NAME "capability"
 #endif
 
+/* flag to keep track of how we were registered */
+static int secondary;
+
+
 static int __init capability_init (void)
 {
 	/* register ourselves with the security framework */
@@ -871,3 +874,5 @@
 
 MODULE_DESCRIPTION("Standard Linux Capabilities Security Module");
 MODULE_LICENSE("GPL");
+
+#endif	/* CONFIG_SECURITY */
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	Wed Nov 27 14:36:28 2002
+++ b/security/dummy.c	Wed Nov 27 14:36:28 2002
@@ -72,12 +72,6 @@
 	return -EPERM;
 }
 
-static int dummy_sys_security (unsigned int id, unsigned int call,
-			       unsigned long *args)
-{
-	return -ENOSYS;
-}
-
 static int dummy_quotactl (int cmds, int type, int id, struct super_block *sb)
 {
 	return 0;
@@ -552,7 +546,6 @@
 	.capset_set =			dummy_capset_set,
 	.acct =				dummy_acct,
 	.capable =			dummy_capable,
-	.sys_security =			dummy_sys_security,
 	.quotactl =			dummy_quotactl,
 	.quota_on =			dummy_quota_on,
 
diff -Nru a/security/security.c b/security/security.c
--- a/security/security.c	Wed Nov 27 14:36:27 2002
+++ b/security/security.c	Wed Nov 27 14:36:27 2002
@@ -223,24 +223,6 @@
 	return 1;
 }
 
-/**
- * sys_security - security syscall multiplexor.
- * @id: module id
- * @call: call identifier
- * @args: arg list for call
- *
- * Similar to sys_socketcall.  Can use id to help identify which module user
- * app is talking to.  The recommended convention for creating the
- * hexadecimal id value is:
- * 'echo "Name_of_module" | md5sum | cut -c -8'.
- * By following this convention, there's no need for a central registry.
- */
-asmlinkage long sys_security (unsigned int id, unsigned int call,
-			      unsigned long *args)
-{
-	return security_ops->sys_security (id, call, args);
-}
-
 EXPORT_SYMBOL_GPL(register_security);
 EXPORT_SYMBOL_GPL(unregister_security);
 EXPORT_SYMBOL_GPL(mod_reg_security);
diff -Nru a/sound/oss/Kconfig b/sound/oss/Kconfig
--- a/sound/oss/Kconfig	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/Kconfig	Wed Nov 27 14:36:31 2002
@@ -156,7 +156,7 @@
 	  1274:5000. Since Ensoniq was bought by Creative Labs,
 	  Sound Blaster 64/PCI models are either ES1370 or ES1371 based.
 	  This driver differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/es1370>.
+	  <file:Documentation/sound/oss/es1370>.
 
 config SOUND_ES1371
 	tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
@@ -180,7 +180,7 @@
 	  Solo1 chip without removing your computer's cover, use
 	  lspci -n and look for the PCI ID 125D:1969. This driver
 	  differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/solo1>.
+	  <file:Documentation/sound/oss/solo1>.
 
 config SOUND_MAESTRO
 	tristate "ESS Maestro, Maestro2, Maestro2E driver"
@@ -188,7 +188,7 @@
 	help
 	  Say Y or M if you have a sound system driven by ESS's Maestro line
 	  of PCI sound chips.  These include the Maestro 1, Maestro 2, and
-	  Maestro 2E.  See <file:Documentation/sound/Maestro> for more
+	  Maestro 2E.  See <file:Documentation/sound/oss/Maestro> for more
 	  details.
 
 config SOUND_MAESTRO3
@@ -221,7 +221,7 @@
 	  SonicVibes chip without removing your computer's cover, use
 	  lspci -n and look for the PCI ID 5333:CA00. This driver
 	  differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/sonicvibes>.
+	  <file:Documentation/sound/oss/sonicvibes>.
 
 config SOUND_VWSND
 	tristate "SGI Visual Workstation Sound"
@@ -229,7 +229,7 @@
 	help
 	  Say Y or M if you have an SGI Visual Workstation and you want to be
 	  able to use its on-board audio.  Read
-	  <file:Documentation/sound/vwsnd> for more info on this driver's
+	  <file:Documentation/sound/oss/vwsnd> for more info on this driver's
 	  capabilities.
 
 config SOUND_VRC5477
@@ -284,7 +284,7 @@
 	  Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
 	  Monterey (not for the Pinnacle or Fiji).
 
-	  See <file:Documentation/sound/MultiSound> for important information
+	  See <file:Documentation/sound/oss/MultiSound> for important information
 	  about this driver.  Note that it has been discontinued, but the
 	  Voyetra Turtle Beach knowledge base entry for it is still available
 	  at <http://www.voyetra-turtle-beach.com/site/kb_ftp/790.asp>.
@@ -293,7 +293,7 @@
 	depends on SOUND_PRIME && SOUND_MSNDCLAS=y
 
 config MSNDCLAS_HAVE_BOOT
-	bool
+	bool "Have MSNDINIT.BIN firmware file"
 	depends on SOUND_MSNDCLAS=y
 	default y
 
@@ -305,7 +305,7 @@
 	  The MultiSound cards have two firmware files which are required for
 	  operation, and are not currently included. These files can be
 	  obtained from Turtle Beach. See
-	  <file:Documentation/sound/MultiSound> for information on how to
+	  <file:Documentation/sound/oss/MultiSound> for information on how to
 	  obtain this.
 
 config MSNDCLAS_PERM_FILE
@@ -316,7 +316,7 @@
 	  The MultiSound cards have two firmware files which are required for
 	  operation, and are not currently included. These files can be
 	  obtained from Turtle Beach. See
-	  <file:Documentation/sound/MultiSound> for information on how to
+	  <file:Documentation/sound/oss/MultiSound> for information on how to
 	  obtain this.
 
 config MSNDCLAS_IRQ
@@ -346,7 +346,7 @@
 	depends on SOUND_PRIME!=n && SOUND
 	help
 	  Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji.
-	  See <file:Documentation/sound/MultiSound> for important information
+	  See <file:Documentation/sound/oss/MultiSound> for important information
 	  about this driver. Note that it has been discontinued, but the
 	  Voyetra Turtle Beach knowledge base entry for it is still available
 	  at <http://www.voyetra-turtle-beach.com/site/kb_ftp/600.asp>.
@@ -355,7 +355,7 @@
 	depends on SOUND_PRIME && SOUND_MSNDPIN=y
 
 config MSNDPIN_HAVE_BOOT
-	bool
+	bool "Have PNDSPINI.BIN firmware file"
 	depends on SOUND_MSNDPIN=y
 	default y
 
@@ -367,7 +367,7 @@
 	  The MultiSound cards have two firmware files which are required
 	  for operation, and are not currently included. These files can be
 	  obtained from Turtle Beach. See
-	  <file:Documentation/sound/MultiSound> for information on how to
+	  <file:Documentation/sound/oss/MultiSound> for information on how to
 	  obtain this.
 
 config MSNDPIN_PERM_FILE
@@ -378,7 +378,7 @@
 	  The MultiSound cards have two firmware files which are required for
 	  operation, and are not currently included. These files can be
 	  obtained from Turtle Beach. See
-	  <file:Documentation/sound/MultiSound> for information on how to
+	  <file:Documentation/sound/oss/MultiSound> for information on how to
 	  obtain this.
 
 config MSNDPIN_IRQ
@@ -412,7 +412,7 @@
 	  If you have the S/PDIF daughter board for the Pinnacle or Fiji,
 	  answer Y here; otherwise, say N. If you have this, you will be able
 	  to play and record from the S/PDIF port (digital signal). See
-	  <file:Documentation/sound/MultiSound> for information on how to make
+	  <file:Documentation/sound/oss/MultiSound> for information on how to make
 	  use of this capability.
 
 config MSNDPIN_NONPNP
@@ -613,7 +613,7 @@
 	  "cs4232=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
 	  command line.
 
-	  See <file:Documentation/sound/CS4232> for more information on
+	  See <file:Documentation/sound/oss/CS4232> for more information on
 	  configuring this card.
 
 config SOUND_SSCAPE
@@ -633,7 +633,7 @@
 	depends on SOUND_OSS
 	help
 	  Say Y here for any type of Gravis Ultrasound card, including the GUS
-	  or GUS MAX.  See also <file:Documentation/sound/ultrasound> for more
+	  or GUS MAX.  See also <file:Documentation/sound/oss/ultrasound> for more
 	  information on configuring this card with modules.
 
 	  If you compile the driver into the kernel, you have to add
@@ -706,7 +706,7 @@
 	  synthesizers (OPL2, OPL3 and OPL4), 6850 UART MIDI Interface.
 
 	  For cards having native support in VoxWare, consult the card
-	  specific instructions in <file:Documentation/sound/README.OSS>.
+	  specific instructions in <file:Documentation/sound/oss/README.OSS>.
 	  Some drivers have their own MSS support and saying Y to this option
 	  will cause a conflict.
 
@@ -724,7 +724,7 @@
 	  will cause a conflict.  Also, enabling MPU401 on a system that
 	  doesn't really have a MPU401 could cause some trouble.  If your card
 	  was in the list of supported cards, look at the card specific
-	  instructions in the <file:Documentation/sound/README.OSS> file.  It
+	  instructions in the <file:Documentation/sound/oss/README.OSS> file.  It
 	  is safe to answer Y if you have a true MPU401 MIDI interface card.
 
 	  If you compile the driver into the kernel, you have to add
@@ -740,7 +740,7 @@
 	  laptops. It includes support for an AC97-compatible mixer and an
 	  apparently proprietary sound engine.
 
-	  See <file:Documentation/sound/NM256> for further information.
+	  See <file:Documentation/sound/oss/NM256> for further information.
 
 config SOUND_MAD16
 	tristate "OPTi MAD16 and/or Mozart based cards"
@@ -759,8 +759,8 @@
 	  "mad16=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the
 	  kernel command line.
 
-	  See also <file:Documentation/sound/Opti> and
-	  <file:Documentation/sound/MAD16> for more information on setting
+	  See also <file:Documentation/sound/oss/Opti> and
+	  <file:Documentation/sound/oss/MAD16> for more information on setting
 	  these cards up as modules.
 
 config MAD16_OLDCARD
@@ -778,7 +778,7 @@
 	  Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
 	  16 or Logitech SoundMan 16 sound card. Answer N if you have some
 	  other card made by Media Vision or Logitech since those are not
-	  PAS16 compatible. Please read <file:Documentation/sound/PAS16>.
+	  PAS16 compatible. Please read <file:Documentation/sound/oss/PAS16>.
 	  It is not necessary to add Sound Blaster support separately; it
 	  is included in PAS support.
 
@@ -801,7 +801,7 @@
 	  ADSP-16 or some other card based on the PSS chipset (AD1848 codec +
 	  ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). For more information on
 	  how to compile it into the kernel or as a module see the file
-	  <file:Documentation/sound/PSS>.
+	  <file:Documentation/sound/oss/PSS>.
 
 	  If you compile the driver into the kernel, you have to add
 	  "pss=<io>,<mssio>,<mssirq>,<mssdma>,<mpuio>,<mpuirq>" to the kernel
@@ -818,7 +818,7 @@
 
 	  If you said M to "PSS support" above, you may enable or disable this
 	  PSS mixer with the module parameter pss_mixer. For more information
-	  see the file <file:Documentation/sound/PSS>.
+	  see the file <file:Documentation/sound/oss/PSS>.
 
 config PSS_HAVE_BOOT
 	bool "Have DSPxxx.LD firmware file"
@@ -845,16 +845,16 @@
 	  SM Games). For an unknown card you may answer Y if the card claims
 	  to be Sound Blaster-compatible.
 
-	  Please read the file <file:Documentation/sound/Soundblaster>.
+	  Please read the file <file:Documentation/sound/oss/Soundblaster>.
 
 	  You should also say Y here for cards based on the Avance Logic
-	  ALS-007 and ALS-1X0 chips (read <file:Documentation/sound/ALS>) and
+	  ALS-007 and ALS-1X0 chips (read <file:Documentation/sound/oss/ALS>) and
 	  for cards based on ESS chips (read
-	  <file:Documentation/sound/ESS1868> and
-	  <file:Documentation/sound/ESS>). If you have an SB AWE 32 or SB AWE
+	  <file:Documentation/sound/oss/ESS1868> and
+	  <file:Documentation/sound/oss/ESS>). If you have an SB AWE 32 or SB AWE
 	  64, say Y here and also to "AWE32 synth" below and read
-	  <file:Documentation/sound/INSTALL.awe>. If you have an IBM Mwave
-	  card, say Y here and read <file:Documentation/sound/mwave>.
+	  <file:Documentation/sound/oss/INSTALL.awe>. If you have an IBM Mwave
+	  card, say Y here and read <file:Documentation/sound/oss/mwave>.
 
 	  If you compile the driver into the kernel and don't want to use
 	  isapnp, you have to add "sb=<io>,<irq>,<dma>,<dma2>" to the kernel
@@ -868,8 +868,8 @@
 	depends on SOUND_OSS
 	help
 	  Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
-	  similar sound card. See <file:Documentation/sound/README.awe>,
-	  <file:Documentation/sound/AWE32> and the Soundblaster-AWE
+	  similar sound card. See <file:Documentation/sound/oss/README.awe>,
+	  <file:Documentation/sound/oss/AWE32> and the Soundblaster-AWE
 	  mini-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>
 	  for more info.
 
@@ -878,8 +878,8 @@
 	depends on SOUND_OSS && m
 	help
 	  Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card
-	  and read the files <file:Documentation/sound/Wavefront> and
-	  <file:Documentation/sound/Tropez+>.
+	  and read the files <file:Documentation/sound/oss/Wavefront> and
+	  <file:Documentation/sound/oss/Tropez+>.
 
 config SOUND_MAUI
 	tristate "Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers"
@@ -916,7 +916,7 @@
 	  cards may have software (TSR) FM emulation. Enabling FM support with
 	  these cards may cause trouble (I don't currently know of any such
 	  cards, however). Please read the file
-	  <file:Documentation/sound/OPL3> if your card has an OPL3 chip.
+	  <file:Documentation/sound/oss/OPL3> if your card has an OPL3 chip.
 
 	  If you compile the driver into the kernel, you have to add
 	  "opl3=<io>" to the kernel command line.
@@ -929,7 +929,7 @@
 	help
 	  Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
 	  usually built into motherboards. Read
-	  <file:Documentation/sound/OPL3-SA> for details.
+	  <file:Documentation/sound/oss/OPL3-SA> for details.
 
 	  If you compile the driver into the kernel, you have to add
 	  "opl3sa=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
@@ -941,7 +941,7 @@
 	help
 	  Say Y or M if you have a card based on one of these Yamaha sound
 	  chipsets or the "SAx", which is actually a SA3. Read
-	  <file:Documentation/sound/OPL3-SA2> for more information on
+	  <file:Documentation/sound/oss/OPL3-SA2> for more information on
 	  configuring these cards.
 
 	  If you compile the driver into the kernel and do not also
@@ -989,9 +989,9 @@
 	  accordingly. You should say Y to one and only one of these two
 	  questions.
 
-	  Read the <file:Documentation/sound/README.OSS> file and the head of
+	  Read the <file:Documentation/sound/oss/README.OSS> file and the head of
 	  <file:drivers/sound/aedsp16.c> as well as
-	  <file:Documentation/sound/AudioExcelDSP16> to get more information
+	  <file:Documentation/sound/oss/AudioExcelDSP16> to get more information
 	  about this driver and its configuration.
 
 config SC6600
diff -Nru a/sound/oss/Makefile b/sound/oss/Makefile
--- a/sound/oss/Makefile	Wed Nov 27 14:36:28 2002
+++ b/sound/oss/Makefile	Wed Nov 27 14:36:28 2002
@@ -69,7 +69,7 @@
 obj-$(CONFIG_SOUND_EMU10K1)	+= ac97_codec.o
 obj-$(CONFIG_SOUND_RME96XX)     += rme96xx.o
 obj-$(CONFIG_SOUND_BT878)	+= btaudio.o
-obj-$(CONFIG_SOUND_EMU10K1)	+= ac97_codec.o
+obj-$(CONFIG_SOUND_IT8172)	+= ite8172.o ac97_codec.o
 
 ifeq ($(CONFIG_MIDI_EMU10K1),y)
   obj-$(CONFIG_SOUND_EMU10K1)	+= sound.o
diff -Nru a/sound/oss/cmpci.c b/sound/oss/cmpci.c
--- a/sound/oss/cmpci.c	Wed Nov 27 14:36:30 2002
+++ b/sound/oss/cmpci.c	Wed Nov 27 14:36:30 2002
@@ -2034,7 +2034,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
@@ -2053,7 +2053,7 @@
 				s->dma_adc.count &= s->dma_adc.fragsize-1;
 		}
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
diff -Nru a/sound/oss/cs4232.c b/sound/oss/cs4232.c
--- a/sound/oss/cs4232.c	Wed Nov 27 14:36:30 2002
+++ b/sound/oss/cs4232.c	Wed Nov 27 14:36:30 2002
@@ -382,10 +382,11 @@
 	isapnpcfg->io_base	= dev->resource[0].start;
 	if (probe_cs4232(isapnpcfg,TRUE) == 0) {
 		printk(KERN_ERR "cs4232: ISA PnP card found, but not detected?\n");
+		kfree(isapnpcfg);
 		return -ENODEV;
 	}
 	attach_cs4232(isapnpcfg);
-	dev->driver_data = isapnpcfg;
+	pci_set_drvdata(dev,isapnpcfg);
 	return 0;
 }
 
diff -Nru a/sound/oss/es1370.c b/sound/oss/es1370.c
--- a/sound/oss/es1370.c	Wed Nov 27 14:36:32 2002
+++ b/sound/oss/es1370.c	Wed Nov 27 14:36:32 2002
@@ -1632,7 +1632,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
@@ -1652,7 +1652,7 @@
 		if (s->dma_dac2.mapped)
 			s->dma_dac2.count &= s->dma_dac2.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
@@ -2113,7 +2113,7 @@
 		if (s->dma_dac1.mapped)
 			s->dma_dac1.count &= s->dma_dac1.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
diff -Nru a/sound/oss/es1371.c b/sound/oss/es1371.c
--- a/sound/oss/es1371.c	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/es1371.c	Wed Nov 27 14:36:31 2002
@@ -1820,7 +1820,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
@@ -1840,9 +1840,10 @@
 		if (s->dma_dac2.mapped)
 			s->dma_dac2.count &= s->dma_dac2.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
+
         case SNDCTL_DSP_GETBLKSIZE:
 		if (file->f_mode & FMODE_WRITE) {
 			if ((val = prog_dmabuf_dac2(s)))
@@ -2291,7 +2292,7 @@
 		if (s->dma_dac1.mapped)
 			s->dma_dac1.count &= s->dma_dac1.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
diff -Nru a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
--- a/sound/oss/esssolo1.c	Wed Nov 27 14:36:28 2002
+++ b/sound/oss/esssolo1.c	Wed Nov 27 14:36:28 2002
@@ -1469,7 +1469,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
@@ -1495,7 +1495,7 @@
 		       cinfo.bytes, cinfo.blocks, cinfo.ptr, s->dma_dac.buforder, s->dma_dac.numfrag, s->dma_dac.fragshift,
 		       s->dma_dac.swptr, s->dma_dac.count, s->dma_dac.fragsize, s->dma_dac.dmasize, s->dma_dac.fragsamples);
 #endif
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
diff -Nru a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
--- a/sound/oss/i810_audio.c	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/i810_audio.c	Wed Nov 27 14:36:31 2002
@@ -101,6 +101,9 @@
 #ifndef PCI_DEVICE_ID_INTEL_ICH3
 #define PCI_DEVICE_ID_INTEL_ICH3	0x2485
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH4
+#define PCI_DEVICE_ID_INTEL_ICH4	0x24c5
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_440MX
 #define PCI_DEVICE_ID_INTEL_440MX	0x7195
 #endif
@@ -110,6 +113,9 @@
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO	0x01b1
 #endif
+#ifndef PCI_DEVICE_ID_AMD_768_AUDIO
+#define PCI_DEVICE_ID_AMD_768_AUDIO	0x7445
+#endif
 
 static int ftsodell=0;
 static int strict_clocking=0;
@@ -230,8 +236,11 @@
 	INTEL440MX,
 	INTELICH2,
 	INTELICH3,
+	INTELICH4,
 	SI7012,
-	NVIDIA_NFORCE
+	NVIDIA_NFORCE,
+	AMD768,
+	AMD8111
 };
 
 static char * card_names[] = {
@@ -240,8 +249,11 @@
 	"Intel 440MX",
 	"Intel ICH2",
 	"Intel ICH3",
+	"Intel ICH4",
 	"SiS 7012",
-	"NVIDIA nForce Audio"
+	"NVIDIA nForce Audio",
+	"AMD 768",
+	"AMD-8111 IOHub"
 };
 
 static struct pci_device_id i810_pci_tbl [] __initdata = {
@@ -255,10 +267,16 @@
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2},
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH3,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH4,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012},
 	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_768_AUDIO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111},
 	{0,}
 };
 
@@ -2090,14 +2108,14 @@
 #if defined(DEBUG) || defined(DEBUG_MMAP)
 		printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val);
 #endif
-		if( !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) {
+		if((file->f_mode & FMODE_READ) && !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) {
 			stop_adc(state);
 		}
-		if( !(val & PCM_ENABLE_OUTPUT) && dmabuf->enable == DAC_RUNNING) {
+		if((file->f_mode & FMODE_WRITE) && !(val & PCM_ENABLE_OUTPUT) && dmabuf->enable == DAC_RUNNING) {
 			stop_dac(state);
 		}
 		dmabuf->trigger = val;
-		if(val & PCM_ENABLE_OUTPUT && !(dmabuf->enable & DAC_RUNNING)) {
+		if((file->f_mode & FMODE_WRITE) && (val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
 			if (!dmabuf->write_channel) {
 				dmabuf->ready = 0;
 				dmabuf->write_channel = state->card->alloc_pcm_channel(state->card);
@@ -2118,7 +2136,7 @@
 			} else
 				start_dac(state);
 		}
-		if(val & PCM_ENABLE_INPUT && !(dmabuf->enable & ADC_RUNNING)) {
+		if((file->f_mode & FMODE_READ) && (val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
 			if (!dmabuf->read_channel) {
 				dmabuf->ready = 0;
 				dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card);
@@ -2686,6 +2704,14 @@
 			break;
 		}
 		
+		codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L);
+		if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID))
+		{
+			printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", num_ac97);
+			kfree(codec);
+			continue;
+		}
+	
 		card->ac97_features = eid;
 				
 		/* Now check the codec for useful features to make up for
@@ -3134,6 +3160,7 @@
 
 	printk(KERN_INFO "Intel 810 + AC97 Audio, version "
 	       DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
+	printk(KERN_WARNING "This driver is deprecated, please use the ALSA drivers.\n");
 
 	if (!pci_register_driver(&i810_pci_driver)) {
 		pci_unregister_driver(&i810_pci_driver);
diff -Nru a/sound/oss/maestro.c b/sound/oss/maestro.c
--- a/sound/oss/maestro.c	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/maestro.c	Wed Nov 27 14:36:31 2002
@@ -2760,7 +2760,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
@@ -2777,7 +2777,7 @@
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
diff -Nru a/sound/oss/maestro3.c b/sound/oss/maestro3.c
--- a/sound/oss/maestro3.c	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/maestro3.c	Wed Nov 27 14:36:31 2002
@@ -1815,7 +1815,7 @@
         if (s->dma_adc.mapped)
             s->dma_adc.count &= s->dma_adc.fragsize-1;
         spin_unlock_irqrestore(&card->lock, flags);
-        if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+	if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 		return -EFAULT;
 	return 0;
 
@@ -1830,7 +1830,7 @@
         if (s->dma_dac.mapped)
             s->dma_dac.count &= s->dma_dac.fragsize-1;
         spin_unlock_irqrestore(&card->lock, flags);
-        if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+	if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 		return -EFAULT;
 	return 0;
 
diff -Nru a/sound/oss/mpu401.c b/sound/oss/mpu401.c
--- a/sound/oss/mpu401.c	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/mpu401.c	Wed Nov 27 14:36:31 2002
@@ -15,6 +15,7 @@
  * Alan Cox		modularisation, use normal request_irq, use dev_id
  * Bartlomiej Zolnierkiewicz	removed some __init to allow using many drivers
  * Chris Rankin		Update the module-usage counter for the coprocessor
+ * Zwane Mwaikambo	Changed attach/unload resource freeing
  */
 
 #include <linux/module.h>
@@ -79,7 +80,7 @@
 
 static void mpu401_close(int dev);
 
-static int mpu401_status(struct mpu_config *devc)
+static inline int mpu401_status(struct mpu_config *devc)
 {
 	return inb(STATPORT(devc->base));
 }
@@ -87,17 +88,17 @@
 #define input_avail(devc)		(!(mpu401_status(devc)&INPUT_AVAIL))
 #define output_ready(devc)		(!(mpu401_status(devc)&OUTPUT_READY))
 
-static void write_command(struct mpu_config *devc, unsigned char cmd)
+static inline void write_command(struct mpu_config *devc, unsigned char cmd)
 {
 	outb(cmd, COMDPORT(devc->base));
 }
 
-static int read_data(struct mpu_config *devc)
+static inline int read_data(struct mpu_config *devc)
 {
 	return inb(DATAPORT(devc->base));
 }
 
-static void write_data(struct mpu_config *devc, unsigned char byte)
+static inline void write_data(struct mpu_config *devc, unsigned char byte)
 {
 	outb(byte, DATAPORT(devc->base));
 }
@@ -962,12 +963,12 @@
 	spin_unlock_irqrestore(&devc->lock,flags);
 }
 
-void attach_mpu401(struct address_info *hw_config, struct module *owner)
+int attach_mpu401(struct address_info *hw_config, struct module *owner)
 {
 	unsigned long flags;
 	char revision_char;
 
-	int m;
+	int m, ret;
 	struct mpu_config *devc;
 
 	hw_config->slots[1] = -1;
@@ -975,7 +976,8 @@
 	if (m == -1)
 	{
 		printk(KERN_WARNING "MPU-401: Too many midi devices detected\n");
-		return;
+		ret = -ENOMEM;
+		goto out_err;
 	}
 	devc = &dev_conf[m];
 	devc->base = hw_config->io_base;
@@ -1006,16 +1008,16 @@
 		if (!reset_mpu401(devc))
 		{
 			printk(KERN_WARNING "mpu401: Device didn't respond\n");
-			sound_unload_mididev(m);
-			return;
+			ret = -ENODEV;
+			goto out_mididev;
 		}
 		if (!devc->shared_irq)
 		{
 			if (request_irq(devc->irq, mpuintr, 0, "mpu401", (void *)m) < 0)
 			{
 				printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq);
-				sound_unload_mididev(m);
-				return;
+				ret = -ENOMEM;
+				goto out_mididev;
 			}
 		}
 		spin_lock_irqsave(&devc->lock,flags);
@@ -1024,7 +1026,12 @@
 			mpu401_chk_version(m, devc);
 			spin_unlock_irqrestore(&devc->lock,flags);
 	}
-	request_region(hw_config->io_base, 2, "mpu401");
+
+	if (!request_region(hw_config->io_base, 2, "mpu401"))
+	{
+		ret = -ENOMEM;
+		goto out_irq;
+	}	
 
 	if (devc->version != 0)
 		if (mpu_cmd(m, 0xC5, 0) >= 0)	/* Set timebase OK */
@@ -1036,9 +1043,9 @@
 
 	if (mpu401_synth_operations[m] == NULL)
 	{
-		sound_unload_mididev(m);
 		printk(KERN_ERR "mpu401: Can't allocate memory\n");
-		return;
+		ret = -ENOMEM;
+		goto out_resource;
 	}
 	if (!(devc->capabilities & MPU_CAP_INTLG))	/* No intelligent mode */
 	{
@@ -1117,6 +1124,17 @@
 
 	hw_config->slots[1] = m;
 	sequencer_init();
+	
+	return 0;
+
+out_resource:
+	release_region(hw_config->io_base, 2);
+out_irq:
+	free_irq(devc->irq, (void *)m);
+out_mididev:
+	sound_unload_mididev(m);
+out_err:
+	return ret;
 }
 
 static int reset_mpu401(struct mpu_config *devc)
@@ -1227,15 +1245,17 @@
 {
 	void *p;
 	int n=hw_config->slots[1];
-	
-	release_region(hw_config->io_base, 2);
-	if (hw_config->always_detect == 0 && hw_config->irq > 0)
-		free_irq(hw_config->irq, (void *)n);
-	p=mpu401_synth_operations[n];
-	sound_unload_mididev(n);
-	sound_unload_timerdev(hw_config->slots[2]);
-	if(p)
-		kfree(p);
+		
+	if (n != -1) {
+		release_region(hw_config->io_base, 2);
+		if (hw_config->always_detect == 0 && hw_config->irq > 0)
+			free_irq(hw_config->irq, (void *)n);
+		p=mpu401_synth_operations[n];
+		sound_unload_mididev(n);
+		sound_unload_timerdev(hw_config->slots[2]);
+		if(p)
+			kfree(p);
+	}
 }
 
 /*****************************************************
@@ -1752,6 +1772,7 @@
 
 int __init init_mpu401(void)
 {
+	int ret;
 	/* Can be loaded either for module use or to provide functions
 	   to others */
 	if (io != -1 && irq != -1) {
@@ -1759,7 +1780,8 @@
 		cfg.io_base = io;
 		if (probe_mpu401(&cfg) == 0)
 			return -ENODEV;
-		attach_mpu401(&cfg, THIS_MODULE);
+		if ((ret = attach_mpu401(&cfg, THIS_MODULE)))
+			return ret;
 	}
 	
 	return 0;
diff -Nru a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
--- a/sound/oss/nm256_audio.c	Wed Nov 27 14:36:30 2002
+++ b/sound/oss/nm256_audio.c	Wed Nov 27 14:36:30 2002
@@ -895,7 +895,7 @@
 
     /* Reset the mixer.  'Tis magic!  */
     nm256_writePort8 (card, 2, 0x6c0, 1);
-    nm256_writePort8 (card, 2, 0x6cc, 0x87);
+//  nm256_writePort8 (card, 2, 0x6cc, 0x87);	/* This crashes Dell latitudes */
     nm256_writePort8 (card, 2, 0x6cc, 0x80);
     nm256_writePort8 (card, 2, 0x6cc, 0x0);
 
diff -Nru a/sound/oss/pss.c b/sound/oss/pss.c
--- a/sound/oss/pss.c	Wed Nov 27 14:36:32 2002
+++ b/sound/oss/pss.c	Wed Nov 27 14:36:32 2002
@@ -1127,7 +1127,7 @@
 MODULE_PARM(pss_mixer, "b");
 MODULE_PARM_DESC(pss_mixer, "Enable (1) or disable (0) PSS mixer (controlling of output volume, bass, treble, synth volume). The mixer is not available on all PSS cards.");
 MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl");
-MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards).\n");
+MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards).");
 MODULE_LICENSE("GPL");
 
 
diff -Nru a/sound/oss/sb_audio.c b/sound/oss/sb_audio.c
--- a/sound/oss/sb_audio.c	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/sb_audio.c	Wed Nov 27 14:36:31 2002
@@ -602,8 +602,8 @@
 
 	if (speed > 0)
 	{
-		if (speed < 5000)	/* which of these */
-			speed = 4000;	/* is correct ??? */
+		if (speed < 5000)
+			speed = 5000;
 
 		if (speed > max_speed)
 			speed = max_speed;
diff -Nru a/sound/oss/sb_card.c b/sound/oss/sb_card.c
--- a/sound/oss/sb_card.c	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/sb_card.c	Wed Nov 27 14:36:31 2002
@@ -373,7 +373,7 @@
 		0,0,0,0,
 		0,1,1,-1},
 	{"Sound Blaster AWE 32",
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0047),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0046),
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 		0,0,0,0,
 		0,1,1,-1},
diff -Nru a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
--- a/sound/oss/sonicvibes.c	Wed Nov 27 14:36:30 2002
+++ b/sound/oss/sonicvibes.c	Wed Nov 27 14:36:30 2002
@@ -1803,7 +1803,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+		if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
 			return -EFAULT;
 		return 0;
 
diff -Nru a/sound/oss/vidc_fill.S b/sound/oss/vidc_fill.S
--- a/sound/oss/vidc_fill.S	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/vidc_fill.S	Wed Nov 27 14:36:31 2002
@@ -9,7 +9,6 @@
  *
  *  Filler routines for DMA buffers
  */
-#define __ASSEMBLY__
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/hardware.h>
diff -Nru a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c
--- a/sound/oss/ymfpci.c	Wed Nov 27 14:36:31 2002
+++ b/sound/oss/ymfpci.c	Wed Nov 27 14:36:31 2002
@@ -2653,7 +2653,7 @@
 	name:		"ymfpci",
 	id_table:	ymf_id_tbl,
 	probe:		ymf_probe_one,
-	remove:         __devexit_p(ymf_remove_one),
+	remove:		__devexit_p(ymf_remove_one),
 	suspend:	ymf_suspend,
 	resume:		ymf_resume
 };
diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c
--- a/sound/pci/cs4281.c	Wed Nov 27 14:36:32 2002
+++ b/sound/pci/cs4281.c	Wed Nov 27 14:36:32 2002
@@ -2109,7 +2109,7 @@
 	snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_CHGM);
 
 	/* remember the status registers */
-	for (i = 0; number_of(saved_regs); i++)
+	for (i = 0; i < number_of(saved_regs); i++)
 		if (saved_regs[i])
 			chip->suspend_regs[i] = snd_cs4281_peekBA0(chip, saved_regs[i]);
 
@@ -2153,7 +2153,7 @@
 	snd_cs4281_chip_init(chip, 0);
 
 	/* restore the status registers */
-	for (i = 0; number_of(saved_regs); i++)
+	for (i = 0; i < number_of(saved_regs); i++)
 		if (saved_regs[i])
 			snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]);
 
diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
--- a/sound/pci/cs46xx/cs46xx_lib.c	Wed Nov 27 14:36:27 2002
+++ b/sound/pci/cs46xx/cs46xx_lib.c	Wed Nov 27 14:36:27 2002
@@ -1027,6 +1027,7 @@
 	return result;
 }
 
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
 static int _cs46xx_adjust_sample_rate (cs46xx_t *chip, cs46xx_pcm_t *cpcm,
 				       int sample_rate) 
 {
@@ -1055,7 +1056,6 @@
 									 cpcm->hw_addr,
 									 cpcm->pcm_channel->pcm_channel_id)) == NULL) {
 			snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");
-			up (&chip->spos_mutex);
 			return -ENXIO;
 		}
 
@@ -1065,6 +1065,8 @@
 
 	return 0;
 }
+#endif
+
 static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
 					 snd_pcm_hw_params_t * hw_params)
 {
@@ -1087,6 +1089,7 @@
 	if (cpcm->pcm_channel->pcm_channel_id != DSP_IEC958_CHANNEL ||
 	    !(chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_AC3_MODE)) {
 		if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) {
+			up (&chip->spos_mutex);
 			return -ENXIO;
 		}
 	}
