aboutsummaryrefslogtreecommitdiff
path: root/drivers/char/cyclades.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/cyclades.c')
-rw-r--r--drivers/char/cyclades.c5540
1 files changed, 5540 insertions, 0 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
new file mode 100644
index 00000000000..6a5337bf093
--- /dev/null
+++ b/drivers/char/cyclades.c
@@ -0,0 +1,5540 @@
+#undef BLOCKMOVE
+#define Z_WAKE
+#undef Z_EXT_CHARS_IN_BUFFER
+static char rcsid[] =
+"$Revision: 2.3.2.20 $$Date: 2004/02/25 18:14:16 $";
+
+/*
+ * linux/drivers/char/cyclades.c
+ *
+ * This file contains the driver for the Cyclades async multiport
+ * serial boards.
+ *
+ * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
+ * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
+ * Currently maintained by Cyclades team <async@cyclades.com>.
+ *
+ * For Technical support and installation problems, please send e-mail
+ * to support@cyclades.com.
+ *
+ * Much of the design and some of the code came from serial.c
+ * which was copyright (C) 1991, 1992 Linus Torvalds. It was
+ * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
+ * and then fixed as suggested by Michael K. Johnson 12/12/92.
+ *
+ * This version supports shared IRQ's (only for PCI boards).
+ *
+ * $Log: cyclades.c,v $
+ * Prevent users from opening non-existing Z ports.
+ *
+ * Revision 2.3.2.8 2000/07/06 18:14:16 ivan
+ * Fixed the PCI detection function to work properly on Alpha systems.
+ * Implemented support for TIOCSERGETLSR ioctl.
+ * Implemented full support for non-standard baud rates.
+ *
+ * Revision 2.3.2.7 2000/06/01 18:26:34 ivan
+ * Request PLX I/O region, although driver doesn't use it, to avoid
+ * problems with other drivers accessing it.
+ * Removed count for on-board buffer characters in cy_chars_in_buffer
+ * (Cyclades-Z only).
+ *
+ * Revision 2.3.2.6 2000/05/05 13:56:05 ivan
+ * Driver now reports physical instead of virtual memory addresses.
+ * Masks were added to some Cyclades-Z read accesses.
+ * Implemented workaround for PLX9050 bug that would cause a system lockup
+ * in certain systems, depending on the MMIO addresses allocated to the
+ * board.
+ * Changed the Tx interrupt programming in the CD1400 chips to boost up
+ * performance (Cyclom-Y only).
+ * Code is now compliant with the new module interface (module_[init|exit]).
+ * Make use of the PCI helper functions to access PCI resources.
+ * Did some code "housekeeping".
+ *
+ * Revision 2.3.2.5 2000/01/19 14:35:33 ivan
+ * Fixed bug in cy_set_termios on CRTSCTS flag turnoff.
+ *
+ * Revision 2.3.2.4 2000/01/17 09:19:40 ivan
+ * Fixed SMP locking in Cyclom-Y interrupt handler.
+ *
+ * Revision 2.3.2.3 1999/12/28 12:11:39 ivan
+ * Added a new cyclades_card field called nports to allow the driver to
+ * know the exact number of ports found by the Z firmware after its load;
+ * RX buffer contention prevention logic on interrupt op mode revisited
+ * (Cyclades-Z only);
+ * Revisited printk's for Z debug;
+ * Driver now makes sure that the constant SERIAL_XMIT_SIZE is defined;
+ *
+ * Revision 2.3.2.2 1999/10/01 11:27:43 ivan
+ * Fixed bug in cyz_poll that would make all ports but port 0
+ * unable to transmit/receive data (Cyclades-Z only);
+ * Implemented logic to prevent the RX buffer from being stuck with data
+ * due to a driver / firmware race condition in interrupt op mode
+ * (Cyclades-Z only);
+ * Fixed bug in block_til_ready logic that would lead to a system crash;
+ * Revisited cy_close spinlock usage;
+ *
+ * Revision 2.3.2.1 1999/09/28 11:01:22 ivan
+ * Revisited CONFIG_PCI conditional compilation for PCI board support;
+ * Implemented TIOCGICOUNT and TIOCMIWAIT ioctl support;
+ * _Major_ cleanup on the Cyclades-Z interrupt support code / logic;
+ * Removed CTS handling from the driver -- this is now completely handled
+ * by the firmware (Cyclades-Z only);
+ * Flush RX on-board buffers on a port open (Cyclades-Z only);
+ * Fixed handling of ASYNC_SPD_* TTY flags;
+ * Module unload now unmaps all memory area allocated by ioremap;
+ *
+ * Revision 2.3.1.1 1999/07/15 16:45:53 ivan
+ * Removed CY_PROC conditional compilation;
+ * Implemented SMP-awareness for the driver;
+ * Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off]
+ * functions;
+ * The driver now accepts memory addresses (maddr=0xMMMMM) and IRQs
+ * (irq=NN) as parameters (only for ISA boards);
+ * Fixed bug in set_line_char that would prevent the Cyclades-Z
+ * ports from being configured at speeds above 115.2Kbps;
+ * Fixed bug in cy_set_termios that would prevent XON/XOFF flow control
+ * switching from working properly;
+ * The driver now only prints IRQ info for the Cyclades-Z if it's
+ * configured to work in interrupt mode;
+ *
+ * Revision 2.2.2.3 1999/06/28 11:13:29 ivan
+ * Added support for interrupt mode operation for the Z cards;
+ * Removed the driver inactivity control for the Z;
+ * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when
+ * the Z firmware is not loaded yet;
+ * Replaced the "manual" Z Tx flush buffer by a call to a FW command of
+ * same functionality;
+ * Implemented workaround for IRQ setting loss on the PCI configuration
+ * registers after a PCI bridge EEPROM reload (affects PLX9060 only);
+ *
+ * Revision 2.2.2.2 1999/05/14 17:18:15 ivan
+ * /proc entry location changed to /proc/tty/driver/cyclades;
+ * Added support to shared IRQ's (only for PCI boards);
+ * Added support for Cobalt Qube2 systems;
+ * IRQ [de]allocation scheme revisited;
+ * BREAK implementation changed in order to make use of the 'break_ctl'
+ * TTY facility;
+ * Fixed typo in TTY structure field 'driver_name';
+ * Included a PCI bridge reset and EEPROM reload in the board
+ * initialization code (for both Y and Z series).
+ *
+ * Revision 2.2.2.1 1999/04/08 16:17:43 ivan
+ * Fixed a bug in cy_wait_until_sent that was preventing the port to be
+ * closed properly after a SIGINT;
+ * Module usage counter scheme revisited;
+ * Added support to the upcoming Y PCI boards (i.e., support to additional
+ * PCI Device ID's).
+ *
+ * Revision 2.2.1.10 1999/01/20 16:14:29 ivan
+ * Removed all unnecessary page-alignement operations in ioremap calls
+ * (ioremap is currently safe for these operations).
+ *
+ * Revision 2.2.1.9 1998/12/30 18:18:30 ivan
+ * Changed access to PLX PCI bridge registers from I/O to MMIO, in
+ * order to make PLX9050-based boards work with certain motherboards.
+ *
+ * Revision 2.2.1.8 1998/11/13 12:46:20 ivan
+ * cy_close function now resets (correctly) the tty->closing flag;
+ * JIFFIES_DIFF macro fixed.
+ *
+ * Revision 2.2.1.7 1998/09/03 12:07:28 ivan
+ * Fixed bug in cy_close function, which was not informing HW of
+ * which port should have the reception disabled before doing so;
+ * fixed Cyclom-8YoP hardware detection bug.
+ *
+ * Revision 2.2.1.6 1998/08/20 17:15:39 ivan
+ * Fixed bug in cy_close function, which causes malfunction
+ * of one of the first 4 ports when a higher port is closed
+ * (Cyclom-Y only).
+ *
+ * Revision 2.2.1.5 1998/08/10 18:10:28 ivan
+ * Fixed Cyclom-4Yo hardware detection bug.
+ *
+ * Revision 2.2.1.4 1998/08/04 11:02:50 ivan
+ * /proc/cyclades implementation with great collaboration of
+ * Marc Lewis <marc@blarg.net>;
+ * cyy_interrupt was changed to avoid occurrence of kernel oopses
+ * during PPP operation.
+ *
+ * Revision 2.2.1.3 1998/06/01 12:09:10 ivan
+ * General code review in order to comply with 2.1 kernel standards;
+ * data loss prevention for slow devices revisited (cy_wait_until_sent
+ * was created);
+ * removed conditional compilation for new/old PCI structure support
+ * (now the driver only supports the new PCI structure).
+ *
+ * Revision 2.2.1.1 1998/03/19 16:43:12 ivan
+ * added conditional compilation for new/old PCI structure support;
+ * removed kernel series (2.0.x / 2.1.x) conditional compilation.
+ *
+ * Revision 2.1.1.3 1998/03/16 18:01:12 ivan
+ * cleaned up the data loss fix;
+ * fixed XON/XOFF handling once more (Cyclades-Z);
+ * general review of the driver routines;
+ * introduction of a mechanism to prevent data loss with slow
+ * printers, by forcing a delay before closing the port.
+ *
+ * Revision 2.1.1.2 1998/02/17 16:50:00 ivan
+ * fixed detection/handling of new CD1400 in Ye boards;
+ * fixed XON/XOFF handling (Cyclades-Z);
+ * fixed data loss caused by a premature port close;
+ * introduction of a flag that holds the CD1400 version ID per port
+ * (used by the CYGETCD1400VER new ioctl).
+ *
+ * Revision 2.1.1.1 1997/12/03 17:31:19 ivan
+ * Code review for the module cleanup routine;
+ * fixed RTS and DTR status report for new CD1400's in get_modem_info;
+ * includes anonymous changes regarding signal_pending.
+ *
+ * Revision 2.1 1997/11/01 17:42:41 ivan
+ * Changes in the driver to support Alpha systems (except 8Zo V_1);
+ * BREAK fix for the Cyclades-Z boards;
+ * driver inactivity control by FW implemented;
+ * introduction of flag that allows driver to take advantage of
+ * a special CD1400 feature related to HW flow control;
+ * added support for the CD1400 rev. J (Cyclom-Y boards);
+ * introduction of ioctls to:
+ * - control the rtsdtr_inv flag (Cyclom-Y);
+ * - control the rflow flag (Cyclom-Y);
+ * - adjust the polling interval (Cyclades-Z);
+ *
+ * Revision 1.36.4.33 1997/06/27 19:00:00 ivan
+ * Fixes related to kernel version conditional
+ * compilation.
+ *
+ * Revision 1.36.4.32 1997/06/14 19:30:00 ivan
+ * Compatibility issues between kernels 2.0.x and
+ * 2.1.x (mainly related to clear_bit function).
+ *
+ * Revision 1.36.4.31 1997/06/03 15:30:00 ivan
+ * Changes to define the memory window according to the
+ * board type.
+ *
+ * Revision 1.36.4.30 1997/05/16 15:30:00 daniel
+ * Changes to support new cycladesZ boards.
+ *
+ * Revision 1.36.4.29 1997/05/12 11:30:00 daniel
+ * Merge of Bentson's and Daniel's version 1.36.4.28.
+ * Corrects bug in cy_detect_pci: check if there are more
+ * ports than the number of static structs allocated.
+ * Warning message during initialization if this driver is
+ * used with the new generation of cycladesZ boards. Those
+ * will be supported only in next release of the driver.
+ * Corrects bug in cy_detect_pci and cy_detect_isa that
+ * returned wrong number of VALID boards, when a cyclomY
+ * was found with no serial modules connected.
+ * Changes to use current (2.1.x) kernel subroutine names
+ * and created macros for compilation with 2.0.x kernel,
+ * instead of the other way around.
+ *
+ * Revision 1.36.4.28 1997/05/?? ??:00:00 bentson
+ * Change queue_task_irq_off to queue_task_irq.
+ * The inline function queue_task_irq_off (tqueue.h)
+ * was removed from latest releases of 2.1.x kernel.
+ * Use of macro __init to mark the initialization
+ * routines, so memory can be reused.
+ * Also incorporate implementation of critical region
+ * in function cleanup_module() created by anonymous
+ * linuxer.
+ *
+ * Revision 1.36.4.28 1997/04/25 16:00:00 daniel
+ * Change to support new firmware that solves DCD problem:
+ * application could fail to receive SIGHUP signal when DCD
+ * varying too fast.
+ *
+ * Revision 1.36.4.27 1997/03/26 10:30:00 daniel
+ * Changed for support linux versions 2.1.X.
+ * Backward compatible with linux versions 2.0.X.
+ * Corrected illegal use of filler field in
+ * CH_CTRL struct.
+ * Deleted some debug messages.
+ *
+ * Revision 1.36.4.26 1997/02/27 12:00:00 daniel
+ * Included check for NULL tty pointer in cyz_poll.
+ *
+ * Revision 1.36.4.25 1997/02/26 16:28:30 bentson
+ * Bill Foster at Blarg! Online services noticed that
+ * some of the switch elements of -Z modem control
+ * lacked a closing "break;"
+ *
+ * Revision 1.36.4.24 1997/02/24 11:00:00 daniel
+ * Changed low water threshold for buffer xmit_buf
+ *
+ * Revision 1.36.4.23 1996/12/02 21:50:16 bentson
+ * Marcio provided fix to modem status fetch for -Z
+ *
+ * Revision 1.36.4.22 1996/10/28 22:41:17 bentson
+ * improve mapping of -Z control page (thanks to Steve
+ * Price <stevep@fa.tdktca.com> for help on this)
+ *
+ * Revision 1.36.4.21 1996/09/10 17:00:10 bentson
+ * shift from CPU-bound to memcopy in cyz_polling operation
+ *
+ * Revision 1.36.4.20 1996/09/09 18:30:32 Bentson
+ * Added support to set and report higher speeds.
+ *
+ * Revision 1.36.4.19c 1996/08/09 10:00:00 Marcio Saito
+ * Some fixes in the HW flow control for the BETA release.
+ * Don't try to register the IRQ.
+ *
+ * Revision 1.36.4.19 1996/08/08 16:23:18 Bentson
+ * make sure "cyc" appears in all kernel messages; all soft interrupts
+ * handled by same routine; recognize out-of-band reception; comment
+ * out some diagnostic messages; leave RTS/CTS flow control to hardware;
+ * fix race condition in -Z buffer management; only -Y needs to explictly
+ * flush chars; tidy up some startup messages;
+ *
+ * Revision 1.36.4.18 1996/07/25 18:57:31 bentson
+ * shift MOD_INC_USE_COUNT location to match
+ * serial.c; purge some diagnostic messages;
+ *
+ * Revision 1.36.4.17 1996/07/25 18:01:08 bentson
+ * enable modem status messages and fetch & process them; note
+ * time of last activity type for each port; set_line_char now
+ * supports more than line 0 and treats 0 baud correctly;
+ * get_modem_info senses rs_status;
+ *
+ * Revision 1.36.4.16 1996/07/20 08:43:15 bentson
+ * barely works--now's time to turn on
+ * more features 'til it breaks
+ *
+ * Revision 1.36.4.15 1996/07/19 22:30:06 bentson
+ * check more -Z board status; shorten boot message
+ *
+ * Revision 1.36.4.14 1996/07/19 22:20:37 bentson
+ * fix reference to ch_ctrl in startup; verify return
+ * values from cyz_issue_cmd and cyz_update_channel;
+ * more stuff to get modem control correct;
+ *
+ * Revision 1.36.4.13 1996/07/11 19:53:33 bentson
+ * more -Z stuff folded in; re-order changes to put -Z stuff
+ * after -Y stuff (to make changes clearer)
+ *
+ * Revision 1.36.4.12 1996/07/11 15:40:55 bentson
+ * Add code to poll Cyclades-Z. Add code to get & set RS-232 control.
+ * Add code to send break. Clear firmware ID word at startup (so
+ * that other code won't talk to inactive board).
+ *
+ * Revision 1.36.4.11 1996/07/09 05:28:29 bentson
+ * add code for -Z in set_line_char
+ *
+ * Revision 1.36.4.10 1996/07/08 19:28:37 bentson
+ * fold more -Z stuff (or in some cases, error messages)
+ * into driver; add text to "don't know what to do" messages.
+ *
+ * Revision 1.36.4.9 1996/07/08 18:38:38 bentson
+ * moved compile-time flags near top of file; cosmetic changes
+ * to narrow text (to allow 2-up printing); changed many declarations
+ * to "static" to limit external symbols; shuffled code order to
+ * coalesce -Y and -Z specific code, also to put internal functions
+ * in order of tty_driver structure; added code to recognize -Z
+ * ports (and for moment, do nothing or report error); add cy_startup
+ * to parse boot command line for extra base addresses for ISA probes;
+ *
+ * Revision 1.36.4.8 1996/06/25 17:40:19 bentson
+ * reorder some code, fix types of some vars (int vs. long),
+ * add cy_setup to support user declared ISA addresses
+ *
+ * Revision 1.36.4.7 1996/06/21 23:06:18 bentson
+ * dump ioctl based firmware load (it's now a user level
+ * program); ensure uninitialzed ports cannot be used
+ *
+ * Revision 1.36.4.6 1996/06/20 23:17:19 bentson
+ * rename vars and restructure some code
+ *
+ * Revision 1.36.4.5 1996/06/14 15:09:44 bentson
+ * get right status back after boot load
+ *
+ * Revision 1.36.4.4 1996/06/13 19:51:44 bentson
+ * successfully loads firmware
+ *
+ * Revision 1.36.4.3 1996/06/13 06:08:33 bentson
+ * add more of the code for the boot/load ioctls
+ *
+ * Revision 1.36.4.2 1996/06/11 21:00:51 bentson
+ * start to add Z functionality--starting with ioctl
+ * for loading firmware
+ *
+ * Revision 1.36.4.1 1996/06/10 18:03:02 bentson
+ * added code to recognize Z/PCI card at initialization; report
+ * presence, but card is not initialized (because firmware needs
+ * to be loaded)
+ *
+ * Revision 1.36.3.8 1996/06/07 16:29:00 bentson
+ * starting minor number at zero; added missing verify_area
+ * as noted by Heiko Eissfeldt <heiko@colossus.escape.de>
+ *
+ * Revision 1.36.3.7 1996/04/19 21:06:18 bentson
+ * remove unneeded boot message & fix CLOCAL hardware flow
+ * control (Miquel van Smoorenburg <miquels@Q.cistron.nl>);
+ * remove unused diagnostic statements; minor 0 is first;
+ *
+ * Revision 1.36.3.6 1996/03/13 13:21:17 marcio
+ * The kernel function vremap (available only in later 1.3.xx kernels)
+ * allows the access to memory addresses above the RAM. This revision
+ * of the driver supports PCI boards below 1Mb (device id 0x100) and
+ * above 1Mb (device id 0x101).
+ *
+ * Revision 1.36.3.5 1996/03/07 15:20:17 bentson
+ * Some global changes to interrupt handling spilled into
+ * this driver--mostly unused arguments in system function
+ * calls. Also added change by Marcio Saito which should
+ * reduce lost interrupts at startup by fast processors.
+ *
+ * Revision 1.36.3.4 1995/11/13 20:45:10 bentson
+ * Changes by Corey Minyard <minyard@wf-rch.cirr.com> distributed
+ * in 1.3.41 kernel to remove a possible race condition, extend
+ * some error messages, and let the driver run as a loadable module
+ * Change by Alan Wendt <alan@ez0.ezlink.com> to remove a
+ * possible race condition.
+ * Change by Marcio Saito <marcio@cyclades.com> to fix PCI addressing.
+ *
+ * Revision 1.36.3.3 1995/11/13 19:44:48 bentson
+ * Changes by Linus Torvalds in 1.3.33 kernel distribution
+ * required due to reordering of driver initialization.
+ * Drivers are now initialized *after* memory management.
+ *
+ * Revision 1.36.3.2 1995/09/08 22:07:14 bentson
+ * remove printk from ISR; fix typo
+ *
+ * Revision 1.36.3.1 1995/09/01 12:00:42 marcio
+ * Minor fixes in the PCI board support. PCI function calls in
+ * conditional compilation (CONFIG_PCI). Thanks to Jim Duncan
+ * <duncan@okay.com>. "bad serial count" message removed.
+ *
+ * Revision 1.36.3 1995/08/22 09:19:42 marcio
+ * Cyclom-Y/PCI support added. Changes in the cy_init routine and
+ * board initialization. Changes in the boot messages. The driver
+ * supports up to 4 boards and 64 ports by default.
+ *
+ * Revision 1.36.1.4 1995/03/29 06:14:14 bentson
+ * disambiguate between Cyclom-16Y and Cyclom-32Ye;
+ *
+ * Revision 1.36.1.3 1995/03/23 22:15:35 bentson
+ * add missing break in modem control block in ioctl switch statement
+ * (discovered by Michael Edward Chastain <mec@jobe.shell.portal.com>);
+ *
+ * Revision 1.36.1.2 1995/03/22 19:16:22 bentson
+ * make sure CTS flow control is set as soon as possible (thanks
+ * to note from David Lambert <lambert@chesapeake.rps.slb.com>);
+ *
+ * Revision 1.36.1.1 1995/03/13 15:44:43 bentson
+ * initialize defaults for receive threshold and stale data timeout;
+ * cosmetic changes;
+ *
+ * Revision 1.36 1995/03/10 23:33:53 bentson
+ * added support of chips 4-7 in 32 port Cyclom-Ye;
+ * fix cy_interrupt pointer dereference problem
+ * (Joe Portman <baron@aa.net>);
+ * give better error response if open is attempted on non-existent port
+ * (Zachariah Vaum <jchryslr@netcom.com>);
+ * correct command timeout (Kenneth Lerman <lerman@@seltd.newnet.com>);
+ * conditional compilation for -16Y on systems with fast, noisy bus;
+ * comment out diagnostic print function;
+ * cleaned up table of base addresses;
+ * set receiver time-out period register to correct value,
+ * set receive threshold to better default values,
+ * set chip timer to more accurate 200 Hz ticking,
+ * add code to monitor and modify receive parameters
+ * (Rik Faith <faith@cs.unc.edu> Nick Simicich
+ * <njs@scifi.emi.net>);
+ *
+ * Revision 1.35 1994/12/16 13:54:18 steffen
+ * additional patch by Marcio Saito for board detection
+ * Accidently left out in 1.34
+ *
+ * Revision 1.34 1994/12/10 12:37:12 steffen
+ * This is the corrected version as suggested by Marcio Saito
+ *
+ * Revision 1.33 1994/12/01 22:41:18 bentson
+ * add hooks to support more high speeds directly; add tytso
+ * patch regarding CLOCAL wakeups
+ *
+ * Revision 1.32 1994/11/23 19:50:04 bentson
+ * allow direct kernel control of higher signalling rates;
+ * look for cards at additional locations
+ *
+ * Revision 1.31 1994/11/16 04:33:28 bentson
+ * ANOTHER fix from Corey Minyard, minyard@wf-rch.cirr.com--
+ * a problem in chars_in_buffer has been resolved by some
+ * small changes; this should yield smoother output
+ *
+ * Revision 1.30 1994/11/16 04:28:05 bentson
+ * Fix from Corey Minyard, Internet: minyard@metronet.com,
+ * UUCP: minyard@wf-rch.cirr.com, WORK: minyardbnr.ca, to
+ * cy_hangup that appears to clear up much (all?) of the
+ * DTR glitches; also he's added/cleaned-up diagnostic messages
+ *
+ * Revision 1.29 1994/11/16 04:16:07 bentson
+ * add change proposed by Ralph Sims, ralphs@halcyon.com, to
+ * operate higher speeds in same way as other serial ports;
+ * add more serial ports (for up to two 16-port muxes).
+ *
+ * Revision 1.28 1994/11/04 00:13:16 root
+ * turn off diagnostic messages
+ *
+ * Revision 1.27 1994/11/03 23:46:37 root
+ * bunch of changes to bring driver into greater conformance
+ * with the serial.c driver (looking for missed fixes)
+ *
+ * Revision 1.26 1994/11/03 22:40:36 root
+ * automatic interrupt probing fixed.
+ *
+ * Revision 1.25 1994/11/03 20:17:02 root
+ * start to implement auto-irq
+ *
+ * Revision 1.24 1994/11/03 18:01:55 root
+ * still working on modem signals--trying not to drop DTR
+ * during the getty/login processes
+ *
+ * Revision 1.23 1994/11/03 17:51:36 root
+ * extend baud rate support; set receive threshold as function
+ * of baud rate; fix some problems with RTS/CTS;
+ *
+ * Revision 1.22 1994/11/02 18:05:35 root
+ * changed arguments to udelay to type long to get
+ * delays to be of correct duration
+ *
+ * Revision 1.21 1994/11/02 17:37:30 root
+ * employ udelay (after calibrating loops_per_second earlier
+ * in init/main.c) instead of using home-grown delay routines
+ *
+ * Revision 1.20 1994/11/02 03:11:38 root
+ * cy_chars_in_buffer forces a return value of 0 to let
+ * login work (don't know why it does); some functions
+ * that were returning EFAULT, now executes the code;
+ * more work on deciding when to disable xmit interrupts;
+ *
+ * Revision 1.19 1994/11/01 20:10:14 root
+ * define routine to start transmission interrupts (by enabling
+ * transmit interrupts); directly enable/disable modem interrupts;
+ *
+ * Revision 1.18 1994/11/01 18:40:45 bentson
+ * Don't always enable transmit interrupts in startup; interrupt on
+ * TxMpty instead of TxRdy to help characters get out before shutdown;
+ * restructure xmit interrupt to check for chars first and quit if
+ * none are ready to go; modem status (MXVRx) is upright, _not_ inverted
+ * (to my view);
+ *
+ * Revision 1.17 1994/10/30 04:39:45 bentson
+ * rename serial_driver and callout_driver to cy_serial_driver and
+ * cy_callout_driver to avoid linkage interference; initialize
+ * info->type to PORT_CIRRUS; ruggedize paranoia test; elide ->port
+ * from cyclades_port structure; add paranoia check to cy_close;
+ *
+ * Revision 1.16 1994/10/30 01:14:33 bentson
+ * change major numbers; add some _early_ return statements;
+ *
+ * Revision 1.15 1994/10/29 06:43:15 bentson
+ * final tidying up for clean compile; enable some error reporting
+ *
+ * Revision 1.14 1994/10/28 20:30:22 Bentson
+ * lots of changes to drag the driver towards the new tty_io
+ * structures and operation. not expected to work, but may
+ * compile cleanly.
+ *
+ * Revision 1.13 1994/07/21 23:08:57 Bentson
+ * add some diagnostic cruft; support 24 lines (for testing
+ * both -8Y and -16Y cards; be more thorough in servicing all
+ * chips during interrupt; add "volatile" a few places to
+ * circumvent compiler optimizations; fix base & offset
+ * computations in block_til_ready (was causing chip 0 to
+ * stop operation)
+ *
+ * Revision 1.12 1994/07/19 16:42:11 Bentson
+ * add some hackery for kernel version 1.1.8; expand
+ * error messages; refine timing for delay loops and
+ * declare loop params volatile
+ *
+ * Revision 1.11 1994/06/11 21:53:10 bentson
+ * get use of save_car right in transmit interrupt service
+ *
+ * Revision 1.10.1.1 1994/06/11 21:31:18 bentson
+ * add some diagnostic printing; try to fix save_car stuff
+ *
+ * Revision 1.10 1994/06/11 20:36:08 bentson
+ * clean up compiler warnings
+ *
+ * Revision 1.9 1994/06/11 19:42:46 bentson
+ * added a bunch of code to support modem signalling
+ *
+ * Revision 1.8 1994/06/11 17:57:07 bentson
+ * recognize break & parity error
+ *
+ * Revision 1.7 1994/06/05 05:51:34 bentson
+ * Reorder baud table to be monotonic; add cli to CP; discard
+ * incoming characters and status if the line isn't open; start to
+ * fold code into cy_throttle; start to port get_serial_info,
+ * set_serial_info, get_modem_info, set_modem_info, and send_break
+ * from serial.c; expand cy_ioctl; relocate and expand config_setup;
+ * get flow control characters from tty struct; invalidate ports w/o
+ * hardware;
+ *
+ * Revision 1.6 1994/05/31 18:42:21 bentson
+ * add a loop-breaker in the interrupt service routine;
+ * note when port is initialized so that it can be shut
+ * down under the right conditions; receive works without
+ * any obvious errors
+ *
+ * Revision 1.5 1994/05/30 00:55:02 bentson
+ * transmit works without obvious errors
+ *
+ * Revision 1.4 1994/05/27 18:46:27 bentson
+ * incorporated more code from lib_y.c; can now print short
+ * strings under interrupt control to port zero; seems to
+ * select ports/channels/lines correctly
+ *
+ * Revision 1.3 1994/05/25 22:12:44 bentson
+ * shifting from multi-port on a card to proper multiplexor
+ * data structures; added skeletons of most routines
+ *
+ * Revision 1.2 1994/05/19 13:21:43 bentson
+ * start to crib from other sources
+ *
+ */
+
+/* If you need to install more boards than NR_CARDS, change the constant
+ in the definition below. No other change is necessary to support up to
+ eight boards. Beyond that you'll have to extend cy_isa_addresses. */
+
+#define NR_CARDS 4
+
+/*
+ If the total number of ports is larger than NR_PORTS, change this
+ constant in the definition below. No other change is necessary to
+ support more boards/ports. */
+
+#define NR_PORTS 256
+
+#define ZE_V1_NPORTS 64
+#define ZO_V1 0
+#define ZO_V2 1
+#define ZE_V1 2
+
+#define SERIAL_PARANOIA_CHECK
+#undef CY_DEBUG_OPEN
+#undef CY_DEBUG_THROTTLE
+#undef CY_DEBUG_OTHER
+#undef CY_DEBUG_IO
+#undef CY_DEBUG_COUNT
+#undef CY_DEBUG_DTR
+#undef CY_DEBUG_WAIT_UNTIL_SENT
+#undef CY_DEBUG_INTERRUPTS
+#undef CY_16Y_HACK
+#undef CY_ENABLE_MONITORING
+#undef CY_PCI_DEBUG
+
+#if 0
+#define PAUSE __asm__("nop");
+#else
+#define PAUSE ;
+#endif
+
+/*
+ * Include section
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/cyclades.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define CY_LOCK(info,flags) \
+ do { \
+ spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \
+ } while (0)
+
+#define CY_UNLOCK(info,flags) \
+ do { \
+ spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \
+ } while (0)
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static void cy_throttle (struct tty_struct *tty);
+static void cy_send_xchar (struct tty_struct *tty, char ch);
+
+#define IS_CYC_Z(card) ((card).num_chips == -1)
+
+#define Z_FPGA_CHECK(card) \
+ ((cy_readl(&((struct RUNTIME_9060 __iomem *) \
+ ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
+
+#define ISZLOADED(card) (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \
+ ((card).ctl_addr))->mail_box_0)) || \
+ Z_FPGA_CHECK(card)) && \
+ (ZFIRM_ID==cy_readl(&((struct FIRM_ID __iomem *) \
+ ((card).base_addr+ID_ADDRESS))->signature)))
+
+#ifndef SERIAL_XMIT_SIZE
+#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096))
+#endif
+#define WAKEUP_CHARS 256
+
+#define STD_COM_FLAGS (0)
+
+#define JIFFIES_DIFF(n, j) ((j) - (n))
+
+static struct tty_driver *cy_serial_driver;
+
+#ifdef CONFIG_ISA
+/* This is the address lookup table. The driver will probe for
+ Cyclom-Y/ISA boards at all addresses in here. If you want the
+ driver to probe addresses at a different address, add it to
+ this table. If the driver is probing some other board and
+ causing problems, remove the offending address from this table.
+ The cy_setup function extracts additional addresses from the
+ boot options line. The form is "cyclades=address,address..."
+*/
+
+static unsigned int cy_isa_addresses[] = {
+ 0xD0000,
+ 0xD2000,
+ 0xD4000,
+ 0xD6000,
+ 0xD8000,
+ 0xDA000,
+ 0xDC000,
+ 0xDE000,
+ 0,0,0,0,0,0,0,0
+};
+#define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*))
+
+#ifdef MODULE
+static long maddr[NR_CARDS] = { 0, };
+static int irq[NR_CARDS] = { 0, };
+
+module_param_array(maddr, long, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+#endif
+
+#endif /* CONFIG_ISA */
+
+/* This is the per-card data structure containing address, irq, number of
+ channels, etc. This driver supports a maximum of NR_CARDS cards.
+*/
+static struct cyclades_card cy_card[NR_CARDS];
+
+/* This is the per-channel data structure containing pointers, flags
+ and variables for the port. This driver supports a maximum of NR_PORTS.
+*/
+static struct cyclades_port cy_port[NR_PORTS];
+
+static int cy_next_channel; /* next minor available */
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write. We need to
+ * lock it in case the copy_from_user blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open. This buffer is
+ * allocated when the first cy_open occurs.
+ */
+static unsigned char *tmp_buf;
+
+/*
+ * This is used to look up the divisor speeds and the timeouts
+ * We're normally limited to 15 distinct baud rates. The extra
+ * are accessed via settings in info->flags.
+ * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ * HI VHI
+ * 20
+ */
+static int baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+ 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000,
+ 230400, 0};
+
+static char baud_co_25[] = { /* 25 MHz clock option table */
+ /* value => 00 01 02 03 04 */
+ /* divide by 8 32 128 512 2048 */
+ 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
+ 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static char baud_bpr_25[] = { /* 25 MHz baud rate period table */
+ 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
+ 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15};
+
+static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */
+ /* value => 00 01 02 03 04 */
+ /* divide by 8 32 128 512 2048 */
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
+ 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00};
+
+static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */
+ 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
+ 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
+ 0x21};
+
+static char baud_cor3[] = { /* receive threshold */
+ 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
+ 0x07};
+
+/*
+ * The Cyclades driver implements HW flow control as any serial driver.
+ * The cyclades_port structure member rflow and the vector rflow_thr
+ * allows us to take advantage of a special feature in the CD1400 to avoid
+ * data loss even when the system interrupt latency is too high. These flags
+ * are to be used only with very special applications. Setting these flags
+ * requires the use of a special cable (DTR and RTS reversed). In the new
+ * CD1400-based boards (rev. 6.00 or later), there is no need for special
+ * cables.
+ */
+
+static char rflow_thr[] = { /* rflow threshold */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x0a};
+
+/* The Cyclom-Ye has placed the sequential chips in non-sequential
+ * address order. This look-up table overcomes that problem.
+ */
+static int cy_chip_offset [] =
+ { 0x0000,
+ 0x0400,
+ 0x0800,
+ 0x0C00,
+ 0x0200,
+ 0x0600,
+ 0x0A00,
+ 0x0E00
+ };
+
+/* PCI related definitions */
+
+static unsigned short cy_pci_nboard;
+static unsigned short cy_isa_nboard;
+static unsigned short cy_nboard;
+#ifdef CONFIG_PCI
+static unsigned short cy_pci_dev_id[] = {
+ PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */
+ PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */
+ 0 /* end of table */
+ };
+#endif
+
+static void cy_start(struct tty_struct *);
+static void set_line_char(struct cyclades_port *);
+static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong);
+#ifdef CONFIG_ISA
+static unsigned detect_isa_irq(void __iomem *);
+#endif /* CONFIG_ISA */
+
+static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *);
+
+#ifndef CONFIG_CYZ_INTR
+static void cyz_poll(unsigned long);
+
+/* The Cyclades-Z polling cycle is defined by this variable */
+static long cyz_polling_cycle = CZ_DEF_POLL;
+
+static int cyz_timeron = 0;
+static struct timer_list cyz_timerlist = TIMER_INITIALIZER(cyz_poll, 0, 0);
+
+#else /* CONFIG_CYZ_INTR */
+static void cyz_rx_restart(unsigned long);
+static struct timer_list cyz_rx_full_timer[NR_PORTS];
+#endif /* CONFIG_CYZ_INTR */
+
+static inline int
+serial_paranoia_check(struct cyclades_port *info,
+ char *name, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+ static const char *badmagic =
+ "cyc Warning: bad magic number for serial struct (%s) in %s\n";
+ static const char *badinfo =
+ "cyc Warning: null cyclades_port for (%s) in %s\n";
+ static const char *badrange =
+ "cyc Warning: cyclades_port out of range for (%s) in %s\n";
+
+ if (!info) {
+ printk(badinfo, name, routine);
+ return 1;
+ }
+
+ if( (long)info < (long)(&cy_port[0])
+ || (long)(&cy_port[NR_PORTS]) < (long)info ){
+ printk(badrange, name, routine);
+ return 1;
+ }
+
+ if (info->magic != CYCLADES_MAGIC) {
+ printk(badmagic, name, routine);
+ return 1;
+ }
+#endif
+ return 0;
+} /* serial_paranoia_check */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver
+ * (also known as the "bottom half"). This can be called any
+ * number of times for any channel without harm.
+ */
+static inline void
+cy_sched_event(struct cyclades_port *info, int event)
+{
+ info->event |= 1 << event; /* remember what kind of event and who */
+ schedule_work(&info->tqueue);
+} /* cy_sched_event */
+
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * cy#/_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using cy_sched_event(), and they get done here.
+ *
+ * This is done through one level of indirection--the task queue.
+ * When a hardware interrupt service routine wants service by the
+ * driver's bottom half, it enqueues the appropriate tq_struct (one
+ * per port) to the keventd work queue and sets a request flag
+ * that the work queue be processed.
+ *
+ * Although this may seem unwieldy, it gives the system a way to
+ * pass an argument (in this case the pointer to the cyclades_port
+ * structure) to the bottom half of the driver. Previous kernels
+ * had to poll every port to see if that port needed servicing.
+ */
+static void
+do_softint(void *private_)
+{
+ struct cyclades_port *info = (struct cyclades_port *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
+ tty_hangup(info->tty);
+ wake_up_interruptible(&info->open_wait);
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
+ }
+ if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
+ wake_up_interruptible(&info->open_wait);
+ }
+#ifdef CONFIG_CYZ_INTR
+ if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) {
+ if (cyz_rx_full_timer[info->line].function == NULL) {
+ cyz_rx_full_timer[info->line].expires = jiffies + 1;
+ cyz_rx_full_timer[info->line].function = cyz_rx_restart;
+ cyz_rx_full_timer[info->line].data = (unsigned long)info;
+ add_timer(&cyz