patch-2.3.99-pre1 linux/drivers/char/sx.c

Next file: linux/drivers/char/sx.h
Previous file: linux/drivers/char/serial.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.51/linux/drivers/char/sx.c linux/drivers/char/sx.c
@@ -4,7 +4,7 @@
  *  This driver will also support the older SI, and XIO cards.
  *
  *
- *   (C) 1998 R.E.Wolff@BitWizard.nl
+ *   (C) 1998 - 2000  R.E.Wolff@BitWizard.nl
  *
  *  Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
  *  version of this driver. Some fragments may have been copied. (none
@@ -33,6 +33,16 @@
  *
  * Revision history:
  * $Log: sx.c,v $
+ * Revision 1.32  2000/03/07 90:00:00  wolff,pvdl
+ * - Fixed some sx_dprintk typos
+ * - added detection for an invalid board/module configuration
+ *
+ * Revision 1.31  2000/03/06 12:00:00  wolff,pvdl
+ * - Added support for EISA
+ *
+ * Revision 1.30  2000/01/21 17:43:06  wolff
+ * - Added support for SX+
+ *
  * Revision 1.26  1999/08/05 15:22:14  wolff
  * - Port to 2.3.x
  * - Reformatted to Linus' liking.
@@ -185,8 +195,8 @@
  * */
 
 
-#define RCS_ID "$Id: sx.c,v 1.26 1999/08/05 15:22:14 wolff Exp $"
-#define RCS_REV "$Revision: 1.26 $"
+#define RCS_ID "$Id: sx.c,v 1.32 2000/03/07 17:01:02 wolff, pvdl Exp $"
+#define RCS_REV "$Revision: 1.32 $"
 
 
 #include <linux/module.h>
@@ -221,6 +231,9 @@
 
 #include "sxboards.h"
 #include "sxwindow.h"
+#include <linux/generic_serial.h>
+#include <linux/compatmac.h>
+#include "sx.h"
 
 
 /* I don't think that this driver can handle more than 256 ports on
@@ -228,149 +241,16 @@
    if you want more than 4 boards.  */
 
 
-/* ************************************************************** */
-/* * This section can be removed when 2.0 becomes outdated....  * */
-/* ************************************************************** */
-
-
-#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
-#define TWO_ZERO
-#else
-#if LINUX_VERSION_CODE < 0x020200   /* less than 2.2.x */
-#warning "Please use a 2.2.x kernel. "
-#else
-#if LINUX_VERSION_CODE < 0x020300   /* less than 2.3.x */
-#define TWO_TWO
-#else
-#define TWO_THREE
-#endif
-#endif
-#endif
-
-#ifdef TWO_ZERO
-
-/* Here is the section that makes the 2.2 compatible driver source 
-   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
-   and provide for compatibility stuff here if possible. */
-
-#include <linux/bios32.h>
-
-#define Get_user(a,b)                a = get_user(b)
-#define Put_user(a,b)                0,put_user(a,b)
-#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
-
-static inline int copy_from_user(void *to,const void *from, int c) 
-{
-  memcpy_fromfs(to, from, c);
-  return 0;
-}
-
-#define pci_present                  pcibios_present
-#define pci_read_config_word         pcibios_read_config_word
-#define pci_read_config_dword        pcibios_read_config_dword
-
-static inline unsigned char get_irq (unsigned char bus, unsigned char fn)
-{
-	unsigned char t; 
-	pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t);
-	return t;
-}
-
-static inline void *ioremap(unsigned long base, long length)
-{
-	if (base < 0x100000) return (void *)base;
-	return vremap (base, length);
-}
-
-#define my_iounmap(x, b)             (((long)x<0x100000)?0:vfree ((void*)x))
-
-#define capable(x)                   suser()
-
-#define queue_task                   queue_task_irq_off
-#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
-#define signal_pending(current)      (current->signal & ~current->blocked)
-#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
-#define time_after(t1,t2)            (((long)t1-t2) > 0)
-
-
-#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
-#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
-
-/* Not yet implemented on 2.0 */
-#define ASYNC_SPD_SHI  -1
-#define ASYNC_SPD_WARP -1
-
-
-/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
-   to the "name" field that does exist. As long as the assignments are
-   done in the right order, there is nothing to worry about. */
-#define driver_name           name 
-
-/* Should be in a header somewhere. They are in tty.h on 2.2 */
-#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
-#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
-
-/* The return type of a "close" routine. */
-#define INT                   void
-#define NO_ERROR              /* Nothing */
-
-#else
-
-/* The 2.2.x compatibility section. */
-#include <asm/uaccess.h>
-
-
-#define Get_user(a,b)         get_user(a,b)
-#define Put_user(a,b)         put_user(a,b)
-#define get_irq(pdev)         pdev->irq
-
-#define INT                   int
-#define NO_ERROR              0
-
-#define my_iounmap(x,b)       (iounmap((char *)(b)))
-
-#endif
-
-#ifndef TWO_THREE
-/* These are new in 2.3. The source now uses 2.3 syntax, and here is 
-   the compatibility define... */
-#define wait_queue_head_t struct wait_queue *
-#define DECLARE_MUTEX(name) struct semaphore name = MUTEX
-#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL }
-
-#endif
-
-#undef RS_EVENT_WRITE_WAKEUP
-#define RS_EVENT_WRITE_WAKEUP	0
-
-
-#include "generic_serial.h"
-#include "sx.h"
-
-
-/* ************************************************************** */
-/* *                End of compatibility section..              * */
-/* ************************************************************** */
-
-
 
 /* Why the hell am I defining these here? */
 #define SX_TYPE_NORMAL 1
 #define SX_TYPE_CALLOUT 2
 
-#ifndef SX_NORMAL_MAJOR
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define SX_NORMAL_MAJOR  32
-#define SX_CALLOUT_MAJOR 33
-#endif
-
 #ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
 #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
 #endif
 
 
-
 /* Configurable options: 
    (Don't be too sure that it'll work if you toggle them) */
 
@@ -410,19 +290,17 @@
 static void sx_enable_rx_interrupts (void * ptr); 
 static int  sx_get_CD (void * ptr); 
 static void sx_shutdown_port (void * ptr);
-static void sx_set_real_termios (void  *ptr);
+static int  sx_set_real_termios (void  *ptr);
 static void sx_hungup (void  *ptr);
 static void sx_close (void  *ptr);
 static int sx_chars_in_buffer (void * ptr);
 static int sx_init_board (struct sx_board *board);
 static int sx_init_portstructs (int nboards, int nports);
 static int sx_fw_ioctl (struct inode *inode, struct file *filp,
-		         unsigned int cmd, unsigned long arg);
+                        unsigned int cmd, unsigned long arg);
 static int sx_fw_open(struct inode *inode, struct file *filp);
 static INT sx_fw_release(struct inode *inode, struct file *filp);
 static int sx_init_drivers(void);
-void my_hd (unsigned char *addr, int len);
-
 
 
 static struct tty_driver sx_driver, sx_callout_driver;
@@ -458,11 +336,13 @@
 int sx_maxints = 100;
 
 /* These are the only open spaces in my computer. Yours may have more
-   or less.... */
+   or less.... -- REW 
+   duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
+*/
 int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
                        0xc8000, 0xd8000, 0xe8000};
 int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, 
-                       0xc8000, 0xd8000, 0xe8000};
+                       0xc8000, 0xd8000, 0xe8000, 0xa0000};
 
 #define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
 #define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
@@ -474,6 +354,8 @@
 
 #ifndef TWO_ZERO
 #ifdef MODULE
+MODULE_PARM(sx_probe_addrs, "i");
+MODULE_PARM(si_probe_addrs, "i");
 MODULE_PARM(sx_poll, "i");
 MODULE_PARM(sx_slowpoll, "i");
 MODULE_PARM(sx_maxints, "i");
@@ -580,6 +462,27 @@
 #define TIMEOUT_2 1000000
 
 
+#ifdef DEBUG
+static void my_hd (unsigned char *addr, int len)
+{
+	int i, j, ch;
+
+	for (i=0;i<len;i+=16) {
+		printk ("%08x ", (int) addr+i);
+		for (j=0;j<16;j++) {
+			printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+		}
+		for (j=0;j<16;j++) {
+			ch = addr[j+i];
+			printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+		}
+		printk ("\n");
+	}
+}
+#endif
+
+
+
 /* This needs redoing for Alpha -- REW -- Done. */
 
 inline void write_sx_byte (struct sx_board *board, int offset, u8 byte)
@@ -675,6 +578,8 @@
 			printk (KERN_INFO "sx: Card doesn't respond to reset....\n");
 			return 0;
 		}
+	} else if (IS_EISA_BOARD(board)) {
+		outb(board->irq<<4, board->eisa_base+0xc02);
 	} else {
 		/* Gory details of the SI/ISA board */
 		write_sx_byte (board, SI2_ISA_RESET,    SI2_ISA_RESET_SET);
@@ -746,9 +651,12 @@
 {
 	if (IS_SX_BOARD (board)) {
 		write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN);
+	} else if (IS_EISA_BOARD(board)) {
+		write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
+		outb((board->irq<<4)|4, board->eisa_base+0xc02);
 	} else {
 		/* Don't bug me about the clear_set. 
-		   I haven't the foggiest idea what it's about -- REW*/
+		   I haven't the foggiest idea what it's about -- REW */
 		write_sx_byte (board, SI2_ISA_RESET,    SI2_ISA_RESET_CLEAR);
 		write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
 	}
@@ -769,6 +677,8 @@
 		write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) | 
 		                                 SX_CONF_BUSEN | 
 		                                 SX_CONF_HOSTIRQ);
+	} else if (IS_EISA_BOARD(board)) {
+		inb(board->eisa_base+0xc03);  
 	} else {
 		switch (board->irq) {
 		case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break;
@@ -834,6 +744,18 @@
 	return module_type >> 4;
 }
 
+static void sx_reconfigure_port(struct sx_port *port)
+{
+	if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
+		if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
+			printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
+		}
+	} else {
+		sx_dprintk (SX_DEBUG_TERMIOS, 
+		            "sx: Not sending reconfigure: port isn't open (%02x).\n", 
+		            sx_read_channel_byte (port, hi_hstat));
+	}	
+}
 
 static void sx_setsignals (struct sx_port *port, int dtr, int rts)
 {
@@ -954,7 +876,7 @@
 /* Simon Allen's version of this routine was 225 lines long. 85 is a lot
    better. -- REW */
 
-static void sx_set_real_termios (void *ptr)
+static int sx_set_real_termios (void *ptr)
 {
 	struct sx_port *port = ptr;
 
@@ -1008,16 +930,7 @@
 	sx_write_channel_byte (port, hi_txoff, STOP_CHAR  (port->gs.tty));
 	sx_write_channel_byte (port, hi_rxoff, STOP_CHAR  (port->gs.tty));
 
-	if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) {
-		if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
-			printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n");
-		}
-	} else {
-		sx_dprintk (SX_DEBUG_TERMIOS, 
-		            "sx: Not sending reconfigure: port isn't open (%02x).\n", 
-		            sx_read_channel_byte (port, hi_hstat));
-	}
-
+	sx_reconfigure_port(port);
 
 	/* Tell line discipline whether we will do input cooking */
 	if(I_OTHER(port->gs.tty)) {
@@ -1045,6 +958,7 @@
 	            O_OTHER(port->gs.tty));
 	/* port->c_dcd = sx_get_CD (port); */
 	func_exit ();
+	return 0;
 }
 
 
@@ -1102,7 +1016,7 @@
 
 		/* Don't copy pas the end of the source buffer */
 		if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) 
-                	c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
+			c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
 
 		sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) \n", 
 		            c, SERIAL_XMIT_SIZE- port->gs.xmit_tail);
@@ -1331,6 +1245,9 @@
 		sx_write_board_word (board, cc_int_pending, 0);
 		if (IS_SX_BOARD (board)) {
 			write_sx_byte (board, SX_RESET_IRQ, 1);
+		} else if (IS_EISA_BOARD(board)) {
+			inb(board->eisa_base+0xc03);
+			write_sx_word(board, 8, 0); 
 		} else {
 			write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
 			write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
@@ -1474,6 +1391,7 @@
 	port->gs.flags &= ~ GS_ACTIVE;
 	if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
 		sx_setsignals (port, 0, 0);
+		sx_reconfigure_port(port);
 	}
 
 	func_exit();
@@ -1711,7 +1629,7 @@
 
 
 static int sx_fw_ioctl (struct inode *inode, struct file *filp,
-		         unsigned int cmd, unsigned long arg)
+                        unsigned int cmd, unsigned long arg)
 {
 	int rc = 0;
 	int *descr = (int *)arg, i;
@@ -1754,7 +1672,11 @@
 		board = &boards[arg];
 		break;
 	case SXIO_GET_TYPE:
-		rc = IS_SX_BOARD (board)? SX_TYPE_SX:SX_TYPE_SI;
+		rc = -ENOENT; /* If we manage to miss one, return error. */
+		if (IS_SX_BOARD (board)) rc = SX_TYPE_SX;
+		if (IS_CF_BOARD (board)) rc = SX_TYPE_CF;
+		if (IS_SI_BOARD (board)) rc = SX_TYPE_SI;
+		if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI;
 		sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
 		break;
 	case SXIO_DO_RAMTEST:
@@ -1786,7 +1708,7 @@
 			for (i=0;i<nbytes;i += SX_CHUNK_SIZE) {
 				copy_from_user (tmp, (char *)data+i, 
 				                (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE);
-				memcpy_toio    ((char *) (board->base + offset + i), tmp, 
+				memcpy_toio    ((char *) (board->base2 + offset + i), tmp, 
 				                (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE);
 			}
 
@@ -1830,6 +1752,9 @@
 	case SXIO_GETGSDEBUG:
 		rc = gs_debug;
 		break;
+	case SXIO_GETNPORTS:
+		rc = sx_nports;
+		break;
 	default:
 		printk (KERN_WARNING "Unknown ioctl on firmware device (%x).\n", cmd);
 		break;
@@ -1886,6 +1811,7 @@
 			Get_user(ival, (unsigned int *) arg);
 			sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
 			                     ((ival & TIOCM_RTS) ? 1 : -1));
+			sx_reconfigure_port(port);
 		}
 		break;
 	case TIOCMBIC:
@@ -1894,6 +1820,7 @@
 			Get_user(ival, (unsigned int *) arg);
 			sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
 			                     ((ival & TIOCM_RTS) ? 0 : -1));
+			sx_reconfigure_port(port);
 		}
 		break;
 	case TIOCMSET:
@@ -1902,6 +1829,7 @@
 			Get_user(ival, (unsigned int *) arg);
 			sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
 			                     ((ival & TIOCM_RTS) ? 1 : 0));
+			sx_reconfigure_port(port);
 		}
 		break;
 
@@ -1980,13 +1908,17 @@
 
 	board->flags |= SX_BOARD_INITIALIZED;
 
+	if (read_sx_byte (board, 0))
+		/* CF boards may need this. */
+		write_sx_byte(board,0, 0);
+
 	/* This resets the processor again, to make sure it didn't do any
 	   foolish things while we were downloading the image */
 	if (!sx_reset (board))
 		return 0;
 
 	sx_start_board (board);
-
+	udelay (10);
 	if (!sx_busy_wait_neq (board, 0, 0xff, 0)) {
 		printk (KERN_ERR "sx: Ooops. Board won't initialize.\n");
 		return 0;
@@ -2050,7 +1982,8 @@
 			chans=0;
 			break;
 		}
-		if (IS_SI_BOARD(board) && (mod_compat_type(type) == 4)) {
+		if ((IS_EISA_BOARD(board) || 
+		     IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) {
 			printk (KERN_ERR "sx: This is an invalid configuration.\n"
 			        "Don't use SXDCs on an SI/XIO adapter.\n");
 			chans=0;
@@ -2147,52 +2080,56 @@
 	int i;
 
 	func_enter();
-	sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %x.\n", 
-	            board->base + SX_VPD_ROM);
 
-	if (sx_debug & SX_DEBUG_PROBE)
-		my_hd ((char *)(board->base + SX_VPD_ROM), 0x40);
+	if (!IS_CF_BOARD (board)) {    
+		sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %x.\n", 
+		            board->base + SX_VPD_ROM);
 
-	p = (char *) &vpdp;
-	for (i=0;i< sizeof (struct vpd_prom);i++)
-		*p++ = read_sx_byte (board, SX_VPD_ROM + i*2);
+		if (sx_debug & SX_DEBUG_PROBE)
+			my_hd ((char *)(board->base + SX_VPD_ROM), 0x40);
 
-	if (sx_debug & SX_DEBUG_PROBE)
-		my_hd ((char *)&vpdp, 0x20);
+		p = (char *) &vpdp;
+		for (i=0;i< sizeof (struct vpd_prom);i++)
+			*p++ = read_sx_byte (board, SX_VPD_ROM + i*2);
 
-	sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n");
+		if (sx_debug & SX_DEBUG_PROBE)
+			my_hd ((char *)&vpdp, 0x20);
 
-	if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
-		sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", 
-		            vpdp.identifier); 
-		return 0;
+		sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n");
+
+		if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
+			sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", 
+			            vpdp.identifier); 
+			return 0;
+		}
 	}
 
 	printheader ();
 
-	printk (KERN_DEBUG "sx: Found an SX board at %x\n", board->hw_base);
-	printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", 
-	        vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
-	printk (           "Manufactured: %d/%d\n", 
-	        1970 + vpdp.myear, vpdp.mweek);
-
-
-	if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) &&
-	    (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
-		/* This might be a bit harsh. This was the primary reason the
-		   SX/ISA card didn't work at first... */
-		printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n");
-		return (0);
-	}
-
-	if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
-		if (board->base & 0x8000) {
-			printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %x.\n", board->base);
-			printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
+	if (!IS_CF_BOARD (board)) {
+		printk (KERN_DEBUG "sx: Found an SX board at %x\n", board->hw_base);
+		printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", 
+		        vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
+		printk (           "Manufactured: %d/%d\n", 
+		        1970 + vpdp.myear, vpdp.mweek);
+
+
+		if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) &&
+		    (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
+			/* This might be a bit harsh. This was the primary reason the
+			   SX/ISA card didn't work at first... */
+			printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n");
+			return (0);
+		}
+
+		if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
+			if (board->base & 0x8000) {
+				printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %x.\n", board->base);
+				printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
+			}
 		}
 	}
 
-
 	board->nports = -1;
 
 	/* This resets the processor, and keeps it off the bus. */
@@ -2225,9 +2162,11 @@
 	if (sx_debug & SX_DEBUG_PROBE)
 		my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8);
 
-	for (i=0;i<8;i++) {
-		if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
-			return 0;
+	if (!IS_EISA_BOARD(board)) {
+		for (i=0;i<8;i++) {
+			if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+				return 0;
+			}
 		}
 	}
 
@@ -2449,7 +2388,7 @@
 	unsigned int t;
 
 #define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x00260000
+#define CNTRL_REG_GOODVALUE     0x18260000
 
 	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
 	hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
@@ -2472,6 +2411,7 @@
 {
 	int i;
 	int found = 0;
+	int eisa_slot;
 	struct sx_board *board;
 
 #ifdef CONFIG_PCI
@@ -2518,22 +2458,35 @@
 			tshort = (tint >> 16) & 0xffff;
 			sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
 			/* sx_dprintk (SX_DEBUG_PROBE, "pdev = %d/%d	(%x)\n", pdev, tint); */ 
-			if (tshort != 0x0200) {
+			if ((tshort != 0x0200) && (tshort != 0x0300)) {
 				sx_dprintk (SX_DEBUG_PROBE, "But it's not an SX card (%d)...\n", 
 				            tshort);
 				continue;
 			}
 			board = &boards[found];
 
-			pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
+			board->flags &= ~SX_BOARD_TYPE;
+			board->flags |= (tshort == 0x200)?SX_PCI_BOARD:
+			                                  SX_CFPCI_BOARD;
+
+			/* CF boards use base address 3.... */
+			if (IS_CF_BOARD (board))
+				pci_read_config_dword(pdev, PCI_BASE_ADDRESS_3,
+				                      &tint);
+			else
+				pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
+				                      &tint);
 			board->hw_base = tint & PCI_BASE_ADDRESS_MEM_MASK;
-			board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN);
+			board->base2 = 
+			board->base = (ulong) ioremap(board->hw_base, WINDOW_LEN (board));
+			/* Most of the stuff on the CF board is offset by
+			   0x18000 ....  */
+			if (IS_CF_BOARD (board)) board->base += 0x18000;
+
 			board->irq = get_irq (pdev);
-			board->flags &= ~SX_BOARD_TYPE;
-			board->flags |=  SX_PCI_BOARD;
 
-			sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%x(%d).\n", 
-			            tint, boards[found].base, board->irq);
+			sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%x(%d) %x.\n", 
+			            tint, boards[found].base, board->irq, board->flags);
 
 			if (probe_sx (board)) {
 				found++;
@@ -2547,6 +2500,7 @@
 	for (i=0;i<NR_SX_ADDRS;i++) {
 		board = &boards[found];
 		board->hw_base = sx_probe_addrs[i];
+		board->base2 =
 		board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN);
 		board->flags &= ~SX_BOARD_TYPE;
 		board->flags |=	SX_ISA_BOARD;
@@ -2562,6 +2516,7 @@
 	for (i=0;i<NR_SI_ADDRS;i++) {
 		board = &boards[found];
 		board->hw_base = si_probe_addrs[i];
+		board->base2 =
 		board->base = (ulong) ioremap(board->hw_base, SI2_ISA_WINDOW_LEN);
 		board->flags &= ~SX_BOARD_TYPE;
 		board->flags |=  SI_ISA_BOARD;
@@ -2574,6 +2529,34 @@
 		}
 	}
 
+        sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n");
+        for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000)
+        {
+                if((inb(eisa_slot+0xc80)==0x4d) &&
+                   (inb(eisa_slot+0xc81)==0x98))
+                {
+			sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n",
+			                        "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83));
+
+			board = &boards[found];
+			board->eisa_base = eisa_slot;
+			board->flags &= ~SX_BOARD_TYPE;
+			board->flags |= SI_EISA_BOARD;
+
+			board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16);
+			board->base2 =
+			board->base = (ulong) ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
+
+			sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %x\n", board->hw_base);
+			sx_dprintk(SX_DEBUG_PROBE, "base: %x\n", board->base);
+			board->irq = inb(board->eisa_base+0xc02)>>4; 
+			sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
+			
+			probe_si(board);
+
+			found++;
+		}
+	}
 	if (found) {
 		printk (KERN_INFO "sx: total of %d boards detected.\n", found);
 
@@ -2588,7 +2571,7 @@
 }
 
 
-
+#ifdef MODULE
 void cleanup_module(void)
 {
 	int i; 
@@ -2622,52 +2605,4 @@
 	kfree (sx_termios_locked);
 	func_exit();
 }
-
-
-#ifdef DEBUG
-void my_hd (unsigned char *addr, int len)
-{
-	int i, j, ch;
-
-	for (i=0;i<len;i+=16) {
-		printk ("%08x ", (int) addr+i);
-		for (j=0;j<16;j++) {
-			printk ("%02x %s", addr[j+i], (j==7)?" ":"");
-		}
-		for (j=0;j<16;j++) {
-			ch = addr[j+i];
-			printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
-		}
-		printk ("\n");
-	}
-}
 #endif
-
-#ifdef MODULE
-#undef func_enter
-#undef func_exit
-
-#include "generic_serial.c"
-#endif
-
-
-/*
- * Anybody who knows why this doesn't work for me, please tell me -- REW.
- * Snatched from scsi.c (fixed one spelling error):
- * Overrides for Emacs so that we follow Linus' tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)