public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: patch for 2.4.1 disable printk and panic messages
       [not found] <Pine.SGI.4.10.10102071945350.926064-100000@Sky.inp.nsk.su>
@ 2001-02-08 11:44 ` Stefani Seibold
  2001-07-20 10:21 ` irda smc patch Stefani Seibold
  2001-07-20 11:36 ` irda smc patch... oops Stefani Seibold
  2 siblings, 0 replies; 4+ messages in thread
From: Stefani Seibold @ 2001-02-08 11:44 UTC (permalink / raw)
  To: torvalds, alan, D.A.Fedorov; +Cc: linux-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="US-ASCII", Size: 12405 bytes --]

> I think it is better to remove statements about rescue discs from patch
> because rescue discs are often interactive systems and needs messages even
> more than desktops.
> And statement about saving disk space by removing messages can irritate
> some kernel people.

I write it now a little bit lightweight - or maybe for recuse disks - okay?

>> To Linus: What must i do, to get this patch in the offical kernel?

> You should forward patch to Linus directly - I'm see that it is normal
> practice in list.

Hi Linus, do you think it is possible to get this patch in the offical kernel?

I had it tested now very well, and it should have no side effects with the new
macro expantion. All arguments of the printk and panic macro will be evaulated.

> Your mail client program wraps around long lines and patch fails
> without editing it in two places.

Sorry, here is the correct version of the patch, without line wraps:

-----patch for 2.4.1disable printk and panic -----

diff -u --recursive --new-file linux/CREDITS linux.noprintk/CREDITS
--- linux/CREDITS	Sun Dec 31 18:27:57 2000
+++ linux.noprintk/CREDITS	Fri Jan 26 10:51:19 2001
@@ -2396,6 +2396,14 @@
 S: Oldenburg
 S: Germany
 
+N: Stefani Seibold
+E: Stefani@Seibold.net
+D: Option to disable all kernel messages by overload printk with a
+D: dummy macro (saves a lot of disk- and ramspace for deeply embedded
+D: systems and maybe for rescue disks).
+S: Munich
+S: Germany
+
 N: Darren Senn
 E: sinster@darkwater.com
 D: Whatever I notice needs doing (so far: itimers, /proc)
diff -u --recursive --new-file linux/Documentation/Configure.help linux.noprintk/Documentation/Configure.help
--- linux/Documentation/Configure.help	Thu Jan  4 22:00:55 2001
+++ linux.noprintk/Documentation/Configure.help	Sun Jan 28 10:57:29 2001
@@ -12224,6 +12224,14 @@
   If unsure, say Y, or else you won't be able to do much with your new
   shiny Linux system :-)
 
+Disable kernel messages
+CONFIG_NOPRINTK
+  This option allows you to disable all kernel messages by overriding
+  the printk function a dummy macro.
+  On small embedded systems, this save a lot of rom and ram space. On
+  server or desktop systems you want human readable outputs, so it is
+  normally the best choice to say N to this option.
+
 Support for console on virtual terminal
 CONFIG_VT_CONSOLE
   The system console is the device which receives all kernel messages
diff -u --recursive --new-file linux/arch/alpha/config.in linux.noprintk/arch/alpha/config.in
--- linux/arch/alpha/config.in	Fri Dec 29 23:07:19 2000
+++ linux.noprintk/arch/alpha/config.in	Sun Jan 28 10:56:21 2001
@@ -359,6 +359,7 @@
 fi
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 
 bool 'Legacy kernel start address' CONFIG_ALPHA_LEGACY_START_ADDRESS
 
diff -u --recursive --new-file linux/arch/arm/config.in linux.noprintk/arch/arm/config.in
--- linux/arch/arm/config.in	Thu Nov 16 21:51:28 2000
+++ linux.noprintk/arch/arm/config.in	Sun Jan 28 10:55:58 2001
@@ -414,6 +414,7 @@
 bool 'Verbose user fault messages' CONFIG_DEBUG_USER
 bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 if [ "$CONFIG_CPU_26" = "y" ]; then
    bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE
 fi
diff -u --recursive --new-file linux/arch/i386/config.in linux.noprintk/arch/i386/config.in
--- linux/arch/i386/config.in	Fri Dec 29 23:35:47 2000
+++ linux.noprintk/arch/i386/config.in	Sun Jan 28 10:56:04 2001
@@ -366,4 +366,5 @@
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 endmenu
diff -u --recursive --new-file linux/arch/ia64/config.in linux.noprintk/arch/ia64/config.in
--- linux/arch/ia64/config.in	Thu Jan  4 21:50:17 2001
+++ linux.noprintk/arch/ia64/config.in	Sun Jan 28 10:56:07 2001
@@ -249,6 +249,7 @@
 fi
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 bool 'Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK
 bool 'Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
 bool 'Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
diff -u --recursive --new-file linux/arch/m68k/config.in linux.noprintk/arch/m68k/config.in
--- linux/arch/m68k/config.in	Thu Jan  4 22:00:55 2001
+++ linux.noprintk/arch/m68k/config.in	Sun Jan 28 10:56:09 2001
@@ -538,4 +538,5 @@
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 endmenu
diff -u --recursive --new-file linux/arch/mips/config.in linux.noprintk/arch/mips/config.in
--- linux/arch/mips/config.in	Thu Nov 16 21:51:28 2000
+++ linux.noprintk/arch/mips/config.in	Sun Jan 28 10:56:12 2001
@@ -397,4 +397,5 @@
   bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
 fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 endmenu
diff -u --recursive --new-file linux/arch/mips64/config.in linux.noprintk/arch/mips64/config.in
--- linux/arch/mips64/config.in	Wed Nov 29 06:42:04 2000
+++ linux.noprintk/arch/mips64/config.in	Sun Jan 28 10:56:31 2001
@@ -266,4 +266,5 @@
 fi
 bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 endmenu
diff -u --recursive --new-file linux/arch/parisc/config.in linux.noprintk/arch/parisc/config.in
--- linux/arch/parisc/config.in	Tue Dec  5 21:29:39 2000
+++ linux.noprintk/arch/parisc/config.in	Sun Jan 28 10:56:34 2001
@@ -204,5 +204,6 @@
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 endmenu
 
diff -u --recursive --new-file linux/arch/ppc/config.in linux.noprintk/arch/ppc/config.in
--- linux/arch/ppc/config.in	Thu Nov 16 21:51:28 2000
+++ linux.noprintk/arch/ppc/config.in	Sun Jan 28 10:56:01 2001
@@ -332,6 +332,7 @@
 comment 'Kernel hacking'
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 bool 'Include kgdb kernel debugger' CONFIG_KGDB
 bool 'Include xmon kernel debugger' CONFIG_XMON
 endmenu
diff -u --recursive --new-file linux/arch/sh/config.in linux.noprintk/arch/sh/config.in
--- linux/arch/sh/config.in	Thu Jan  4 22:19:13 2001
+++ linux.noprintk/arch/sh/config.in	Sun Jan 28 10:55:55 2001
@@ -260,6 +260,7 @@
 comment 'Kernel hacking'
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 bool 'Use LinuxSH standard BIOS' CONFIG_SH_STANDARD_BIOS
 if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then
    bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB
diff -u --recursive --new-file linux/arch/sparc/config.in linux.noprintk/arch/sparc/config.in
--- linux/arch/sparc/config.in	Wed Nov 29 06:53:44 2000
+++ linux.noprintk/arch/sparc/config.in	Sun Jan 28 10:56:26 2001
@@ -261,4 +261,5 @@
 comment 'Kernel hacking'
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 endmenu
diff -u --recursive --new-file linux/arch/sparc64/config.in linux.noprintk/arch/sparc64/config.in
--- linux/arch/sparc64/config.in	Thu Nov 16 21:51:28 2000
+++ linux.noprintk/arch/sparc64/config.in	Sun Jan 28 10:56:29 2001
@@ -335,5 +335,6 @@
 comment 'Kernel hacking'
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Disable kernel messages' CONFIG_NOPRINTK
 #bool 'ECache flush trap support at ta 0x72' CONFIG_EC_FLUSH_TRAP
 endmenu
diff -u --recursive --new-file linux/include/asm-i386/spinlock.h linux.noprintk/include/asm-i386/spinlock.h
--- linux/include/asm-i386/spinlock.h	Thu Jan  4 23:50:46 2001
+++ linux.noprintk/include/asm-i386/spinlock.h	Sun Jan 28 12:16:17 2001
@@ -5,8 +5,10 @@
 #include <asm/rwlock.h>
 #include <asm/page.h>
 
+#ifndef CONFIG_NOPRINTK
 extern int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
+#endif
 
 /* It seems that people are forgetting to
  * initialize their spinlocks properly, tsk tsk.
diff -u --recursive --new-file linux/include/linux/kernel.h linux.noprintk/include/linux/kernel.h
--- linux/include/linux/kernel.h	Mon Dec 11 21:49:54 2000
+++ linux.noprintk/include/linux/kernel.h	Mon Jan 29 21:03:40 2001
@@ -48,8 +48,15 @@
 struct semaphore;
 
 extern struct notifier_block *panic_notifier_list;
+#ifdef CONFIG_NOPRINTK
+
+#define panic(format, args...) ((format ,## args),panic_nomsg())
+
+NORET_TYPE void panic_nomsg(void) ATTRIB_NORET;
+#else
 NORET_TYPE void panic(const char * fmt, ...)
 	__attribute__ ((NORET_AND format (printf, 1, 2)));
+#endif
 NORET_TYPE void do_exit(long error_code)
 	ATTRIB_NORET;
 NORET_TYPE void up_and_exit(struct semaphore *, long)
@@ -68,8 +75,15 @@
 
 extern int session_of_pgrp(int pgrp);
 
+#ifdef CONFIG_NOPRINTK
+#define printk(format, args...) ((format ,## args),(int)0)
+
+#else
+
 asmlinkage int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
+#endif
+
 
 extern int console_loglevel;
 
diff -u --recursive --new-file linux/kernel/ksyms.c linux.noprintk/kernel/ksyms.c
--- linux/kernel/ksyms.c	Wed Jan  3 01:45:37 2001
+++ linux.noprintk/kernel/ksyms.c	Sun Jan 28 10:56:51 2001
@@ -440,8 +440,10 @@
 EXPORT_SYMBOL(nr_running);
 
 /* misc */
+#ifndef CONFIG_NOPRINTK
 EXPORT_SYMBOL(panic);
 EXPORT_SYMBOL(printk);
+#endif
 EXPORT_SYMBOL(sprintf);
 EXPORT_SYMBOL(vsprintf);
 EXPORT_SYMBOL(kdevname);
diff -u --recursive --new-file linux/kernel/panic.c linux.noprintk/kernel/panic.c
--- linux/kernel/panic.c	Mon Oct 16 21:58:51 2000
+++ linux.noprintk/kernel/panic.c	Sun Jan 28 12:13:47 2001
@@ -43,18 +43,25 @@
  *	This function never returns.
  */
  
+#ifdef CONFIG_NOPRINTK
+NORET_TYPE void panic_nomsg(void)
+#else
 NORET_TYPE void panic(const char * fmt, ...)
+#endif
 {
-	static char buf[1024];
-	va_list args;
 #if defined(CONFIG_ARCH_S390)
         unsigned long caller = (unsigned long) __builtin_return_address(0);
 #endif
 
+#ifndef CONFIG_NOPRINTK
+	static char buf[1024];
+	va_list args;
+
 	va_start(args, fmt);
 	vsprintf(buf, fmt, args);
 	va_end(args);
 	printk(KERN_EMERG "Kernel panic: %s\n",buf);
+#endif
 	if (in_interrupt())
 		printk(KERN_EMERG "In interrupt handler - not syncing\n");
 	else if (!current->pid)
@@ -70,6 +77,9 @@
 
 	notifier_call_chain(&panic_notifier_list, 0, NULL);
 
+#ifdef CONFIG_NOPRINTK
+	machine_restart(NULL);
+#else
 	if (panic_timeout > 0)
 	{
 		/*
@@ -93,6 +103,7 @@
 		printk("Press L1-A to return to the boot prom\n");
 	}
 #endif
+#endif
 #if defined(CONFIG_ARCH_S390)
         disabled_wait(caller);
 #endif
@@ -101,3 +112,18 @@
 		CHECK_EMERGENCY_SYNC
 	}
 }
+
+#ifdef CONFIG_NOPRINTK
+#undef panic
+
+#include <linux/module.h>
+
+NORET_TYPE void panic(const char * fmt, ...)
+{
+	panic_nomsg();
+}
+
+EXPORT_SYMBOL_NOVERS(panic);
+
+#endif
+
diff -u --recursive --new-file linux/kernel/printk.c linux.noprintk/kernel/printk.c
--- linux/kernel/printk.c	Sun Dec 31 03:16:13 2000
+++ linux.noprintk/kernel/printk.c	Sun Jan 28 10:57:23 2001
@@ -25,7 +25,9 @@
 #define LOG_BUF_LEN	(16384)
 #define LOG_BUF_MASK	(LOG_BUF_LEN-1)
 
+#ifndef CONFIG_NOPRINTK
 static char buf[1024];
+#endif
 
 /* printk's without a loglevel use this.. */
 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
@@ -251,6 +253,20 @@
 	return do_syslog(type, buf, len);
 }
 
+
+#ifdef CONFIG_NOPRINTK
+#undef printk
+
+#include <linux/module.h>
+
+asmlinkage int printk(const char *fmt, ...)
+{
+	return 0;
+}
+
+EXPORT_SYMBOL_NOVERS(printk);
+
+#else
 asmlinkage int printk(const char *fmt, ...)
 {
 	va_list args;
@@ -311,6 +327,7 @@
 	wake_up_interruptible(&log_wait);
 	return i;
 }
+#endif
 
 void console_print(const char *s)
 {
diff -u --recursive --new-file linux/Makefile linux.noprintk/Makefile
--- linux/Makefile	Thu Jan  4 22:48:13 2001
+++ linux.noprintk/Makefile	Mon Jan 29 20:51:51 2001
@@ -89,6 +90,10 @@
 
 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing
 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
+
+ifneq ($(CONFIG_NOPRINTK),)
+CFLAGS += -Wno-unused
+endif
 
 #
 # ROOT_DEV specifies the default root-device when making the image.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 4+ messages in thread

* irda smc patch
       [not found] <Pine.SGI.4.10.10102071945350.926064-100000@Sky.inp.nsk.su>
  2001-02-08 11:44 ` patch for 2.4.1 disable printk and panic messages Stefani Seibold
@ 2001-07-20 10:21 ` Stefani Seibold
  2001-07-20 11:36 ` irda smc patch... oops Stefani Seibold
  2 siblings, 0 replies; 4+ messages in thread
From: Stefani Seibold @ 2001-07-20 10:21 UTC (permalink / raw)
  To: torvalds, alan; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 21653 bytes --]

Hi folks,

this patch make the linux irda smc-ircc driver working the newer LPC47xxx smc chips, 
with are mostly used in notebook computers.

I added also support for all smc super i/o chips, which i had found a reference manual
on the smc webpage:

FDC37C44
FDC37C665GT
FDC37C669
FDC37C669
FDC37C78
FDC37N769
FDC37N869
FDC37B72X
FDC37B77X
FDC37B78X
FDC37B80X
FDC37C67X
FDC37C93X
FDC37C93XAPM
FDC37C93XFR
FDC37M707
FDC37M81X
FDC37N958FR
FDC37N972
LPC47N227
LPC47N267
LPC47B27X
LPC47B37X
LPC47M10X
LPC47M120
LPC47M13X
LPC47M14X
LPC47N252
LPC47S42X

It was tested currently on my INSPIRON 8000, so feedbacks are welcome

I hope this patch will go in to the 2.4 tree...

Greetings

diff -u --recursive --new-file linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c.save linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c
--- linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c.save	Fri Jul 20 10:32:05 2001
+++ linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c	Fri Jul 20 11:52:27 2001
@@ -8,7 +8,10 @@
  * Created at:    
  * Modified at:   Tue Feb 22 10:05:06 2000
  * Modified by:   Dag Brattli <dag@brattli.net>
+ * Modified at:   Tue Jun 26 2001
+ * Modified by:   Stefani Seibold <stefani@seibold.net>
  * 
+ *     Copyright (c) 2001      Stefani Seibold
  *     Copyright (c) 1999-2000 Dag Brattli
  *     Copyright (c) 1998-1999 Thomas Davis, 
  *     All Rights Reserved.
@@ -28,8 +31,9 @@
  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
  *     MA 02111-1307 USA
  *
- *     SIO's: SMC FDC37N869, FDC37C669, FDC37N958
- *     Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
+ *     SIO's: all SIO documentet by SMC (June, 2001)
+ *     Applicable Models :	Fujitsu Lifebook 635t, Sony PCG-505TX,
+ *     				Dell Inspiron 8000
  *
  ********************************************************************/
 
@@ -60,23 +64,27 @@
 #include <net/irda/smc-ircc.h>
 #include <net/irda/irport.h>
 
+struct smc_chip {
+	char *name;
+	u16 flags;
+	u8 devid;
+	u8 rev;
+};
+typedef struct smc_chip smc_chip_t;
+
 static char *driver_name = "smc-ircc";
 
-#define CHIP_IO_EXTENT 8
+#define	DIM(x)	(sizeof(x)/(sizeof(*(x))))
 
-static unsigned int io[]  = { ~0, ~0 }; 
-static unsigned int io2[] = { 0, 0 };
+#define CHIP_IO_EXTENT 8
 
 static struct ircc_cb *dev_self[] = { NULL, NULL};
 
 /* Some prototypes */
-static int  ircc_open(int i, unsigned int iobase, unsigned int board_addr);
+static int  ircc_open(unsigned int iobase, unsigned int board_addr);
 #ifdef MODULE
 static int  ircc_close(struct ircc_cb *self);
 #endif /* MODULE */
-static int  ircc_probe(int iobase, int board_addr);
-static int  ircc_probe_58(smc_chip_t *chip, chipio_t *info);
-static int  ircc_probe_69(smc_chip_t *chip, chipio_t *info);
 static int  ircc_dma_receive(struct ircc_cb *self, int iobase); 
 static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
 static int  ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -91,20 +99,73 @@
 static int  ircc_net_close(struct net_device *dev);
 static int  ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 
-/* These are the currently known SMC chipsets */
-static smc_chip_t chips[] =
+#define	KEY55_1	0	// SuperIO Configuration mode with Key <0x55>
+#define	KEY55_2	1	// SuperIO Configuration mode with Key <0x55,0x55>
+#define	NoIRDA	2	// SuperIO Chip has no IRDA Port
+#define	SIR	0	// SuperIO Chip has only slow IRDA
+#define	FIR	4	// SuperIO Chip has fast IRDA
+#define	SERx4	8	// SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud
+
+/* These are the currently known SMC SuperIO chipsets */
+static smc_chip_t fdc_chips_flat[]=
+{
+	// Base address 0x3f0 or 0x370
+	{ "37C44",	KEY55_1|NoIRDA,		0x00, 0x00 }, /* This chip can not detected */
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x65, 0x01 },
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x66, 0x01 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x03, 0x02 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x04, 0x02 }, /* ID? */
+	{ "37C78",	KEY55_2|NoIRDA,		0x78, 0x00 },
+	{ "37N769",	KEY55_1|FIR|SERx4,	0x28, 0x00 },
+	{ "37N869",	KEY55_1|FIR|SERx4,	0x29, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t fdc_chips_paged[]=
+{
+	{ "37B72X",	KEY55_1|SIR|SERx4,	0x4c, 0x00 },
+	{ "37B77X",	KEY55_1|SIR|SERx4,	0x43, 0x00 },
+	{ "37B78X",	KEY55_1|SIR|SERx4,	0x44, 0x00 },
+	{ "37B80X",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37C67X",	KEY55_1|FIR|SERx4,	0x40, 0x00 },
+	{ "37C93X",	KEY55_2|SIR|SERx4,	0x02, 0x01 },
+	{ "37C93XAPM",	KEY55_1|SIR|SERx4,	0x30, 0x01 },
+	{ "37C93XFR",	KEY55_2|FIR|SERx4,	0x03, 0x01 },
+	{ "37M707",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37M81X",	KEY55_1|SIR|SERx4,	0x4d, 0x00 },
+	{ "37N958FR",	KEY55_1|FIR|SERx4,	0x09, 0x04 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0a, 0x00 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0b, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t lpc_chips_flat[]=
 {
-	{ "FDC37C669", 0x55, 0x55, 0x0d, 0x04, ircc_probe_69 },
-	{ "FDC37N769", 0x55, 0x55, 0x0d, 0x28, ircc_probe_69 },
-	{ "FDC37N869", 0x55, 0x00, 0x0d, 0x29, ircc_probe_69 },
-	{ "FDC37N958", 0x55, 0x55, 0x20, 0x09, ircc_probe_58 },
-	{ "FDC37N971", 0x55, 0x55, 0x20, 0x0a, ircc_probe_58 },
-	{ "FDC37N972", 0x55, 0x55, 0x20, 0x0b, ircc_probe_58 },
+	// Base address 0x2E or 0x4E
+	{ "47N227",	KEY55_1|FIR|SERx4,	0x5a, 0x00 },
+	{ "47N267",	KEY55_1|FIR|SERx4,	0x5e, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t lpc_chips_paged[]=
+{
+	{ "47B27X",	KEY55_1|SIR|SERx4,	0x51, 0x00 },
+	{ "47B37X",	KEY55_1|SIR|SERx4,	0x52, 0x00 },
+	{ "47M10X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M120",	KEY55_1|NoIRDA|SERx4,	0x5c, 0x00 },
+	{ "47M13X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M14X",	KEY55_1|SIR|SERx4,	0x5f, 0x00 },
+	{ "47N252",	KEY55_1|FIR|SERx4,	0x0e, 0x00 },
+	{ "47S42X",	KEY55_1|SIR|SERx4,	0x57, 0x00 },
 	{ NULL }
 };
 
 static int ircc_irq=255;
 static int ircc_dma=255;
+static int ircc_fir=0;
+static int ircc_sir=0;
+
+static unsigned short	dev_count=0;
 
 static inline void register_bank(int iobase, int bank)
 {
@@ -112,6 +173,209 @@
                iobase+IRCC_MASTER);
 }
 
+static int smc_access(unsigned short cfg_base,unsigned char reg)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	outb(reg, cfg_base);
+
+	if (inb(cfg_base)!=reg)
+		return -1;
+
+	return 0;
+}
+
+static smc_chip_t * smc_probe(unsigned short cfg_base,u8 reg,smc_chip_t *chip,char *type)
+{
+	u8	devid,xdevid; 
+	u8	rev; 
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	/* Leave configuration */
+
+	outb(0xaa, cfg_base);
+
+	if (inb(cfg_base)==0xaa)	/* not a smc superio chip */
+		return NULL;
+
+	outb(reg, cfg_base);
+
+	xdevid=inb(cfg_base+1);
+
+	/* Enter configuration */
+
+	outb(0x55, cfg_base);
+
+	if (smc_access(cfg_base,0x55))	/* send second key and check */
+		return NULL;
+
+	/* probe device ID */
+
+	if (smc_access(cfg_base,reg))
+		return NULL;
+
+	devid=inb(cfg_base+1);
+
+	if (devid==0)			/* typical value for unused port */
+		return NULL;
+
+	if (devid==0xff)		/* typical value for unused port */
+		return NULL;
+
+	/* probe revision ID */
+
+	if (smc_access(cfg_base,reg+1))
+		return NULL;
+
+	rev=inb(cfg_base+1);
+
+	if (rev>=128)			/* i think this will make no sense */
+		return NULL;
+
+	if (devid==xdevid)		/* protection against false positives */        
+		return NULL;
+
+	/* Check for expected device ID; are there others? */
+
+	while(chip->devid!=devid) {
+
+		chip++;
+
+		if (chip->name==NULL)
+			return NULL;
+	}
+	if (chip->rev>rev)
+		return NULL;
+
+	MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+	
+	if (chip->flags&NoIRDA)
+		MESSAGE("chipset does not support IRDA\n");
+
+	return chip;
+}
+
+/*
+ * Function smc_superio_flat (chip, base, type)
+ *
+ *    Try get configuration of a smc SuperIO chip with flat register model
+ *
+ */
+static int smc_superio_flat(smc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io;
+	unsigned short sir_io;
+	__u8 mode;
+	int ret = -ENODEV;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (smc_probe(cfg_base,0xD,chips,type)==NULL)
+		return ret;
+
+	outb(0x0c, cfg_base);
+
+	mode = inb(cfg_base+1);
+	mode = (mode & 0x38) >> 3;
+		
+	/* Value for IR port */
+	if (mode && mode < 4) {
+		/* SIR iobase */
+		outb(0x25, cfg_base);
+		sir_io = inb(cfg_base+1) << 2;
+
+	       	/* FIR iobase */
+		outb(0x2b, cfg_base);
+		fir_io = inb(cfg_base+1) << 3;
+
+		if (fir_io) {
+			if (ircc_open(fir_io, sir_io) == 0)
+				ret=0; 
+		}
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+/*
+ * Function smc_superio_paged (chip, base, type)
+ *
+ *    Try  get configuration of a smc SuperIO chip with paged register model
+ *
+ */
+static int smc_superio_paged(smc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io;
+	unsigned short sir_io;
+	int ret = -ENODEV;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (smc_probe(cfg_base,0x20,chips,type)==NULL)
+		return ret;
+	
+	/* Select logical device (UART2) */
+	outb(0x07, cfg_base);
+	outb(0x05, cfg_base + 1);
+		
+	/* SIR iobase */
+	outb(0x60, cfg_base);
+	sir_io  = inb(cfg_base + 1) << 8;
+	outb(0x61, cfg_base);
+	sir_io |= inb(cfg_base + 1);
+		
+	/* Read FIR base */
+	outb(0x62, cfg_base);
+	fir_io = inb(cfg_base + 1) << 8;
+	outb(0x63, cfg_base);
+	fir_io |= inb(cfg_base + 1);
+	outb(0x2b, cfg_base); // ???
+
+	if (fir_io) {
+		if (ircc_open(fir_io, sir_io) == 0)
+			ret=0; 
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+static int smc_superio_fdc(unsigned short cfg_base)
+{
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+
+	if (!smc_superio_flat(fdc_chips_flat,cfg_base,"FDC")||!smc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+		return 0;
+
+	return -1;
+}
+
+static int smc_superio_lpc(unsigned short cfg_base)
+{
+#if 0
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+#endif
+
+	if (!smc_superio_flat(lpc_chips_flat,cfg_base,"LPC")||!smc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+		return 0;
+
+	return -1;
+}
+
 /*
  * Function ircc_init ()
  *
@@ -120,37 +384,36 @@
  */
 int __init ircc_init(void)
 {
-	static int smcreg[] = { 0x3f0, 0x370 };
-	smc_chip_t *chip;
-	chipio_t info;
-	int ret = -ENODEV;
-	int i;
+	int ret=-ENODEV;
 
 	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	/* Probe for all the NSC chipsets we know about */
-	for (chip=chips; chip->name ; chip++) {
-		for (i=0; i<2; i++) {
-			info.cfg_base = smcreg[i];
-			
-			/* 
-			 * First we check if the user has supplied any
-                         * parameters which we should use instead of probed
-			 * values
-			 */
-			if (io[i] < 0x2000) {
-				info.fir_base = io[i];
-				info.sir_base = io2[i];
-			} else if (chip->probe(chip, &info) < 0)
-				continue;
-			if (check_region(info.fir_base, CHIP_IO_EXTENT) < 0)
-				continue;
-			if (check_region(info.sir_base, CHIP_IO_EXTENT) < 0)
-				continue;
-			if (ircc_open(i, info.fir_base, info.sir_base) == 0)
-				ret = 0; 
-		}
+	dev_count=0;
+
+	if ((ircc_fir>0)&&(ircc_sir>0)) {
+	        MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
+		MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
+
+		if (ircc_open(ircc_fir, ircc_sir) == 0)
+			return 0;
+
+		return -ENODEV;
 	}
+
+	/* Trys to open for all the SMC chipsets we know about */
+
+	IRDA_DEBUG(0, __FUNCTION__ 
+	" Try to open all known SMC chipsets\n");
+
+	if (smc_superio_fdc(0x3f0))
+		ret=0;
+	if (smc_superio_fdc(0x370))
+		ret=0;
+	if (smc_superio_lpc(0x2e))
+		ret=0;
+	if (smc_superio_lpc(0x4e))
+		ret=0;
+
 	return ret;
 }
 
@@ -177,24 +440,57 @@
 /*
  * Function ircc_open (iobase, irq)
  *
- *    Open driver instance
+ *    Try to open driver instance
  *
  */
-static int ircc_open(int i, unsigned int fir_base, unsigned int sir_base)
+static int ircc_open(unsigned int fir_base, unsigned int sir_base)
 {
 	struct ircc_cb *self;
         struct irport_cb *irport;
-	int config;
-	int ret;
+	unsigned char low, high, chip, config, dma, irq, version;
+
 
 	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	if ((config = ircc_probe(fir_base, sir_base)) == -1) {
+	if (check_region(fir_base, CHIP_IO_EXTENT) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
+			   fir_base);
+		return -ENODEV;
+	}
+#if POSSIBLE_USED_BY_SERIAL_DRIVER
+	if (check_region(sir_base, CHIP_IO_EXTENT) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get sir_base of 0x%03x\n",
+			   sir_base);
+		return -ENODEV;
+	}
+#endif
+
+	register_bank(fir_base, 3);
+
+	high    = inb(fir_base+IRCC_ID_HIGH);
+	low     = inb(fir_base+IRCC_ID_LOW);
+	chip    = inb(fir_base+IRCC_CHIP_ID);
+	version = inb(fir_base+IRCC_VERSION);
+	config  = inb(fir_base+IRCC_INTERFACE);
+
+	irq     = config >> 4 & 0x0f;
+	dma     = config & 0x0f;
+
+        if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { 
 	        IRDA_DEBUG(0, __FUNCTION__ 
 			   "(), addr 0x%04x - no device found!\n", fir_base);
-		return -1;
+		return -ENODEV;
 	}
-	
+	MESSAGE("SMC IrDA Controller found\n IrCC version %d.%d, "
+		"firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
+		chip & 0x0f, version, fir_base, sir_base, dma, irq);
+
+	if (dev_count>DIM(dev_self)) {
+	        IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), to many devices!\n");
+		return -ENOMEM;
+	}
+
 	/*
 	 *  Allocate new instance of the driver
 	 */
@@ -206,46 +502,74 @@
 	}
 	memset(self, 0, sizeof(struct ircc_cb));
 	spin_lock_init(&self->lock);
-   
-	/* Need to store self somewhere */
-	dev_self[i] = self;
 
-	irport = irport_open(i, sir_base, config >> 4 & 0x0f);
-	if (!irport)
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for receive buffer!\n",
+                      driver_name);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for transmit buffer!\n",
+                      driver_name);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	irport = irport_open(dev_count, sir_base, irq);
+	if (!irport) {
+		kfree(self->tx_buff.head);
+		kfree(self->rx_buff.head);
+		kfree(self);
 		return -ENODEV;
+	}
+
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+   
+	/* Need to store self somewhere */
+	dev_self[dev_count++] = self;
 
 	/* Steal the network device from irport */
 	self->netdev = irport->netdev;
 	self->irport = irport;
+
 	irport->priv = self;
 
 	/* Initialize IO */
 	self->io.fir_base  = fir_base;
         self->io.sir_base  = sir_base; /* Used by irport */
-        self->io.irq       = config >> 4 & 0x0f;
+        self->io.fir_ext   = CHIP_IO_EXTENT;
+        self->io.sir_ext   = 8;       /* Used by irport */
+
 	if (ircc_irq < 255) {
-	        MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
-			driver_name, self->io.irq, ircc_irq);
+		if (ircc_irq!=irq)
+			MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
+				driver_name, self->io.irq, ircc_irq);
 		self->io.irq = ircc_irq;
 	}
-        self->io.fir_ext   = CHIP_IO_EXTENT;
-        self->io.sir_ext   = 8;       /* Used by irport */
-        self->io.dma       = config & 0x0f;
+	else
+		self->io.irq = irq;
 	if (ircc_dma < 255) {
-	        MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
-			driver_name, self->io.dma, ircc_dma);
+		if (ircc_dma!=dma)
+			MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
+				driver_name, self->io.dma, ircc_dma);
 		self->io.dma = ircc_dma;
 	}
+	else
+		self->io.dma = dma;
 
-	/* Lock the port that we need */
-	ret = check_region(self->io.fir_base, self->io.fir_ext);
-	if (ret < 0) { 
-		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
-			   self->io.fir_base);
-                kfree(self);
-		return -ENODEV;
-	}
-	request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+	request_region(fir_base, CHIP_IO_EXTENT, driver_name);
 
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&irport->qos);
@@ -260,23 +584,6 @@
 
 	irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 	
-	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	self->rx_buff.truesize = 4000; 
-	self->tx_buff.truesize = 4000;
-
-	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-					      GFP_KERNEL|GFP_DMA);
-	if (self->rx_buff.head == NULL)
-		return -ENOMEM;
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	
-	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-					      GFP_KERNEL|GFP_DMA);
-	if (self->tx_buff.head == NULL) {
-		kfree(self->rx_buff.head);
-		return -ENOMEM;
-	}
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
@@ -295,6 +602,10 @@
         if (self->pmdev)
                 self->pmdev->data = self;
 
+	/* Power on device */
+
+	outb(0x00, fir_base+IRCC_MASTER);
+
 	return 0;
 }
 
@@ -347,146 +658,6 @@
 #endif /* MODULE */
 
 /*
- * Function ircc_probe_69 (chip, info)
- *
- *    Probes for the SMC FDC37C669 and FDC37N869
- *
- */
-static int ircc_probe_69(smc_chip_t *chip, chipio_t *info)
-{
-	int cfg_base = info->cfg_base;
-	__u8 devid, mode;
-	int ret = -ENODEV;
-	int fir_io;
-	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Enter configuration */
-	outb(chip->entr1, cfg_base);
-	outb(chip->entr2, cfg_base);
-	
-	outb(chip->cid_index, cfg_base);
-	devid = inb(cfg_base+1);
-	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
-	
-	/* Check for expected device ID; are there others? */
-	if (devid == chip->cid_value) {
-		outb(0x0c, cfg_base);
-		mode = inb(cfg_base+1);
-		mode = (mode & 0x38) >> 3;
-		
-		/* Value for IR port */
-		if (mode && mode < 4) {
-			/* SIR iobase */
-			outb(0x25, cfg_base);
-			info->sir_base = inb(cfg_base+1) << 2;
-
-		       	/* FIR iobase */
-			outb(0x2b, cfg_base);
-			fir_io = inb(cfg_base+1) << 3;
-			if (fir_io) {
-				ret = 0;
-				info->fir_base = fir_io;
-			}
-		}
-	}
-	
-	/* Exit configuration */
-	outb(0xaa, cfg_base);
-
-	return ret;
-}
-
-/*
- * Function ircc_probe_58 (chip, info)
- *
- *    Probes for the SMC FDC37N958
- *
- */
-static int ircc_probe_58(smc_chip_t *chip, chipio_t *info)
-{
-	int cfg_base = info->cfg_base;
-	__u8 devid;
-	int ret = -ENODEV;
-	int fir_io;
-	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Enter configuration */
-	outb(chip->entr1, cfg_base);
-	outb(chip->entr2, cfg_base);
-	
-	outb(chip->cid_index, cfg_base);
-	devid = inb(cfg_base+1);
-	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
-	
-	/* Check for expected device ID; are there others? */
-	if (devid == chip->cid_value) {
-		/* Select logical device (UART2) */
-		outb(0x07, cfg_base);
-		outb(0x05, cfg_base + 1);
-		
-		/* SIR iobase */
-		outb(0x60, cfg_base);
-		info->sir_base = inb(cfg_base + 1) << 8;
-		outb(0x61, cfg_base);
-		info->sir_base |= inb(cfg_base + 1);
-		
-		/* Read FIR base */
-		outb(0x62, cfg_base);
-		fir_io = inb(cfg_base + 1) << 8;
-		outb(0x63, cfg_base);
-		fir_io |= inb(cfg_base + 1);
-		outb(0x2b, cfg_base);
-		if (fir_io) {
-			ret = 0;
-			info->fir_base = fir_io;
-		}
-	}
-	
-	/* Exit configuration */
-	outb(0xaa, cfg_base);
-
-	return ret;
-}
-
-/*
- * Function ircc_probe (iobase, board_addr, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
-static int ircc_probe(int fir_base, int sir_base) 
-{
-	int low, high, chip, config, dma, irq;
-	int iobase = fir_base;
-	int version = 1;
-
-	IRDA_DEBUG(0, __FUNCTION__ "\n");
-
-	register_bank(iobase, 3);
-	high    = inb(iobase+IRCC_ID_HIGH);
-	low     = inb(iobase+IRCC_ID_LOW);
-	chip    = inb(iobase+IRCC_CHIP_ID);
-	version = inb(iobase+IRCC_VERSION);
-	config  = inb(iobase+IRCC_INTERFACE);
-	irq     = config >> 4 & 0x0f;
-	dma     = config & 0x0f;
-
-        if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) { 
-                MESSAGE("SMC IrDA Controller found; IrCC version %d.%d, "
-			"port 0x%03x, dma=%d, irq=%d\n",
-			chip & 0x0f, version, iobase, dma, irq);
-	} else
-		return -ENODEV;
-
-	/* Power on device */
-	outb(0x00, iobase+IRCC_MASTER);
-
-	return config;
-}
-
-/*
  * Function ircc_change_speed (self, baud)
  *
  *    Change the speed of the device
@@ -1055,6 +1226,10 @@
 MODULE_PARM_DESC(ircc_dma, "DMA channel");
 MODULE_PARM(ircc_irq, "1i");
 MODULE_PARM_DESC(ircc_irq, "IRQ line");
+MODULE_PARM(ircc_fir, "1-4i");
+MODULE_PARM_DESC(ircc_fir, "FIR Base Adress");
+MODULE_PARM(ircc_sir, "1-4i");
+MODULE_PARM_DESC(ircc_sir, "SIR Base Adress");
 
 int init_module(void)
 {
diff -u --recursive --new-file linux-2.4.6-ac5/include/net/irda/smc-ircc.h.save linux-2.4.6-ac5/include/net/irda/smc-ircc.h
--- linux-2.4.6-ac5/include/net/irda/smc-ircc.h.save	Fri Jul 20 10:59:58 2001
+++ linux-2.4.6-ac5/include/net/irda/smc-ircc.h	Fri Jul 20 11:00:25 2001
@@ -154,16 +154,6 @@
 #define IRCC_1152                  0x80
 #define IRCC_CRC                   0x40
 
-struct smc_chip {
-	char *name;
-	unsigned char entr1;
-	unsigned char entr2;
-	unsigned char cid_index;
-	unsigned char cid_value;
-	int (*probe)(struct smc_chip *chip, chipio_t *info);
-};
-typedef struct smc_chip smc_chip_t;
-
 /* Private data for each instance */
 struct ircc_cb {
 	struct net_device *netdev;     /* Yes! we are some kind of netdevice */

[-- Attachment #2: patch for smc-ircc superio support --]
[-- Type: text/plain, Size: 20974 bytes --]

diff -u --recursive --new-file linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c.save linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c
--- linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c.save	Fri Jul 20 10:32:05 2001
+++ linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c	Fri Jul 20 11:52:27 2001
@@ -8,7 +8,10 @@
  * Created at:    
  * Modified at:   Tue Feb 22 10:05:06 2000
  * Modified by:   Dag Brattli <dag@brattli.net>
+ * Modified at:   Tue Jun 26 2001
+ * Modified by:   Stefani Seibold <stefani@seibold.net>
  * 
+ *     Copyright (c) 2001      Stefani Seibold
  *     Copyright (c) 1999-2000 Dag Brattli
  *     Copyright (c) 1998-1999 Thomas Davis, 
  *     All Rights Reserved.
@@ -28,8 +31,9 @@
  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
  *     MA 02111-1307 USA
  *
- *     SIO's: SMC FDC37N869, FDC37C669, FDC37N958
- *     Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
+ *     SIO's: all SIO documentet by SMC (June, 2001)
+ *     Applicable Models :	Fujitsu Lifebook 635t, Sony PCG-505TX,
+ *     				Dell Inspiron 8000
  *
  ********************************************************************/
 
@@ -60,23 +64,27 @@
 #include <net/irda/smc-ircc.h>
 #include <net/irda/irport.h>
 
+struct smc_chip {
+	char *name;
+	u16 flags;
+	u8 devid;
+	u8 rev;
+};
+typedef struct smc_chip smc_chip_t;
+
 static char *driver_name = "smc-ircc";
 
-#define CHIP_IO_EXTENT 8
+#define	DIM(x)	(sizeof(x)/(sizeof(*(x))))
 
-static unsigned int io[]  = { ~0, ~0 }; 
-static unsigned int io2[] = { 0, 0 };
+#define CHIP_IO_EXTENT 8
 
 static struct ircc_cb *dev_self[] = { NULL, NULL};
 
 /* Some prototypes */
-static int  ircc_open(int i, unsigned int iobase, unsigned int board_addr);
+static int  ircc_open(unsigned int iobase, unsigned int board_addr);
 #ifdef MODULE
 static int  ircc_close(struct ircc_cb *self);
 #endif /* MODULE */
-static int  ircc_probe(int iobase, int board_addr);
-static int  ircc_probe_58(smc_chip_t *chip, chipio_t *info);
-static int  ircc_probe_69(smc_chip_t *chip, chipio_t *info);
 static int  ircc_dma_receive(struct ircc_cb *self, int iobase); 
 static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
 static int  ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -91,20 +99,73 @@
 static int  ircc_net_close(struct net_device *dev);
 static int  ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 
-/* These are the currently known SMC chipsets */
-static smc_chip_t chips[] =
+#define	KEY55_1	0	// SuperIO Configuration mode with Key <0x55>
+#define	KEY55_2	1	// SuperIO Configuration mode with Key <0x55,0x55>
+#define	NoIRDA	2	// SuperIO Chip has no IRDA Port
+#define	SIR	0	// SuperIO Chip has only slow IRDA
+#define	FIR	4	// SuperIO Chip has fast IRDA
+#define	SERx4	8	// SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud
+
+/* These are the currently known SMC SuperIO chipsets */
+static smc_chip_t fdc_chips_flat[]=
+{
+	// Base address 0x3f0 or 0x370
+	{ "37C44",	KEY55_1|NoIRDA,		0x00, 0x00 }, /* This chip can not detected */
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x65, 0x01 },
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x66, 0x01 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x03, 0x02 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x04, 0x02 }, /* ID? */
+	{ "37C78",	KEY55_2|NoIRDA,		0x78, 0x00 },
+	{ "37N769",	KEY55_1|FIR|SERx4,	0x28, 0x00 },
+	{ "37N869",	KEY55_1|FIR|SERx4,	0x29, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t fdc_chips_paged[]=
+{
+	{ "37B72X",	KEY55_1|SIR|SERx4,	0x4c, 0x00 },
+	{ "37B77X",	KEY55_1|SIR|SERx4,	0x43, 0x00 },
+	{ "37B78X",	KEY55_1|SIR|SERx4,	0x44, 0x00 },
+	{ "37B80X",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37C67X",	KEY55_1|FIR|SERx4,	0x40, 0x00 },
+	{ "37C93X",	KEY55_2|SIR|SERx4,	0x02, 0x01 },
+	{ "37C93XAPM",	KEY55_1|SIR|SERx4,	0x30, 0x01 },
+	{ "37C93XFR",	KEY55_2|FIR|SERx4,	0x03, 0x01 },
+	{ "37M707",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37M81X",	KEY55_1|SIR|SERx4,	0x4d, 0x00 },
+	{ "37N958FR",	KEY55_1|FIR|SERx4,	0x09, 0x04 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0a, 0x00 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0b, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t lpc_chips_flat[]=
 {
-	{ "FDC37C669", 0x55, 0x55, 0x0d, 0x04, ircc_probe_69 },
-	{ "FDC37N769", 0x55, 0x55, 0x0d, 0x28, ircc_probe_69 },
-	{ "FDC37N869", 0x55, 0x00, 0x0d, 0x29, ircc_probe_69 },
-	{ "FDC37N958", 0x55, 0x55, 0x20, 0x09, ircc_probe_58 },
-	{ "FDC37N971", 0x55, 0x55, 0x20, 0x0a, ircc_probe_58 },
-	{ "FDC37N972", 0x55, 0x55, 0x20, 0x0b, ircc_probe_58 },
+	// Base address 0x2E or 0x4E
+	{ "47N227",	KEY55_1|FIR|SERx4,	0x5a, 0x00 },
+	{ "47N267",	KEY55_1|FIR|SERx4,	0x5e, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t lpc_chips_paged[]=
+{
+	{ "47B27X",	KEY55_1|SIR|SERx4,	0x51, 0x00 },
+	{ "47B37X",	KEY55_1|SIR|SERx4,	0x52, 0x00 },
+	{ "47M10X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M120",	KEY55_1|NoIRDA|SERx4,	0x5c, 0x00 },
+	{ "47M13X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M14X",	KEY55_1|SIR|SERx4,	0x5f, 0x00 },
+	{ "47N252",	KEY55_1|FIR|SERx4,	0x0e, 0x00 },
+	{ "47S42X",	KEY55_1|SIR|SERx4,	0x57, 0x00 },
 	{ NULL }
 };
 
 static int ircc_irq=255;
 static int ircc_dma=255;
+static int ircc_fir=0;
+static int ircc_sir=0;
+
+static unsigned short	dev_count=0;
 
 static inline void register_bank(int iobase, int bank)
 {
@@ -112,6 +173,209 @@
                iobase+IRCC_MASTER);
 }
 
+static int smc_access(unsigned short cfg_base,unsigned char reg)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	outb(reg, cfg_base);
+
+	if (inb(cfg_base)!=reg)
+		return -1;
+
+	return 0;
+}
+
+static smc_chip_t * smc_probe(unsigned short cfg_base,u8 reg,smc_chip_t *chip,char *type)
+{
+	u8	devid,xdevid; 
+	u8	rev; 
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	/* Leave configuration */
+
+	outb(0xaa, cfg_base);
+
+	if (inb(cfg_base)==0xaa)	/* not a smc superio chip */
+		return NULL;
+
+	outb(reg, cfg_base);
+
+	xdevid=inb(cfg_base+1);
+
+	/* Enter configuration */
+
+	outb(0x55, cfg_base);
+
+	if (smc_access(cfg_base,0x55))	/* send second key and check */
+		return NULL;
+
+	/* probe device ID */
+
+	if (smc_access(cfg_base,reg))
+		return NULL;
+
+	devid=inb(cfg_base+1);
+
+	if (devid==0)			/* typical value for unused port */
+		return NULL;
+
+	if (devid==0xff)		/* typical value for unused port */
+		return NULL;
+
+	/* probe revision ID */
+
+	if (smc_access(cfg_base,reg+1))
+		return NULL;
+
+	rev=inb(cfg_base+1);
+
+	if (rev>=128)			/* i think this will make no sense */
+		return NULL;
+
+	if (devid==xdevid)		/* protection against false positives */        
+		return NULL;
+
+	/* Check for expected device ID; are there others? */
+
+	while(chip->devid!=devid) {
+
+		chip++;
+
+		if (chip->name==NULL)
+			return NULL;
+	}
+	if (chip->rev>rev)
+		return NULL;
+
+	MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+	
+	if (chip->flags&NoIRDA)
+		MESSAGE("chipset does not support IRDA\n");
+
+	return chip;
+}
+
+/*
+ * Function smc_superio_flat (chip, base, type)
+ *
+ *    Try get configuration of a smc SuperIO chip with flat register model
+ *
+ */
+static int smc_superio_flat(smc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io;
+	unsigned short sir_io;
+	__u8 mode;
+	int ret = -ENODEV;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (smc_probe(cfg_base,0xD,chips,type)==NULL)
+		return ret;
+
+	outb(0x0c, cfg_base);
+
+	mode = inb(cfg_base+1);
+	mode = (mode & 0x38) >> 3;
+		
+	/* Value for IR port */
+	if (mode && mode < 4) {
+		/* SIR iobase */
+		outb(0x25, cfg_base);
+		sir_io = inb(cfg_base+1) << 2;
+
+	       	/* FIR iobase */
+		outb(0x2b, cfg_base);
+		fir_io = inb(cfg_base+1) << 3;
+
+		if (fir_io) {
+			if (ircc_open(fir_io, sir_io) == 0)
+				ret=0; 
+		}
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+/*
+ * Function smc_superio_paged (chip, base, type)
+ *
+ *    Try  get configuration of a smc SuperIO chip with paged register model
+ *
+ */
+static int smc_superio_paged(smc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io;
+	unsigned short sir_io;
+	int ret = -ENODEV;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (smc_probe(cfg_base,0x20,chips,type)==NULL)
+		return ret;
+	
+	/* Select logical device (UART2) */
+	outb(0x07, cfg_base);
+	outb(0x05, cfg_base + 1);
+		
+	/* SIR iobase */
+	outb(0x60, cfg_base);
+	sir_io  = inb(cfg_base + 1) << 8;
+	outb(0x61, cfg_base);
+	sir_io |= inb(cfg_base + 1);
+		
+	/* Read FIR base */
+	outb(0x62, cfg_base);
+	fir_io = inb(cfg_base + 1) << 8;
+	outb(0x63, cfg_base);
+	fir_io |= inb(cfg_base + 1);
+	outb(0x2b, cfg_base); // ???
+
+	if (fir_io) {
+		if (ircc_open(fir_io, sir_io) == 0)
+			ret=0; 
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+static int smc_superio_fdc(unsigned short cfg_base)
+{
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+
+	if (!smc_superio_flat(fdc_chips_flat,cfg_base,"FDC")||!smc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+		return 0;
+
+	return -1;
+}
+
+static int smc_superio_lpc(unsigned short cfg_base)
+{
+#if 0
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+#endif
+
+	if (!smc_superio_flat(lpc_chips_flat,cfg_base,"LPC")||!smc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+		return 0;
+
+	return -1;
+}
+
 /*
  * Function ircc_init ()
  *
@@ -120,37 +384,36 @@
  */
 int __init ircc_init(void)
 {
-	static int smcreg[] = { 0x3f0, 0x370 };
-	smc_chip_t *chip;
-	chipio_t info;
-	int ret = -ENODEV;
-	int i;
+	int ret=-ENODEV;
 
 	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	/* Probe for all the NSC chipsets we know about */
-	for (chip=chips; chip->name ; chip++) {
-		for (i=0; i<2; i++) {
-			info.cfg_base = smcreg[i];
-			
-			/* 
-			 * First we check if the user has supplied any
-                         * parameters which we should use instead of probed
-			 * values
-			 */
-			if (io[i] < 0x2000) {
-				info.fir_base = io[i];
-				info.sir_base = io2[i];
-			} else if (chip->probe(chip, &info) < 0)
-				continue;
-			if (check_region(info.fir_base, CHIP_IO_EXTENT) < 0)
-				continue;
-			if (check_region(info.sir_base, CHIP_IO_EXTENT) < 0)
-				continue;
-			if (ircc_open(i, info.fir_base, info.sir_base) == 0)
-				ret = 0; 
-		}
+	dev_count=0;
+
+	if ((ircc_fir>0)&&(ircc_sir>0)) {
+	        MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
+		MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
+
+		if (ircc_open(ircc_fir, ircc_sir) == 0)
+			return 0;
+
+		return -ENODEV;
 	}
+
+	/* Trys to open for all the SMC chipsets we know about */
+
+	IRDA_DEBUG(0, __FUNCTION__ 
+	" Try to open all known SMC chipsets\n");
+
+	if (smc_superio_fdc(0x3f0))
+		ret=0;
+	if (smc_superio_fdc(0x370))
+		ret=0;
+	if (smc_superio_lpc(0x2e))
+		ret=0;
+	if (smc_superio_lpc(0x4e))
+		ret=0;
+
 	return ret;
 }
 
@@ -177,24 +440,57 @@
 /*
  * Function ircc_open (iobase, irq)
  *
- *    Open driver instance
+ *    Try to open driver instance
  *
  */
-static int ircc_open(int i, unsigned int fir_base, unsigned int sir_base)
+static int ircc_open(unsigned int fir_base, unsigned int sir_base)
 {
 	struct ircc_cb *self;
         struct irport_cb *irport;
-	int config;
-	int ret;
+	unsigned char low, high, chip, config, dma, irq, version;
+
 
 	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	if ((config = ircc_probe(fir_base, sir_base)) == -1) {
+	if (check_region(fir_base, CHIP_IO_EXTENT) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
+			   fir_base);
+		return -ENODEV;
+	}
+#if POSSIBLE_USED_BY_SERIAL_DRIVER
+	if (check_region(sir_base, CHIP_IO_EXTENT) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get sir_base of 0x%03x\n",
+			   sir_base);
+		return -ENODEV;
+	}
+#endif
+
+	register_bank(fir_base, 3);
+
+	high    = inb(fir_base+IRCC_ID_HIGH);
+	low     = inb(fir_base+IRCC_ID_LOW);
+	chip    = inb(fir_base+IRCC_CHIP_ID);
+	version = inb(fir_base+IRCC_VERSION);
+	config  = inb(fir_base+IRCC_INTERFACE);
+
+	irq     = config >> 4 & 0x0f;
+	dma     = config & 0x0f;
+
+        if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { 
 	        IRDA_DEBUG(0, __FUNCTION__ 
 			   "(), addr 0x%04x - no device found!\n", fir_base);
-		return -1;
+		return -ENODEV;
 	}
-	
+	MESSAGE("SMC IrDA Controller found\n IrCC version %d.%d, "
+		"firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
+		chip & 0x0f, version, fir_base, sir_base, dma, irq);
+
+	if (dev_count>DIM(dev_self)) {
+	        IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), to many devices!\n");
+		return -ENOMEM;
+	}
+
 	/*
 	 *  Allocate new instance of the driver
 	 */
@@ -206,46 +502,74 @@
 	}
 	memset(self, 0, sizeof(struct ircc_cb));
 	spin_lock_init(&self->lock);
-   
-	/* Need to store self somewhere */
-	dev_self[i] = self;
 
-	irport = irport_open(i, sir_base, config >> 4 & 0x0f);
-	if (!irport)
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for receive buffer!\n",
+                      driver_name);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for transmit buffer!\n",
+                      driver_name);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	irport = irport_open(dev_count, sir_base, irq);
+	if (!irport) {
+		kfree(self->tx_buff.head);
+		kfree(self->rx_buff.head);
+		kfree(self);
 		return -ENODEV;
+	}
+
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+   
+	/* Need to store self somewhere */
+	dev_self[dev_count++] = self;
 
 	/* Steal the network device from irport */
 	self->netdev = irport->netdev;
 	self->irport = irport;
+
 	irport->priv = self;
 
 	/* Initialize IO */
 	self->io.fir_base  = fir_base;
         self->io.sir_base  = sir_base; /* Used by irport */
-        self->io.irq       = config >> 4 & 0x0f;
+        self->io.fir_ext   = CHIP_IO_EXTENT;
+        self->io.sir_ext   = 8;       /* Used by irport */
+
 	if (ircc_irq < 255) {
-	        MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
-			driver_name, self->io.irq, ircc_irq);
+		if (ircc_irq!=irq)
+			MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
+				driver_name, self->io.irq, ircc_irq);
 		self->io.irq = ircc_irq;
 	}
-        self->io.fir_ext   = CHIP_IO_EXTENT;
-        self->io.sir_ext   = 8;       /* Used by irport */
-        self->io.dma       = config & 0x0f;
+	else
+		self->io.irq = irq;
 	if (ircc_dma < 255) {
-	        MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
-			driver_name, self->io.dma, ircc_dma);
+		if (ircc_dma!=dma)
+			MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
+				driver_name, self->io.dma, ircc_dma);
 		self->io.dma = ircc_dma;
 	}
+	else
+		self->io.dma = dma;
 
-	/* Lock the port that we need */
-	ret = check_region(self->io.fir_base, self->io.fir_ext);
-	if (ret < 0) { 
-		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
-			   self->io.fir_base);
-                kfree(self);
-		return -ENODEV;
-	}
-	request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+	request_region(fir_base, CHIP_IO_EXTENT, driver_name);
 
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&irport->qos);
@@ -260,23 +584,6 @@
 
 	irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 	
-	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	self->rx_buff.truesize = 4000; 
-	self->tx_buff.truesize = 4000;
-
-	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-					      GFP_KERNEL|GFP_DMA);
-	if (self->rx_buff.head == NULL)
-		return -ENOMEM;
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	
-	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-					      GFP_KERNEL|GFP_DMA);
-	if (self->tx_buff.head == NULL) {
-		kfree(self->rx_buff.head);
-		return -ENOMEM;
-	}
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
@@ -295,6 +602,10 @@
         if (self->pmdev)
                 self->pmdev->data = self;
 
+	/* Power on device */
+
+	outb(0x00, fir_base+IRCC_MASTER);
+
 	return 0;
 }
 
@@ -347,146 +658,6 @@
 #endif /* MODULE */
 
 /*
- * Function ircc_probe_69 (chip, info)
- *
- *    Probes for the SMC FDC37C669 and FDC37N869
- *
- */
-static int ircc_probe_69(smc_chip_t *chip, chipio_t *info)
-{
-	int cfg_base = info->cfg_base;
-	__u8 devid, mode;
-	int ret = -ENODEV;
-	int fir_io;
-	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Enter configuration */
-	outb(chip->entr1, cfg_base);
-	outb(chip->entr2, cfg_base);
-	
-	outb(chip->cid_index, cfg_base);
-	devid = inb(cfg_base+1);
-	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
-	
-	/* Check for expected device ID; are there others? */
-	if (devid == chip->cid_value) {
-		outb(0x0c, cfg_base);
-		mode = inb(cfg_base+1);
-		mode = (mode & 0x38) >> 3;
-		
-		/* Value for IR port */
-		if (mode && mode < 4) {
-			/* SIR iobase */
-			outb(0x25, cfg_base);
-			info->sir_base = inb(cfg_base+1) << 2;
-
-		       	/* FIR iobase */
-			outb(0x2b, cfg_base);
-			fir_io = inb(cfg_base+1) << 3;
-			if (fir_io) {
-				ret = 0;
-				info->fir_base = fir_io;
-			}
-		}
-	}
-	
-	/* Exit configuration */
-	outb(0xaa, cfg_base);
-
-	return ret;
-}
-
-/*
- * Function ircc_probe_58 (chip, info)
- *
- *    Probes for the SMC FDC37N958
- *
- */
-static int ircc_probe_58(smc_chip_t *chip, chipio_t *info)
-{
-	int cfg_base = info->cfg_base;
-	__u8 devid;
-	int ret = -ENODEV;
-	int fir_io;
-	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Enter configuration */
-	outb(chip->entr1, cfg_base);
-	outb(chip->entr2, cfg_base);
-	
-	outb(chip->cid_index, cfg_base);
-	devid = inb(cfg_base+1);
-	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
-	
-	/* Check for expected device ID; are there others? */
-	if (devid == chip->cid_value) {
-		/* Select logical device (UART2) */
-		outb(0x07, cfg_base);
-		outb(0x05, cfg_base + 1);
-		
-		/* SIR iobase */
-		outb(0x60, cfg_base);
-		info->sir_base = inb(cfg_base + 1) << 8;
-		outb(0x61, cfg_base);
-		info->sir_base |= inb(cfg_base + 1);
-		
-		/* Read FIR base */
-		outb(0x62, cfg_base);
-		fir_io = inb(cfg_base + 1) << 8;
-		outb(0x63, cfg_base);
-		fir_io |= inb(cfg_base + 1);
-		outb(0x2b, cfg_base);
-		if (fir_io) {
-			ret = 0;
-			info->fir_base = fir_io;
-		}
-	}
-	
-	/* Exit configuration */
-	outb(0xaa, cfg_base);
-
-	return ret;
-}
-
-/*
- * Function ircc_probe (iobase, board_addr, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
-static int ircc_probe(int fir_base, int sir_base) 
-{
-	int low, high, chip, config, dma, irq;
-	int iobase = fir_base;
-	int version = 1;
-
-	IRDA_DEBUG(0, __FUNCTION__ "\n");
-
-	register_bank(iobase, 3);
-	high    = inb(iobase+IRCC_ID_HIGH);
-	low     = inb(iobase+IRCC_ID_LOW);
-	chip    = inb(iobase+IRCC_CHIP_ID);
-	version = inb(iobase+IRCC_VERSION);
-	config  = inb(iobase+IRCC_INTERFACE);
-	irq     = config >> 4 & 0x0f;
-	dma     = config & 0x0f;
-
-        if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) { 
-                MESSAGE("SMC IrDA Controller found; IrCC version %d.%d, "
-			"port 0x%03x, dma=%d, irq=%d\n",
-			chip & 0x0f, version, iobase, dma, irq);
-	} else
-		return -ENODEV;
-
-	/* Power on device */
-	outb(0x00, iobase+IRCC_MASTER);
-
-	return config;
-}
-
-/*
  * Function ircc_change_speed (self, baud)
  *
  *    Change the speed of the device
@@ -1055,6 +1226,10 @@
 MODULE_PARM_DESC(ircc_dma, "DMA channel");
 MODULE_PARM(ircc_irq, "1i");
 MODULE_PARM_DESC(ircc_irq, "IRQ line");
+MODULE_PARM(ircc_fir, "1-4i");
+MODULE_PARM_DESC(ircc_fir, "FIR Base Adress");
+MODULE_PARM(ircc_sir, "1-4i");
+MODULE_PARM_DESC(ircc_sir, "SIR Base Adress");
 
 int init_module(void)
 {
diff -u --recursive --new-file linux-2.4.6-ac5/include/net/irda/smc-ircc.h.save linux-2.4.6-ac5/include/net/irda/smc-ircc.h
--- linux-2.4.6-ac5/include/net/irda/smc-ircc.h.save	Fri Jul 20 10:59:58 2001
+++ linux-2.4.6-ac5/include/net/irda/smc-ircc.h	Fri Jul 20 11:00:25 2001
@@ -154,16 +154,6 @@
 #define IRCC_1152                  0x80
 #define IRCC_CRC                   0x40
 
-struct smc_chip {
-	char *name;
-	unsigned char entr1;
-	unsigned char entr2;
-	unsigned char cid_index;
-	unsigned char cid_value;
-	int (*probe)(struct smc_chip *chip, chipio_t *info);
-};
-typedef struct smc_chip smc_chip_t;
-
 /* Private data for each instance */
 struct ircc_cb {
 	struct net_device *netdev;     /* Yes! we are some kind of netdevice */

^ permalink raw reply	[flat|nested] 4+ messages in thread

* irda smc patch... oops
       [not found] <Pine.SGI.4.10.10102071945350.926064-100000@Sky.inp.nsk.su>
  2001-02-08 11:44 ` patch for 2.4.1 disable printk and panic messages Stefani Seibold
  2001-07-20 10:21 ` irda smc patch Stefani Seibold
@ 2001-07-20 11:36 ` Stefani Seibold
       [not found]   ` <20010720145856.C2798@intern.kubla.de>
  2 siblings, 1 reply; 4+ messages in thread
From: Stefani Seibold @ 2001-07-20 11:36 UTC (permalink / raw)
  To: torvalds, alan; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 21732 bytes --]

Hi folks,

sorry about the previous patch, it was my test code, which will not work....

This patch make the linux irda smc-ircc driver working with the newer LPC47xxx smc chips, 
mostly found notebook computers.

I added also support for all smc super i/o chips, which i have found a reference manual
on the smc webpage:

FDC37C44
FDC37C665GT
FDC37C669
FDC37C669
FDC37C78
FDC37N769
FDC37N869
FDC37B72X
FDC37B77X
FDC37B78X
FDC37B80X
FDC37C67X
FDC37C93X
FDC37C93XAPM
FDC37C93XFR
FDC37M707
FDC37M81X
FDC37N958FR
FDC37N972
LPC47N227
LPC47N267
LPC47B27X
LPC47B37X
LPC47M10X
LPC47M120
LPC47M13X
LPC47M14X
LPC47N252
LPC47S42X

It was tested currently on my INSPIRON 8000, so feedbacks are welcome

I hope this patch will go in to the 2.4 tree...

Greetings

diff -u --recursive --new-file linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c.save linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c
--- linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c.save	Fri Jul 20 10:32:05 2001
+++ linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c	Fri Jul 20 11:52:27 2001
@@ -8,7 +8,10 @@
  * Created at:    
  * Modified at:   Tue Feb 22 10:05:06 2000
  * Modified by:   Dag Brattli <dag@brattli.net>
+ * Modified at:   Tue Jun 26 2001
+ * Modified by:   Stefani Seibold <stefani@seibold.net>
  * 
+ *     Copyright (c) 2001      Stefani Seibold
  *     Copyright (c) 1999-2000 Dag Brattli
  *     Copyright (c) 1998-1999 Thomas Davis, 
  *     All Rights Reserved.
@@ -28,8 +31,9 @@
  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
  *     MA 02111-1307 USA
  *
- *     SIO's: SMC FDC37N869, FDC37C669, FDC37N958
- *     Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
+ *     SIO's: all SIO documentet by SMC (June, 2001)
+ *     Applicable Models :	Fujitsu Lifebook 635t, Sony PCG-505TX,
+ *     				Dell Inspiron 8000
  *
  ********************************************************************/
 
@@ -60,23 +64,27 @@
 #include <net/irda/smc-ircc.h>
 #include <net/irda/irport.h>
 
+struct smc_chip {
+	char *name;
+	u16 flags;
+	u8 devid;
+	u8 rev;
+};
+typedef struct smc_chip smc_chip_t;
+
 static char *driver_name = "smc-ircc";
 
-#define CHIP_IO_EXTENT 8
+#define	DIM(x)	(sizeof(x)/(sizeof(*(x))))
 
-static unsigned int io[]  = { ~0, ~0 }; 
-static unsigned int io2[] = { 0, 0 };
+#define CHIP_IO_EXTENT 8
 
 static struct ircc_cb *dev_self[] = { NULL, NULL};
 
 /* Some prototypes */
-static int  ircc_open(int i, unsigned int iobase, unsigned int board_addr);
+static int  ircc_open(unsigned int iobase, unsigned int board_addr);
 #ifdef MODULE
 static int  ircc_close(struct ircc_cb *self);
 #endif /* MODULE */
-static int  ircc_probe(int iobase, int board_addr);
-static int  ircc_probe_58(smc_chip_t *chip, chipio_t *info);
-static int  ircc_probe_69(smc_chip_t *chip, chipio_t *info);
 static int  ircc_dma_receive(struct ircc_cb *self, int iobase); 
 static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
 static int  ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -91,20 +99,73 @@
 static int  ircc_net_close(struct net_device *dev);
 static int  ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 
-/* These are the currently known SMC chipsets */
-static smc_chip_t chips[] =
+#define	KEY55_1	0	// SuperIO Configuration mode with Key <0x55>
+#define	KEY55_2	1	// SuperIO Configuration mode with Key <0x55,0x55>
+#define	NoIRDA	2	// SuperIO Chip has no IRDA Port
+#define	SIR	0	// SuperIO Chip has only slow IRDA
+#define	FIR	4	// SuperIO Chip has fast IRDA
+#define	SERx4	8	// SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud
+
+/* These are the currently known SMC SuperIO chipsets */
+static smc_chip_t fdc_chips_flat[]=
+{
+	// Base address 0x3f0 or 0x370
+	{ "37C44",	KEY55_1|NoIRDA,		0x00, 0x00 }, /* This chip can not detected */
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x65, 0x01 },
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x66, 0x01 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x03, 0x02 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x04, 0x02 }, /* ID? */
+	{ "37C78",	KEY55_2|NoIRDA,		0x78, 0x00 },
+	{ "37N769",	KEY55_1|FIR|SERx4,	0x28, 0x00 },
+	{ "37N869",	KEY55_1|FIR|SERx4,	0x29, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t fdc_chips_paged[]=
+{
+	{ "37B72X",	KEY55_1|SIR|SERx4,	0x4c, 0x00 },
+	{ "37B77X",	KEY55_1|SIR|SERx4,	0x43, 0x00 },
+	{ "37B78X",	KEY55_1|SIR|SERx4,	0x44, 0x00 },
+	{ "37B80X",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37C67X",	KEY55_1|FIR|SERx4,	0x40, 0x00 },
+	{ "37C93X",	KEY55_2|SIR|SERx4,	0x02, 0x01 },
+	{ "37C93XAPM",	KEY55_1|SIR|SERx4,	0x30, 0x01 },
+	{ "37C93XFR",	KEY55_2|FIR|SERx4,	0x03, 0x01 },
+	{ "37M707",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37M81X",	KEY55_1|SIR|SERx4,	0x4d, 0x00 },
+	{ "37N958FR",	KEY55_1|FIR|SERx4,	0x09, 0x04 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0a, 0x00 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0b, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t lpc_chips_flat[]=
 {
-	{ "FDC37C669", 0x55, 0x55, 0x0d, 0x04, ircc_probe_69 },
-	{ "FDC37N769", 0x55, 0x55, 0x0d, 0x28, ircc_probe_69 },
-	{ "FDC37N869", 0x55, 0x00, 0x0d, 0x29, ircc_probe_69 },
-	{ "FDC37N958", 0x55, 0x55, 0x20, 0x09, ircc_probe_58 },
-	{ "FDC37N971", 0x55, 0x55, 0x20, 0x0a, ircc_probe_58 },
-	{ "FDC37N972", 0x55, 0x55, 0x20, 0x0b, ircc_probe_58 },
+	// Base address 0x2E or 0x4E
+	{ "47N227",	KEY55_1|FIR|SERx4,	0x5a, 0x00 },
+	{ "47N267",	KEY55_1|FIR|SERx4,	0x5e, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t lpc_chips_paged[]=
+{
+	{ "47B27X",	KEY55_1|SIR|SERx4,	0x51, 0x00 },
+	{ "47B37X",	KEY55_1|SIR|SERx4,	0x52, 0x00 },
+	{ "47M10X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M120",	KEY55_1|NoIRDA|SERx4,	0x5c, 0x00 },
+	{ "47M13X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M14X",	KEY55_1|SIR|SERx4,	0x5f, 0x00 },
+	{ "47N252",	KEY55_1|FIR|SERx4,	0x0e, 0x00 },
+	{ "47S42X",	KEY55_1|SIR|SERx4,	0x57, 0x00 },
 	{ NULL }
 };
 
 static int ircc_irq=255;
 static int ircc_dma=255;
+static int ircc_fir=0;
+static int ircc_sir=0;
+
+static unsigned short	dev_count=0;
 
 static inline void register_bank(int iobase, int bank)
 {
@@ -112,6 +173,209 @@
                iobase+IRCC_MASTER);
 }
 
+static int smc_access(unsigned short cfg_base,unsigned char reg)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	outb(reg, cfg_base);
+
+	if (inb(cfg_base)!=reg)
+		return -1;
+
+	return 0;
+}
+
+static smc_chip_t * smc_probe(unsigned short cfg_base,u8 reg,smc_chip_t *chip,char *type)
+{
+	u8	devid,xdevid; 
+	u8	rev; 
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	/* Leave configuration */
+
+	outb(0xaa, cfg_base);
+
+	if (inb(cfg_base)==0xaa)	/* not a smc superio chip */
+		return NULL;
+
+	outb(reg, cfg_base);
+
+	xdevid=inb(cfg_base+1);
+
+	/* Enter configuration */
+
+	outb(0x55, cfg_base);
+
+	if (smc_access(cfg_base,0x55))	/* send second key and check */
+		return NULL;
+
+	/* probe device ID */
+
+	if (smc_access(cfg_base,reg))
+		return NULL;
+
+	devid=inb(cfg_base+1);
+
+	if (devid==0)			/* typical value for unused port */
+		return NULL;
+
+	if (devid==0xff)		/* typical value for unused port */
+		return NULL;
+
+	/* probe revision ID */
+
+	if (smc_access(cfg_base,reg+1))
+		return NULL;
+
+	rev=inb(cfg_base+1);
+
+	if (rev>=128)			/* i think this will make no sense */
+		return NULL;
+
+	if (devid==xdevid)		/* protection against false positives */        
+		return NULL;
+
+	/* Check for expected device ID; are there others? */
+
+	while(chip->devid!=devid) {
+
+		chip++;
+
+		if (chip->name==NULL)
+			return NULL;
+	}
+	if (chip->rev>rev)
+		return NULL;
+
+	MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+	
+	if (chip->flags&NoIRDA)
+		MESSAGE("chipset does not support IRDA\n");
+
+	return chip;
+}
+
+/*
+ * Function smc_superio_flat (chip, base, type)
+ *
+ *    Try get configuration of a smc SuperIO chip with flat register model
+ *
+ */
+static int smc_superio_flat(smc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io;
+	unsigned short sir_io;
+	__u8 mode;
+	int ret = -ENODEV;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (smc_probe(cfg_base,0xD,chips,type)==NULL)
+		return ret;
+
+	outb(0x0c, cfg_base);
+
+	mode = inb(cfg_base+1);
+	mode = (mode & 0x38) >> 3;
+		
+	/* Value for IR port */
+	if (mode && mode < 4) {
+		/* SIR iobase */
+		outb(0x25, cfg_base);
+		sir_io = inb(cfg_base+1) << 2;
+
+	       	/* FIR iobase */
+		outb(0x2b, cfg_base);
+		fir_io = inb(cfg_base+1) << 3;
+
+		if (fir_io) {
+			if (ircc_open(fir_io, sir_io) == 0)
+				ret=0; 
+		}
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+/*
+ * Function smc_superio_paged (chip, base, type)
+ *
+ *    Try  get configuration of a smc SuperIO chip with paged register model
+ *
+ */
+static int smc_superio_paged(smc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io;
+	unsigned short sir_io;
+	int ret = -ENODEV;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (smc_probe(cfg_base,0x20,chips,type)==NULL)
+		return ret;
+	
+	/* Select logical device (UART2) */
+	outb(0x07, cfg_base);
+	outb(0x05, cfg_base + 1);
+		
+	/* SIR iobase */
+	outb(0x60, cfg_base);
+	sir_io  = inb(cfg_base + 1) << 8;
+	outb(0x61, cfg_base);
+	sir_io |= inb(cfg_base + 1);
+		
+	/* Read FIR base */
+	outb(0x62, cfg_base);
+	fir_io = inb(cfg_base + 1) << 8;
+	outb(0x63, cfg_base);
+	fir_io |= inb(cfg_base + 1);
+	outb(0x2b, cfg_base); // ???
+
+	if (fir_io) {
+		if (ircc_open(fir_io, sir_io) == 0)
+			ret=0; 
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+static int smc_superio_fdc(unsigned short cfg_base)
+{
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+
+	if (!smc_superio_flat(fdc_chips_flat,cfg_base,"FDC")||!smc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+		return 0;
+
+	return -1;
+}
+
+static int smc_superio_lpc(unsigned short cfg_base)
+{
+#if 0
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+#endif
+
+	if (!smc_superio_flat(lpc_chips_flat,cfg_base,"LPC")||!smc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+		return 0;
+
+	return -1;
+}
+
 /*
  * Function ircc_init ()
  *
@@ -120,37 +384,36 @@
  */
 int __init ircc_init(void)
 {
-	static int smcreg[] = { 0x3f0, 0x370 };
-	smc_chip_t *chip;
-	chipio_t info;
-	int ret = -ENODEV;
-	int i;
+	int ret=-ENODEV;
 
 	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	/* Probe for all the NSC chipsets we know about */
-	for (chip=chips; chip->name ; chip++) {
-		for (i=0; i<2; i++) {
-			info.cfg_base = smcreg[i];
-			
-			/* 
-			 * First we check if the user has supplied any
-                         * parameters which we should use instead of probed
-			 * values
-			 */
-			if (io[i] < 0x2000) {
-				info.fir_base = io[i];
-				info.sir_base = io2[i];
-			} else if (chip->probe(chip, &info) < 0)
-				continue;
-			if (check_region(info.fir_base, CHIP_IO_EXTENT) < 0)
-				continue;
-			if (check_region(info.sir_base, CHIP_IO_EXTENT) < 0)
-				continue;
-			if (ircc_open(i, info.fir_base, info.sir_base) == 0)
-				ret = 0; 
-		}
+	dev_count=0;
+
+	if ((ircc_fir>0)&&(ircc_sir>0)) {
+	        MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
+		MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
+
+		if (ircc_open(ircc_fir, ircc_sir) == 0)
+			return 0;
+
+		return -ENODEV;
 	}
+
+	/* Trys to open for all the SMC chipsets we know about */
+
+	IRDA_DEBUG(0, __FUNCTION__ 
+	" Try to open all known SMC chipsets\n");
+
+	if (!smc_superio_fdc(0x3f0))
+		ret=0;
+	if (!smc_superio_fdc(0x370))
+		ret=0;
+	if (!smc_superio_lpc(0x2e))
+		ret=0;
+	if (!smc_superio_lpc(0x4e))
+		ret=0;
+
 	return ret;
 }
 
@@ -177,24 +440,57 @@
 /*
  * Function ircc_open (iobase, irq)
  *
- *    Open driver instance
+ *    Try to open driver instance
  *
  */
-static int ircc_open(int i, unsigned int fir_base, unsigned int sir_base)
+static int ircc_open(unsigned int fir_base, unsigned int sir_base)
 {
 	struct ircc_cb *self;
         struct irport_cb *irport;
-	int config;
-	int ret;
+	unsigned char low, high, chip, config, dma, irq, version;
+
 
 	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	if ((config = ircc_probe(fir_base, sir_base)) == -1) {
+	if (check_region(fir_base, CHIP_IO_EXTENT) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
+			   fir_base);
+		return -ENODEV;
+	}
+#if POSSIBLE_USED_BY_SERIAL_DRIVER
+	if (check_region(sir_base, CHIP_IO_EXTENT) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get sir_base of 0x%03x\n",
+			   sir_base);
+		return -ENODEV;
+	}
+#endif
+
+	register_bank(fir_base, 3);
+
+	high    = inb(fir_base+IRCC_ID_HIGH);
+	low     = inb(fir_base+IRCC_ID_LOW);
+	chip    = inb(fir_base+IRCC_CHIP_ID);
+	version = inb(fir_base+IRCC_VERSION);
+	config  = inb(fir_base+IRCC_INTERFACE);
+
+	irq     = config >> 4 & 0x0f;
+	dma     = config & 0x0f;
+
+        if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { 
 	        IRDA_DEBUG(0, __FUNCTION__ 
 			   "(), addr 0x%04x - no device found!\n", fir_base);
-		return -1;
+		return -ENODEV;
 	}
-	
+	MESSAGE("SMC IrDA Controller found\n IrCC version %d.%d, "
+		"firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
+		chip & 0x0f, version, fir_base, sir_base, dma, irq);
+
+	if (dev_count>DIM(dev_self)) {
+	        IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), to many devices!\n");
+		return -ENOMEM;
+	}
+
 	/*
 	 *  Allocate new instance of the driver
 	 */
@@ -206,46 +502,74 @@
 	}
 	memset(self, 0, sizeof(struct ircc_cb));
 	spin_lock_init(&self->lock);
-   
-	/* Need to store self somewhere */
-	dev_self[i] = self;
 
-	irport = irport_open(i, sir_base, config >> 4 & 0x0f);
-	if (!irport)
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for receive buffer!\n",
+                      driver_name);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for transmit buffer!\n",
+                      driver_name);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	irport = irport_open(dev_count, sir_base, irq);
+	if (!irport) {
+		kfree(self->tx_buff.head);
+		kfree(self->rx_buff.head);
+		kfree(self);
 		return -ENODEV;
+	}
+
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+   
+	/* Need to store self somewhere */
+	dev_self[dev_count++] = self;
 
 	/* Steal the network device from irport */
 	self->netdev = irport->netdev;
 	self->irport = irport;
+
 	irport->priv = self;
 
 	/* Initialize IO */
 	self->io.fir_base  = fir_base;
         self->io.sir_base  = sir_base; /* Used by irport */
-        self->io.irq       = config >> 4 & 0x0f;
+        self->io.fir_ext   = CHIP_IO_EXTENT;
+        self->io.sir_ext   = 8;       /* Used by irport */
+
 	if (ircc_irq < 255) {
-	        MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
-			driver_name, self->io.irq, ircc_irq);
+		if (ircc_irq!=irq)
+			MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
+				driver_name, self->io.irq, ircc_irq);
 		self->io.irq = ircc_irq;
 	}
-        self->io.fir_ext   = CHIP_IO_EXTENT;
-        self->io.sir_ext   = 8;       /* Used by irport */
-        self->io.dma       = config & 0x0f;
+	else
+		self->io.irq = irq;
 	if (ircc_dma < 255) {
-	        MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
-			driver_name, self->io.dma, ircc_dma);
+		if (ircc_dma!=dma)
+			MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
+				driver_name, self->io.dma, ircc_dma);
 		self->io.dma = ircc_dma;
 	}
+	else
+		self->io.dma = dma;
 
-	/* Lock the port that we need */
-	ret = check_region(self->io.fir_base, self->io.fir_ext);
-	if (ret < 0) { 
-		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
-			   self->io.fir_base);
-                kfree(self);
-		return -ENODEV;
-	}
-	request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+	request_region(fir_base, CHIP_IO_EXTENT, driver_name);
 
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&irport->qos);
@@ -260,23 +584,6 @@
 
 	irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 	
-	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	self->rx_buff.truesize = 4000; 
-	self->tx_buff.truesize = 4000;
-
-	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-					      GFP_KERNEL|GFP_DMA);
-	if (self->rx_buff.head == NULL)
-		return -ENOMEM;
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	
-	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-					      GFP_KERNEL|GFP_DMA);
-	if (self->tx_buff.head == NULL) {
-		kfree(self->rx_buff.head);
-		return -ENOMEM;
-	}
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
@@ -295,6 +602,10 @@
         if (self->pmdev)
                 self->pmdev->data = self;
 
+	/* Power on device */
+
+	outb(0x00, fir_base+IRCC_MASTER);
+
 	return 0;
 }
 
@@ -347,146 +658,6 @@
 #endif /* MODULE */
 
 /*
- * Function ircc_probe_69 (chip, info)
- *
- *    Probes for the SMC FDC37C669 and FDC37N869
- *
- */
-static int ircc_probe_69(smc_chip_t *chip, chipio_t *info)
-{
-	int cfg_base = info->cfg_base;
-	__u8 devid, mode;
-	int ret = -ENODEV;
-	int fir_io;
-	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Enter configuration */
-	outb(chip->entr1, cfg_base);
-	outb(chip->entr2, cfg_base);
-	
-	outb(chip->cid_index, cfg_base);
-	devid = inb(cfg_base+1);
-	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
-	
-	/* Check for expected device ID; are there others? */
-	if (devid == chip->cid_value) {
-		outb(0x0c, cfg_base);
-		mode = inb(cfg_base+1);
-		mode = (mode & 0x38) >> 3;
-		
-		/* Value for IR port */
-		if (mode && mode < 4) {
-			/* SIR iobase */
-			outb(0x25, cfg_base);
-			info->sir_base = inb(cfg_base+1) << 2;
-
-		       	/* FIR iobase */
-			outb(0x2b, cfg_base);
-			fir_io = inb(cfg_base+1) << 3;
-			if (fir_io) {
-				ret = 0;
-				info->fir_base = fir_io;
-			}
-		}
-	}
-	
-	/* Exit configuration */
-	outb(0xaa, cfg_base);
-
-	return ret;
-}
-
-/*
- * Function ircc_probe_58 (chip, info)
- *
- *    Probes for the SMC FDC37N958
- *
- */
-static int ircc_probe_58(smc_chip_t *chip, chipio_t *info)
-{
-	int cfg_base = info->cfg_base;
-	__u8 devid;
-	int ret = -ENODEV;
-	int fir_io;
-	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Enter configuration */
-	outb(chip->entr1, cfg_base);
-	outb(chip->entr2, cfg_base);
-	
-	outb(chip->cid_index, cfg_base);
-	devid = inb(cfg_base+1);
-	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
-	
-	/* Check for expected device ID; are there others? */
-	if (devid == chip->cid_value) {
-		/* Select logical device (UART2) */
-		outb(0x07, cfg_base);
-		outb(0x05, cfg_base + 1);
-		
-		/* SIR iobase */
-		outb(0x60, cfg_base);
-		info->sir_base = inb(cfg_base + 1) << 8;
-		outb(0x61, cfg_base);
-		info->sir_base |= inb(cfg_base + 1);
-		
-		/* Read FIR base */
-		outb(0x62, cfg_base);
-		fir_io = inb(cfg_base + 1) << 8;
-		outb(0x63, cfg_base);
-		fir_io |= inb(cfg_base + 1);
-		outb(0x2b, cfg_base);
-		if (fir_io) {
-			ret = 0;
-			info->fir_base = fir_io;
-		}
-	}
-	
-	/* Exit configuration */
-	outb(0xaa, cfg_base);
-
-	return ret;
-}
-
-/*
- * Function ircc_probe (iobase, board_addr, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
-static int ircc_probe(int fir_base, int sir_base) 
-{
-	int low, high, chip, config, dma, irq;
-	int iobase = fir_base;
-	int version = 1;
-
-	IRDA_DEBUG(0, __FUNCTION__ "\n");
-
-	register_bank(iobase, 3);
-	high    = inb(iobase+IRCC_ID_HIGH);
-	low     = inb(iobase+IRCC_ID_LOW);
-	chip    = inb(iobase+IRCC_CHIP_ID);
-	version = inb(iobase+IRCC_VERSION);
-	config  = inb(iobase+IRCC_INTERFACE);
-	irq     = config >> 4 & 0x0f;
-	dma     = config & 0x0f;
-
-        if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) { 
-                MESSAGE("SMC IrDA Controller found; IrCC version %d.%d, "
-			"port 0x%03x, dma=%d, irq=%d\n",
-			chip & 0x0f, version, iobase, dma, irq);
-	} else
-		return -ENODEV;
-
-	/* Power on device */
-	outb(0x00, iobase+IRCC_MASTER);
-
-	return config;
-}
-
-/*
  * Function ircc_change_speed (self, baud)
  *
  *    Change the speed of the device
@@ -1055,6 +1226,10 @@
 MODULE_PARM_DESC(ircc_dma, "DMA channel");
 MODULE_PARM(ircc_irq, "1i");
 MODULE_PARM_DESC(ircc_irq, "IRQ line");
+MODULE_PARM(ircc_fir, "1-4i");
+MODULE_PARM_DESC(ircc_fir, "FIR Base Adress");
+MODULE_PARM(ircc_sir, "1-4i");
+MODULE_PARM_DESC(ircc_sir, "SIR Base Adress");
 
 int init_module(void)
 {
diff -u --recursive --new-file linux-2.4.6-ac5/include/net/irda/smc-ircc.h.save linux-2.4.6-ac5/include/net/irda/smc-ircc.h
--- linux-2.4.6-ac5/include/net/irda/smc-ircc.h.save	Fri Jul 20 10:59:58 2001
+++ linux-2.4.6-ac5/include/net/irda/smc-ircc.h	Fri Jul 20 11:00:25 2001
@@ -154,16 +154,6 @@
 #define IRCC_1152                  0x80
 #define IRCC_CRC                   0x40
 
-struct smc_chip {
-	char *name;
-	unsigned char entr1;
-	unsigned char entr2;
-	unsigned char cid_index;
-	unsigned char cid_value;
-	int (*probe)(struct smc_chip *chip, chipio_t *info);
-};
-typedef struct smc_chip smc_chip_t;
-
 /* Private data for each instance */
 struct ircc_cb {
 	struct net_device *netdev;     /* Yes! we are some kind of netdevice */



[-- Attachment #2: smc-ircc irda superio patch --]
[-- Type: text/plain, Size: 20978 bytes --]

diff -u --recursive --new-file linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c.save linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c
--- linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c.save	Fri Jul 20 10:32:05 2001
+++ linux-2.4.6-ac5/drivers/net/irda/smc-ircc.c	Fri Jul 20 11:52:27 2001
@@ -8,7 +8,10 @@
  * Created at:    
  * Modified at:   Tue Feb 22 10:05:06 2000
  * Modified by:   Dag Brattli <dag@brattli.net>
+ * Modified at:   Tue Jun 26 2001
+ * Modified by:   Stefani Seibold <stefani@seibold.net>
  * 
+ *     Copyright (c) 2001      Stefani Seibold
  *     Copyright (c) 1999-2000 Dag Brattli
  *     Copyright (c) 1998-1999 Thomas Davis, 
  *     All Rights Reserved.
@@ -28,8 +31,9 @@
  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
  *     MA 02111-1307 USA
  *
- *     SIO's: SMC FDC37N869, FDC37C669, FDC37N958
- *     Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
+ *     SIO's: all SIO documentet by SMC (June, 2001)
+ *     Applicable Models :	Fujitsu Lifebook 635t, Sony PCG-505TX,
+ *     				Dell Inspiron 8000
  *
  ********************************************************************/
 
@@ -60,23 +64,27 @@
 #include <net/irda/smc-ircc.h>
 #include <net/irda/irport.h>
 
+struct smc_chip {
+	char *name;
+	u16 flags;
+	u8 devid;
+	u8 rev;
+};
+typedef struct smc_chip smc_chip_t;
+
 static char *driver_name = "smc-ircc";
 
-#define CHIP_IO_EXTENT 8
+#define	DIM(x)	(sizeof(x)/(sizeof(*(x))))
 
-static unsigned int io[]  = { ~0, ~0 }; 
-static unsigned int io2[] = { 0, 0 };
+#define CHIP_IO_EXTENT 8
 
 static struct ircc_cb *dev_self[] = { NULL, NULL};
 
 /* Some prototypes */
-static int  ircc_open(int i, unsigned int iobase, unsigned int board_addr);
+static int  ircc_open(unsigned int iobase, unsigned int board_addr);
 #ifdef MODULE
 static int  ircc_close(struct ircc_cb *self);
 #endif /* MODULE */
-static int  ircc_probe(int iobase, int board_addr);
-static int  ircc_probe_58(smc_chip_t *chip, chipio_t *info);
-static int  ircc_probe_69(smc_chip_t *chip, chipio_t *info);
 static int  ircc_dma_receive(struct ircc_cb *self, int iobase); 
 static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
 static int  ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -91,20 +99,73 @@
 static int  ircc_net_close(struct net_device *dev);
 static int  ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 
-/* These are the currently known SMC chipsets */
-static smc_chip_t chips[] =
+#define	KEY55_1	0	// SuperIO Configuration mode with Key <0x55>
+#define	KEY55_2	1	// SuperIO Configuration mode with Key <0x55,0x55>
+#define	NoIRDA	2	// SuperIO Chip has no IRDA Port
+#define	SIR	0	// SuperIO Chip has only slow IRDA
+#define	FIR	4	// SuperIO Chip has fast IRDA
+#define	SERx4	8	// SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud
+
+/* These are the currently known SMC SuperIO chipsets */
+static smc_chip_t fdc_chips_flat[]=
+{
+	// Base address 0x3f0 or 0x370
+	{ "37C44",	KEY55_1|NoIRDA,		0x00, 0x00 }, /* This chip can not detected */
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x65, 0x01 },
+	{ "37C665GT",	KEY55_2|NoIRDA,		0x66, 0x01 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x03, 0x02 },
+	{ "37C669",	KEY55_2|SIR|SERx4,	0x04, 0x02 }, /* ID? */
+	{ "37C78",	KEY55_2|NoIRDA,		0x78, 0x00 },
+	{ "37N769",	KEY55_1|FIR|SERx4,	0x28, 0x00 },
+	{ "37N869",	KEY55_1|FIR|SERx4,	0x29, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t fdc_chips_paged[]=
+{
+	{ "37B72X",	KEY55_1|SIR|SERx4,	0x4c, 0x00 },
+	{ "37B77X",	KEY55_1|SIR|SERx4,	0x43, 0x00 },
+	{ "37B78X",	KEY55_1|SIR|SERx4,	0x44, 0x00 },
+	{ "37B80X",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37C67X",	KEY55_1|FIR|SERx4,	0x40, 0x00 },
+	{ "37C93X",	KEY55_2|SIR|SERx4,	0x02, 0x01 },
+	{ "37C93XAPM",	KEY55_1|SIR|SERx4,	0x30, 0x01 },
+	{ "37C93XFR",	KEY55_2|FIR|SERx4,	0x03, 0x01 },
+	{ "37M707",	KEY55_1|SIR|SERx4,	0x42, 0x00 },
+	{ "37M81X",	KEY55_1|SIR|SERx4,	0x4d, 0x00 },
+	{ "37N958FR",	KEY55_1|FIR|SERx4,	0x09, 0x04 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0a, 0x00 },
+	{ "37N972",	KEY55_1|FIR|SERx4,	0x0b, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t lpc_chips_flat[]=
 {
-	{ "FDC37C669", 0x55, 0x55, 0x0d, 0x04, ircc_probe_69 },
-	{ "FDC37N769", 0x55, 0x55, 0x0d, 0x28, ircc_probe_69 },
-	{ "FDC37N869", 0x55, 0x00, 0x0d, 0x29, ircc_probe_69 },
-	{ "FDC37N958", 0x55, 0x55, 0x20, 0x09, ircc_probe_58 },
-	{ "FDC37N971", 0x55, 0x55, 0x20, 0x0a, ircc_probe_58 },
-	{ "FDC37N972", 0x55, 0x55, 0x20, 0x0b, ircc_probe_58 },
+	// Base address 0x2E or 0x4E
+	{ "47N227",	KEY55_1|FIR|SERx4,	0x5a, 0x00 },
+	{ "47N267",	KEY55_1|FIR|SERx4,	0x5e, 0x00 },
+	{ NULL }
+};
+
+static smc_chip_t lpc_chips_paged[]=
+{
+	{ "47B27X",	KEY55_1|SIR|SERx4,	0x51, 0x00 },
+	{ "47B37X",	KEY55_1|SIR|SERx4,	0x52, 0x00 },
+	{ "47M10X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M120",	KEY55_1|NoIRDA|SERx4,	0x5c, 0x00 },
+	{ "47M13X",	KEY55_1|SIR|SERx4,	0x59, 0x00 },
+	{ "47M14X",	KEY55_1|SIR|SERx4,	0x5f, 0x00 },
+	{ "47N252",	KEY55_1|FIR|SERx4,	0x0e, 0x00 },
+	{ "47S42X",	KEY55_1|SIR|SERx4,	0x57, 0x00 },
 	{ NULL }
 };
 
 static int ircc_irq=255;
 static int ircc_dma=255;
+static int ircc_fir=0;
+static int ircc_sir=0;
+
+static unsigned short	dev_count=0;
 
 static inline void register_bank(int iobase, int bank)
 {
@@ -112,6 +173,209 @@
                iobase+IRCC_MASTER);
 }
 
+static int smc_access(unsigned short cfg_base,unsigned char reg)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	outb(reg, cfg_base);
+
+	if (inb(cfg_base)!=reg)
+		return -1;
+
+	return 0;
+}
+
+static smc_chip_t * smc_probe(unsigned short cfg_base,u8 reg,smc_chip_t *chip,char *type)
+{
+	u8	devid,xdevid; 
+	u8	rev; 
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	/* Leave configuration */
+
+	outb(0xaa, cfg_base);
+
+	if (inb(cfg_base)==0xaa)	/* not a smc superio chip */
+		return NULL;
+
+	outb(reg, cfg_base);
+
+	xdevid=inb(cfg_base+1);
+
+	/* Enter configuration */
+
+	outb(0x55, cfg_base);
+
+	if (smc_access(cfg_base,0x55))	/* send second key and check */
+		return NULL;
+
+	/* probe device ID */
+
+	if (smc_access(cfg_base,reg))
+		return NULL;
+
+	devid=inb(cfg_base+1);
+
+	if (devid==0)			/* typical value for unused port */
+		return NULL;
+
+	if (devid==0xff)		/* typical value for unused port */
+		return NULL;
+
+	/* probe revision ID */
+
+	if (smc_access(cfg_base,reg+1))
+		return NULL;
+
+	rev=inb(cfg_base+1);
+
+	if (rev>=128)			/* i think this will make no sense */
+		return NULL;
+
+	if (devid==xdevid)		/* protection against false positives */        
+		return NULL;
+
+	/* Check for expected device ID; are there others? */
+
+	while(chip->devid!=devid) {
+
+		chip++;
+
+		if (chip->name==NULL)
+			return NULL;
+	}
+	if (chip->rev>rev)
+		return NULL;
+
+	MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+	
+	if (chip->flags&NoIRDA)
+		MESSAGE("chipset does not support IRDA\n");
+
+	return chip;
+}
+
+/*
+ * Function smc_superio_flat (chip, base, type)
+ *
+ *    Try get configuration of a smc SuperIO chip with flat register model
+ *
+ */
+static int smc_superio_flat(smc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io;
+	unsigned short sir_io;
+	__u8 mode;
+	int ret = -ENODEV;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (smc_probe(cfg_base,0xD,chips,type)==NULL)
+		return ret;
+
+	outb(0x0c, cfg_base);
+
+	mode = inb(cfg_base+1);
+	mode = (mode & 0x38) >> 3;
+		
+	/* Value for IR port */
+	if (mode && mode < 4) {
+		/* SIR iobase */
+		outb(0x25, cfg_base);
+		sir_io = inb(cfg_base+1) << 2;
+
+	       	/* FIR iobase */
+		outb(0x2b, cfg_base);
+		fir_io = inb(cfg_base+1) << 3;
+
+		if (fir_io) {
+			if (ircc_open(fir_io, sir_io) == 0)
+				ret=0; 
+		}
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+/*
+ * Function smc_superio_paged (chip, base, type)
+ *
+ *    Try  get configuration of a smc SuperIO chip with paged register model
+ *
+ */
+static int smc_superio_paged(smc_chip_t *chips, unsigned short cfg_base, char *type)
+{
+	unsigned short fir_io;
+	unsigned short sir_io;
+	int ret = -ENODEV;
+	
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (smc_probe(cfg_base,0x20,chips,type)==NULL)
+		return ret;
+	
+	/* Select logical device (UART2) */
+	outb(0x07, cfg_base);
+	outb(0x05, cfg_base + 1);
+		
+	/* SIR iobase */
+	outb(0x60, cfg_base);
+	sir_io  = inb(cfg_base + 1) << 8;
+	outb(0x61, cfg_base);
+	sir_io |= inb(cfg_base + 1);
+		
+	/* Read FIR base */
+	outb(0x62, cfg_base);
+	fir_io = inb(cfg_base + 1) << 8;
+	outb(0x63, cfg_base);
+	fir_io |= inb(cfg_base + 1);
+	outb(0x2b, cfg_base); // ???
+
+	if (fir_io) {
+		if (ircc_open(fir_io, sir_io) == 0)
+			ret=0; 
+	}
+	
+	/* Exit configuration */
+	outb(0xaa, cfg_base);
+
+	return ret;
+}
+
+static int smc_superio_fdc(unsigned short cfg_base)
+{
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+
+	if (!smc_superio_flat(fdc_chips_flat,cfg_base,"FDC")||!smc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+		return 0;
+
+	return -1;
+}
+
+static int smc_superio_lpc(unsigned short cfg_base)
+{
+#if 0
+	if (check_region(cfg_base, 2) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+			   cfg_base);
+		return -1;
+	}
+#endif
+
+	if (!smc_superio_flat(lpc_chips_flat,cfg_base,"LPC")||!smc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+		return 0;
+
+	return -1;
+}
+
 /*
  * Function ircc_init ()
  *
@@ -120,37 +384,36 @@
  */
 int __init ircc_init(void)
 {
-	static int smcreg[] = { 0x3f0, 0x370 };
-	smc_chip_t *chip;
-	chipio_t info;
-	int ret = -ENODEV;
-	int i;
+	int ret=-ENODEV;
 
 	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	/* Probe for all the NSC chipsets we know about */
-	for (chip=chips; chip->name ; chip++) {
-		for (i=0; i<2; i++) {
-			info.cfg_base = smcreg[i];
-			
-			/* 
-			 * First we check if the user has supplied any
-                         * parameters which we should use instead of probed
-			 * values
-			 */
-			if (io[i] < 0x2000) {
-				info.fir_base = io[i];
-				info.sir_base = io2[i];
-			} else if (chip->probe(chip, &info) < 0)
-				continue;
-			if (check_region(info.fir_base, CHIP_IO_EXTENT) < 0)
-				continue;
-			if (check_region(info.sir_base, CHIP_IO_EXTENT) < 0)
-				continue;
-			if (ircc_open(i, info.fir_base, info.sir_base) == 0)
-				ret = 0; 
-		}
+	dev_count=0;
+
+	if ((ircc_fir>0)&&(ircc_sir>0)) {
+	        MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
+		MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
+
+		if (ircc_open(ircc_fir, ircc_sir) == 0)
+			return 0;
+
+		return -ENODEV;
 	}
+
+	/* Trys to open for all the SMC chipsets we know about */
+
+	IRDA_DEBUG(0, __FUNCTION__ 
+	" Try to open all known SMC chipsets\n");
+
+	if (!smc_superio_fdc(0x3f0))
+		ret=0;
+	if (!smc_superio_fdc(0x370))
+		ret=0;
+	if (!smc_superio_lpc(0x2e))
+		ret=0;
+	if (!smc_superio_lpc(0x4e))
+		ret=0;
+
 	return ret;
 }
 
@@ -177,24 +440,57 @@
 /*
  * Function ircc_open (iobase, irq)
  *
- *    Open driver instance
+ *    Try to open driver instance
  *
  */
-static int ircc_open(int i, unsigned int fir_base, unsigned int sir_base)
+static int ircc_open(unsigned int fir_base, unsigned int sir_base)
 {
 	struct ircc_cb *self;
         struct irport_cb *irport;
-	int config;
-	int ret;
+	unsigned char low, high, chip, config, dma, irq, version;
+
 
 	IRDA_DEBUG(0, __FUNCTION__ "\n");
 
-	if ((config = ircc_probe(fir_base, sir_base)) == -1) {
+	if (check_region(fir_base, CHIP_IO_EXTENT) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
+			   fir_base);
+		return -ENODEV;
+	}
+#if POSSIBLE_USED_BY_SERIAL_DRIVER
+	if (check_region(sir_base, CHIP_IO_EXTENT) < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ ": can't get sir_base of 0x%03x\n",
+			   sir_base);
+		return -ENODEV;
+	}
+#endif
+
+	register_bank(fir_base, 3);
+
+	high    = inb(fir_base+IRCC_ID_HIGH);
+	low     = inb(fir_base+IRCC_ID_LOW);
+	chip    = inb(fir_base+IRCC_CHIP_ID);
+	version = inb(fir_base+IRCC_VERSION);
+	config  = inb(fir_base+IRCC_INTERFACE);
+
+	irq     = config >> 4 & 0x0f;
+	dma     = config & 0x0f;
+
+        if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { 
 	        IRDA_DEBUG(0, __FUNCTION__ 
 			   "(), addr 0x%04x - no device found!\n", fir_base);
-		return -1;
+		return -ENODEV;
 	}
-	
+	MESSAGE("SMC IrDA Controller found\n IrCC version %d.%d, "
+		"firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
+		chip & 0x0f, version, fir_base, sir_base, dma, irq);
+
+	if (dev_count>DIM(dev_self)) {
+	        IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), to many devices!\n");
+		return -ENOMEM;
+	}
+
 	/*
 	 *  Allocate new instance of the driver
 	 */
@@ -206,46 +502,74 @@
 	}
 	memset(self, 0, sizeof(struct ircc_cb));
 	spin_lock_init(&self->lock);
-   
-	/* Need to store self somewhere */
-	dev_self[i] = self;
 
-	irport = irport_open(i, sir_base, config >> 4 & 0x0f);
-	if (!irport)
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+
+	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+					      GFP_KERNEL|GFP_DMA);
+	if (self->rx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for receive buffer!\n",
+                      driver_name);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+					      GFP_KERNEL|GFP_DMA);
+	if (self->tx_buff.head == NULL) {
+		ERROR("%s, Can't allocate memory for transmit buffer!\n",
+                      driver_name);
+		kfree(self->rx_buff.head);
+		kfree(self);
+		return -ENOMEM;
+	}
+
+	irport = irport_open(dev_count, sir_base, irq);
+	if (!irport) {
+		kfree(self->tx_buff.head);
+		kfree(self->rx_buff.head);
+		kfree(self);
 		return -ENODEV;
+	}
+
+	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+   
+	/* Need to store self somewhere */
+	dev_self[dev_count++] = self;
 
 	/* Steal the network device from irport */
 	self->netdev = irport->netdev;
 	self->irport = irport;
+
 	irport->priv = self;
 
 	/* Initialize IO */
 	self->io.fir_base  = fir_base;
         self->io.sir_base  = sir_base; /* Used by irport */
-        self->io.irq       = config >> 4 & 0x0f;
+        self->io.fir_ext   = CHIP_IO_EXTENT;
+        self->io.sir_ext   = 8;       /* Used by irport */
+
 	if (ircc_irq < 255) {
-	        MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
-			driver_name, self->io.irq, ircc_irq);
+		if (ircc_irq!=irq)
+			MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
+				driver_name, self->io.irq, ircc_irq);
 		self->io.irq = ircc_irq;
 	}
-        self->io.fir_ext   = CHIP_IO_EXTENT;
-        self->io.sir_ext   = 8;       /* Used by irport */
-        self->io.dma       = config & 0x0f;
+	else
+		self->io.irq = irq;
 	if (ircc_dma < 255) {
-	        MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
-			driver_name, self->io.dma, ircc_dma);
+		if (ircc_dma!=dma)
+			MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
+				driver_name, self->io.dma, ircc_dma);
 		self->io.dma = ircc_dma;
 	}
+	else
+		self->io.dma = dma;
 
-	/* Lock the port that we need */
-	ret = check_region(self->io.fir_base, self->io.fir_ext);
-	if (ret < 0) { 
-		IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
-			   self->io.fir_base);
-                kfree(self);
-		return -ENODEV;
-	}
-	request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+	request_region(fir_base, CHIP_IO_EXTENT, driver_name);
 
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&irport->qos);
@@ -260,23 +584,6 @@
 
 	irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 	
-	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	self->rx_buff.truesize = 4000; 
-	self->tx_buff.truesize = 4000;
-
-	self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-					      GFP_KERNEL|GFP_DMA);
-	if (self->rx_buff.head == NULL)
-		return -ENOMEM;
-	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	
-	self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-					      GFP_KERNEL|GFP_DMA);
-	if (self->tx_buff.head == NULL) {
-		kfree(self->rx_buff.head);
-		return -ENOMEM;
-	}
-	memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
@@ -295,6 +602,10 @@
         if (self->pmdev)
                 self->pmdev->data = self;
 
+	/* Power on device */
+
+	outb(0x00, fir_base+IRCC_MASTER);
+
 	return 0;
 }
 
@@ -347,146 +658,6 @@
 #endif /* MODULE */
 
 /*
- * Function ircc_probe_69 (chip, info)
- *
- *    Probes for the SMC FDC37C669 and FDC37N869
- *
- */
-static int ircc_probe_69(smc_chip_t *chip, chipio_t *info)
-{
-	int cfg_base = info->cfg_base;
-	__u8 devid, mode;
-	int ret = -ENODEV;
-	int fir_io;
-	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Enter configuration */
-	outb(chip->entr1, cfg_base);
-	outb(chip->entr2, cfg_base);
-	
-	outb(chip->cid_index, cfg_base);
-	devid = inb(cfg_base+1);
-	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
-	
-	/* Check for expected device ID; are there others? */
-	if (devid == chip->cid_value) {
-		outb(0x0c, cfg_base);
-		mode = inb(cfg_base+1);
-		mode = (mode & 0x38) >> 3;
-		
-		/* Value for IR port */
-		if (mode && mode < 4) {
-			/* SIR iobase */
-			outb(0x25, cfg_base);
-			info->sir_base = inb(cfg_base+1) << 2;
-
-		       	/* FIR iobase */
-			outb(0x2b, cfg_base);
-			fir_io = inb(cfg_base+1) << 3;
-			if (fir_io) {
-				ret = 0;
-				info->fir_base = fir_io;
-			}
-		}
-	}
-	
-	/* Exit configuration */
-	outb(0xaa, cfg_base);
-
-	return ret;
-}
-
-/*
- * Function ircc_probe_58 (chip, info)
- *
- *    Probes for the SMC FDC37N958
- *
- */
-static int ircc_probe_58(smc_chip_t *chip, chipio_t *info)
-{
-	int cfg_base = info->cfg_base;
-	__u8 devid;
-	int ret = -ENODEV;
-	int fir_io;
-	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
-	/* Enter configuration */
-	outb(chip->entr1, cfg_base);
-	outb(chip->entr2, cfg_base);
-	
-	outb(chip->cid_index, cfg_base);
-	devid = inb(cfg_base+1);
-	IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
-	
-	/* Check for expected device ID; are there others? */
-	if (devid == chip->cid_value) {
-		/* Select logical device (UART2) */
-		outb(0x07, cfg_base);
-		outb(0x05, cfg_base + 1);
-		
-		/* SIR iobase */
-		outb(0x60, cfg_base);
-		info->sir_base = inb(cfg_base + 1) << 8;
-		outb(0x61, cfg_base);
-		info->sir_base |= inb(cfg_base + 1);
-		
-		/* Read FIR base */
-		outb(0x62, cfg_base);
-		fir_io = inb(cfg_base + 1) << 8;
-		outb(0x63, cfg_base);
-		fir_io |= inb(cfg_base + 1);
-		outb(0x2b, cfg_base);
-		if (fir_io) {
-			ret = 0;
-			info->fir_base = fir_io;
-		}
-	}
-	
-	/* Exit configuration */
-	outb(0xaa, cfg_base);
-
-	return ret;
-}
-
-/*
- * Function ircc_probe (iobase, board_addr, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
-static int ircc_probe(int fir_base, int sir_base) 
-{
-	int low, high, chip, config, dma, irq;
-	int iobase = fir_base;
-	int version = 1;
-
-	IRDA_DEBUG(0, __FUNCTION__ "\n");
-
-	register_bank(iobase, 3);
-	high    = inb(iobase+IRCC_ID_HIGH);
-	low     = inb(iobase+IRCC_ID_LOW);
-	chip    = inb(iobase+IRCC_CHIP_ID);
-	version = inb(iobase+IRCC_VERSION);
-	config  = inb(iobase+IRCC_INTERFACE);
-	irq     = config >> 4 & 0x0f;
-	dma     = config & 0x0f;
-
-        if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) { 
-                MESSAGE("SMC IrDA Controller found; IrCC version %d.%d, "
-			"port 0x%03x, dma=%d, irq=%d\n",
-			chip & 0x0f, version, iobase, dma, irq);
-	} else
-		return -ENODEV;
-
-	/* Power on device */
-	outb(0x00, iobase+IRCC_MASTER);
-
-	return config;
-}
-
-/*
  * Function ircc_change_speed (self, baud)
  *
  *    Change the speed of the device
@@ -1055,6 +1226,10 @@
 MODULE_PARM_DESC(ircc_dma, "DMA channel");
 MODULE_PARM(ircc_irq, "1i");
 MODULE_PARM_DESC(ircc_irq, "IRQ line");
+MODULE_PARM(ircc_fir, "1-4i");
+MODULE_PARM_DESC(ircc_fir, "FIR Base Adress");
+MODULE_PARM(ircc_sir, "1-4i");
+MODULE_PARM_DESC(ircc_sir, "SIR Base Adress");
 
 int init_module(void)
 {
diff -u --recursive --new-file linux-2.4.6-ac5/include/net/irda/smc-ircc.h.save linux-2.4.6-ac5/include/net/irda/smc-ircc.h
--- linux-2.4.6-ac5/include/net/irda/smc-ircc.h.save	Fri Jul 20 10:59:58 2001
+++ linux-2.4.6-ac5/include/net/irda/smc-ircc.h	Fri Jul 20 11:00:25 2001
@@ -154,16 +154,6 @@
 #define IRCC_1152                  0x80
 #define IRCC_CRC                   0x40
 
-struct smc_chip {
-	char *name;
-	unsigned char entr1;
-	unsigned char entr2;
-	unsigned char cid_index;
-	unsigned char cid_value;
-	int (*probe)(struct smc_chip *chip, chipio_t *info);
-};
-typedef struct smc_chip smc_chip_t;
-
 /* Private data for each instance */
 struct ircc_cb {
 	struct net_device *netdev;     /* Yes! we are some kind of netdevice */

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: irda smc patch... oops
       [not found]   ` <20010720145856.C2798@intern.kubla.de>
@ 2001-07-20 13:15     ` Stefani Seibold
  0 siblings, 0 replies; 4+ messages in thread
From: Stefani Seibold @ 2001-07-20 13:15 UTC (permalink / raw)
  To: Dominik Kubla; +Cc: linux-kernel

Sorry,

but i had a look on the irda homepage and it seems that there is nothing happening
since more than a year.

I will sent a copy of my patch to linux-irda@pasta.cs.uit.no and dag@brattli.net.

Greetings,
Stefani

Am Freitag, 20. Juli 2001 14:58 schrieben Sie:
> On Fri, Jul 20, 2001 at 12:36:24PM +0100, Stefani Seibold wrote:
> > Hi folks,
> >
> > sorry about the previous patch, it was my test code, which will not
> > work....
>
> You should also notify the IRDA maintainer as listed in the MAINTAINERS
> file:  linux-irda@pasta.cs.uit.no
>
> Linus and Alan will ignore patches that bypass the subsystem maintainers
> in most cases.
>
> Dominik

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2001-07-20 13:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <Pine.SGI.4.10.10102071945350.926064-100000@Sky.inp.nsk.su>
2001-02-08 11:44 ` patch for 2.4.1 disable printk and panic messages Stefani Seibold
2001-07-20 10:21 ` irda smc patch Stefani Seibold
2001-07-20 11:36 ` irda smc patch... oops Stefani Seibold
     [not found]   ` <20010720145856.C2798@intern.kubla.de>
2001-07-20 13:15     ` Stefani Seibold

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox