summaryrefslogtreecommitdiffstats
path: root/drivers/char/sx.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-19 01:28:40 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-19 01:28:40 +0000
commit8abb719409c9060a7c0676f76e9182c1e0b8ca46 (patch)
treeb88cc5a6cd513a04a512b7e6215c873c90a1c5dd /drivers/char/sx.c
parentf01bd7aeafd95a08aafc9e3636bb26974df69d82 (diff)
Merge with 2.3.99-pre1.
Diffstat (limited to 'drivers/char/sx.c')
-rw-r--r--drivers/char/sx.c437
1 files changed, 186 insertions, 251 deletions
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 7caf1058a..1b8583034 100644
--- a/drivers/char/sx.c
+++ b/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_disable_rx_interrupts (void * ptr);
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_slowpoll = 0;
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 @@ int sx_irqmask = -1;
#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 @@ static inline int sx_paranoia_check(struct sx_port const * port,
#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 @@ int sx_reset (struct sx_board *board)
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 @@ int sx_start_board (struct sx_board *board)
{
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 @@ int sx_start_interrupts (struct sx_board *board)
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 @@ int mod_compat_type (int module_type)
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 @@ static void sx_set_baud (struct sx_port *port)
/* 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 @@ static void sx_set_real_termios (void *ptr)
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 @@ static void sx_set_real_termios (void *ptr)
O_OTHER(port->gs.tty));
/* port->c_dcd = sx_get_CD (port); */
func_exit ();
+ return 0;
}
@@ -1102,7 +1016,7 @@ void sx_transmit_chars (struct sx_port *port)
/* 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 @@ static void sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
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 @@ static void sx_shutdown_port (void * ptr)
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 @@ int do_memtest_w (struct sx_board *board, int min, int max)
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 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
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 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
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 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp,
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 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
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 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
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 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp,
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 @@ static int sx_init_board (struct sx_board *board)
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 @@ static int sx_init_board (struct sx_board *board)
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 probe_sx (struct sx_board *board)
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 (!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_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 (((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 @@ int probe_si (struct sx_board *board)
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 @@ void fix_sx_pci (PDEV, struct sx_board *board)
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 sx_init(void)
{
int i;
int found = 0;
+ int eisa_slot;
struct sx_board *board;
#ifdef CONFIG_PCI
@@ -2518,22 +2458,35 @@ int sx_init(void)
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 @@ int sx_init(void)
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 @@ int sx_init(void)
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 @@ int sx_init(void)
}
}
+ 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 @@ int sx_init(void)
}
-
+#ifdef MODULE
void cleanup_module(void)
{
int i;
@@ -2622,52 +2605,4 @@ void cleanup_module(void)
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:
- */