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

diff -urN linux-2.5.64-bk3/Documentation/basic_profiling.txt linux-2.5.64-bk4/Documentation/basic_profiling.txt
--- linux-2.5.64-bk3/Documentation/basic_profiling.txt	Wed Dec 31 16:00:00 1969
+++ linux-2.5.64-bk4/Documentation/basic_profiling.txt	Mon Mar 31 12:25:43 2003
@@ -0,0 +1,48 @@
+These instructions are deliberately very basic. If you want something clever,
+go read the real docs ;-) Please don't add more stuff, but feel free to 
+correct my mistakes ;-)    (mbligh@aracnet.com)
+Thanks to John Levon, Dave Hansen, et al. for help writing this.
+
+<test> is the thing you're trying to measure.
+Make sure you have the correct System.map / vmlinux referenced!
+IMHO it's easier to use "make install" for linux and hack /sbin/installkernel
+to copy config files, system.map, vmlinux to /boot.
+
+Readprofile
+-----------
+You need a fixed readprofile command for 2.5 ... either get hold of
+a current version from:
+http://www.kernel.org/pub/linux/utils/util-linux/
+or get readprofile binary fixed for 2.5 / akpm's 2.5 patch from 
+ftp://ftp.kernel.org/pub/linux/kernel/people/mbligh/tools/readprofile/
+
+Add "profile=2" to the kernel command line.
+
+clear		readprofile -r
+		<test>
+dump output	readprofile -m /boot/System.map > captured_profile
+
+Oprofile
+--------
+get source (I use 0.5) from http://oprofile.sourceforge.net/
+add "idle=poll" to the kernel command line 
+Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
+./configure --with-kernel-support
+make install
+
+One time setup (pick appropriate one for your CPU):
+P3		opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=CPU_CLK_UNHALTED --ctr0-count=100000
+Athlon/x86-64	opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=RETIRED_INSNS --ctr0-count=100000
+P4		opcontrol --setup --vmlinux=/boot/vmlinux \
+		--ctr0-event=GLOBAL_POWER_EVENTS \
+		--ctr0-unit-mask=1 --ctr0-count=100000
+
+start daemon	opcontrol --start-daemon
+clear		opcontrol --reset
+start		opcontrol --start
+		<test>
+stop		opcontrol --stop
+dump output	oprofpp -dl -i /boot/vmlinux  >  output_file
+
diff -urN linux-2.5.64-bk3/Documentation/cdrom/cdrom-standard.tex linux-2.5.64-bk4/Documentation/cdrom/cdrom-standard.tex
--- linux-2.5.64-bk3/Documentation/cdrom/cdrom-standard.tex	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/Documentation/cdrom/cdrom-standard.tex	Mon Mar 31 12:25:43 2003
@@ -758,11 +758,8 @@
 \subsection{$Struct\ file_operations\ cdrom_fops$}
 
 The contents of this structure were described in section~\ref{cdrom.c}.
-As already stated, this structure should be used to register block
-devices with the kernel:
-$$
-register_blkdev(major, <name>, \&cdrom_fops);
-$$
+A pointer to this structure is assigned to the $fops$ field
+of the $struct gendisk$.
 
 \subsection{$Int\ register_cdrom( struct\ cdrom_device_info\ * cdi)$}
 
diff -urN linux-2.5.64-bk3/Makefile linux-2.5.64-bk4/Makefile
--- linux-2.5.64-bk3/Makefile	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/Makefile	Mon Mar 31 12:25:43 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 64
-EXTRAVERSION = bk3
+EXTRAVERSION = bk4
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.64-bk3/arch/alpha/Kconfig linux-2.5.64-bk4/arch/alpha/Kconfig
--- linux-2.5.64-bk3/arch/alpha/Kconfig	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/arch/alpha/Kconfig	Mon Mar 31 12:25:43 2003
@@ -15,10 +15,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 
diff -urN linux-2.5.64-bk3/arch/alpha/kernel/irq.c linux-2.5.64-bk4/arch/alpha/kernel/irq.c
--- linux-2.5.64-bk3/arch/alpha/kernel/irq.c	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/arch/alpha/kernel/irq.c	Mon Mar 31 12:25:43 2003
@@ -515,6 +515,7 @@
 #endif
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 #ifdef CONFIG_SMP
 	seq_puts(p, "           ");
@@ -525,9 +526,10 @@
 #endif
 
 	for (i = 0; i < ACTUAL_NR_IRQS; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -538,15 +540,18 @@
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %c%s",
-			     (action->flags & SA_INTERRUPT)?'+':' ',
-			     action->name);
+			(action->flags & SA_INTERRUPT)?'+':' ',
+			action->name);
 
 		for (action=action->next; action; action = action->next) {
 			seq_printf(p, ", %c%s",
-				     (action->flags & SA_INTERRUPT)?'+':' ',
-				     action->name);
+				  (action->flags & SA_INTERRUPT)?'+':' ',
+				   action->name);
 		}
+
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 #if CONFIG_SMP
 	seq_puts(p, "IPI: ");
diff -urN linux-2.5.64-bk3/arch/arm/Kconfig linux-2.5.64-bk4/arch/arm/Kconfig
--- linux-2.5.64-bk3/arch/arm/Kconfig	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/arch/arm/Kconfig	Mon Mar 31 12:25:43 2003
@@ -20,10 +20,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config EISA
 	bool
 	---help---
diff -urN linux-2.5.64-bk3/arch/arm/kernel/irq.c linux-2.5.64-bk4/arch/arm/kernel/irq.c
--- linux-2.5.64-bk3/arch/arm/kernel/irq.c	Tue Mar  4 19:28:52 2003
+++ linux-2.5.64-bk4/arch/arm/kernel/irq.c	Mon Mar 31 12:25:43 2003
@@ -165,17 +165,22 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_controller_lock, flags);
 	    	action = irq_desc[i].action;
 		if (!action)
-			continue;
+			goto unlock;
+
 		seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
 		seq_printf(p, "  %s", action->name);
-		for (action = action->next; action; action = action->next) {
+		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
-		}
+
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_controller_lock, flags);
 	}
 
 #ifdef CONFIG_ARCH_ACORN
diff -urN linux-2.5.64-bk3/arch/cris/Kconfig linux-2.5.64-bk4/arch/cris/Kconfig
--- linux-2.5.64-bk3/arch/cris/Kconfig	Tue Mar  4 19:29:36 2003
+++ linux-2.5.64-bk4/arch/cris/Kconfig	Mon Mar 31 12:25:43 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -urN linux-2.5.64-bk3/arch/cris/kernel/irq.c linux-2.5.64-bk4/arch/cris/kernel/irq.c
--- linux-2.5.64-bk3/arch/cris/kernel/irq.c	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/arch/cris/kernel/irq.c	Mon Mar 31 12:25:43 2003
@@ -228,11 +228,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0; i < NR_IRQS; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %10u %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -243,6 +245,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/i386/Kconfig linux-2.5.64-bk4/arch/i386/Kconfig
--- linux-2.5.64-bk3/arch/i386/Kconfig	Tue Mar  4 19:29:00 2003
+++ linux-2.5.64-bk4/arch/i386/Kconfig	Mon Mar 31 12:25:44 2003
@@ -18,15 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool "Support for paging of anonymous memory"
-	default y
-	help
-	  This option allows you to choose whether you want to have support
-	  for socalled swap devices or swap files in your kernel that are
-	  used to provide more virtual memory than the actual RAM present
-	  in your computer.  If unusre say Y.
-
 config SBUS
 	bool
 
@@ -488,7 +479,7 @@
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation Support"
-	depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)))
+	depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) || X86_PC
 
 config DISCONTIGMEM
 	bool
diff -urN linux-2.5.64-bk3/arch/i386/kernel/i386_ksyms.c linux-2.5.64-bk4/arch/i386/kernel/i386_ksyms.c
--- linux-2.5.64-bk3/arch/i386/kernel/i386_ksyms.c	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/arch/i386/kernel/i386_ksyms.c	Mon Mar 31 12:25:44 2003
@@ -68,6 +68,7 @@
 EXPORT_SYMBOL(MCA_bus);
 #ifdef CONFIG_DISCONTIGMEM
 EXPORT_SYMBOL(node_data);
+EXPORT_SYMBOL(physnode_map);
 #endif
 #ifdef CONFIG_X86_NUMAQ
 EXPORT_SYMBOL(xquad_portio);
diff -urN linux-2.5.64-bk3/arch/i386/kernel/io_apic.c linux-2.5.64-bk4/arch/i386/kernel/io_apic.c
--- linux-2.5.64-bk3/arch/i386/kernel/io_apic.c	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/arch/i386/kernel/io_apic.c	Mon Mar 31 12:25:44 2003
@@ -1167,11 +1167,8 @@
 	enable_8259A_irq(0);
 }
 
-void __init UNEXPECTED_IO_APIC(void)
+static inline void UNEXPECTED_IO_APIC(void)
 {
-	printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n");
-	printk(KERN_WARNING "      http://bugzilla.kernel.org\n");
-	printk(KERN_WARNING "      if your kernel is less than 3 months old.\n");
 }
 
 void __init print_IO_APIC(void)
diff -urN linux-2.5.64-bk3/arch/i386/kernel/irq.c linux-2.5.64-bk4/arch/i386/kernel/irq.c
--- linux-2.5.64-bk3/arch/i386/kernel/irq.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/arch/i386/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -135,43 +135,47 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "CPU%d       ",j);
+			seq_printf(p, "CPU%d       ",j);
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < NR_CPUS; j++)
 			if (cpu_online(j))
-				p += seq_printf(p, "%10u ",
-					     kstat_cpu(j).irqs[i]);
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
+
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "%10u ", nmi_count(j));
+			seq_printf(p, "%10u ", nmi_count(j));
 	seq_putc(p, '\n');
 #if CONFIG_X86_LOCAL_APIC
 	seq_printf(p, "LOC: ");
 	for (j = 0; j < NR_CPUS; j++)
 		if (cpu_online(j))
-			p += seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
+			seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
 	seq_putc(p, '\n');
 #endif
 	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
diff -urN linux-2.5.64-bk3/arch/i386/kernel/numaq.c linux-2.5.64-bk4/arch/i386/kernel/numaq.c
--- linux-2.5.64-bk3/arch/i386/kernel/numaq.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/arch/i386/kernel/numaq.c	Mon Mar 31 12:25:44 2003
@@ -31,8 +31,7 @@
 #include <asm/numaq.h>
 
 /* These are needed before the pgdat's are created */
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+extern long node_start_pfn[], node_end_pfn[];
 
 #define	MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
 
@@ -66,26 +65,6 @@
 }
 
 /*
- * -----------------------------------------
- *
- * functions related to physnode_map
- *
- * -----------------------------------------
- */
-/*
- * physnode_map keeps track of the physical memory layout of the
- * numaq nodes on a 256Mb break (each element of the array will
- * represent 256Mb of memory and will be marked by the node id.  so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- * physnode_map[0-3] = 0;
- * physnode_map[4-7] = 1;
- * physnode_map[8- ] = -1;
- */
-int physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(physnode_map);
-
-/*
  * for each node mark the regions
  *        TOPOFMEM = hi_shrd_mem_start + hi_shrd_mem_size
  *
diff -urN linux-2.5.64-bk3/arch/i386/kernel/smpboot.c linux-2.5.64-bk4/arch/i386/kernel/smpboot.c
--- linux-2.5.64-bk3/arch/i386/kernel/smpboot.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/arch/i386/kernel/smpboot.c	Mon Mar 31 12:25:44 2003
@@ -966,6 +966,7 @@
 		if (APIC_init_uniprocessor())
 			printk(KERN_NOTICE "Local APIC not detected."
 					   " Using dummy APIC emulation.\n");
+		map_cpu_to_logical_apicid();
 		return;
 	}
 
diff -urN linux-2.5.64-bk3/arch/i386/kernel/srat.c linux-2.5.64-bk4/arch/i386/kernel/srat.c
--- linux-2.5.64-bk3/arch/i386/kernel/srat.c	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/arch/i386/kernel/srat.c	Mon Mar 31 12:25:44 2003
@@ -57,8 +57,7 @@
 static int zholes_size_init;
 static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
 
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+extern unsigned long node_start_pfn[], node_end_pfn[];
 
 extern void * boot_ioremap(unsigned long, unsigned long);
 
@@ -182,30 +181,19 @@
 	}
 }
 
-/*
- * physnode_map keeps track of the physical memory layout of the
- * numaq nodes on a 256Mb break (each element of the array will
- * represent 256Mb of memory and will be marked by the node id.  so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- * physnode_map[0-3] = 0;
- * physnode_map[4-7] = 1;
- * physnode_map[8- ] = -1;
- */
-int pfnnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(pfnnode_map);
-
-static void __init initialize_pfnnode_map(void)
+static void __init initialize_physnode_map(void)
 {
-	unsigned long topofchunk, cur = 0;
 	int i;
-	
-	for (i = 0; i < num_memory_chunks; i++) {
-		cur = node_memory_chunk[i].start_pfn;
-		topofchunk = node_memory_chunk[i].end_pfn;
-		while (cur < topofchunk) {
-			pfnnode_map[PFN_TO_ELEMENT(cur)] = node_memory_chunk[i].nid;
-			cur ++;
+	unsigned long pfn;
+	struct node_memory_chunk_s *nmcp;
+
+	/* Run the list of memory chunks and fill in the phymap. */
+	nmcp = node_memory_chunk;
+	for (i = num_memory_chunks; --i >= 0; nmcp++) {
+		for (pfn = nmcp->start_pfn; pfn <= nmcp->end_pfn;
+						pfn += PAGES_PER_ELEMENT)
+		{
+			physnode_map[pfn / PAGES_PER_ELEMENT] = (int)nmcp->nid;
 		}
 	}
 }
@@ -272,7 +260,7 @@
 	for (i = 0; i < num_memory_chunks; i++)
 		node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm];
 
-	initialize_pfnnode_map();
+	initialize_physnode_map();
 	
 	printk("pxm bitmap: ");
 	for (i = 0; i < sizeof(pxm_bitmap); i++) {
diff -urN linux-2.5.64-bk3/arch/i386/mm/discontig.c linux-2.5.64-bk4/arch/i386/mm/discontig.c
--- linux-2.5.64-bk3/arch/i386/mm/discontig.c	Tue Mar  4 19:29:21 2003
+++ linux-2.5.64-bk4/arch/i386/mm/discontig.c	Mon Mar 31 12:25:44 2003
@@ -36,11 +36,36 @@
 struct pglist_data *node_data[MAX_NUMNODES];
 bootmem_data_t node0_bdata;
 
+/*
+ * numa interface - we expect the numa architecture specfic code to have
+ *                  populated the following initialisation.
+ *
+ * 1) numnodes         - the total number of nodes configured in the system
+ * 2) physnode_map     - the mapping between a pfn and owning node
+ * 3) node_start_pfn   - the starting page frame number for a node
+ * 3) node_end_pfn     - the ending page fram number for a node
+ */
+
+/*
+ * physnode_map keeps track of the physical memory layout of a generic
+ * numa node on a 256Mb break (each element of the array will
+ * represent 256Mb of memory and will be marked by the node id.  so,
+ * if the first gig is on node 0, and the second gig is on node 1
+ * physnode_map will contain:
+ *
+ *     physnode_map[0-3] = 0;
+ *     physnode_map[4-7] = 1;
+ *     physnode_map[8- ] = -1;
+ */
+u8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+
+unsigned long node_start_pfn[MAX_NUMNODES];
+unsigned long node_end_pfn[MAX_NUMNODES];
+
 extern unsigned long find_max_low_pfn(void);
 extern void find_max_pfn(void);
 extern void one_highpage_init(struct page *, int, int);
 
-extern unsigned long node_start_pfn[], node_end_pfn[];
 extern struct e820map e820;
 extern char _end;
 extern unsigned long highend_pfn, highstart_pfn;
@@ -57,6 +82,36 @@
 void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
 
 /*
+ * FLAT - support for basic PC memory model with discontig enabled, essentially
+ *        a single node with all available processors in it with a flat
+ *        memory map.
+ */
+void __init get_memcfg_numa_flat(void)
+{
+	int pfn;
+
+	printk("NUMA - single node, flat memory mode\n");
+
+	/* Run the memory configuration and find the top of memory. */
+	find_max_pfn();
+	node_start_pfn[0]  = 0;
+	node_end_pfn[0]	  = max_pfn;
+
+	/* Fill in the physnode_map with our simplistic memory model,
+	* all memory is in node 0.
+	*/
+	for (pfn = node_start_pfn[0]; pfn <= node_end_pfn[0];
+	       pfn += PAGES_PER_ELEMENT)
+	{
+		physnode_map[pfn / PAGES_PER_ELEMENT] = 0;
+	}
+
+         /* Indicate there is one node available. */
+	node_set_online(0);
+	numnodes = 1;
+}
+
+/*
  * Find the highest page frame number we have available for the node
  */
 static void __init find_max_pfn_node(int nid)
diff -urN linux-2.5.64-bk3/arch/ia64/Kconfig linux-2.5.64-bk4/arch/ia64/Kconfig
--- linux-2.5.64-bk3/arch/ia64/Kconfig	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/arch/ia64/Kconfig	Mon Mar 31 12:25:44 2003
@@ -22,10 +22,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default y
diff -urN linux-2.5.64-bk3/arch/ia64/kernel/irq.c linux-2.5.64-bk4/arch/ia64/kernel/irq.c
--- linux-2.5.64-bk3/arch/ia64/kernel/irq.c	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/arch/ia64/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -154,6 +154,7 @@
 	int i, j;
 	struct irqaction * action;
 	irq_desc_t *idesc;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -163,9 +164,10 @@
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		idesc = irq_desc(i);
+		spin_lock_irqsave(&idesc->lock, flags);
 		action = idesc->action;
 		if (!action)
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -176,10 +178,12 @@
 #endif
 		seq_printf(p, " %14s", idesc->handler->typename);
 		seq_printf(p, "  %s", action->name);
-
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
+		
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&idesc->lock, flags);
 	}
 	seq_puts(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
diff -urN linux-2.5.64-bk3/arch/m68k/Kconfig linux-2.5.64-bk4/arch/m68k/Kconfig
--- linux-2.5.64-bk3/arch/m68k/Kconfig	Tue Mar  4 19:29:23 2003
+++ linux-2.5.64-bk4/arch/m68k/Kconfig	Mon Mar 31 12:25:44 2003
@@ -10,10 +10,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -urN linux-2.5.64-bk3/arch/m68k/atari/stram.c linux-2.5.64-bk4/arch/m68k/atari/stram.c
--- linux-2.5.64-bk3/arch/m68k/atari/stram.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/arch/m68k/atari/stram.c	Mon Mar 31 12:25:44 2003
@@ -1052,8 +1052,7 @@
 	if (!stram_disk)
 		return -ENOMEM;
 
-	if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) {
-		printk(KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR);
+	if (register_blkdev(STRAM_MAJOR, "stram")) {
 		put_disk(stram_disk);
 		return -ENXIO;
 	}
diff -urN linux-2.5.64-bk3/arch/m68knommu/Kconfig linux-2.5.64-bk4/arch/m68knommu/Kconfig
--- linux-2.5.64-bk3/arch/m68knommu/Kconfig	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk4/arch/m68knommu/Kconfig	Mon Mar 31 12:25:44 2003
@@ -9,10 +9,6 @@
 	bool
 	default n
 
-config SWAP
-	bool
-	default n
-
 config FPU
 	bool
 	default n
diff -urN linux-2.5.64-bk3/arch/mips/Kconfig linux-2.5.64-bk4/arch/mips/Kconfig
--- linux-2.5.64-bk3/arch/mips/Kconfig	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/arch/mips/Kconfig	Mon Mar 31 12:25:44 2003
@@ -10,10 +10,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config SMP
 	bool
 	---help---
diff -urN linux-2.5.64-bk3/arch/mips/baget/irq.c linux-2.5.64-bk4/arch/mips/baget/irq.c
--- linux-2.5.64-bk3/arch/mips/baget/irq.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/arch/mips/baget/irq.c	Mon Mar 31 12:25:44 2003
@@ -146,11 +146,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < BAGET_IRQ_NR ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -161,6 +163,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/mips/dec/irq.c linux-2.5.64-bk4/arch/mips/dec/irq.c
--- linux-2.5.64-bk3/arch/mips/dec/irq.c	Tue Mar  4 19:29:22 2003
+++ linux-2.5.64-bk4/arch/mips/dec/irq.c	Mon Mar 31 12:25:44 2003
@@ -97,11 +97,13 @@
 {
 	int i;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < 32; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action)
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 				i, kstat_cpu(0).irqs[i],
 				(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -112,6 +114,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/mips/ite-boards/generic/irq.c linux-2.5.64-bk4/arch/mips/ite-boards/generic/irq.c
--- linux-2.5.64-bk3/arch/mips/ite-boards/generic/irq.c	Tue Mar  4 19:29:21 2003
+++ linux-2.5.64-bk4/arch/mips/ite-boards/generic/irq.c	Mon Mar 31 12:25:44 2003
@@ -222,6 +222,7 @@
 {
         int i, j;
         struct irqaction * action;
+	unsigned long flags;
 
         seq_printf(p, "           ");
         for (j=0; j<smp_num_cpus; j++)
@@ -229,20 +230,25 @@
 	seq_putc(p, '\n');
 
         for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
                 action = irq_desc[i].action;
+
                 if ( !action || !action->handler )
-                        continue;
+                        goto skip;
                 seq_printf(p, "%3d: ", i);		
                 seq_printf(p, "%10u ", kstat_irqs(i));
                 if ( irq_desc[i].handler )		
                         seq_printf(p, " %s ", irq_desc[i].handler->typename );
                 else
                         seq_puts(p, "  None      ");
+
                 seq_printf(p, "    %s",action->name);
                 for (action=action->next; action; action = action->next) {
                         seq_printf(p, ", %s", action->name);
                 }
                 seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
         }
         seq_printf(p, "BAD: %10lu\n", spurious_count);
         return 0;
@@ -437,6 +443,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &it8172_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 	/*
diff -urN linux-2.5.64-bk3/arch/mips/kernel/irq.c linux-2.5.64-bk4/arch/mips/kernel/irq.c
--- linux-2.5.64-bk3/arch/mips/kernel/irq.c	Tue Mar  4 19:28:59 2003
+++ linux-2.5.64-bk4/arch/mips/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -73,17 +73,19 @@
 int show_interrupts(struct seq_file *p, void *v)
 {
 	struct irqaction * action;
+	unsigned long flags;
 	int i;
-
+	
 	seq_puts(p, "           ");
 	for (i=0; i < 1 /*smp_num_cpus*/; i++)
 		seq_printf(p, "CPU%d       ", i);
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -92,6 +94,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
diff -urN linux-2.5.64-bk3/arch/mips/kernel/old-irq.c linux-2.5.64-bk4/arch/mips/kernel/old-irq.c
--- linux-2.5.64-bk3/arch/mips/kernel/old-irq.c	Tue Mar  4 19:29:20 2003
+++ linux-2.5.64-bk4/arch/mips/kernel/old-irq.c	Mon Mar 31 12:25:44 2003
@@ -128,11 +128,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < 32 ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -143,6 +145,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/mips/mips-boards/atlas/atlas_int.c linux-2.5.64-bk4/arch/mips/mips-boards/atlas/atlas_int.c
--- linux-2.5.64-bk3/arch/mips/mips-boards/atlas/atlas_int.c	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk4/arch/mips/mips-boards/atlas/atlas_int.c	Mon Mar 31 12:25:44 2003
@@ -99,11 +99,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < ATLASINT_END; i++, num++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -114,6 +116,8 @@
 				action->name);
 		}
 		seq_printf(p, " [hw0]\n");
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -243,6 +247,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &atlas_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 #ifdef CONFIG_REMOTE_DEBUG
diff -urN linux-2.5.64-bk3/arch/mips/philips/nino/irq.c linux-2.5.64-bk4/arch/mips/philips/nino/irq.c
--- linux-2.5.64-bk3/arch/mips/philips/nino/irq.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/arch/mips/philips/nino/irq.c	Mon Mar 31 12:25:44 2003
@@ -119,11 +119,13 @@
 {
     int i;
     struct irqaction *action;
+    unsigned long flags;
 
     for (i = 0; i < NR_IRQS; i++) {
+	local_irq_save(flags);
 	action = irq_action[i];
 	if (!action)
-	    continue;
+	    goto skip;
 	seq_printf(p, "%2d: %8d %c %s",
 		       i, kstat_cpu(0).irqs[i],
 		       (action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -134,6 +136,8 @@
 			   action->name);
 	}
 	seq_putc(p, '\n');
+skip:
+	local_irq_restore(flags);
     }
     return 0;
 }
diff -urN linux-2.5.64-bk3/arch/mips64/Kconfig linux-2.5.64-bk4/arch/mips64/Kconfig
--- linux-2.5.64-bk3/arch/mips64/Kconfig	Tue Mar  4 19:29:04 2003
+++ linux-2.5.64-bk4/arch/mips64/Kconfig	Mon Mar 31 12:25:44 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 source "init/Kconfig"
 
 
diff -urN linux-2.5.64-bk3/arch/mips64/mips-boards/atlas/atlas_int.c linux-2.5.64-bk4/arch/mips64/mips-boards/atlas/atlas_int.c
--- linux-2.5.64-bk3/arch/mips64/mips-boards/atlas/atlas_int.c	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/arch/mips64/mips-boards/atlas/atlas_int.c	Mon Mar 31 12:25:44 2003
@@ -95,11 +95,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < ATLASINT_END; i++, num++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -110,6 +112,8 @@
 				action->name);
 		}
 		seq_puts(p, " [hw0]\n");
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -239,6 +243,7 @@
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &atlas_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 #ifdef CONFIG_REMOTE_DEBUG
diff -urN linux-2.5.64-bk3/arch/mips64/mips-boards/malta/malta_int.c linux-2.5.64-bk4/arch/mips64/mips-boards/malta/malta_int.c
--- linux-2.5.64-bk3/arch/mips64/mips-boards/malta/malta_int.c	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk4/arch/mips64/mips-boards/malta/malta_int.c	Mon Mar 31 12:25:44 2003
@@ -125,11 +125,13 @@
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < 8; i++, num++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_1;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -140,11 +142,14 @@
 				action->name);
 		}
 		seq_puts(p, " [on-chip]\n");
+skip_1:
+		local_irq_restore(flags);
 	}
 	for (i = 0; i < MALTAINT_END; i++, num++) {
+		local_irq_save(flags);
 		action = hw0_irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_2;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -155,6 +160,8 @@
 				action->name);
 		}
 		seq_puts(p, " [hw0]\n");
+skip_2:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/mips64/sgi-ip22/ip22-int.c linux-2.5.64-bk4/arch/mips64/sgi-ip22/ip22-int.c
--- linux-2.5.64-bk3/arch/mips64/sgi-ip22/ip22-int.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/arch/mips64/sgi-ip22/ip22-int.c	Mon Mar 31 12:25:44 2003
@@ -237,11 +237,13 @@
 	int i;
 	int num = 0;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < 16 ; i++, num++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_1;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -252,11 +254,14 @@
 				action->name);
 		}
 		seq_puts(p, " [on-chip]\n");
+skip_1:
+		local_irq_restore(flags);
 	}
 	for (i = 0 ; i < 24 ; i++, num++) {
+		local_irq_save(flags);
 		action = local_irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_2;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -267,6 +272,8 @@
 				action->name);
 		}
 		seq_puts(p, " [local]\n");
+skip_2:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/mips64/sgi-ip27/ip27-irq.c linux-2.5.64-bk4/arch/mips64/sgi-ip27/ip27-irq.c
--- linux-2.5.64-bk3/arch/mips64/sgi-ip27/ip27-irq.c	Tue Mar  4 19:29:19 2003
+++ linux-2.5.64-bk4/arch/mips64/sgi-ip27/ip27-irq.c	Mon Mar 31 12:25:44 2003
@@ -141,11 +141,13 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i],
 		               (action->flags & SA_INTERRUPT) ? '+' : ' ',
 		               action->name);
@@ -156,6 +158,8 @@
 			                action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/parisc/Kconfig linux-2.5.64-bk4/arch/parisc/Kconfig
--- linux-2.5.64-bk3/arch/parisc/Kconfig	Tue Mar  4 19:29:23 2003
+++ linux-2.5.64-bk4/arch/parisc/Kconfig	Mon Mar 31 12:25:44 2003
@@ -18,10 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config STACK_GROWSUP
 	bool
 	default y
diff -urN linux-2.5.64-bk3/arch/ppc/Kconfig linux-2.5.64-bk4/arch/ppc/Kconfig
--- linux-2.5.64-bk3/arch/ppc/Kconfig	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/arch/ppc/Kconfig	Mon Mar 31 12:25:44 2003
@@ -1126,22 +1126,6 @@
 config PIN_TLB
 	bool "Pinned Kernel TLBs (860 ONLY)"
 	depends on ADVANCED_OPTIONS && 8xx
-
-config SWAP
-	bool "Enable support for swap"
-	depends on ADVANCED_OPTIONS
-	help
-	  This option allows you to turn off support for swapfiles in
-	  the kernel.  This can be useful if you know that your system
-	  will never have swap.
-
-	  Say Y here unless you know what you are doing.
-
-config SWAP
-	bool
-	depends on !ADVANCED_OPTIONS
-	default y
-
 endmenu
 
 source "drivers/mtd/Kconfig"
diff -urN linux-2.5.64-bk3/arch/ppc/kernel/irq.c linux-2.5.64-bk4/arch/ppc/kernel/irq.c
--- linux-2.5.64-bk3/arch/ppc/kernel/irq.c	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/arch/ppc/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -346,6 +346,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -354,9 +355,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if ( !action || !action->handler )
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++)
@@ -373,8 +375,10 @@
 		seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge  ");
 		seq_printf(p, "    %s", action->name);
 		for (action = action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
+				seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 #ifdef CONFIG_TAU_INT
 	if (tau_initialized){
diff -urN linux-2.5.64-bk3/arch/ppc64/Kconfig linux-2.5.64-bk4/arch/ppc64/Kconfig
--- linux-2.5.64-bk3/arch/ppc64/Kconfig	Tue Mar  4 19:29:21 2003
+++ linux-2.5.64-bk4/arch/ppc64/Kconfig	Mon Mar 31 12:25:44 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 
diff -urN linux-2.5.64-bk3/arch/ppc64/kernel/irq.c linux-2.5.64-bk4/arch/ppc64/kernel/irq.c
--- linux-2.5.64-bk3/arch/ppc64/kernel/irq.c	Tue Mar  4 19:29:17 2003
+++ linux-2.5.64-bk4/arch/ppc64/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -341,6 +341,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++) {
@@ -350,9 +351,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action || !action->handler)
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++) {
@@ -371,6 +373,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
 	return 0;
diff -urN linux-2.5.64-bk3/arch/s390/Kconfig linux-2.5.64-bk4/arch/s390/Kconfig
--- linux-2.5.64-bk3/arch/s390/Kconfig	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk4/arch/s390/Kconfig	Mon Mar 31 12:25:44 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -urN linux-2.5.64-bk3/arch/s390x/Kconfig linux-2.5.64-bk4/arch/s390x/Kconfig
--- linux-2.5.64-bk3/arch/s390x/Kconfig	Tue Mar  4 19:29:19 2003
+++ linux-2.5.64-bk4/arch/s390x/Kconfig	Mon Mar 31 12:25:44 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
diff -urN linux-2.5.64-bk3/arch/sh/Kconfig linux-2.5.64-bk4/arch/sh/Kconfig
--- linux-2.5.64-bk3/arch/sh/Kconfig	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/arch/sh/Kconfig	Mon Mar 31 12:25:44 2003
@@ -18,10 +18,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -urN linux-2.5.64-bk3/arch/sh/kernel/irq.c linux-2.5.64-bk4/arch/sh/kernel/irq.c
--- linux-2.5.64-bk3/arch/sh/kernel/irq.c	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk4/arch/sh/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -90,6 +90,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
@@ -97,9 +98,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
-		if (!action) 
-			continue;
+		if (!action)
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -108,6 +110,8 @@
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/sparc/Kconfig linux-2.5.64-bk4/arch/sparc/Kconfig
--- linux-2.5.64-bk3/arch/sparc/Kconfig	Tue Mar  4 19:28:52 2003
+++ linux-2.5.64-bk4/arch/sparc/Kconfig	Mon Mar 31 12:25:44 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config UID16
 	bool
 	default y
diff -urN linux-2.5.64-bk3/arch/sparc/kernel/irq.c linux-2.5.64-bk4/arch/sparc/kernel/irq.c
--- linux-2.5.64-bk3/arch/sparc/kernel/irq.c	Tue Mar  4 19:28:56 2003
+++ linux-2.5.64-bk4/arch/sparc/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -104,6 +104,7 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 #ifdef CONFIG_SMP
 	int j;
 #endif
@@ -114,9 +115,10 @@
 		return show_sun4d_interrupts(p, v);
 	}
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		local_irq_save(flags);
 	        action = *(i + irq_action);
 		if (!action) 
-		        continue;
+		        goto skip;
 		seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -136,6 +138,8 @@
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/arch/sparc64/Kconfig linux-2.5.64-bk4/arch/sparc64/Kconfig
--- linux-2.5.64-bk3/arch/sparc64/Kconfig	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/arch/sparc64/Kconfig	Mon Mar 31 12:25:44 2003
@@ -9,10 +9,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 source "init/Kconfig"
 
 
diff -urN linux-2.5.64-bk3/arch/sparc64/defconfig linux-2.5.64-bk4/arch/sparc64/defconfig
--- linux-2.5.64-bk3/arch/sparc64/defconfig	Tue Mar  4 19:29:15 2003
+++ linux-2.5.64-bk4/arch/sparc64/defconfig	Mon Mar 31 12:25:44 2003
@@ -39,9 +39,11 @@
 # CONFIG_PREEMPT is not set
 CONFIG_NR_CPUS=4
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_PROC_INTF=y
 CONFIG_CPU_FREQ_TABLE=y
 CONFIG_US3_FREQ=m
+CONFIG_CPU_FREQ_PROC_INTF=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+# CONFIG_CPU_FREQ_24_API is not set
 CONFIG_SPARC64=y
 CONFIG_HOTPLUG=y
 CONFIG_HAVE_DEC_LOCK=y
@@ -354,6 +356,8 @@
 CONFIG_XFRM_USER=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -872,6 +876,7 @@
 CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
 CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_XPAD is not set
 
@@ -928,6 +933,7 @@
 # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
 CONFIG_USB_SERIAL_KEYSPAN_PDA=m
 CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
@@ -938,6 +944,7 @@
 # CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
 CONFIG_USB_SERIAL_KLSI=m
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 CONFIG_USB_SERIAL_MCT_U232=m
diff -urN linux-2.5.64-bk3/arch/sparc64/kernel/ioctl32.c linux-2.5.64-bk4/arch/sparc64/kernel/ioctl32.c
--- linux-2.5.64-bk3/arch/sparc64/kernel/ioctl32.c	Tue Mar  4 19:29:35 2003
+++ linux-2.5.64-bk4/arch/sparc64/kernel/ioctl32.c	Mon Mar 31 12:25:44 2003
@@ -38,6 +38,7 @@
 #include <linux/cdrom.h>
 #include <linux/loop.h>
 #include <linux/auto_fs.h>
+#include <linux/auto_fs4.h>
 #include <linux/devfs_fs.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
@@ -4850,6 +4851,7 @@
 COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
 COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
 COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
+COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
 /* DEVFS */
 COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV)
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
diff -urN linux-2.5.64-bk3/arch/sparc64/kernel/pci_common.c linux-2.5.64-bk4/arch/sparc64/kernel/pci_common.c
--- linux-2.5.64-bk3/arch/sparc64/kernel/pci_common.c	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/arch/sparc64/kernel/pci_common.c	Mon Mar 31 12:25:44 2003
@@ -78,20 +78,6 @@
 	return 0;
 }
 
-/* Remove a PCI device from the device trees, then
- * free it up.  Note that this must run before
- * the device's resources are registered because we
- * do not handle unregistering them here.
- */
-static void pci_device_delete(struct pci_dev *pdev)
-{
-	list_del(&pdev->global_list);
-	list_del(&pdev->bus_list);
-
-	/* Ok, all references are gone, free it up. */
-	kfree(pdev);
-}
-
 /* Older versions of OBP on PCI systems encode 64-bit MEM
  * space assignments incorrectly, this fixes them up.  We also
  * take the opportunity here to hide other kinds of bogus
@@ -164,7 +150,7 @@
 		 * second EBUS/HappyMeal pair if the external
 		 * connector for it is not present.
 		 */
-		pci_device_delete(pdev);
+		pci_remove_bus_device(pdev);
 		return;
 	}
 
diff -urN linux-2.5.64-bk3/arch/sparc64/kernel/smp.c linux-2.5.64-bk4/arch/sparc64/kernel/smp.c
--- linux-2.5.64-bk3/arch/sparc64/kernel/smp.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk4/arch/sparc64/kernel/smp.c	Mon Mar 31 12:25:44 2003
@@ -1137,17 +1137,17 @@
 	do {
 		sparc64_do_profile(regs);
 		if (!--prof_counter(cpu)) {
-			if (cpu == boot_cpu_id) {
-				irq_enter();
+			irq_enter();
 
+			if (cpu == boot_cpu_id) {
 				kstat_cpu(cpu).irqs[0]++;
 				timer_tick_interrupt(regs);
-
-				irq_exit();
 			}
 
 			update_process_times(user);
 
+			irq_exit();
+
 			prof_counter(cpu) = prof_multiplier(cpu);
 		}
 
diff -urN linux-2.5.64-bk3/arch/um/Kconfig linux-2.5.64-bk4/arch/um/Kconfig
--- linux-2.5.64-bk3/arch/um/Kconfig	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/arch/um/Kconfig	Mon Mar 31 12:25:44 2003
@@ -7,10 +7,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 mainmenu "Linux/Usermode Kernel Configuration"
 
 config ISA
diff -urN linux-2.5.64-bk3/arch/um/drivers/ubd_kern.c linux-2.5.64-bk4/arch/um/drivers/ubd_kern.c
--- linux-2.5.64-bk3/arch/um/drivers/ubd_kern.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/arch/um/drivers/ubd_kern.c	Mon Mar 31 12:25:44 2003
@@ -673,7 +673,7 @@
 static int ubd_mc_init(void)
 {
 	mconsole_register_dev(&ubd_mc);
-	return(0);
+	return 0;
 }
 
 __initcall(ubd_mc_init);
@@ -682,29 +682,24 @@
 {
         int i;
 
-	ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL);
-	if(register_blkdev(MAJOR_NR, "ubd", &ubd_blops)){
-		printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR);
+	ubd_dir_handle = devfs_mk_dir(NULL, "ubd", NULL);
+	if (register_blkdev(MAJOR_NR, "ubd"))
 		return -1;
-	}
 
 	blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock);
 	elevator_init(&ubd_queue, &elevator_noop);
 
-	if(fake_major != 0){
+	if (fake_major != 0) {
 		char name[sizeof("ubd_nnn\0")];
 
 		snprintf(name, sizeof(name), "ubd_%d", fake_major);
 		ubd_fake_dir_handle = devfs_mk_dir(NULL, name, NULL);
-		if(register_blkdev(fake_major, "ubd", &ubd_blops)){
-			printk(KERN_ERR "ubd: unable to get major %d\n",
-			       fake_major);
+		if (register_blkdev(fake_major, "ubd"))
 			return -1;
-		}
 	}
-	for(i = 0; i < MAX_DEV; i++) 
+	for (i = 0; i < MAX_DEV; i++) 
 		ubd_add(i);
-	return(0);
+	return 0;
 }
 
 late_initcall(ubd_init);
diff -urN linux-2.5.64-bk3/arch/v850/Kconfig linux-2.5.64-bk4/arch/v850/Kconfig
--- linux-2.5.64-bk3/arch/v850/Kconfig	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/arch/v850/Kconfig	Mon Mar 31 12:25:44 2003
@@ -10,9 +10,6 @@
 config MMU
        	bool
 	default n
-config SWAP
-	bool
-	default n
 config UID16
 	bool
 	default n
diff -urN linux-2.5.64-bk3/arch/v850/kernel/irq.c linux-2.5.64-bk4/arch/v850/kernel/irq.c
--- linux-2.5.64-bk3/arch/v850/kernel/irq.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/arch/v850/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -78,6 +78,7 @@
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (i=0; i < 1 /*smp_num_cpus*/; i++)
@@ -87,10 +88,10 @@
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		int j, count, num;
 		const char *type_name = irq_desc[i].handler->typename;
-
+		spin_lock_irqsave(&irq_desc[j].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 
 		count = 0;
 		num = -1;
@@ -108,11 +109,13 @@
 			seq_printf(p, " %*s%d", 14 - prec, type_name, num);
 		} else
 			seq_printf(p, " %14s", type_name);
+		
 		seq_printf(p, "  %s", action->name);
-
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[j].lock, flags);
 	}
 	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
diff -urN linux-2.5.64-bk3/arch/x86_64/Kconfig linux-2.5.64-bk4/arch/x86_64/Kconfig
--- linux-2.5.64-bk3/arch/x86_64/Kconfig	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/arch/x86_64/Kconfig	Mon Mar 31 12:25:44 2003
@@ -24,10 +24,6 @@
 	bool
 	default y
 
-config SWAP
-	bool
-	default y
-
 config ISA
 	bool
 
diff -urN linux-2.5.64-bk3/arch/x86_64/kernel/irq.c linux-2.5.64-bk4/arch/x86_64/kernel/irq.c
--- linux-2.5.64-bk3/arch/x86_64/kernel/irq.c	Tue Mar  4 19:29:17 2003
+++ linux-2.5.64-bk4/arch/x86_64/kernel/irq.c	Mon Mar 31 12:25:44 2003
@@ -135,6 +135,7 @@
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -143,9 +144,10 @@
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -156,11 +158,13 @@
 				kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
-		seq_printf(p, "  %s", action->name);
 
+		seq_printf(p, "  %s", action->name);
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
diff -urN linux-2.5.64-bk3/drivers/acorn/block/fd1772.c linux-2.5.64-bk4/drivers/acorn/block/fd1772.c
--- linux-2.5.64-bk3/drivers/acorn/block/fd1772.c	Tue Mar  4 19:29:15 2003
+++ linux-2.5.64-bk4/drivers/acorn/block/fd1772.c	Mon Mar 31 12:25:44 2003
@@ -1539,11 +1539,9 @@
 			goto err_disk;
 	}
 
-	err = register_blkdev(MAJOR_NR, "fd", &floppy_fops);
-	if (err) {
-		printk("Unable to get major %d for floppy\n", MAJOR_NR);
+	err = register_blkdev(MAJOR_NR, "fd");
+	if (err)
 		goto err_disk;
-	}
 
 	err = -EBUSY;
 	if (request_dma(FLOPPY_DMA, "fd1772")) {
diff -urN linux-2.5.64-bk3/drivers/acorn/block/mfmhd.c linux-2.5.64-bk4/drivers/acorn/block/mfmhd.c
--- linux-2.5.64-bk3/drivers/acorn/block/mfmhd.c	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/drivers/acorn/block/mfmhd.c	Mon Mar 31 12:25:44 2003
@@ -1267,11 +1267,9 @@
 	if (!request_region (mfm_addr, 10, "mfm"))
 		goto out1;
 
-	ret = register_blkdev(MAJOR_NR, "mfm", &mfm_fops);
-	if (ret) {
-		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
+	ret = register_blkdev(MAJOR_NR, "mfm");
+	if (ret)
 		goto out2;
-	}
 
 	/* Stuff for the assembler routines to get to */
 	hdc63463_baseaddress	= ioaddr(mfm_addr);
diff -urN linux-2.5.64-bk3/drivers/block/DAC960.c linux-2.5.64-bk4/drivers/block/DAC960.c
--- linux-2.5.64-bk3/drivers/block/DAC960.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/block/DAC960.c	Mon Mar 31 12:25:45 2003
@@ -13,9 +13,6 @@
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for complete details.
 
-  The author respectfully requests that any modifications to this software be
-  sent directly to him for evaluation and testing.
-
 */
 
 
@@ -2381,13 +2378,9 @@
   /*
     Register the Block Device Major Number for this DAC960 Controller.
   */
-  if (register_blkdev(MajorNumber, "dac960",
-			    &DAC960_BlockDeviceOperations) < 0)
-    {
-      DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
-		   Controller, MajorNumber);
+  if (register_blkdev(MajorNumber, "dac960") < 0)
       return false;
-    }
+
   /*
     Initialize the I/O Request Queue.
   */
diff -urN linux-2.5.64-bk3/drivers/block/acsi.c linux-2.5.64-bk4/drivers/block/acsi.c
--- linux-2.5.64-bk3/drivers/block/acsi.c	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/drivers/block/acsi.c	Mon Mar 31 12:25:45 2003
@@ -1613,7 +1613,6 @@
 
 
 int acsi_init( void )
-
 {
 	int err = 0;
 	int i, target, lun;
@@ -1623,8 +1622,7 @@
 #endif
 	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
 		return 0;
-	if (register_blkdev( ACSI_MAJOR, "ad", &acsi_fops )) {
-		printk( KERN_ERR "Unable to get major %d for ACSI\n", ACSI_MAJOR );
+	if (register_blkdev(ACSI_MAJOR, "ad")) {
 		err = -EBUSY;
 		goto out1;
 	}
diff -urN linux-2.5.64-bk3/drivers/block/amiflop.c linux-2.5.64-bk4/drivers/block/amiflop.c
--- linux-2.5.64-bk3/drivers/block/amiflop.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/drivers/block/amiflop.c	Mon Mar 31 12:25:45 2003
@@ -1754,10 +1754,9 @@
 	if (!AMIGAHW_PRESENT(AMI_FLOPPY))
 		return -ENXIO;
 
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk("fd: Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd"))
 		return -EBUSY;
-	}
+
 	/*
 	 *  We request DSKPTR, DSKLEN and DSKDATA only, because the other
 	 *  floppy registers are too spreaded over the custom register space
diff -urN linux-2.5.64-bk3/drivers/block/ataflop.c linux-2.5.64-bk4/drivers/block/ataflop.c
--- linux-2.5.64-bk3/drivers/block/ataflop.c	Tue Mar  4 19:29:00 2003
+++ linux-2.5.64-bk4/drivers/block/ataflop.c	Mon Mar 31 12:25:45 2003
@@ -1929,10 +1929,8 @@
 		/* Hades doesn't have Atari-compatible floppy */
 		return -ENXIO;
 
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk(KERN_ERR "Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd"))
 		return -EBUSY;
-	}
 
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		unit[i].disk = alloc_disk(1);
diff -urN linux-2.5.64-bk3/drivers/block/cciss.c linux-2.5.64-bk4/drivers/block/cciss.c
--- linux-2.5.64-bk3/drivers/block/cciss.c	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/drivers/block/cciss.c	Mon Mar 31 12:25:45 2003
@@ -2451,14 +2451,12 @@
 		return -ENODEV;
 	}
 
-	if( register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname, &cciss_fops))
-	{
-		printk(KERN_ERR "cciss:  Unable to get major number "
-			"%d for %s\n", COMPAQ_CISS_MAJOR+i, hba[i]->devname);
+	if (register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname)) {
 		release_io_mem(hba[i]);
 		free_hba(i);
-		return(-1);
+		return -1;
 	}
+
 	/* make sure the board interrupts are off */
 	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
 	if( request_irq(hba[i]->intr, do_cciss_intr, 
diff -urN linux-2.5.64-bk3/drivers/block/cpqarray.c linux-2.5.64-bk4/drivers/block/cpqarray.c
--- linux-2.5.64-bk3/drivers/block/cpqarray.c	Tue Mar  4 19:29:00 2003
+++ linux-2.5.64-bk4/drivers/block/cpqarray.c	Mon Mar 31 12:25:45 2003
@@ -339,11 +339,9 @@
 	for(i=0; i < nr_ctlr; i++) {
 	  	/* If this successful it should insure that we are the only */
 		/* instance of the driver */	
-		if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname, &ida_fops)) {
-                        printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n",
-                                COMPAQ_SMART2_MAJOR+i);
+		if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname))
                         continue;
-                }
+
 		hba[i]->access.set_intr_mask(hba[i], 0);
 		if (request_irq(hba[i]->intr, do_ida_intr,
 			SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) {
diff -urN linux-2.5.64-bk3/drivers/block/floppy.c linux-2.5.64-bk4/drivers/block/floppy.c
--- linux-2.5.64-bk3/drivers/block/floppy.c	Tue Mar  4 19:29:00 2003
+++ linux-2.5.64-bk4/drivers/block/floppy.c	Mon Mar 31 12:25:45 2003
@@ -4232,8 +4232,7 @@
 	}
 
 	devfs_mk_dir (NULL, "floppy", NULL);
-	if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) {
-		printk("Unable to get major %d for floppy\n",FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR,"fd")) {
 		err = -EBUSY;
 		goto out;
 	}
diff -urN linux-2.5.64-bk3/drivers/block/genhd.c linux-2.5.64-bk4/drivers/block/genhd.c
--- linux-2.5.64-bk3/drivers/block/genhd.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/drivers/block/genhd.c	Mon Mar 31 12:25:45 2003
@@ -14,10 +14,16 @@
 #include <linux/slab.h>
 #include <linux/kmod.h>
 
+#define MAX_PROBE_HASH 255	/* random */
 
 static struct subsystem block_subsys;
 
-#define MAX_PROBE_HASH 23	/* random */
+/* Can be merged with blk_probe or deleted altogether. Later. */
+static struct blk_major_name {
+	struct blk_major_name *next;
+	int major;
+	char name[16];
+} *major_names[MAX_PROBE_HASH];
 
 static struct blk_probe {
 	struct blk_probe *next;
@@ -30,9 +36,132 @@
 } *probes[MAX_PROBE_HASH];
 
 /* index in the above - for now: assume no multimajor ranges */
+static inline int major_to_index(int major)
+{
+	return major % MAX_PROBE_HASH;
+}
+
 static inline int dev_to_index(dev_t dev)
 {
-	return MAJOR(dev) % MAX_PROBE_HASH;
+	return major_to_index(MAJOR(dev));
+}
+
+const char *__bdevname(dev_t dev)
+{
+	static char buffer[40];
+	char *name = "unknown-block";
+	unsigned int major = MAJOR(dev);
+	unsigned int minor = MINOR(dev);
+	int index = major_to_index(major);
+	struct blk_major_name *n;
+
+	down_read(&block_subsys.rwsem);
+	for (n = major_names[index]; n; n = n->next)
+		if (n->major == major)
+			break;
+	if (n)
+		name = &(n->name[0]);
+	sprintf(buffer, "%s(%u,%u)", name, major, minor);
+	up_read(&block_subsys.rwsem);
+
+	return buffer;
+}
+
+/* get block device names in somewhat random order */
+int get_blkdev_list(char *p)
+{
+	struct blk_major_name *n;
+	int i, len;
+
+	len = sprintf(p, "\nBlock devices:\n");
+
+	down_read(&block_subsys.rwsem);
+	for (i = 0; i < ARRAY_SIZE(major_names); i++) {
+		for (n = major_names[i]; n; n = n->next)
+			len += sprintf(p+len, "%3d %s\n",
+				       n->major, n->name);
+	}
+	up_read(&block_subsys.rwsem);
+
+	return len;
+}
+
+int register_blkdev(unsigned int major, const char *name)
+{
+	struct blk_major_name **n, *p;
+	int index, ret = 0;
+
+	if (devfs_only())
+		return 0;
+
+	/* temporary */
+	if (major == 0) {
+		down_read(&block_subsys.rwsem);
+		for (index = ARRAY_SIZE(major_names)-1; index > 0; index--)
+			if (major_names[index] == NULL)
+				break;
+		up_read(&block_subsys.rwsem);
+
+		if (index == 0) {
+			printk("register_blkdev: failed to get major for %s\n",
+			       name);
+			return -EBUSY;
+		}
+		ret = major = index;
+	}
+
+	p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL);
+	if (p == NULL)
+		return -ENOMEM;
+
+	p->major = major;
+	strncpy(p->name, name, sizeof(p->name)-1);
+	p->name[sizeof(p->name)-1] = 0;
+	p->next = 0;
+	index = major_to_index(major);
+
+	down_write(&block_subsys.rwsem);
+	for (n = &major_names[index]; *n; n = &(*n)->next)
+		if ((*n)->major == major)
+			break;
+	if (!*n)
+		*n = p;
+	else
+		ret = -EBUSY;
+	up_write(&block_subsys.rwsem);
+
+	if (ret < 0)
+		printk("register_blkdev: cannot get major %d for %s\n",
+		       major, name);
+
+	return ret;
+}
+
+/* todo: make void - error printk here */
+int unregister_blkdev(unsigned int major, const char *name)
+{
+	struct blk_major_name **n, *p;
+	int index;
+	int ret = 0;
+
+	if (devfs_only())
+		return 0;
+	index = major_to_index(major);
+
+	down_write(&block_subsys.rwsem);
+	for (n = &major_names[index]; *n; n = &(*n)->next)
+		if ((*n)->major == major)
+			break;
+	if (!*n || strcmp((*n)->name, name))
+		ret = -EINVAL;
+	else {
+		p = *n;
+		*n = p->next;
+		kfree(p);
+	}
+	up_write(&block_subsys.rwsem);
+
+	return ret;
 }
 
 /*
@@ -48,6 +177,9 @@
 	struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
 	struct blk_probe **s;
 
+	if (p == NULL)
+		return;
+
 	p->owner = module;
 	p->get = probe;
 	p->lock = lock;
@@ -98,9 +230,9 @@
 
 /**
  * add_gendisk - add partitioning information to kernel list
- * @gp: per-device partitioning information
+ * @disk: per-device partitioning information
  *
- * This function registers the partitioning information in @gp
+ * This function registers the partitioning information in @disk
  * with the kernel.
  */
 void add_disk(struct gendisk *disk)
@@ -318,7 +450,7 @@
 	return (jif / HZ) * 1000 + (jif % HZ) * 1000 / HZ;
 #endif
 }
-static ssize_t disk_stat_read(struct gendisk * disk, char *page)
+static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
 	disk_round_stats(disk);
 	return sprintf(page,
@@ -326,14 +458,16 @@
 		"%8u %8u %8llu %8u "
 		"%8u %8u %8u"
 		"\n",
-		disk->reads, disk->read_merges,
-		(unsigned long long)disk->read_sectors,
-		jiffies_to_msec(disk->read_ticks),
-		disk->writes, disk->write_merges,
-		(unsigned long long)disk->write_sectors,
-		jiffies_to_msec(disk->write_ticks),
-		disk->in_flight, jiffies_to_msec(disk->io_ticks),
-		jiffies_to_msec(disk->time_in_queue));
+		disk_stat_read(disk, reads), disk_stat_read(disk, read_merges),
+		(unsigned long long)disk_stat_read(disk, read_sectors),
+		jiffies_to_msec(disk_stat_read(disk, read_ticks)),
+		disk_stat_read(disk, writes), 
+		disk_stat_read(disk, write_merges),
+		(unsigned long long)disk_stat_read(disk, write_sectors),
+		jiffies_to_msec(disk_stat_read(disk, write_ticks)),
+		disk_stat_read(disk, in_flight), 
+		jiffies_to_msec(disk_stat_read(disk, io_ticks)),
+		jiffies_to_msec(disk_stat_read(disk, time_in_queue)));
 }
 static struct disk_attribute disk_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
@@ -349,7 +483,7 @@
 };
 static struct disk_attribute disk_attr_stat = {
 	.attr = {.name = "stat", .mode = S_IRUGO },
-	.show	= disk_stat_read
+	.show	= disk_stats_read
 };
 
 static struct attribute * default_attrs[] = {
@@ -365,6 +499,7 @@
 	struct gendisk *disk = to_disk(kobj);
 	kfree(disk->random);
 	kfree(disk->part);
+	free_disk_stats(disk);
 	kfree(disk);
 }
 
@@ -384,6 +519,10 @@
 	struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
 	if (disk) {
 		memset(disk, 0, sizeof(struct gendisk));
+		if (!init_disk_stats(disk)) {
+			kfree(disk);
+			return NULL;
+		}
 		if (minors > 1) {
 			int size = (minors - 1) * sizeof(struct hd_struct);
 			disk->part = kmalloc(size, GFP_KERNEL);
diff -urN linux-2.5.64-bk3/drivers/block/ll_rw_blk.c linux-2.5.64-bk4/drivers/block/ll_rw_blk.c
--- linux-2.5.64-bk3/drivers/block/ll_rw_blk.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/drivers/block/ll_rw_blk.c	Mon Mar 31 12:25:45 2003
@@ -1475,17 +1475,17 @@
 		return;
 
 	if (rw == READ) {
-		rq->rq_disk->read_sectors += nr_sectors;
+		disk_stat_add(rq->rq_disk, read_sectors, nr_sectors);
 		if (!new_io)
-			rq->rq_disk->read_merges++;
+			disk_stat_inc(rq->rq_disk, read_merges);
 	} else if (rw == WRITE) {
-		rq->rq_disk->write_sectors += nr_sectors;
+		disk_stat_add(rq->rq_disk, write_sectors, nr_sectors);
 		if (!new_io)
-			rq->rq_disk->write_merges++;
+			disk_stat_inc(rq->rq_disk, write_merges);
 	}
 	if (new_io) {
 		disk_round_stats(rq->rq_disk);
-		rq->rq_disk->in_flight++;
+		disk_stat_inc(rq->rq_disk, in_flight);
 	}
 }
 
@@ -1525,11 +1525,12 @@
 {
 	unsigned long now = jiffies;
 
-	disk->time_in_queue += disk->in_flight * (now - disk->stamp);
+	disk_stat_add(disk, time_in_queue, 
+			disk_stat_read(disk, in_flight) * (now - disk->stamp));
 	disk->stamp = now;
 
-	if (disk->in_flight)
-		disk->io_ticks += (now - disk->stamp_idle);
+	if (disk_stat_read(disk, in_flight))
+		disk_stat_add(disk, io_ticks, (now - disk->stamp_idle));
 	disk->stamp_idle = now;
 }
 
@@ -1647,7 +1648,7 @@
 
 		if (req->rq_disk) {
 			disk_round_stats(req->rq_disk);
-			req->rq_disk->in_flight--;
+			disk_stat_dec(req->rq_disk, in_flight);
 		}
 
 		__blk_put_request(q, next);
@@ -2199,16 +2200,16 @@
 		unsigned long duration = jiffies - req->start_time;
 		switch (rq_data_dir(req)) {
 		    case WRITE:
-			disk->writes++;
-			disk->write_ticks += duration;
+			disk_stat_inc(disk, writes);
+			disk_stat_add(disk, write_ticks, duration);
 			break;
 		    case READ:
-			disk->reads++;
-			disk->read_ticks += duration;
+			disk_stat_inc(disk, reads);
+			disk_stat_add(disk, read_ticks, duration);
 			break;
 		}
 		disk_round_stats(disk);
-		disk->in_flight--;
+		disk_stat_dec(disk, in_flight);
 	}
 	__blk_put_request(req->q, req);
 }
diff -urN linux-2.5.64-bk3/drivers/block/loop.c linux-2.5.64-bk4/drivers/block/loop.c
--- linux-2.5.64-bk3/drivers/block/loop.c	Tue Mar  4 19:29:22 2003
+++ linux-2.5.64-bk4/drivers/block/loop.c	Mon Mar 31 12:25:45 2003
@@ -1017,11 +1017,8 @@
 		max_loop = 8;
 	}
 
-	if (register_blkdev(LOOP_MAJOR, "loop", &lo_fops)) {
-		printk(KERN_WARNING "Unable to get major number %d for loop"
-				    " device\n", LOOP_MAJOR);
+	if (register_blkdev(LOOP_MAJOR, "loop"))
 		return -EIO;
-	}
 
 	devfs_mk_dir(NULL, "loop", NULL);
 
diff -urN linux-2.5.64-bk3/drivers/block/nbd.c linux-2.5.64-bk4/drivers/block/nbd.c
--- linux-2.5.64-bk3/drivers/block/nbd.c	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/drivers/block/nbd.c	Mon Mar 31 12:25:45 2003
@@ -564,9 +564,7 @@
 		nbd_dev[i].disk = disk;
 	}
 
-	if (register_blkdev(NBD_MAJOR, "nbd", &nbd_fops)) {
-		printk("Unable to get major number %d for NBD\n",
-		       NBD_MAJOR);
+	if (register_blkdev(NBD_MAJOR, "nbd")) {
 		err = -EIO;
 		goto out;
 	}
diff -urN linux-2.5.64-bk3/drivers/block/paride/pcd.c linux-2.5.64-bk4/drivers/block/paride/pcd.c
--- linux-2.5.64-bk3/drivers/block/paride/pcd.c	Tue Mar  4 19:29:53 2003
+++ linux-2.5.64-bk4/drivers/block/paride/pcd.c	Mon Mar 31 12:25:45 2003
@@ -942,8 +942,7 @@
 	/* get the atapi capabilities page */
 	pcd_probe_capabilities();
 
-	if (register_blkdev(major, name, &pcd_bdops)) {
-		printk("pcd: unable to get major number %d\n", major);
+	if (register_blkdev(major, name)) {
 		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
 			put_disk(cd->disk);
 		return -1;
diff -urN linux-2.5.64-bk3/drivers/block/paride/pd.c linux-2.5.64-bk4/drivers/block/paride/pd.c
--- linux-2.5.64-bk3/drivers/block/paride/pd.c	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/drivers/block/paride/pd.c	Mon Mar 31 12:25:45 2003
@@ -890,10 +890,9 @@
 {
 	if (disable)
 		return -1;
-	if (register_blkdev(major, name, &pd_fops)) {
-		printk("%s: unable to get major number %d\n", name, major);
+	if (register_blkdev(major, name))
 		return -1;
-	}
+
 	blk_init_queue(&pd_queue, do_pd_request, &pd_lock);
 	blk_queue_max_sectors(&pd_queue, cluster);
 
diff -urN linux-2.5.64-bk3/drivers/block/paride/pf.c linux-2.5.64-bk4/drivers/block/paride/pf.c
--- linux-2.5.64-bk3/drivers/block/paride/pf.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/drivers/block/paride/pf.c	Mon Mar 31 12:25:45 2003
@@ -957,8 +957,7 @@
 		return -1;
 	pf_busy = 0;
 
-	if (register_blkdev(major, name, &pf_fops)) {
-		printk("pf_init: unable to get major number %d\n", major);
+	if (register_blkdev(major, name)) {
 		for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
 			put_disk(pf->disk);
 		return -1;
@@ -969,6 +968,7 @@
 
 	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {
 		struct gendisk *disk = pf->disk;
+
 		if (!pf->present)
 			continue;
 		disk->private_data = pf;
diff -urN linux-2.5.64-bk3/drivers/block/ps2esdi.c linux-2.5.64-bk4/drivers/block/ps2esdi.c
--- linux-2.5.64-bk3/drivers/block/ps2esdi.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk4/drivers/block/ps2esdi.c	Mon Mar 31 12:25:45 2003
@@ -146,13 +146,10 @@
 
 	int error = 0;
 
-	/* register the device - pass the name, major number and operations
-	   vector .                                                 */
-	if (register_blkdev(PS2ESDI_MAJOR, "ed", &ps2esdi_fops)) {
-		printk("%s: Unable to get major number %d\n", DEVICE_NAME,
-				PS2ESDI_MAJOR);
+	/* register the device - pass the name and major number */
+	if (register_blkdev(PS2ESDI_MAJOR, "ed"))
 		return -1;
-	}
+
 	/* set up some global information - indicating device specific info */
 	blk_init_queue(&ps2esdi_queue, do_ps2esdi_request, &ps2esdi_lock);
 
diff -urN linux-2.5.64-bk3/drivers/block/rd.c linux-2.5.64-bk4/drivers/block/rd.c
--- linux-2.5.64-bk3/drivers/block/rd.c	Tue Mar  4 19:29:24 2003
+++ linux-2.5.64-bk4/drivers/block/rd.c	Mon Mar 31 12:25:45 2003
@@ -409,8 +409,7 @@
 			goto out;
 	}
 
-	if (register_blkdev(RAMDISK_MAJOR, "ramdisk", &rd_bd_op)) {
-		printk("RAMDISK: Could not get major %d", RAMDISK_MAJOR);
+	if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) {
 		err = -EIO;
 		goto out;
 	}
diff -urN linux-2.5.64-bk3/drivers/block/swim3.c linux-2.5.64-bk4/drivers/block/swim3.c
--- linux-2.5.64-bk3/drivers/block/swim3.c	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk4/drivers/block/swim3.c	Mon Mar 31 12:25:45 2003
@@ -1004,9 +1004,7 @@
 			goto out;
 	}
 
-	if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) {
-		printk(KERN_ERR"Unable to get major %d for floppy\n",
-				FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR, "fd")) {
 		err = -EBUSY;
 		goto out;
 	}
diff -urN linux-2.5.64-bk3/drivers/block/swim_iop.c linux-2.5.64-bk4/drivers/block/swim_iop.c
--- linux-2.5.64-bk3/drivers/block/swim_iop.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk4/drivers/block/swim_iop.c	Mon Mar 31 12:25:45 2003
@@ -137,13 +137,12 @@
 	current_req = NULL;
 	floppy_count = 0;
 
-	if (!iop_ism_present) return -ENODEV;
+	if (!iop_ism_present)
+		return -ENODEV;
 
-	if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) {
-		printk(KERN_ERR "SWIM-IOP: Unable to get major %d for floppy\n",
-		       FLOPPY_MAJOR);
+	if (register_blkdev(FLOPPY_MAJOR, "fd"))
 		return -EBUSY;
-	}
+
 	blk_init_queue(&swim_queue, do_fd_request, &swim_iop_lock);
 	printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n",
 		DRIVER_VERSION);
diff -urN linux-2.5.64-bk3/drivers/block/umem.c linux-2.5.64-bk4/drivers/block/umem.c
--- linux-2.5.64-bk3/drivers/block/umem.c	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/drivers/block/umem.c	Mon Mar 31 12:25:45 2003
@@ -1145,11 +1145,9 @@
 	if (retval)
 		return -ENOMEM;
 
-	err = major_nr = register_blkdev(0, "umem", &mm_fops);
-	if (err < 0) {
-		printk(KERN_ERR "MM: Could not register block device\n");
+	err = major_nr = register_blkdev(0, "umem");
+	if (err < 0)
 		return -EIO;
-	}
 
 	for (i = 0; i < num_cards; i++) {
 		mm_gendisk[i] = alloc_disk(1 << MM_SHIFT);
diff -urN linux-2.5.64-bk3/drivers/block/xd.c linux-2.5.64-bk4/drivers/block/xd.c
--- linux-2.5.64-bk3/drivers/block/xd.c	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/drivers/block/xd.c	Mon Mar 31 12:25:45 2003
@@ -154,9 +154,9 @@
 
 #ifdef MODULE
 	for (i = 4; i > 0; i--)
-		if(((xd[i] = xd[i-1]) >= 0) && !count)
+		if (((xd[i] = xd[i-1]) >= 0) && !count)
 			count = i;
-	if((xd[0] = count))
+	if ((xd[0] = count))
 		do_xd_setup(xd);
 #endif
 
@@ -170,10 +170,9 @@
 	}
 
 	err = -EBUSY;
-	if (register_blkdev(XT_DISK_MAJOR,"xd",&xd_fops)) {
-		printk("xd: Unable to get major number %d\n",XT_DISK_MAJOR);
+	if (register_blkdev(XT_DISK_MAJOR, "xd"))
 		goto out1;
-	}
+
 	devfs_mk_dir(NULL, "xd", NULL);
 	blk_init_queue(&xd_queue, do_xd_request, &xd_lock);
 	if (xd_detect(&controller,&address)) {
diff -urN linux-2.5.64-bk3/drivers/block/z2ram.c linux-2.5.64-bk4/drivers/block/z2ram.c
--- linux-2.5.64-bk3/drivers/block/z2ram.c	Tue Mar  4 19:29:29 2003
+++ linux-2.5.64-bk4/drivers/block/z2ram.c	Mon Mar 31 12:25:45 2003
@@ -331,21 +331,18 @@
 static struct request_queue z2_queue;
 
 int __init 
-z2_init( void )
+z2_init(void)
 {
 
-    if ( !MACH_IS_AMIGA )
+    if (!MACH_IS_AMIGA)
 	return -ENXIO;
 
-    if ( register_blkdev( Z2RAM_MAJOR, DEVICE_NAME, &z2_fops ) )
-    {
-	printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n",
-	    Z2RAM_MAJOR );
+    if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME))
 	return -EBUSY;
-    }
+
     z2ram_gendisk = alloc_disk(1);
     if (!z2ram_gendisk) {
-	unregister_blkdev( Z2RAM_MAJOR, DEVICE_NAME );
+	unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
 	return -ENOMEM;
     }
     z2ram_gendisk->major = Z2RAM_MAJOR;
diff -urN linux-2.5.64-bk3/drivers/cdrom/aztcd.c linux-2.5.64-bk4/drivers/cdrom/aztcd.c
--- linux-2.5.64-bk3/drivers/cdrom/aztcd.c	Tue Mar  4 19:29:37 2003
+++ linux-2.5.64-bk4/drivers/cdrom/aztcd.c	Mon Mar 31 12:25:45 2003
@@ -1910,12 +1910,12 @@
 	azt_disk = alloc_disk(1);
 	if (!azt_disk)
 		goto err_out;
-	if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) {
-		printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech"
-		       " CD-ROM\n", MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR, "aztcd")) {
 		ret = -EIO;
 		goto err_out2;
 	}
+
 	blk_init_queue(&azt_queue, do_aztcd_request, &aztSpin);
 	blk_queue_hardsect_size(&azt_queue, 2048);
 	azt_disk->major = MAJOR_NR;
@@ -1931,7 +1931,7 @@
 	azt_invalidate_buffers();
 	aztPresent = 1;
 	aztCloseDoor();
-	return (0);
+	return 0;
 err_out2:
 	put_disk(azt_disk);
 err_out:
diff -urN linux-2.5.64-bk3/drivers/cdrom/cdu31a.c linux-2.5.64-bk4/drivers/cdrom/cdu31a.c
--- linux-2.5.64-bk3/drivers/cdrom/cdu31a.c	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk4/drivers/cdrom/cdu31a.c	Mon Mar 31 12:25:45 2003
@@ -3368,11 +3368,8 @@
 	if (!request_region(cdu31a_port, 4, "cdu31a"))
 		goto errout3;
 
-	if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) {
-		printk("Unable to get major %d for CDU-31a\n",
-		       MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "cdu31a"))
 		goto errout2;
-	}
 
 	disk = alloc_disk(1);
 	if (!disk)
diff -urN linux-2.5.64-bk3/drivers/cdrom/cm206.c linux-2.5.64-bk4/drivers/cdrom/cm206.c
--- linux-2.5.64-bk3/drivers/cdrom/cm206.c	Tue Mar  4 19:29:35 2003
+++ linux-2.5.64-bk4/drivers/cdrom/cm206.c	Mon Mar 31 12:25:45 2003
@@ -1489,10 +1489,10 @@
 		goto out_probe;
 	}
 	printk(".\n");
-	if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) {
-		printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR, "cm206"))
 		goto out_blkdev;
-	}
+
 	disk = alloc_disk(1);
 	if (!disk)
 		goto out_disk;
diff -urN linux-2.5.64-bk3/drivers/cdrom/gscd.c linux-2.5.64-bk4/drivers/cdrom/gscd.c
--- linux-2.5.64-bk3/drivers/cdrom/gscd.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk4/drivers/cdrom/gscd.c	Mon Mar 31 12:25:45 2003
@@ -959,12 +959,11 @@
 	gscd_disk->fops = &gscd_fops;
 	sprintf(gscd_disk->disk_name, "gscd");
 
-	if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
-		printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar "
-		       "CD-ROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "gscd")) {
 		ret = -EIO;
 		goto err_out2;
 	}
+
 	devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
 		       S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
 
diff -urN linux-2.5.64-bk3/drivers/cdrom/mcd.c linux-2.5.64-bk4/drivers/cdrom/mcd.c
--- linux-2.5.64-bk3/drivers/cdrom/mcd.c	Tue Mar  4 19:29:24 2003
+++ linux-2.5.64-bk4/drivers/cdrom/mcd.c	Mon Mar 31 12:25:45 2003
@@ -1068,8 +1068,7 @@
 		put_disk(disk);
 		return -EIO;
 	}
-	if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) {
-		printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "mcd")) {
 		put_disk(disk);
 		return -EIO;
 	}
diff -urN linux-2.5.64-bk3/drivers/cdrom/mcdx.c linux-2.5.64-bk4/drivers/cdrom/mcdx.c
--- linux-2.5.64-bk3/drivers/cdrom/mcdx.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/drivers/cdrom/mcdx.c	Mon Mar 31 12:25:45 2003
@@ -1193,11 +1193,9 @@
 	}
 
 	xtrace(INIT, "init() register blkdev\n");
-	if (register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) {
+	if (register_blkdev(MAJOR_NR, "mcdx")) {
 		release_region((unsigned long) stuffp->wreg_data,
 			       MCDX_IO_SIZE);
-		xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR);
 		kfree(stuffp);
 		put_disk(disk);
 		return 1;
diff -urN linux-2.5.64-bk3/drivers/cdrom/optcd.c linux-2.5.64-bk4/drivers/cdrom/optcd.c
--- linux-2.5.64-bk3/drivers/cdrom/optcd.c	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/drivers/cdrom/optcd.c	Mon Mar 31 12:25:45 2003
@@ -2047,8 +2047,7 @@
 		put_disk(optcd_disk);
 		return -EIO;
 	}
-	if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) {
-		printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "optcd")) {
 		release_region(optcd_port, 4);
 		put_disk(optcd_disk);
 		return -EIO;
diff -urN linux-2.5.64-bk3/drivers/cdrom/sbpcd.c linux-2.5.64-bk4/drivers/cdrom/sbpcd.c
--- linux-2.5.64-bk3/drivers/cdrom/sbpcd.c	Tue Mar  4 19:29:00 2003
+++ linux-2.5.64-bk4/drivers/cdrom/sbpcd.c	Mon Mar 31 12:25:45 2003
@@ -5795,15 +5795,14 @@
 	OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
 #endif /* SOUND_BASE */
 
-	if (register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0)
-	{
-		msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, major_name)) {
 #ifdef MODULE
 		return -EIO;
 #else
 		goto init_done;
 #endif /* MODULE */
 	}
+
 	blk_init_queue(&sbpcd_queue, do_sbpcd_request, &sbpcd_lock);
 
 	devfs_mk_dir (NULL, "sbp", NULL);
diff -urN linux-2.5.64-bk3/drivers/cdrom/sjcd.c linux-2.5.64-bk4/drivers/cdrom/sjcd.c
--- linux-2.5.64-bk3/drivers/cdrom/sjcd.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/drivers/cdrom/sjcd.c	Mon Mar 31 12:25:45 2003
@@ -1677,11 +1677,8 @@
 	printk("SJCD: sjcd=0x%x: ", sjcd_base);
 #endif
 
-	if (register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {
-		printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n",
-		       MAJOR_NR);
-		return (-EIO);
-	}
+	if (register_blkdev(MAJOR_NR, "sjcd"))
+		return -EIO;
 
 	blk_init_queue(&sjcd_queue, do_sjcd_request, &sjcd_lock);
 	blk_queue_hardsect_size(&sjcd_queue, 2048);
diff -urN linux-2.5.64-bk3/drivers/cdrom/sonycd535.c linux-2.5.64-bk4/drivers/cdrom/sonycd535.c
--- linux-2.5.64-bk3/drivers/cdrom/sonycd535.c	Tue Mar  4 19:29:15 2003
+++ linux-2.5.64-bk4/drivers/cdrom/sonycd535.c	Mon Mar 31 12:25:45 2003
@@ -1546,9 +1546,7 @@
 		printk("IRQ%d, ", tmp_irq);
 	printk("using %d byte buffer\n", sony_buffer_size);
 
-	if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
-		printk("Unable to get major %d for %s\n",
-				MAJOR_NR, CDU535_MESSAGE_NAME);
+	if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
 		err = -EIO;
 		goto out1;
 	}
diff -urN linux-2.5.64-bk3/drivers/char/raw.c linux-2.5.64-bk4/drivers/char/raw.c
--- linux-2.5.64-bk3/drivers/char/raw.c	Tue Mar  4 19:29:24 2003
+++ linux-2.5.64-bk4/drivers/char/raw.c	Mon Mar 31 12:25:45 2003
@@ -19,14 +19,16 @@
 
 #include <asm/uaccess.h>
 
+#define MAX_RAW_MINORS	256
+
 struct raw_device_data {
 	struct block_device *binding;
 	int inuse;
 };
 
-static struct raw_device_data raw_devices[256];
+static struct raw_device_data raw_devices[MAX_RAW_MINORS];
 static DECLARE_MUTEX(raw_mutex);
-static struct file_operations raw_ctl_fops;
+static struct file_operations raw_ctl_fops;	     /* forward declaration */
 
 /*
  * Open/close code for raw IO.
@@ -85,11 +87,16 @@
 {
 	const int minor= minor(inode->i_rdev);
 	struct block_device *bdev;
-	
+
 	down(&raw_mutex);
 	bdev = raw_devices[minor].binding;
 	raw_devices[minor].inuse--;
 	up(&raw_mutex);
+
+	/* Here  inode->i_mapping == bdev->bd_inode->i_mapping  */
+	inode->i_mapping = &inode->i_data;
+	inode->i_mapping->backing_dev_info = &default_backing_dev_info;
+	
 	bd_release(bdev);
 	blkdev_put(bdev, BDEV_RAW);
 	return 0;
@@ -130,11 +137,13 @@
 			goto out;
 		
 		err = -EINVAL;
-		if (rq.raw_minor < 0 || rq.raw_minor > MINORMASK)
+		if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS)
 			goto out;
 		rawdev = &raw_devices[rq.raw_minor];
 
 		if (command == RAW_SETBIND) {
+			dev_t dev;
+
 			/*
 			 * This is like making block devices, so demand the
 			 * same capability
@@ -151,9 +160,10 @@
 			 */
 
 			err = -EINVAL;
+			dev = MKDEV(rq.block_major, rq.block_minor);
 			if ((rq.block_major == 0 && rq.block_minor != 0) ||
-					rq.block_major > MAX_BLKDEV ||
-					rq.block_minor > MINORMASK)
+			    MAJOR(dev) != rq.block_major ||
+			    MINOR(dev) != rq.block_minor)
 				goto out;
 			
 			down(&raw_mutex);
@@ -170,10 +180,7 @@
 				/* unbind */
 				rawdev->binding = NULL;
 			} else {
-				kdev_t kdev;
-
-				kdev = mk_kdev(rq.block_major, rq.block_minor);
-				rawdev->binding = bdget(kdev_t_to_nr(kdev));
+				rawdev->binding = bdget(dev);
 				MOD_INC_USE_COUNT;
 			}
 			up(&raw_mutex);
diff -urN linux-2.5.64-bk3/drivers/char/watchdog/amd7xx_tco.c linux-2.5.64-bk4/drivers/char/watchdog/amd7xx_tco.c
--- linux-2.5.64-bk3/drivers/char/watchdog/amd7xx_tco.c	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/drivers/char/watchdog/amd7xx_tco.c	Mon Mar 31 12:25:45 2003
@@ -1,6 +1,6 @@
 /*
  *	AMD 766/768 TCO Timer Driver
- *	(c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
+ *	(c) Copyright 2002 Zwane Mwaikambo <zwane@holomorphy.com>
  *	All Rights Reserved.
  *
  *	Parts from;
@@ -34,35 +34,48 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 
-#define AMDTCO_MODULE_VER	"build 20020601"
+#define AMDTCO_MODULE_VER	"build 20021116"
 #define AMDTCO_MODULE_NAME	"amd7xx_tco"
 #define PFX			AMDTCO_MODULE_NAME ": "
 
-#define	MAX_TIMEOUT	38	/* max of 38 seconds */
+#define	MAX_TIMEOUT	38	/* max of 38 seconds, although the system will only
+				 * reset itself after the second timeout */
 
 /* pmbase registers */
-#define GLOBAL_SMI_REG	0x2a
-#define TCO_EN		(1 << 1)	/* bit 1 in global SMI register */
 #define TCO_RELOAD_REG	0x40		/* bits 0-5 are current count, 6-7 are reserved */
 #define TCO_INITVAL_REG	0x41		/* bits 0-5 are value to load, 6-7 are reserved */
 #define TCO_TIMEOUT_MASK	0x3f
+#define TCO_STATUS1_REG 0x44
 #define TCO_STATUS2_REG	0x46
 #define NDTO_STS2	(1 << 1)	/* we're interested in the second timeout */ 
 #define BOOT_STS	(1 << 2)	/* will be set if NDTO_STS2 was set before reboot */
 #define TCO_CTRL1_REG	0x48
 #define TCO_HALT	(1 << 11)
+#define NO_REBOOT	(1 << 10)	/* in DevB:3x48 */
 
-static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER;
-static int timeout = 38;
+static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n";
+static int timeout = MAX_TIMEOUT;
 static u32 pmbase;		/* PMxx I/O base */
 static struct pci_dev *dev;
 static struct semaphore open_sem;
-spinlock_t amdtco_lock;	/* only for device access */
+static spinlock_t amdtco_lock;	/* only for device access */
 static int expect_close = 0;
 
 MODULE_PARM(timeout, "i");
 MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38");
 
+static inline u8 seconds_to_ticks(int seconds)
+{
+	/* the internal timer is stored as ticks which decrement
+	 * every 0.6 seconds */
+	return (seconds * 10) / 6;
+}
+
+static inline int ticks_to_seconds(u8 ticks)
+{
+	return (ticks * 6) / 10;
+}
+
 static inline int amdtco_status(void)
 {
 	u16 reg;
@@ -81,28 +94,19 @@
 
 static inline void amdtco_ping(void)
 {
-	u8 reg;
-
-	spin_lock(&amdtco_lock);
-	reg = inb(pmbase+TCO_RELOAD_REG);
-	outb(1 | reg, pmbase+TCO_RELOAD_REG);
-	spin_unlock(&amdtco_lock);
+	outb(1, pmbase+TCO_RELOAD_REG);
 }
 
 static inline int amdtco_gettimeout(void)
 {
-	return inb(TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
+	u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
+	return ticks_to_seconds(reg);
 }
 
 static inline void amdtco_settimeout(unsigned int timeout)
 {
-	u8 reg;
-
-	spin_lock(&amdtco_lock);
-	reg = inb(pmbase+TCO_INITVAL_REG);
-	reg |= timeout & TCO_TIMEOUT_MASK;
+	u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK;
 	outb(reg, pmbase+TCO_INITVAL_REG);
-	spin_unlock(&amdtco_lock);
 }
 
 static inline void amdtco_global_enable(void)
@@ -110,9 +114,12 @@
 	u16 reg;
 
 	spin_lock(&amdtco_lock);
-	reg = inw(pmbase+GLOBAL_SMI_REG);
-	reg |= TCO_EN;
-	outw(reg, pmbase+GLOBAL_SMI_REG);
+
+	/* clear NO_REBOOT on DevB:3x48 p97 */
+	pci_read_config_word(dev, 0x48, &reg);
+	reg &= ~NO_REBOOT;
+	pci_write_config_word(dev, 0x48, reg);
+
 	spin_unlock(&amdtco_lock);
 }
 
@@ -146,10 +153,12 @@
 	if (timeout > MAX_TIMEOUT)
 		timeout = MAX_TIMEOUT;
 
+	amdtco_disable();
 	amdtco_settimeout(timeout);	
 	amdtco_global_enable();
+	amdtco_enable();
 	amdtco_ping();
-	printk(KERN_INFO PFX "Watchdog enabled, timeout = %d/%d seconds",
+	printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n",
 		amdtco_gettimeout(), timeout);
 	
 	return 0;
@@ -198,7 +207,7 @@
 
 		case WDIOC_GETTIMEOUT:
 			return put_user(amdtco_gettimeout(), (int *)arg);
-	
+		
 		case WDIOC_SETOPTIONS:
 			if (copy_from_user(&tmp, (int *)arg, sizeof tmp))
                                 return -EFAULT;
@@ -221,7 +230,7 @@
 		printk(KERN_INFO PFX "Watchdog disabled\n");
 	} else {
 		amdtco_ping();
-		printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds)\n", timeout);
+		printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout);
 	}	
 	
 	up(&open_sem);
@@ -249,10 +258,9 @@
 		}
 #endif
 		amdtco_ping();
-		return len;
 	}
 
-	return 0;
+	return len;
 }
 
 
@@ -357,6 +365,9 @@
 	if (ints[0] > 0)
 		timeout = ints[1];
 
+	if (!timeout || timeout > MAX_TIMEOUT)
+		timeout = MAX_TIMEOUT;
+
 	return 1;
 }
 
@@ -366,8 +377,7 @@
 module_init(amdtco_init);
 module_exit(amdtco_exit);
 
-MODULE_AUTHOR("Zwane Mwaikambo <zwane@commfireservices.com>");
+MODULE_AUTHOR("Zwane Mwaikambo <zwane@holomorphy.com>");
 MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver");
 MODULE_LICENSE("GPL");
-EXPORT_NO_SYMBOLS;
 
diff -urN linux-2.5.64-bk3/drivers/ide/ide-probe.c linux-2.5.64-bk4/drivers/ide/ide-probe.c
--- linux-2.5.64-bk3/drivers/ide/ide-probe.c	Tue Mar  4 19:29:23 2003
+++ linux-2.5.64-bk4/drivers/ide/ide-probe.c	Mon Mar 31 12:25:45 2003
@@ -1292,11 +1292,8 @@
 	/* we set it back to 1 if all is ok below */	
 	hwif->present = 0;
 
-	if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
-		printk("%s: UNABLE TO GET MAJOR NUMBER %d\n",
-			hwif->name, hwif->major);
+	if (register_blkdev(hwif->major, hwif->name))
 		return 0;
-	}
 
 	if (alloc_disks(hwif) < 0)
 		goto out;
diff -urN linux-2.5.64-bk3/drivers/ide/legacy/hd.c linux-2.5.64-bk4/drivers/ide/legacy/hd.c
--- linux-2.5.64-bk3/drivers/ide/legacy/hd.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk4/drivers/ide/legacy/hd.c	Mon Mar 31 12:25:45 2003
@@ -708,10 +708,10 @@
 static int __init hd_init(void)
 {
 	int drive;
-	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
-		printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
+
+	if (register_blkdev(MAJOR_NR,"hd"))
 		return -1;
-	}
+
 	blk_init_queue(&hd_queue, do_hd_request, &hd_lock);
 	blk_queue_max_sectors(&hd_queue, 255);
 	init_timer(&device_timer);
diff -urN linux-2.5.64-bk3/drivers/isdn/hardware/avm/b1pci.c linux-2.5.64-bk4/drivers/isdn/hardware/avm/b1pci.c
--- linux-2.5.64-bk3/drivers/isdn/hardware/avm/b1pci.c	Tue Mar  4 19:28:55 2003
+++ linux-2.5.64-bk4/drivers/isdn/hardware/avm/b1pci.c	Mon Mar 31 12:25:45 2003
@@ -343,12 +343,16 @@
 
 static void __devexit b1pci_pci_remove(struct pci_dev *pdev)
 {
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 	avmcard *card = pci_get_drvdata(pdev);
 
 	if (card->dma)
 		b1pciv4_remove(pdev);
 	else
 		b1pci_remove(pdev);
+#else
+	b1pci_remove(pdev);
+#endif
 }
 
 static struct pci_driver b1pci_pci_driver = {
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/amd7930.c linux-2.5.64-bk4/drivers/isdn/hisax/amd7930.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/amd7930.c	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/amd7930.c	Wed Dec 31 16:00:00 1969
@@ -1,717 +0,0 @@
-/* $Id: amd7930.c,v 1.5.6.4 2001/09/23 22:24:46 kai Exp $
- *
- * HiSax ISDN driver - chip specific routines for AMD 7930
- *
- * Author       Brent Baccala
- * Copyright    by Brent Baccala <baccala@FreeSoft.org>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- *    - Existing ISDN HiSax driver provides all the smarts
- *    - it compiles, runs, talks to an isolated phone switch, connects
- *      to a Cisco, pings go through
- *    - AMD 7930 support only (no DBRI yet)
- *    - no US NI-1 support (may not work on US phone system - untested)
- *    - periodic packet loss, apparently due to lost interrupts
- *    - ISDN sometimes freezes, requiring reboot before it will work again
- *
- * The code is unreliable enough to be consider alpha
- *
- * This file is (c) under GNU General Public License
- *
- * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
- * SparcStation 1+.  The chip provides microphone and speaker interfaces
- * which provide mono-channel audio at 8K samples per second via either
- * 8-bit A-law or 8-bit mu-law encoding.  Also, the chip features an
- * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
- * which performs basic D channel LAPD processing and provides raw
- * B channel data.  The digital audio channel, the two ISDN B channels,
- * and two 64 Kbps channels to the microprocessor are all interconnected
- * via a multiplexer.
- *
- * This driver interfaces to the Linux HiSax ISDN driver, which performs
- * all high-level Q.921 and Q.931 ISDN functions.  The file is not
- * itself a hardware driver; rather it uses functions exported by
- * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio),
- * allowing the chip to be simultaneously used for both audio and ISDN data.
- * The hardware driver does _no_ buffering, but provides several callbacks
- * which are called during interrupt service and should therefore run quickly.
- *
- * D channel transmission is performed by passing the hardware driver the
- * address and size of an skb's data area, then waiting for a callback
- * to signal successful transmission of the packet.  A task is then
- * queued to notify the HiSax driver that another packet may be transmitted.
- *
- * D channel reception is quite simple, mainly because of:
- *   1) the slow speed of the D channel - 16 kbps, and
- *   2) the presence of an 8- or 32-byte (depending on chip version) FIFO
- *      to buffer the D channel data on the chip
- * Worst case scenario of back-to-back packets with the 8 byte buffer
- * at 16 kbps yields an service time of 4 ms - long enough to preclude
- * the need for fancy buffering.  We queue a background task that copies
- * data out of the receive buffer into an skb, and the hardware driver
- * simply does nothing until we're done with the receive buffer and
- * reset it for a new packet.
- *
- * B channel processing is more complex, because of:
- *   1) the faster speed - 64 kbps,
- *   2) the lack of any on-chip buffering (it interrupts for every byte), and
- *   3) the lack of any chip support for HDLC encapsulation
- *
- * The HiSax driver can put each B channel into one of three modes -
- * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay),
- * and L1_MODE_HDLC (HDLC encapsulation by low-level driver).
- * L1_MODE_HDLC is the most common, used for almost all "pure" digital
- * data sessions.  L1_MODE_TRANS is used for ISDN audio.
- *
- * HDLC B channel transmission is performed via a large buffer into
- * which the skb is copied while performing HDLC bit-stuffing.  A CRC
- * is computed and attached to the end of the buffer, which is then
- * passed to the low-level routines for raw transmission.  Once
- * transmission is complete, the hardware driver is set to enter HDLC
- * idle by successive transmission of mark (all 1) bytes, waiting for
- * the ISDN driver to prepare another packet for transmission and
- * deliver it.
- *
- * HDLC B channel reception is performed via an X-byte ring buffer
- * divided into N sections of X/N bytes each.  Defaults: X=256 bytes, N=4.
- * As the hardware driver notifies us that each section is full, we
- * hand it the next section and schedule a background task to peruse
- * the received section, bit-by-bit, with an HDLC decoder.  As
- * packets are detected, they are copied into a large buffer while
- * decoding HDLC bit-stuffing.  The ending CRC is verified, and if
- * it is correct, we alloc a new skb of the correct length (which we
- * now know), copy the packet into it, and hand it to the upper layers.
- * Optimization: for large packets, we hand the buffer (which also
- * happens to be an skb) directly to the upper layer after an skb_trim,
- * and alloc a new large buffer for future packets, thus avoiding a copy.
- * Then we return to HDLC processing; state is saved between calls.
- * 
- */
-
-#include "hisax.h"
-#include "../../sbus/audio/amd7930.h"
-#include "isac.h"
-#include "isdnl1.h"
-#include "rawhdlc.h"
-#include <linux/interrupt.h>
-
-static const char *amd7930_revision = "$Revision: 1.5.6.4 $";
-
-#define RCV_BUFSIZE	1024	/* Size of raw receive buffer in bytes */
-#define RCV_BUFBLKS	4	/* Number of blocks to divide buffer into
-				 * (must divide RCV_BUFSIZE) */
-
-static void Bchan_fill_fifo(struct BCState *, struct sk_buff *);
-
-static void
-Bchan_xmt_bh(void *data)
-{
-	struct BCState *bcs = data;
-	struct sk_buff *skb;
-
-	if (bcs->hw.amd7930.tx_skb != NULL) {
-		dev_kfree_skb(bcs->hw.amd7930.tx_skb);
-		bcs->hw.amd7930.tx_skb = NULL;
-	}
-	xmit_ready_b(bcs);
-}
-
-static void
-Bchan_xmit_callback(struct BCState *bcs)
-{
-	schedule_work(&bcs->hw.amd7930.xmt_work);
-}
-
-/* B channel transmission: two modes (three, if you count L1_MODE_NULL)
- *
- * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting
- * the packet (i.e. make_raw_hdlc_data).  Since this can be a
- * time-consuming operation, our completion callback just schedules
- * a bottom half to do encapsulation for the next packet.  In between,
- * the link will just idle
- *
- * L1_MODE_TRANS - Data goes through, well, transparent.  No HDLC encap,
- * and we can't just let the link idle, so the "bottom half" actually
- * gets called during the top half (it's our callback routine in this case),
- * but it's a lot faster now since we don't call make_raw_hdlc_data
- */
-
-static void
-Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	int len;
-
-	if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) {
-		char tmp[1024];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930_fill_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', skb->len);
-		if (cs->debug & L1_DEB_HSCX_FIFO)
-			QuickHex(t, skb->data, skb->len);
-		debugl1(cs, tmp);
-	}
-
-	if (bcs->mode == L1_MODE_HDLC) {
-		len = make_raw_hdlc_data(skb->data, skb->len,
-					 bcs->hw.amd7930.tx_buff, RAW_BUFMAX);
-		if (len > 0)
-			amd7930_bxmit(0, bcs->channel,
-				      bcs->hw.amd7930.tx_buff, len,
-				      (void *) &Bchan_xmit_callback,
-				      (void *) bcs);
-		dev_kfree_skb(skb);
-	} else if (bcs->mode == L1_MODE_TRANS) {
-		amd7930_bxmit(0, bcs->channel,
-			      bcs->hw.amd7930.tx_buff, skb->len,
-			      (void *) &Bchan_xmt_bh,
-			      (void *) bcs);
-		bcs->hw.amd7930.tx_skb = skb;
-	} else {
-		dev_kfree_skb(skb);
-	}
-}
-
-static void
-Bchan_mode(struct BCState *bcs, int mode, int bc)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "AMD 7930 mode %d bchan %d/%d",
-			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
-	bcs->mode = mode;
-}
-
-/* Bchan_l2l1 is the entry point for upper layer routines that want to
- * transmit on the B channel.  PH_DATA_REQ is a normal packet that
- * we either start transmitting (if idle) or queue (if busy).
- * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF)
- * once the link is idle.  After a "pull" callback, the upper layer
- * routines can use PH_PULL_IND to send data.
- */
-
-static void
-Bchan_l2l1(struct PStack *st, int pr, void *arg)
-{
-	struct sk_buff *skb = arg;
-
-	switch (pr) {
-		case (PH_DATA_REQ):
-			if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-			} else {
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				Bchan_fill_fifo(st->l1.bcs, skb);
-			}
-			break;
-		case (PH_PULL_IND):
-			if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				printk(KERN_WARNING "amd7930: this shouldn't happen\n");
-				break;
-			}
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			Bchan_fill_fifo(st->l1.bcs, skb);
-			break;
-		case (PH_PULL_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
-			} else
-				set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-			break;
-	}
-}
-
-/* Receiver callback and bottom half - decodes HDLC at leisure (if
- * L1_MODE_HDLC) and passes newly received skb on via bcs->rqueue.  If
- * a large packet is received, stick rv_skb (the buffer that the
- * packet has been decoded into) on the receive queue and alloc a new
- * (large) skb to act as buffer for future receives.  If a small
- * packet is received, leave rv_skb alone, alloc a new skb of the
- * correct size, and copy the packet into it
- */
-
-static void
-Bchan_recv_callback(struct BCState *bcs)
-{
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-
-	hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS;
-	hw->rv_buff_in %= RCV_BUFSIZE;
-
-	if (hw->rv_buff_in != hw->rv_buff_out) {
-		amd7930_brecv(0, bcs->channel,
-			      hw->rv_buff + hw->rv_buff_in,
-			      RCV_BUFSIZE/RCV_BUFBLKS,
-			      (void *) &Bchan_recv_callback, (void *) bcs);
-	}
-
-	schedule_work(&hw->rcv_work);
-}
-
-static void
-Bchan_rcv_bh(void *data)
-{
-	struct BCState *bcs = data;
-	struct IsdnCardState *cs = bcs->cs;
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-	struct sk_buff *skb;
-	int len;
-
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[1024];
-
-		sprintf(tmp, "amd7930_Bchan_rcv (%d/%d)",
-			hw->rv_buff_in, hw->rv_buff_out);
-		debugl1(cs, tmp);
-		QuickHex(tmp, hw->rv_buff + hw->rv_buff_out,
-			 RCV_BUFSIZE/RCV_BUFBLKS);
-		debugl1(cs, tmp);
-	}
-
-	do {
-		if (bcs->mode == L1_MODE_HDLC) {
-			while ((len = read_raw_hdlc_data(hw->hdlc_state,
-							 hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS,
-							 hw->rv_skb->tail, HSCX_BUFMAX))) {
-				if (len > 0 && (cs->debug & L1_DEB_HSCX_FIFO)) {
-					char tmp[1024];
-					char *t = tmp;
-
-					t += sprintf(t, "amd7930_Bchan_rcv %c cnt %d", bcs->channel ? 'B' : 'A', len);
-					QuickHex(t, hw->rv_skb->tail, len);
-					debugl1(cs, tmp);
-				}
-
-				if (len > HSCX_BUFMAX/2) {
-					/* Large packet received */
-
-					if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) {
-						printk(KERN_WARNING "amd7930: receive out of memory");
-					} else {
-						skb_put(hw->rv_skb, len);
-						skb_queue_tail(&bcs->rqueue, hw->rv_skb);
-						hw->rv_skb = skb;
-						bcs->event |= 1 << B_RCVBUFREADY;
-						schedule_work(&bcs->work);
-					}
-				} else if (len > 0) {
-					/* Small packet received */
-
-					if (!(skb = dev_alloc_skb(len))) {
-						printk(KERN_WARNING "amd7930: receive out of memory\n");
-					} else {
-						memcpy(skb_put(skb, len), hw->rv_skb->tail, len);
-						skb_queue_tail(&bcs->rqueue, skb);
-						bcs->event |= 1 << B_RCVBUFREADY;
-						schedule_work(&bcs->work);
-					}
-				} else {
-					/* Reception Error */
-					/* printk("amd7930: B channel receive error\n"); */
-				}
-			}
-		} else if (bcs->mode == L1_MODE_TRANS) {
-			if (!(skb = dev_alloc_skb(RCV_BUFSIZE/RCV_BUFBLKS))) {
-				printk(KERN_WARNING "amd7930: receive out of memory\n");
-			} else {
-				memcpy(skb_put(skb, RCV_BUFSIZE/RCV_BUFBLKS),
-				       hw->rv_buff + hw->rv_buff_out,
-				       RCV_BUFSIZE/RCV_BUFBLKS);
-				skb_queue_tail(&bcs->rqueue, skb);
-				bcs->event |= 1 << B_RCVBUFREADY;
-				schedule_work(&bcs->work);
-			}
-		}
-
-		if (hw->rv_buff_in == hw->rv_buff_out) {
-			/* Buffer was filled up - need to restart receiver */
-			amd7930_brecv(0, bcs->channel,
-				      hw->rv_buff + hw->rv_buff_in,
-				      RCV_BUFSIZE/RCV_BUFBLKS,
-				      (void *) &Bchan_recv_callback,
-				      (void *) bcs);
-		}
-
-		hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS;
-		hw->rv_buff_out %= RCV_BUFSIZE;
-
-	} while (hw->rv_buff_in != hw->rv_buff_out);
-}
-
-static void
-Bchan_close(struct BCState *bcs)
-{
-	struct sk_buff *skb;
-
-	Bchan_mode(bcs, 0, 0);
-	amd7930_bclose(0, bcs->channel);
-
-	if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
-		skb_queue_purge(&bcs->rqueue);
-		skb_queue_purge(&bcs->squeue);
-	}
-	test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-}
-
-static int
-Bchan_open(struct BCState *bcs)
-{
-	struct amd7930_hw *hw = &bcs->hw.amd7930;
-
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-	}
-	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-
-	amd7930_bopen(0, bcs->channel, 0xff);
-	hw->rv_buff_in = 0;
-	hw->rv_buff_out = 0;
-	hw->tx_skb = NULL;
-	init_hdlc_state(hw->hdlc_state, 0);
-	amd7930_brecv(0, bcs->channel,
-		      hw->rv_buff + hw->rv_buff_in, RCV_BUFSIZE/RCV_BUFBLKS,
-		      (void *) &Bchan_recv_callback, (void *) bcs);
-
-	bcs->event = 0;
-	bcs->tx_cnt = 0;
-	return (0);
-}
-
-static void
-Bchan_init(struct BCState *bcs)
-{
-	if (!(bcs->hw.amd7930.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.tx_buff\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.rv_buff\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.rv_skb\n");
-		return;
-	}
-	if (!(bcs->hw.amd7930.hdlc_state = kmalloc(sizeof(struct hdlc_state),
-						   GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for amd7930.hdlc_state\n");
-		return;
-	}
-
-	INIT_WORK(&bcs->hw.amd7930.rcv_work, &Bchan_rcv_bh, bcs);
-	INIT_WORK(&bcs->hw.amd7930.xmt_work, &Bchan_xmt_bh, bcs);
-}
-
-static void
-Bchan_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				Bchan_mode(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
-int
-setstack_amd7930(struct PStack *st, struct BCState *bcs)
-{
-	if (Bchan_open(bcs))
-		return (-1);
-	st->l1.bcs = bcs;
-	st->l2.l2l1 = Bchan_l2l1;
-	st->ma.manl1 = Bchan_manl1;
-	setstack_manager(st);
-	bcs->st = st;
-	return (0);
-}
-
-
-static void
-amd7930_drecv_callback(void *arg, int error, unsigned int count)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct work_struct task;
-	struct sk_buff *skb;
-
-        /* NOTE: This function is called directly from an interrupt handler */
-
-	if (1) {
-		if (!(skb = alloc_skb(count, GFP_ATOMIC)))
-			printk(KERN_WARNING "HiSax: D receive out of memory\n");
-		else {
-			memcpy(skb_put(skb, count), cs->rcvbuf, count);
-			skb_queue_tail(&cs->rq, skb);
-		}
-
-		INIT_WORK(&task, (void *) DChannel_proc_rcv, (void *) cs);
-		schedule_work(&task);
-	}
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930 Drecv cnt %d", count);
-		if (error) t += sprintf(t, " ERR %x", error);
-		QuickHex(t, cs->rcvbuf, count);
-		debugl1(cs, tmp);
-	}
-
-	amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
-		      &amd7930_drecv_callback, cs);
-}
-
-static void
-amd7930_dxmit_callback(void *arg, int error)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct work_struct task;
-
-        /* NOTE: This function is called directly from an interrupt handler */
-
-	/* may wish to do retransmission here, if error indicates collision */
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
-
-		t += sprintf(t, "amd7930 Dxmit cnt %d", cs->tx_skb->len);
-		if (error) t += sprintf(t, " ERR %x", error);
-		QuickHex(t, cs->tx_skb->data, cs->tx_skb->len);
-		debugl1(cs, tmp);
-	}
-
-	cs->tx_skb = NULL;
-
-	INIT_WORK(&task, (void *) DChannel_proc_xmt, (void *) cs);
-	schedule_work(&task);
-}
-
-static void
-amd7930_Dchan_l2l1(struct PStack *st, int pr, void *arg)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
-	struct sk_buff *skb = arg;
-	char str[64];
-
-	switch (pr) {
-		case (PH_DATA_REQ):
-			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 {
-				if ((cs->dlogflag) && (!(skb->data[2] & 1))) {
-					/* I-FRAME */
-					LogFrame(cs, skb->data, skb->len);
-					sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-					dlogframe(cs, skb->data+4, skb->len-4,
-						  str);
-				}
-				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
-				amd7930_dxmit(0, skb->data, skb->len,
-					      &amd7930_dxmit_callback, cs);
-			}
-			break;
-		case (PH_PULL_IND):
-			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->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
-				LogFrame(cs, skb->data, skb->len);
-				sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-				dlogframe(cs, skb->data + 4, skb->len - 4,
-					  str);
-			}
-			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
-			amd7930_dxmit(0, cs->tx_skb->data, cs->tx_skb->len,
-				      &amd7930_dxmit_callback, cs);
-			break;
-		case (PH_PULL_REQ):
-#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);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-			break;
-	}
-}
-
-int
-setDstack_amd7930(struct PStack *st, struct IsdnCardState *cs)
-{
-	st->l2.l2l1 = amd7930_Dchan_l2l1;
-	if (! cs->rcvbuf) {
-		printk("setDstack_amd7930: No cs->rcvbuf!\n");
-	} else {
-		amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
-			      &amd7930_drecv_callback, cs);
-	}
-	return (0);
-}
-
-static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
-	struct PStack *st;
-
-	st = cs->stlist;
-	while (st) {
-		st->ma.manl1(st, msg, arg);
-		st = st->next;
-	}
-}
-
-static void
-amd7930_new_ph(struct IsdnCardState *cs)
-{
-	switch (amd7930_get_liu_state(0)) {
-	        case 3:
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
-                        break;
-
-	        case 7:
-			manl1_msg(cs, PH_I4_P8_IND, NULL);
-			break;
-
-	        case 8:
-			manl1_msg(cs, PH_RSYNC_IND, NULL);
-			break;
-	}
-}
-
-/* amd7930 LIU state change callback */
-
-static void
-amd7930_liu_callback(struct IsdnCardState *cs)
-{
-	static struct work_struct task;
-
-	if (!cs)
-		return;
-
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "amd7930_liu state %d", amd7930_get_liu_state(0));
-		debugl1(cs, tmp);
-	}
-
-	INIT_WORK(&task, (void *) &amd7930_new_ph, (void *) cs);
-	schedule_work(&task);
-}
-
-void
-amd7930_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
-	u8 val;
-	char tmp[32];
-	
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "amd7930_l1cmd msg %x", msg);
-		debugl1(cs, tmp);
-	}
-
-	switch(msg) {
-		case PH_RESET_REQ:
-			if (amd7930_get_liu_state(0) <= 3)
-				amd7930_liu_activate(0,0);
-			else
-				amd7930_liu_deactivate(0);
-			break;
-		case PH_ENABLE_REQ:
-			break;
-		case PH_INFO3_REQ:
-			amd7930_liu_activate(0,0);
-			break;
-		case PH_TESTLOOP_REQ:
-			break;
-		default:
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "amd7930_l1cmd unknown %4x", msg);
-				debugl1(cs, tmp);
-			}
-			break;
-	}
-}
-
-static void init_amd7930(struct IsdnCardState *cs)
-{
-	Bchan_init(&cs->bcs[0]);
-	Bchan_init(&cs->bcs[1]);
-	cs->bcs[0].BC_SetStack = setstack_amd7930;
-	cs->bcs[1].BC_SetStack = setstack_amd7930;
-	cs->bcs[0].BC_Close = Bchan_close;
-	cs->bcs[1].BC_Close = Bchan_close;
-	Bchan_mode(cs->bcs, 0, 0);
-	Bchan_mode(cs->bcs + 1, 0, 0);
-}
-
-static int
-amd7930_init(struct IsdnCardState *cs)
-{
-	cs->l1cmd = amd7930_l1cmd;
-	amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
-	init_amd7930(cs);
-	return 0;
-}
-
-static struct card_ops amd7930_ops = {
-	.init     = amd7930_init,
-};
-
-int __init
-setup_amd7930(struct IsdnCard *card)
-{
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, amd7930_revision);
-	printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp));
-
-        cs->irq = amd7930_get_irqnum(0);
-        if (cs->irq == 0)
-		return 0;
-
-	cs->card_ops = &amd7930_ops;
-	return 1;
-}
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/asuscom.c linux-2.5.64-bk4/drivers/isdn/hisax/asuscom.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/asuscom.c	Tue Mar  4 19:29:55 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/asuscom.c	Mon Mar 31 12:25:45 2003
@@ -231,6 +231,51 @@
 	.irq_func = ipac_irq,
 };
 
+static int __init
+asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	u8 val;
+
+	printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
+
+	cs->hw.asus.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn"))
+		goto err;
+
+	rc = -ENODEV;
+	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
+	val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
+	if ((val == 1) || (val == 2)) {
+		cs->subtyp = ASUS_IPAC;
+		cs->card_ops = &asuscom_ipac_ops;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
+	} else {
+		cs->subtyp = ASUS_ISACHSCX;
+		cs->card_ops = &asuscom_ops;
+		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
+		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
+		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
+	}
+	printk(KERN_INFO "ISDNLink: resetting card\n");
+	cs->card_ops->reset(cs);
+	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id asus_ids[] __initdata = {
 	{ ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
@@ -255,9 +300,6 @@
 int __init
 setup_asuscom(struct IsdnCard *card)
 {
-	int bytecnt;
-	struct IsdnCardState *cs = card->cs;
-	u8 val;
 	char tmp[64];
 
 	strcpy(tmp, Asuscom_revision);
@@ -310,36 +352,7 @@
 		}
 	}
 #endif
-	bytecnt = 8;
-	cs->hw.asus.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-	if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn"))
-		goto err;
-	printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
-		cs->hw.asus.cfg_reg, cs->irq);
-	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
-	val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
-	if ((val == 1) || (val == 2)) {
-		cs->subtyp = ASUS_IPAC;
-		cs->card_ops = &asuscom_ipac_ops;
-		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else {
-		cs->subtyp = ASUS_ISACHSCX;
-		cs->card_ops = &asuscom_ops;
-		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
-		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
-		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
-		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
-		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
-	}
-	printk(KERN_INFO "ISDNLink: resetting card\n");
-	cs->card_ops->reset(cs);
+	if (asuscom_probe(card->cs, card) < 0)
+		return 0;
 	return 1;
- err:
-	hisax_release_resources(cs);
-	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/avm_a1.c linux-2.5.64-bk4/drivers/isdn/hisax/avm_a1.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/avm_a1.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/avm_a1.c	Mon Mar 31 12:25:45 2003
@@ -160,16 +160,16 @@
 	.irq_func = avm_a1_interrupt,
 };
 
-int __init
-setup_avm_a1(struct IsdnCard *card)
+static int __init
+avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
+	int rc;
 	u8 val;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
 
-	strcpy(tmp, avm_revision);
-	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
 
+	rc = -EBUSY;
 	cs->hw.avm.cfg_reg     = request_io(&cs->rs, card->para[1] + 0x1800,  8, "avm cfg");
 	if (!cs->hw.avm.cfg_reg) goto err;
 	cs->hw.avm.isac        = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac");
@@ -216,23 +216,24 @@
 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
 	       cs->hw.avm.cfg_reg, val);
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.avm.cfg_reg);
-	printk(KERN_INFO
-	       "HiSax: isac:0x%X/0x%X\n",
-	       cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
-	printk(KERN_INFO
-	       "HiSax: hscx A:0x%X/0x%X  hscx B:0x%X/0x%X\n",
-	       cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
-	       cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
-
 	cs->card_ops = &avm_a1_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return rc;
+}
+
+int __init
+setup_avm_a1(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (avm_a1_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/avm_a1p.c linux-2.5.64-bk4/drivers/isdn/hisax/avm_a1p.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/avm_a1p.c	Tue Mar  4 19:29:56 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/avm_a1p.c	Mon Mar 31 12:25:45 2003
@@ -215,20 +215,13 @@
 	.irq_func = avm_a1p_interrupt,
 };
 
-int __devinit
-setup_avm_a1_pcmcia(struct IsdnCard *card)
+static int __init
+avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
 	u8 model, vers;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
 
-
-	strcpy(tmp, avm_revision);
-	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
-	       HiSax_getrev(tmp));
-	cs->hw.avm.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
-
+	cs->hw.avm.cfg_reg = card->para[1];
 
 	outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
 
@@ -244,11 +237,26 @@
 	vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
 
 	printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
-				cs->hw.avm.cfg_reg, cs->irq, model, vers);
+	       cs->hw.avm.cfg_reg, cs->irq, model, vers);
 
 	cs->card_ops = &avm_a1p_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		return 0;
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __devinit
+setup_avm_a1_pcmcia(struct IsdnCard *card)
+{
+	char tmp[64];
 
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+	if (avm_a1p_probe(card->cs, card))
+		return 0;
 	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/avm_pci.c linux-2.5.64-bk4/drivers/isdn/hisax/avm_pci.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/avm_pci.c	Tue Mar  4 19:29:15 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/avm_pci.c	Mon Mar 31 12:25:45 2003
@@ -497,7 +497,7 @@
 	.close     = close_hdlcstate,
 };
 
-void __init
+static void __init
 inithdlc(struct IsdnCardState *cs)
 {
 	u_int val;
@@ -596,6 +596,82 @@
 	.irq_func = avm_pcipnp_interrupt,
 };
 
+static int __init
+avm_pcipnp_hw_init(struct IsdnCardState *cs)
+{
+	cs->bc_hw_ops = &hdlc_hw_ops;
+	cs->bc_l1_ops = &hdlc_l1_ops;
+	cs->card_ops = &avm_pci_ops;
+	avm_pcipnp_reset(cs);
+	return isac_setup(cs, &isac_ops);
+}
+
+static int __init
+avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	int rc;
+	u32 val;
+
+	printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n",
+	       pci_resource_start(pdev, 1), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp = AVM_FRITZ_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
+	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI"))
+		goto err;
+
+	val = inl(cs->hw.avm.cfg_reg);
+	printk(KERN_INFO "AVM PCI: stat %#x\n", val);
+	printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
+	       val & 0xff, (val>>8) & 0xff);
+
+	if (avm_pcipnp_hw_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
+static int __init
+avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	u8 val, ver;
+
+	printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n",
+	       card->para[1], card->para[0]);
+
+	cs->subtyp = AVM_FRITZ_PNP;
+	cs->irq = card->para[0];
+	cs->hw.avm.cfg_reg = card->para[1];
+	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP"))
+		goto err;
+	
+	val = inb(cs->hw.avm.cfg_reg);
+	ver = inb(cs->hw.avm.cfg_reg + 1);
+	printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
+
+	if (avm_pcipnp_hw_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 static struct pci_dev *dev_avm __initdata = NULL;
 #ifdef __ISAPNP__
 static struct pnp_card *card_avm __initdata = NULL;
@@ -605,17 +681,15 @@
 int __init
 setup_avm_pcipnp(struct IsdnCard *card)
 {
-	u_int val, ver;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, avm_pci_rev);
 	printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
 	if (card->para[1]) {
 		/* old manual method */
-		cs->hw.avm.cfg_reg = card->para[1];
-		cs->irq = card->para[0];
-		cs->subtyp = AVM_FRITZ_PNP;
+		if (avm_pnp_probe(card->cs, card))
+			return 0;
+		return 1;
 	} else {
 #ifdef __ISAPNP__
 		if (isapnp_present()) {
@@ -647,69 +721,24 @@
 						pnp_device_detach(pnp_avm);
 						return(0);
 					}
-					cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm, 0);
-					cs->irq = pnp_irq(pnp_avm, 0);
-					cs->subtyp = AVM_FRITZ_PNP;
-					goto ready;
+					card->para[1] = pnp_port_start(pnp_avm, 0);
+					card->para[0] = pnp_irq(pnp_avm, 0);
+					if (avm_pnp_probe(card->cs, card))
+						return 0;
+					return 1;
 				}
 			}
-		} else {
-			printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
 		}
 #endif
 #if CONFIG_PCI
 		if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
 			PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
-			cs->irq = dev_avm->irq;
-			if (!cs->irq) {
-				printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			if (pci_enable_device(dev_avm))
-				return(0);
-			cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
-			if (!cs->hw.avm.cfg_reg) {
-				printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = AVM_FRITZ_PCI;
-		} else {
-			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
-			return(0);
+			if (avm_pci_probe(card->cs, dev_avm))
+				return 0;
+			return 1;
 		}
-		cs->irq_flags |= SA_SHIRQ;
 #endif /* CONFIG_PCI */
 	}
-ready:
-	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
-	if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32,
-		 cs->subtyp == AVM_FRITZ_PCI ? "avm PCI" : "avm PnP"))
-		goto err;
-	
-	switch (cs->subtyp) {
-	  case AVM_FRITZ_PCI:
-		val = inl(cs->hw.avm.cfg_reg);
-		printk(KERN_INFO "AVM PCI: stat %#x\n", val);
-		printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
-			val & 0xff, (val>>8) & 0xff);
-		break;
-	  case AVM_FRITZ_PNP:
-		val = inb(cs->hw.avm.cfg_reg);
-		ver = inb(cs->hw.avm.cfg_reg + 1);
-		printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
-		avm_pcipnp_reset(cs);
-		break;
-	}
-	printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
-		(cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
-		cs->irq, cs->hw.avm.cfg_reg);
-
-	cs->bc_hw_ops = &hdlc_hw_ops;
-	cs->bc_l1_ops = &hdlc_l1_ops;
-	cs->card_ops = &avm_pci_ops;
-	isac_setup(cs, &isac_ops);
-	return 1;
- err:
-	hisax_release_resources(cs);
+	printk(KERN_WARNING "FritzPCI: No card found\n");
 	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/bkm_a4t.c linux-2.5.64-bk4/drivers/isdn/hisax/bkm_a4t.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/bkm_a4t.c	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/bkm_a4t.c	Mon Mar 31 12:25:45 2003
@@ -21,11 +21,11 @@
 #include "bkm_ax.h"
 
 extern const char *CardType[];
+// FIXME needs per card lock
 static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED;
 
 const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $";
 
-
 static inline u8
 readreg(unsigned int ale, unsigned long adr, u8 off)
 {
@@ -249,15 +249,57 @@
 	.irq_func = bkm_interrupt,
 };
 
+static int __init
+bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	I20_REGISTER_FILE *pI20_Regs;
+	int rc;
+
+	printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n",
+	       pci_resource_start(pdev, 0), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
+
+	cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T");
+	if (!cs->hw.ax.base)
+		goto err;
+	
+	/* Check suspicious address */
+	// FIXME needs to use read[bl]
+	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
+		printk(KERN_WARNING "HiSax: address %lx suspicious\n",
+		       cs->hw.ax.base);
+		goto err;
+	}
+	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.isac_ale = GCS_1;
+	cs->hw.ax.jade_ale = GCS_3;
+
+	reset_bkm(cs);
+	cs->card_ops = &bkm_a4t_ops;
+	isac_setup(cs, &isac_ops);
+	jade_setup(cs, &jade_ops);
+	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 static struct pci_dev *dev_a4t __initdata = NULL;
 
 int __init
 setup_bkm_a4t(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u_int pci_memaddr = 0, found = 0;
-	I20_REGISTER_FILE *pI20_Regs;
 
 	strcpy(tmp, bkm_a4t_revision);
 	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
@@ -268,49 +310,13 @@
 
 		sub_vendor = dev_a4t->subsystem_vendor;
 		sub_sys = dev_a4t->subsystem_device;
-		if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
-			if (pci_enable_device(dev_a4t))
-				return(0);
-			found = 1;
-			pci_memaddr = pci_resource_start(dev_a4t, 0);
-			cs->irq = dev_a4t->irq;
-			break;
+		if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T && 
+		    sub_vendor == PCI_VENDOR_ID_BERKOM) {
+			if (bkm_a4t_probe(card->cs, dev_a4t))
+				return 0;
+			return 1;
 		}
 	}
-	if (!found) {
-		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
-		return (0);
-	}
-	if (!cs->irq) {		/* IRQ range check ?? */
-		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
-		return (0);
-	}
-	cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs,pci_memaddr, 4096, "Telekom A4T");
-	if (!cs->hw.ax.base) {
-		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
-		return (0);
-	}
-	
-	/* Check suspecious address */
-	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
-	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
-		printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
-		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
-		hisax_release_resources(cs);
-		return (0);
-	}
-	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
-	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
-	cs->hw.ax.isac_ale = GCS_1;
-	cs->hw.ax.jade_ale = GCS_3;
-
-	printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
-	       CardType[card->typ], cs->hw.ax.base, cs->irq);
-
-	reset_bkm(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &bkm_a4t_ops;
-	isac_setup(cs, &isac_ops);
-	jade_setup(cs, &jade_ops);
-	return 1;
+	printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
+	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/config.c linux-2.5.64-bk4/drivers/isdn/hisax/config.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/config.c	Tue Mar  4 19:29:34 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/config.c	Mon Mar 31 12:25:45 2003
@@ -490,125 +490,36 @@
 __setup("hisax=", HiSax_setup);
 #endif /* MODULES */
 
-#if CARD_TELES0
 extern int setup_teles0(struct IsdnCard *card);
-#endif
-
-#if CARD_TELES3
 extern int setup_teles3(struct IsdnCard *card);
-#endif
-
-#if CARD_S0BOX
 extern int setup_s0box(struct IsdnCard *card);
-#endif
-
-#if CARD_TELESPCI
 extern int setup_telespci(struct IsdnCard *card);
-#endif
-
-#if CARD_AVM_A1
 extern int setup_avm_a1(struct IsdnCard *card);
-#endif
-
-#if CARD_AVM_A1_PCMCIA
 extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
-#endif
-
-#if CARD_FRITZPCI
 extern int setup_avm_pcipnp(struct IsdnCard *card);
-#endif
-
-#if CARD_ELSA
 extern int setup_elsa(struct IsdnCard *card);
-#endif
-
-#if CARD_IX1MICROR2
 extern int setup_ix1micro(struct IsdnCard *card);
-#endif
-
-#if CARD_DIEHLDIVA
 extern int setup_diva(struct IsdnCard *card);
-#endif
-
-#if CARD_ASUSCOM
 extern int setup_asuscom(struct IsdnCard *card);
-#endif
-
-#if CARD_TELEINT
 extern int setup_TeleInt(struct IsdnCard *card);
-#endif
-
-#if CARD_SEDLBAUER
 extern int setup_sedlbauer(struct IsdnCard *card);
-#endif
-
-#if CARD_SPORTSTER
 extern int setup_sportster(struct IsdnCard *card);
-#endif
-
-#if CARD_MIC
 extern int setup_mic(struct IsdnCard *card);
-#endif
-
-#if CARD_NETJET_S
 extern int setup_netjet_s(struct IsdnCard *card);
-#endif
-
-#if CARD_HFCS
 extern int setup_hfcs(struct IsdnCard *card);
-#endif
-
-#if CARD_HFC_PCI
 extern int setup_hfcpci(struct IsdnCard *card);
-#endif
-
-#if CARD_HFC_SX
 extern int setup_hfcsx(struct IsdnCard *card);
-#endif
-
-#if CARD_AMD7930
 extern int setup_amd7930(struct IsdnCard *card);
-#endif
-
-#if CARD_NICCY
 extern int setup_niccy(struct IsdnCard *card);
-#endif
-
-#if CARD_ISURF
 extern int setup_isurf(struct IsdnCard *card);
-#endif
-
-#if CARD_HSTSAPHIR
 extern int setup_saphir(struct IsdnCard *card);
-#endif
-
-#if CARD_TESTEMU
 extern int setup_testemu(struct IsdnCard *card);
-#endif
-
-#if CARD_BKM_A4T
 extern int setup_bkm_a4t(struct IsdnCard *card);
-#endif
-
-#if CARD_SCT_QUADRO
 extern int setup_sct_quadro(struct IsdnCard *card);
-#endif
-
-#if CARD_GAZEL
 extern int setup_gazel(struct IsdnCard *card);
-#endif
-
-#if CARD_W6692
 extern int setup_w6692(struct IsdnCard *card);
-#endif
-
-#if CARD_NETJET_U
 extern int setup_netjet_u(struct IsdnCard *card);
-#endif
-
-#if CARD_FN_ENTERNOW_PCI
 extern int setup_enternow_pci(struct IsdnCard *card);
-#endif
 
 /*
  * Find card with given driverId
@@ -703,16 +614,16 @@
 	return 8;
 }
 
-static u8 tmpbuf[HISAX_STATUS_BUFSIZE];
+static char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
 		      va_list args)
 {
 	/* if head == NULL the fmt contains the full info */
 
 	unsigned long flags;
 	int count, i;
-	u8 *p;
+	char *p;
 	isdn_ctrl ic;
 	int len;
 
@@ -727,7 +638,7 @@
 		len = p - tmpbuf;
 		p = tmpbuf;
 	} else {
-		p = fmt;
+		p = (char *) fmt;
 		len = strlen(fmt);
 	}
 	if (!cs) {
@@ -814,12 +725,6 @@
 	ic.command = ISDN_STAT_UNLOAD;
 	ic.driver = cs->myid;
 	cs->iif.statcallb(&ic);
-	if (cs->status_buf)
-		kfree(cs->status_buf);
-	cs->status_read = NULL;
-	cs->status_write = NULL;
-	cs->status_end = NULL;
-	kfree(cs->dlog);
 }
 
 static void closecard(int cardnr)
@@ -893,59 +798,97 @@
 	return 3;
 }
 
+static struct IsdnCardState *
+alloc_IsdnCardState(void)
+{
+	struct IsdnCardState *cs;
+
+	cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME
+	if (!cs)
+		goto err;
+
+	memset(cs, 0, sizeof(*cs));
+
+	cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC);
+	if (!cs->dlog)
+		goto err_cs;
+
+	cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC);
+	if (!cs->status_buf)
+		goto err_dlog;
+
+	cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC);
+	if (!cs->rcvbuf)
+		goto err_status_buf;
+
+	cs->chanlimit = 2;	/* maximum B-channel number */
+	cs->debug = L1_DEB_WARN;
+	cs->irq_flags = I4L_IRQ_FLAG;
+	cs->stlist = NULL;
+	cs->status_read = cs->status_buf;
+	cs->status_write = cs->status_buf;
+	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
+	cs->rcvidx = 0;
+	cs->tx_skb = NULL;
+	cs->tx_cnt = 0;
+	cs->event = 0;
+
+	skb_queue_head_init(&cs->rq);
+	skb_queue_head_init(&cs->sq);
+
+	spin_lock_init(&cs->lock);
+	resources_init(&cs->rs);
+	return cs;
+
+ err_status_buf:
+	kfree(cs->status_buf);
+ err_dlog:
+	kfree(cs->dlog);
+ err_cs:
+	kfree(cs);
+ err:
+	return NULL;
+}
+
+static void
+free_IsdnCardState(struct IsdnCardState *cs)
+{
+	kfree(cs->rcvbuf);
+	kfree(cs->status_buf);
+	kfree(cs->dlog);
+	kfree(cs);
+}
+
 static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
 {
 	int ret = 0;
 	struct IsdnCard *card = cards + cardnr;
 	struct IsdnCardState *cs;
 
-	cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+	cs = alloc_IsdnCardState();
 	if (!cs) {
 		printk(KERN_WARNING
 		       "HiSax: No memory for IsdnCardState(card %d)\n",
 		       cardnr + 1);
 		goto out;
 	}
-	memset(cs, 0, sizeof(struct IsdnCardState));
 	card->cs = cs;
-	cs->chanlimit = 2;	/* maximum B-channel number */
-	cs->logecho = 0;	/* No echo logging */
-	cs->cardnr = cardnr;
-	cs->debug = L1_DEB_WARN;
-	cs->HW_Flags = 0;
-	cs->busy_flag = busy_flag;
-	cs->irq_flags = I4L_IRQ_FLAG;
 #if TEI_PER_CARD
 	if (card->protocol == ISDN_PTYPE_NI1)
 		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
 #else
 	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
 #endif
+	cs->cardnr = cardnr;
 	cs->protocol = card->protocol;
+	cs->typ = card->typ;
+	cs->busy_flag = busy_flag;
 
 	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
 		printk(KERN_WARNING
 		       "HiSax: Card Type %d out of range\n", card->typ);
 		goto outf_cs;
 	}
-	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
-		goto outf_cs;
-	}
-	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for status_buf(card %d)\n",
-		       cardnr + 1);
-		goto outf_dlog;
-	}
-	cs->stlist = NULL;
-	cs->status_read = cs->status_buf;
-	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);
-	resources_init(&cs->rs);
 	SET_MODULE_OWNER(&cs->iif);
 	strcpy(cs->iif.id, id);
 	cs->iif.channels = 2;
@@ -982,13 +925,13 @@
 	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
 	       "NONE", cs->iif.id, cs->myid);
 	switch (card->typ) {
-#if CARD_TELES0
+#ifdef CONFIG_HISAX_16_0
 	case ISDN_CTYPE_16_0:
 	case ISDN_CTYPE_8_0:
 		ret = setup_teles0(card);
 		break;
 #endif
-#if CARD_TELES3
+#ifdef CONFIG_HISAX_16_3
 	case ISDN_CTYPE_16_3:
 	case ISDN_CTYPE_PNP:
 	case ISDN_CTYPE_TELESPCMCIA:
@@ -996,32 +939,32 @@
 		ret = setup_teles3(card);
 		break;
 #endif
-#if CARD_S0BOX
+#ifdef CONFIG_HISAX_S0BOX
 	case ISDN_CTYPE_S0BOX:
 		ret = setup_s0box(card);
 		break;
 #endif
-#if CARD_TELESPCI
+#ifdef CONFIG_HISAX_TELESPCI
 	case ISDN_CTYPE_TELESPCI:
 		ret = setup_telespci(card);
 		break;
 #endif
-#if CARD_AVM_A1
+#ifdef CONFIG_HISAX_AVM_A1
 	case ISDN_CTYPE_A1:
 		ret = setup_avm_a1(card);
 		break;
 #endif
-#if CARD_AVM_A1_PCMCIA
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
 	case ISDN_CTYPE_A1_PCMCIA:
 		ret = setup_avm_a1_pcmcia(card);
 		break;
 #endif
-#if CARD_FRITZPCI
+#ifdef CONFIG_HISAX_FRITZPCI
 	case ISDN_CTYPE_FRITZPCI:
 		ret = setup_avm_pcipnp(card);
 		break;
 #endif
-#if CARD_ELSA
+#ifdef CONFIG_HISAX_ELSA
 	case ISDN_CTYPE_ELSA:
 	case ISDN_CTYPE_ELSA_PNP:
 	case ISDN_CTYPE_ELSA_PCMCIA:
@@ -1029,115 +972,115 @@
 		ret = setup_elsa(card);
 		break;
 #endif
-#if CARD_IX1MICROR2
+#ifdef CONFIG_HISAX_IX1MICROR2
 	case ISDN_CTYPE_IX1MICROR2:
 		ret = setup_ix1micro(card);
 		break;
 #endif
-#if CARD_DIEHLDIVA
+#ifdef CONFIG_HISAX_DIEHLDIVA
 	case ISDN_CTYPE_DIEHLDIVA:
 		ret = setup_diva(card);
 		break;
 #endif
-#if CARD_ASUSCOM
+#ifdef CONFIG_HISAX_ASUSCOM
 	case ISDN_CTYPE_ASUSCOM:
 		ret = setup_asuscom(card);
 		break;
 #endif
-#if CARD_TELEINT
+#ifdef CONFIG_HISAX_TELEINT
 	case ISDN_CTYPE_TELEINT:
 		ret = setup_TeleInt(card);
 		break;
 #endif
-#if CARD_SEDLBAUER
+#ifdef CONFIG_HISAX_SEDLBAUER
 	case ISDN_CTYPE_SEDLBAUER:
 	case ISDN_CTYPE_SEDLBAUER_PCMCIA:
 	case ISDN_CTYPE_SEDLBAUER_FAX:
 		ret = setup_sedlbauer(card);
 		break;
 #endif
-#if CARD_SPORTSTER
+#ifdef CONFIG_HISAX_SPORTSTER
 	case ISDN_CTYPE_SPORTSTER:
 		ret = setup_sportster(card);
 		break;
 #endif
-#if CARD_MIC
+#ifdef CONFIG_HISAX_MIC
 	case ISDN_CTYPE_MIC:
 		ret = setup_mic(card);
 		break;
 #endif
-#if CARD_NETJET_S
+#ifdef CONFIG_HISAX_NETJET
 	case ISDN_CTYPE_NETJET_S:
 		ret = setup_netjet_s(card);
 		break;
 #endif
-#if CARD_HFCS
+#ifdef CONFIG_HISAX_HFCS
 	case ISDN_CTYPE_TELES3C:
 	case ISDN_CTYPE_ACERP10:
 		ret = setup_hfcs(card);
 		break;
 #endif
-#if CARD_HFC_PCI
+#ifdef CONFIG_HISAX_HFC_PCI
 	case ISDN_CTYPE_HFC_PCI:
 		ret = setup_hfcpci(card);
 		break;
 #endif
-#if CARD_HFC_SX
+#ifdef CONFIG_HISAX_HFC_SX
 	case ISDN_CTYPE_HFC_SX:
 		ret = setup_hfcsx(card);
 		break;
 #endif
-#if CARD_NICCY
+#ifdef CONFIG_HISAX_NICCY
 	case ISDN_CTYPE_NICCY:
 		ret = setup_niccy(card);
 		break;
 #endif
-#if CARD_AMD7930
+#ifdef CONFIG_HISAX_AMD7930
 	case ISDN_CTYPE_AMD7930:
 		ret = setup_amd7930(card);
 		break;
 #endif
-#if CARD_ISURF
+#ifdef CONFIG_HISAX_ISURF
 	case ISDN_CTYPE_ISURF:
 		ret = setup_isurf(card);
 		break;
 #endif
-#if CARD_HSTSAPHIR
+#ifdef CONFIG_HISAX_HSTSAPHIR
 	case ISDN_CTYPE_HSTSAPHIR:
 		ret = setup_saphir(card);
 		break;
 #endif
-#if CARD_TESTEMU
+#ifdef CONFIG_HISAX_TESTEMU
 	case ISDN_CTYPE_TESTEMU:
 		ret = setup_testemu(card);
 		break;
 #endif
-#if	CARD_BKM_A4T
+#ifdef CONFIG_HISAX_BKM_A4T
 	case ISDN_CTYPE_BKM_A4T:
 		ret = setup_bkm_a4t(card);
 		break;
 #endif
-#if	CARD_SCT_QUADRO
+#ifdef CONFIG_HISAX_SCT_QUADRO
 	case ISDN_CTYPE_SCT_QUADRO:
 		ret = setup_sct_quadro(card);
 		break;
 #endif
-#if CARD_GAZEL
+#ifdef CONFIG_HISAX_GAZEL
 	case ISDN_CTYPE_GAZEL:
 		ret = setup_gazel(card);
 		break;
 #endif
-#if CARD_W6692
+#ifdef CONFIG_HISAX_W6692
 	case ISDN_CTYPE_W6692:
 		ret = setup_w6692(card);
 		break;
 #endif
-#if CARD_NETJET_U
+#ifdef CONFIG_HISAX_NETJET_U
 	case ISDN_CTYPE_NETJET_U:
 		ret = setup_netjet_u(card);
 		break;
 #endif
-#if CARD_FN_ENTERNOW_PCI
+#ifdef CONFIG_HISAX_ENTERNOW_PCI
 	case ISDN_CTYPE_ENTERNOW:
 		ret = setup_enternow_pci(card);
 		break;
@@ -1156,19 +1099,6 @@
 		ll_unload(cs);
 		goto outf_cs;
 	}
-	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
-		printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
-		ll_unload(cs);
-		goto outf_cs;
-	}
-	cs->rcvidx = 0;
-	cs->tx_skb = NULL;
-	cs->tx_cnt = 0;
-	cs->event = 0;
-
-	skb_queue_head_init(&cs->rq);
-	skb_queue_head_init(&cs->sq);
-
 	init_bcstate(cs, 0);
 	init_bcstate(cs, 1);
 
@@ -1201,10 +1131,8 @@
 	ret = 1;
 	goto out;
 
- outf_dlog:
-	kfree(cs->dlog);
  outf_cs:
-	kfree(cs);
+	free_IsdnCardState(cs);
 	card->cs = NULL;
  out:
 	return ret;
@@ -1253,8 +1181,8 @@
 			i++;
 		} else {
 			printk(KERN_WARNING
-			       "HiSax: Card %s not installed !\n",
-			       CardType[cards[i].typ]);
+			       "HiSax: Card type %d not installed !\n",
+			       cards[i].typ);
 			HiSax_shiftcards(i);
 			nrcards--;
 		}
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/diva.c linux-2.5.64-bk4/drivers/isdn/hisax/diva.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/diva.c	Tue Mar  4 19:29:51 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/diva.c	Mon Mar 31 12:25:45 2003
@@ -362,7 +362,7 @@
 static void
 diva_release(struct IsdnCardState *cs)
 {
-	del_timer(&cs->hw.diva.tl);
+	del_timer_sync(&cs->hw.diva.tl);
 	if (cs->hw.diva.cfg_reg)
 		byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
 
@@ -515,6 +515,162 @@
 	.irq_func    = diva_ipacx_pci_irq,
 };
 
+static int __init
+diva_ipac_probe(struct IsdnCardState *cs)
+{
+	u8 val;
+
+	// request_io
+	val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
+		      cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
+	printk(KERN_INFO "Diva: IPAC version %x\n", val);
+	return (val == 1 || val == 2);
+}
+
+static int __init
+diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = DIVA_IPAC_ISA;
+	cs->irq = card->para[0];
+	cs->hw.diva.cfg_reg  = card->para[1];
+	cs->hw.diva.isac     = card->para[1] + DIVA_IPAC_DATA;
+	cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPAC ISA", cs->hw.diva.cfg_reg, cs->irq);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		goto err;
+	diva_ipac_isa_reset(cs);
+	cs->card_ops = &diva_ipac_isa_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = DIVA_ISA;
+	cs->irq = card->para[0];
+	cs->hw.diva.cfg_reg  = card->para[1];
+	cs->hw.diva.ctrl     = card->para[1] + DIVA_ISA_CTRL;
+	cs->hw.diva.isac     = card->para[1] + DIVA_ISA_ISAC_DATA;
+	cs->hw.diva.hscx     = card->para[1] + DIVA_HSCX_DATA;
+	cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
+	cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "ISA", cs->hw.diva.cfg_reg, cs->irq);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		goto err;
+	diva_reset(cs);
+	init_timer(&cs->hw.diva.tl);
+	cs->hw.diva.tl.function = (void *) diva_led_handler;
+	cs->hw.diva.tl.data = (long) cs;
+	cs->card_ops = &diva_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int is_ipac;
+	cs->hw.diva.cfg_reg  = card->para[1];
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
+		return -EBUSY;
+
+	is_ipac = diva_ipac_probe(cs);
+	hisax_release_resources(cs);
+
+	if (is_ipac)
+		return diva_ipac_isa_probe(cs, card);
+	else
+		return diva_isac_isa_probe(cs, card);
+}
+
+static int __init
+diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.diva.cfg_reg  = pci_resource_start(pdev, 2);
+	cs->hw.diva.ctrl     = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
+	cs->hw.diva.isac     = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
+	cs->hw.diva.hscx     = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
+	cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
+	cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "PCI", cs->hw.diva.pci_cfg);
+	if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn"))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_IPAC_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.diva.pci_cfg = (unsigned long)request_mmio(
+		&cs->rs, pci_resource_start(pdev, 0), 4096, "diva");
+	cs->hw.diva.cfg_reg = (unsigned long)request_mmio(
+		&cs->rs, pci_resource_start(pdev, 1), 4096, "diva");
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "IPAC PCI", cs->hw.diva.pci_cfg);
+	diva_ipac_pci_reset(cs);
+	cs->card_ops = &diva_ipac_pci_ops;
+	if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = DIVA_IPACX_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
+	       "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq);
+	printk(KERN_INFO "Diva: %s space at %#lx\n",
+	       "IPACX PCI", cs->hw.diva.pci_cfg);
+	diva_ipacx_pci_reset(cs);
+	cs->card_ops = &diva_ipacx_pci_ops;
+	if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_diva __initdata = NULL;
 static struct pci_dev *dev_diva_u __initdata = NULL;
 static struct pci_dev *dev_diva201 __initdata = NULL;
@@ -545,101 +701,60 @@
 static struct pnp_card *pnp_c __devinitdata = NULL;
 #endif
 
-
 int __init
 setup_diva(struct IsdnCard *card)
 {
-	int bytecnt = 8;
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Diva_revision);
 	printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
 	if (card->para[1]) {
-		cs->hw.diva.ctrl_reg = 0;
-		cs->hw.diva.cfg_reg = card->para[1];
-		val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
-			cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
-		printk(KERN_INFO "Diva: IPAC version %x\n", val);
-		if ((val == 1) || (val==2)) {
-			cs->subtyp = DIVA_IPAC_ISA;
-			cs->hw.diva.ctrl = 0;
-			cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
-			cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
-			cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
-			cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
-		} else {
-			cs->subtyp = DIVA_ISA;
-			cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
-			cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
-			cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
-			cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
-			cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
-		}
-		cs->irq = card->para[0];
-	} else {
+		if (diva_isa_probe(card->cs, card) < 0)
+			return 0;
+		return 1;
+		
+	}
 #ifdef __ISAPNP__
-		if (isapnp_present()) {
-			struct pnp_card *pb;
-			struct pnp_dev *pd;
-
-			while(pdev->card_vendor) {
-				if ((pb = pnp_find_card(pdev->card_vendor,
-							pdev->card_device,
-							pnp_c))) {
-					pnp_c = pb;
-					pd = NULL;
-					if ((pd = pnp_find_dev(pnp_c,
-							       pdev->vendor,
-							       pdev->function,
-							       pd))) {
-						printk(KERN_INFO "HiSax: %s detected\n",
-							(char *)pdev->driver_data);
-						if (pnp_device_attach(pd) < 0) {
-							printk(KERN_ERR "Diva PnP: attach failed\n");
+	if (isapnp_present()) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+		
+		while(pdev->card_vendor) {
+			if ((pb = pnp_find_card(pdev->card_vendor,
+						pdev->card_device, pnp_c))) {
+				pnp_c = pb;
+				pd = NULL;
+				if ((pd = pnp_find_dev(pnp_c,
+						       pdev->vendor,
+						       pdev->function,
+						       pd))) {
+					printk(KERN_INFO "HiSax: %s detected\n",
+					       (char *)pdev->driver_data);
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "Diva PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd) < 0) {
+						printk(KERN_ERR "Diva PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+						printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
+						       pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
+						return(0);
+					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
+					if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
+						if (diva_ipac_isa_probe(cs->card, cs))
 							return 0;
-						}
-						if (pnp_activate_dev(pd) < 0) {
-							printk(KERN_ERR "Diva PnP: activate failed\n");
-							pnp_device_detach(pd);
+						return 1;
+					} else {
+						if (diva_isac_isa_probe(cs->card, cs))
 							return 0;
-						}
-						if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
-							printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
-								pnp_irq(pd, 0), pnp_port_start(pd, 0));
-							pnp_device_detach(pd);
-							return(0);
-						}
-						card->para[1] = pnp_port_start(pd, 0);
-						card->para[0] = pnp_irq(pd, 0);
-						cs->hw.diva.cfg_reg  = card->para[1];
-						cs->irq = card->para[0];
-						if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
-							cs->subtyp = DIVA_IPAC_ISA;
-							cs->hw.diva.ctrl = 0;
-							cs->hw.diva.isac =
-								card->para[1] + DIVA_IPAC_DATA;
-							cs->hw.diva.hscx =
-								card->para[1] + DIVA_IPAC_DATA;
-							cs->hw.diva.isac_adr =
-								card->para[1] + DIVA_IPAC_ADR;
-							cs->hw.diva.hscx_adr =
-								card->para[1] + DIVA_IPAC_ADR;
-						} else {
-							cs->subtyp = DIVA_ISA;
-							cs->hw.diva.ctrl =
-								card->para[1] + DIVA_ISA_CTRL;
-							cs->hw.diva.isac =
-								card->para[1] + DIVA_ISA_ISAC_DATA;
-							cs->hw.diva.hscx =
-								card->para[1] + DIVA_HSCX_DATA;
-							cs->hw.diva.isac_adr =
-								card->para[1] + DIVA_ISA_ISAC_ADR;
-							cs->hw.diva.hscx_adr =
-								card->para[1] + DIVA_HSCX_ADR;
-						}
-						goto ready;
+						return 1;
 					} else {
 						printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
 						return(0);
@@ -652,111 +767,29 @@
 				printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
 			}
 		}
+	}
 #endif
 #if CONFIG_PCI
-		cs->subtyp = 0;
-		if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
-			if (pci_enable_device(dev_diva))
-				return(0);
-			cs->subtyp = DIVA_PCI;
-			cs->irq = dev_diva->irq;
-			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
-		} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
-			if (pci_enable_device(dev_diva_u))
-				return(0);
-			cs->subtyp = DIVA_PCI;
-			cs->irq = dev_diva_u->irq;
-			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
-		} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
-			PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
-			if (pci_enable_device(dev_diva201))
-				return(0);
-			cs->subtyp = DIVA_IPAC_PCI;
-			cs->irq = dev_diva201->irq;
-			cs->hw.diva.pci_cfg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 0), 4096, "diva");
-			cs->hw.diva.cfg_reg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 1), 4096, "diva");
-		} else {
-			printk(KERN_WARNING "Diva: No PCI card found\n");
-			return(0);
-		}
-
-		if (!cs->irq) {
-			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
-			goto err;
-		}
-
-		if (!cs->hw.diva.cfg_reg) {
-			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
-			goto err;
-		}
-		cs->irq_flags |= SA_SHIRQ;
-#endif /* CONFIG_PCI */
-		if ((cs->subtyp == DIVA_IPAC_PCI) ||
-		    (cs->subtyp == DIVA_IPACX_PCI)   ) {
-			cs->hw.diva.ctrl = 0;
-			cs->hw.diva.isac = 0;
-			cs->hw.diva.hscx = 0;
-			cs->hw.diva.isac_adr = 0;
-			cs->hw.diva.hscx_adr = 0;
-			bytecnt = 0;
-		} else {
-			cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
-			cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
-			cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
-			cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
-			cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
-			bytecnt = 32;
-		}
-	}
-ready:
-	printk(KERN_INFO
-		"Diva: %s card configured at %#lx IRQ %d\n",
-		(cs->subtyp == DIVA_PCI) ? "PCI" :
-		(cs->subtyp == DIVA_ISA) ? "ISA" : 
-		(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :
-		(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
-		cs->hw.diva.cfg_reg, cs->irq);
-	if ((cs->subtyp == DIVA_IPAC_PCI)  || 
-	    (cs->subtyp == DIVA_IPACX_PCI) || 
-	    (cs->subtyp == DIVA_PCI)         )
-		printk(KERN_INFO "Diva: %s space at %#lx\n",
-			(cs->subtyp == DIVA_PCI) ? "PCI" :
-			(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
-			cs->hw.diva.pci_cfg);
-	if ((cs->subtyp != DIVA_IPAC_PCI) &&
-	    (cs->subtyp != DIVA_IPACX_PCI)   ) {
-		if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, bytecnt, "diva isdn"))
+	if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
+					PCI_DEVICE_ID_EICON_DIVA20,
+					dev_diva))) {
+		if (diva_pci_probe(card->cs, dev_diva))
 			return 0;
+		return 1;
+	} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
+						 PCI_DEVICE_ID_EICON_DIVA20_U,
+						 dev_diva_u))) {
+		if (diva_pci_probe(card->cs, dev_diva_u))
+			return 0;
+		return 1;
+	} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
+						  PCI_DEVICE_ID_EICON_DIVA201,
+						  dev_diva201))) {
+		if (diva_ipac_pci_probe(card->cs, dev_diva201))
+			return 0;
+		return 1;
 	}
-	if (cs->subtyp == DIVA_IPAC_ISA) {
-		diva_ipac_isa_reset(cs);
-		cs->card_ops = &diva_ipac_isa_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else if (cs->subtyp == DIVA_IPAC_PCI) {
-		diva_ipac_pci_reset(cs);
-		cs->card_ops = &diva_ipac_pci_ops;
-		if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
-			goto err;
-	} else if (cs->subtyp == DIVA_IPACX_PCI) {
-		diva_ipacx_pci_reset(cs);
-		cs->card_ops = &diva_ipacx_pci_ops;
-		if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
-			goto err;
-	} else { /* DIVA 2.0 */
-		diva_reset(cs);
-		cs->hw.diva.tl.function = (void *) diva_led_handler;
-		cs->hw.diva.tl.data = (long) cs;
-		init_timer(&cs->hw.diva.tl);
-		cs->card_ops = &diva_ops;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
-	}
-	return 1;
- err:
-	diva_release(cs);
+	printk(KERN_WARNING "Diva: No PCI card found\n");
+#endif /* CONFIG_PCI */
 	return 0;
-
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/elsa.c linux-2.5.64-bk4/drivers/isdn/hisax/elsa.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/elsa.c	Tue Mar  4 19:29:00 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/elsa.c	Mon Mar 31 12:25:45 2003
@@ -690,7 +690,47 @@
 	.irq_func    = elsa_interrupt_ipac,
 };
 
-static unsigned char
+static void __init
+elsa_arcofi_init(struct IsdnCardState *cs)
+{
+#if ARCOFI_USE
+	init_arcofi(cs);
+#endif
+}
+
+static void __init
+elsa_timer_init(struct IsdnCardState *cs)
+{
+	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
+	cs->hw.elsa.tl.data = (long) cs;
+	init_timer(&cs->hw.elsa.tl);
+}
+
+static int __init
+elsa_timer_test(struct IsdnCardState *cs)
+{
+	/* test timer */
+	byteout(cs->hw.elsa.trig, 0xff);
+	byteout(cs->hw.elsa.timer, 0);
+	if (!TimerRun(cs)) {
+		byteout(cs->hw.elsa.timer, 0);	/* second attempt */
+		if (!TimerRun(cs)) {
+			printk(KERN_WARNING "Elsa: timer does not start\n");
+			goto err;
+		}
+	}
+	HZDELAY(10 * HZ / 1000); /* wait >=10 ms */
+	if (TimerRun(cs)) {
+		printk(KERN_WARNING "Elsa: timer does not run\n");
+		goto err;
+	}
+	printk(KERN_INFO "Elsa: timer OK; resetting card\n");
+	return 0;
+ err:
+	return -EBUSY;
+}
+
+static unsigned char __init
 probe_elsa_adr(unsigned int adr, int typ)
 {
 	int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0,
@@ -699,15 +739,13 @@
 	/* In case of the elsa pcmcia card, this region is in use,
 	   reserved for us by the card manager. So we do not check it
 	   here, it would fail. */
-	if (typ != ISDN_CTYPE_ELSA_PCMCIA && check_region(adr, 8)) {
-		printk(KERN_WARNING
-		       "Elsa: Probing Port 0x%x: already in use\n",
-		       adr);
-		return (0);
+	if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) {
+		printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n",  adr);
+		return 0;
 	}
 	for (i = 0; i < 16; i++) {
-		in1 = inb(adr + ELSA_CONFIG);	/* 'toggelt' bei */
-		in2 = inb(adr + ELSA_CONFIG);	/* jedem Zugriff */
+		in1 = inb(adr + ELSA_CONFIG);	/* 'toggels' at */
+		in2 = inb(adr + ELSA_CONFIG);	/* each access  */
 		p16_1 += 0x04 & in1;
 		p16_2 += 0x04 & in2;
 		p8_1 += 0x02 & in1;
@@ -717,6 +755,7 @@
 		pfp_1 += 0x40 & in1;
 		pfp_2 += 0x40 & in2;
 	}
+	release_region(adr, 8);
 	printk(KERN_INFO "Elsa: Probing IO 0x%x", adr);
 	if (65 == ++p16_1 * ++p16_2) {
 		printk(" PCC-16/PCF found\n");
@@ -736,18 +775,227 @@
 	}
 }
 
-static unsigned int
-probe_elsa(struct IsdnCardState *cs)
+static int __init
+elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	int i;
-	unsigned int CARD_portlist[] =
-	{0x160, 0x170, 0x260, 0x360, 0};
-
-	for (i = 0; CARD_portlist[i]; i++) {
-		if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ)))
+	u8 val;
+	int i, bytecnt = 8;
+	unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0};
+
+	cs->hw.elsa.base = card->para[0];
+	printk(KERN_INFO "Elsa: Microlink IO probing\n");
+	if (cs->hw.elsa.base) {
+		cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ);
+		if (!cs->subtyp) {
+			printk(KERN_WARNING "Elsa: no Microlink at %#lx\n",
+			       cs->hw.elsa.base);
+			goto err;
+		}
+	} else {
+		for (i = 0; CARD_portlist[i]; i++) {
+			cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ);
+			if (cs->subtyp)
+				cs->hw.elsa.base = CARD_portlist[i];
 			break;
+		}
+	}
+	if (!cs->hw.elsa.base)
+		goto err;
+		
+	cs->hw.elsa.cfg   = cs->hw.elsa.base + ELSA_CONFIG;
+	cs->hw.elsa.ctrl  = cs->hw.elsa.base + ELSA_CONTROL;
+	cs->hw.elsa.ale   = cs->hw.elsa.base + ELSA_ALE;
+	cs->hw.elsa.isac  = cs->hw.elsa.base + ELSA_ISAC;
+	cs->hw.elsa.itac  = cs->hw.elsa.base + ELSA_ITAC;
+	cs->hw.elsa.hscx  = cs->hw.elsa.base + ELSA_HSCX;
+	cs->hw.elsa.trig  = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+	cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+	val = bytein(cs->hw.elsa.cfg);
+	if (cs->subtyp == ELSA_PC) {
+		const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
+	} else if (cs->subtyp == ELSA_PCC8) {
+		const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
+	} else {
+		const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9};
+		cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
+	}
+	val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
+	if (val < 3)
+		val |= 8;
+	val += 'A' - 3;
+	if (val == 'B' || val == 'C')
+		val ^= 1;
+	if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
+		val = 'C';
+	printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq);
+	val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
+	if (val) {
+		printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n");
+		cs->hw.elsa.status |= ELSA_BAD_PWR;
+	}
+	switch (cs->subtyp) {
+	case ELSA_PCFPRO: bytecnt = 16;	break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	if (elsa_timer_test(cs))
+		goto err;
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	if (cs->subtyp == ELSA_PC) {
+		val = readitac(cs, ITAC_SYS);
+		printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
+		writeitac(cs, ITAC_ISEN, 0);
+		writeitac(cs, ITAC_RFIE, 0);
+		writeitac(cs, ITAC_XFIE, 0);
+		writeitac(cs, ITAC_SCIE, 0);
+		writeitac(cs, ITAC_STIE, 0);
+	}
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int bytecnt = 8;
+
+	cs->irq           = card->para[0];
+	cs->hw.elsa.base  = card->para[1];
+	cs->hw.elsa.cfg   = cs->hw.elsa.base + ELSA_CONFIG;
+	cs->hw.elsa.ale   = cs->hw.elsa.base + ELSA_ALE;
+	cs->hw.elsa.isac  = cs->hw.elsa.base + ELSA_ISAC;
+	cs->hw.elsa.hscx  = cs->hw.elsa.base + ELSA_HSCX;
+	cs->hw.elsa.trig  = cs->hw.elsa.base + ELSA_TRIG_IRQ;
+	cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
+	cs->hw.elsa.ctrl  = cs->hw.elsa.base + ELSA_CONTROL;
+	printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
+	switch (cs->subtyp) {
+	case ELSA_QS3000: bytecnt = 16;	break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	if (elsa_timer_test(cs))
+		goto err;
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = ELSA_QS1000;
+	return elsa_qs_probe(cs, card);
+}
+
+static int __init
+elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = ELSA_QS3000;
+	return elsa_qs_probe(cs, card);
+}
+
+static int __init
+elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->irq = card->para[0];
+	cs->hw.elsa.base = card->para[1];
+	cs->hw.elsa.ale = cs->hw.elsa.base + 0;
+	val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
+	if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
+		cs->subtyp = ELSA_PCMCIA_IPAC;
+		cs->hw.elsa.isac = cs->hw.elsa.base + 2;
+	} else {
+		cs->subtyp = ELSA_PCMCIA;
+		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
+		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
+		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
+	}
+	cs->hw.elsa.timer = 0;
+	cs->hw.elsa.trig = 0;
+	cs->hw.elsa.ctrl = 0;
+	printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
+	elsa_arcofi_init(cs);
+	elsa_reset(cs);
+	if (cs->subtyp == ELSA_PCMCIA_IPAC) {
+		cs->card_ops = &elsa_ipac_ops;
+		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+			goto err;
+	} else {
+		cs->card_ops = &elsa_ops;
+		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+			goto err;
 	}
-	return (CARD_portlist[i]);
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
+}
+
+static int __init
+elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev,
+		  int subtyp)
+{
+	int bytecnt = 2;
+	u8 pci_rev;
+
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = subtyp;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.elsa.cfg = pci_resource_start(pdev, 1);
+	cs->hw.elsa.base = pci_resource_start(pdev, 3);
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
+	if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
+		printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
+		__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
+	}
+	cs->hw.elsa.ale  = cs->hw.elsa.base;
+	cs->hw.elsa.isac = cs->hw.elsa.base +1;
+	cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
+	printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n",
+	       Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg,
+	       cs->irq);
+	switch (cs->subtyp) {
+	case ELSA_QS3000PCI: bytecnt = 16; break;
+	}
+	if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
+		goto err;
+	elsa_arcofi_init(cs);
+	elsa_timer_init(cs);
+	elsa_reset(cs);
+	cs->card_ops = &elsa_ipac_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+	return 0;
+ err:
+	elsa_release(cs);
+	return -EBUSY;
 }
 
 static 	struct pci_dev *dev_qs1000 __devinitdata = NULL;
@@ -771,83 +1019,21 @@
 int __devinit
 setup_elsa(struct IsdnCard *card)
 {
-	int bytecnt;
-	u8 val, pci_rev;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Elsa_revision);
 	printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
-	cs->hw.elsa.ctrl_reg = 0;
-	cs->hw.elsa.status = 0;
-	cs->hw.elsa.MFlag = 0;
-	cs->subtyp = 0;
-	if (cs->typ == ISDN_CTYPE_ELSA) {
-		cs->hw.elsa.base = card->para[0];
-		printk(KERN_INFO "Elsa: Microlink IO probing\n");
-		if (cs->hw.elsa.base) {
-			if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base,
-							  cs->typ))) {
-				printk(KERN_WARNING
-				       "Elsa: no Elsa Microlink at %#lx\n",
-				       cs->hw.elsa.base);
-				return (0);
-			}
-		} else
-			cs->hw.elsa.base = probe_elsa(cs);
-		if (cs->hw.elsa.base) {
-			cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
-			cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
-			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
-			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
-			cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-			cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-			cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-			val = bytein(cs->hw.elsa.cfg);
-			if (cs->subtyp == ELSA_PC) {
-				const u8 CARD_IrqTab[8] =
-				{7, 3, 5, 9, 0, 0, 0, 0};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
-			} else if (cs->subtyp == ELSA_PCC8) {
-				const u8 CARD_IrqTab[8] =
-				{7, 3, 5, 9, 0, 0, 0, 0};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
-			} else {
-				const u8 CARD_IrqTab[8] =
-				{15, 10, 15, 3, 11, 5, 11, 9};
-				cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
-			}
-			val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
-			if (val < 3)
-				val |= 8;
-			val += 'A' - 3;
-			if (val == 'B' || val == 'C')
-				val ^= 1;
-			if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
-				val = 'C';
-			printk(KERN_INFO
-			       "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
-			       Elsa_Types[cs->subtyp],
-			       cs->hw.elsa.base,
-			       val, cs->irq);
-			val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
-			if (val) {
-				printk(KERN_WARNING
-				   "Elsa: Microlink S0 bus power bad\n");
-				cs->hw.elsa.status |= ELSA_BAD_PWR;
-			}
-		} else {
-			printk(KERN_WARNING
-			       "No Elsa Microlink found\n");
-			return (0);
-		}
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
+
+	if (card->typ == ISDN_CTYPE_ELSA) {
+		if (elsa_probe(card->cs, card))
+			return 0;
+		return 1;
+	} else if (card->typ == ISDN_CTYPE_ELSA_PNP) {
 #ifdef __ISAPNP__
 		if (!card->para[1] && isapnp_present()) {
 			struct pnp_card *pb;
 			struct pnp_dev *pd;
-
+			
 			while(pdev->card_vendor) {
 				if ((pb = pnp_find_card(pdev->card_vendor,
 							pdev->card_device,
@@ -878,10 +1064,15 @@
 						}
 						card->para[1] = pnp_port_start(pd, 0);
 						card->para[0] = pnp_irq(pd, 0);
-						if (pdev->function == ISAPNP_FUNCTION(0x133))
-							cs->subtyp = ELSA_QS1000;
-						else
-							cs->subtyp = ELSA_QS3000;
+						if (pdev->function == ISAPNP_FUNCTION(0x133)) {
+							if (elsa_qs1000_probe(card->cs, card))
+								return 0;
+							return 1;
+						} else {
+							if (elsa_qs3000_probe(card->cs, card))
+								return 0;
+							return 1;
+						}
 						break;
 					} else {
 						printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
@@ -897,184 +1088,33 @@
 			}
 		}
 #endif
-		if (card->para[1] && card->para[0]) { 
-			cs->hw.elsa.base = card->para[1];
-			cs->irq = card->para[0];
-			if (!cs->subtyp)
-				cs->subtyp = ELSA_QS1000;
-		} else {
-			printk(KERN_ERR "Elsa PnP: no parameter\n");
-		}
-		cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
-		cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
-		cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
-		cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-		cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
-		cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
-		cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->irq);
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) {
-		cs->hw.elsa.base = card->para[1];
-		cs->irq = card->para[0];
-		cs->hw.elsa.ale = cs->hw.elsa.base + 0;
-		val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
-		if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
-			cs->subtyp = ELSA_PCMCIA_IPAC;
-			cs->hw.elsa.isac = cs->hw.elsa.base + 2;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
-		} else {
-			cs->subtyp = ELSA_PCMCIA;
-			cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
-			cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
-			cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
-		}
-		cs->hw.elsa.timer = 0;
-		cs->hw.elsa.trig = 0;
-		cs->hw.elsa.ctrl = 0;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->irq);
-	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
+		if (elsa_qs1000_probe(card->cs, card))
+			return 0;
+		return 1;
+
+	} else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) {
+		if (elsa_pcmcia_probe(card->cs, card))
+			return 0;
+		return 1;
+	} else if (card->typ == ISDN_CTYPE_ELSA_PCI) {
 #if CONFIG_PCI
-		cs->subtyp = 0;
 		if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
-			if (pci_enable_device(dev_qs1000))
-				return(0);
-			cs->subtyp = ELSA_QS1000PCI;
-			cs->irq = dev_qs1000->irq;
-			cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
-			cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
-			pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
+			if (elsa_qs_pci_probe(card->cs, dev_qs1000,
+					      ELSA_QS1000PCI))
+				return 0;
+			return 1;
 		} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
-			if (pci_enable_device(dev_qs3000))
-				return(0);
-			cs->subtyp = ELSA_QS3000PCI;
-			cs->irq = dev_qs3000->irq;
-			cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
-			cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
-			pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
+			if (elsa_qs_pci_probe(card->cs, dev_qs3000,
+					      ELSA_QS3000PCI))
+				return 0;
+			return 1;
 		} else {
 			printk(KERN_WARNING "Elsa: No PCI card found\n");
-			return(0);
+			return 0;
 		}
-		if (!cs->irq) {
-			printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
-			return(0);
-		}
-
-		if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
-			printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
-			return(0);
-		}
-		if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
-			printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
-			set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-		}
-		cs->hw.elsa.ale  = cs->hw.elsa.base;
-		cs->hw.elsa.isac = cs->hw.elsa.base +1;
-		cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
-		cs->hw.elsa.timer = 0;
-		cs->hw.elsa.trig  = 0;
-		cs->irq_flags |= SA_SHIRQ;
-		printk(KERN_INFO
-		       "Elsa: %s defined at %#lx/0x%x IRQ %d\n",
-		       Elsa_Types[cs->subtyp],
-		       cs->hw.elsa.base,
-		       cs->hw.elsa.cfg,
-		       cs->irq);
 #endif /* CONFIG_PCI */
-	} else 
-		return (0);
-
-	switch (cs->subtyp) {
-		case ELSA_PC:
-		case ELSA_PCC8:
-		case ELSA_PCC16:
-		case ELSA_QS1000:
-		case ELSA_PCMCIA:
-		case ELSA_PCMCIA_IPAC:
-			bytecnt = 8;
-			break;
-		case ELSA_PCFPRO:
-		case ELSA_PCF:
-		case ELSA_QS3000:
-		case ELSA_QS3000PCI:
-			bytecnt = 16;
-			break;
-		case ELSA_QS1000PCI:
-			bytecnt = 2;
-			break;
-		default:
-			printk(KERN_WARNING
-			       "Unknown ELSA subtype %d\n", cs->subtyp);
-			return (0);
 	}
-	/* In case of the elsa pcmcia card, this region is in use,
-	   reserved for us by the card manager. So we do not check it
-	   here, it would fail. */
-	if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA)
-		if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
-			goto err;
-	
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI))
-		if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
-			goto err;
-
-#if ARCOFI_USE
-	init_arcofi(cs);
-#endif
-
-	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
-	cs->hw.elsa.tl.data = (long) cs;
-	init_timer(&cs->hw.elsa.tl);
-	/* Teste Timer */
-	if (cs->hw.elsa.timer) {
-		byteout(cs->hw.elsa.trig, 0xff);
-		byteout(cs->hw.elsa.timer, 0);
-		if (!TimerRun(cs)) {
-			byteout(cs->hw.elsa.timer, 0);	/* 2. Versuch */
-			if (!TimerRun(cs)) {
-				printk(KERN_WARNING
-				       "Elsa: timer do not start\n");
-				goto err;
-			}
-		}
-		HZDELAY(1);	/* wait >=10 ms */
-		if (TimerRun(cs)) {
-			printk(KERN_WARNING "Elsa: timer do not run down\n");
-			goto err;
-		}
-		printk(KERN_INFO "Elsa: timer OK; resetting card\n");
-	}
-	elsa_reset(cs);
-	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
-		cs->card_ops = &elsa_ipac_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-	} else {
-		cs->card_ops = &elsa_ops;
-		if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-			goto err;
-	}
-	if (cs->subtyp == ELSA_PC) {
-		val = readitac(cs, ITAC_SYS);
-		printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
-		writeitac(cs, ITAC_ISEN, 0);
-		writeitac(cs, ITAC_RFIE, 0);
-		writeitac(cs, ITAC_XFIE, 0);
-		writeitac(cs, ITAC_SCIE, 0);
-		writeitac(cs, ITAC_STIE, 0);
-	}
-	return 1;
- err:
-	elsa_release(cs);
 	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/enternow_pci.c linux-2.5.64-bk4/drivers/isdn/hisax/enternow_pci.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/enternow_pci.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/enternow_pci.c	Mon Mar 31 12:25:45 2003
@@ -263,13 +263,65 @@
 	.irq_func    = enpci_interrupt,
 };
 
+static int __init
+enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
+		goto err;
+
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
+
+	/* Reset an */
+	cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
+	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	/* 50 ms Pause */
+	schedule_timeout((50*HZ)/1000);
+	
+	cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
+	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0x00; // war 0xc0
+	cs->hw.njet.dmactrl = 0;
+	
+	OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
+	OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
+	OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
+	
+	printk(KERN_INFO
+	       "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
+	       cs->hw.njet.base, cs->irq);
+	reset_enpci(cs);
+	cs->hw.njet.last_is0 = 0;
+	cs->hw.njet.bc_activate = enpci_bc_activate;
+	cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
+	amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
+
+	cs->card_ops = &enpci_ops;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 /* called by config.c */
 int __init
 setup_enternow_pci(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 #ifdef __BIG_ENDIAN
@@ -278,72 +330,22 @@
         strcpy(tmp, enternow_pci_rev);
 	printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
 
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-                        /* checks Sub-Vendor ID because system crashes with Traverse-Card */
-			if ((dev_netjet->subsystem_vendor != 0x55) ||
-				(dev_netjet->subsystem_device != 0x02)) {
-				printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
-                                printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
-                                return(0);
-                        }
-		} else {
-                        printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
-			return(0);
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		if (dev_netjet->subsystem_vendor != 0x55 ||
+		    dev_netjet->subsystem_device != 0x02) {
+			printk(KERN_WARNING "enter:now: You tried to load "
+			       "this driver with an incompatible "
+			       "TigerJet-card\n");
+			printk(KERN_WARNING "Use type=20 for Traverse "
+			       "NetJet PCI Card.\n");
+			return 0;
 		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
-
-		/* Reset an */
-		cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
-		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		/* 50 ms Pause */
-		schedule_timeout((50*HZ)/1000);
-
-		cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
-		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0x00; // war 0xc0
-		cs->hw.njet.dmactrl = 0;
-
-		OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
-		OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
-		OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-			   break;
-	}
-	printk(KERN_INFO
-		"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
+		if (enpci_probe(card->cs, dev_netjet))
+			return 1;
 		return 0;
-	reset_enpci(cs);
-	cs->hw.njet.last_is0 = 0;
-	cs->hw.njet.bc_activate = enpci_bc_activate;
-	cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
-	amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
-
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &enpci_ops;
-
-        return 1;
+	}
+	printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
+	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/gazel.c linux-2.5.64-bk4/drivers/isdn/hisax/gazel.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/gazel.c	Tue Mar  4 19:29:20 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/gazel.c	Mon Mar 31 12:25:45 2003
@@ -294,60 +294,6 @@
 	inithscxisac(cs);
 }
 
-static int
-r647_reserve_regions(struct IsdnCardState *cs)
-{
-	int i, base = cs->hw.gazel.hscx[0];
-
-	for (i = 0; i < 0xc000; i += 0x1000) {
-		if (!request_io(&cs->rs, i + base, 16, "gazel"))
-			goto err;
-	}
-	if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r685_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r742_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
-static int
-r753_reserve_regions(struct IsdnCardState *cs)
-{
-	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
-		goto err;
-	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
-		goto err;
-	return 0;
- err:
-	hisax_release_resources(cs);
-	return -EBUSY;
-}
-
 static struct card_ops r647_ops = {
 	.init     = gazel_init,
 	.reset    = r647_reset,
@@ -377,194 +323,213 @@
 };
 
 static int __init
-setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
+gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
-	// we got an irq parameter, assume it is an ISA card
-	// R742 decodes address even in not started...
-	// R647 returns FF if not present or not started
-	// eventually needs improvment
-	cs->hw.gazel.ipac = card->para[1];
-	if (ipac_read(cs, IPAC_ID) == 1)
-		cs->subtyp = R742;
-	else
-		cs->subtyp = R647;
+	int i, base;
 
+	cs->subtyp = R647;
+	cs->irq = card->para[0];
 	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
+
+	printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
+	cs->dc.isac.adf2 = 0x87;
+	printk(KERN_INFO "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+	printk(KERN_INFO
+	       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+
 	cs->hw.gazel.isac = card->para[1] + 0x8000;
 	cs->hw.gazel.hscx[0] = card->para[1];
 	cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
-	cs->irq = card->para[0];
 	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
 	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
 
-	switch (cs->subtyp) {
-	case R647:
-		printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
-		cs->dc.isac.adf2 = 0x87;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-		printk(KERN_INFO
-		       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-		       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-		
-		return r647_reserve_regions(cs);
-	case R742:
-		printk(KERN_INFO "Gazel: Card ISA R742 found\n");
-		printk(KERN_INFO
-		       "Gazel: config irq:%d ipac:0x%X\n",
-		       cs->irq, cs->hw.gazel.ipac);
-		return r742_reserve_regions(cs);
+	base = cs->hw.gazel.hscx[0];
+	for (i = 0; i < 0xc000; i += 0x1000) {
+		if (!request_io(&cs->rs, base + i, 16, "gazel"))
+			goto err;
 	}
+	if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
+		goto err;
+
+	cs->card_ops = &r647_ops;
+	if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
 }
 
-static struct pci_dev *dev_tel __initdata = NULL;
-
 static int __init
-setup_gazelpci(struct IsdnCardState *cs)
+gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
-	u8 pci_irq = 0, found;
-	u_int nbseek, seekcard;
-	u8 pci_rev;
+	cs->subtyp = R742;
+	cs->irq = card->para[0];
+	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
 
-	printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
+	printk(KERN_INFO "Gazel: Card ISA R742 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n",
+	       cs->irq, cs->hw.gazel.ipac);
 
-	found = 0;
-	if (!pci_present()) {
-		printk(KERN_WARNING "Gazel: No PCI bus present\n");
-		return 1;
-	}
-	seekcard = PCI_DEVICE_ID_PLX_R685;
-	for (nbseek = 0; nbseek < 3; nbseek++) {
-		if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) {
-			if (pci_enable_device(dev_tel))
-				return 1;
-			pci_irq = dev_tel->irq;
-			pci_ioaddr0 = pci_resource_start(dev_tel, 1);
-			pci_ioaddr1 = pci_resource_start(dev_tel, 2);
-			found = 1;
-		}
-		if (found)
-			break;
-		else {
-			switch (seekcard) {
-			case PCI_DEVICE_ID_PLX_R685:
-				seekcard = PCI_DEVICE_ID_PLX_R753;
-				break;
-			case PCI_DEVICE_ID_PLX_R753:
-				seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO;
-				break;
-			}
-		}
-	}
-	if (!found) {
-		printk(KERN_WARNING "Gazel: No PCI card found\n");
-		return -ENODEV;
-	}
-	if (!pci_irq) {
-		printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
-		return -ENODEV;
-	}
-	cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
-	cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
+	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
+		goto err;
 
-	pci_ioaddr1 &= 0xfffe;
-	cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
-	cs->hw.gazel.ipac = pci_ioaddr1;
-	cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
-	cs->hw.gazel.hscx[0] = pci_ioaddr1;
-	cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
-	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
+	cs->card_ops = &r742_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp               = R685;
+	cs->irq                  = pdev->irq;
+	cs->irq_flags           |= SA_SHIRQ;
+	cs->hw.gazel.cfg_reg     = pci_resource_start(pdev, 1);
+	cs->hw.gazel.isac        = pci_resource_start(pdev, 2) + 0x80;
+	cs->hw.gazel.hscx[0]     = pci_resource_start(pdev, 2);
+	cs->hw.gazel.hscx[1]     = pci_resource_start(pdev, 2) + 0x40;
+	cs->hw.gazel.isacfifo    = cs->hw.gazel.isac;
 	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
 	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
-	cs->irq = pci_irq;
-	cs->irq_flags |= SA_SHIRQ;
+	cs->dc.isac.adf2 = 0x87;
 
-	switch (seekcard) {
-	case PCI_DEVICE_ID_PLX_R685:
-		printk(KERN_INFO "Gazel: Card PCI R685 found\n");
-		cs->subtyp = R685;
-		cs->dc.isac.adf2 = 0x87;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
-		printk(KERN_INFO
-		       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
-		       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
-		return r685_reserve_regions(cs);
-	case PCI_DEVICE_ID_PLX_R753:
-	case PCI_DEVICE_ID_PLX_DJINN_ITOO:
-		printk(KERN_INFO "Gazel: Card PCI R753 found\n");
-		cs->subtyp = R753;
-		printk(KERN_INFO
-		       "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
-		       cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
-		/* 
-		 * Erratum for PLX9050, revision 1:
-		 * If bit 7 of BAR 0/1 is set, local config registers
-		 * can not be read (write is okay)
-		 */
-		if (cs->hw.gazel.cfg_reg & 0x80) {
-			pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev);
-			if (pci_rev == 1) {
-				printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n");
-				set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
-			}
+	if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
+		goto err;
+
+	printk(KERN_INFO "Gazel: Card PCI R685 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+	printk(KERN_INFO "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+
+	cs->card_ops  = &r685_ops;
+	if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	u8 pci_rev;
+
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->subtyp           = R753;
+	cs->irq              = pdev->irq;
+	cs->irq_flags       |= SA_SHIRQ;
+	cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1);
+	cs->hw.gazel.ipac    = pci_resource_start(pdev, 2);
+
+	if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
+		goto err;
+
+	printk(KERN_INFO "Gazel: Card PCI R753 found\n");
+	printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
+	       cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
+	/* 
+	 * Erratum for PLX9050, revision 1:
+	 * If bit 7 of BAR 0/1 is set, local config registers
+	 * can not be read (write is okay)
+	 */
+	if (cs->hw.gazel.cfg_reg & 0x80) {
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
+		if (pci_rev == 1) {
+			printk(KERN_INFO "Gazel: PLX9050 rev1 workaround "
+			       "activated\n");
+			__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
 		}
-		return r753_reserve_regions(cs);
 	}
+	cs->card_ops = &r753_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		goto err;
+
+	cs->card_ops->reset(cs);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
 }
 
+static struct pci_dev *dev_tel __initdata = NULL;
+static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685;
+
 int __init
 setup_gazel(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, gazel_revision);
 	printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
 
 	if (card->para[0]) {
-		if (setup_gazelisa(card, cs))
-			return (0);
-	} else {
-		if (setup_gazelpci(cs))
-			return (0);
+		printk(KERN_INFO "Gazel: ISA card automatic recognition\n");
+		// we got an irq parameter, assume it is an ISA card
+		// R742 decodes address even in not started...
+		// R647 returns FF if not present or not started
+		// eventually needs improvment
+		card->cs->hw.gazel.ipac = card->para[1];
+		if (ipac_read(card->cs, IPAC_ID) == 1) {
+			if (gazel742_probe(card->cs, card))
+				return 0;
+		} else {
+			if (gazel647_probe(card->cs, card))
+				return 0;
+		}
+		return 1;
 	}
 
-	switch (cs->subtyp) {
-	case R647:
-	case R685:
-		if (cs->subtyp == R647) {
-			cs->card_ops  = &r647_ops;
-			if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
-				goto err;
-		} else {
-			cs->card_ops  = &r685_ops;
-			if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
-				goto err;
+	for (;;) {
+		dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel);
+		if (dev_tel) {
+			switch (dev_id) {
+			case PCI_DEVICE_ID_PLX_R685:
+				if (gazel685_probe(card->cs, dev_tel))
+					return 0;
+				return 1;
+			case PCI_DEVICE_ID_PLX_R753:
+			case PCI_DEVICE_ID_PLX_DJINN_ITOO:
+				if (gazel753_probe(card->cs, dev_tel))
+					return 0;
+				return 1;
+			}
 		}
-		cs->card_ops->reset(cs);
-		break;
-	case R742:
-	case R753:
-		if (cs->subtyp == R742) {
-			cs->card_ops = &r742_ops;
-		} else {
-			cs->card_ops = &r753_ops;
+		switch (dev_id) {
+		case PCI_DEVICE_ID_PLX_R685:
+			dev_id = PCI_DEVICE_ID_PLX_R753;
+		case PCI_DEVICE_ID_PLX_R753:
+			dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO;
+		default:
+			break;
 		}
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-		cs->card_ops->reset(cs);
-		break;
 	}
-	return 1;
- err:
-	hisax_release_resources(cs);
+	printk(KERN_WARNING "Gazel: No PCI card found\n");
 	return 0;
 }
+
+
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/hfc_pci.c linux-2.5.64-bk4/drivers/isdn/hisax/hfc_pci.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/hfc_pci.c	Tue Mar  4 19:29:17 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/hfc_pci.c	Mon Mar 31 12:25:45 2003
@@ -1382,72 +1382,41 @@
 };
 
 
-/* this variable is used as card index when more than one cards are present */
-static struct pci_dev *dev_hfcpci __initdata = NULL;
-
-int __init
-setup_hfcpci(struct IsdnCard *card)
+static int __init
+niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-	int i;
-	struct pci_dev *tmp_hfcpci = NULL;
+	int rc;
 
-	strcpy(tmp, hfcpci_revision);
-	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	cs->hw.hfcpci.int_s1 = 0;
-	cs->dc.hfcpci.ph_state = 0;
-	cs->hw.hfcpci.fifo = 255;
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
 
-	i = 0;
-	while (id_list[i].vendor_id) {
-		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
-					     id_list[i].device_id,
-					     dev_hfcpci);
-		i++;
-		if (tmp_hfcpci) {
-			if (pci_enable_device(tmp_hfcpci))
-				continue;
-			pci_set_master(tmp_hfcpci);
-			if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
-				continue;
-			else
-				break;
-		}
-	}
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.hfcpci.pdev = pdev;
+
+	cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, 
+					    pci_resource_start(pdev, 1), 128,
+					    "hfc_pci");
+	if (!cs->hw.hfcpci.pci_io)
+		goto err;
 	
-	if (tmp_hfcpci) {
-		i--;
-		dev_hfcpci = tmp_hfcpci;	/* old device */
-		cs->irq = dev_hfcpci->irq;
-		cs->hw.hfcpci.pdev = tmp_hfcpci;
-		if (!cs->irq) {
-			printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
-			return (0);
-		}
-		printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
-	} else {
-		printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
-		return (0);
-	}
 	/* Allocate memory for FIFOS */
-	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;
-	}
+	rc = -ENOMEM;
+	cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768, 
+						   &cs->hw.hfcpci.fifos_dma);
+	if (!cs->hw.hfcpci.fifos)
+		goto err;
+
 	pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80,
 			       (u_int)cs->hw.hfcpci.fifos_dma);
-	cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, dev_hfcpci->resource[ 1].start, 256, "hfc_pci");
-	if (!cs->hw.hfcpci.pci_io)
-		goto err;
-	
-	printk(KERN_INFO
-	       "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
-	       (u_int) cs->hw.hfcpci.pci_io,
-	       (u_int) cs->hw.hfcpci.fifos,
-	       (u_int) cs->hw.hfcpci.fifos_dma,
-	       cs->irq, HZ);
+	printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n",
+	       id_list[i].vendor_name, id_list[i].card_name);
+	printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n",
+	       (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos,
+	       (u_int) cs->hw.hfcpci.fifos_dma, cs->irq);
 	printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID));
 	cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
 	cs->hw.hfcpci.int_m1 = 0;
@@ -1456,17 +1425,46 @@
 	/* At this point the needed PCI config is done */
 	/* fifos are still not enabled */
 
-	cs->irq_flags |= SA_SHIRQ;
-
+	init_timer(&cs->hw.hfcpci.timer);
 	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
 	cs->hw.hfcpci.timer.data = (long) cs;
-	init_timer(&cs->hw.hfcpci.timer);
 
 	hfcpci_reset(cs);
 	cs->auxcmd = &hfcpci_auxcmd;
 	cs->card_ops = &hfcpci_ops;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+/* this variable is used as card index when more than one cards are present */
+static struct pci_dev *dev_hfcpci __initdata = NULL;
+
+int __init
+setup_hfcpci(struct IsdnCard *card)
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	int i;
+	struct pci_dev *tmp_hfcpci = NULL;
+
+	strcpy(tmp, hfcpci_revision);
+	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	cs->hw.hfcpci.int_s1 = 0;
+	cs->dc.hfcpci.ph_state = 0;
+	cs->hw.hfcpci.fifo = 255;
+
+	for (i = 0; id_list[i].vendor_id; i++) {
+		tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+					     id_list[i].device_id,
+					     dev_hfcpci);
+		if (!tmp_hfcpci)
+			continue;
+
+		if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0)
+			return 0;
+		return 1;
+	}
 	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/hfc_sx.c linux-2.5.64-bk4/drivers/isdn/hisax/hfc_sx.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/hfc_sx.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/hfc_sx.c	Mon Mar 31 12:25:45 2003
@@ -1159,6 +1159,74 @@
 	.irq_func = hfcsx_interrupt,
 };
 
+static int __init
+hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	int rc;
+	char c;
+
+	cs->irq = card->para[0];
+	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
+
+	cs->hw.hfcsx.fifo = 255;
+	cs->hw.hfcsx.int_s1 = 0;
+	cs->dc.hfcsx.ph_state = 0;
+
+	rc = -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
+		goto err;
+
+	rc = -ENODEV;
+	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
+	byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
+	udelay(10);
+	cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
+	switch (cs->hw.hfcsx.chip >> 4) {
+	case 1: 
+		c ='+';
+		break;
+	case 9: 
+		c ='P';
+		break;
+	default:
+		printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
+		       cs->hw.hfcsx.chip >> 4);
+		goto err;
+	}  
+	if (!ccd_sp_irqtab[cs->irq & 0xF]) {
+		printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
+		       cs->irq & 0xF);
+		goto err;
+	}
+	rc = -ENOMEM;
+	cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC);
+	if (!cs->hw.hfcsx.extra) {
+		printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
+		goto err;
+	}
+	printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n",
+	       c, (u_int) cs->hw.hfcsx.base, cs->irq);
+
+	cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
+	cs->hw.hfcsx.int_m1 = 0;
+	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+
+	init_timer(&cs->hw.hfcsx.timer);
+	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
+	cs->hw.hfcsx.timer.data = (long) cs;
+	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
+	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */
+
+	hfcsx_reset(cs);
+	cs->auxcmd = &hfcsx_auxcmd;
+	cs->card_ops = &hfcsx_ops;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id hfc_ids[] __initdata = {
 	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
@@ -1174,7 +1242,6 @@
 int __devinit
 setup_hfcsx(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, hfcsx_revision);
@@ -1227,62 +1294,7 @@
 		}
 	}
 #endif
-	cs->hw.hfcsx.base = card->para[1] & 0xfffe;
-	cs->irq = card->para[0];
-	cs->hw.hfcsx.int_s1 = 0;
-	cs->dc.hfcsx.ph_state = 0;
-	cs->hw.hfcsx.fifo = 255;
-
-	if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
-		return 0;
-	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
-	byteout(cs->hw.hfcsx.base + 1,
-		((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
-	udelay(10);
-	cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
-	switch (cs->hw.hfcsx.chip >> 4) {
-	case 1: 
-		tmp[0] ='+';
-		break;
-	case 9: 
-		tmp[0] ='P';
-		break;
-	default:
-		printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
-		       cs->hw.hfcsx.chip >> 4);
-		hisax_release_resources(cs);
-		return 0;
-	}  
-	if (!ccd_sp_irqtab[cs->irq & 0xF]) {
-		printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
-		       cs->irq & 0xF);
-		hisax_release_resources(cs);
+	if (hfcsx_probe(card->cs, card) < 0)
 		return 0;
-	}  
-	cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), 
-				     GFP_ATOMIC);
-	if (!cs->hw.hfcsx.extra) {
-		hisax_release_resources(cs);
-		printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
-		return 0;
-	}
-	
-	printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
-	       tmp[0], (u_int) cs->hw.hfcsx.base,
-	       cs->irq, HZ);
-	cs->hw.hfcsx.int_m2 = 0;	/* disable alle interrupts */
-	cs->hw.hfcsx.int_m1 = 0;
-	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
-	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
-
-	cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
-	cs->hw.hfcsx.timer.data = (long) cs;
-	cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
-	cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
-	init_timer(&cs->hw.hfcsx.timer);
-
-	hfcsx_reset(cs);
-	cs->auxcmd = &hfcsx_auxcmd;
-	cs->card_ops = &hfcsx_ops;
 	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/hfcscard.c linux-2.5.64-bk4/drivers/isdn/hisax/hfcscard.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/hfcscard.c	Tue Mar  4 19:29:51 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/hfcscard.c	Mon Mar 31 12:25:45 2003
@@ -133,6 +133,50 @@
 	.irq_func = hfcs_interrupt,
 };
 
+static int __init
+hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.hfcD.addr = card->para[1];
+
+	if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
+		goto err;
+
+	printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n",
+	       cs->hw.hfcD.addr, cs->irq);
+
+	cs->hw.hfcD.cip = 0;
+	cs->hw.hfcD.int_s1 = 0;
+	cs->hw.hfcD.send = NULL;
+	cs->bcs[0].hw.hfc.send = NULL;
+	cs->bcs[1].hw.hfc.send = NULL;
+	cs->hw.hfcD.dfifosize = 512;
+	cs->dc.hfcd.ph_state = 0;
+	cs->hw.hfcD.fifo = 255;
+
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		cs->hw.hfcD.bfifosize = 1024 + 512;
+		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x56, cs->hw.hfcD.addr | 1);
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		cs->hw.hfcD.bfifosize = 7*1024 + 512;
+		/* Acer P10 IO ADR is 0x300 */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x57, cs->hw.hfcD.addr | 1);
+	}
+	set_cs_func(cs);
+	init_timer(&cs->hw.hfcD.timer);
+	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
+	cs->hw.hfcD.timer.data = (long) cs;
+	hfcs_reset(cs);
+	cs->card_ops = &hfcs_ops;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id hfc_ids[] __initdata = {
 	{ ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
@@ -166,7 +210,6 @@
 int __init
 setup_hfcs(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, hfcs_revision);
@@ -220,42 +263,8 @@
 		}
 	}
 #endif
-	cs->hw.hfcD.addr = card->para[1] & 0xfffe;
-	cs->irq = card->para[0];
-	cs->hw.hfcD.cip = 0;
-	cs->hw.hfcD.int_s1 = 0;
-	cs->hw.hfcD.send = NULL;
-	cs->bcs[0].hw.hfc.send = NULL;
-	cs->bcs[1].hw.hfc.send = NULL;
-	cs->hw.hfcD.dfifosize = 512;
-	cs->dc.hfcd.ph_state = 0;
-	cs->hw.hfcD.fifo = 255;
-	if (cs->typ == ISDN_CTYPE_TELES3C) {
-		cs->hw.hfcD.bfifosize = 1024 + 512;
-	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
-		cs->hw.hfcD.bfifosize = 7*1024 + 512;
-	} else
-		return (0);
-	if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
+	if (hfcs_probe(card->cs, card) < 0)
 		return 0;
-	printk(KERN_INFO
-	       "HFCS: defined at 0x%x IRQ %d HZ %d\n",
-	       cs->hw.hfcD.addr,
-	       cs->irq, HZ);
-	if (cs->typ == ISDN_CTYPE_TELES3C) {
-		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
-		outb(0x00, cs->hw.hfcD.addr);
-		outb(0x56, cs->hw.hfcD.addr | 1);
-	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
-		/* Acer P10 IO ADR is 0x300 */
-		outb(0x00, cs->hw.hfcD.addr);
-		outb(0x57, cs->hw.hfcD.addr | 1);
-	}
-	set_cs_func(cs);
-	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
-	cs->hw.hfcD.timer.data = (long) cs;
-	init_timer(&cs->hw.hfcD.timer);
-	hfcs_reset(cs);
-	cs->card_ops = &hfcs_ops;
-	return (1);
+	return 1;
+	
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/hisax.h linux-2.5.64-bk4/drivers/isdn/hisax/hisax.h
--- linux-2.5.64-bk3/drivers/isdn/hisax/hisax.h	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/hisax.h	Mon Mar 31 12:25:45 2003
@@ -782,7 +782,6 @@
 
 struct gazel_hw {
 	unsigned int cfg_reg;
-	unsigned int pciaddr[2];
         signed   int ipac;
 	signed   int isac;
 	signed   int hscx[2];
@@ -1073,264 +1072,17 @@
 #define  ISDN_CTYPE_COUNT	41
 
 
-#ifdef ISDN_CHIP_ISAC
-#undef ISDN_CHIP_ISAC
-#endif
-
-#ifdef	CONFIG_HISAX_16_0
-#define  CARD_TELES0 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELES0  0
-#endif
-
-#ifdef	CONFIG_HISAX_16_3
-#define  CARD_TELES3 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELES3  0
-#endif
-
-#ifdef	CONFIG_HISAX_TELESPCI
-#define  CARD_TELESPCI 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_TELESPCI  0
-#endif
-
-#ifdef	CONFIG_HISAX_AVM_A1
-#define  CARD_AVM_A1 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_AVM_A1  0
-#endif
-
-#ifdef	CONFIG_HISAX_AVM_A1_PCMCIA
-#define  CARD_AVM_A1_PCMCIA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_AVM_A1_PCMCIA  0
-#endif
-
-#ifdef	CONFIG_HISAX_FRITZPCI
-#define  CARD_FRITZPCI 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_FRITZPCI  0
-#endif
-
-#ifdef	CONFIG_HISAX_ELSA
-#define  CARD_ELSA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_ELSA  0
-#endif
-
-#ifdef	CONFIG_HISAX_IX1MICROR2
-#define	CARD_IX1MICROR2 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_IX1MICROR2 0
-#endif
-
-#ifdef  CONFIG_HISAX_DIEHLDIVA
-#define CARD_DIEHLDIVA 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_DIEHLDIVA 0
-#endif
-
-#ifdef  CONFIG_HISAX_ASUSCOM
-#define CARD_ASUSCOM 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_ASUSCOM 0
-#endif
-
-#ifdef  CONFIG_HISAX_TELEINT
-#define CARD_TELEINT 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_TELEINT 0
-#endif
-
-#ifdef  CONFIG_HISAX_SEDLBAUER
-#define CARD_SEDLBAUER 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SEDLBAUER 0
-#endif
-
-#ifdef  CONFIG_HISAX_SPORTSTER
-#define CARD_SPORTSTER 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SPORTSTER 0
-#endif
-
-#ifdef  CONFIG_HISAX_MIC
-#define CARD_MIC 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_MIC 0
-#endif
-
-#ifdef  CONFIG_HISAX_NETJET
-#define CARD_NETJET_S 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_NETJET_S 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFCS
-#define  CARD_HFCS 1
-#else
-#define  CARD_HFCS 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFC_PCI
-#define  CARD_HFC_PCI 1
-#else
-#define  CARD_HFC_PCI 0
-#endif
-
-#ifdef	CONFIG_HISAX_HFC_SX
-#define  CARD_HFC_SX 1
-#else
-#define  CARD_HFC_SX 0
-#endif
-
-#ifdef  CONFIG_HISAX_AMD7930
-#define CARD_AMD7930 1
-#else
-#define CARD_AMD7930 0
-#endif
-
-#ifdef	CONFIG_HISAX_NICCY
-#define	CARD_NICCY 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_NICCY 0
-#endif
-
-#ifdef	CONFIG_HISAX_ISURF
-#define	CARD_ISURF 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_ISURF 0
-#endif
-
-#ifdef	CONFIG_HISAX_S0BOX
-#define	CARD_S0BOX 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_S0BOX 0
-#endif
-
-#ifdef	CONFIG_HISAX_HSTSAPHIR
-#define	CARD_HSTSAPHIR 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_HSTSAPHIR 0
-#endif
-
 #ifdef	CONFIG_HISAX_TESTEMU
-#define	CARD_TESTEMU 1
 #define ISDN_CTYPE_TESTEMU 99
 #undef ISDN_CTYPE_COUNT
 #define  ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
-#else
-#define CARD_TESTEMU 0
-#endif
-
-#ifdef	CONFIG_HISAX_BKM_A4T
-#define	CARD_BKM_A4T 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_BKM_A4T 0
-#endif
-
-#ifdef	CONFIG_HISAX_SCT_QUADRO
-#define	CARD_SCT_QUADRO 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define CARD_SCT_QUADRO 0
-#endif
-
-#ifdef	CONFIG_HISAX_GAZEL
-#define  CARD_GAZEL 1
-#ifndef ISDN_CHIP_ISAC
-#define ISDN_CHIP_ISAC 1
-#endif
-#else
-#define  CARD_GAZEL  0
-#endif
-
-#ifdef	CONFIG_HISAX_W6692
-#define	CARD_W6692	1
-#ifndef	ISDN_CHIP_W6692
-#define	ISDN_CHIP_W6692	1
-#endif
-#else
-#define	CARD_W6692	0
 #endif
 
 #ifdef  CONFIG_HISAX_NETJET_U
-#define CARD_NETJET_U 1
-#ifndef ISDN_CHIP_ICC
-#define ISDN_CHIP_ICC 1
-#endif
 #ifndef HISAX_UINTERFACE
 #define HISAX_UINTERFACE 1
 #endif
 #else
-#define CARD_NETJET_U 0
-#endif
-
-#ifdef CONFIG_HISAX_ENTERNOW_PCI
-#define CARD_FN_ENTERNOW_PCI 1
 #endif
 
 #define TEI_PER_CARD 1
@@ -1402,7 +1154,7 @@
 int HiSax_command(isdn_ctrl * ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u8 * p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u8 * p, int size);
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/hisax_fcclassic.c linux-2.5.64-bk4/drivers/isdn/hisax/hisax_fcclassic.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/hisax_fcclassic.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/hisax_fcclassic.c	Mon Mar 31 12:25:45 2003
@@ -231,7 +231,7 @@
 	adapter->isac.write_isac      = &fcclassic_write_isac;
 	adapter->isac.read_isac_fifo  = &fcclassic_read_isac_fifo;
 	adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo;
-	isac_setup(&adapter->isac);
+	hisax_isac_setup(&adapter->isac);
 	for (i = 0; i < 2; i++) {
 		hscx_init(&adapter->hscx[i]);
 		adapter->hscx[i].priv            = adapter;
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/hisax_fcpcipnp.c linux-2.5.64-bk4/drivers/isdn/hisax/hisax_fcpcipnp.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/hisax_fcpcipnp.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/hisax_fcpcipnp.c	Mon Mar 31 12:25:45 2003
@@ -46,24 +46,22 @@
 MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
 MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
 
-// FIXME temporary hack until I sort out the new PnP stuff
-#define __ISAPNP__
-
 static struct pci_device_id fcpci_ids[] __devinitdata = {
-	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1   , PCI_ANY_ID, PCI_ANY_ID,
-	  0, 0, (unsigned long) "Fritz!Card PCI" },
-	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
-	  0, 0, (unsigned long) "Fritz!Card PCI v2" },
-	{ }
+	{ .vendor      = PCI_VENDOR_ID_AVM,
+	  .device      = PCI_DEVICE_ID_AVM_A1,
+	  .subvendor   = PCI_ANY_ID,
+	  .subdevice   = PCI_ANY_ID,
+	  .driver_data = (unsigned long) "Fritz!Card PCI",
+	},
+	{ .vendor      = PCI_VENDOR_ID_AVM,
+	  .device      = PCI_DEVICE_ID_AVM_A1_V2,
+	  .subvendor   = PCI_ANY_ID,
+	  .subdevice   = PCI_ANY_ID,
+	  .driver_data = (unsigned long) "Fritz!Card PCI v2" },
+	{}
 };
-MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
-static struct pnp_card_device_id fcpnp_ids[] __devinitdata = {
-	{ .id = "AVM0900", 
-	  .driver_data = (unsigned long) "Fritz!Card PnP",
-	  .devs = { { "AVM0900" } } }
-};
-MODULE_DEVICE_TABLE(pnp_card, fcpnp_ids);
+MODULE_DEVICE_TABLE(pci, fcpci_ids);
 
 static int protocol = 2;       /* EURO-ISDN Default */
 MODULE_PARM(protocol, "i");
@@ -782,7 +780,7 @@
 	case AVM_FRITZ_PCI:
 	case AVM_FRITZ_PNP:
 		fcpci_init(adapter);
-		isac_setup(&adapter->isac);
+		hisax_isac_setup(&adapter->isac);
 		break;
 	}
 	val = adapter->read_hdlc_status(adapter, 0);
@@ -908,10 +906,10 @@
 	.id_table = fcpci_ids,
 };
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 
 static int __devinit fcpnp_probe(struct pnp_card *card,
-				 const struct pnp_card_device_id *card_id)
+				 const struct pnp_card_id *card_id)
 {
 	struct fritz_adapter *adapter;
 	struct pnp_dev *pnp_dev;
@@ -957,6 +955,14 @@
 	delete_adapter(adapter);
 }
 
+static struct pnp_card_id fcpnp_ids[] __devinitdata = {
+	{ .id          = "AVM0900", 
+	  .driver_data = (unsigned long) "Fritz!Card PnP",
+	  .devs        = { { "AVM0900" } },
+	},
+	{}
+};
+
 static struct pnpc_driver fcpnp_driver = {
 	.name     = "fcpnp",
 	.probe    = fcpnp_probe,
@@ -968,7 +974,7 @@
 
 static int __init hisax_fcpcipnp_init(void)
 {
-	int retval, pci_nr_found;
+	int retval = 0, pci_nr_found;
 
 	printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
 
@@ -977,10 +983,8 @@
 		goto out;
 	pci_nr_found = retval;
 
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 	retval = pnpc_register_driver(&fcpnp_driver);
-#else
-	retval = 0;
 #endif
 	if (retval < 0)
 		goto out_unregister_pci;
@@ -988,14 +992,14 @@
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
 	if (pci_nr_found + retval == 0) {
 		retval = -ENODEV;
-		goto out_unregister_isapnp;
+		goto out_unregister_pnp;
 	}
 #endif
 	return 0;
 
 #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
- out_unregister_isapnp:
-#ifdef __ISAPNP__
+ out_unregister_pnp:
+#ifdef CONFIG_PNP_CARD
 	pnpc_unregister_driver(&fcpnp_driver);
 #endif
 #endif
@@ -1007,7 +1011,7 @@
 
 static void __exit hisax_fcpcipnp_exit(void)
 {
-#ifdef __ISAPNP__
+#ifdef CONFIG_PNP_CARD
 	pnpc_unregister_driver(&fcpnp_driver);
 #endif
 	pci_unregister_driver(&fcpci_driver);
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/hisax_isac.c linux-2.5.64-bk4/drivers/isdn/hisax/hisax_isac.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/hisax_isac.c	Tue Mar  4 19:28:57 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/hisax_isac.c	Mon Mar 31 12:25:45 2003
@@ -770,7 +770,7 @@
 	FsmInitTimer(&isac->l1m, &isac->timer);
 }
 
-void isac_setup(struct isac *isac)
+void hisax_isac_setup(struct isac *isac)
 {
 	int val, eval;
 
@@ -890,7 +890,7 @@
 EXPORT_SYMBOL(isacsx_setup);
 EXPORT_SYMBOL(isacsx_irq);
 
-EXPORT_SYMBOL(isac_setup);
+EXPORT_SYMBOL(hisax_isac_setup);
 EXPORT_SYMBOL(isac_irq);
 
 module_init(hisax_isac_init);
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/hisax_isac.h linux-2.5.64-bk4/drivers/isdn/hisax/hisax_isac.h
--- linux-2.5.64-bk3/drivers/isdn/hisax/hisax_isac.h	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/hisax_isac.h	Mon Mar 31 12:25:45 2003
@@ -36,7 +36,7 @@
 void isac_init(struct isac *isac);
 void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
 
-void isac_setup(struct isac *isac);
+void hisax_isac_setup(struct isac *isac);
 void isac_irq(struct isac *isac);
 
 void isacsx_setup(struct isac *isac);
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/isdnl1.c linux-2.5.64-bk4/drivers/isdn/hisax/isdnl1.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/isdnl1.c	Tue Mar  4 19:29:04 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/isdnl1.c	Mon Mar 31 12:25:45 2003
@@ -126,7 +126,7 @@
 };
 
 void
-debugl1(struct IsdnCardState *cs, char *fmt, ...)
+debugl1(struct IsdnCardState *cs, const char *fmt, ...)
 {
 	va_list args;
 	char tmp[8];
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/isdnl1.h linux-2.5.64-bk4/drivers/isdn/hisax/isdnl1.h
--- linux-2.5.64-bk3/drivers/isdn/hisax/isdnl1.h	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/isdnl1.h	Mon Mar 31 12:25:45 2003
@@ -28,7 +28,7 @@
 #define B_LL_CONNECT	9
 #define B_LL_OK		10
 
-extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
+extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...);
 extern void DChannel_proc_xmt(struct IsdnCardState *cs);
 extern void DChannel_proc_rcv(struct IsdnCardState *cs);
 extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/isurf.c linux-2.5.64-bk4/drivers/isdn/hisax/isurf.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/isurf.c	Tue Mar  4 19:29:20 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/isurf.c	Mon Mar 31 12:25:45 2003
@@ -187,95 +187,92 @@
 static struct pnp_card *pnp_surf __devinitdata = NULL;
 #endif
 
-int __init
-setup_isurf(struct IsdnCard *card)
+static int __init
+isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	unsigned long phymem;
-	char tmp[64];
 
-	strcpy(tmp, ISurf_revision);
-	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
-	
-	if (card->para[1] && card->para[2]) {
-		cs->hw.isurf.reset = card->para[1];
-		phymem = card->para[2];
-		cs->irq = card->para[0];
-	} else {
-#ifdef __ISAPNP__
-		struct pnp_card *pb;
-		struct pnp_dev *pd;
+	phymem = card->para[2];
+	cs->hw.isurf.reset = card->para[1];
+	cs->irq = card->para[0];
 
-		if (isapnp_present()) {
-			cs->subtyp = 0;
-			if ((pb = pnp_find_card(
-				ISAPNP_VENDOR('S', 'I', 'E'),
-				ISAPNP_FUNCTION(0x0010), pnp_surf))) {
-				pnp_surf = pb;
-				pd = NULL;
-				if (!(pd = pnp_find_dev(pnp_surf,
-					ISAPNP_VENDOR('S', 'I', 'E'),
-					ISAPNP_FUNCTION(0x0010), pd))) {
-					printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
-					return (0);
-				}
-				if (pnp_device_attach(pd) < 0) {
-					printk(KERN_ERR "ISurfPnP: attach failed\n");
-					return 0;
-				}
-				if (pnp_activate_dev(pd) < 0) {
-					printk(KERN_ERR "ISurfPnP: activate failed\n");
-					pnp_device_detach(pd);
-					return 0;
-				}
-				if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
-					printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
-						pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
-					pnp_device_detach(pd);
-					return(0);
-				}
-				cs->hw.isurf.reset = pnp_port_start(pd, 0);
-				phymem = pnp_port_start(pd, 1);
-				cs->irq = pnp_irq(pd, 0);
-			} else {
-				printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
-				return(0);
-			}
-		} else {
-			printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
-			return(0);
-		}
-#else
-		printk(KERN_WARNING "HiSax: %s port/mem not set\n",
-			CardType[card->typ]);
-		return (0);
-#endif
-	}
 	if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn"))
 		goto err;
-	cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, "isurf iomem");
+
+	cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE,
+					 "isurf iomem");
 	if (!cs->hw.isurf.isar)
 		goto err;
 
 	cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
-	printk(KERN_INFO
-	       "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
-	       cs->hw.isurf.reset,
-	       card->para[2],
-	       cs->irq);
+	printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
+	       cs->hw.isurf.reset, phymem, cs->irq);
 
 	cs->auxcmd = &isurf_auxcmd;
 	cs->card_ops = &isurf_ops;
 	cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
 	cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
 	reset_isurf(cs, ISURF_RESET);
-	test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+	__set_bit(HW_ISAR, &cs->HW_Flags);
 	isac_setup(cs, &isac_ops);
 	if (isar_setup(cs, &isar_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
+
+int __init
+setup_isurf(struct IsdnCard *card)
+{
+	char tmp[64];
 
+	strcpy(tmp, ISurf_revision);
+	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
+	
+#ifdef __ISAPNP__
+	if (!card->para[1] || !card->para[2]) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+	
+		cs->subtyp = 0;
+		if ((pb = pnp_find_card(
+			     ISAPNP_VENDOR('S', 'I', 'E'),
+			     ISAPNP_FUNCTION(0x0010), pnp_surf))) {
+			pnp_surf = pb;
+			pd = NULL;
+			if (!(pd = pnp_find_dev(pnp_surf,
+						ISAPNP_VENDOR('S', 'I', 'E'),
+						ISAPNP_FUNCTION(0x0010), pd))) {
+				printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
+				return (0);
+			}
+			if (pnp_device_attach(pd) < 0) {
+				printk(KERN_ERR "ISurfPnP: attach failed\n");
+				return 0;
+			}
+			if (pnp_activate_dev(pd) < 0) {
+				printk(KERN_ERR "ISurfPnP: activate failed\n");
+				pnp_device_detach(pd);
+				return 0;
+			}
+			if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
+				printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
+				       pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
+				pnp_device_detach(pd);
+				return(0);
+			}
+			card->para[1] = pnp_port_start(pd, 0);
+			card->para[2] = pnp_port_start(pd, 1);
+			card->para[0] = pnp_irq(pd, 0);
+		} else {
+			printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
+			return 0;
+		}
+	}
+#endif
+	if (isurf_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/ix1_micro.c linux-2.5.64-bk4/drivers/isdn/hisax/ix1_micro.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/ix1_micro.c	Tue Mar  4 19:29:52 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/ix1_micro.c	Mon Mar 31 12:25:45 2003
@@ -162,6 +162,29 @@
 	.irq_func = hscxisac_irq,
 };
 
+static int __init
+ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq             = card->para[0];
+	cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
+	cs->hw.ix1.isac     = card->para[1] + ISAC_DATA_OFFSET;
+	cs->hw.ix1.hscx     = card->para[1] + HSCX_DATA_OFFSET;
+	cs->hw.ix1.cfg_reg  = card->para[1];
+	if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
+		goto err;
+	
+	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
+	ix1_reset(cs);
+	cs->card_ops = &ix1_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id itk_ids[] __initdata = {
 	{ ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
@@ -181,14 +204,18 @@
 int __init
 setup_ix1micro(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, ix1_revision);
 	printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp));
 
+	if (card->para[1]) {
+		if (ix1_probe(card->cs, card))
+			return 0;
+		return 1;
+	}
 #ifdef __ISAPNP__
-	if (!card->para[1] && isapnp_present()) {
+	if (isapnp_present()) {
 		struct pnp_card *pb;
 		struct pnp_dev *pd;
 
@@ -221,7 +248,9 @@
 					}
 					card->para[1] = pnp_port_start(pd, 0);
 					card->para[0] = pnp_irq(pd, 0);
-					break;
+					if (ix1_probe(card->cs, card))
+						return 0;
+					return 1;
 				} else {
 					printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
 				}
@@ -231,27 +260,8 @@
 		} 
 		if (!idev->card_vendor) {
 			printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
-			return(0);
 		}
 	}
 #endif
-	/* IO-Ports */
-	cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
-	cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET;
-	cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET;
-	cs->hw.ix1.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-	if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
-		goto err;
-	
-	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
-	ix1_reset(cs);
-	cs->card_ops = &ix1_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 1;
- err:
-	hisax_release_resources(cs);
 	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/mic.c linux-2.5.64-bk4/drivers/isdn/hisax/mic.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/mic.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/mic.c	Mon Mar 31 12:25:45 2003
@@ -138,17 +138,11 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_mic(struct IsdnCard *card)
+static int __init
+mic_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, mic_revision);
-	printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
-
-	cs->hw.mic.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
+	cs->hw.mic.cfg_reg = card->para[1];
 	cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
 	cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
 	cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
@@ -158,11 +152,25 @@
   
 	printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
 	       cs->hw.mic.cfg_reg, cs->irq);
+
 	cs->card_ops = &mic_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
+
+int __init
+setup_mic(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, mic_revision);
+	printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (mic_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/niccy.c linux-2.5.64-bk4/drivers/isdn/hisax/niccy.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/niccy.c	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/niccy.c	Mon Mar 31 12:25:45 2003
@@ -199,6 +199,70 @@
 	.irq_func = niccy_interrupt,
 };
 
+static int __init
+niccy_probe(struct IsdnCardState *cs)
+{
+	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
+	       CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
+	       cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
+	cs->card_ops = &niccy_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -EBUSY;
+	return 0;
+}
+
+static int __init
+niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = NICCY_PNP;
+	cs->irq = card->para[0];
+	cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
+	cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
+	cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
+	cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
+	cs->hw.niccy.cfg_reg = 0;
+
+	if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
+		goto err;
+	if (niccy_probe(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	u32 pci_ioaddr;
+
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = NICCY_PCI;
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0);
+	pci_ioaddr = pci_resource_start(pdev, 1);
+	cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
+	cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
+	cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
+	cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
+	if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
+		goto err;
+	if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
+		goto err;
+	if (niccy_probe(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *niccy_dev __initdata = NULL;
 #ifdef __ISAPNP__
 static struct pnp_card *pnp_c __devinitdata = NULL;
@@ -207,7 +271,6 @@
 int __init
 setup_niccy(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, niccy_revision);
@@ -252,66 +315,18 @@
 	}
 #endif
 	if (card->para[1]) {
-		cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
-		cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
-		cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
-		cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
-		cs->hw.niccy.cfg_reg = 0;
-		cs->subtyp = NICCY_PNP;
-		cs->irq = card->para[0];
-		if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
-			goto err;
+		if (niccy_pnp_probe(card->cs, card) < 0)
+			return 0;
+		return 1;
 	} else {
 #if CONFIG_PCI
-		u_int pci_ioaddr;
-		cs->subtyp = 0;
 		if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
 			PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) {
-			if (pci_enable_device(niccy_dev))
-				return(0);
-			/* get IRQ */
-			if (!niccy_dev->irq) {
-				printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->irq = niccy_dev->irq;
-			cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
-			if (!cs->hw.niccy.cfg_reg) {
-				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
-				return(0);
-			}
-			pci_ioaddr = pci_resource_start(niccy_dev, 1);
-			if (!pci_ioaddr) {
-				printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = NICCY_PCI;
-		} else {
-			printk(KERN_WARNING "Niccy: No PCI card found\n");
-			return(0);
+			if (niccy_pci_probe(card->cs, niccy_dev) < 0)
+				return 0;
+			return 1;
 		}
-		cs->irq_flags |= SA_SHIRQ;
-		cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
-		cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
-		cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
-		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
-
-		if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
-			goto err;
 #endif /* CONFIG_PCI */
 	}
-	printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
-		CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
-		cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
-	cs->card_ops = &niccy_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
-	return 1;
- err:
-	niccy_release(cs);
 	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/nj_s.c linux-2.5.64-bk4/drivers/isdn/hisax/nj_s.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/nj_s.c	Tue Mar  4 19:29:04 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/nj_s.c	Mon Mar 31 12:25:45 2003
@@ -106,96 +106,99 @@
 	.irq_func = nj_s_interrupt,
 };
 
+static int __init
+nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.pdev = pdev;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
+		return 0;
+	
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+	
+	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);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0xC0;
+	cs->hw.njet.dmactrl = 0;
+	
+	byteout(cs->hw.njet.auxa, 0);
+	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+	switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) {
+	case 0 :
+		break;
+	case 3 :
+		printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
+		goto err;
+	default :
+		printk(KERN_WARNING "NETjet-S: No PCI card found\n" );
+		goto err;
+	}
+	printk(KERN_INFO
+		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
+		cs->hw.njet.base, cs->irq);
+	
+	nj_s_reset(cs);
+	cs->irq_flags |= SA_SHIRQ;
+	cs->card_ops = &nj_s_ops;
+	isac_setup(cs, &netjet_dc_ops);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_s(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_S_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			pci_set_master(dev_netjet);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
-				return(0);
-			}
- 			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
- 			if ((dev_netjet->subsystem_vendor == 0x55) &&
- 				(dev_netjet->subsystem_device == 0x02)) {
- 				printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
- 				printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
- 				return(0);
- 			}
- 			/* end new code */
-			cs->hw.njet.pdev = dev_netjet;
-		} else {
-			printk(KERN_WARNING "NETjet-S: No PCI card found\n");
-			return(0);
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
+		if (dev_netjet->subsystem_vendor == 0x55 &&
+		    dev_netjet->subsystem_device == 0x02) {
+			printk(KERN_WARNING "Netjet: You tried to load this "
+			       "driver with an incompatible TigerJet-card\n");
+			printk(KERN_WARNING "Use type=41 for Formula-n "
+			       "enter:now ISDN PCI and compatible\n");
+			return 0;
 		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-
-		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);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0xC0;
-		cs->hw.njet.dmactrl = 0;
-
-		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-		switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) )
-		{
-			case 0 :
-				break;
-
-			case 3 :
-				printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
-				continue;
-
-			default :
-				printk( KERN_WARNING "NETjet-S: No PCI card found\n" );
-				return 0;
-                }
-                break;
-	}
-	printk(KERN_INFO
-		"NETjet-S: PCI card configured at %#lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
+		if (nj_s_probe(card->cs, dev_netjet))
+			return 1;
 		return 0;
-	
-	nj_s_reset(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &nj_s_ops;
-	isac_setup(cs, &netjet_dc_ops);
-	return 1;
+	}
+	printk(KERN_WARNING "NETjet-S: No PCI card found\n");
+	return 0;
 }
+
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/nj_u.c linux-2.5.64-bk4/drivers/isdn/hisax/nj_u.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/nj_u.c	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/nj_u.c	Mon Mar 31 12:25:45 2003
@@ -110,88 +110,85 @@
 	.irq_func = nj_u_interrupt,
 };
 
+static int __init
+nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	pci_set_master(pdev);
+
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.njet.pdev = pdev;
+	cs->hw.njet.base = pci_resource_start(pdev, 0);
+	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn"))
+		goto err;
+	
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
+
+	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);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
+	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	
+	cs->hw.njet.auxd = 0xC0;
+	cs->hw.njet.dmactrl = 0;
+	
+	byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
+	byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
+	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+
+	switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3)	{
+	case 3:
+		break;
+	case 0:
+		printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
+		goto err;
+	default:
+		printk(KERN_WARNING "NETspider-U: No PCI card found\n" );
+		goto err;
+	}
+	printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n",
+	       cs->hw.njet.base, cs->irq);
+
+	nj_u_reset(cs);
+	cs->card_ops = &nj_u_ops;
+	icc_setup(cs, &netjet_dc_ops);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_u(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
 	strcpy(tmp, NETjet_U_revision);
-	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp));
-
-	for ( ;; ) {
-		if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
-			if (pci_enable_device(dev_netjet))
-				return(0);
-			pci_set_master(dev_netjet);
-			cs->irq = dev_netjet->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
-			if (!cs->hw.njet.base) {
-				printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->hw.njet.pdev = dev_netjet;
-		} else {
-			printk(KERN_WARNING "NETspider-U: No PCI card found\n");
-			return(0);
-		}
-
-		cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
-		cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
-
-		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);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
-		byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-
-		cs->hw.njet.auxd = 0xC0;
-		cs->hw.njet.dmactrl = 0;
-
-		byteout(cs->hw.njet.auxa, 0);
-		byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
-		byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
-		byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
-
-		switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
-		{
-			case 3 :
-				break;
-
-			case 0 :
-				printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
-				continue;
-
-			default :
-				printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
-				return 0;
-                }
-                break;
-	}
-	printk(KERN_INFO
-		"NETspider-U: PCI card configured at %#lx IRQ %d\n",
-		cs->hw.njet.base, cs->irq);
-	if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
-		return 0;
+	printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 	
-	nj_u_reset(cs);
-	cs->irq_flags |= SA_SHIRQ;
-	cs->card_ops = &nj_u_ops;
-	icc_setup(cs, &netjet_dc_ops);
-	return 1;
+	dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				     PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
+	if (dev_netjet) {
+		if (nj_u_probe(card->cs, dev_netjet))
+			return 1;
+		return 0;
+	}
+	printk(KERN_WARNING "NETspider-U: No PCI card found\n");
+	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/s0box.c linux-2.5.64-bk4/drivers/isdn/hisax/s0box.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/s0box.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/s0box.c	Mon Mar 31 12:25:45 2003
@@ -172,14 +172,9 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_s0box(struct IsdnCard *card)
+static int __init
+s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, s0box_revision);
-	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
 	cs->hw.teles3.cfg_reg = card->para[1];
 	cs->hw.teles3.hscx[0] = -0x20;
 	cs->hw.teles3.hscx[1] = 0x0;
@@ -200,8 +195,20 @@
 	cs->card_ops = &s0box_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
-	return 0;
+	return -EBUSY;
+}
+
+int __init
+setup_s0box(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, s0box_revision);
+	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
+	if (s0box_probe(card->cs, card))
+		return 0;
+	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/saphir.c linux-2.5.64-bk4/drivers/isdn/hisax/saphir.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/saphir.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/saphir.c	Mon Mar 31 12:25:45 2003
@@ -201,36 +201,21 @@
 	.irq_func = saphir_interrupt,
 };
 
-int __init
-setup_saphir(struct IsdnCard *card)
+static int __init
+saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, saphir_rev);
-	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
-		return (0);
-
-	init_timer(&cs->hw.saphir.timer);
-	/* IO-Ports */
 	cs->hw.saphir.cfg_reg = card->para[1];
 	cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
 	cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
 	cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
 	cs->irq = card->para[0];
+
 	if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir"))
 		goto err;
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d io:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.saphir.cfg_reg);
+	printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
 
-	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
-	cs->hw.saphir.timer.data = (long) cs;
-	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
-	add_timer(&cs->hw.saphir.timer);
 	if (saphir_reset(cs))
 		goto err;
 
@@ -238,8 +223,27 @@
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
 
-	return 1;
- err:
-	saphir_release(cs);
+	init_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
+	cs->hw.saphir.timer.data = (long) cs;
+	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
+	add_timer(&cs->hw.saphir.timer);
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_saphir(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, saphir_rev);
+	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (saphir_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/sedlbauer.c linux-2.5.64-bk4/drivers/isdn/hisax/sedlbauer.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/sedlbauer.c	Tue Mar  4 19:29:53 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/sedlbauer.c	Mon Mar 31 12:25:45 2003
@@ -73,7 +73,6 @@
 #define SEDL_SPEEDFAX_PYRAMID	7
 #define SEDL_SPEEDFAX_PCI	8
 
-#define SEDL_CHIP_TEST		0
 #define SEDL_CHIP_ISAC_HSCX	1
 #define SEDL_CHIP_ISAC_ISAR	2
 #define SEDL_CHIP_IPAC		3
@@ -452,6 +451,241 @@
 	.irq_func    = sedlbauer_isar_interrupt,
 };
 
+static int __init
+sedl_ipac_probe(struct IsdnCardState *cs)
+{
+	u8 val;
+
+	cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+	val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
+	printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
+	return (val == 1 || val == 2);
+}
+
+static int __init
+sedl_ipac_init(struct IsdnCardState *cs)
+{
+	cs->card_ops = &sedlbauer_ipac_ops;
+	if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
+		return -ENODEV;
+	sedlbauer_reset(cs);
+	return 0;
+}
+
+static int __init
+sedl_isac_isar_init(struct IsdnCardState *cs)
+{
+	cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
+	cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
+	__set_bit(HW_ISAR, &cs->HW_Flags);
+	cs->card_ops = &sedlbauer_isar_ops;
+	cs->auxcmd = &isar_auxcmd;
+	isac_setup(cs, &isac_ops);
+	return isar_setup(cs, &isar_ops);
+}
+
+static int __init
+sedl_isac_hscx_init(struct IsdnCardState *cs)
+{
+	cs->card_ops = &sedlbauer_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -ENODEV;
+	sedlbauer_reset(cs);
+	return 0;
+}
+
+static int __init
+sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.sedl.cfg_reg = card->para[1];
+	cs->hw.sedl.bus = SEDL_BUS_ISA;
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn"))
+		goto err;
+
+	if (sedl_ipac_probe(cs)) {
+		cs->subtyp = SEDL_SPEED_WIN2_PC104;
+		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		if (sedl_ipac_init(cs))
+			goto err;
+	} else {
+		cs->subtyp = SEDL_SPEED_CARD_WIN;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
+		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
+		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
+		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
+		if (sedl_isac_hscx_init(cs))
+			goto err;
+	}
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
+	if (sedl_ipac_probe(cs)) {
+		cs->subtyp = SEDL_SPEED_STAR2;
+		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		if (sedl_ipac_init(cs))
+			goto err;
+	} else {
+		cs->subtyp = SEDL_SPEED_STAR;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
+		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
+		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
+		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+		if (sedl_isac_hscx_init(cs))
+			goto err;
+	}
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->subtyp = SEDL_SPEED_FAX;
+	cs->hw.sedl.bus = SEDL_BUS_ISA;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn"))
+		goto err;
+
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq);
+
+	cs->hw.sedl.adr = cs->hw.sedl.cfg_reg  + SEDL_ISAR_ISA_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
+	cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
+	cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0);
+	cs->hw.sedl.bus = SEDL_BUS_PCI;
+
+	if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn"))
+		return -EBUSY;
+
+	printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
+	       Sedlbauer_Types[cs->subtyp],
+	       cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq);
+
+	cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
+	cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
+	byteout(cs->hw.sedl.cfg_reg, 0xff);
+	byteout(cs->hw.sedl.cfg_reg, 0x00);
+	byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+	byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000);
+	byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
+	return 0;
+}
+
+static int __init
+sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEEDFAX_PCI;
+	cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
+	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
+	if (sedl_isac_isar_init(cs))
+		goto err;
+
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	if (pci_enable_device(pdev))
+		goto err;
+
+	cs->subtyp = SEDL_SPEED_PCI;
+	cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+	if (sedl_pci_init(cs, pdev))
+		goto err;
+
+	cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
+	cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+	if (sedl_ipac_init(cs))
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 static struct pci_dev *dev_sedl __devinitdata = NULL;
 
 #ifdef __ISAPNP__
@@ -472,265 +706,117 @@
 int __devinit
 setup_sedlbauer(struct IsdnCard *card)
 {
-	int bytecnt, val;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u16 sub_vendor_id, sub_id;
 
 	strcpy(tmp, Sedlbauer_revision);
-	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n",
+	       HiSax_getrev(tmp));
 	
- 	if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
- 		cs->subtyp = SEDL_SPEED_CARD_WIN;
-		cs->hw.sedl.bus = SEDL_BUS_ISA;
-		cs->hw.sedl.chip = SEDL_CHIP_TEST;
- 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
- 		cs->subtyp = SEDL_SPEED_STAR;
-		cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
-		cs->hw.sedl.chip = SEDL_CHIP_TEST;
- 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
- 		cs->subtyp = SEDL_SPEED_FAX;
-		cs->hw.sedl.bus = SEDL_BUS_ISA;
-		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
- 	} else
-		return (0);
-
-	bytecnt = 8;
 	if (card->para[1]) {
-		cs->hw.sedl.cfg_reg = card->para[1];
-		cs->irq = card->para[0];
-		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-			bytecnt = 16;
+		if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
+			if (sedl_card_win_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
+		} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
+			if (sedl_star_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
+		} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
+			if (sedl_fax_probe(card->cs, card) < 0)
+				return 0;
+			return 1;
 		}
-	} else {
+	}
 #ifdef __ISAPNP__
-		if (isapnp_present()) {
-			struct pnp_card *pb;
-			struct pnp_dev *pd;
-
-			while(pdev->card_vendor) {
-				if ((pb = pnp_find_card(pdev->card_vendor,
-						        pdev->card_device,
-						        pnp_c))) {
-					pnp_c = pb;
-					pd = NULL;
-					if ((pd = pnp_find_dev(pnp_c,
-							       pdev->vendor,
-							       pdev->function,
-							       pd))) {
-						printk(KERN_INFO "HiSax: %s detected\n",
-							(char *)pdev->driver_data);
-						if (pnp_device_attach(pd) < 0) {
-							printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
-							return 0;
-						}
-						if (pnp_activate_dev(pd) < 0) {
-							printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
-							pnp_device_detach(pd);
+	if (isapnp_present()) {
+		struct pnp_card *pb;
+		struct pnp_dev *pd;
+		
+		while(pdev->card_vendor) {
+			if ((pb = pnp_find_card(pdev->card_vendor,
+						pdev->card_device,
+						pnp_c))) {
+				pnp_c = pb;
+				pd = NULL;
+				if ((pd = pnp_find_dev(pnp_c,
+						       pdev->vendor,
+						       pdev->function,
+						       pd))) {
+					printk(KERN_INFO "HiSax: %s detected\n",
+					       (char *)pdev->driver_data);
+					if (pnp_device_attach(pd) < 0) {
+						printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
+						return 0;
+					}
+					if (pnp_activate_dev(pd) < 0) {
+						printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
+						pnp_device_detach(pd);
+						return 0;
+					}
+					if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
+						printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
+						       pnp_irq(pd, 0), pnp_port_start(pd, 0));
+						pnp_device_detach(pd);
+						goto err;
+					}
+					card->para[1] = pnp_port_start(pd, 0);
+					card->para[0] = pnp_irq(pd, 0);
+					cs->hw.sedl.cfg_reg = card->para[1];
+					cs->irq = card->para[0];
+					if (pdev->function == ISAPNP_FUNCTION(0x2)) {
+						if (sedl_fax_probe(card->cs, card))
 							return 0;
-						}
-						if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
-							printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
-								pnp_irq(pd, 0), pnp_port_start(pd, 0));
-							pnp_device_detach(pd);
-							goto err;
-						}
-						card->para[1] = pnp_port_start(pd, 0);
-						card->para[0] = pnp_irq(pd, 0);
-						cs->hw.sedl.cfg_reg = card->para[1];
-						cs->irq = card->para[0];
-						if (pdev->function == ISAPNP_FUNCTION(0x2)) {
-							cs->subtyp = SEDL_SPEED_FAX;
-							cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-							bytecnt = 16;
-						} else {
-							cs->subtyp = SEDL_SPEED_CARD_WIN;
-							cs->hw.sedl.chip = SEDL_CHIP_TEST;
-						}
-						goto ready;
+						return 1;
 					} else {
-						printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
-						goto err;
+						if (sedl_card_win_probe(card->cs, card))
+							return 0;
+						return 1;
 					}
+				} else {
+					printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
+					goto err;
 				}
-				pdev++;
-				pnp_c=NULL;
-			} 
-			if (!pdev->card_vendor) {
-				printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
 			}
+			pdev++;
+			pnp_c=NULL;
+		} 
+		if (!pdev->card_vendor) {
+			printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
 		}
+	}
 #endif
 /* Probe for Sedlbauer speed pci */
 #if CONFIG_PCI
-		if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
-				PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
-			if (pci_enable_device(dev_sedl))
-				goto err;
-			cs->irq = dev_sedl->irq;
-			if (!cs->irq) {
-				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
-				goto err;
-			}
-			cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
-		} else {
-			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
-			goto err;
-		}
-		cs->irq_flags |= SA_SHIRQ;
-		cs->hw.sedl.bus = SEDL_BUS_PCI;
+	dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
+				   PCI_DEVICE_ID_TIGERJET_100, dev_sedl);
+	if (dev_sedl) {
 		sub_vendor_id = dev_sedl->subsystem_vendor;
 		sub_id = dev_sedl->subsystem_device;
 		printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
-			sub_vendor_id, sub_id);
-		printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
-			cs->hw.sedl.cfg_reg);
+		       sub_vendor_id, sub_id);
 		if (sub_id != PCI_SUB_ID_SEDLBAUER) {
 			printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
-			goto err;
+			return 0;
 		}
 		if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
-			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-			cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
+			if (sedl_fax_pyramid_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		} else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
-			cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
-			cs->subtyp = SEDL_SPEEDFAX_PCI;
+			if (sedl_fax_pci_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		} else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
-			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-			cs->subtyp = SEDL_SPEED_PCI;
-		} else {
-			printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
-				sub_vendor_id);
-			goto err;
-		}
-		bytecnt = 256;
-		cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
-		cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
-		byteout(cs->hw.sedl.cfg_reg, 0xff);
-		byteout(cs->hw.sedl.cfg_reg, 0x00);
-		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
-		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);
-		byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
-#endif /* CONFIG_PCI */
-	}	
-ready:	
-	/* In case of the sedlbauer pcmcia card, this region is in use,
-	 * reserved for us by the card manager. So we do not check it
-	 * here, it would fail.
-	 */
-	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA) {
-		if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn"))
-			goto err;
-	}
-
-	printk(KERN_INFO
-	       "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
-	       cs->hw.sedl.cfg_reg,
-	       cs->hw.sedl.cfg_reg + bytecnt,
-	       cs->irq);
-
-/*
- * testing ISA and PCMCIA Cards for IPAC, default is ISAC
- * do not test for PCI card, because ports are different
- * and PCI card uses only IPAC (for the moment)
- */	
-	if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-		val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC,
-			      IPAC_ID);
-		printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
-	        if ((val == 1) || (val == 2)) {
-			/* IPAC */
-			cs->subtyp = SEDL_SPEED_WIN2_PC104;
-			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
-				cs->subtyp = SEDL_SPEED_STAR2;
-			}
-			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
-		} else {
-			/* ISAC_HSCX oder ISAC_ISAR */
-			if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
-				cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
-			}
-		}
-	}
-
-/*
- * hw.sedl.chip is now properly set
- */
-	printk(KERN_INFO "Sedlbauer: %s detected\n",
-		Sedlbauer_Types[cs->subtyp]);
-
-
-	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
-		if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
-	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
-			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
-			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
-		} else {
-	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
-			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
-			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
-		}
-		cs->card_ops = &sedlbauer_ipac_ops;
-		if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
-			goto err;
-		sedlbauer_reset(cs);
-	} else {
-		/* ISAC_HSCX oder ISAC_ISAR */
-		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-			if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_PCI_ISAR;
-			} else {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR_RESET_ON;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
-							SEDL_ISAR_ISA_ISAR_RESET_OFF;
-			}
-			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
-			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
-			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
-			cs->card_ops = &sedlbauer_isar_ops;
-			cs->auxcmd = &isar_auxcmd;
-			isac_setup(cs, &isac_ops);
-			if (isar_setup(cs, &isar_ops))
-				goto err;
-		} else {
-			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
-			} else {
-				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
-				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
-				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
-				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
-				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
-			}
-			cs->card_ops = &sedlbauer_ops;
-			if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-				goto err;
-
-			sedlbauer_reset(cs);
+			if (sedl_pci_probe(cs, dev_sedl))
+				return 0;
+			return 1;
 		}
+		printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
+		       sub_vendor_id);
+		return 0;
 	}
-	return 1;
- err:
-	hisax_release_resources(cs);
+#endif /* CONFIG_PCI */
 	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/sportster.c linux-2.5.64-bk4/drivers/isdn/hisax/sportster.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/sportster.c	Tue Mar  4 19:29:00 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/sportster.c	Mon Mar 31 12:25:45 2003
@@ -189,42 +189,29 @@
 	}
 	return 0;
 }
-  
-int __init
-setup_sportster(struct IsdnCard *card)
-{
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, sportster_revision);
-	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp));
 
-	cs->hw.spt.cfg_reg = card->para[1];
+static int __init
+sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
 	cs->irq = card->para[0];
+	cs->hw.spt.cfg_reg = card->para[1];
 	if (!get_io_range(cs))
-		return (0);
+		return -EBUSY;
 	cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC;
 	cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA;
 	cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB;
 	
 	switch(cs->irq) {
-		case 5:	cs->hw.spt.res_irq = 1;
-			break;
-		case 7:	cs->hw.spt.res_irq = 2;
-			break;
-		case 10:cs->hw.spt.res_irq = 3;
-			break;
-		case 11:cs->hw.spt.res_irq = 4;
-			break;
-		case 12:cs->hw.spt.res_irq = 5;
-			break;
-		case 14:cs->hw.spt.res_irq = 6;
-			break;
-		case 15:cs->hw.spt.res_irq = 7;
-			break;
-		default:sportster_release(cs);
-			printk(KERN_WARNING "Sportster: wrong IRQ\n");
-			return(0);
+	case 5:	cs->hw.spt.res_irq = 1;	break;
+	case 7:	cs->hw.spt.res_irq = 2;	break;
+	case 10:cs->hw.spt.res_irq = 3;	break;
+	case 11:cs->hw.spt.res_irq = 4;	break;
+	case 12:cs->hw.spt.res_irq = 5;	break;
+	case 14:cs->hw.spt.res_irq = 6;	break;
+	case 15:cs->hw.spt.res_irq = 7;	break;
+	default:
+		printk(KERN_WARNING "Sportster: wrong IRQ\n");
+		goto err;
 	}
 	sportster_reset(cs);
 	printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
@@ -234,8 +221,22 @@
 	cs->card_ops = &sportster_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
- err:
-	hisax_release_resources(cs);
 	return 0;
+ err:
+	sportster_release(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_sportster(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, sportster_revision);
+	printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (sportster_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/teleint.c linux-2.5.64-bk4/drivers/isdn/hisax/teleint.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/teleint.c	Tue Mar  4 19:29:55 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/teleint.c	Mon Mar 31 12:25:45 2003
@@ -256,15 +256,9 @@
 	.irq_func = teleint_interrupt,
 };
 
-int __init
-setup_TeleInt(struct IsdnCard *card)
+static int __init
+teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, TeleInt_revision);
-	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
-
 	cs->hw.hfc.addr = card->para[1] & 0x3fe;
 	cs->irq = card->para[0];
 	cs->hw.hfc.cirm = HFC_CIRM;
@@ -284,42 +278,54 @@
 	byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
 	byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
 	switch (cs->irq) {
-		case 3:
-			cs->hw.hfc.cirm |= HFC_INTA;
-			break;
-		case 4:
-			cs->hw.hfc.cirm |= HFC_INTB;
-			break;
-		case 5:
-			cs->hw.hfc.cirm |= HFC_INTC;
-			break;
-		case 7:
-			cs->hw.hfc.cirm |= HFC_INTD;
-			break;
-		case 10:
-			cs->hw.hfc.cirm |= HFC_INTE;
-			break;
-		case 11:
-			cs->hw.hfc.cirm |= HFC_INTF;
-			break;
-		default:
-			printk(KERN_WARNING "TeleInt: wrong IRQ\n");
-			goto err;
+	case 3:
+		cs->hw.hfc.cirm |= HFC_INTA;
+		break;
+	case 4:
+		cs->hw.hfc.cirm |= HFC_INTB;
+		break;
+	case 5:
+		cs->hw.hfc.cirm |= HFC_INTC;
+		break;
+	case 7:
+		cs->hw.hfc.cirm |= HFC_INTD;
+		break;
+	case 10:
+		cs->hw.hfc.cirm |= HFC_INTE;
+		break;
+	case 11:
+		cs->hw.hfc.cirm |= HFC_INTF;
+		break;
+	default:
+		printk(KERN_WARNING "TeleInt: wrong IRQ\n");
+		goto err;
 	}
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
 
-	printk(KERN_INFO
-	       "TeleInt: defined at 0x%x IRQ %d\n",
-	       cs->hw.hfc.addr,
-	       cs->irq);
+	printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
+	       cs->hw.hfc.addr, cs->irq);
 
 	cs->card_ops = &teleint_ops;
 	teleint_reset(cs);
 	isac_setup(cs, &isac_ops);
 	hfc_setup(cs, &hfc_ops);
-	return 1;
- err:
-	teleint_release(cs);
 	return 0;
+
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_TeleInt(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, TeleInt_revision);
+	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
+
+	if (teleint_probe(card->cs, card) < 0)
+		return 0;
+	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/teles0.c linux-2.5.64-bk4/drivers/isdn/hisax/teles0.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/teles0.c	Tue Mar  4 19:29:19 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/teles0.c	Mon Mar 31 12:25:45 2003
@@ -165,72 +165,95 @@
 	.irq_func = hscxisac_irq,
 };
 
-int __init
-setup_teles0(struct IsdnCard *card)
+static int __init
+teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
 {
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, teles0_revision);
-	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ == ISDN_CTYPE_16_0)
-		cs->hw.teles0.cfg_reg = card->para[2];
-	else			/* 8.0 */
-		cs->hw.teles0.cfg_reg = 0;
-
-	if (card->para[1] < 0x10000) {
-		card->para[1] <<= 4;
-		printk(KERN_INFO
-		   "Teles0: membase configured DOSish, assuming 0x%lx\n",
-		       (unsigned long) card->para[1]);
-	}
 	cs->irq = card->para[0];
-	if (cs->hw.teles0.cfg_reg) {
-		if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
-			goto err;
-
-		if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 0, val);
-			goto err;
-		}
-		if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 1, val);
-			goto err;
-		}
-		val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
-							 * 0x1f=with AB
-							 * 0x1c 16.3 ???
-							 */
-		if (val != 0x1e && val != 0x1f) {
-			printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
-			       cs->hw.teles0.cfg_reg + 2, val);
-			goto err;
-		}
-	}
 	/* 16.0 and 8.0 designed for IOM1 */
 	test_and_set_bit(HW_IOM1, &cs->HW_Flags);
 	cs->hw.teles0.phymem = card->para[1];
-	cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem");
+	cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem,
+					     TELES_IOMEM_SIZE, "teles iomem");
 	if (!cs->hw.teles0.membase)
-		goto err;
+		return -EBUSY;
 
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d mem:0x%p cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
 	if (teles0_reset(cs)) {
 		printk(KERN_WARNING "Teles0: wrong IRQ\n");
-		goto err;
+		return -EBUSY;
 	}
 	cs->card_ops = &teles0_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-  		goto err;
-	return 1;
+		return -EBUSY;
+
+	return 0;
+}
+
+static int __init
+teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->hw.teles0.cfg_reg = card->para[2];
+	if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
+		goto err;
+		
+	if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 0, val);
+		goto err;
+	}
+	if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 1, val);
+		goto err;
+	}
+	val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
+						 * 0x1f=with AB
+						 * 0x1c 16.3 ???
+						 */
+	if (val != 0x1e && val != 0x1f) {
+		printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
+		       cs->hw.teles0.cfg_reg + 2, val);
+		goto err;
+	}
+	if (teles0_probe(cs, card) < 0)
+		goto err;
 
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles0.cfg_reg = 0;
+
+	if (teles0_probe(cs, card) < 0)
+		goto err;
+
 	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+int __init
+setup_teles0(struct IsdnCard *card)
+{
+	char tmp[64];
+
+	strcpy(tmp, teles0_revision);
+	printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+
+	if (card->cs->typ == ISDN_CTYPE_16_0) {
+		if (teles16_0_probe(card->cs, card) < 0)
+			return 0;
+	} else {
+		if (teles8_0_probe(card->cs, card) < 0)
+			return 0;
+	}
+	return 1;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/teles3.c linux-2.5.64-bk4/drivers/isdn/hisax/teles3.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/teles3.c	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/teles3.c	Mon Mar 31 12:25:45 2003
@@ -176,6 +176,152 @@
 	.irq_func = hscxisac_irq,
 };
 
+static int
+teles_hw_init(struct IsdnCardState *cs)
+{
+	
+	printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X  cfg:0x%X\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
+	printk(KERN_INFO "HiSax: hscx A:0x%X  hscx B:0x%X\n",
+	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
+
+	if (teles3_reset(cs)) {
+		printk(KERN_WARNING "Teles3: wrong IRQ\n");
+		return -EBUSY;
+	}
+	cs->card_ops = &teles3_ops;
+	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
+		return -EBUSY;
+	return 0;
+}
+
+static void __init
+teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->irq = card->para[0];
+	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
+	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
+	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
+}
+
+static int __init
+telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = 0;
+	cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
+	cs->hw.teles3.hscx[1] = card->para[1];
+	cs->hw.teles3.isac = card->para[1] + 0x20;
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, 
+			"HiSax Teles PCMCIA"))
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+teles_request_io(struct IsdnCardState *cs)
+{
+	if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
+		return -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A"))
+		return -EBUSY;
+	if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B"))
+		return -EBUSY;
+	return 0;
+}
+
+static int __init
+teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	u8 val;
+
+	cs->hw.teles3.cfg_reg = card->para[1];
+	switch (cs->hw.teles3.cfg_reg) {
+	case 0x180:
+	case 0x280:
+	case 0x380:
+		cs->hw.teles3.cfg_reg |= 0xc00;
+		break;
+	}
+	cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
+	cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
+	cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
+		goto err;
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 0, val);
+		goto err;
+	}
+	if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 1, val);
+		goto err;
+	}
+	/* 0x1e without AB, 0x1f with AB,  0x1c 16.3 ???, 
+	 * 0x39 16.3 1.1,   0x38 16.3 1.3, 0x46 16.3 with AB + Video */
+	val = bytein(cs->hw.teles3.cfg_reg + 2);
+	if (val != 0x46 && val != 0x39 && val != 0x38 && 
+	    val != 0x1c && val != 0x1e && val != 0x1f) {
+		printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
+		       cs->hw.teles3.cfg_reg + 2, val);
+		goto err;
+	}
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = card->para[3];
+	cs->hw.teles3.isac = card->para[2] - 32;
+	cs->hw.teles3.hscx[0] = card->para[1] - 32;
+	cs->hw.teles3.hscx[1] = card->para[1];
+	teles_setup_io(cs, card);
+	if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
+		goto err;
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
+static int __init
+telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
+{
+	cs->hw.teles3.cfg_reg = 0;
+	cs->hw.teles3.isac = card->para[1] - 32;
+	cs->hw.teles3.hscx[0] = card->para[2] - 32;
+	cs->hw.teles3.hscx[1] = card->para[2];
+	teles_setup_io(cs, card);
+	if (teles_request_io(cs) < 0)
+		goto err;
+	if (teles_hw_init(cs) < 0)
+		goto err;
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return -EBUSY;
+}
+
 #ifdef __ISAPNP__
 static struct isapnp_device_id teles_ids[] __initdata = {
 	{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
@@ -197,16 +343,10 @@
 int __devinit
 setup_teles3(struct IsdnCard *card)
 {
-	u8 val;
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, teles3_revision);
 	printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp));
-	if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP)
-	    && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
-		return (0);
-
 #ifdef __ISAPNP__
 	if (!card->para[1] && isapnp_present()) {
 		struct pnp_card *pnp_card;
@@ -258,100 +398,18 @@
 		}
 	}
 #endif
-	if (cs->typ == ISDN_CTYPE_16_3) {
-		cs->hw.teles3.cfg_reg = card->para[1];
-		switch (cs->hw.teles3.cfg_reg) {
-			case 0x180:
-			case 0x280:
-			case 0x380:
-				cs->hw.teles3.cfg_reg |= 0xc00;
-				break;
-		}
-		cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
-		cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
-		cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
-	} else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		cs->hw.teles3.cfg_reg = 0;
-		cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
-		cs->hw.teles3.hscx[1] = card->para[1];
-		cs->hw.teles3.isac = card->para[1] + 0x20;
-	} else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-		cs->hw.teles3.cfg_reg = card->para[3];
-		cs->hw.teles3.isac = card->para[2] - 32;
-		cs->hw.teles3.hscx[0] = card->para[1] - 32;
-		cs->hw.teles3.hscx[1] = card->para[1];
+	if (card->cs->typ == ISDN_CTYPE_16_3) {
+		if (teles16_3_probe(card->cs, card) < 0)
+			return 0;
+	} else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) {
+		if (telespcmcia_probe(card->cs, card) < 0)
+			return 0;
+	} else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
+		if (compaq_probe(card->cs, card) < 0)
+			return 0;
 	} else {	/* PNP */
-		cs->hw.teles3.cfg_reg = 0;
-		cs->hw.teles3.isac = card->para[1] - 32;
-		cs->hw.teles3.hscx[0] = card->para[2] - 32;
-		cs->hw.teles3.hscx[1] = card->para[2];
+		if (telespnp_probe(card->cs, card) < 0)
+			return 0;
 	}
-	cs->irq = card->para[0];
-	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
-	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
-	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
-	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA"))
-			goto err;
-	} else {
-		if (cs->hw.teles3.cfg_reg) {
-			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-				if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
-					goto err;
-			} else {
-				if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
-					goto err;
-			}
-		}
-		if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A"))
-			goto err;
-		if (!request_io(&cs->rs, cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B"))
-			goto err;
-	}
-	if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
-		if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 0, val);
-			goto err;
-		}
-		if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 1, val);
-			goto err;
-		}
-		val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB
-							 * 0x1f=with AB
-							 * 0x1c 16.3 ???
-							 * 0x39 16.3 1.1
-							 * 0x38 16.3 1.3
-							 * 0x46 16.3 with AB + Video (Teles-Vision)
-							 */
-		if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
-			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
-			       cs->hw.teles3.cfg_reg + 2, val);
-			goto err;
-		}
-	}
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d isac:0x%X  cfg:0x%X\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
-	printk(KERN_INFO
-	       "HiSax: hscx A:0x%X  hscx B:0x%X\n",
-	       cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
-
-	if (teles3_reset(cs)) {
-		printk(KERN_WARNING "Teles3: wrong IRQ\n");
-		goto err;
-	}
-	cs->card_ops = &teles3_ops;
-	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
-		goto err;
 	return 1;
- err:
-	hisax_release_resources(cs);
-	return 0;
-
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/telespci.c linux-2.5.64-bk4/drivers/isdn/hisax/telespci.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/telespci.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/telespci.c	Mon Mar 31 12:25:45 2003
@@ -231,36 +231,23 @@
 	.irq_func = telespci_interrupt,
 };
 
-static struct pci_dev *dev_tel __initdata = NULL;
-
-int __init
-setup_telespci(struct IsdnCard *card)
+static int __init
+telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
 {
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
+	int rc;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-	strcpy(tmp, telespci_revision);
-	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
-	if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
-		if (pci_enable_device(dev_tel))
-			return(0);
-		cs->irq = dev_tel->irq;
-		if (!cs->irq) {
-			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
-			return(0);
-		}
-		cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(dev_tel, 0), 4096, "telespci");
-		if (!cs->hw.teles0.membase)
-			goto err;
-		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
-			pci_resource_start(dev_tel, 0), dev_tel->irq);
-	} else {
-		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
-		return(0);
-	}
+	printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n",
+	       pci_resource_start(pdev, 0), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci");
+	if (!cs->hw.teles0.membase)
+		goto err;
 
 	/* Initialize Zoran PCI controller */
 	writel(0x00000000, cs->hw.teles0.membase + 0x28);
@@ -270,17 +257,36 @@
 	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
 	writel(0x61000000, cs->hw.teles0.membase + 0x40);
 	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d mem:%p\n",
-	       CardType[cs->typ], cs->irq,
-	       cs->hw.teles0.membase);
 
-	cs->irq_flags |= SA_SHIRQ;
 	cs->card_ops = &telespci_ops;
 	if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
 		goto err;
-	return 1;
+	return 0;
  err:
 	hisax_release_resources(cs);
+	return rc;
+}
+
+static struct pci_dev *dev_tel __initdata = NULL;
+
+int __init
+setup_telespci(struct IsdnCard *card)
+{
+	char tmp[64];
+
+#ifdef __BIG_ENDIAN
+#error "not running on big endian machines now"
+#endif
+	strcpy(tmp, telespci_revision);
+	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n",
+	       HiSax_getrev(tmp));
+	dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN, 
+				  PCI_DEVICE_ID_ZORAN_36120, dev_tel);
+	if (dev_tel) {
+		if (telespci_probe(card->cs, dev_tel) < 0)
+			return 0;
+		return 1;
+	}
+	printk(KERN_WARNING "TelesPCI: No PCI card found\n");
 	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/hisax/w6692.c linux-2.5.64-bk4/drivers/isdn/hisax/w6692.c
--- linux-2.5.64-bk3/drivers/isdn/hisax/w6692.c	Tue Mar  4 19:29:34 2003
+++ linux-2.5.64-bk4/drivers/isdn/hisax/w6692.c	Mon Mar 31 12:25:45 2003
@@ -669,11 +669,11 @@
 static struct pci_dev *dev_w6692 __initdata = NULL;
 
 static int
-w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops,
-	    struct bc_hw_ops *bc_ops)
+w6692_hw_init(struct IsdnCardState *cs)
 {
-	cs->dc_hw_ops = dc_ops;
-	cs->bc_hw_ops = bc_ops;
+	cs->card_ops = &w6692_ops;
+	cs->dc_hw_ops = &w6692_dc_hw_ops, 
+	cs->bc_hw_ops = &w6692_bc_hw_ops;
 	dc_l1_init(cs, &w6692_dc_l1_ops);
 	cs->bc_l1_ops = &w6692_bc_l1_ops;
 	W6692Version(cs, "W6692:");
@@ -685,14 +685,45 @@
 	return 0;
 }
 
+static int __init
+w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
+{
+	int rc;
+
+	printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n",
+	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
+	       pci_resource_start(pdev, 1), pdev->irq);
+	
+	rc = -EBUSY;
+	if (pci_enable_device(pdev))
+		goto err;
+			
+	/* USR ISDN PCI card TA need some special handling */
+	if (cs->subtyp == W6692_WINBOND) {
+		if (pdev->subsystem_vendor == W6692_SV_USR  &&
+		    pdev->subsystem_device == W6692_SD_USR) {
+			cs->subtyp = W6692_USR;
+		}
+	}
+	cs->irq = pdev->irq;
+	cs->irq_flags |= SA_SHIRQ;
+	cs->hw.w6692.iobase = pci_resource_start(pdev, 1);
+	
+	if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100,
+			id_list[cs->subtyp].card_name))
+		goto err;
+
+	w6692_hw_init(cs);
+	return 0;
+ err:
+	hisax_release_resources(cs);
+	return rc;
+}
+
 int __init 
 setup_w6692(struct IsdnCard *card)
 {
-	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-	u8 found = 0;
-	u8 pci_irq = 0;
-	u_int pci_ioaddr = 0;
 
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
@@ -704,54 +735,13 @@
 					    id_list[id_idx].device_id,
 					    dev_w6692);
 		if (dev_w6692) {
-			if (pci_enable_device(dev_w6692))
-				continue;
-			cs->subtyp = id_idx;
-			break;
+			card->cs->subtyp = id_idx;
+			if (w6692_probe(card->cs, dev_w6692) < 0)
+				return 0;
+			return 1;
 		}
 		id_idx++;
 	}
-	if (dev_w6692) {
-		found = 1;
-		pci_irq = dev_w6692->irq;
-		/* I think address 0 is allways the configuration area */
-		/* and address 1 is the real IO space KKe 03.09.99 */
-		pci_ioaddr = pci_resource_start(dev_w6692, 1);
-		/* USR ISDN PCI card TA need some special handling */
-		if (cs->subtyp == W6692_WINBOND) {
-			if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
-			    (W6692_SD_USR == dev_w6692->subsystem_device)) {
-				cs->subtyp = W6692_USR;
-			}
-		}
-	}
-	if (!found) {
-		printk(KERN_WARNING "W6692: No PCI card found\n");
-		return (0);
-	}
-	cs->irq = pci_irq;
-	if (!cs->irq) {
-		printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
-		return (0);
-	}
-	if (!pci_ioaddr) {
-		printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
-		return (0);
-	}
-	cs->hw.w6692.iobase = pci_ioaddr;
-	printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
-	       id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
-	       pci_ioaddr, pci_irq);
-	if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, id_list[cs->subtyp].card_name))
-		return 0;
-	
-	printk(KERN_INFO
-	       "HiSax: %s config irq:%d I/O:%x\n",
-	       id_list[cs->subtyp].card_name, cs->irq,
-	       cs->hw.w6692.iobase);
-
-	cs->card_ops = &w6692_ops;
-	w6692_setup(cs, &w6692_dc_hw_ops, &w6692_bc_hw_ops);
-	cs->irq_flags |= SA_SHIRQ;
-	return (1);
+	printk(KERN_WARNING "W6692: No PCI card found\n");
+	return 0;
 }
diff -urN linux-2.5.64-bk3/drivers/isdn/i4l/Kconfig linux-2.5.64-bk4/drivers/isdn/i4l/Kconfig
--- linux-2.5.64-bk3/drivers/isdn/i4l/Kconfig	Tue Mar  4 19:29:15 2003
+++ linux-2.5.64-bk4/drivers/isdn/i4l/Kconfig	Mon Mar 31 12:25:45 2003
@@ -85,7 +85,7 @@
 
 config ISDN_X25
 	bool "X.25 PLP on top of ISDN"
-	depends on X25
+	depends on X25 && BROKEN
 	help
 	  This feature provides the X.25 protocol over ISDN connections.
 	  See <file:Documentation/isdn/README.x25> for more information
diff -urN linux-2.5.64-bk3/drivers/isdn/i4l/isdn_net_lib.c linux-2.5.64-bk4/drivers/isdn/i4l/isdn_net_lib.c
--- linux-2.5.64-bk3/drivers/isdn/i4l/isdn_net_lib.c	Tue Mar  4 19:28:56 2003
+++ linux-2.5.64-bk4/drivers/isdn/i4l/isdn_net_lib.c	Mon Mar 31 12:25:45 2003
@@ -58,6 +58,7 @@
 #include "isdn_net.h"
 #include "isdn_ppp.h"
 #include "isdn_ciscohdlck.h"
+#include "isdn_concap.h"
 
 #define ISDN_NET_TX_TIMEOUT (20*HZ) 
 
diff -urN linux-2.5.64-bk3/drivers/isdn/i4l/isdn_ppp.c linux-2.5.64-bk4/drivers/isdn/i4l/isdn_ppp.c
--- linux-2.5.64-bk3/drivers/isdn/i4l/isdn_ppp.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/drivers/isdn/i4l/isdn_ppp.c	Mon Mar 31 12:25:45 2003
@@ -867,7 +867,7 @@
 		skb_pull(skb, 1);
 	} else {
 		if (skb->len < 2)
-			return -1;
+			return -EINVAL;
 		get_u16(skb->data, proto);
 		skb_pull(skb, 2);
 	}
@@ -1037,7 +1037,7 @@
                 isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1);
 
 	ippp_push_proto(ind_ppp, skb, proto);
-	ippp_mp_xmit(idev, skb, proto);
+	ippp_mp_xmit(idev, skb);
 	return 0;
 
  drop:
diff -urN linux-2.5.64-bk3/drivers/isdn/i4l/isdn_ppp_mp.c linux-2.5.64-bk4/drivers/isdn/i4l/isdn_ppp_mp.c
--- linux-2.5.64-bk3/drivers/isdn/i4l/isdn_ppp_mp.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/drivers/isdn/i4l/isdn_ppp_mp.c	Mon Mar 31 12:25:45 2003
@@ -91,12 +91,13 @@
 }
 
 void
-ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
 {
 	struct ind_ppp *ind_ppp = idev->ind_priv;
 	struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
 	unsigned char *p;
-	long txseq;
+	u32 txseq;
+	u16 proto;
 
 	if (!(inl_ppp->mp_cfg & SC_MP_PROT)) {
 		return ippp_xmit(idev, skb);
diff -urN linux-2.5.64-bk3/drivers/isdn/i4l/isdn_ppp_mp.h linux-2.5.64-bk4/drivers/isdn/i4l/isdn_ppp_mp.h
--- linux-2.5.64-bk3/drivers/isdn/i4l/isdn_ppp_mp.h	Tue Mar  4 19:29:58 2003
+++ linux-2.5.64-bk4/drivers/isdn/i4l/isdn_ppp_mp.h	Mon Mar 31 12:25:45 2003
@@ -19,7 +19,7 @@
 int  ippp_mp_bind(isdn_net_dev *idev);
 void ippp_mp_disconnected(isdn_net_dev *idev);
 int  ippp_mp_bundle(isdn_net_dev *idev, int val);
-void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
+void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb);
 void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
 
 #else
@@ -42,9 +42,9 @@
 }
 
 static inline void
-ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
+ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
 {
-	ippp_xmit(idev, skb, proto);
+	ippp_xmit(idev, skb);
 }
 
 static inline void 
diff -urN linux-2.5.64-bk3/drivers/md/dm.c linux-2.5.64-bk4/drivers/md/dm.c
--- linux-2.5.64-bk3/drivers/md/dm.c	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/drivers/md/dm.c	Mon Mar 31 12:25:45 2003
@@ -79,9 +79,8 @@
 		return -ENOMEM;
 
 	_major = major;
-	r = register_blkdev(_major, _name, &dm_blk_dops);
+	r = register_blkdev(_major, _name);
 	if (r < 0) {
-		DMERR("register_blkdev failed");
 		kmem_cache_destroy(_io_cache);
 		return r;
 	}
diff -urN linux-2.5.64-bk3/drivers/md/md.c linux-2.5.64-bk4/drivers/md/md.c
--- linux-2.5.64-bk3/drivers/md/md.c	Tue Mar  4 19:29:04 2003
+++ linux-2.5.64-bk4/drivers/md/md.c	Mon Mar 31 12:25:45 2003
@@ -2803,7 +2803,9 @@
 	idle = 1;
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
-		curr_events = disk->read_sectors + disk->write_sectors - disk->sync_io;
+		curr_events = disk_stat_read(disk, read_sectors) + 
+				disk_stat_read(disk, write_sectors) - 
+				disk->sync_io;
 		if ((curr_events - rdev->last_events) > 32) {
 			rdev->last_events = curr_events;
 			idle = 0;
@@ -3214,11 +3216,10 @@
 			MD_MAJOR_VERSION, MD_MINOR_VERSION,
 			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
 
-	if (register_blkdev (MAJOR_NR, "md", &md_fops)) {
-		printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR);
-		return (-1);
-	}
-	devfs_mk_dir (NULL, "md", NULL);
+	if (register_blkdev(MAJOR_NR, "md"))
+		return -1;
+
+	devfs_mk_dir(NULL, "md", NULL);
 	blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE,
 				md_probe, NULL, NULL);
 	for (minor=0; minor < MAX_MD_DEVS; ++minor) {
diff -urN linux-2.5.64-bk3/drivers/message/i2o/i2o_block.c linux-2.5.64-bk4/drivers/message/i2o/i2o_block.c
--- linux-2.5.64-bk3/drivers/message/i2o/i2o_block.c	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk4/drivers/message/i2o/i2o_block.c	Mon Mar 31 12:25:46 2003
@@ -1608,12 +1608,8 @@
 	/*
 	 *	Register the block device interfaces
 	 */
-
-	if (register_blkdev(MAJOR_NR, "i2o_block", &i2ob_fops)) {
-		printk(KERN_ERR "Unable to get major number %d for i2o_block\n",
-		       MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "i2o_block"))
 		return -EIO;
-	}
 
 	for (i = 0; i < MAX_I2OB; i++) {
 		struct gendisk *disk = alloc_disk(16);
diff -urN linux-2.5.64-bk3/drivers/mtd/ftl.c linux-2.5.64-bk4/drivers/mtd/ftl.c
--- linux-2.5.64-bk3/drivers/mtd/ftl.c	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/drivers/mtd/ftl.c	Mon Mar 31 12:25:46 2003
@@ -1281,11 +1281,9 @@
 	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
 	DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n");
 
-	if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {
-		printk(KERN_NOTICE "ftl_cs: unable to grab major "
-		       "device number!\n");
+	if (register_blkdev(FTL_MAJOR, "ftl"))
 		return -EAGAIN;
-	}
+
 	blk_init_queue(&ftl_queue, &do_ftl_request, &lock);
 	register_mtd_user(&ftl_notifier);
 	return 0;
diff -urN linux-2.5.64-bk3/drivers/mtd/mtdblock.c linux-2.5.64-bk4/drivers/mtd/mtdblock.c
--- linux-2.5.64-bk3/drivers/mtd/mtdblock.c	Tue Mar  4 19:29:16 2003
+++ linux-2.5.64-bk4/drivers/mtd/mtdblock.c	Mon Mar 31 12:25:46 2003
@@ -570,11 +570,10 @@
 int __init init_mtdblock(void)
 {
 	spin_lock_init(&mtdblks_lock);
-	if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
-		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
-		       MTD_BLOCK_MAJOR);
+
+	if (register_blkdev(MAJOR_NR, DEVICE_NAME))
 		return -EAGAIN;
-	}
+
 #ifdef CONFIG_DEVFS_FS
 	devfs_mk_dir(NULL, DEVICE_NAME, NULL);
 #endif
diff -urN linux-2.5.64-bk3/drivers/mtd/mtdblock_ro.c linux-2.5.64-bk4/drivers/mtd/mtdblock_ro.c
--- linux-2.5.64-bk3/drivers/mtd/mtdblock_ro.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/drivers/mtd/mtdblock_ro.c	Mon Mar 31 12:25:46 2003
@@ -240,20 +240,13 @@
 
 int __init init_mtdblock(void)
 {
-	int err;
-
-	if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
-		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
-		       MTD_BLOCK_MAJOR);
-		err = -EAGAIN;
-		goto out;
-	}
+	if (register_blkdev(MAJOR_NR, DEVICE_NAME))
+		return -EAGAIN;
 
 	blk_init_queue(&mtdro_queue, &mtdblock_request, &mtdro_lock);
 	register_mtd_user(&notifier);
-	err = 0;
- out:
-	return err;
+
+	return 0;
 }
 
 static void __exit cleanup_mtdblock(void)
diff -urN linux-2.5.64-bk3/drivers/mtd/nftlcore.c linux-2.5.64-bk4/drivers/mtd/nftlcore.c
--- linux-2.5.64-bk3/drivers/mtd/nftlcore.c	Tue Mar  4 19:28:55 2003
+++ linux-2.5.64-bk4/drivers/mtd/nftlcore.c	Mon Mar 31 12:25:46 2003
@@ -928,10 +928,8 @@
 	printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.82 $, nftlmount.c %s\n", nftlmountrev);
 #endif
 
-	if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)) {
-		printk("unable to register NFTL block device on major %d\n", MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, "nftl"))
 		return -EBUSY;
-	}
 
 	blk_register_region(MKDEV(MAJOR_NR, 0), 256,
 			THIS_MODULE, nftl_probe, NULL, NULL);
diff -urN linux-2.5.64-bk3/drivers/net/bonding.c linux-2.5.64-bk4/drivers/net/bonding.c
--- linux-2.5.64-bk3/drivers/net/bonding.c	Tue Mar  4 19:29:38 2003
+++ linux-2.5.64-bk4/drivers/net/bonding.c	Mon Mar 31 12:25:46 2003
@@ -2574,6 +2574,13 @@
 		return 0;
 	}
 
+	if (bond->slave_cnt == 0) {
+		/* no slaves in the bond, frame not sent */
+		dev_kfree_skb(skb);
+		read_unlock_irqrestore(&bond->lock, flags);
+		return 0;
+	}
+	
 	slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;
 
 	while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {
diff -urN linux-2.5.64-bk3/drivers/net/eepro100.c linux-2.5.64-bk4/drivers/net/eepro100.c
--- linux-2.5.64-bk3/drivers/net/eepro100.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/drivers/net/eepro100.c	Mon Mar 31 12:25:46 2003
@@ -529,8 +529,6 @@
 static int eepro100_init_one(struct pci_dev *pdev,
 		const struct pci_device_id *ent);
 
-static void eepro100_remove_one (struct pci_dev *pdev);
-
 static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
 static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
@@ -843,6 +841,7 @@
 	sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
 	sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
 	init_timer(&sp->timer); /* used in ioctl() */
+	spin_lock_init(&sp->lock);
 
 	sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
 	if (card_idx >= 0) {
@@ -994,7 +993,6 @@
 	sp->dirty_tx = 0;
 	sp->last_cmd = 0;
 	sp->tx_full = 0;
-	spin_lock_init(&sp->lock);
 	sp->in_interrupt = 0;
 
 	/* .. we can safely take handler calls during init. */
diff -urN linux-2.5.64-bk3/drivers/s390/block/dasd_genhd.c linux-2.5.64-bk4/drivers/s390/block/dasd_genhd.c
--- linux-2.5.64-bk3/drivers/s390/block/dasd_genhd.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/s390/block/dasd_genhd.c	Mon Mar 31 12:25:46 2003
@@ -60,11 +60,8 @@
 	}
 
 	/* Register block device. */
-	new_major = register_blkdev(major, "dasd", &dasd_device_operations);
+	new_major = register_blkdev(major, "dasd");
 	if (new_major < 0) {
-		MESSAGE(KERN_WARNING,
-			"Cannot register to major no %d, rc = %d",
-			major, new_major);
 		kfree(mi);
 		return new_major;
 	}
diff -urN linux-2.5.64-bk3/drivers/s390/block/xpram.c linux-2.5.64-bk4/drivers/s390/block/xpram.c
--- linux-2.5.64-bk3/drivers/s390/block/xpram.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/s390/block/xpram.c	Mon Mar 31 12:25:46 2003
@@ -430,13 +430,11 @@
 	/*
 	 * Register xpram major.
 	 */
-	rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops);
-	if (rc < 0) {
-		PRINT_ERR("Can't get xpram major %d\n", XPRAM_MAJOR);
+	rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME);
+	if (rc < 0)
 		goto out;
-	}
 
-	devfs_mk_dir (NULL, "slram", NULL);
+	devfs_mk_dir(NULL, "slram", NULL);
 
 	/*
 	 * Assign the other needed values: make request function, sizes and
@@ -452,6 +450,7 @@
 	for (i = 0; i < xpram_devs; i++) {
 		struct gendisk *disk = xpram_disks[i];
 		char name[16];
+
 		xpram_devices[i].size = xpram_sizes[i] / 4;
 		xpram_devices[i].offset = offset;
 		offset += xpram_devices[i].size;
diff -urN linux-2.5.64-bk3/drivers/s390/char/tape_block.c linux-2.5.64-bk4/drivers/s390/char/tape_block.c
--- linux-2.5.64-bk3/drivers/s390/char/tape_block.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/s390/char/tape_block.c	Mon Mar 31 12:25:46 2003
@@ -333,12 +333,10 @@
 	int rc;
 
 	/* Register the tape major number to the kernel */
-	rc = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops);
-	if (rc < 0) {
-		PRINT_ERR("can't get major %d for block device\n",
-			  tapeblock_major);
+	rc = register_blkdev(tapeblock_major, "tBLK");
+	if (rc < 0)
 		return rc;
-	}
+
 	if (tapeblock_major == 0)
 		tapeblock_major = rc;
 	PRINT_INFO("tape gets major %d for block device\n", tapeblock_major);
diff -urN linux-2.5.64-bk3/drivers/sbus/char/jsflash.c linux-2.5.64-bk4/drivers/sbus/char/jsflash.c
--- linux-2.5.64-bk3/drivers/sbus/char/jsflash.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/drivers/sbus/char/jsflash.c	Mon Mar 31 12:25:46 2003
@@ -570,9 +570,7 @@
 		jsfd_disk[i] = disk;
 	}
 
-	if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) {
-		printk("jsfd_init: unable to get major number %d\n",
-		    JSFD_MAJOR);
+	if (register_blkdev(JSFD_MAJOR, "jsfd")) {
 		err = -EIO;
 		goto out;
 	}
diff -urN linux-2.5.64-bk3/drivers/scsi/sd.c linux-2.5.64-bk4/drivers/scsi/sd.c
--- linux-2.5.64-bk3/drivers/scsi/sd.c	Tue Mar  4 19:29:32 2003
+++ linux-2.5.64-bk4/drivers/scsi/sd.c	Mon Mar 31 12:25:46 2003
@@ -1389,14 +1389,9 @@
 
 	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
 
-	for (i = 0; i < SD_MAJORS; i++) {
-		if (register_blkdev(sd_major(i), "sd", &sd_fops))
-			printk(KERN_NOTICE
-			       "Unable to get major %d for SCSI disk\n",
-			       sd_major(i));
-		else
+	for (i = 0; i < SD_MAJORS; i++)
+		if (register_blkdev(sd_major(i), "sd") == 0)
 			majors++;
-	}
 
 	if (!majors)
 		return -ENODEV;
@@ -1409,7 +1404,7 @@
 }
 
 /**
- *	exit_sd - exit point for this driver (when it is	a module).
+ *	exit_sd - exit point for this driver (when it is a module).
  *
  *	Note: this function unregisters this driver from the scsi mid-level.
  **/
diff -urN linux-2.5.64-bk3/drivers/scsi/sr.c linux-2.5.64-bk4/drivers/scsi/sr.c
--- linux-2.5.64-bk3/drivers/scsi/sr.c	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/drivers/scsi/sr.c	Mon Mar 31 12:25:46 2003
@@ -835,7 +835,7 @@
 {
 	int rc;
 
-	rc = register_blkdev(SCSI_CDROM_MAJOR, "sr", &sr_bdops);
+	rc = register_blkdev(SCSI_CDROM_MAJOR, "sr");
 	if (rc)
 		return rc;
 	return scsi_register_device(&sr_template);
diff -urN linux-2.5.64-bk3/drivers/scsi/sym53c8xx_2/sym_hipd.c linux-2.5.64-bk4/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- linux-2.5.64-bk3/drivers/scsi/sym53c8xx_2/sym_hipd.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk4/drivers/scsi/sym53c8xx_2/sym_hipd.c	Mon Mar 31 12:25:46 2003
@@ -221,7 +221,7 @@
  */
 static void sym_soft_reset (hcb_p np)
 {
-	u_char istat;
+	u_char istat = 0;
 	int i;
 
 	if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN))
diff -urN linux-2.5.64-bk3/drivers/serial/8250.c linux-2.5.64-bk4/drivers/serial/8250.c
--- linux-2.5.64-bk3/drivers/serial/8250.c	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/drivers/serial/8250.c	Mon Mar 31 12:25:46 2003
@@ -1982,10 +1982,11 @@
 	.index		= -1,
 };
 
-static void __init serial8250_console_init(void)
+static int __init serial8250_console_init(void)
 {
 	serial8250_isa_init_ports();
 	register_console(&serial8250_console);
+	return 0;
 }
 console_initcall(serial8250_console_init);
 
diff -urN linux-2.5.64-bk3/drivers/video/Makefile linux-2.5.64-bk4/drivers/video/Makefile
--- linux-2.5.64-bk3/drivers/video/Makefile	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/drivers/video/Makefile	Mon Mar 31 12:25:47 2003
@@ -70,9 +70,6 @@
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
-# One by one these are being converted over to the new APIs
-#obj-$(CONFIG_FB_LEO)              += leofb.o sbusfb.o
-
 obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_CG6)               += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_CG3)               += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
@@ -85,6 +82,8 @@
 				      cfbfillrect.o
 obj-$(CONFIG_FB_TCX)               += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
 				      cfbfillrect.o
+obj-$(CONFIG_FB_LEO)               += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				      cfbfillrect.o
 
 # Files generated that shall be removed upon make clean
 clean-files := promcon_tbl.c
diff -urN linux-2.5.64-bk3/drivers/video/fbmem.c linux-2.5.64-bk4/drivers/video/fbmem.c
--- linux-2.5.64-bk3/drivers/video/fbmem.c	Tue Mar  4 19:28:52 2003
+++ linux-2.5.64-bk4/drivers/video/fbmem.c	Mon Mar 31 12:25:47 2003
@@ -158,6 +158,8 @@
 extern int p9100_setup(char*);
 extern int tcx_init(void);
 extern int tcx_setup(char*);
+extern int leo_init(void);
+extern int leo_setup(char*);
 
 static struct {
 	const char *name;
@@ -270,6 +272,9 @@
 #ifdef CONFIG_FB_TCX
 	{ "tcx", tcx_init, tcx_setup },
 #endif
+#ifdef CONFIG_FB_LEO
+	{ "leo", leo_init, leo_setup },
+#endif
 
 	/*
 	 * Generic drivers that are used as fallbacks
diff -urN linux-2.5.64-bk3/drivers/video/leo.c linux-2.5.64-bk4/drivers/video/leo.c
--- linux-2.5.64-bk3/drivers/video/leo.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.64-bk4/drivers/video/leo.c	Mon Mar 31 12:25:47 2003
@@ -0,0 +1,587 @@
+/* leo.c: LEO frame buffer driver
+ *
+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
+ *
+ * Driver layout based loosely on tgafb.c, see that file for credits.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/sbus.h>
+#include <asm/oplib.h>
+#include <asm/fbio.h>
+
+#include "sbuslib.h"
+
+/*
+ * Local functions.
+ */
+
+static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
+			 unsigned, struct fb_info *);
+static int leo_blank(int, struct fb_info *);
+
+static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
+static int leo_ioctl(struct inode *, struct file *, unsigned int,
+		     unsigned long, struct fb_info *);
+
+/*
+ *  Frame buffer operations
+ */
+
+static struct fb_ops leo_ops = {
+	.owner			= THIS_MODULE,
+	.fb_setcolreg		= leo_setcolreg,
+	.fb_blank		= leo_blank,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+	.fb_mmap		= leo_mmap,
+	.fb_ioctl		= leo_ioctl,
+	.fb_cursor		= soft_cursor,
+};
+
+#define LEO_OFF_LC_SS0_KRN	0x00200000UL
+#define LEO_OFF_LC_SS0_USR	0x00201000UL
+#define LEO_OFF_LC_SS1_KRN	0x01200000UL
+#define LEO_OFF_LC_SS1_USR	0x01201000UL
+#define LEO_OFF_LD_SS0		0x00400000UL
+#define LEO_OFF_LD_SS1		0x01400000UL
+#define LEO_OFF_LD_GBL		0x00401000UL
+#define LEO_OFF_LX_KRN		0x00600000UL
+#define LEO_OFF_LX_CURSOR	0x00601000UL
+#define LEO_OFF_SS0		0x00800000UL
+#define LEO_OFF_SS1		0x01800000UL
+#define LEO_OFF_UNK		0x00602000UL
+#define LEO_OFF_UNK2		0x00000000UL
+
+#define LEO_CUR_ENABLE		0x00000080
+#define LEO_CUR_UPDATE		0x00000030
+#define LEO_CUR_PROGRESS	0x00000006
+#define LEO_CUR_UPDATECMAP	0x00000003
+
+#define LEO_CUR_TYPE_MASK	0x00000000
+#define LEO_CUR_TYPE_IMAGE	0x00000020
+#define LEO_CUR_TYPE_CMAP	0x00000050
+
+struct leo_cursor {
+	u8		xxx0[16];
+	volatile u32	cur_type;
+	volatile u32	cur_misc;
+	volatile u32	cur_cursxy;
+	volatile u32	cur_data;
+};
+
+#define LEO_KRN_TYPE_CLUT0	0x00001000
+#define LEO_KRN_TYPE_CLUT1	0x00001001
+#define LEO_KRN_TYPE_CLUT2	0x00001002
+#define LEO_KRN_TYPE_WID	0x00001003
+#define LEO_KRN_TYPE_UNK	0x00001006
+#define LEO_KRN_TYPE_VIDEO	0x00002003
+#define LEO_KRN_TYPE_CLUTDATA	0x00004000
+#define LEO_KRN_CSR_ENABLE	0x00000008
+#define LEO_KRN_CSR_PROGRESS	0x00000004
+#define LEO_KRN_CSR_UNK		0x00000002
+#define LEO_KRN_CSR_UNK2	0x00000001
+
+struct leo_lx_krn {
+	volatile u32	krn_type;
+	volatile u32	krn_csr;
+	volatile u32	krn_value;
+};
+
+struct leo_lc_ss0_krn {
+	volatile u32 	misc;
+	u8		xxx0[0x800-4];
+	volatile u32	rev;
+};
+
+struct leo_lc_ss0_usr {
+	volatile u32	csr;
+	volatile u32	addrspace;
+	volatile u32 	fontmsk;
+	volatile u32	fontt;
+	volatile u32	extent;
+	volatile u32	src;
+	u32		dst;
+	volatile u32	copy;
+	volatile u32	fill;
+};
+
+struct leo_lc_ss1_krn {
+	u8	unknown;
+};
+
+struct leo_lc_ss1_usr {
+	u8	unknown;
+};
+
+struct leo_ld {
+	u8		xxx0[0xe00];
+	volatile u32	csr;
+	volatile u32	wid;
+	volatile u32	wmask;
+	volatile u32	widclip;
+	volatile u32	vclipmin;
+	volatile u32	vclipmax;
+	volatile u32	pickmin;	/* SS1 only */
+	volatile u32	pickmax;	/* SS1 only */
+	volatile u32	fg;
+	volatile u32	bg;
+	volatile u32	src;		/* Copy/Scroll (SS0 only) */
+	volatile u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
+	volatile u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
+	u32		xxx1[3];
+	volatile u32	setsem;		/* SS1 only */
+	volatile u32	clrsem;		/* SS1 only */
+	volatile u32	clrpick;	/* SS1 only */
+	volatile u32	clrdat;		/* SS1 only */
+	volatile u32	alpha;		/* SS1 only */
+	u8		xxx2[0x2c];
+	volatile u32	winbg;
+	volatile u32	planemask;
+	volatile u32	rop;
+	volatile u32	z;
+	volatile u32	dczf;		/* SS1 only */
+	volatile u32	dczb;		/* SS1 only */
+	volatile u32	dcs;		/* SS1 only */
+	volatile u32	dczs;		/* SS1 only */
+	volatile u32	pickfb;		/* SS1 only */
+	volatile u32	pickbb;		/* SS1 only */
+	volatile u32	dcfc;		/* SS1 only */
+	volatile u32	forcecol;	/* SS1 only */
+	volatile u32	door[8];	/* SS1 only */
+	volatile u32	pick[5];	/* SS1 only */
+};
+
+#define LEO_SS1_MISC_ENABLE	0x00000001
+#define LEO_SS1_MISC_STEREO	0x00000002
+struct leo_ld_ss1 {
+	u8		xxx0[0xef4];
+	volatile u32	ss1_misc;
+};
+
+struct leo_ld_gbl {
+	u8	unknown;
+};
+
+struct leo_par {
+	spinlock_t		lock;
+	struct leo_lx_krn	*lx_krn;
+	struct leo_lc_ss0_usr	*lc_ss0_usr;
+	struct leo_ld_ss0	*ld_ss0;
+	struct leo_ld_ss1	*ld_ss1;
+	struct leo_cursor	*cursor;
+	u32			extent;
+	u32			clut_data[256];
+
+	u32			flags;
+#define LEO_FLAG_BLANKED	0x00000001
+
+	unsigned long		physbase;
+	unsigned long		fbsize;
+
+	struct sbus_dev		*sdev;
+	struct list_head	list;
+};
+
+static void leo_wait(struct leo_lx_krn *lx_krn)
+{
+	int i;
+	
+	for (i = 0;
+	     (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000;
+	     i++)
+		udelay (1); /* Busy wait at most 0.3 sec */
+	return;
+}
+
+/**
+ *      leo_setcolreg - Optional function. Sets a color register.
+ *      @regno: boolean, 0 copy local, 1 get_user() function
+ *      @red: frame buffer colormap structure
+ *      @green: The green value which can be up to 16 bits wide
+ *      @blue:  The blue value which can be up to 16 bits wide.
+ *      @transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ */
+static int leo_setcolreg(unsigned regno,
+			 unsigned red, unsigned green, unsigned blue,
+			 unsigned transp, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+        struct leo_lx_krn *lx_krn = par->lx_krn;
+	unsigned long flags;
+	u32 val;
+	int i;
+
+	if (regno >= 256)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	par->clut_data[regno] = red | (green << 8) | (blue << 16);
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	leo_wait(lx_krn);
+
+	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
+	for (i = 0; i < 256; i++)
+		sbus_writel(par->clut_data[i], &lx_krn->krn_value);
+	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
+
+	val = sbus_readl(&lx_krn->krn_csr);
+	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
+	sbus_writel(val, &lx_krn->krn_csr);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+/**
+ *      leo_blank - Optional function.  Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ */
+static int leo_blank(int blank, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn *lx_krn = par->lx_krn;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	switch (blank) {
+	case 0: /* Unblanking */
+		val = sbus_readl(&lx_krn->krn_csr);
+		val |= LEO_KRN_CSR_ENABLE;
+		sbus_writel(val, &lx_krn->krn_csr);
+		par->flags &= ~LEO_FLAG_BLANKED;
+		break;
+
+	case 1: /* Normal blanking */
+	case 2: /* VESA blank (vsync off) */
+	case 3: /* VESA blank (hsync off) */
+	case 4: /* Poweroff */
+		val = sbus_readl(&lx_krn->krn_csr);
+		val &= ~LEO_KRN_CSR_ENABLE;
+		sbus_writel(val, &lx_krn->krn_csr);
+		par->flags |= LEO_FLAG_BLANKED;
+		break;
+	}
+
+	spin_unlock_irqrestore(&par->lock, flags);
+
+	return 0;
+}
+
+static struct sbus_mmap_map leo_mmap_map[] = {
+	{ LEO_SS0_MAP,		LEO_OFF_SS0,		0x800000	},
+	{ LEO_LC_SS0_USR_MAP,	LEO_OFF_LC_SS0_USR,	0x1000		},
+	{ LEO_LD_SS0_MAP,	LEO_OFF_LD_SS0,		0x1000		},
+	{ LEO_LX_CURSOR_MAP,	LEO_OFF_LX_CURSOR,	0x1000		},
+	{ LEO_SS1_MAP,		LEO_OFF_SS1,		0x800000	},
+	{ LEO_LC_SS1_USR_MAP,	LEO_OFF_LC_SS1_USR,	0x1000		},
+	{ LEO_LD_SS1_MAP,	LEO_OFF_LD_SS1,		0x1000		},
+	{ LEO_UNK_MAP,		LEO_OFF_UNK,		0x1000		},
+	{ LEO_LX_KRN_MAP,	LEO_OFF_LX_KRN,		0x1000		},
+	{ LEO_LC_SS0_KRN_MAP,	LEO_OFF_LC_SS0_KRN,	0x1000		},
+	{ LEO_LC_SS1_KRN_MAP,	LEO_OFF_LC_SS1_KRN,	0x1000		},
+	{ LEO_LD_GBL_MAP,	LEO_OFF_LD_GBL,		0x1000		},
+	{ LEO_UNK2_MAP,		LEO_OFF_UNK2,		0x100000	},
+	{ 0,			0,			0	  	}
+};
+
+static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+{
+	struct leo_par *par = (struct leo_par *)info->par;
+
+	return sbusfb_mmap_helper(leo_mmap_map,
+				  par->physbase, par->fbsize,
+				  par->sdev->reg_addrs[0].which_io,
+				  vma);
+}
+
+static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg, struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+
+	return sbusfb_ioctl_helper(cmd, arg, info,
+				   FBTYPE_SUNLEO, 32, par->fbsize);
+}
+
+/*
+ *  Initialisation
+ */
+
+static void
+leo_init_fix(struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *)info->par;
+
+	strncpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id) - 1);
+	info->fix.id[sizeof(info->fix.id)-1] = 0;
+
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	info->fix.line_length = 8192;
+
+	info->fix.accel = FB_ACCEL_SUN_LEO;
+}
+
+static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_lx_krn *lx_krn = par->lx_krn;
+	struct fb_wid_item *wi;
+	unsigned long flags;
+	u32 val;
+	int i, j;
+
+	spin_lock_irqsave(&par->lock, flags);
+
+	leo_wait(lx_krn);
+
+	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
+		switch(wi->wi_type) {
+		case FB_WID_DBL_8:
+			j = (wi->wi_index & 0xf) + 0x40;
+			break;
+
+		case FB_WID_DBL_24:
+			j = wi->wi_index & 0x3f;
+			break;
+
+		default:
+			continue;
+		};
+		sbus_writel(0x5800 + j, &lx_krn->krn_type);
+		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
+	}
+	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
+
+	val = sbus_readl(&lx_krn->krn_csr);
+	val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2);
+	sbus_writel(val, &lx_krn->krn_csr);
+
+	spin_unlock_irqrestore(&par->lock, flags);
+}
+
+static void leo_init_wids(struct fb_info *info)
+{
+	struct fb_wid_item wi;
+	struct fb_wid_list wl;
+
+	wl.wl_count = 1;
+	wl.wl_list = &wi;
+	wi.wi_type = FB_WID_DBL_8;
+	wi.wi_index = 0;
+	wi.wi_values [0] = 0x2c0;
+	leo_wid_put(info, &wl);
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put(info, &wl);
+	wi.wi_index = 2;
+	wi.wi_values [0] = 0x20;
+	leo_wid_put(info, &wl);
+	wi.wi_type = FB_WID_DBL_24;
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put(info, &wl);
+
+}
+
+static void leo_init_hw(struct fb_info *info)
+{
+	struct leo_par *par = (struct leo_par *) info->par;
+	struct leo_ld *ss = (struct leo_ld *) par->ld_ss0;
+	u32 val;
+
+	val = sbus_readl(&par->ld_ss1->ss1_misc);
+	val |= LEO_SS1_MISC_ENABLE;
+	sbus_writel(val, &par->ld_ss1->ss1_misc);
+
+	par->extent = ((info->var.xres - 1) |
+		       ((info->var.yres - 1) << 16));
+
+	sbus_writel(0xffffffff, &ss->wid);
+	sbus_writel(0xffff, &ss->wmask);
+	sbus_writel(0, &ss->vclipmin);
+	sbus_writel(par->extent, &ss->vclipmax);
+	sbus_writel(0, &ss->fg);
+	sbus_writel(0xff000000, &ss->planemask);
+	sbus_writel(0x310850, &ss->rop);
+	sbus_writel(0, &ss->widclip);
+	sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
+		    &par->lc_ss0_usr->extent);
+	sbus_writel(4, &par->lc_ss0_usr->addrspace);
+	sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
+	sbus_writel(0, &par->lc_ss0_usr->fontt);
+	do {
+		val = sbus_readl(&par->lc_ss0_usr->csr);
+	} while (val & 0x20000000);
+}
+
+static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
+{
+	var->red.offset = 0;
+	var->red.length = 8;
+	var->green.offset = 8;
+	var->green.length = 8;
+	var->blue.offset = 16;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+}
+
+struct all_info {
+	struct fb_info info;
+	struct leo_par par;
+	struct list_head list;
+};
+static LIST_HEAD(leo_list);
+
+static void leo_init_one(struct sbus_dev *sdev)
+{
+	struct all_info *all;
+	int linebytes;
+
+	all = kmalloc(sizeof(*all), GFP_KERNEL);
+	if (!all) {
+		printk(KERN_ERR "leo: Cannot allocate memory.\n");
+		return;
+	}
+	memset(all, 0, sizeof(*all));
+
+	INIT_LIST_HEAD(&all->list);
+
+	spin_lock_init(&all->par.lock);
+	all->par.sdev = sdev;
+
+	all->par.physbase = sdev->reg_addrs[0].phys_addr;
+
+	sbusfb_fill_var(&all->info.var, sdev->prom_node, 32);
+	leo_fixup_var_rgb(&all->info.var);
+
+	linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
+				       all->info.var.xres);
+	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+
+#ifdef CONFIG_SPARC32
+	all->info.screen_base = (char *)
+		prom_getintdefault(sdev->prom_node, "address", 0);
+#endif
+	if (!all->info.screen_base)
+		all->info.screen_base = (char *)
+			sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
+				     0x800000, "leo ram");
+
+	all->par.lc_ss0_usr = (struct leo_lc_ss0_usr *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
+			     0x1000, "leolc ss0usr");
+	all->par.ld_ss0 = (struct leo_ld_ss0 *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
+			     0x1000, "leold ss0");
+	all->par.ld_ss1 = (struct leo_ld_ss1 *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
+			     0x1000, "leold ss1");
+	all->par.lx_krn = (struct leo_lx_krn *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
+			     0x1000, "leolx krn");
+	all->par.cursor = (struct leo_cursor *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
+			     sizeof(struct leo_cursor), "leolx cursor");
+
+	all->info.node = NODEV;
+	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.fbops = &leo_ops;
+	all->info.currcon = -1;
+	all->info.par = &all->par;
+
+	leo_init_wids(&all->info);
+	leo_init_hw(&all->info);
+
+	leo_blank(0, &all->info);
+
+	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+		printk(KERN_ERR "leo: Could not allocate color map.\n");
+		kfree(all);
+		return;
+	}
+
+	leo_init_fix(&all->info);
+
+	if (register_framebuffer(&all->info) < 0) {
+		printk(KERN_ERR "leo: Could not register framebuffer.\n");
+		fb_dealloc_cmap(&all->info.cmap);
+		kfree(all);
+		return;
+	}
+
+	list_add(&all->list, &leo_list);
+
+	printk("leo: %s at %lx:%lx\n",
+	       sdev->prom_name,
+	       (long) sdev->reg_addrs[0].which_io,
+	       (long) sdev->reg_addrs[0].phys_addr);
+}
+
+int __init leo_init(void)
+{
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
+
+	for_all_sbusdev(sdev, sbus) {
+		if (!strcmp(sdev->prom_name, "leo"))
+			leo_init_one(sdev);
+	}
+
+	return 0;
+}
+
+void __exit leo_exit(void)
+{
+	struct list_head *pos, *tmp;
+
+	list_for_each_safe(pos, tmp, &leo_list) {
+		struct all_info *all = list_entry(pos, typeof(*all), list);
+
+		unregister_framebuffer(&all->info);
+		fb_dealloc_cmap(&all->info.cmap);
+		kfree(all);
+	}
+}
+
+int __init
+leo_setup(char *arg)
+{
+	/* No cmdline options yet... */
+	return 0;
+}
+
+#ifdef MODULE
+module_init(leo_init);
+module_exit(leo_exit);
+#endif
+
+MODULE_DESCRIPTION("framebuffer driver for LEO chipsets");
+MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_LICENSE("GPL");
diff -urN linux-2.5.64-bk3/drivers/video/leofb.c linux-2.5.64-bk4/drivers/video/leofb.c
--- linux-2.5.64-bk3/drivers/video/leofb.c	Tue Mar  4 19:29:56 2003
+++ linux-2.5.64-bk4/drivers/video/leofb.c	Wed Dec 31 16:00:00 1969
@@ -1,764 +0,0 @@
-/* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $
- * leofb.c: Leo (ZX) 24/8bit frame buffer driver
- *
- * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
- */
-
-#include <linux/module.h>
-#include <linux/sched.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/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-
-#include <video/sbusfb.h>
-#include <asm/io.h>
-
-#define LEO_OFF_LC_SS0_KRN	0x00200000UL
-#define LEO_OFF_LC_SS0_USR	0x00201000UL
-#define LEO_OFF_LC_SS1_KRN	0x01200000UL
-#define LEO_OFF_LC_SS1_USR	0x01201000UL
-#define LEO_OFF_LD_SS0		0x00400000UL
-#define LEO_OFF_LD_SS1		0x01400000UL
-#define LEO_OFF_LD_GBL		0x00401000UL
-#define LEO_OFF_LX_KRN		0x00600000UL
-#define LEO_OFF_LX_CURSOR	0x00601000UL
-#define LEO_OFF_SS0		0x00800000UL
-#define LEO_OFF_SS1		0x01800000UL
-#define LEO_OFF_UNK		0x00602000UL
-#define LEO_OFF_UNK2		0x00000000UL
-
-#define LEO_CUR_ENABLE		0x00000080
-#define LEO_CUR_UPDATE		0x00000030
-#define LEO_CUR_PROGRESS	0x00000006
-#define LEO_CUR_UPDATECMAP	0x00000003
-
-#define LEO_CUR_TYPE_MASK	0x00000000
-#define LEO_CUR_TYPE_IMAGE	0x00000020
-#define LEO_CUR_TYPE_CMAP	0x00000050
-
-struct leo_cursor {
-	u8		xxx0[16];
-	volatile u32	cur_type;
-	volatile u32	cur_misc;
-	volatile u32	cur_cursxy;
-	volatile u32	cur_data;
-};
-
-#define LEO_KRN_TYPE_CLUT0	0x00001000
-#define LEO_KRN_TYPE_CLUT1	0x00001001
-#define LEO_KRN_TYPE_CLUT2	0x00001002
-#define LEO_KRN_TYPE_WID	0x00001003
-#define LEO_KRN_TYPE_UNK	0x00001006
-#define LEO_KRN_TYPE_VIDEO	0x00002003
-#define LEO_KRN_TYPE_CLUTDATA	0x00004000
-#define LEO_KRN_CSR_ENABLE	0x00000008
-#define LEO_KRN_CSR_PROGRESS	0x00000004
-#define LEO_KRN_CSR_UNK		0x00000002
-#define LEO_KRN_CSR_UNK2	0x00000001
-
-struct leo_lx_krn {
-	volatile u32	krn_type;
-	volatile u32	krn_csr;
-	volatile u32	krn_value;
-};
-
-struct leo_lc_ss0_krn {
-	volatile u32 	misc;
-	u8		xxx0[0x800-4];
-	volatile u32	rev;
-};
-
-struct leo_lc_ss0_usr {
-	volatile u32	csr;
-	volatile u32	addrspace;
-	volatile u32 	fontmsk;
-	volatile u32	fontt;
-	volatile u32	extent;
-	volatile u32	src;
-	u32		dst;
-	volatile u32	copy;
-	volatile u32	fill;
-};
-
-struct leo_lc_ss1_krn {
-	u8	unknown;
-};
-
-struct leo_lc_ss1_usr {
-	u8	unknown;
-};
-
-struct leo_ld {
-	u8		xxx0[0xe00];
-	volatile u32	csr;
-	volatile u32	wid;
-	volatile u32	wmask;
-	volatile u32	widclip;
-	volatile u32	vclipmin;
-	volatile u32	vclipmax;
-	volatile u32	pickmin;	/* SS1 only */
-	volatile u32	pickmax;	/* SS1 only */
-	volatile u32	fg;
-	volatile u32	bg;
-	volatile u32	src;		/* Copy/Scroll (SS0 only) */
-	volatile u32	dst;		/* Copy/Scroll/Fill (SS0 only) */
-	volatile u32	extent;		/* Copy/Scroll/Fill size (SS0 only) */
-	u32		xxx1[3];
-	volatile u32	setsem;		/* SS1 only */
-	volatile u32	clrsem;		/* SS1 only */
-	volatile u32	clrpick;	/* SS1 only */
-	volatile u32	clrdat;		/* SS1 only */
-	volatile u32	alpha;		/* SS1 only */
-	u8		xxx2[0x2c];
-	volatile u32	winbg;
-	volatile u32	planemask;
-	volatile u32	rop;
-	volatile u32	z;
-	volatile u32	dczf;		/* SS1 only */
-	volatile u32	dczb;		/* SS1 only */
-	volatile u32	dcs;		/* SS1 only */
-	volatile u32	dczs;		/* SS1 only */
-	volatile u32	pickfb;		/* SS1 only */
-	volatile u32	pickbb;		/* SS1 only */
-	volatile u32	dcfc;		/* SS1 only */
-	volatile u32	forcecol;	/* SS1 only */
-	volatile u32	door[8];	/* SS1 only */
-	volatile u32	pick[5];	/* SS1 only */
-};
-
-#define LEO_SS1_MISC_ENABLE	0x00000001
-#define LEO_SS1_MISC_STEREO	0x00000002
-struct leo_ld_ss1 {
-	u8		xxx0[0xef4];
-	volatile u32	ss1_misc;
-};
-
-struct leo_ld_gbl {
-	u8	unknown;
-};
-
-static struct sbus_mmap_map leo_mmap_map[] = {
-	{ LEO_SS0_MAP,		LEO_OFF_SS0,		0x800000	},
-	{ LEO_LC_SS0_USR_MAP,	LEO_OFF_LC_SS0_USR,	0x1000		},
-	{ LEO_LD_SS0_MAP,	LEO_OFF_LD_SS0,		0x1000		},
-	{ LEO_LX_CURSOR_MAP,	LEO_OFF_LX_CURSOR,	0x1000		},
-	{ LEO_SS1_MAP,		LEO_OFF_SS1,		0x800000	},
-	{ LEO_LC_SS1_USR_MAP,	LEO_OFF_LC_SS1_USR,	0x1000		},
-	{ LEO_LD_SS1_MAP,	LEO_OFF_LD_SS1,		0x1000		},
-	{ LEO_UNK_MAP,		LEO_OFF_UNK,		0x1000		},
-	{ LEO_LX_KRN_MAP,	LEO_OFF_LX_KRN,		0x1000		},
-	{ LEO_LC_SS0_KRN_MAP,	LEO_OFF_LC_SS0_KRN,	0x1000		},
-	{ LEO_LC_SS1_KRN_MAP,	LEO_OFF_LC_SS1_KRN,	0x1000		},
-	{ LEO_LD_GBL_MAP,	LEO_OFF_LD_GBL,		0x1000		},
-	{ LEO_UNK2_MAP,		LEO_OFF_UNK2,		0x100000	},
-	{ 0,			0,			0	  	}
-};
-
-static void leo_setup(struct display *p)
-{
-	p->next_line = 8192;
-	p->next_plane = 0;
-}
-
-static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
-		      int height, int width)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int x, y, w, h;
-	int i;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	sbus_writel((attr_bgcol_ec(p,conp)<<24), &ss->fg);
-	if (fontheightlog(p)) {
-		y = sy << fontheightlog(p); h = height << fontheightlog(p);
-	} else {
-		y = sy * fontheight(p); h = height * fontheight(p);
-	}
-	if (fontwidthlog(p)) {
-		x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
-	} else {
-		x = sx * fontwidth(p); w = width * fontwidth(p);
-	}
-	sbus_writel((w - 1) | ((h - 1) << 11), &us->extent);
-	sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000,
-		    &us->fill);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
-		     int count, unsigned short *boxes)
-{
-	int i;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel((attr_bgcol(p,s)<<24), &ss->fg);
-	while (count-- > 0) {
-		do {
-			i = sbus_readl(&us->csr);
-		} while (i & 0x20000000);
-		sbus_writel((boxes[2] - boxes[0] - 1) | 
-			    ((boxes[3] - boxes[1] - 1) << 11),
-			    &us->extent);
-		sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000,
-			    &us->fill);
-		boxes += 4;
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int i, x, y;
-	u8 *fd;
-	u32 *u;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	if (fontheightlog(p)) {
-		y = yy << (fontheightlog(p) + 11);
-		i = (c & p->charmask) << fontheightlog(p);
-	} else {
-		y = (yy * fontheight(p)) << 11;
-		i = (c & p->charmask) * fontheight(p);
-	}
-	if (fontwidth(p) <= 8)
-		fd = p->fontdata + i;
-	else
-		fd = p->fontdata + (i << 1);
-	if (fontwidthlog(p))
-		x = xx << fontwidthlog(p);
-	else
-		x = xx * fontwidth(p);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	sbus_writel(attr_fgcol(p,c) << 24, &ss->fg);
-	sbus_writel(attr_bgcol(p,c) << 24, &ss->bg);
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)),
-		    &us->fontmsk);
-	u = ((u32 *)fb->info.screen_base) + y + x;
-	if (fontwidth(p) <= 8) {
-		for (i = 0; i < fontheight(p); i++, u += 2048) {
-			u32 val = *fd++ << 24;
-
-			sbus_writel(val, u);
-		}
-	} else {
-		for (i = 0; i < fontheight(p); i++, u += 2048) {
-			u32 val = *(u16 *)fd << 16;
-
-			sbus_writel(val, u);
-			fd += 2;
-		}
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
-		      int count, int yy, int xx)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-	int i, x, y;
-	u8 *fd1, *fd2, *fd3, *fd4;
-	u16 c;
-	u32 *u;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-	c = scr_readw(s);
-	sbus_writel(attr_fgcol(p, c) << 24, &ss->fg);
-	sbus_writel(attr_bgcol(p, c) << 24, &ss->bg);
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
-	if (fontwidthlog(p))
-		x = (xx << fontwidthlog(p));
-	else
-		x = xx * fontwidth(p);
-	if (fontheightlog(p))
-		y = yy << (fontheightlog(p) + 11);
-	else
-		y = (yy * fontheight(p)) << 11;
-	u = ((u32 *)fb->info.screen_base) + y + x;
-	if (fontwidth(p) <= 8) {
-		sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk);
-		x = 4*fontwidth(p) - fontheight(p)*2048;
-		while (count >= 4) {
-			count -= 4;
-			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-			} else {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
-			}
-			if (fontwidth(p) == 8) {
-				for (i = 0; i < fontheight(p); i++, u += 2048) {
-					u32 val;
-
-					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< 8)) << 8)) << 8);
-					sbus_writel(val, u);
-				}
-				u += x;
-			} else {
-				for (i = 0; i < fontheight(p); i++, u += 2048) {
-					u32 val;
-
-					val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
-					sbus_writel(val, u);
-				}
-				u += x;
-			}
-		}
-	} else {
-		sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk);
-		x = 2*fontwidth(p) - fontheight(p)*2048;
-		while (count >= 2) {
-			count -= 2;
-			if (fontheightlog(p)) {
-				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
-			} else {
-				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
-			}
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val;
-
-				val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
-				sbus_writel(val, u);
-				fd1 += 2; fd2 += 2;
-			}
-			u += x;
-		}
-	}
-	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
-	x = fontwidth(p) - fontheight(p)*2048;
-	while (count) {
-		count--;
-		if (fontheightlog(p))
-			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
-		else
-			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
-		if (fontwidth(p) <= 8) {
-			fd1 = p->fontdata + i;
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val = *fd1++ << 24;
-
-				sbus_writel(val, u);
-			}
-		} else {
-			fd1 = p->fontdata + (i << 1);
-			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				u32 val = *(u16 *)fd1 << 16;
-
-				sbus_writel(val, u);
-				fd1 += 2;
-			}
-		}
-		u += x;
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_revc(struct display *p, int xx, int yy)
-{
-	/* Not used if hw cursor */
-}
-
-static int leo_wait (struct leo_lx_krn *lx_krn)
-{
-	int i;
-	
-	for (i = 0; (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
-		udelay (1); /* Busy wait at most 0.3 sec */
-	if (i == 300000)
-		return -EFAULT; /* Timed out - should we print some message? */
-	return 0;
-}
-
-static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
-{
-        struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
-	unsigned long flags;
-	u32 tmp;
-	int i;
-	
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
-	i = leo_wait (lx_krn);
-	if (i)
-		goto out;
-	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
-	for (i = 0; i < 256; i++) {
-		u32 val;
-
-		val = fb->color_map CM(i,0) |
-			(fb->color_map CM(i,1) << 8) |
-			(fb->color_map CM(i,2) << 16);
-
-		sbus_writel(val, &lx_krn->krn_value); /* Throw colors there :)) */
-	}
-	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
-	tmp = sbus_readl(&lx_krn->krn_csr);
-	tmp |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
-	sbus_writel(tmp, &lx_krn->krn_csr);
-out:
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static void leo_restore_palette (struct fb_info_sbusfb *fb)
-{
-	u32 tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
-	tmp &= ~(LEO_SS1_MISC_ENABLE);
-	sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static struct display_switch leo_dispsw __initdata = {
-	.setup =	leo_setup,
-	.bmove =	fbcon_redraw_bmove,
-	.clear =	leo_clear,
-	.putc =		leo_putc,
-	.putcs =	leo_putcs,
-	.revc =		leo_revc, 
-	.fontwidthmask =FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
-};
-
-static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
-{
-        struct leo_cursor *l = fb->s.leo.cursor;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	for (i = 0; (sbus_readl(&l->cur_misc) & LEO_CUR_PROGRESS) && i < 300000; i++)
-		udelay (1); /* Busy wait at most 0.3 sec */
-	if (i == 300000)
-		goto out; /* Timed out - should we print some message? */
-	sbus_writel(LEO_CUR_TYPE_CMAP, &l->cur_type);
-	sbus_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &l->cur_data);
-	sbus_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &l->cur_data);
-	sbus_writel(LEO_CUR_UPDATECMAP, &l->cur_misc);
-out:
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Set cursor shape */
-static void leo_setcurshape (struct fb_info_sbusfb *fb)
-{
-	int i, j, k;
-	u32 m, n, mask;
-	struct leo_cursor *l = fb->s.leo.cursor;
-	u32 tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&l->cur_misc);
-	tmp &= ~LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	for (k = 0; k < 2; k ++) {
-		sbus_writel((k * LEO_CUR_TYPE_IMAGE), &l->cur_type);
-		for (i = 0; i < 32; i++) {
-			mask = 0;
-			m = fb->cursor.bits[k][i];
-			/* mask = m with reversed bit order */
-			for (j = 0, n = 1; j < 32; j++, n <<= 1)
-				if (m & n)
-					mask |= (0x80000000 >> j);
-			sbus_writel(mask, &l->cur_data);
-		}
-	}
-	tmp = sbus_readl(&l->cur_misc);
-	tmp |= LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-/* Load cursor information */
-static void leo_setcursor (struct fb_info_sbusfb *fb)
-{
-	struct cg_cursor *c = &fb->cursor;
-	struct leo_cursor *l = fb->s.leo.cursor;
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	tmp = sbus_readl(&l->cur_misc);
-	tmp &= ~LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-
-	sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) |
-		    (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11),
-		    &l->cur_cursxy);
-
-	tmp = sbus_readl(&l->cur_misc);
-	tmp |= LEO_CUR_UPDATE;
-	if (c->enable)
-		tmp |= LEO_CUR_ENABLE;
-	sbus_writel(tmp, &l->cur_misc);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int leo_blank (struct fb_info_sbusfb *fb)
-{
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
-
-	tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
-	tmp &= ~LEO_KRN_CSR_ENABLE;
-	sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
-	spin_unlock_irqrestore(&fb->lock, flags);
-	return 0;
-}
-
-static int leo_unblank (struct fb_info_sbusfb *fb)
-{
-	unsigned long flags;
-	u32 tmp;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
-
-	tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
-	if (!(tmp & LEO_KRN_CSR_ENABLE)) {
-		tmp |= LEO_KRN_CSR_ENABLE;
-		sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
-	}
-	spin_unlock_irqrestore(&fb->lock, flags);
-	return 0;
-}
-
-static int __init
-leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)
-{
-	struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
-	struct fb_wid_item *wi;
-	int i, j;
-
-	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
-	i = leo_wait (lx_krn);
-	if (i)
-		return i;
-	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
-		switch (wi->wi_type) {
-		case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break;
-		case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break;
-		default: return -EINVAL;
-		}
-		sbus_writel(0x5800 + j, &lx_krn->krn_type);
-		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
-	}
-	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
-	sbus_writel(3, &lx_krn->krn_csr);
-	return 0;
-}
-
-static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
-{
-	fb->info.screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
-}
-
-static void leo_switch_from_graph (struct fb_info_sbusfb *fb)
-{
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fb->lock, flags);
-	sbus_writel(0xffffffff, &ss->wid);
-	sbus_writel(0xffff, &ss->wmask);
-	sbus_writel(0, &ss->vclipmin);
-	sbus_writel(fb->s.leo.extent, &ss->vclipmax);
-	sbus_writel(0xff000000, &ss->planemask);
-	sbus_writel(0x310850, &ss->rop);
-	sbus_writel(0, &ss->widclip);
-	sbus_writel(4, &us->addrspace);
-	sbus_writel(0, &us->fontt);
-	spin_unlock_irqrestore(&fb->lock, flags);
-}
-
-static int __init leo_rasterimg (struct fb_info *info, int start)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-
-	if (start) {
-		sbus_writel(1, &ss->wid);
-		sbus_writel(0xffffff, &ss->planemask); 
-		sbus_writel(0x310b90, &ss->rop);
-		sbus_writel(0, &us->addrspace);
-	} else {
-		sbus_writel(0xffffffff, &ss->wid);
-		sbus_writel(0xff000000, &ss->planemask);
-		sbus_writel(0x310850, &ss->rop);
-		sbus_writel(4, &us->addrspace);
-	}
-	return 0;
-}
-
-static char idstring[40] __initdata = { 0 };
-
-char * __init leofb_init(struct fb_info_sbusfb *fb)
-{
-	struct fb_fix_screeninfo *fix = &fb->info.fix;
-	struct fb_var_screeninfo *var = &fb->info.var;
-	struct display *disp = &fb->disp;
-	struct fbtype *type = &fb->type;
-	struct sbus_dev *sdev = fb->sbdp;
-	unsigned long phys = sdev->reg_addrs[0].phys_addr;
-	struct fb_wid_item wi;
-	struct fb_wid_list wl;
-	int i;
-	register struct leo_lc_ss0_usr *us;
-	register struct leo_ld *ss;
-	struct fb_ops *fbops;
-	u32 tmp;
-
-	strcpy(fb->info.modename, "Leo");
-		
-	strcpy(fix->id, "Leo");
-	fix->visual = FB_VISUAL_TRUECOLOR;
-	fix->line_length = 8192;
-	fix->accel = FB_ACCEL_SUN_LEO;
-	
-	var->bits_per_pixel = 32;
-	var->green.offset = 8;
-	var->blue.offset = 16;
-	var->accel_flags = FB_ACCELF_TEXT;
-	
-	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-	if (fbops == NULL)
-		return NULL;
-	
-	*fbops = *fb->info.fbops;
-	fbops->fb_rasterimg = leo_rasterimg;
-	fb->info.fbops = fbops;
-	
-	disp->scrollmode = SCROLL_YREDRAW;
-	if (!fb->info.screen_base) {
-		fb->info.screen_base = (char *)
-			sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
-				     0x800000, "leo ram");
-	}
-	fb->info.screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
-	us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
-			     0x1000, "leolc ss0usr");
-	fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
-			     0x1000, "leold ss0");
-	ss = (struct leo_ld *) fb->s.leo.ld_ss0;
-	fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
-			     0x1000, "leold ss1");
-	fb->s.leo.lx_krn = (struct leo_lx_krn *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
-			     0x1000, "leolx krn");
-	fb->s.leo.cursor = (struct leo_cursor *)
-		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
-			     sizeof(struct leo_cursor), "leolx cursor");
-	fb->dispsw = leo_dispsw;
-	
-	fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
-
-	wl.wl_count = 1;
-	wl.wl_list = &wi;
-	wi.wi_type = FB_WID_DBL_8;
-	wi.wi_index = 0;
-	wi.wi_values [0] = 0x2c0;
-	leo_wid_put (fb, &wl);
-	wi.wi_index = 1;
-	wi.wi_values [0] = 0x30;
-	leo_wid_put (fb, &wl);
-	wi.wi_index = 2;
-	wi.wi_values [0] = 0x20;
-	leo_wid_put (fb, &wl);
-	wi.wi_type = FB_WID_DBL_24;
-	wi.wi_index = 1;
-	wi.wi_values [0] = 0x30;
-	leo_wid_put (fb, &wl);
-
-	tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
-	tmp |= LEO_SS1_MISC_ENABLE;
-	sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
-
-	sbus_writel(0xffffffff, &ss->wid);
-	sbus_writel(0xffff, &ss->wmask);
-	sbus_writel(0, &ss->vclipmin);
-	sbus_writel(fb->s.leo.extent, &ss->vclipmax);
-	sbus_writel(0, &ss->fg);
-	sbus_writel(0xff000000, &ss->planemask);
-	sbus_writel(0x310850, &ss->rop);
-	sbus_writel(0, &ss->widclip);
-	sbus_writel((type->fb_width-1) | ((type->fb_height-1) << 11), &us->extent);
-	sbus_writel(4, &us->addrspace);
-	sbus_writel(0x80000000, &us->fill);
-	sbus_writel(0, &us->fontt);
-	do {
-		i = sbus_readl(&us->csr);
-	} while (i & 0x20000000);
-
-	fb->margins = leo_margins;
-	fb->loadcmap = leo_loadcmap;
-	fb->setcursor = leo_setcursor;
-	fb->setcursormap = leo_setcursormap;
-	fb->setcurshape = leo_setcurshape;
-	fb->restore_palette = leo_restore_palette;
-	fb->switch_from_graph = leo_switch_from_graph;
-	fb->fill = leo_fill;
-	fb->blank = leo_blank;
-	fb->unblank = leo_unblank;
-	
-	fb->physbase = phys;
-	fb->mmap_map = leo_mmap_map;
-	
-#ifdef __sparc_v9__
-	sprintf(idstring, "leo at %016lx", phys);
-#else	
-	sprintf(idstring, "leo at %x.%08lx", fb->iospace, phys);
-#endif
-		    
-	return idstring;
-}
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.5.64-bk3/fs/binfmt_elf.c linux-2.5.64-bk4/fs/binfmt_elf.c
--- linux-2.5.64-bk3/fs/binfmt_elf.c	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/fs/binfmt_elf.c	Mon Mar 31 12:25:47 2003
@@ -390,7 +390,6 @@
 	unsigned long text_data, elf_entry = ~0UL;
 	char * addr;
 	loff_t offset;
-	int retval;
 
 	current->mm->end_code = interp_ex->a_text;
 	text_data = interp_ex->a_text + interp_ex->a_data;
@@ -412,11 +411,9 @@
 	}
 
 	do_brk(0, text_data);
-	retval = -ENOEXEC;
 	if (!interpreter->f_op || !interpreter->f_op->read)
 		goto out;
-	retval = interpreter->f_op->read(interpreter, addr, text_data, &offset);
-	if (retval < 0)
+	if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
 		goto out;
 	flush_icache_range((unsigned long)addr,
 	                   (unsigned long)addr + text_data);
@@ -638,7 +635,7 @@
 	retval = setup_arg_pages(bprm);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
-		return retval;
+		goto out_free_dentry;
 	}
 	
 	current->mm->start_stack = bprm->p;
@@ -742,7 +739,8 @@
 			printk(KERN_ERR "Unable to load interpreter\n");
 			kfree(elf_phdata);
 			send_sig(SIGSEGV, current, 0);
-			return 0;
+			retval = -ENOEXEC; /* Nobody gets to see this, but.. */
+			goto out;
 		}
 	} else {
 		elf_entry = elf_ex.e_entry;
diff -urN linux-2.5.64-bk3/fs/block_dev.c linux-2.5.64-bk4/fs/block_dev.c
--- linux-2.5.64-bk3/fs/block_dev.c	Tue Mar  4 19:29:56 2003
+++ linux-2.5.64-bk4/fs/block_dev.c	Mon Mar 31 12:25:47 2003
@@ -436,56 +436,6 @@
 	spin_unlock(&bdev_lock);
 }
 
-static const char *blkdevs[MAX_BLKDEV];
-
-int get_blkdev_list(char * p)
-{
-	int i;
-	int len;
-
-	len = sprintf(p, "\nBlock devices:\n");
-	for (i = 0; i < MAX_BLKDEV ; i++) {
-		if (blkdevs[i])
-			len += sprintf(p+len, "%3d %s\n", i, blkdevs[i]);
-	}
-	return len;
-}
-
-int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
-{
-	if (devfs_only())
-		return 0;
-	if (major == 0) {
-		for (major = MAX_BLKDEV-1; major > 0; major--) {
-			if (blkdevs[major] == NULL) {
-				blkdevs[major] = name;
-				return major;
-			}
-		}
-		return -EBUSY;
-	}
-	if (major >= MAX_BLKDEV)
-		return -EINVAL;
-	if (blkdevs[major])
-		return -EBUSY;
-	blkdevs[major] = name;
-	return 0;
-}
-
-int unregister_blkdev(unsigned int major, const char * name)
-{
-	if (devfs_only())
-		return 0;
-	if (major >= MAX_BLKDEV)
-		return -EINVAL;
-	if (!blkdevs[major])
-		return -EINVAL;
-	if (strcmp(blkdevs[major], name))
-		return -EINVAL;
-	blkdevs[major] = NULL;
-	return 0;
-}
-
 /*
  * This routine checks whether a removable media has been changed,
  * and invalidates all buffer-cache-entries in that case. This
@@ -786,18 +736,6 @@
 	return res;
 }
 
-const char *__bdevname(dev_t dev)
-{
-	static char buffer[32];
-	const char * name = blkdevs[MAJOR(dev)];
-
-	if (!name)
-		name = "unknown-block";
-
-	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
-	return buffer;
-}
-
 /**
  * lookup_bdev  - lookup a struct block_device by name
  *
diff -urN linux-2.5.64-bk3/fs/ext2/super.c linux-2.5.64-bk4/fs/ext2/super.c
--- linux-2.5.64-bk3/fs/ext2/super.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/fs/ext2/super.c	Mon Mar 31 12:25:47 2003
@@ -781,7 +781,6 @@
 		if (!sbi->s_group_desc[i]) {
 			for (j = 0; j < i; j++)
 				brelse (sbi->s_group_desc[j]);
-			kfree(sbi->s_group_desc);
 			printk ("EXT2-fs: unable to read group descriptors\n");
 			goto failed_mount_group_desc;
 		}
diff -urN linux-2.5.64-bk3/fs/ext2/xattr.c linux-2.5.64-bk4/fs/ext2/xattr.c
--- linux-2.5.64-bk3/fs/ext2/xattr.c	Tue Mar  4 19:29:24 2003
+++ linux-2.5.64-bk4/fs/ext2/xattr.c	Mon Mar 31 12:25:47 2003
@@ -731,7 +731,7 @@
 			 * The old block will be released after updating
 			 * the inode.
 			 */
-			ea_bdebug(old_bh, "reusing block %ld",
+			ea_bdebug(new_bh, "reusing block %ld",
 				new_bh->b_blocknr);
 			
 			error = -EDQUOT;
diff -urN linux-2.5.64-bk3/fs/ext3/xattr.c linux-2.5.64-bk4/fs/ext3/xattr.c
--- linux-2.5.64-bk3/fs/ext3/xattr.c	Tue Mar  4 19:29:22 2003
+++ linux-2.5.64-bk4/fs/ext3/xattr.c	Mon Mar 31 12:25:47 2003
@@ -732,7 +732,7 @@
 			 * The old block will be released after updating
 			 * the inode.
 			 */
-			ea_bdebug(old_bh, "reusing block %ld",
+			ea_bdebug(new_bh, "reusing block %ld",
 				new_bh->b_blocknr);
 			
 			error = -EDQUOT;
diff -urN linux-2.5.64-bk3/fs/file_table.c linux-2.5.64-bk4/fs/file_table.c
--- linux-2.5.64-bk3/fs/file_table.c	Tue Mar  4 19:28:56 2003
+++ linux-2.5.64-bk4/fs/file_table.c	Mon Mar 31 12:25:47 2003
@@ -27,7 +27,7 @@
 /* And here the free ones sit */
 static LIST_HEAD(free_list);
 /* public *and* exported. Not pretty! */
-spinlock_t files_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t files_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /* Find an unused file structure and return a pointer to it.
  * Returns NULL, if there are no more free file structures or
diff -urN linux-2.5.64-bk3/fs/mbcache.c linux-2.5.64-bk4/fs/mbcache.c
--- linux-2.5.64-bk3/fs/mbcache.c	Tue Mar  4 19:29:53 2003
+++ linux-2.5.64-bk4/fs/mbcache.c	Mon Mar 31 12:25:47 2003
@@ -433,6 +433,7 @@
 		list_add(&ce->e_indexes[n].o_list,
 			 &cache->c_indexes_hash[n][bucket]);
 	}
+	error = 0;
 out:
 	spin_unlock(&mb_cache_spinlock);
 	return error;
diff -urN linux-2.5.64-bk3/fs/nfs/file.c linux-2.5.64-bk4/fs/nfs/file.c
--- linux-2.5.64-bk3/fs/nfs/file.c	Tue Mar  4 19:29:30 2003
+++ linux-2.5.64-bk4/fs/nfs/file.c	Mon Mar 31 12:25:47 2003
@@ -35,6 +35,7 @@
 #define NFSDBG_FACILITY		NFSDBG_FILE
 
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
+static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
 static ssize_t nfs_file_read(struct kiocb *, char *, size_t, loff_t);
 static ssize_t nfs_file_write(struct kiocb *, const char *, size_t, loff_t);
 static int  nfs_file_flush(struct file *);
@@ -52,6 +53,7 @@
 	.release	= nfs_release,
 	.fsync		= nfs_fsync,
 	.lock		= nfs_lock,
+	.sendfile	= nfs_file_sendfile,
 };
 
 struct inode_operations nfs_file_inode_operations = {
@@ -102,6 +104,24 @@
 	return result;
 }
 
+static ssize_t
+nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
+		read_actor_t actor, void *target)
+{
+	struct dentry *dentry = filp->f_dentry;
+	struct inode *inode = dentry->d_inode;
+	ssize_t res;
+
+	dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name,
+		(unsigned long) count, (unsigned long long) *ppos);
+
+	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	if (!res)
+		res = generic_file_sendfile(filp, ppos, count, actor, target);
+	return res;
+}
+
 static int
 nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
diff -urN linux-2.5.64-bk3/fs/partitions/check.c linux-2.5.64-bk4/fs/partitions/check.c
--- linux-2.5.64-bk3/fs/partitions/check.c	Tue Mar  4 19:29:36 2003
+++ linux-2.5.64-bk4/fs/partitions/check.c	Mon Mar 31 12:25:47 2003
@@ -503,13 +503,7 @@
 	disk->capacity = 0;
 	disk->flags &= ~GENHD_FL_UP;
 	unlink_gendisk(disk);
-	disk->reads = disk->writes = 0;
-	disk->read_sectors = disk->write_sectors = 0;
-	disk->read_merges = disk->write_merges = 0;
-	disk->read_ticks = disk->write_ticks = 0;
-	disk->in_flight = 0;
-	disk->io_ticks = 0;
-	disk->time_in_queue = 0;
+	disk_stat_set_all(disk, 0);
 	disk->stamp = disk->stamp_idle = 0;
 	devfs_remove_partitions(disk);
 	if (disk->driverfs_dev) {
diff -urN linux-2.5.64-bk3/fs/proc/proc_misc.c linux-2.5.64-bk4/fs/proc/proc_misc.c
--- linux-2.5.64-bk3/fs/proc/proc_misc.c	Tue Mar  4 19:28:59 2003
+++ linux-2.5.64-bk4/fs/proc/proc_misc.c	Mon Mar 31 12:25:47 2003
@@ -389,11 +389,7 @@
 extern int show_interrupts(struct seq_file *p, void *v);
 static int interrupts_open(struct inode *inode, struct file *file)
 {
-	unsigned size = PAGE_SIZE;
-	/*
-	 * probably should depend on NR_CPUS, but that's only rough estimate;
-	 * if we'll need more it will be given,
-	 */
+	unsigned size = PAGE_SIZE * (1 + NR_CPUS / 8);
 	char *buf = kmalloc(size, GFP_KERNEL);
 	struct seq_file *m;
 	int res;
diff -urN linux-2.5.64-bk3/fs/readdir.c linux-2.5.64-bk4/fs/readdir.c
--- linux-2.5.64-bk3/fs/readdir.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/fs/readdir.c	Mon Mar 31 12:25:47 2003
@@ -72,11 +72,16 @@
 		return -EINVAL;
 	buf->count++;
 	dirent = buf->dirent;
-	put_user(ino, &dirent->d_ino);
-	put_user(offset, &dirent->d_offset);
-	put_user(namlen, &dirent->d_namlen);
-	copy_to_user(dirent->d_name, name, namlen);
-	put_user(0, dirent->d_name + namlen);
+	if (!access_ok(VERIFY_WRITE, (unsigned long)dirent,
+			(unsigned long)(dirent->d_name + namlen + 1) -
+				(unsigned long)dirent))
+		return -EFAULT;
+	if (	__put_user(ino, &dirent->d_ino) ||
+		__put_user(offset, &dirent->d_offset) ||
+		__put_user(namlen, &dirent->d_namlen) ||
+		__copy_to_user(dirent->d_name, name, namlen) ||
+		__put_user(0, dirent->d_name + namlen))
+		return -EFAULT;
 	return 0;
 }
 
diff -urN linux-2.5.64-bk3/fs/sysfs/dir.c linux-2.5.64-bk4/fs/sysfs/dir.c
--- linux-2.5.64-bk3/fs/sysfs/dir.c	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/fs/sysfs/dir.c	Mon Mar 31 12:25:47 2003
@@ -106,7 +106,7 @@
 		pr_debug(" done\n");
 		node = dentry->d_subdirs.next;
 	}
-
+	spin_unlock(&dcache_lock);
 	up(&dentry->d_inode->i_sem);
 	d_invalidate(dentry);
 	simple_rmdir(parent->d_inode,dentry);
diff -urN linux-2.5.64-bk3/include/asm-i386/mmzone.h linux-2.5.64-bk4/include/asm-i386/mmzone.h
--- linux-2.5.64-bk3/include/asm-i386/mmzone.h	Tue Mar  4 19:29:19 2003
+++ linux-2.5.64-bk4/include/asm-i386/mmzone.h	Mon Mar 31 12:25:47 2003
@@ -10,14 +10,6 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
-#ifdef CONFIG_X86_NUMAQ
-#include <asm/numaq.h>
-#elif CONFIG_X86_SUMMIT
-#include <asm/srat.h>
-#else
-#define pfn_to_nid(pfn)		(0)
-#endif /* CONFIG_X86_NUMAQ */
-
 extern struct pglist_data *node_data[];
 
 /*
@@ -101,5 +93,41 @@
  * ( pfn_to_pgdat(pfn) && ((pfn) < node_end_pfn(pfn_to_nid(pfn))) ) 
  */ 
 #define pfn_valid(pfn)          ((pfn) < num_physpages)
+
+/*
+ * generic node memory support, the following assumptions apply:
+ *
+ * 1) memory comes in 256Mb contigious chunks which are either present or not
+ * 2) we will not have more than 64Gb in total
+ *
+ * for now assume that 64Gb is max amount of RAM for whole system
+ *    64Gb / 4096bytes/page = 16777216 pages
+ */
+#define MAX_NR_PAGES 16777216
+#define MAX_ELEMENTS 256
+#define PAGES_PER_ELEMENT (MAX_NR_PAGES/MAX_ELEMENTS)
+
+extern u8 physnode_map[];
+
+static inline int pfn_to_nid(unsigned long pfn)
+{
+	return(physnode_map[(pfn) / PAGES_PER_ELEMENT]);
+}
+static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+	return(NODE_DATA(pfn_to_nid(pfn)));
+}
+
+#ifdef CONFIG_X86_NUMAQ
+#include <asm/numaq.h>
+#elif CONFIG_X86_SUMMIT
+#include <asm/srat.h>
+#elif CONFIG_X86_PC
+#define get_memcfg_numa get_memcfg_numa_flat
+#define get_zholes_size(n) (0)
+#else
+#define pfn_to_nid(pfn)		(0)
+#endif /* CONFIG_X86_NUMAQ */
+
 #endif /* CONFIG_DISCONTIGMEM */
 #endif /* _ASM_MMZONE_H_ */
diff -urN linux-2.5.64-bk3/include/asm-i386/numaq.h linux-2.5.64-bk4/include/asm-i386/numaq.h
--- linux-2.5.64-bk3/include/asm-i386/numaq.h	Tue Mar  4 19:29:21 2003
+++ linux-2.5.64-bk4/include/asm-i386/numaq.h	Mon Mar 31 12:25:47 2003
@@ -28,18 +28,6 @@
 
 #ifdef CONFIG_X86_NUMAQ
 
-/*
- * for now assume that 64Gb is max amount of RAM for whole system
- *    64Gb / 4096bytes/page = 16777216 pages
- */
-#define MAX_NR_PAGES 16777216
-#define MAX_ELEMENTS 256
-#define PAGES_PER_ELEMENT (16777216/256)
-
-extern int physnode_map[];
-#define pfn_to_nid(pfn)	({ physnode_map[(pfn) / PAGES_PER_ELEMENT]; })
-#define pfn_to_pgdat(pfn) NODE_DATA(pfn_to_nid(pfn))
-#define PHYSADDR_TO_NID(pa) pfn_to_nid(pa >> PAGE_SHIFT)
 #define MAX_NUMNODES		8
 extern void get_memcfg_numaq(void);
 #define get_memcfg_numa() get_memcfg_numaq()
@@ -169,7 +157,7 @@
         struct	eachquadmem eq[MAX_NUMNODES];	/* indexed by quad id */
 };
 
-static inline unsigned long get_zholes_size(int nid)
+static inline unsigned long *get_zholes_size(int nid)
 {
 	return 0;
 }
diff -urN linux-2.5.64-bk3/include/asm-i386/srat.h linux-2.5.64-bk4/include/asm-i386/srat.h
--- linux-2.5.64-bk3/include/asm-i386/srat.h	Tue Mar  4 19:29:04 2003
+++ linux-2.5.64-bk4/include/asm-i386/srat.h	Mon Mar 31 12:25:47 2003
@@ -27,17 +27,6 @@
 #ifndef _ASM_SRAT_H_
 #define _ASM_SRAT_H_
 
-/*
- * each element in pfnnode_map represents 256 MB (2^28) of pages.
- * so, to represent 64GB we need 256 elements.
- */
-#define MAX_ELEMENTS 256
-#define PFN_TO_ELEMENT(pfn) ((pfn)>>(28 - PAGE_SHIFT))
-
-extern int pfnnode_map[];
-#define pfn_to_nid(pfn) ({ pfnnode_map[PFN_TO_ELEMENT(pfn)]; })
-#define pfn_to_pgdat(pfn) NODE_DATA(pfn_to_nid(pfn))
-#define PHYSADDR_TO_NID(pa) pfn_to_nid(pa >> PAGE_SHIFT)
 #define MAX_NUMNODES		8
 extern void get_memcfg_from_srat(void);
 extern unsigned long *get_zholes_size(int);
diff -urN linux-2.5.64-bk3/include/asm-sparc/termios.h linux-2.5.64-bk4/include/asm-sparc/termios.h
--- linux-2.5.64-bk3/include/asm-sparc/termios.h	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/include/asm-sparc/termios.h	Mon Mar 31 12:25:47 2003
@@ -92,7 +92,7 @@
 	reprint=^R	discard=^U	werase=^W	lnext=^V
 	vmin=\1         vtime=\0
 */
-#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001\000"
+#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001"
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
diff -urN linux-2.5.64-bk3/include/asm-sparc64/termios.h linux-2.5.64-bk4/include/asm-sparc64/termios.h
--- linux-2.5.64-bk3/include/asm-sparc64/termios.h	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/include/asm-sparc64/termios.h	Mon Mar 31 12:25:47 2003
@@ -91,7 +91,7 @@
 	reprint=^R	discard=^U	werase=^W	lnext=^V
 	vmin=\1         vtime=\0
 */
-#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001\000"
+#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001"
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
diff -urN linux-2.5.64-bk3/include/linux/fs.h linux-2.5.64-bk4/include/linux/fs.h
--- linux-2.5.64-bk3/include/linux/fs.h	Tue Mar  4 19:29:03 2003
+++ linux-2.5.64-bk4/include/linux/fs.h	Mon Mar 31 12:25:47 2003
@@ -1033,7 +1033,7 @@
 #define putname(name)	kmem_cache_free(names_cachep, (void *)(name))
 
 enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDEV_RAW};
-extern int register_blkdev(unsigned int, const char *, struct block_device_operations *);
+extern int register_blkdev(unsigned int, const char *);
 extern int unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern int bd_acquire(struct inode *inode);
diff -urN linux-2.5.64-bk3/include/linux/genhd.h linux-2.5.64-bk4/include/linux/genhd.h
--- linux-2.5.64-bk3/include/linux/genhd.h	Tue Mar  4 19:29:00 2003
+++ linux-2.5.64-bk4/include/linux/genhd.h	Mon Mar 31 12:25:47 2003
@@ -13,6 +13,8 @@
 #include <linux/types.h>
 #include <linux/major.h>
 #include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/string.h>
 
 enum {
 /* These three have identical behaviour; use the second one if DOS FDISK gets
@@ -70,6 +72,16 @@
 #define GENHD_FL_CD	8
 #define GENHD_FL_UP	16
 
+struct disk_stats {
+	unsigned read_sectors, write_sectors;
+	unsigned reads, writes;
+	unsigned read_merges, write_merges;
+	unsigned read_ticks, write_ticks;
+	unsigned io_ticks;
+	int in_flight;
+	unsigned time_in_queue;
+};
+	
 struct gendisk {
 	int major;			/* major number of driver */
 	int first_minor;
@@ -94,16 +106,86 @@
 	int policy;
 
 	unsigned sync_io;		/* RAID */
-	unsigned read_sectors, write_sectors;
-	unsigned reads, writes;
-	unsigned read_merges, write_merges;
-	unsigned read_ticks, write_ticks;
-	unsigned io_ticks;
-	int in_flight;
 	unsigned long stamp, stamp_idle;
-	unsigned time_in_queue;
+#ifdef	CONFIG_SMP
+	struct disk_stats *dkstats;
+#else
+	struct disk_stats dkstats;
+#endif
 };
 
+/* 
+ * Macros to operate on percpu disk statistics:
+ * Since writes to disk_stats are serialised through the queue_lock,
+ * smp_processor_id() should be enough to get to the per_cpu versions
+ * of statistics counters
+ */
+#ifdef	CONFIG_SMP
+#define disk_stat_add(gendiskp, field, addnd) 	\
+	(per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd)
+#define disk_stat_read(gendiskp, field)					\
+({									\
+	typeof(gendiskp->dkstats->field) res = 0;			\
+	int i;								\
+	for (i=0; i < NR_CPUS; i++) {					\
+		if (!cpu_possible(i))					\
+			continue;					\
+		res += per_cpu_ptr(gendiskp->dkstats, i)->field;	\
+	}								\
+	res;								\
+})
+
+static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)	{
+	int i;
+	for (i=0; i < NR_CPUS; i++) {
+		if (cpu_possible(i)) {
+			memset(per_cpu_ptr(gendiskp->dkstats, i), value,	
+					sizeof (struct disk_stats));
+		}
+	}
+}		
+				
+#else
+#define disk_stat_add(gendiskp, field, addnd) (gendiskp->dkstats.field += addnd)
+#define disk_stat_read(gendiskp, field)	(gendiskp->dkstats.field)
+
+static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)	{
+	memset(&gendiskp->dkstats, value, sizeof (struct disk_stats));
+}
+#endif
+
+#define disk_stat_inc(gendiskp, field) disk_stat_add(gendiskp, field, 1)
+#define disk_stat_dec(gendiskp, field) disk_stat_add(gendiskp, field, -1)
+#define disk_stat_sub(gendiskp, field, subnd) \
+		disk_stat_add(gendiskp, field, -subnd)
+
+
+/* Inlines to alloc and free disk stats in struct gendisk */
+#ifdef  CONFIG_SMP
+static inline int init_disk_stats(struct gendisk *disk)
+{
+	disk->dkstats = kmalloc_percpu(sizeof (struct disk_stats), GFP_KERNEL);
+	if (!disk->dkstats)
+		return 0;
+	disk_stat_set_all(disk, 0);
+	return 1;
+}
+
+static inline void free_disk_stats(struct gendisk *disk)
+{
+	kfree_percpu(disk->dkstats);
+}
+#else	/* CONFIG_SMP */
+static inline int init_disk_stats(struct gendisk *disk)
+{
+	return 1;
+}
+
+static inline void free_disk_stats(struct gendisk *disk)
+{
+}
+#endif	/* CONFIG_SMP */
+
 /* drivers/block/ll_rw_blk.c */
 extern void disk_round_stats(struct gendisk *disk);
 
diff -urN linux-2.5.64-bk3/include/linux/hugetlb.h linux-2.5.64-bk4/include/linux/hugetlb.h
--- linux-2.5.64-bk3/include/linux/hugetlb.h	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/include/linux/hugetlb.h	Mon Mar 31 12:25:47 2003
@@ -66,6 +66,7 @@
 
 #ifndef HPAGE_MASK
 #define HPAGE_MASK	0		/* Keep the compiler happy */
+#define HPAGE_SIZE	0
 #endif
 
 #endif /* !CONFIG_HUGETLB_PAGE */
diff -urN linux-2.5.64-bk3/include/linux/mm.h linux-2.5.64-bk4/include/linux/mm.h
--- linux-2.5.64-bk3/include/linux/mm.h	Tue Mar  4 19:28:56 2003
+++ linux-2.5.64-bk4/include/linux/mm.h	Mon Mar 31 12:25:47 2003
@@ -558,6 +558,7 @@
 /* readahead.c */
 #define VM_MAX_READAHEAD	128	/* kbytes */
 #define VM_MIN_READAHEAD	16	/* kbytes (includes current page) */
+
 int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
 			unsigned long offset, unsigned long nr_to_read);
 void page_cache_readahead(struct address_space *mapping, 
@@ -569,7 +570,7 @@
 			   struct file *filp,
 			   unsigned long offset);
 void handle_ra_miss(struct address_space *mapping, 
-		    struct file_ra_state *ra);
+		    struct file_ra_state *ra, pgoff_t offset);
 unsigned long max_sane_readahead(unsigned long nr);
 
 /* Do stack extension */
diff -urN linux-2.5.64-bk3/include/linux/slab.h linux-2.5.64-bk4/include/linux/slab.h
--- linux-2.5.64-bk3/include/linux/slab.h	Tue Mar  4 19:29:54 2003
+++ linux-2.5.64-bk4/include/linux/slab.h	Mon Mar 31 12:25:47 2003
@@ -37,6 +37,7 @@
 #define	SLAB_HWCACHE_ALIGN	0x00002000UL	/* align objs on a h/w cache lines */
 #define SLAB_CACHE_DMA		0x00004000UL	/* use GFP_DMA memory */
 #define SLAB_MUST_HWCACHE_ALIGN	0x00008000UL	/* force alignment */
+#define SLAB_STORE_USER		0x00010000UL	/* store the last owner for bug hunting */
 
 /* flags passed to a constructor func */
 #define	SLAB_CTOR_CONSTRUCTOR	0x001UL		/* if not set, then deconstructor */
diff -urN linux-2.5.64-bk3/init/Kconfig linux-2.5.64-bk4/init/Kconfig
--- linux-2.5.64-bk3/init/Kconfig	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/init/Kconfig	Mon Mar 31 12:25:47 2003
@@ -37,6 +37,16 @@
 
 menu "General setup"
 
+config SWAP
+	bool "Support for paging of anonymous memory"
+	depends on MMU
+	default y
+	help
+	  This option allows you to choose whether you want to have support
+	  for socalled swap devices or swap files in your kernel that are
+	  used to provide more virtual memory than the actual RAM present
+	  in your computer.  If unusre say Y.
+
 config SYSVIPC
 	bool "System V IPC"
 	---help---
diff -urN linux-2.5.64-bk3/kernel/ksyms.c linux-2.5.64-bk4/kernel/ksyms.c
--- linux-2.5.64-bk3/kernel/ksyms.c	Tue Mar  4 19:28:53 2003
+++ linux-2.5.64-bk4/kernel/ksyms.c	Mon Mar 31 12:25:47 2003
@@ -57,6 +57,7 @@
 #include <linux/mount.h>
 #include <linux/ptrace.h>
 #include <linux/time.h>
+#include <linux/backing-dev.h>
 #include <asm/checksum.h>
 
 #if defined(CONFIG_PROC_FS)
@@ -367,6 +368,7 @@
 EXPORT_SYMBOL(generic_file_readv);
 EXPORT_SYMBOL(generic_file_writev);
 EXPORT_SYMBOL(iov_shorten);
+EXPORT_SYMBOL_GPL(default_backing_dev_info);
 
 /* tty routines */
 EXPORT_SYMBOL(tty_wait_until_sent);
diff -urN linux-2.5.64-bk3/kernel/sched.c linux-2.5.64-bk4/kernel/sched.c
--- linux-2.5.64-bk3/kernel/sched.c	Mon Mar 31 12:25:41 2003
+++ linux-2.5.64-bk4/kernel/sched.c	Mon Mar 31 12:25:47 2003
@@ -33,6 +33,12 @@
 #include <linux/timer.h>
 #include <linux/rcupdate.h>
 
+#ifdef CONFIG_NUMA
+#define cpu_to_node_mask(cpu) node_to_cpumask(cpu_to_node(cpu))
+#else
+#define cpu_to_node_mask(cpu) (cpu_online_map)
+#endif
+
 /*
  * Convert user-nice values [ -20 ... 0 ... 19 ]
  * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
@@ -154,10 +160,9 @@
 	task_t *curr, *idle;
 	struct mm_struct *prev_mm;
 	prio_array_t *active, *expired, arrays[2];
-	int prev_nr_running[NR_CPUS];
+	int prev_cpu_load[NR_CPUS];
 #ifdef CONFIG_NUMA
 	atomic_t *node_nr_running;
-	unsigned int nr_balanced;
 	int prev_node_load[MAX_NUMNODES];
 #endif
 	task_t *migration_thread;
@@ -867,29 +872,6 @@
 	return node;
 }
 
-static inline unsigned long cpus_to_balance(int this_cpu, runqueue_t *this_rq)
-{
-	int this_node = cpu_to_node(this_cpu);
-	/*
-	 * Avoid rebalancing between nodes too often.
-	 * We rebalance globally once every NODE_BALANCE_RATE load balances.
-	 */
-	if (++(this_rq->nr_balanced) == NODE_BALANCE_RATE) {
-		int node = find_busiest_node(this_node);
-		this_rq->nr_balanced = 0;
-		if (node >= 0)
-			return (node_to_cpumask(node) | (1UL << this_cpu));
-	}
-	return node_to_cpumask(this_node);
-}
-
-#else /* !CONFIG_NUMA */
-
-static inline unsigned long cpus_to_balance(int this_cpu, runqueue_t *this_rq)
-{
-	return cpu_online_map;
-}
-
 #endif /* CONFIG_NUMA */
 
 #if CONFIG_SMP
@@ -909,10 +891,10 @@
 			spin_lock(&busiest->lock);
 			spin_lock(&this_rq->lock);
 			/* Need to recalculate nr_running */
-			if (idle || (this_rq->nr_running > this_rq->prev_nr_running[this_cpu]))
+			if (idle || (this_rq->nr_running > this_rq->prev_cpu_load[this_cpu]))
 				nr_running = this_rq->nr_running;
 			else
-				nr_running = this_rq->prev_nr_running[this_cpu];
+				nr_running = this_rq->prev_cpu_load[this_cpu];
 		} else
 			spin_lock(&busiest->lock);
 	}
@@ -949,10 +931,10 @@
 	 * that case we are less picky about moving a task across CPUs and
 	 * take what can be taken.
 	 */
-	if (idle || (this_rq->nr_running > this_rq->prev_nr_running[this_cpu]))
+	if (idle || (this_rq->nr_running > this_rq->prev_cpu_load[this_cpu]))
 		nr_running = this_rq->nr_running;
 	else
-		nr_running = this_rq->prev_nr_running[this_cpu];
+		nr_running = this_rq->prev_cpu_load[this_cpu];
 
 	busiest = NULL;
 	max_load = 1;
@@ -961,11 +943,11 @@
 			continue;
 
 		rq_src = cpu_rq(i);
-		if (idle || (rq_src->nr_running < this_rq->prev_nr_running[i]))
+		if (idle || (rq_src->nr_running < this_rq->prev_cpu_load[i]))
 			load = rq_src->nr_running;
 		else
-			load = this_rq->prev_nr_running[i];
-		this_rq->prev_nr_running[i] = rq_src->nr_running;
+			load = this_rq->prev_cpu_load[i];
+		this_rq->prev_cpu_load[i] = rq_src->nr_running;
 
 		if ((load > max_load) && (rq_src != this_rq)) {
 			busiest = rq_src;
@@ -1029,7 +1011,7 @@
  * We call this with the current runqueue locked,
  * irqs disabled.
  */
-static void load_balance(runqueue_t *this_rq, int idle)
+static void load_balance(runqueue_t *this_rq, int idle, unsigned long cpumask)
 {
 	int imbalance, idx, this_cpu = smp_processor_id();
 	runqueue_t *busiest;
@@ -1037,8 +1019,7 @@
 	struct list_head *head, *curr;
 	task_t *tmp;
 
-	busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance,
-					cpus_to_balance(this_cpu, this_rq));
+	busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance, cpumask);
 	if (!busiest)
 		goto out;
 
@@ -1113,21 +1094,75 @@
  * frequency and balancing agressivity depends on whether the CPU is
  * idle or not.
  *
- * busy-rebalance every 250 msecs. idle-rebalance every 1 msec. (or on
+ * busy-rebalance every 200 msecs. idle-rebalance every 1 msec. (or on
  * systems with HZ=100, every 10 msecs.)
+ *
+ * On NUMA, do a node-rebalance every 400 msecs.
  */
-#define BUSY_REBALANCE_TICK (HZ/4 ?: 1)
 #define IDLE_REBALANCE_TICK (HZ/1000 ?: 1)
+#define BUSY_REBALANCE_TICK (HZ/5 ?: 1)
+#define IDLE_NODE_REBALANCE_TICK (IDLE_REBALANCE_TICK * 5)
+#define BUSY_NODE_REBALANCE_TICK (BUSY_REBALANCE_TICK * 100)
 
-static inline void idle_tick(runqueue_t *rq)
+#if CONFIG_NUMA
+static void balance_node(runqueue_t *this_rq, int idle, int this_cpu)
 {
-	if (jiffies % IDLE_REBALANCE_TICK)
-		return;
-	spin_lock(&rq->lock);
-	load_balance(rq, 1);
-	spin_unlock(&rq->lock);
+	int node = find_busiest_node(cpu_to_node(this_cpu));
+	unsigned long cpumask, this_cpumask = 1UL << this_cpu;
+
+	if (node >= 0) {
+		cpumask = node_to_cpumask(node) | this_cpumask;
+		spin_lock(&this_rq->lock);
+		load_balance(this_rq, idle, cpumask);
+		spin_unlock(&this_rq->lock);
+	}
 }
+#endif
 
+static void rebalance_tick(runqueue_t *this_rq, int idle)
+{
+#if CONFIG_NUMA
+	int this_cpu = smp_processor_id();
+#endif
+	unsigned long j = jiffies;
+
+	/*
+	 * First do inter-node rebalancing, then intra-node rebalancing,
+	 * if both events happen in the same tick. The inter-node
+	 * rebalancing does not necessarily have to create a perfect
+	 * balance within the node, since we load-balance the most loaded
+	 * node with the current CPU. (ie. other CPUs in the local node
+	 * are not balanced.)
+	 */
+	if (idle) {
+#if CONFIG_NUMA
+		if (!(j % IDLE_NODE_REBALANCE_TICK))
+			balance_node(this_rq, idle, this_cpu);
+#endif
+		if (!(j % IDLE_REBALANCE_TICK)) {
+			spin_lock(&this_rq->lock);
+			load_balance(this_rq, 0, cpu_to_node_mask(this_cpu));
+			spin_unlock(&this_rq->lock);
+		}
+		return;
+	}
+#if CONFIG_NUMA
+	if (!(j % BUSY_NODE_REBALANCE_TICK))
+		balance_node(this_rq, idle, this_cpu);
+#endif
+	if (!(j % BUSY_REBALANCE_TICK)) {
+		spin_lock(&this_rq->lock);
+		load_balance(this_rq, idle, cpu_to_node_mask(this_cpu));
+		spin_unlock(&this_rq->lock);
+	}
+}
+#else
+/*
+ * on UP we do not need to balance between CPUs:
+ */
+static inline void rebalance_tick(runqueue_t *this_rq, int idle)
+{
+}
 #endif
 
 DEFINE_PER_CPU(struct kernel_stat, kstat) = { { 0 } };
@@ -1170,9 +1205,7 @@
 			kstat_cpu(cpu).cpustat.iowait += sys_ticks;
 		else
 			kstat_cpu(cpu).cpustat.idle += sys_ticks;
-#if CONFIG_SMP
-		idle_tick(rq);
-#endif
+		rebalance_tick(rq, 1);
 		return;
 	}
 	if (TASK_NICE(p) > 0)
@@ -1228,11 +1261,8 @@
 			enqueue_task(p, rq->active);
 	}
 out:
-#if CONFIG_SMP
-	if (!(jiffies % BUSY_REBALANCE_TICK))
-		load_balance(rq, 0);
-#endif
 	spin_unlock(&rq->lock);
+	rebalance_tick(rq, 0);
 }
 
 void scheduling_functions_start_here(void) { }
@@ -1291,7 +1321,7 @@
 pick_next_task:
 	if (unlikely(!rq->nr_running)) {
 #if CONFIG_SMP
-		load_balance(rq, 1);
+		load_balance(rq, 1, cpu_to_node_mask(smp_processor_id()));
 		if (rq->nr_running)
 			goto pick_next_task;
 #endif
diff -urN linux-2.5.64-bk3/mm/filemap.c linux-2.5.64-bk4/mm/filemap.c
--- linux-2.5.64-bk3/mm/filemap.c	Tue Mar  4 19:29:15 2003
+++ linux-2.5.64-bk4/mm/filemap.c	Mon Mar 31 12:25:47 2003
@@ -562,7 +562,7 @@
 find_page:
 		page = find_get_page(mapping, index);
 		if (unlikely(page == NULL)) {
-			handle_ra_miss(mapping, ra);
+			handle_ra_miss(mapping, ra, index);
 			goto no_cached_page;
 		}
 		if (!PageUptodate(page))
@@ -978,7 +978,7 @@
 	page = find_get_page(mapping, pgoff);
 	if (!page) {
 		if (did_readahead) {
-			handle_ra_miss(mapping,ra);
+			handle_ra_miss(mapping, ra, pgoff);
 			did_readahead = 0;
 		}
 		goto no_cached_page;
diff -urN linux-2.5.64-bk3/mm/memory.c linux-2.5.64-bk4/mm/memory.c
--- linux-2.5.64-bk3/mm/memory.c	Tue Mar  4 19:29:18 2003
+++ linux-2.5.64-bk4/mm/memory.c	Mon Mar 31 12:25:47 2003
@@ -286,9 +286,16 @@
 					goto cont_copy_pte_range_noset;
 				}
 				pfn = pte_pfn(pte);
+				/* the pte points outside of valid memory, the
+				 * mapping is assumed to be good, meaningful
+				 * and not mapped via rmap - duplicate the
+				 * mapping as is.
+				 */
+				if (!pfn_valid(pfn)) {
+					set_pte(dst_pte, pte);
+					goto cont_copy_pte_range_noset;
+				}
 				page = pfn_to_page(pfn);
-				if (!pfn_valid(pfn))
-					goto cont_copy_pte_range;
 				if (PageReserved(page))
 					goto cont_copy_pte_range;
 
@@ -477,6 +484,16 @@
 #define ZAP_BLOCK_SIZE	(~(0UL))
 #endif
 
+/*
+ * hugepage regions must be unmapped with HPAGE_SIZE granularity
+ */
+static inline unsigned long zap_block_size(struct vm_area_struct *vma)
+{
+	if (is_vm_hugetlb_page(vma))
+		return HPAGE_SIZE;
+	return ZAP_BLOCK_SIZE;
+}
+
 /**
  * unmap_vmas - unmap a range of memory covered by a list of vma's
  * @tlbp: address of the caller's struct mmu_gather
@@ -507,7 +524,7 @@
 		struct vm_area_struct *vma, unsigned long start_addr,
 		unsigned long end_addr, unsigned long *nr_accounted)
 {
-	unsigned long zap_bytes = ZAP_BLOCK_SIZE;
+	unsigned long zap_bytes = zap_block_size(vma);
 	unsigned long tlb_start;	/* For tlb_finish_mmu */
 	int tlb_start_valid = 0;
 	int ret = 0;
@@ -555,7 +572,7 @@
 				*tlbp = tlb_gather_mmu(mm, 0);
 				tlb_start_valid = 0;
 			}
-			zap_bytes = ZAP_BLOCK_SIZE;
+			zap_bytes = zap_block_size(vma);
 		}
 		if (vma->vm_next && vma->vm_next->vm_start < vma->vm_end)
 			printk("%s: VMA list is not sorted correctly!\n",
diff -urN linux-2.5.64-bk3/mm/mmap.c linux-2.5.64-bk4/mm/mmap.c
--- linux-2.5.64-bk3/mm/mmap.c	Tue Mar  4 19:29:24 2003
+++ linux-2.5.64-bk4/mm/mmap.c	Mon Mar 31 12:25:47 2003
@@ -1258,20 +1258,24 @@
  
 	/*
 	 * If we need to split any vma, do it now to save pain later.
+	 *
+	 * Note: mremap's move_vma VM_ACCOUNT handling assumes a partially
+	 * unmapped vm_area_struct will remain in use: so lower split_vma
+	 * places tmp vma above, and higher split_vma places tmp vma below.
 	 */
 	if (start > mpnt->vm_start) {
 		if (split_vma(mm, mpnt, start, 0))
 			return -ENOMEM;
 		prev = mpnt;
-		mpnt = mpnt->vm_next;
 	}
 
 	/* Does it split the last one? */
 	last = find_vma(mm, end);
 	if (last && end > last->vm_start) {
-		if (split_vma(mm, last, end, 0))
+		if (split_vma(mm, last, end, 1))
 			return -ENOMEM;
 	}
+	mpnt = prev? prev->vm_next: mm->mmap;
 
 	/*
 	 * Remove the vma's, and unmap the actual pages
diff -urN linux-2.5.64-bk3/mm/page-writeback.c linux-2.5.64-bk4/mm/page-writeback.c
--- linux-2.5.64-bk3/mm/page-writeback.c	Tue Mar  4 19:29:31 2003
+++ linux-2.5.64-bk4/mm/page-writeback.c	Mon Mar 31 12:25:47 2003
@@ -139,6 +139,9 @@
 	struct page_state ps;
 	long background_thresh;
 	long dirty_thresh;
+	unsigned long pages_written = 0;
+	unsigned long write_chunk = sync_writeback_pages();
+
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 
 	get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
@@ -147,7 +150,7 @@
 			.bdi		= bdi,
 			.sync_mode	= WB_SYNC_NONE,
 			.older_than_this = NULL,
-			.nr_to_write	= sync_writeback_pages(),
+			.nr_to_write	= write_chunk,
 		};
 
 		dirty_exceeded = 1;
@@ -158,10 +161,14 @@
 		get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
 		if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh)
 			break;
+		pages_written += write_chunk - wbc.nr_to_write;
+		if (pages_written >= write_chunk)
+			break;		/* We've done our duty */
 		blk_congestion_wait(WRITE, HZ/10);
 	}
 
-	dirty_exceeded = 0;
+	if (ps.nr_dirty + ps.nr_writeback <= dirty_thresh)
+		dirty_exceeded = 0;
 
 	if (!writeback_in_progress(bdi) && ps.nr_dirty > background_thresh)
 		pdflush_operation(background_writeout, 0);
diff -urN linux-2.5.64-bk3/mm/readahead.c linux-2.5.64-bk4/mm/readahead.c
--- linux-2.5.64-bk3/mm/readahead.c	Tue Mar  4 19:28:58 2003
+++ linux-2.5.64-bk4/mm/readahead.c	Mon Mar 31 12:25:47 2003
@@ -136,6 +136,12 @@
  * ahead_size:  Together, these form the "ahead window".
  * ra_pages:	The externally controlled max readahead for this fd.
  *
+ * When readahead is in the "maximally shrunk" state (next_size == -1UL),
+ * readahead is disabled.  In this state, prev_page and size are used, inside
+ * handle_ra_miss(), to detect the resumption of sequential I/O.  Once there
+ * has been a decent run of sequential I/O (defined by get_min_readahead),
+ * readahead is reenabled.
+ *
  * The readahead code manages two windows - the "current" and the "ahead"
  * windows.  The intent is that while the application is walking the pages
  * in the current window, I/O is underway on the ahead window.  When the
@@ -168,6 +174,8 @@
  * will continue to perform linear reads.  Either at the new file position, or
  * at the old one after another seek.
  *
+ * After enough misses, readahead is fully disabled. (next_size = -1UL).
+ *
  * There is a special-case: if the first page which the application tries to
  * read happens to be the first page of the file, it is assumed that a linear
  * read is about to happen and the window is immediately set to half of the
@@ -253,14 +261,19 @@
 	int ret = 0;
 
 	while (nr_to_read) {
+		int err;
+
 		unsigned long this_chunk = (2 * 1024 * 1024) / PAGE_CACHE_SIZE;
 
 		if (this_chunk > nr_to_read)
 			this_chunk = nr_to_read;
-		ret = __do_page_cache_readahead(mapping, filp,
+		err = __do_page_cache_readahead(mapping, filp,
 						offset, this_chunk);
-		if (ret < 0)
+		if (err < 0) {
+			ret = err;
 			break;
+		}
+		ret += err;
 		offset += this_chunk;
 		nr_to_read -= this_chunk;
 	}
@@ -286,6 +299,7 @@
 				ra->ahead_size = ra->next_size;
 		} else {
 			ra->next_size = -1UL;
+			ra->size = 0;
 		}
 	}
 }
@@ -345,16 +359,19 @@
 		ra->next_size += 2;
 	} else {
 		/*
-		 * A miss - lseek, pread, etc.  Shrink the readahead
+		 * A miss - lseek, pagefault, pread, etc.  Shrink the readahead
 		 * window by 25%.
 		 */
-		ra->next_size -= ra->next_size / 4;
+		ra->next_size -= ra->next_size / 4 + 2;
 	}
 
-	if (ra->next_size > max)
+	if ((long)ra->next_size > (long)max)
 		ra->next_size = max;
-	if (ra->next_size < min)
-		ra->next_size = min;
+	if ((long)ra->next_size <= 0L) {
+		ra->next_size = -1UL;
+		ra->size = 0;
+		goto out;		/* Readahead is off */
+	}
 
 	/*
 	 * Is this request outside the current window?
@@ -374,6 +391,7 @@
 			ra->prev_page = ra->start;
 			ra->ahead_start = 0;
 			ra->ahead_size = 0;
+
 			/*
 			 * Control now returns, probably to sleep until I/O
 			 * completes against the first ahead page.
@@ -394,7 +412,6 @@
 		ra->size = ra->next_size;
 		ra->ahead_start = 0;		/* Invalidate these */
 		ra->ahead_size = 0;
-
 		actual = do_page_cache_readahead(mapping, filp, offset,
 						 ra->size);
 		check_ra_success(ra, ra->size, actual, orig_next_size);
@@ -455,21 +472,37 @@
  * not found.  This will happen if it was evicted by the VM (readahead
  * thrashing) or if the readahead window is maximally shrunk.
  *
- * If the window has been maximally shrunk (next_size == 0) then bump it up
- * again to resume readahead.
+ * If the window has been maximally shrunk (next_size == -1UL) then look to see
+ * if we are getting misses against sequential file offsets.  If so, and this
+ * persists then resume readahead.
  *
  * Otherwise we're thrashing, so shrink the readahead window by three pages.
  * This is because it is grown by two pages on a readahead hit.  Theory being
  * that the readahead window size will stabilise around the maximum level at
  * which there is no thrashing.
  */
-void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra)
+void handle_ra_miss(struct address_space *mapping,
+		struct file_ra_state *ra, pgoff_t offset)
 {
-	const unsigned long min = get_min_readahead(ra);
-
 	if (ra->next_size == -1UL) {
-		ra->next_size = min;
+		const unsigned long max = get_max_readahead(ra);
+
+		if (offset != ra->prev_page + 1) {
+			ra->size = 0;			/* Not sequential */
+		} else {
+			ra->size++;			/* A sequential read */
+			if (ra->size >= max) {		/* Resume readahead */
+				ra->start = offset - max;
+				ra->next_size = max;
+				ra->size = max;
+				ra->ahead_start = 0;
+				ra->ahead_size = 0;
+			}
+		}
+		ra->prev_page = offset;
 	} else {
+		const unsigned long min = get_min_readahead(ra);
+
 		ra->next_size -= 3;
 		if (ra->next_size < min)
 			ra->next_size = min;
diff -urN linux-2.5.64-bk3/mm/slab.c linux-2.5.64-bk4/mm/slab.c
--- linux-2.5.64-bk3/mm/slab.c	Tue Mar  4 19:29:33 2003
+++ linux-2.5.64-bk4/mm/slab.c	Mon Mar 31 12:25:47 2003
@@ -82,6 +82,7 @@
 #include	<linux/compiler.h>
 #include	<linux/seq_file.h>
 #include	<linux/notifier.h>
+#include	<linux/kallsyms.h>
 #include	<asm/uaccess.h>
 
 /*
@@ -114,7 +115,7 @@
 # define CREATE_MASK	(SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \
 			 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
 			 SLAB_NO_REAP | SLAB_CACHE_DMA | \
-			 SLAB_MUST_HWCACHE_ALIGN)
+			 SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER)
 #else
 # define CREATE_MASK	(SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
 			 SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN)
@@ -280,9 +281,7 @@
 #endif
 };
 
-/* internal c_flags */
-#define	CFLGS_OFF_SLAB	0x010000UL	/* slab management in own cache */
-
+#define CFLGS_OFF_SLAB		(0x80000000UL)
 #define	OFF_SLAB(x)	((x)->flags & CFLGS_OFF_SLAB)
 
 #define BATCHREFILL_LIMIT	16
@@ -764,10 +763,28 @@
 		addr += BYTES_PER_WORD;
 		size -= 2*BYTES_PER_WORD;
 	}
+	if (cachep->flags & SLAB_STORE_USER) {
+		size -= BYTES_PER_WORD;
+	}
 	memset(addr, val, size);
 	*(unsigned char *)(addr+size-1) = POISON_END;
 }
 
+static void *fprob(unsigned char* addr, unsigned int size)
+{
+	unsigned char *end;
+	
+	end = addr + size - 1;
+
+	for (; addr < end; addr++) {
+		if (*addr != POISON_BEFORE && *addr != POISON_AFTER)
+			return addr;
+	}
+	if (*addr != POISON_END)
+		return addr;
+	return NULL;
+}
+
 static void check_poison_obj(kmem_cache_t *cachep, void *addr)
 {
 	int size = cachep->objsize;
@@ -776,9 +793,47 @@
 		addr += BYTES_PER_WORD;
 		size -= 2*BYTES_PER_WORD;
 	}
-	end = memchr(addr, POISON_END, size);
-	if (end != (addr+size-1))
+	if (cachep->flags & SLAB_STORE_USER) {
+		size -= BYTES_PER_WORD;
+	}
+	end = fprob(addr, size);
+	if (end) {
+		int s;
+		printk(KERN_ERR "Slab corruption: start=%p, expend=%p, "
+				"problemat=%p\n", addr, addr+size-1, end);
+		if (cachep->flags & SLAB_STORE_USER) {
+			void *pc;
+
+			if (cachep->flags & SLAB_RED_ZONE)
+				pc = *(void**)(addr+size+BYTES_PER_WORD);
+			else
+				pc = *(void**)(addr+size);
+			printk(KERN_ERR "Last user: [<%p>]", pc);
+			print_symbol("(%s)", (unsigned long)pc);
+			printk("\n");
+		}
+		printk(KERN_ERR "Data: ");
+		for (s = 0; s < size; s++) {
+			if (((char*)addr)[s] == POISON_BEFORE)
+				printk(".");
+			else if (((char*)addr)[s] == POISON_AFTER)
+				printk("*");
+			else
+				printk("%02X ", ((unsigned char*)addr)[s]);
+		}
+		printk("\n");
+		printk(KERN_ERR "Next: ");
+		for (; s < size + 32; s++) {
+			if (((char*)addr)[s] == POISON_BEFORE)
+				printk(".");
+			else if (((char*)addr)[s] == POISON_AFTER)
+				printk("*");
+			else
+				printk("%02X ", ((unsigned char*)addr)[s]);
+		}
+		printk("\n");
 		slab_error(cachep, "object was modified after freeing");
+	}
 }
 #endif
 
@@ -792,16 +847,19 @@
 	int i;
 	for (i = 0; i < cachep->num; i++) {
 		void *objp = slabp->s_mem + cachep->objsize * i;
+		int objlen = cachep->objsize;
 
 		if (cachep->flags & SLAB_POISON)
 			check_poison_obj(cachep, objp);
+		if (cachep->flags & SLAB_STORE_USER)
+			objlen -= BYTES_PER_WORD;
 
 		if (cachep->flags & SLAB_RED_ZONE) {
 			if (*((unsigned long*)(objp)) != RED_INACTIVE)
 				slab_error(cachep, "start of a freed object "
 							"was overwritten");
-			if (*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) != RED_INACTIVE)
+			if (*((unsigned long*)(objp + objlen - BYTES_PER_WORD))
+				       	!= RED_INACTIVE)
 				slab_error(cachep, "end of a freed object "
 							"was overwritten");
 			objp += BYTES_PER_WORD;
@@ -890,7 +948,7 @@
 		 * do not red zone large object, causes severe
 		 * fragmentation.
 		 */
-		flags |= SLAB_RED_ZONE;
+		flags |= SLAB_RED_ZONE|SLAB_STORE_USER;
 	flags |= SLAB_POISON;
 #endif
 #endif
@@ -927,6 +985,10 @@
 		flags &= ~SLAB_HWCACHE_ALIGN;
 		size += 2*BYTES_PER_WORD;	/* words for redzone */
 	}
+	if (flags & SLAB_STORE_USER) {
+		flags &= ~SLAB_HWCACHE_ALIGN;
+		size += BYTES_PER_WORD;		/* word for kfree caller address */
+	}
 #endif
 	align = BYTES_PER_WORD;
 	if (flags & SLAB_HWCACHE_ALIGN)
@@ -1283,15 +1345,20 @@
 	for (i = 0; i < cachep->num; i++) {
 		void* objp = slabp->s_mem+cachep->objsize*i;
 #if DEBUG
+		int objlen = cachep->objsize;
 		/* need to poison the objs? */
 		if (cachep->flags & SLAB_POISON)
 			poison_obj(cachep, objp, POISON_BEFORE);
+		if (cachep->flags & SLAB_STORE_USER) {
+			objlen -= BYTES_PER_WORD;
+			((unsigned long*)(objp+objlen))[0] = 0;
+		}
 
 		if (cachep->flags & SLAB_RED_ZONE) {
 			*((unsigned long*)(objp)) = RED_INACTIVE;
-			*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) = RED_INACTIVE;
 			objp += BYTES_PER_WORD;
+			objlen -= 2* BYTES_PER_WORD;
+			*((unsigned long*)(objp + objlen)) = RED_INACTIVE;
 		}
 		/*
 		 * Constructors are not allowed to allocate memory from
@@ -1302,14 +1369,13 @@
 			cachep->ctor(objp, cachep, ctor_flags);
 
 		if (cachep->flags & SLAB_RED_ZONE) {
+			if (*((unsigned long*)(objp + objlen)) != RED_INACTIVE)
+				slab_error(cachep, "constructor overwrote the"
+							" end of an object");
 			objp -= BYTES_PER_WORD;
 			if (*((unsigned long*)(objp)) != RED_INACTIVE)
 				slab_error(cachep, "constructor overwrote the"
 							" start of an object");
-			if (*((unsigned long*)(objp + cachep->objsize -
-					BYTES_PER_WORD)) != RED_INACTIVE)
-				slab_error(cachep, "constructor overwrote the"
-							" end of an object");
 		}
 #else
 		if (cachep->ctor)
@@ -1451,11 +1517,12 @@
 #endif 
 }
 
-static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp)
+static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp, void *caller)
 {
 #if DEBUG
 	struct page *page;
 	unsigned int objnr;
+	int objlen = cachep->objsize;
 	struct slab *slabp;
 
 	kfree_debugcheck(objp);
@@ -1464,16 +1531,21 @@
 	BUG_ON(GET_PAGE_CACHE(page) != cachep);
 	slabp = GET_PAGE_SLAB(page);
 
+	if (cachep->flags & SLAB_STORE_USER) {
+		objlen -= BYTES_PER_WORD;
+	}
 	if (cachep->flags & SLAB_RED_ZONE) {
 		objp -= BYTES_PER_WORD;
 		if (xchg((unsigned long *)objp, RED_INACTIVE) != RED_ACTIVE)
 			slab_error(cachep, "double free, or memory before"
 						" object was overwritten");
-		if (xchg((unsigned long *)(objp+cachep->objsize -
-				BYTES_PER_WORD), RED_INACTIVE) != RED_ACTIVE)
+		if (xchg((unsigned long *)(objp+objlen-BYTES_PER_WORD), RED_INACTIVE) != RED_ACTIVE)
 			slab_error(cachep, "double free, or memory after "
 						" object was overwritten");
 	}
+	if (cachep->flags & SLAB_STORE_USER) {
+		*((void**)(objp+objlen)) = caller;
+	}
 
 	objnr = (objp-slabp->s_mem)/cachep->objsize;
 
@@ -1626,22 +1698,31 @@
 
 static inline void *
 cache_alloc_debugcheck_after(kmem_cache_t *cachep,
-			unsigned long flags, void *objp)
+			unsigned long flags, void *objp, void *caller)
 {
 #if DEBUG
+	int objlen = cachep->objsize;
+
 	if (!objp)	
 		return objp;
 	if (cachep->flags & SLAB_POISON)
 		check_poison_obj(cachep, objp);
+	if (cachep->flags & SLAB_STORE_USER) {
+		objlen -= BYTES_PER_WORD;
+		*((void **)(objp+objlen)) = caller;
+	}
+
 	if (cachep->flags & SLAB_RED_ZONE) {
 		/* Set alloc red-zone, and check old one. */
-		if (xchg((unsigned long *)objp, RED_ACTIVE) != RED_INACTIVE)
+		if (xchg((unsigned long *)objp, RED_ACTIVE) != RED_INACTIVE) {
 			slab_error(cachep, "memory before object was "
 						"overwritten");
-		if (xchg((unsigned long *)(objp+cachep->objsize -
-			  BYTES_PER_WORD), RED_ACTIVE) != RED_INACTIVE)
+		}
+		if (xchg((unsigned long *)(objp+objlen - BYTES_PER_WORD),
+				       	RED_ACTIVE) != RED_INACTIVE) {
 			slab_error(cachep, "memory after object was "
 						"overwritten");
+		}
 		objp += BYTES_PER_WORD;
 	}
 	if (cachep->ctor && cachep->flags & SLAB_POISON) {
@@ -1676,7 +1757,7 @@
 		objp = cache_alloc_refill(cachep, flags);
 	}
 	local_irq_restore(save_flags);
-	objp = cache_alloc_debugcheck_after(cachep, flags, objp);
+	objp = cache_alloc_debugcheck_after(cachep, flags, objp, __builtin_return_address(0));
 	return objp;
 }
 
@@ -1783,7 +1864,7 @@
 	struct array_cache *ac = ac_data(cachep);
 
 	check_irq_off();
-	objp = cache_free_debugcheck(cachep, objp);
+	objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
 
 	if (likely(ac->avail < ac->limit)) {
 		STATS_INC_FREEHIT(cachep);
diff -urN linux-2.5.64-bk3/net/sunrpc/sched.c linux-2.5.64-bk4/net/sunrpc/sched.c
--- linux-2.5.64-bk3/net/sunrpc/sched.c	Tue Mar  4 19:29:21 2003
+++ linux-2.5.64-bk4/net/sunrpc/sched.c	Mon Mar 31 12:25:48 2003
@@ -158,10 +158,8 @@
 static inline void
 rpc_delete_timer(struct rpc_task *task)
 {
-	if (timer_pending(&task->tk_timer)) {
+	if (del_timer_sync(&task->tk_timer))
 		dprintk("RPC: %4d deleting timer\n", task->tk_pid);
-		del_timer_sync(&task->tk_timer);
-	}
 }
 
 /*
