aboutsummaryrefslogtreecommitdiff
path: root/drivers/char/sx.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-02-22 17:09:33 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-22 17:09:33 -0800
commit4c37705877e74c02c968735c2eee0f84914cf557 (patch)
tree87af608b211f1b6920927ab101a192ee4529946b /drivers/char/sx.c
parent4a6514e6d096716fb7bedf238efaaca877e2a7e8 (diff)
tty: move obsolete and broken generic_serial drivers to drivers/staging/generic_serial/
As planned by Arnd Bergmann, this moves the following drivers to the drivers/staging/generic_serial directory where they will be removed after 2.6.41 if no one steps up to claim them. generic_serial rio ser_a2232 sx vme_scc Cc: Arnd Bergmann <arnd@arndb.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Jiri Slaby <jslaby@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char/sx.c')
-rw-r--r--drivers/char/sx.c2894
1 files changed, 0 insertions, 2894 deletions
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
deleted file mode 100644
index 1291462bcdd..00000000000
--- a/drivers/char/sx.c
+++ /dev/null
@@ -1,2894 +0,0 @@
-/* sx.c -- driver for the Specialix SX series cards.
- *
- * This driver will also support the older SI, and XIO cards.
- *
- *
- * (C) 1998 - 2004 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
- * yet :-)
- *
- * Specialix pays for the development and support of this driver.
- * Please DO contact support@specialix.co.uk if you require
- * support. But please read the documentation (sx.txt) first.
- *
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- * Revision history:
- * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff
- * - Fixed module and port counting
- * - Fixed signal handling
- * - Fixed an Ooops
- *
- * Revision 1.32 2000/03/07 09: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.
- *
- * Revision 1.25 1999/07/30 14:24:08 wolff
- * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0).
- *
- * Revision 1.24 1999/07/28 09:41:52 wolff
- * - I noticed the remark about use-count straying in sx.txt. I checked
- * sx_open, and found a few places where that could happen. I hope it's
- * fixed now.
- *
- * Revision 1.23 1999/07/28 08:56:06 wolff
- * - Fixed crash when sx_firmware run twice.
- * - Added sx_slowpoll as a module parameter (I guess nobody really wanted
- * to change it from the default... )
- * - Fixed a stupid editing problem I introduced in 1.22.
- * - Fixed dropping characters on a termios change.
- *
- * Revision 1.22 1999/07/26 21:01:43 wolff
- * Russell Brown noticed that I had overlooked 4 out of six modem control
- * signals in sx_getsignals. Ooops.
- *
- * Revision 1.21 1999/07/23 09:11:33 wolff
- * I forgot to free dynamically allocated memory when the driver is unloaded.
- *
- * Revision 1.20 1999/07/20 06:25:26 wolff
- * The "closing wait" wasn't honoured. Thanks to James Griffiths for
- * reporting this.
- *
- * Revision 1.19 1999/07/11 08:59:59 wolff
- * Fixed an oops in close, when an open was pending. Changed the memtest
- * a bit. Should also test the board in word-mode, however my card fails the
- * memtest then. I still have to figure out what is wrong...
- *
- * Revision 1.18 1999/06/10 09:38:42 wolff
- * Changed the format of the firmware revision from %04x to %x.%02x .
- *
- * Revision 1.17 1999/06/04 09:44:35 wolff
- * fixed problem: reference to pci stuff when config_pci was off...
- * Thanks to Jorge Novo for noticing this.
- *
- * Revision 1.16 1999/06/02 08:30:15 wolff
- * added/removed the workaround for the DCD bug in the Firmware.
- * A bit more debugging code to locate that...
- *
- * Revision 1.15 1999/06/01 11:35:30 wolff
- * when DCD is left low (floating?), on TA's the firmware first tells us
- * that DCD is high, but after a short while suddenly comes to the
- * conclusion that it is low. All this would be fine, if it weren't that
- * Unix requires us to send a "hangup" signal in that case. This usually
- * all happens BEFORE the program has had a chance to ioctl the device
- * into clocal mode..
- *
- * Revision 1.14 1999/05/25 11:18:59 wolff
- * Added PCI-fix.
- * Added checks for return code of sx_sendcommand.
- * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...)
- *
- * Revision 1.13 1999/04/29 15:18:01 wolff
- * Fixed an "oops" that showed on SuSE 6.0 systems.
- * Activate DTR again after stty 0.
- *
- * Revision 1.12 1999/04/29 07:49:52 wolff
- * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming
- * the connection would be dropped anyway. That is not always the case,
- * and confuses people).
- * Told the card to always monitor the modem signals.
- * Added support for dynamic gs_debug adjustments.
- * Now tells the rest of the system the number of ports.
- *
- * Revision 1.11 1999/04/24 11:11:30 wolff
- * Fixed two stupid typos in the memory test.
- *
- * Revision 1.10 1999/04/24 10:53:39 wolff
- * Added some of Christian's suggestions.
- * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the
- * card to send the signal to the process.....)
- *
- * Revision 1.9 1999/04/23 07:26:38 wolff
- * Included Christian Lademann's 2.0 compile-warning fixes and interrupt
- * assignment redesign.
- * Cleanup of some other stuff.
- *
- * Revision 1.8 1999/04/16 13:05:30 wolff
- * fixed a DCD change unnoticed bug.
- *
- * Revision 1.7 1999/04/14 22:19:51 wolff
- * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!)
- *
- * Revision 1.6 1999/04/13 18:40:20 wolff
- * changed misc-minor to 161, as assigned by HPA.
- *
- * Revision 1.5 1999/04/13 15:12:25 wolff
- * Fixed use-count leak when "hangup" occurred.
- * Added workaround for a stupid-PCIBIOS bug.
- *
- *
- * Revision 1.4 1999/04/01 22:47:40 wolff
- * Fixed < 1M linux-2.0 problem.
- * (vremap isn't compatible with ioremap in that case)
- *
- * Revision 1.3 1999/03/31 13:45:45 wolff
- * Firmware loading is now done through a separate IOCTL.
- *
- * Revision 1.2 1999/03/28 12:22:29 wolff
- * rcs cleanup
- *
- * Revision 1.1 1999/03/28 12:10:34 wolff
- * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS).
- *
- * Revision 0.12 1999/03/28 09:20:10 wolff
- * Fixed problem in 0.11, continueing cleanup.
- *
- * Revision 0.11 1999/03/28 08:46:44 wolff
- * cleanup. Not good.
- *
- * Revision 0.10 1999/03/28 08:09:43 wolff
- * Fixed loosing characters on close.
- *
- * Revision 0.9 1999/03/21 22:52:01 wolff
- * Ported back to 2.2.... (minor things)
- *
- * Revision 0.8 1999/03/21 22:40:33 wolff
- * Port to 2.0
- *
- * Revision 0.7 1999/03/21 19:06:34 wolff
- * Fixed hangup processing.
- *
- * Revision 0.6 1999/02/05 08:45:14 wolff
- * fixed real_raw problems. Inclusion into kernel imminent.
- *
- * Revision 0.5 1998/12/21 23:51:06 wolff
- * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it
- * shouldn't have. THATs why I want to have transmit interrupts even when
- * the buffer is empty.
- *
- * Revision 0.4 1998/12/17 09:34:46 wolff
- * PPP works. ioctl works. Basically works!
- *
- * Revision 0.3 1998/12/15 13:05:18 wolff
- * It works! Wow! Gotta start implementing IOCTL and stuff....
- *
- * Revision 0.2 1998/12/01 08:33:53 wolff
- * moved over to 2.1.130
- *
- * Revision 0.1 1998/11/03 21:23:51 wolff
- * Initial revision. Detects SX card.
- *
- * */
-
-#define SX_VERSION 1.33
-
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/eisa.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-/* The 3.0.0 version of sxboards/sxwindow.h uses BYTE and WORD.... */
-#define BYTE u8
-#define WORD u16
-
-/* .... but the 3.0.4 version uses _u8 and _u16. */
-#define _u8 u8
-#define _u16 u16
-
-#include "sxboards.h"
-#include "sxwindow.h"
-
-#include <linux/generic_serial.h>
-#include "sx.h"
-
-/* I don't think that this driver can handle more than 256 ports on
- one machine. You'll have to increase the number of boards in sx.h
- if you want more than 4 boards. */
-
-#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) */
-
-/* Am I paranoid or not ? ;-) */
-#undef SX_PARANOIA_CHECK
-
-/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
- Hz, but it is user configurable. I don't recommend going above 1000
- Hz. The interrupt ratelimit might trigger if the interrupt is
- shared with a very active other device. */
-#define IRQ_RATE_LIMIT 20
-
-/* Sharing interrupts is possible now. If the other device wants more
- than 2000 interrupts per second, we'd gracefully decline further
- interrupts. That's not what we want. On the other hand, if the
- other device interrupts 2000 times a second, don't use the SX
- interrupt. Use polling. */
-#undef IRQ_RATE_LIMIT
-
-#if 0
-/* Not implemented */
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#define SX_REPORT_FIFO
-#define SX_REPORT_OVERRUN
-#endif
-
-/* Function prototypes */
-static void sx_disable_tx_interrupts(void *ptr);
-static void sx_enable_tx_interrupts(void *ptr);
-static void sx_disable_rx_interrupts(void *ptr);
-static void sx_enable_rx_interrupts(void *ptr);
-static int sx_carrier_raised(struct tty_port *port);
-static void sx_shutdown_port(void *ptr);
-static int sx_set_real_termios(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 long sx_fw_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg);
-static int sx_init_drivers(void);
-
-static struct tty_driver *sx_driver;
-
-static DEFINE_MUTEX(sx_boards_lock);
-static struct sx_board boards[SX_NBOARDS];
-static struct sx_port *sx_ports;
-static int sx_initialized;
-static int sx_nports;
-static int sx_debug;
-
-/* You can have the driver poll your card.
- - Set sx_poll to 1 to poll every timer tick (10ms on Intel).
- This is used when the card cannot use an interrupt for some reason.
-
- - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If
- the driver misses an interrupt (report this if it DOES happen to you!)
- everything will continue to work....
- */
-static int sx_poll = 1;
-static int sx_slowpoll;
-
-/* The card limits the number of interrupts per second.
- At 115k2 "100" should be sufficient.
- If you're using higher baudrates, you can increase this...
- */
-
-static int sx_maxints = 100;
-
-#ifdef CONFIG_ISA
-
-/* These are the only open spaces in my computer. Yours may have more
- or less.... -- REW
- duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
-*/
-static int sx_probe_addrs[] = {
- 0xc0000, 0xd0000, 0xe0000,
- 0xc8000, 0xd8000, 0xe8000
-};
-static int si_probe_addrs[] = {
- 0xc0000, 0xd0000, 0xe0000,
- 0xc8000, 0xd8000, 0xe8000, 0xa0000
-};
-static int si1_probe_addrs[] = {
- 0xd0000
-};
-
-#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
-#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
-#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
-
-module_param_array(sx_probe_addrs, int, NULL, 0);
-module_param_array(si_probe_addrs, int, NULL, 0);
-#endif
-
-/* Set the mask to all-ones. This alas, only supports 32 interrupts.
- Some architectures may need more. */
-static int sx_irqmask = -1;
-
-module_param(sx_poll, int, 0);
-module_param(sx_slowpoll, int, 0);
-module_param(sx_maxints, int, 0);
-module_param(sx_debug, int, 0);
-module_param(sx_irqmask, int, 0);
-
-MODULE_LICENSE("GPL");
-
-static struct real_driver sx_real_driver = {
- sx_disable_tx_interrupts,
- sx_enable_tx_interrupts,
- sx_disable_rx_interrupts,
- sx_enable_rx_interrupts,
- sx_shutdown_port,
- sx_set_real_termios,
- sx_chars_in_buffer,
- sx_close,
-};
-
-/*
- This driver can spew a whole lot of debugging output at you. If you
- need maximum performance, you should disable the DEBUG define. To
- aid in debugging in the field, I'm leaving the compile-time debug
- features enabled, and disable them "runtime". That allows me to
- instruct people with problems to enable debugging without requiring
- them to recompile...
-*/
-#define DEBUG
-
-#ifdef DEBUG
-#define sx_dprintk(f, str...) if (sx_debug & f) printk (str)
-#else
-#define sx_dprintk(f, str...) /* nothing */
-#endif
-
-#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
-#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__func__)
-
-#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
- __func__, port->line)
-
-/*
- * Firmware loader driver specific routines
- *
- */
-
-static const struct file_operations sx_fw_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = sx_fw_ioctl,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice sx_fw_device = {
- SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
-};
-
-#ifdef SX_PARANOIA_CHECK
-
-/* This doesn't work. Who's paranoid around here? Not me! */
-
-static inline int sx_paranoia_check(struct sx_port const *port,
- char *name, const char *routine)
-{
- static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
- "number for device %s in %s\n";
- static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
- "device %s in %s\n";
-
- if (!port) {
- printk(badinfo, name, routine);
- return 1;
- }
- if (port->magic != SX_MAGIC) {
- printk(badmagic, name, routine);
- return 1;
- }
-
- return 0;
-}
-#else
-#define sx_paranoia_check(a,b,c) 0
-#endif
-
-/* The timeouts. First try 30 times as fast as possible. Then give
- the card some time to breathe between accesses. (Otherwise the
- processor on the card might not be able to access its OWN bus... */
-
-#define TIMEOUT_1 30
-#define TIMEOUT_2 1000000
-
-#ifdef DEBUG
-static void my_hd_io(void __iomem *p, int len)
-{
- int i, j, ch;
- unsigned char __iomem *addr = p;
-
- for (i = 0; i < len; i += 16) {
- printk("%p ", addr + i);
- for (j = 0; j < 16; j++) {
- printk("%02x %s", readb(addr + j + i),
- (j == 7) ? " " : "");
- }
- for (j = 0; j < 16; j++) {
- ch = readb(addr + j + i);
- printk("%c", (ch < 0x20) ? '.' :
- ((ch > 0x7f) ? '.' : ch));
- }
- printk("\n");
- }
-}
-static void my_hd(void *p, int len)
-{
- int i, j, ch;
- unsigned char *addr = p;
-
- for (i = 0; i < len; i += 16) {
- printk("%p ", 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. */
-
-static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
-{
- writeb(byte, board->base + offset);
-}
-
-static inline u8 read_sx_byte(struct sx_board *board, int offset)
-{
- return readb(board->base + offset);
-}
-
-static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
-{
- writew(word, board->base + offset);
-}
-
-static inline u16 read_sx_word(struct sx_board *board, int offset)
-{
- return readw(board->base + offset);
-}
-
-static int sx_busy_wait_eq(struct sx_board *board,
- int offset, int mask, int correctval)
-{
- int i;
-
- func_enter();
-
- for (i = 0; i < TIMEOUT_1; i++)
- if ((read_sx_byte(board, offset) & mask) == correctval) {
- func_exit();
- return 1;
- }
-
- for (i = 0; i < TIMEOUT_2; i++) {
- if ((read_sx_byte(board, offset) & mask) == correctval) {
- func_exit();
- return 1;
- }
- udelay(1);
- }
-
- func_exit();
- return 0;
-}
-
-static int sx_busy_wait_neq(struct sx_board *board,
- int offset, int mask, int badval)
-{
- int i;
-
- func_enter();
-
- for (i = 0; i < TIMEOUT_1; i++)
- if ((read_sx_byte(board, offset) & mask) != badval) {
- func_exit();
- return 1;
- }
-
- for (i = 0; i < TIMEOUT_2; i++) {
- if ((read_sx_byte(board, offset) & mask) != badval) {
- func_exit();
- return 1;
- }
- udelay(1);
- }
-
- func_exit();
- return 0;
-}
-
-/* 5.6.4 of 6210028 r2.3 */
-static int sx_reset(struct sx_board *board)
-{
- func_enter();
-
- if (IS_SX_BOARD(board)) {
-
- write_sx_byte(board, SX_CONFIG, 0);
- write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
-
- if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
- 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 if (IS_SI1_BOARD(board)) {
- write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/
- } else {
- /* Gory details of the SI/ISA board */
- write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
- write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
- write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
- write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
- write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
- write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
- }
-
- func_exit();
- return 1;
-}
-
-/* This doesn't work on machines where "NULL" isn't 0 */
-/* If you have one of those, someone will need to write
- the equivalent of this, which will amount to about 3 lines. I don't
- want to complicate this right now. -- REW
- (See, I do write comments every now and then :-) */
-#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem))
-
-#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))
-#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem))
-#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem))
-
-#define sx_write_channel_byte(port, elem, val) \
- write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
-
-#define sx_read_channel_byte(port, elem) \
- read_sx_byte (port->board, CHAN_OFFSET (port, elem))
-
-#define sx_write_channel_word(port, elem, val) \
- write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
-
-#define sx_read_channel_word(port, elem) \
- read_sx_word (port->board, CHAN_OFFSET (port, elem))
-
-#define sx_write_module_byte(board, addr, elem, val) \
- write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
-
-#define sx_read_module_byte(board, addr, elem) \
- read_sx_byte (board, MODU_OFFSET (board, addr, elem))
-
-#define sx_write_module_word(board, addr, elem, val) \
- write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
-
-#define sx_read_module_word(board, addr, elem) \
- read_sx_word (board, MODU_OFFSET (board, addr, elem))
-
-#define sx_write_board_byte(board, elem, val) \
- write_sx_byte (board, BRD_OFFSET (board, elem), val)
-
-#define sx_read_board_byte(board, elem) \
- read_sx_byte (board, BRD_OFFSET (board, elem))
-
-#define sx_write_board_word(board, elem, val) \
- write_sx_word (board, BRD_OFFSET (board, elem), val)
-
-#define sx_read_board_word(board, elem) \
- read_sx_word (board, BRD_OFFSET (board, elem))
-
-static 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 if (IS_SI1_BOARD(board)) {
- write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
- write_sx_byte(board, SI1_ISA_INTCL, 0);
- } else {
- /* Don't bug me about the clear_set.
- I haven't the foggiest idea what it's about -- REW */
- write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
- write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
- }
- return 1;
-}
-
-#define SX_IRQ_REG_VAL(board) \
- ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
-
-/* Note. The SX register is write-only. Therefore, we have to enable the
- bus too. This is a no-op, if you don't mess with this driver... */
-static int sx_start_interrupts(struct sx_board *board)
-{
-
- /* Don't call this with board->irq == 0 */
-
- if (IS_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 if (IS_SI1_BOARD(board)) {
- write_sx_byte(board, SI1_ISA_INTCL, 0);
- write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
- } else {
- switch (board->irq) {
- case 11:
- write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
- break;
- case 12:
- write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
- break;
- case 15:
- write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
- break;
- default:
- printk(KERN_INFO "sx: SI/XIO card doesn't support "
- "interrupt %d.\n", board->irq);
- return 0;
- }
- write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
- }
-
- return 1;
-}
-
-static int sx_send_command(struct sx_port *port,
- int command, int mask, int newstat)
-{
- func_enter2();
- write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
- func_exit();
- return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
- newstat);
-}
-
-static char *mod_type_s(int module_type)
-{
- switch (module_type) {
- case TA4:
- return "TA4";
- case TA8:
- return "TA8";
- case TA4_ASIC:
- return "TA4_ASIC";
- case TA8_ASIC:
- return "TA8_ASIC";
- case MTA_CD1400:
- return "MTA_CD1400";
- case SXDC:
- return "SXDC";
- default:
- return "Unknown/invalid";
- }
-}
-
-static char *pan_type_s(int pan_type)
-{
- switch (pan_type) {
- case MOD_RS232DB25:
- return "MOD_RS232DB25";
- case MOD_RS232RJ45:
- return "MOD_RS232RJ45";
- case MOD_RS422DB25:
- return "MOD_RS422DB25";
- case MOD_PARALLEL:
- return "MOD_PARALLEL";
- case MOD_2_RS232DB25:
- return "MOD_2_RS232DB25";
- case MOD_2_RS232RJ45:
- return "MOD_2_RS232RJ45";
- case MOD_2_RS422DB25:
- return "MOD_2_RS422DB25";
- case MOD_RS232DB25MALE:
- return "MOD_RS232DB25MALE";
- case MOD_2_PARALLEL:
- return "MOD_2_PARALLEL";
- case MOD_BLANK:
- return "empty";
- default:
- return "invalid";
- }
-}
-
-static 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)
-{
- int t;
- func_enter2();
-
- t = sx_read_channel_byte(port, hi_op);
- if (dtr >= 0)
- t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
- if (rts >= 0)
- t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
- sx_write_channel_byte(port, hi_op, t);
- sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
-
- func_exit();
-}
-
-static int sx_getsignals(struct sx_port *port)
-{
- int i_stat, o_stat;
-
- o_stat = sx_read_channel_byte(port, hi_op);
- i_stat = sx_read_channel_byte(port, hi_ip);
-
- sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) "
- "%02x/%02x\n",
- (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
- port->c_dcd, tty_port_carrier_raised(&port->gs.port),
- sx_read_channel_byte(port, hi_ip),
- sx_read_channel_byte(port, hi_state));
-
- return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
- ((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
- ((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
- ((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
- ((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
- ((i_stat & IP_RI) ? TIOCM_RNG : 0));
-}
-
-static void sx_set_baud(struct sx_port *port)
-{
- int t;
-
- if (port->board->ta_type == MOD_SXDC) {
- switch (port->gs.baud) {
- /* Save some typing work... */
-#define e(x) case x: t = BAUD_ ## x; break
- e(50);
- e(75);
- e(110);
- e(150);
- e(200);
- e(300);
- e(600);
- e(1200);
- e(1800);
- e(2000);
- e(2400);
- e(4800);
- e(7200);
- e(9600);
- e(14400);
- e(19200);
- e(28800);
- e(38400);
- e(56000);
- e(57600);
- e(64000);
- e(76800);
- e(115200);
- e(128000);
- e(150000);
- e(230400);
- e(256000);
- e(460800);
- e(921600);
- case 134:
- t = BAUD_134_5;
- break;
- case 0:
- t = -1;
- break;
- default:
- /* Can I return "invalid"? */
- t = BAUD_9600;
- printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
- port->gs.baud);
- break;
- }
-#undef e
- if (t > 0) {
-/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
- sx_setsignals(port, 1, -1);
- /* XXX This is not TA & MTA compatible */
- sx_write_channel_byte(port, hi_csr, 0xff);
-
- sx_write_channel_byte(port, hi_txbaud, t);
- sx_write_channel_byte(port, hi_rxbaud, t);
- } else {
- sx_setsignals(port, 0, -1);
- }
- } else {
- switch (port->gs.baud) {
-#define e(x) case x: t = CSR_ ## x; break
- e(75);
- e(150);
- e(300);
- e(600);
- e(1200);
- e(2400);
- e(4800);
- e(1800);
- e(9600);
- e(19200);
- e(57600);
- e(38400);
-/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
- case 110:
- if (port->board->ta_type == MOD_TA) {
- t = CSR_110;
- break;
- } else {
- t = CSR_9600;
- printk(KERN_INFO "sx: Unsupported baud rate: "
- "%d.\n", port->gs.baud);
- break;
- }
- case 115200:
- if (port->board->ta_type == MOD_TA) {
- t = CSR_9600;
- printk(KERN_INFO "sx: Unsupported baud rate: "
- "%d.\n", port->gs.baud);
- break;
- } else {
- t = CSR_110;
- break;
- }
- case 0:
- t = -1;
- break;
- default:
- t = CSR_9600;
- printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
- port->gs.baud);
- break;
- }
-#undef e
- if (t >= 0) {
- sx_setsignals(port, 1, -1);
- sx_write_channel_byte(port, hi_csr, t * 0x11);
- } else {
- sx_setsignals(port, 0, -1);
- }
- }
-}
-
-/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
- better. -- REW */
-
-static int sx_set_real_termios(void *ptr)
-{
- struct sx_port *port = ptr;
-
- func_enter2();
-
- if (!port->gs.port.tty)
- return 0;
-
- /* What is this doing here? -- REW
- Ha! figured it out. It is to allow you to get DTR active again
- if you've dropped it with stty 0. Moved to set_baud, where it
- belongs (next to the drop dtr if baud == 0) -- REW */
- /* sx_setsignals (port, 1, -1); */
-
- sx_set_baud(port);
-
-#define CFLAG port->gs.port.tty->termios->c_cflag
- sx_write_channel_byte(port, hi_mr1,
- (C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) |
- (C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) |
- (C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) |
- (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
- (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
- (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
- (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
-
- sx_write_channel_byte(port, hi_mr2,
- (C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) |
- (C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP :
- MR2_1_STOP));
-
- switch (CFLAG & CSIZE) {
- case CS8:
- sx_write_channel_byte(port, hi_mask, 0xff);
- break;
- case CS7:
- sx_write_channel_byte(port, hi_mask, 0x7f);
- break;
- case CS6:
- sx_write_channel_byte(port, hi_mask, 0x3f);
- break;
- case CS5:
- sx_write_channel_byte(port, hi_mask, 0x1f);
- break;
- default:
- printk(KERN_INFO "sx: Invalid wordsize: %u\n",
- (unsigned int)CFLAG & CSIZE);
- break;
- }
-
- sx_write_channel_byte(port, hi_prtcl,
- (I_IXON(port->gs.port.tty) ? SP_TXEN : 0) |
- (I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) |
- (I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN);
-
- sx_write_channel_byte(port, hi_break,
- (I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 |
- I_BRKINT(port->gs.port.tty) ? BR_INT : 0));
-
- sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty));
- sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty));
- sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty));
- sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty));
-
- sx_reconfigure_port(port);
-
- /* Tell line discipline whether we will do input cooking */
- if (I_OTHER(port->gs.port.tty)) {
- clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
- } else {
- set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
- }
- sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
- (unsigned int)port->gs.port.tty->termios->c_iflag,
- I_OTHER(port->gs.port.tty));
-
-/* Tell line discipline whether we will do output cooking.
- * If OPOST is set and no other output flags are set then we can do output
- * processing. Even if only *one* other flag in the O_OTHER group is set
- * we do cooking in software.
- */
- if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) {
- set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
- } else {
- clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
- }
- sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
- (unsigned int)port->gs.port.tty->termios->c_oflag,
- O_OTHER(port->gs.port.tty));
- /* port->c_dcd = sx_get_CD (port); */
- func_exit();
- return 0;
-}
-
-/* ********************************************************************** *
- * the interrupt related routines *
- * ********************************************************************** */
-
-/* Note:
- Other drivers use the macro "MIN" to calculate how much to copy.
- This has the disadvantage that it will evaluate parts twice. That's
- expensive when it's IO (and the compiler cannot optimize those away!).
- Moreover, I'm not sure that you're race-free.
-
- I assign a value, and then only allow the value to decrease. This
- is always safe. This makes the code a few lines longer, and you
- know I'm dead against that, but I think it is required in this
- case. */
-
-static void sx_transmit_chars(struct sx_port *port)
-{
- int c;
- int tx_ip;
- int txroom;
-
- func_enter2();
- sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
- port, port->gs.xmit_cnt);
-
- if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
- return;
- }
-
- while (1) {
- c = port->gs.xmit_cnt;
-
- sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
- tx_ip = sx_read_channel_byte(port, hi_txipos);
-
- /* Took me 5 minutes to deduce this formula.
- Luckily it is literally in the manual in section 6.5.4.3.5 */
- txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
- 0xff;
-
- /* Don't copy more bytes than there is room for in the buffer */
- if (c > txroom)
- c = txroom;
- sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
-
- /* Don't copy past the end of the hardware transmit buffer */
- if (c > 0x100 - tx_ip)
- c = 0x100 - tx_ip;
-
- sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
-
- /* 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;
-
- sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
- c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
-
- /* If for one reason or another, we can't copy more data, we're
- done! */
- if (c == 0)
- break;
-
- memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
- tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
-
- /* Update the pointer in the card */
- sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
-
- /* Update the kernel buffer end */
- port->gs.xmit_tail = (port->gs.xmit_tail + c) &
- (SERIAL_XMIT_SIZE - 1);
-
- /* This one last. (this is essential)
- It would allow others to start putting more data into the
- buffer! */
- port->gs.xmit_cnt -= c;
- }
-
- if (port->gs.xmit_cnt == 0) {
- sx_disable_tx_interrupts(port);
- }
-
- if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
- tty_wakeup(port->gs.port.tty);
- sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
- port->gs.wakeup_chars);
- }
-
- clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
- func_exit();
-}
-
-/* Note the symmetry between receiving chars and transmitting them!
- Note: The kernel should have implemented both a receive buffer and
- a transmit buffer. */
-
-/* Inlined: Called only once. Remove the in