tty: cyclades, cache HW version
[deliverable/linux.git] / drivers / char / cyclades.c
CommitLineData
1da177e4
LT
1#undef BLOCKMOVE
2#define Z_WAKE
3#undef Z_EXT_CHARS_IN_BUFFER
1da177e4
LT
4
5/*
6 * linux/drivers/char/cyclades.c
7 *
8 * This file contains the driver for the Cyclades async multiport
9 * serial boards.
10 *
11 * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
12 * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
1da177e4 13 *
c8e1693a 14 * Copyright (C) 2007 Jiri Slaby <jirislaby@gmail.com>
1da177e4
LT
15 *
16 * Much of the design and some of the code came from serial.c
17 * which was copyright (C) 1991, 1992 Linus Torvalds. It was
18 * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
19 * and then fixed as suggested by Michael K. Johnson 12/12/92.
c8e1693a 20 * Converted to pci probing and cleaned up by Jiri Slaby.
1da177e4
LT
21 *
22 * This version supports shared IRQ's (only for PCI boards).
23 *
1da177e4
LT
24 * Prevent users from opening non-existing Z ports.
25 *
26 * Revision 2.3.2.8 2000/07/06 18:14:16 ivan
27 * Fixed the PCI detection function to work properly on Alpha systems.
28 * Implemented support for TIOCSERGETLSR ioctl.
29 * Implemented full support for non-standard baud rates.
30 *
31 * Revision 2.3.2.7 2000/06/01 18:26:34 ivan
32 * Request PLX I/O region, although driver doesn't use it, to avoid
33 * problems with other drivers accessing it.
34 * Removed count for on-board buffer characters in cy_chars_in_buffer
35 * (Cyclades-Z only).
36 *
37 * Revision 2.3.2.6 2000/05/05 13:56:05 ivan
38 * Driver now reports physical instead of virtual memory addresses.
39 * Masks were added to some Cyclades-Z read accesses.
40 * Implemented workaround for PLX9050 bug that would cause a system lockup
41 * in certain systems, depending on the MMIO addresses allocated to the
42 * board.
43 * Changed the Tx interrupt programming in the CD1400 chips to boost up
44 * performance (Cyclom-Y only).
45 * Code is now compliant with the new module interface (module_[init|exit]).
46 * Make use of the PCI helper functions to access PCI resources.
47 * Did some code "housekeeping".
48 *
49 * Revision 2.3.2.5 2000/01/19 14:35:33 ivan
50 * Fixed bug in cy_set_termios on CRTSCTS flag turnoff.
51 *
52 * Revision 2.3.2.4 2000/01/17 09:19:40 ivan
53 * Fixed SMP locking in Cyclom-Y interrupt handler.
54 *
55 * Revision 2.3.2.3 1999/12/28 12:11:39 ivan
56 * Added a new cyclades_card field called nports to allow the driver to
57 * know the exact number of ports found by the Z firmware after its load;
58 * RX buffer contention prevention logic on interrupt op mode revisited
59 * (Cyclades-Z only);
60 * Revisited printk's for Z debug;
61 * Driver now makes sure that the constant SERIAL_XMIT_SIZE is defined;
62 *
63 * Revision 2.3.2.2 1999/10/01 11:27:43 ivan
15ed6cc0 64 * Fixed bug in cyz_poll that would make all ports but port 0
1da177e4
LT
65 * unable to transmit/receive data (Cyclades-Z only);
66 * Implemented logic to prevent the RX buffer from being stuck with data
67 * due to a driver / firmware race condition in interrupt op mode
68 * (Cyclades-Z only);
69 * Fixed bug in block_til_ready logic that would lead to a system crash;
70 * Revisited cy_close spinlock usage;
71 *
72 * Revision 2.3.2.1 1999/09/28 11:01:22 ivan
73 * Revisited CONFIG_PCI conditional compilation for PCI board support;
74 * Implemented TIOCGICOUNT and TIOCMIWAIT ioctl support;
75 * _Major_ cleanup on the Cyclades-Z interrupt support code / logic;
76 * Removed CTS handling from the driver -- this is now completely handled
77 * by the firmware (Cyclades-Z only);
78 * Flush RX on-board buffers on a port open (Cyclades-Z only);
79 * Fixed handling of ASYNC_SPD_* TTY flags;
80 * Module unload now unmaps all memory area allocated by ioremap;
81 *
82 * Revision 2.3.1.1 1999/07/15 16:45:53 ivan
83 * Removed CY_PROC conditional compilation;
84 * Implemented SMP-awareness for the driver;
15ed6cc0 85 * Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off]
1da177e4
LT
86 * functions;
87 * The driver now accepts memory addresses (maddr=0xMMMMM) and IRQs
88 * (irq=NN) as parameters (only for ISA boards);
15ed6cc0 89 * Fixed bug in set_line_char that would prevent the Cyclades-Z
1da177e4
LT
90 * ports from being configured at speeds above 115.2Kbps;
91 * Fixed bug in cy_set_termios that would prevent XON/XOFF flow control
92 * switching from working properly;
15ed6cc0 93 * The driver now only prints IRQ info for the Cyclades-Z if it's
1da177e4
LT
94 * configured to work in interrupt mode;
95 *
96 * Revision 2.2.2.3 1999/06/28 11:13:29 ivan
97 * Added support for interrupt mode operation for the Z cards;
98 * Removed the driver inactivity control for the Z;
15ed6cc0 99 * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when
1da177e4 100 * the Z firmware is not loaded yet;
15ed6cc0 101 * Replaced the "manual" Z Tx flush buffer by a call to a FW command of
1da177e4 102 * same functionality;
15ed6cc0 103 * Implemented workaround for IRQ setting loss on the PCI configuration
1da177e4
LT
104 * registers after a PCI bridge EEPROM reload (affects PLX9060 only);
105 *
106 * Revision 2.2.2.2 1999/05/14 17:18:15 ivan
107 * /proc entry location changed to /proc/tty/driver/cyclades;
108 * Added support to shared IRQ's (only for PCI boards);
109 * Added support for Cobalt Qube2 systems;
110 * IRQ [de]allocation scheme revisited;
111 * BREAK implementation changed in order to make use of the 'break_ctl'
112 * TTY facility;
113 * Fixed typo in TTY structure field 'driver_name';
15ed6cc0 114 * Included a PCI bridge reset and EEPROM reload in the board
1da177e4
LT
115 * initialization code (for both Y and Z series).
116 *
117 * Revision 2.2.2.1 1999/04/08 16:17:43 ivan
15ed6cc0 118 * Fixed a bug in cy_wait_until_sent that was preventing the port to be
1da177e4
LT
119 * closed properly after a SIGINT;
120 * Module usage counter scheme revisited;
121 * Added support to the upcoming Y PCI boards (i.e., support to additional
122 * PCI Device ID's).
15ed6cc0 123 *
1da177e4
LT
124 * Revision 2.2.1.10 1999/01/20 16:14:29 ivan
125 * Removed all unnecessary page-alignement operations in ioremap calls
126 * (ioremap is currently safe for these operations).
127 *
128 * Revision 2.2.1.9 1998/12/30 18:18:30 ivan
15ed6cc0 129 * Changed access to PLX PCI bridge registers from I/O to MMIO, in
1da177e4
LT
130 * order to make PLX9050-based boards work with certain motherboards.
131 *
132 * Revision 2.2.1.8 1998/11/13 12:46:20 ivan
133 * cy_close function now resets (correctly) the tty->closing flag;
134 * JIFFIES_DIFF macro fixed.
135 *
136 * Revision 2.2.1.7 1998/09/03 12:07:28 ivan
137 * Fixed bug in cy_close function, which was not informing HW of
138 * which port should have the reception disabled before doing so;
139 * fixed Cyclom-8YoP hardware detection bug.
140 *
141 * Revision 2.2.1.6 1998/08/20 17:15:39 ivan
142 * Fixed bug in cy_close function, which causes malfunction
143 * of one of the first 4 ports when a higher port is closed
144 * (Cyclom-Y only).
145 *
146 * Revision 2.2.1.5 1998/08/10 18:10:28 ivan
147 * Fixed Cyclom-4Yo hardware detection bug.
148 *
149 * Revision 2.2.1.4 1998/08/04 11:02:50 ivan
15ed6cc0 150 * /proc/cyclades implementation with great collaboration of
1da177e4
LT
151 * Marc Lewis <marc@blarg.net>;
152 * cyy_interrupt was changed to avoid occurrence of kernel oopses
153 * during PPP operation.
154 *
155 * Revision 2.2.1.3 1998/06/01 12:09:10 ivan
156 * General code review in order to comply with 2.1 kernel standards;
157 * data loss prevention for slow devices revisited (cy_wait_until_sent
158 * was created);
15ed6cc0 159 * removed conditional compilation for new/old PCI structure support
1da177e4
LT
160 * (now the driver only supports the new PCI structure).
161 *
162 * Revision 2.2.1.1 1998/03/19 16:43:12 ivan
163 * added conditional compilation for new/old PCI structure support;
164 * removed kernel series (2.0.x / 2.1.x) conditional compilation.
165 *
166 * Revision 2.1.1.3 1998/03/16 18:01:12 ivan
167 * cleaned up the data loss fix;
168 * fixed XON/XOFF handling once more (Cyclades-Z);
169 * general review of the driver routines;
15ed6cc0 170 * introduction of a mechanism to prevent data loss with slow
1da177e4
LT
171 * printers, by forcing a delay before closing the port.
172 *
173 * Revision 2.1.1.2 1998/02/17 16:50:00 ivan
174 * fixed detection/handling of new CD1400 in Ye boards;
175 * fixed XON/XOFF handling (Cyclades-Z);
176 * fixed data loss caused by a premature port close;
177 * introduction of a flag that holds the CD1400 version ID per port
178 * (used by the CYGETCD1400VER new ioctl).
179 *
180 * Revision 2.1.1.1 1997/12/03 17:31:19 ivan
181 * Code review for the module cleanup routine;
182 * fixed RTS and DTR status report for new CD1400's in get_modem_info;
183 * includes anonymous changes regarding signal_pending.
15ed6cc0 184 *
1da177e4
LT
185 * Revision 2.1 1997/11/01 17:42:41 ivan
186 * Changes in the driver to support Alpha systems (except 8Zo V_1);
187 * BREAK fix for the Cyclades-Z boards;
188 * driver inactivity control by FW implemented;
15ed6cc0 189 * introduction of flag that allows driver to take advantage of
1da177e4
LT
190 * a special CD1400 feature related to HW flow control;
191 * added support for the CD1400 rev. J (Cyclom-Y boards);
192 * introduction of ioctls to:
193 * - control the rtsdtr_inv flag (Cyclom-Y);
194 * - control the rflow flag (Cyclom-Y);
195 * - adjust the polling interval (Cyclades-Z);
196 *
197 * Revision 1.36.4.33 1997/06/27 19:00:00 ivan
15ed6cc0 198 * Fixes related to kernel version conditional
1da177e4 199 * compilation.
15ed6cc0 200 *
1da177e4 201 * Revision 1.36.4.32 1997/06/14 19:30:00 ivan
15ed6cc0 202 * Compatibility issues between kernels 2.0.x and
1da177e4 203 * 2.1.x (mainly related to clear_bit function).
15ed6cc0 204 *
1da177e4 205 * Revision 1.36.4.31 1997/06/03 15:30:00 ivan
15ed6cc0 206 * Changes to define the memory window according to the
1da177e4 207 * board type.
15ed6cc0 208 *
1da177e4
LT
209 * Revision 1.36.4.30 1997/05/16 15:30:00 daniel
210 * Changes to support new cycladesZ boards.
211 *
212 * Revision 1.36.4.29 1997/05/12 11:30:00 daniel
213 * Merge of Bentson's and Daniel's version 1.36.4.28.
214 * Corrects bug in cy_detect_pci: check if there are more
215 * ports than the number of static structs allocated.
216 * Warning message during initialization if this driver is
217 * used with the new generation of cycladesZ boards. Those
218 * will be supported only in next release of the driver.
219 * Corrects bug in cy_detect_pci and cy_detect_isa that
220 * returned wrong number of VALID boards, when a cyclomY
221 * was found with no serial modules connected.
222 * Changes to use current (2.1.x) kernel subroutine names
223 * and created macros for compilation with 2.0.x kernel,
224 * instead of the other way around.
225 *
226 * Revision 1.36.4.28 1997/05/?? ??:00:00 bentson
227 * Change queue_task_irq_off to queue_task_irq.
228 * The inline function queue_task_irq_off (tqueue.h)
229 * was removed from latest releases of 2.1.x kernel.
230 * Use of macro __init to mark the initialization
231 * routines, so memory can be reused.
232 * Also incorporate implementation of critical region
233 * in function cleanup_module() created by anonymous
234 * linuxer.
235 *
236 * Revision 1.36.4.28 1997/04/25 16:00:00 daniel
237 * Change to support new firmware that solves DCD problem:
238 * application could fail to receive SIGHUP signal when DCD
239 * varying too fast.
240 *
241 * Revision 1.36.4.27 1997/03/26 10:30:00 daniel
242 * Changed for support linux versions 2.1.X.
243 * Backward compatible with linux versions 2.0.X.
244 * Corrected illegal use of filler field in
245 * CH_CTRL struct.
246 * Deleted some debug messages.
247 *
248 * Revision 1.36.4.26 1997/02/27 12:00:00 daniel
249 * Included check for NULL tty pointer in cyz_poll.
250 *
251 * Revision 1.36.4.25 1997/02/26 16:28:30 bentson
252 * Bill Foster at Blarg! Online services noticed that
253 * some of the switch elements of -Z modem control
254 * lacked a closing "break;"
255 *
256 * Revision 1.36.4.24 1997/02/24 11:00:00 daniel
257 * Changed low water threshold for buffer xmit_buf
258 *
259 * Revision 1.36.4.23 1996/12/02 21:50:16 bentson
260 * Marcio provided fix to modem status fetch for -Z
261 *
262 * Revision 1.36.4.22 1996/10/28 22:41:17 bentson
263 * improve mapping of -Z control page (thanks to Steve
264 * Price <stevep@fa.tdktca.com> for help on this)
265 *
266 * Revision 1.36.4.21 1996/09/10 17:00:10 bentson
267 * shift from CPU-bound to memcopy in cyz_polling operation
268 *
269 * Revision 1.36.4.20 1996/09/09 18:30:32 Bentson
270 * Added support to set and report higher speeds.
271 *
272 * Revision 1.36.4.19c 1996/08/09 10:00:00 Marcio Saito
273 * Some fixes in the HW flow control for the BETA release.
274 * Don't try to register the IRQ.
275 *
276 * Revision 1.36.4.19 1996/08/08 16:23:18 Bentson
277 * make sure "cyc" appears in all kernel messages; all soft interrupts
278 * handled by same routine; recognize out-of-band reception; comment
279 * out some diagnostic messages; leave RTS/CTS flow control to hardware;
33430dc5 280 * fix race condition in -Z buffer management; only -Y needs to explicitly
1da177e4
LT
281 * flush chars; tidy up some startup messages;
282 *
283 * Revision 1.36.4.18 1996/07/25 18:57:31 bentson
284 * shift MOD_INC_USE_COUNT location to match
285 * serial.c; purge some diagnostic messages;
286 *
287 * Revision 1.36.4.17 1996/07/25 18:01:08 bentson
288 * enable modem status messages and fetch & process them; note
289 * time of last activity type for each port; set_line_char now
290 * supports more than line 0 and treats 0 baud correctly;
291 * get_modem_info senses rs_status;
292 *
293 * Revision 1.36.4.16 1996/07/20 08:43:15 bentson
294 * barely works--now's time to turn on
295 * more features 'til it breaks
296 *
297 * Revision 1.36.4.15 1996/07/19 22:30:06 bentson
298 * check more -Z board status; shorten boot message
299 *
300 * Revision 1.36.4.14 1996/07/19 22:20:37 bentson
301 * fix reference to ch_ctrl in startup; verify return
302 * values from cyz_issue_cmd and cyz_update_channel;
303 * more stuff to get modem control correct;
304 *
305 * Revision 1.36.4.13 1996/07/11 19:53:33 bentson
306 * more -Z stuff folded in; re-order changes to put -Z stuff
307 * after -Y stuff (to make changes clearer)
308 *
309 * Revision 1.36.4.12 1996/07/11 15:40:55 bentson
310 * Add code to poll Cyclades-Z. Add code to get & set RS-232 control.
311 * Add code to send break. Clear firmware ID word at startup (so
312 * that other code won't talk to inactive board).
313 *
314 * Revision 1.36.4.11 1996/07/09 05:28:29 bentson
315 * add code for -Z in set_line_char
316 *
317 * Revision 1.36.4.10 1996/07/08 19:28:37 bentson
318 * fold more -Z stuff (or in some cases, error messages)
319 * into driver; add text to "don't know what to do" messages.
320 *
321 * Revision 1.36.4.9 1996/07/08 18:38:38 bentson
322 * moved compile-time flags near top of file; cosmetic changes
323 * to narrow text (to allow 2-up printing); changed many declarations
324 * to "static" to limit external symbols; shuffled code order to
325 * coalesce -Y and -Z specific code, also to put internal functions
326 * in order of tty_driver structure; added code to recognize -Z
327 * ports (and for moment, do nothing or report error); add cy_startup
328 * to parse boot command line for extra base addresses for ISA probes;
329 *
330 * Revision 1.36.4.8 1996/06/25 17:40:19 bentson
331 * reorder some code, fix types of some vars (int vs. long),
332 * add cy_setup to support user declared ISA addresses
333 *
334 * Revision 1.36.4.7 1996/06/21 23:06:18 bentson
335 * dump ioctl based firmware load (it's now a user level
336 * program); ensure uninitialzed ports cannot be used
337 *
338 * Revision 1.36.4.6 1996/06/20 23:17:19 bentson
339 * rename vars and restructure some code
340 *
341 * Revision 1.36.4.5 1996/06/14 15:09:44 bentson
342 * get right status back after boot load
343 *
344 * Revision 1.36.4.4 1996/06/13 19:51:44 bentson
345 * successfully loads firmware
346 *
347 * Revision 1.36.4.3 1996/06/13 06:08:33 bentson
348 * add more of the code for the boot/load ioctls
349 *
350 * Revision 1.36.4.2 1996/06/11 21:00:51 bentson
351 * start to add Z functionality--starting with ioctl
352 * for loading firmware
353 *
354 * Revision 1.36.4.1 1996/06/10 18:03:02 bentson
355 * added code to recognize Z/PCI card at initialization; report
356 * presence, but card is not initialized (because firmware needs
357 * to be loaded)
358 *
359 * Revision 1.36.3.8 1996/06/07 16:29:00 bentson
360 * starting minor number at zero; added missing verify_area
96de0e25 361 * as noted by Heiko Eißfeldt <heiko@colossus.escape.de>
1da177e4
LT
362 *
363 * Revision 1.36.3.7 1996/04/19 21:06:18 bentson
364 * remove unneeded boot message & fix CLOCAL hardware flow
365 * control (Miquel van Smoorenburg <miquels@Q.cistron.nl>);
366 * remove unused diagnostic statements; minor 0 is first;
367 *
368 * Revision 1.36.3.6 1996/03/13 13:21:17 marcio
369 * The kernel function vremap (available only in later 1.3.xx kernels)
370 * allows the access to memory addresses above the RAM. This revision
371 * of the driver supports PCI boards below 1Mb (device id 0x100) and
372 * above 1Mb (device id 0x101).
373 *
374 * Revision 1.36.3.5 1996/03/07 15:20:17 bentson
375 * Some global changes to interrupt handling spilled into
376 * this driver--mostly unused arguments in system function
377 * calls. Also added change by Marcio Saito which should
378 * reduce lost interrupts at startup by fast processors.
379 *
380 * Revision 1.36.3.4 1995/11/13 20:45:10 bentson
381 * Changes by Corey Minyard <minyard@wf-rch.cirr.com> distributed
382 * in 1.3.41 kernel to remove a possible race condition, extend
383 * some error messages, and let the driver run as a loadable module
384 * Change by Alan Wendt <alan@ez0.ezlink.com> to remove a
385 * possible race condition.
386 * Change by Marcio Saito <marcio@cyclades.com> to fix PCI addressing.
387 *
388 * Revision 1.36.3.3 1995/11/13 19:44:48 bentson
389 * Changes by Linus Torvalds in 1.3.33 kernel distribution
390 * required due to reordering of driver initialization.
391 * Drivers are now initialized *after* memory management.
392 *
393 * Revision 1.36.3.2 1995/09/08 22:07:14 bentson
394 * remove printk from ISR; fix typo
395 *
396 * Revision 1.36.3.1 1995/09/01 12:00:42 marcio
397 * Minor fixes in the PCI board support. PCI function calls in
398 * conditional compilation (CONFIG_PCI). Thanks to Jim Duncan
399 * <duncan@okay.com>. "bad serial count" message removed.
400 *
401 * Revision 1.36.3 1995/08/22 09:19:42 marcio
402 * Cyclom-Y/PCI support added. Changes in the cy_init routine and
403 * board initialization. Changes in the boot messages. The driver
404 * supports up to 4 boards and 64 ports by default.
405 *
406 * Revision 1.36.1.4 1995/03/29 06:14:14 bentson
407 * disambiguate between Cyclom-16Y and Cyclom-32Ye;
408 *
409 * Revision 1.36.1.3 1995/03/23 22:15:35 bentson
410 * add missing break in modem control block in ioctl switch statement
411 * (discovered by Michael Edward Chastain <mec@jobe.shell.portal.com>);
412 *
413 * Revision 1.36.1.2 1995/03/22 19:16:22 bentson
414 * make sure CTS flow control is set as soon as possible (thanks
415 * to note from David Lambert <lambert@chesapeake.rps.slb.com>);
416 *
417 * Revision 1.36.1.1 1995/03/13 15:44:43 bentson
418 * initialize defaults for receive threshold and stale data timeout;
419 * cosmetic changes;
420 *
421 * Revision 1.36 1995/03/10 23:33:53 bentson
422 * added support of chips 4-7 in 32 port Cyclom-Ye;
423 * fix cy_interrupt pointer dereference problem
424 * (Joe Portman <baron@aa.net>);
425 * give better error response if open is attempted on non-existent port
426 * (Zachariah Vaum <jchryslr@netcom.com>);
427 * correct command timeout (Kenneth Lerman <lerman@@seltd.newnet.com>);
428 * conditional compilation for -16Y on systems with fast, noisy bus;
429 * comment out diagnostic print function;
430 * cleaned up table of base addresses;
431 * set receiver time-out period register to correct value,
432 * set receive threshold to better default values,
433 * set chip timer to more accurate 200 Hz ticking,
434 * add code to monitor and modify receive parameters
435 * (Rik Faith <faith@cs.unc.edu> Nick Simicich
436 * <njs@scifi.emi.net>);
437 *
438 * Revision 1.35 1994/12/16 13:54:18 steffen
439 * additional patch by Marcio Saito for board detection
440 * Accidently left out in 1.34
441 *
442 * Revision 1.34 1994/12/10 12:37:12 steffen
443 * This is the corrected version as suggested by Marcio Saito
444 *
445 * Revision 1.33 1994/12/01 22:41:18 bentson
446 * add hooks to support more high speeds directly; add tytso
447 * patch regarding CLOCAL wakeups
448 *
449 * Revision 1.32 1994/11/23 19:50:04 bentson
450 * allow direct kernel control of higher signalling rates;
451 * look for cards at additional locations
452 *
453 * Revision 1.31 1994/11/16 04:33:28 bentson
454 * ANOTHER fix from Corey Minyard, minyard@wf-rch.cirr.com--
455 * a problem in chars_in_buffer has been resolved by some
456 * small changes; this should yield smoother output
457 *
458 * Revision 1.30 1994/11/16 04:28:05 bentson
459 * Fix from Corey Minyard, Internet: minyard@metronet.com,
460 * UUCP: minyard@wf-rch.cirr.com, WORK: minyardbnr.ca, to
461 * cy_hangup that appears to clear up much (all?) of the
462 * DTR glitches; also he's added/cleaned-up diagnostic messages
463 *
464 * Revision 1.29 1994/11/16 04:16:07 bentson
465 * add change proposed by Ralph Sims, ralphs@halcyon.com, to
466 * operate higher speeds in same way as other serial ports;
467 * add more serial ports (for up to two 16-port muxes).
468 *
469 * Revision 1.28 1994/11/04 00:13:16 root
470 * turn off diagnostic messages
471 *
472 * Revision 1.27 1994/11/03 23:46:37 root
473 * bunch of changes to bring driver into greater conformance
474 * with the serial.c driver (looking for missed fixes)
475 *
476 * Revision 1.26 1994/11/03 22:40:36 root
477 * automatic interrupt probing fixed.
478 *
479 * Revision 1.25 1994/11/03 20:17:02 root
480 * start to implement auto-irq
481 *
482 * Revision 1.24 1994/11/03 18:01:55 root
483 * still working on modem signals--trying not to drop DTR
484 * during the getty/login processes
485 *
486 * Revision 1.23 1994/11/03 17:51:36 root
487 * extend baud rate support; set receive threshold as function
488 * of baud rate; fix some problems with RTS/CTS;
489 *
490 * Revision 1.22 1994/11/02 18:05:35 root
491 * changed arguments to udelay to type long to get
492 * delays to be of correct duration
493 *
494 * Revision 1.21 1994/11/02 17:37:30 root
495 * employ udelay (after calibrating loops_per_second earlier
496 * in init/main.c) instead of using home-grown delay routines
497 *
498 * Revision 1.20 1994/11/02 03:11:38 root
499 * cy_chars_in_buffer forces a return value of 0 to let
500 * login work (don't know why it does); some functions
501 * that were returning EFAULT, now executes the code;
502 * more work on deciding when to disable xmit interrupts;
503 *
504 * Revision 1.19 1994/11/01 20:10:14 root
505 * define routine to start transmission interrupts (by enabling
506 * transmit interrupts); directly enable/disable modem interrupts;
507 *
508 * Revision 1.18 1994/11/01 18:40:45 bentson
509 * Don't always enable transmit interrupts in startup; interrupt on
510 * TxMpty instead of TxRdy to help characters get out before shutdown;
511 * restructure xmit interrupt to check for chars first and quit if
512 * none are ready to go; modem status (MXVRx) is upright, _not_ inverted
513 * (to my view);
514 *
515 * Revision 1.17 1994/10/30 04:39:45 bentson
516 * rename serial_driver and callout_driver to cy_serial_driver and
517 * cy_callout_driver to avoid linkage interference; initialize
518 * info->type to PORT_CIRRUS; ruggedize paranoia test; elide ->port
519 * from cyclades_port structure; add paranoia check to cy_close;
520 *
521 * Revision 1.16 1994/10/30 01:14:33 bentson
522 * change major numbers; add some _early_ return statements;
523 *
524 * Revision 1.15 1994/10/29 06:43:15 bentson
525 * final tidying up for clean compile; enable some error reporting
526 *
527 * Revision 1.14 1994/10/28 20:30:22 Bentson
528 * lots of changes to drag the driver towards the new tty_io
529 * structures and operation. not expected to work, but may
530 * compile cleanly.
531 *
532 * Revision 1.13 1994/07/21 23:08:57 Bentson
533 * add some diagnostic cruft; support 24 lines (for testing
534 * both -8Y and -16Y cards; be more thorough in servicing all
535 * chips during interrupt; add "volatile" a few places to
536 * circumvent compiler optimizations; fix base & offset
537 * computations in block_til_ready (was causing chip 0 to
538 * stop operation)
539 *
540 * Revision 1.12 1994/07/19 16:42:11 Bentson
541 * add some hackery for kernel version 1.1.8; expand
542 * error messages; refine timing for delay loops and
543 * declare loop params volatile
544 *
545 * Revision 1.11 1994/06/11 21:53:10 bentson
546 * get use of save_car right in transmit interrupt service
547 *
548 * Revision 1.10.1.1 1994/06/11 21:31:18 bentson
549 * add some diagnostic printing; try to fix save_car stuff
550 *
551 * Revision 1.10 1994/06/11 20:36:08 bentson
552 * clean up compiler warnings
553 *
554 * Revision 1.9 1994/06/11 19:42:46 bentson
555 * added a bunch of code to support modem signalling
556 *
557 * Revision 1.8 1994/06/11 17:57:07 bentson
558 * recognize break & parity error
559 *
560 * Revision 1.7 1994/06/05 05:51:34 bentson
561 * Reorder baud table to be monotonic; add cli to CP; discard
562 * incoming characters and status if the line isn't open; start to
563 * fold code into cy_throttle; start to port get_serial_info,
564 * set_serial_info, get_modem_info, set_modem_info, and send_break
565 * from serial.c; expand cy_ioctl; relocate and expand config_setup;
566 * get flow control characters from tty struct; invalidate ports w/o
567 * hardware;
568 *
569 * Revision 1.6 1994/05/31 18:42:21 bentson
570 * add a loop-breaker in the interrupt service routine;
571 * note when port is initialized so that it can be shut
572 * down under the right conditions; receive works without
573 * any obvious errors
574 *
575 * Revision 1.5 1994/05/30 00:55:02 bentson
576 * transmit works without obvious errors
577 *
578 * Revision 1.4 1994/05/27 18:46:27 bentson
579 * incorporated more code from lib_y.c; can now print short
580 * strings under interrupt control to port zero; seems to
581 * select ports/channels/lines correctly
582 *
583 * Revision 1.3 1994/05/25 22:12:44 bentson
584 * shifting from multi-port on a card to proper multiplexor
585 * data structures; added skeletons of most routines
586 *
587 * Revision 1.2 1994/05/19 13:21:43 bentson
588 * start to crib from other sources
589 *
590 */
591
c8e1693a 592#define CY_VERSION "2.5"
096dcfce 593
1da177e4
LT
594/* If you need to install more boards than NR_CARDS, change the constant
595 in the definition below. No other change is necessary to support up to
596 eight boards. Beyond that you'll have to extend cy_isa_addresses. */
597
02f1175c 598#define NR_CARDS 4
1da177e4
LT
599
600/*
601 If the total number of ports is larger than NR_PORTS, change this
602 constant in the definition below. No other change is necessary to
603 support more boards/ports. */
604
02f1175c 605#define NR_PORTS 256
1da177e4
LT
606
607#define ZE_V1_NPORTS 64
608#define ZO_V1 0
609#define ZO_V2 1
610#define ZE_V1 2
611
612#define SERIAL_PARANOIA_CHECK
613#undef CY_DEBUG_OPEN
614#undef CY_DEBUG_THROTTLE
615#undef CY_DEBUG_OTHER
616#undef CY_DEBUG_IO
617#undef CY_DEBUG_COUNT
618#undef CY_DEBUG_DTR
619#undef CY_DEBUG_WAIT_UNTIL_SENT
620#undef CY_DEBUG_INTERRUPTS
621#undef CY_16Y_HACK
622#undef CY_ENABLE_MONITORING
623#undef CY_PCI_DEBUG
624
1da177e4 625/*
15ed6cc0 626 * Include section
1da177e4 627 */
1da177e4
LT
628#include <linux/module.h>
629#include <linux/errno.h>
630#include <linux/signal.h>
631#include <linux/sched.h>
632#include <linux/timer.h>
633#include <linux/interrupt.h>
634#include <linux/tty.h>
33f0f88f 635#include <linux/tty_flip.h>
1da177e4
LT
636#include <linux/serial.h>
637#include <linux/major.h>
638#include <linux/string.h>
639#include <linux/fcntl.h>
640#include <linux/ptrace.h>
641#include <linux/cyclades.h>
642#include <linux/mm.h>
643#include <linux/ioport.h>
644#include <linux/init.h>
645#include <linux/delay.h>
646#include <linux/spinlock.h>
647#include <linux/bitops.h>
054f5b0a 648#include <linux/firmware.h>
9f56fad7 649#include <linux/device.h>
1da177e4
LT
650
651#include <asm/system.h>
15ed6cc0 652#include <linux/io.h>
1da177e4 653#include <asm/irq.h>
15ed6cc0 654#include <linux/uaccess.h>
1da177e4 655
1da177e4
LT
656#include <linux/kernel.h>
657#include <linux/pci.h>
658
659#include <linux/stat.h>
660#include <linux/proc_fs.h>
444697d6 661#include <linux/seq_file.h>
1da177e4 662
02f1175c
JS
663static void cy_throttle(struct tty_struct *tty);
664static void cy_send_xchar(struct tty_struct *tty, char ch);
1da177e4 665
65f76a82 666#define IS_CYC_Z(card) ((card).num_chips == (unsigned int)-1)
1da177e4
LT
667
668#define Z_FPGA_CHECK(card) \
97e87f8e 669 ((readl(&(card).ctl_addr.p9060->init_ctrl) & (1<<17)) != 0)
1da177e4 670
101b8159 671#define ISZLOADED(card) ((ZO_V1 == (card).hw_ver || Z_FPGA_CHECK(card)) && \
15ed6cc0 672 (ZFIRM_ID == readl(&((struct FIRM_ID __iomem *) \
1da177e4
LT
673 ((card).base_addr+ID_ADDRESS))->signature)))
674
675#ifndef SERIAL_XMIT_SIZE
676#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096))
677#endif
678#define WAKEUP_CHARS 256
679
680#define STD_COM_FLAGS (0)
681
054f5b0a
JS
682/* firmware stuff */
683#define ZL_MAX_BLOCKS 16
684#define DRIVER_VERSION 0x02010203
685#define RAM_SIZE 0x80000
686
687#define Z_FPGA_LOADED(X) ((readl(&(X)->init_ctrl) & (1<<17)) != 0)
688
689enum zblock_type {
690 ZBLOCK_PRG = 0,
691 ZBLOCK_FPGA = 1
692};
693
694struct zfile_header {
695 char name[64];
696 char date[32];
697 char aux[32];
698 u32 n_config;
699 u32 config_offset;
700 u32 n_blocks;
701 u32 block_offset;
702 u32 reserved[9];
703} __attribute__ ((packed));
704
705struct zfile_config {
706 char name[64];
707 u32 mailbox;
708 u32 function;
709 u32 n_blocks;
710 u32 block_list[ZL_MAX_BLOCKS];
711} __attribute__ ((packed));
712
713struct zfile_block {
714 u32 type;
715 u32 file_offset;
716 u32 ram_offset;
717 u32 size;
718} __attribute__ ((packed));
719
1da177e4
LT
720static struct tty_driver *cy_serial_driver;
721
722#ifdef CONFIG_ISA
723/* This is the address lookup table. The driver will probe for
724 Cyclom-Y/ISA boards at all addresses in here. If you want the
725 driver to probe addresses at a different address, add it to
726 this table. If the driver is probing some other board and
727 causing problems, remove the offending address from this table.
1da177e4
LT
728*/
729
730static unsigned int cy_isa_addresses[] = {
02f1175c
JS
731 0xD0000,
732 0xD2000,
733 0xD4000,
734 0xD6000,
735 0xD8000,
736 0xDA000,
737 0xDC000,
738 0xDE000,
739 0, 0, 0, 0, 0, 0, 0, 0
1da177e4 740};
02f1175c 741
fe971071 742#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
1da177e4
LT
743
744#ifdef MODULE
3046d50e
JS
745static long maddr[NR_CARDS];
746static int irq[NR_CARDS];
1da177e4
LT
747
748module_param_array(maddr, long, NULL, 0);
749module_param_array(irq, int, NULL, 0);
750#endif
751
02f1175c 752#endif /* CONFIG_ISA */
1da177e4
LT
753
754/* This is the per-card data structure containing address, irq, number of
755 channels, etc. This driver supports a maximum of NR_CARDS cards.
756*/
757static struct cyclades_card cy_card[NR_CARDS];
758
02f1175c 759static int cy_next_channel; /* next minor available */
1da177e4 760
1da177e4
LT
761/*
762 * This is used to look up the divisor speeds and the timeouts
763 * We're normally limited to 15 distinct baud rates. The extra
77451e53 764 * are accessed via settings in info->port.flags.
1da177e4
LT
765 * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
766 * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
767 * HI VHI
768 * 20
769 */
770static int baud_table[] = {
02f1175c
JS
771 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
772 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
773 230400, 0
774};
775
776static char baud_co_25[] = { /* 25 MHz clock option table */
777 /* value => 00 01 02 03 04 */
778 /* divide by 8 32 128 512 2048 */
779 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
780 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
781};
782
783static char baud_bpr_25[] = { /* 25 MHz baud rate period table */
784 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
785 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
786};
787
788static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */
789 /* value => 00 01 02 03 04 */
790 /* divide by 8 32 128 512 2048 */
791 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
792 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00
794};
795
796static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */
797 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
798 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
799 0x21
800};
801
802static char baud_cor3[] = { /* receive threshold */
803 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
804 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
805 0x07
806};
1da177e4
LT
807
808/*
809 * The Cyclades driver implements HW flow control as any serial driver.
15ed6cc0
AC
810 * The cyclades_port structure member rflow and the vector rflow_thr
811 * allows us to take advantage of a special feature in the CD1400 to avoid
812 * data loss even when the system interrupt latency is too high. These flags
813 * are to be used only with very special applications. Setting these flags
814 * requires the use of a special cable (DTR and RTS reversed). In the new
815 * CD1400-based boards (rev. 6.00 or later), there is no need for special
1da177e4
LT
816 * cables.
817 */
818
02f1175c
JS
819static char rflow_thr[] = { /* rflow threshold */
820 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
822 0x0a
823};
1da177e4
LT
824
825/* The Cyclom-Ye has placed the sequential chips in non-sequential
826 * address order. This look-up table overcomes that problem.
827 */
02f1175c
JS
828static int cy_chip_offset[] = { 0x0000,
829 0x0400,
830 0x0800,
831 0x0C00,
832 0x0200,
833 0x0600,
834 0x0A00,
835 0x0E00
836};
1da177e4
LT
837
838/* PCI related definitions */
839
1da177e4 840#ifdef CONFIG_PCI
893de2df 841static struct pci_device_id cy_pci_dev_id[] __devinitdata = {
15ed6cc0
AC
842 /* PCI < 1Mb */
843 { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
844 /* PCI > 1Mb */
845 { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },
846 /* 4Y PCI < 1Mb */
847 { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },
848 /* 4Y PCI > 1Mb */
849 { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },
850 /* 8Y PCI < 1Mb */
851 { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },
852 /* 8Y PCI > 1Mb */
853 { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },
854 /* Z PCI < 1Mb */
855 { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },
856 /* Z PCI > 1Mb */
857 { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },
893de2df 858 { } /* end of table */
02f1175c 859};
893de2df 860MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
1da177e4
LT
861#endif
862
863static void cy_start(struct tty_struct *);
864static void set_line_char(struct cyclades_port *);
1a86b5e3 865static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
1da177e4
LT
866#ifdef CONFIG_ISA
867static unsigned detect_isa_irq(void __iomem *);
02f1175c 868#endif /* CONFIG_ISA */
1da177e4 869
1da177e4
LT
870#ifndef CONFIG_CYZ_INTR
871static void cyz_poll(unsigned long);
872
873/* The Cyclades-Z polling cycle is defined by this variable */
874static long cyz_polling_cycle = CZ_DEF_POLL;
875
8d06afab 876static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
1da177e4 877
02f1175c 878#else /* CONFIG_CYZ_INTR */
1da177e4
LT
879static void cyz_rx_restart(unsigned long);
880static struct timer_list cyz_rx_full_timer[NR_PORTS];
02f1175c 881#endif /* CONFIG_CYZ_INTR */
1da177e4 882
02f1175c
JS
883static inline int serial_paranoia_check(struct cyclades_port *info,
884 char *name, const char *routine)
1da177e4
LT
885{
886#ifdef SERIAL_PARANOIA_CHECK
02f1175c 887 if (!info) {
21719191
JS
888 printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) "
889 "in %s\n", name, routine);
02f1175c
JS
890 return 1;
891 }
892
02f1175c 893 if (info->magic != CYCLADES_MAGIC) {
21719191
JS
894 printk(KERN_WARNING "cyc Warning: bad magic number for serial "
895 "struct (%s) in %s\n", name, routine);
02f1175c
JS
896 return 1;
897 }
1da177e4 898#endif
02f1175c
JS
899 return 0;
900} /* serial_paranoia_check */
1da177e4 901
1da177e4
LT
902/***********************************************************/
903/********* Start of block of Cyclom-Y specific code ********/
904
905/* This routine waits up to 1000 micro-seconds for the previous
906 command to the Cirrus chip to complete and then issues the
907 new command. An error is returned if the previous command
908 didn't finish within the time limit.
909
910 This function is only called from inside spinlock-protected code.
911 */
15ed6cc0 912static int cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
1da177e4 913{
ad39c300 914 unsigned int i;
1da177e4 915
02f1175c
JS
916 /* Check to see that the previous command has completed */
917 for (i = 0; i < 100; i++) {
15ed6cc0 918 if (readb(base_addr + (CyCCR << index)) == 0)
02f1175c 919 break;
02f1175c 920 udelay(10L);
1da177e4 921 }
02f1175c
JS
922 /* if the CCR never cleared, the previous command
923 didn't finish within the "reasonable time" */
924 if (i == 100)
096dcfce 925 return -1;
1da177e4 926
02f1175c
JS
927 /* Issue the new command */
928 cy_writeb(base_addr + (CyCCR << index), cmd);
1da177e4 929
096dcfce 930 return 0;
02f1175c 931} /* cyy_issue_cmd */
1da177e4
LT
932
933#ifdef CONFIG_ISA
934/* ISA interrupt detection code */
15ed6cc0 935static unsigned detect_isa_irq(void __iomem *address)
1da177e4 936{
02f1175c
JS
937 int irq;
938 unsigned long irqs, flags;
939 int save_xir, save_car;
940 int index = 0; /* IRQ probing is only for ISA */
941
942 /* forget possible initially masked and pending IRQ */
943 irq = probe_irq_off(probe_irq_on());
944
945 /* Clear interrupts on the board first */
946 cy_writeb(address + (Cy_ClrIntr << index), 0);
947 /* Cy_ClrIntr is 0x1800 */
948
949 irqs = probe_irq_on();
950 /* Wait ... */
951 udelay(5000L);
952
953 /* Enable the Tx interrupts on the CD1400 */
954 local_irq_save(flags);
955 cy_writeb(address + (CyCAR << index), 0);
956 cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
957
958 cy_writeb(address + (CyCAR << index), 0);
959 cy_writeb(address + (CySRER << index),
db05c3b1 960 readb(address + (CySRER << index)) | CyTxRdy);
02f1175c
JS
961 local_irq_restore(flags);
962
963 /* Wait ... */
964 udelay(5000L);
965
966 /* Check which interrupt is in use */
967 irq = probe_irq_off(irqs);
968
969 /* Clean up */
db05c3b1
JS
970 save_xir = (u_char) readb(address + (CyTIR << index));
971 save_car = readb(address + (CyCAR << index));
02f1175c
JS
972 cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
973 cy_writeb(address + (CySRER << index),
db05c3b1 974 readb(address + (CySRER << index)) & ~CyTxRdy);
02f1175c
JS
975 cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
976 cy_writeb(address + (CyCAR << index), (save_car));
977 cy_writeb(address + (Cy_ClrIntr << index), 0);
978 /* Cy_ClrIntr is 0x1800 */
979
980 return (irq > 0) ? irq : 0;
1da177e4 981}
02f1175c 982#endif /* CONFIG_ISA */
1da177e4 983
ce97a097
JS
984static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
985 void __iomem *base_addr)
e941027f
JS
986{
987 struct cyclades_port *info;
988 struct tty_struct *tty;
65f76a82
JS
989 int len, index = cinfo->bus_index;
990 u8 save_xir, channel, save_car, data, char_count;
e941027f 991
e941027f 992#ifdef CY_DEBUG_INTERRUPTS
ce97a097 993 printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
e941027f 994#endif
ce97a097 995 /* determine the channel & change to that context */
65f76a82
JS
996 save_xir = readb(base_addr + (CyRIR << index));
997 channel = save_xir & CyIRChannel;
ce97a097
JS
998 info = &cinfo->ports[channel + chip * 4];
999 save_car = readb(base_addr + (CyCAR << index));
1000 cy_writeb(base_addr + (CyCAR << index), save_xir);
1001
1002 /* if there is nowhere to put the data, discard it */
77451e53 1003 if (info->port.tty == NULL) {
65f76a82
JS
1004 if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
1005 CyIVRRxEx) { /* exception */
ce97a097
JS
1006 data = readb(base_addr + (CyRDSR << index));
1007 } else { /* normal character reception */
1008 char_count = readb(base_addr + (CyRDCR << index));
1009 while (char_count--)
db05c3b1 1010 data = readb(base_addr + (CyRDSR << index));
ce97a097
JS
1011 }
1012 goto end;
1013 }
1014 /* there is an open port for this data */
77451e53 1015 tty = info->port.tty;
65f76a82
JS
1016 if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
1017 CyIVRRxEx) { /* exception */
ce97a097
JS
1018 data = readb(base_addr + (CyRDSR << index));
1019
1020 /* For statistics only */
1021 if (data & CyBREAK)
1022 info->icount.brk++;
1023 else if (data & CyFRAME)
1024 info->icount.frame++;
1025 else if (data & CyPARITY)
1026 info->icount.parity++;
1027 else if (data & CyOVERRUN)
1028 info->icount.overrun++;
1029
1030 if (data & info->ignore_status_mask) {
1031 info->icount.rx++;
ce97a097
JS
1032 return;
1033 }
1034 if (tty_buffer_request_room(tty, 1)) {
1035 if (data & info->read_status_mask) {
1036 if (data & CyBREAK) {
1037 tty_insert_flip_char(tty,
1038 readb(base_addr + (CyRDSR <<
1039 index)), TTY_BREAK);
1040 info->icount.rx++;
77451e53 1041 if (info->port.flags & ASYNC_SAK)
ce97a097
JS
1042 do_SAK(tty);
1043 } else if (data & CyFRAME) {
15ed6cc0 1044 tty_insert_flip_char(tty,
ce97a097
JS
1045 readb(base_addr + (CyRDSR <<
1046 index)), TTY_FRAME);
1047 info->icount.rx++;
1048 info->idle_stats.frame_errs++;
1049 } else if (data & CyPARITY) {
1050 /* Pieces of seven... */
1051 tty_insert_flip_char(tty,
1052 readb(base_addr + (CyRDSR <<
1053 index)), TTY_PARITY);
1054 info->icount.rx++;
1055 info->idle_stats.parity_errs++;
1056 } else if (data & CyOVERRUN) {
1057 tty_insert_flip_char(tty, 0,
1058 TTY_OVERRUN);
1059 info->icount.rx++;
1060 /* If the flip buffer itself is
1061 overflowing, we still lose
1062 the next incoming character.
1063 */
1064 tty_insert_flip_char(tty,
1065 readb(base_addr + (CyRDSR <<
1066 index)), TTY_FRAME);
02f1175c 1067 info->icount.rx++;
02f1175c 1068 info->idle_stats.overruns++;
ce97a097
JS
1069 /* These two conditions may imply */
1070 /* a normal read should be done. */
1071 /* } else if(data & CyTIMEOUT) { */
1072 /* } else if(data & CySPECHAR) { */
1073 } else {
1074 tty_insert_flip_char(tty, 0,
1075 TTY_NORMAL);
1076 info->icount.rx++;
02f1175c 1077 }
ce97a097
JS
1078 } else {
1079 tty_insert_flip_char(tty, 0, TTY_NORMAL);
1080 info->icount.rx++;
1081 }
1082 } else {
1083 /* there was a software buffer overrun and nothing
1084 * could be done about it!!! */
1085 info->icount.buf_overrun++;
1086 info->idle_stats.overruns++;
1087 }
1088 } else { /* normal character reception */
1089 /* load # chars available from the chip */
1090 char_count = readb(base_addr + (CyRDCR << index));
e941027f
JS
1091
1092#ifdef CY_ENABLE_MONITORING
ce97a097
JS
1093 ++info->mon.int_count;
1094 info->mon.char_count += char_count;
1095 if (char_count > info->mon.char_max)
1096 info->mon.char_max = char_count;
1097 info->mon.char_last = char_count;
e941027f 1098#endif
ce97a097
JS
1099 len = tty_buffer_request_room(tty, char_count);
1100 while (len--) {
1101 data = readb(base_addr + (CyRDSR << index));
1102 tty_insert_flip_char(tty, data, TTY_NORMAL);
1103 info->idle_stats.recv_bytes++;
1104 info->icount.rx++;
e941027f 1105#ifdef CY_16Y_HACK
ce97a097 1106 udelay(10L);
e941027f 1107#endif
e941027f 1108 }
ce97a097 1109 info->idle_stats.recv_idle = jiffies;
e941027f 1110 }
ce97a097
JS
1111 tty_schedule_flip(tty);
1112end:
1113 /* end of service */
1114 cy_writeb(base_addr + (CyRIR << index), save_xir & 0x3f);
1115 cy_writeb(base_addr + (CyCAR << index), save_car);
ce97a097 1116}
e941027f 1117
65f76a82 1118static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
ce97a097
JS
1119 void __iomem *base_addr)
1120{
1121 struct cyclades_port *info;
65f76a82
JS
1122 int char_count, index = cinfo->bus_index;
1123 u8 save_xir, channel, save_car, outch;
ce97a097
JS
1124
1125 /* Since we only get here when the transmit buffer
1126 is empty, we know we can always stuff a dozen
1127 characters. */
e941027f 1128#ifdef CY_DEBUG_INTERRUPTS
ce97a097 1129 printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
e941027f
JS
1130#endif
1131
ce97a097 1132 /* determine the channel & change to that context */
65f76a82
JS
1133 save_xir = readb(base_addr + (CyTIR << index));
1134 channel = save_xir & CyIRChannel;
ce97a097
JS
1135 save_car = readb(base_addr + (CyCAR << index));
1136 cy_writeb(base_addr + (CyCAR << index), save_xir);
1137
1138 /* validate the port# (as configured and open) */
1139 if (channel + chip * 4 >= cinfo->nports) {
1140 cy_writeb(base_addr + (CySRER << index),
1141 readb(base_addr + (CySRER << index)) & ~CyTxRdy);
1142 goto end;
1143 }
1144 info = &cinfo->ports[channel + chip * 4];
77451e53 1145 if (info->port.tty == NULL) {
ce97a097
JS
1146 cy_writeb(base_addr + (CySRER << index),
1147 readb(base_addr + (CySRER << index)) & ~CyTxRdy);
1148 goto end;
1149 }
02f1175c 1150
ce97a097
JS
1151 /* load the on-chip space for outbound data */
1152 char_count = info->xmit_fifo_size;
02f1175c 1153
ce97a097
JS
1154 if (info->x_char) { /* send special char */
1155 outch = info->x_char;
1156 cy_writeb(base_addr + (CyTDR << index), outch);
1157 char_count--;
1158 info->icount.tx++;
1159 info->x_char = 0;
1160 }
02f1175c 1161
ce97a097
JS
1162 if (info->breakon || info->breakoff) {
1163 if (info->breakon) {
1164 cy_writeb(base_addr + (CyTDR << index), 0);
1165 cy_writeb(base_addr + (CyTDR << index), 0x81);
1166 info->breakon = 0;
1167 char_count -= 2;
e941027f 1168 }
ce97a097
JS
1169 if (info->breakoff) {
1170 cy_writeb(base_addr + (CyTDR << index), 0);
1171 cy_writeb(base_addr + (CyTDR << index), 0x83);
1172 info->breakoff = 0;
1173 char_count -= 2;
e941027f 1174 }
ce97a097 1175 }
02f1175c 1176
ce97a097
JS
1177 while (char_count-- > 0) {
1178 if (!info->xmit_cnt) {
1179 if (readb(base_addr + (CySRER << index)) & CyTxMpty) {
1180 cy_writeb(base_addr + (CySRER << index),
1181 readb(base_addr + (CySRER << index)) &
02f1175c 1182 ~CyTxMpty);
ce97a097
JS
1183 } else {
1184 cy_writeb(base_addr + (CySRER << index),
1185 (readb(base_addr + (CySRER << index)) &
02f1175c 1186 ~CyTxRdy) | CyTxMpty);
02f1175c 1187 }
ce97a097
JS
1188 goto done;
1189 }
77451e53 1190 if (info->port.xmit_buf == NULL) {
ce97a097
JS
1191 cy_writeb(base_addr + (CySRER << index),
1192 readb(base_addr + (CySRER << index)) &
02f1175c 1193 ~CyTxRdy);
ce97a097
JS
1194 goto done;
1195 }
77451e53 1196 if (info->port.tty->stopped || info->port.tty->hw_stopped) {
ce97a097
JS
1197 cy_writeb(base_addr + (CySRER << index),
1198 readb(base_addr + (CySRER << index)) &
02f1175c 1199 ~CyTxRdy);
ce97a097
JS
1200 goto done;
1201 }
1202 /* Because the Embedded Transmit Commands have been enabled,
1203 * we must check to see if the escape character, NULL, is being
1204 * sent. If it is, we must ensure that there is room for it to
1205 * be doubled in the output stream. Therefore we no longer
1206 * advance the pointer when the character is fetched, but
1207 * rather wait until after the check for a NULL output
1208 * character. This is necessary because there may not be room
1209 * for the two chars needed to send a NULL.)
1210 */
77451e53 1211 outch = info->port.xmit_buf[info->xmit_tail];
ce97a097
JS
1212 if (outch) {
1213 info->xmit_cnt--;
1214 info->xmit_tail = (info->xmit_tail + 1) &
1215 (SERIAL_XMIT_SIZE - 1);
1216 cy_writeb(base_addr + (CyTDR << index), outch);
1217 info->icount.tx++;
1218 } else {
1219 if (char_count > 1) {
02f1175c
JS
1220 info->xmit_cnt--;
1221 info->xmit_tail = (info->xmit_tail + 1) &
ce97a097 1222 (SERIAL_XMIT_SIZE - 1);
02f1175c 1223 cy_writeb(base_addr + (CyTDR << index), outch);
ce97a097 1224 cy_writeb(base_addr + (CyTDR << index), 0);
02f1175c 1225 info->icount.tx++;
ce97a097 1226 char_count--;
02f1175c 1227 }
e941027f 1228 }
e941027f
JS
1229 }
1230
ce97a097 1231done:
77451e53 1232 tty_wakeup(info->port.tty);
ce97a097
JS
1233end:
1234 /* end of service */
1235 cy_writeb(base_addr + (CyTIR << index), save_xir & 0x3f);
1236 cy_writeb(base_addr + (CyCAR << index), save_car);
ce97a097 1237}
02f1175c 1238
ce97a097
JS
1239static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
1240 void __iomem *base_addr)
1241{
1242 struct cyclades_port *info;
65f76a82
JS
1243 int index = cinfo->bus_index;
1244 u8 save_xir, channel, save_car, mdm_change, mdm_status;
ce97a097
JS
1245
1246 /* determine the channel & change to that context */
65f76a82
JS
1247 save_xir = readb(base_addr + (CyMIR << index));
1248 channel = save_xir & CyIRChannel;
ce97a097
JS
1249 info = &cinfo->ports[channel + chip * 4];
1250 save_car = readb(base_addr + (CyCAR << index));
1251 cy_writeb(base_addr + (CyCAR << index), save_xir);
1252
1253 mdm_change = readb(base_addr + (CyMISR << index));
1254 mdm_status = readb(base_addr + (CyMSVR1 << index));
1255
77451e53 1256 if (!info->port.tty)
ce97a097
JS
1257 goto end;
1258
1259 if (mdm_change & CyANY_DELTA) {
1260 /* For statistics only */
1261 if (mdm_change & CyDCD)
1262 info->icount.dcd++;
1263 if (mdm_change & CyCTS)
1264 info->icount.cts++;
1265 if (mdm_change & CyDSR)
1266 info->icount.dsr++;
1267 if (mdm_change & CyRI)
1268 info->icount.rng++;
1269
1270 wake_up_interruptible(&info->delta_msr_wait);
1271 }
1272
77451e53 1273 if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
ce97a097 1274 if (!(mdm_status & CyDCD)) {
77451e53
AC
1275 tty_hangup(info->port.tty);
1276 info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
ce97a097 1277 }
77451e53 1278 wake_up_interruptible(&info->port.open_wait);
ce97a097 1279 }
77451e53
AC
1280 if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
1281 if (info->port.tty->hw_stopped) {
ce97a097
JS
1282 if (mdm_status & CyCTS) {
1283 /* cy_start isn't used
1284 because... !!! */
77451e53 1285 info->port.tty->hw_stopped = 0;
ce97a097
JS
1286 cy_writeb(base_addr + (CySRER << index),
1287 readb(base_addr + (CySRER << index)) |
1288 CyTxRdy);
77451e53 1289 tty_wakeup(info->port.tty);
02f1175c 1290 }
ce97a097
JS
1291 } else {
1292 if (!(mdm_status & CyCTS)) {
1293 /* cy_stop isn't used
1294 because ... !!! */
77451e53 1295 info->port.tty->hw_stopped = 1;
ce97a097
JS
1296 cy_writeb(base_addr + (CySRER << index),
1297 readb(base_addr + (CySRER << index)) &
1298 ~CyTxRdy);
02f1175c 1299 }
e941027f 1300 }
e941027f 1301 }
ce97a097
JS
1302/* if (mdm_change & CyDSR) {
1303 }
1304 if (mdm_change & CyRI) {
1305 }*/
1306end:
1307 /* end of service */
1308 cy_writeb(base_addr + (CyMIR << index), save_xir & 0x3f);
1309 cy_writeb(base_addr + (CyCAR << index), save_car);
e941027f
JS
1310}
1311
1da177e4
LT
1312/* The real interrupt service routine is called
1313 whenever the card wants its hand held--chars
1314 received, out buffer empty, modem change, etc.
1315 */
02f1175c 1316static irqreturn_t cyy_interrupt(int irq, void *dev_id)
1da177e4 1317{
02f1175c 1318 int status;
f7429034 1319 struct cyclades_card *cinfo = dev_id;
02f1175c 1320 void __iomem *base_addr, *card_base_addr;
65f76a82 1321 unsigned int chip, too_many, had_work;
02f1175c 1322 int index;
02f1175c 1323
f7429034 1324 if (unlikely(cinfo == NULL)) {
1da177e4 1325#ifdef CY_DEBUG_INTERRUPTS
15ed6cc0
AC
1326 printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",
1327 irq);
1da177e4 1328#endif
02f1175c
JS
1329 return IRQ_NONE; /* spurious interrupt */
1330 }
1331
1332 card_base_addr = cinfo->base_addr;
1333 index = cinfo->bus_index;
1334
f1e83c6c
JS
1335 /* card was not initialized yet (e.g. DEBUG_SHIRQ) */
1336 if (unlikely(card_base_addr == NULL))
1337 return IRQ_HANDLED;
1338
02f1175c
JS
1339 /* This loop checks all chips in the card. Make a note whenever
1340 _any_ chip had some work to do, as this is considered an
1341 indication that there will be more to do. Only when no chip
1342 has any work does this outermost loop exit.
1343 */
1344 do {
1345 had_work = 0;
1346 for (chip = 0; chip < cinfo->num_chips; chip++) {
1347 base_addr = cinfo->base_addr +
1348 (cy_chip_offset[chip] << index);
1349 too_many = 0;
db05c3b1 1350 while ((status = readb(base_addr +
02f1175c
JS
1351 (CySVRR << index))) != 0x00) {
1352 had_work++;
1353 /* The purpose of the following test is to ensure that
1354 no chip can monopolize the driver. This forces the
1355 chips to be checked in a round-robin fashion (after
1356 draining each of a bunch (1000) of characters).
1357 */
ce97a097 1358 if (1000 < too_many++)
02f1175c 1359 break;
1c0a387c 1360 spin_lock(&cinfo->card_lock);
ce97a097
JS
1361 if (status & CySRReceive) /* rx intr */
1362 cyy_chip_rx(cinfo, chip, base_addr);
1363 if (status & CySRTransmit) /* tx intr */
1364 cyy_chip_tx(cinfo, chip, base_addr);
1365 if (status & CySRModem) /* modem intr */
1366 cyy_chip_modem(cinfo, chip, base_addr);
1c0a387c 1367 spin_unlock(&cinfo->card_lock);
02f1175c
JS
1368 }
1369 }
1370 } while (had_work);
1371
1372 /* clear interrupts */
1373 spin_lock(&cinfo->card_lock);
1374 cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0);
1375 /* Cy_ClrIntr is 0x1800 */
1376 spin_unlock(&cinfo->card_lock);
1377 return IRQ_HANDLED;
1378} /* cyy_interrupt */
1da177e4
LT
1379
1380/***********************************************************/
1381/********* End of block of Cyclom-Y specific code **********/
15ed6cc0 1382/******** Start of block of Cyclades-Z specific code *******/
1da177e4
LT
1383/***********************************************************/
1384
1385static int
02f1175c 1386cyz_fetch_msg(struct cyclades_card *cinfo,
15ed6cc0 1387 __u32 *channel, __u8 *cmd, __u32 *param)
1da177e4 1388{
02f1175c
JS
1389 struct FIRM_ID __iomem *firm_id;
1390 struct ZFW_CTRL __iomem *zfw_ctrl;
1391 struct BOARD_CTRL __iomem *board_ctrl;
1392 unsigned long loc_doorbell;
1393
1394 firm_id = cinfo->base_addr + ID_ADDRESS;
db05c3b1 1395 zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c
JS
1396 board_ctrl = &zfw_ctrl->board_ctrl;
1397
97e87f8e 1398 loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
02f1175c
JS
1399 if (loc_doorbell) {
1400 *cmd = (char)(0xff & loc_doorbell);
db05c3b1
JS
1401 *channel = readl(&board_ctrl->fwcmd_channel);
1402 *param = (__u32) readl(&board_ctrl->fwcmd_param);
97e87f8e 1403 cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
02f1175c
JS
1404 return 1;
1405 }
1406 return 0;
1407} /* cyz_fetch_msg */
1da177e4
LT
1408
1409static int
02f1175c 1410cyz_issue_cmd(struct cyclades_card *cinfo,
1a86b5e3 1411 __u32 channel, __u8 cmd, __u32 param)
1da177e4 1412{
02f1175c
JS
1413 struct FIRM_ID __iomem *firm_id;
1414 struct ZFW_CTRL __iomem *zfw_ctrl;
1415 struct BOARD_CTRL __iomem *board_ctrl;
1a86b5e3 1416 __u32 __iomem *pci_doorbell;
65f76a82 1417 unsigned int index;
02f1175c
JS
1418
1419 firm_id = cinfo->base_addr + ID_ADDRESS;
15ed6cc0 1420 if (!ISZLOADED(*cinfo))
096dcfce 1421 return -1;
15ed6cc0 1422
db05c3b1 1423 zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c
JS
1424 board_ctrl = &zfw_ctrl->board_ctrl;
1425
1426 index = 0;
97e87f8e 1427 pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
db05c3b1 1428 while ((readl(pci_doorbell) & 0xff) != 0) {
15ed6cc0 1429 if (index++ == 1000)
db05c3b1 1430 return (int)(readl(pci_doorbell) & 0xff);
02f1175c
JS
1431 udelay(50L);
1432 }
1433 cy_writel(&board_ctrl->hcmd_channel, channel);
1434 cy_writel(&board_ctrl->hcmd_param, param);
1435 cy_writel(pci_doorbell, (long)cmd);
1436
096dcfce 1437 return 0;
02f1175c 1438} /* cyz_issue_cmd */
1da177e4 1439
65f76a82 1440static void cyz_handle_rx(struct cyclades_port *info,
ad39c300 1441 struct BUF_CTRL __iomem *buf_ctrl)
1da177e4 1442{
875b206b 1443 struct cyclades_card *cinfo = info->card;
77451e53 1444 struct tty_struct *tty = info->port.tty;
65f76a82 1445 unsigned int char_count;
02f1175c 1446 int len;
1da177e4 1447#ifdef BLOCKMOVE
ce71b0ff 1448 unsigned char *buf;
1da177e4 1449#else
02f1175c 1450 char data;
1da177e4 1451#endif
ad39c300 1452 __u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
1da177e4 1453
db05c3b1
JS
1454 rx_get = new_rx_get = readl(&buf_ctrl->rx_get);
1455 rx_put = readl(&buf_ctrl->rx_put);
1456 rx_bufsize = readl(&buf_ctrl->rx_bufsize);
1457 rx_bufaddr = readl(&buf_ctrl->rx_bufaddr);
02f1175c
JS
1458 if (rx_put >= rx_get)
1459 char_count = rx_put - rx_get;
1460 else
1461 char_count = rx_put - rx_get + rx_bufsize;
1da177e4 1462
02f1175c 1463 if (char_count) {
1da177e4 1464#ifdef CY_ENABLE_MONITORING
02f1175c
JS
1465 info->mon.int_count++;
1466 info->mon.char_count += char_count;
1467 if (char_count > info->mon.char_max)
1468 info->mon.char_max = char_count;
1469 info->mon.char_last = char_count;
1da177e4 1470#endif
f7429034 1471 if (tty == NULL) {
02f1175c
JS
1472 /* flush received characters */
1473 new_rx_get = (new_rx_get + char_count) &
1474 (rx_bufsize - 1);
1475 info->rflush_count++;
1476 } else {
1da177e4 1477#ifdef BLOCKMOVE
02f1175c
JS
1478 /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
1479 for performance, but because of buffer boundaries, there
1480 may be several steps to the operation */
ce71b0ff
JS
1481 while (1) {
1482 len = tty_prepare_flip_string(tty, &buf,
1483 char_count);
1484 if (!len)
1485 break;
1486
1487 len = min_t(unsigned int, min(len, char_count),
1488 rx_bufsize - new_rx_get);
1489
1490 memcpy_fromio(buf, cinfo->base_addr +
1491 rx_bufaddr + new_rx_get, len);
1492
1493 new_rx_get = (new_rx_get + len) &
02f1175c 1494 (rx_bufsize - 1);
ce71b0ff
JS
1495 char_count -= len;
1496 info->icount.rx += len;
1497 info->idle_stats.recv_bytes += len;
02f1175c 1498 }
1da177e4 1499#else
02f1175c
JS
1500 len = tty_buffer_request_room(tty, char_count);
1501 while (len--) {
db05c3b1 1502 data = readb(cinfo->base_addr + rx_bufaddr +
02f1175c 1503 new_rx_get);
15ed6cc0
AC
1504 new_rx_get = (new_rx_get + 1) &
1505 (rx_bufsize - 1);
02f1175c
JS
1506 tty_insert_flip_char(tty, data, TTY_NORMAL);
1507 info->idle_stats.recv_bytes++;
1508 info->icount.rx++;
1509 }
1da177e4
LT
1510#endif
1511#ifdef CONFIG_CYZ_INTR
02f1175c
JS
1512 /* Recalculate the number of chars in the RX buffer and issue
1513 a cmd in case it's higher than the RX high water mark */
db05c3b1 1514 rx_put = readl(&buf_ctrl->rx_put);
02f1175c
JS
1515 if (rx_put >= rx_get)
1516 char_count = rx_put - rx_get;
1517 else
1518 char_count = rx_put - rx_get + rx_bufsize;
65f76a82 1519 if (char_count >= readl(&buf_ctrl->rx_threshold) &&
ebafeeff
JS
1520 !timer_pending(&cyz_rx_full_timer[
1521 info->line]))
1522 mod_timer(&cyz_rx_full_timer[info->line],
1523 jiffies + 1);
1da177e4 1524#endif
02f1175c
JS
1525 info->idle_stats.recv_idle = jiffies;
1526 tty_schedule_flip(tty);
1527 }
1528 /* Update rx_get */
1529 cy_writel(&buf_ctrl->rx_get, new_rx_get);
1da177e4 1530 }
1da177e4
LT
1531}
1532
65f76a82 1533static void cyz_handle_tx(struct cyclades_port *info,
ad39c300 1534 struct BUF_CTRL __iomem *buf_ctrl)
1da177e4 1535{
875b206b 1536 struct cyclades_card *cinfo = info->card;
77451e53 1537 struct tty_struct *tty = info->port.tty;
65f76a82
JS
1538 u8 data;
1539 unsigned int char_count;
1da177e4 1540#ifdef BLOCKMOVE
02f1175c 1541 int small_count;
1da177e4 1542#endif
ad39c300 1543 __u32 tx_put, tx_get, tx_bufsize, tx_bufaddr;
1da177e4 1544
02f1175c
JS
1545 if (info->xmit_cnt <= 0) /* Nothing to transmit */
1546 return;
1da177e4 1547
db05c3b1
JS
1548 tx_get = readl(&buf_ctrl->tx_get);
1549 tx_put = readl(&buf_ctrl->tx_put);
1550 tx_bufsize = readl(&buf_ctrl->tx_bufsize);
1551 tx_bufaddr = readl(&buf_ctrl->tx_bufaddr);
02f1175c
JS
1552 if (tx_put >= tx_get)
1553 char_count = tx_get - tx_put - 1 + tx_bufsize;
1554 else
1555 char_count = tx_get - tx_put - 1;
1da177e4 1556
02f1175c 1557 if (char_count) {
1da177e4 1558
f7429034 1559 if (tty == NULL)
02f1175c 1560 goto ztxdone;
1da177e4 1561
02f1175c
JS
1562 if (info->x_char) { /* send special char */
1563 data = info->x_char;
1da177e4 1564
02f1175c
JS
1565 cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
1566 tx_put = (tx_put + 1) & (tx_bufsize - 1);
1567 info->x_char = 0;
1568 char_count--;
1569 info->icount.tx++;
02f1175c 1570 }
1da177e4 1571#ifdef BLOCKMOVE
02f1175c
JS
1572 while (0 < (small_count = min_t(unsigned int,
1573 tx_bufsize - tx_put, min_t(unsigned int,
1574 (SERIAL_XMIT_SIZE - info->xmit_tail),
1575 min_t(unsigned int, info->xmit_cnt,
1576 char_count))))) {
1577
1578 memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
1579 tx_put),
77451e53 1580 &info->port.xmit_buf[info->xmit_tail],
02f1175c
JS
1581 small_count);
1582
1583 tx_put = (tx_put + small_count) & (tx_bufsize - 1);
1584 char_count -= small_count;
1585 info->icount.tx += small_count;
1586 info->xmit_cnt -= small_count;
1587 info->xmit_tail = (info->xmit_tail + small_count) &
1588 (SERIAL_XMIT_SIZE - 1);
02f1175c 1589 }
1da177e4 1590#else
02f1175c 1591 while (info->xmit_cnt && char_count) {
77451e53 1592 data = info->port.xmit_buf[info->xmit_tail];
02f1175c
JS
1593 info->xmit_cnt--;
1594 info->xmit_tail = (info->xmit_tail + 1) &
1595 (SERIAL_XMIT_SIZE - 1);
1596
1597 cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
1598 tx_put = (tx_put + 1) & (tx_bufsize - 1);
1599 char_count--;
1600 info->icount.tx++;
02f1175c 1601 }
1da177e4 1602#endif
ebafeeff 1603 tty_wakeup(tty);
7fa57a0c 1604ztxdone:
02f1175c
JS
1605 /* Update tx_put */
1606 cy_writel(&buf_ctrl->tx_put, tx_put);
1da177e4 1607 }
1da177e4
LT
1608}
1609
02f1175c 1610static void cyz_handle_cmd(struct cyclades_card *cinfo)
1da177e4 1611{
02f1175c
JS
1612 struct tty_struct *tty;
1613 struct cyclades_port *info;
ad39c300
JS
1614 static struct FIRM_ID __iomem *firm_id;
1615 static struct ZFW_CTRL __iomem *zfw_ctrl;
1616 static struct BOARD_CTRL __iomem *board_ctrl;
1617 static struct CH_CTRL __iomem *ch_ctrl;
1618 static struct BUF_CTRL __iomem *buf_ctrl;
101b8159 1619 __u32 channel, param, fw_ver;
1a86b5e3 1620 __u8 cmd;
02f1175c
JS
1621 int special_count;
1622 int delta_count;
1623
1624 firm_id = cinfo->base_addr + ID_ADDRESS;
db05c3b1 1625 zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c 1626 board_ctrl = &zfw_ctrl->board_ctrl;
db05c3b1 1627 fw_ver = readl(&board_ctrl->fw_version);
02f1175c
JS
1628
1629 while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
1630 special_count = 0;
1631 delta_count = 0;
dd025c0c 1632 info = &cinfo->ports[channel];
77451e53 1633 tty = info->port.tty;
15ed6cc0 1634 if (tty == NULL)
02f1175c 1635 continue;
f7429034 1636
02f1175c
JS
1637 ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
1638 buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
1639
1640 switch (cmd) {
1641 case C_CM_PR_ERROR:
1642 tty_insert_flip_char(tty, 0, TTY_PARITY);
1643 info->icount.rx++;
1644 special_count++;
1645 break;
1646 case C_CM_FR_ERROR:
1647 tty_insert_flip_char(tty, 0, TTY_FRAME);
1648 info->icount.rx++;
1649 special_count++;
1650 break;
1651 case C_CM_RXBRK:
1652 tty_insert_flip_char(tty, 0, TTY_BREAK);
1653 info->icount.rx++;
1654 special_count++;
1655 break;
1656 case C_CM_MDCD:
1657 info->icount.dcd++;
1658 delta_count++;
77451e53 1659 if (info->port.flags & ASYNC_CHECK_CD) {
02f1175c 1660 if ((fw_ver > 241 ? ((u_long) param) :
db05c3b1 1661 readl(&ch_ctrl->rs_status)) &
02f1175c 1662 C_RS_DCD) {
77451e53 1663 wake_up_interruptible(&info->port.open_wait);
02f1175c 1664 } else {
77451e53
AC
1665 tty_hangup(info->port.tty);
1666 wake_up_interruptible(&info->port.open_wait);
1667 info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
02f1175c
JS
1668 }
1669 }
1670 break;
1671 case C_CM_MCTS:
1672 info->icount.cts++;
1673 delta_count++;
1674 break;
1675 case C_CM_MRI:
1676 info->icount.rng++;
1677 delta_count++;
1678 break;
1679 case C_CM_MDSR:
1680 info->icount.dsr++;
1681 delta_count++;
1682 break;
1da177e4 1683#ifdef Z_WAKE
02f1175c 1684 case C_CM_IOCTLW:
ebafeeff 1685 complete(&info->shutdown_wait);
02f1175c 1686 break;
1da177e4
LT
1687#endif
1688#ifdef CONFIG_CYZ_INTR
02f1175c
JS
1689 case C_CM_RXHIWM:
1690 case C_CM_RXNNDT:
1691 case C_CM_INTBACK2:
1692 /* Reception Interrupt */
1da177e4 1693#ifdef CY_DEBUG_INTERRUPTS
21719191
JS
1694 printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
1695 "port %ld\n", info->card, channel);
1da177e4 1696#endif
65f76a82 1697 cyz_handle_rx(info, buf_ctrl);
02f1175c
JS
1698 break;
1699 case C_CM_TXBEMPTY:
1700 case C_CM_TXLOWWM:
1701 case C_CM_INTBACK:
1702 /* Transmission Interrupt */
1da177e4 1703#ifdef CY_DEBUG_INTERRUPTS
21719191
JS
1704 printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
1705 "port %ld\n", info->card, channel);
1da177e4 1706#endif
65f76a82 1707 cyz_handle_tx(info, buf_ctrl);
02f1175c
JS
1708 break;
1709#endif /* CONFIG_CYZ_INTR */
1710 case C_CM_FATAL:
1711 /* should do something with this !!! */
1712 break;
1713 default:
1714 break;
1715 }
1716 if (delta_count)
ebafeeff 1717 wake_up_interruptible(&info->delta_msr_wait);
02f1175c
JS
1718 if (special_count)
1719 tty_schedule_flip(tty);
1da177e4 1720 }
1da177e4
LT
1721}
1722
1723#ifdef CONFIG_CYZ_INTR
02f1175c 1724static irqreturn_t cyz_interrupt(int irq, void *dev_id)
1da177e4 1725{
f7429034 1726 struct cyclades_card *cinfo = dev_id;
1da177e4 1727
f7429034 1728 if (unlikely(!ISZLOADED(*cinfo))) {
1da177e4 1729#ifdef CY_DEBUG_INTERRUPTS
21719191
JS
1730 printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
1731 "(IRQ%d).\n", irq);
1da177e4 1732#endif
02f1175c
JS
1733 return IRQ_NONE;
1734 }
1da177e4 1735
02f1175c
JS
1736 /* Handle the interrupts */
1737 cyz_handle_cmd(cinfo);
1da177e4 1738
02f1175c
JS
1739 return IRQ_HANDLED;
1740} /* cyz_interrupt */
1da177e4 1741
02f1175c 1742static void cyz_rx_restart(unsigned long arg)
1da177e4 1743{
02f1175c 1744 struct cyclades_port *info = (struct cyclades_port *)arg;
875b206b 1745 struct cyclades_card *card = info->card;
02f1175c 1746 int retval;
875b206b 1747 __u32 channel = info->line - card->first_line;
02f1175c
JS
1748 unsigned long flags;
1749
9fa1b3b1 1750 spin_lock_irqsave(&card->card_lock, flags);
875b206b 1751 retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L);
02f1175c 1752 if (retval != 0) {
21719191 1753 printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n",
02f1175c
JS
1754 info->line, retval);
1755 }
9fa1b3b1 1756 spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4
LT
1757}
1758
02f1175c 1759#else /* CONFIG_CYZ_INTR */
1da177e4 1760
02f1175c 1761static void cyz_poll(unsigned long arg)
1da177e4 1762{
02f1175c
JS
1763 struct cyclades_card *cinfo;
1764 struct cyclades_port *info;
1765 struct tty_struct *tty;
c4923b4f
JS
1766 struct FIRM_ID __iomem *firm_id;
1767 struct ZFW_CTRL __iomem *zfw_ctrl;
1768 struct BOARD_CTRL __iomem *board_ctrl;
c4923b4f 1769 struct BUF_CTRL __iomem *buf_ctrl;
b7050906 1770 unsigned long expires = jiffies + HZ;
65f76a82 1771 unsigned int port, card;
1da177e4 1772
02f1175c
JS
1773 for (card = 0; card < NR_CARDS; card++) {
1774 cinfo = &cy_card[card];
1775
1776 if (!IS_CYC_Z(*cinfo))
1777 continue;
1778 if (!ISZLOADED(*cinfo))
1779 continue;
1780
1781 firm_id = cinfo->base_addr + ID_ADDRESS;
1782 zfw_ctrl = cinfo->base_addr +
db05c3b1 1783 (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c 1784 board_ctrl = &(zfw_ctrl->board_ctrl);
1da177e4
LT
1785
1786 /* Skip first polling cycle to avoid racing conditions with the FW */
02f1175c 1787 if (!cinfo->intr_enabled) {
db05c3b1 1788 cinfo->nports = (int)readl(&board_ctrl->n_channel);
02f1175c
JS
1789 cinfo->intr_enabled = 1;
1790 continue;
1791 }
1da177e4 1792
02f1175c 1793 cyz_handle_cmd(cinfo);
1da177e4 1794
02f1175c 1795 for (port = 0; port < cinfo->nports; port++) {
dd025c0c 1796 info = &cinfo->ports[port];
77451e53 1797 tty = info->port.tty;
02f1175c 1798 buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
1da177e4 1799
02f1175c 1800 if (!info->throttle)
65f76a82
JS
1801 cyz_handle_rx(info, buf_ctrl);
1802 cyz_handle_tx(info, buf_ctrl);
02f1175c
JS
1803 }
1804 /* poll every 'cyz_polling_cycle' period */
b7050906 1805 expires = jiffies + cyz_polling_cycle;
1da177e4 1806 }
b7050906 1807 mod_timer(&cyz_timerlist, expires);
02f1175c 1808} /* cyz_poll */
1da177e4 1809
02f1175c 1810#endif /* CONFIG_CYZ_INTR */
1da177e4
LT
1811
1812/********** End of block of Cyclades-Z specific code *********/
1813/***********************************************************/
1814
1da177e4
LT
1815/* This is called whenever a port becomes active;
1816 interrupts are enabled and DTR & RTS are turned on.
1817 */
02f1175c 1818static int startup(struct cyclades_port *info)
1da177e4 1819{
875b206b 1820 struct cyclades_card *card;
02f1175c
JS
1821 unsigned long flags;
1822 int retval = 0;
1823 void __iomem *base_addr;
875b206b 1824 int chip, channel, index;
02f1175c 1825 unsigned long page;
1da177e4 1826
02f1175c 1827 card = info->card;
875b206b 1828 channel = info->line - card->first_line;
1da177e4 1829
02f1175c
JS
1830 page = get_zeroed_page(GFP_KERNEL);
1831 if (!page)
1832 return -ENOMEM;
1da177e4 1833
9fa1b3b1 1834 spin_lock_irqsave(&card->card_lock, flags);
1da177e4 1835
77451e53 1836 if (info->port.flags & ASYNC_INITIALIZED) {
02f1175c
JS
1837 free_page(page);
1838 goto errout;
1839 }
1da177e4 1840
02f1175c 1841 if (!info->type) {
77451e53
AC
1842 if (info->port.tty)
1843 set_bit(TTY_IO_ERROR, &info->port.tty->flags);
02f1175c
JS
1844 free_page(page);
1845 goto errout;
1846 }
1da177e4 1847
77451e53 1848 if (info->port.xmit_buf)
02f1175c
JS
1849 free_page(page);
1850 else
77451e53 1851 info->port.xmit_buf = (unsigned char *)page;
1da177e4 1852
9fa1b3b1 1853 spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4 1854
02f1175c 1855 set_line_char(info);
1da177e4 1856
875b206b 1857 if (!IS_CYC_Z(*card)) {
02f1175c
JS
1858 chip = channel >> 2;
1859 channel &= 0x03;
875b206b
JS
1860 index = card->bus_index;
1861 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
1da177e4
LT
1862
1863#ifdef CY_DEBUG_OPEN
21719191
JS
1864 printk(KERN_DEBUG "cyc startup card %d, chip %d, channel %d, "
1865 "base_addr %p\n",
1866 card, chip, channel, base_addr);
1da177e4 1867#endif
9fa1b3b1 1868 spin_lock_irqsave(&card->card_lock, flags);
1da177e4 1869
02f1175c 1870 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
1da177e4 1871
02f1175c
JS
1872 cy_writeb(base_addr + (CyRTPR << index),
1873 (info->default_timeout ? info->default_timeout : 0x02));
1874 /* 10ms rx timeout */
1da177e4 1875
02f1175c
JS
1876 cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR,
1877 index);
1da177e4 1878
02f1175c
JS
1879 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
1880 cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
1881 cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
1da177e4
LT
1882
1883#ifdef CY_DEBUG_DTR
21719191
JS
1884 printk(KERN_DEBUG "cyc:startup raising DTR\n");
1885 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
db05c3b1
JS
1886 readb(base_addr + (CyMSVR1 << index)),
1887 readb(base_addr + (CyMSVR2 << index)));
1da177e4
LT
1888#endif
1889
02f1175c 1890 cy_writeb(base_addr + (CySRER << index),
db05c3b1 1891 readb(base_addr + (CySRER << index)) | CyRxData);
77451e53 1892 info->port.flags |= ASYNC_INITIALIZED;
1da177e4 1893
77451e53
AC
1894 if (info->port.tty)
1895 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
02f1175c
JS
1896 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1897 info->breakon = info->breakoff = 0;
1898 memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
1899 info->idle_stats.in_use =
1900 info->idle_stats.recv_idle =
1901 info->idle_stats.xmit_idle = jiffies;
1da177e4 1902
9fa1b3b1 1903 spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4 1904
02f1175c
JS
1905 } else {
1906 struct FIRM_ID __iomem *firm_id;
1907 struct ZFW_CTRL __iomem *zfw_ctrl;
1908 struct BOARD_CTRL __iomem *board_ctrl;
1909 struct CH_CTRL __iomem *ch_ctrl;
1da177e4 1910
875b206b 1911 base_addr = card->base_addr;
1da177e4 1912
02f1175c 1913 firm_id = base_addr + ID_ADDRESS;
15ed6cc0 1914 if (!ISZLOADED(*card))
02f1175c 1915 return -ENODEV;
1da177e4 1916
875b206b 1917 zfw_ctrl = card->base_addr +
db05c3b1 1918 (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c
JS
1919 board_ctrl = &zfw_ctrl->board_ctrl;
1920 ch_ctrl = zfw_ctrl->ch_ctrl;
1da177e4
LT
1921
1922#ifdef CY_DEBUG_OPEN
21719191
JS
1923 printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
1924 "base_addr %p\n", card, channel, base_addr);
1da177e4 1925#endif
9fa1b3b1 1926 spin_lock_irqsave(&card->card_lock, flags);
1da177e4 1927
02f1175c 1928 cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
1da177e4
LT
1929#ifdef Z_WAKE
1930#ifdef CONFIG_CYZ_INTR
02f1175c
JS
1931 cy_writel(&ch_ctrl[channel].intr_enable,
1932 C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
1933 C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
1da177e4 1934#else
02f1175c
JS
1935 cy_writel(&ch_ctrl[channel].intr_enable,
1936 C_IN_IOCTLW | C_IN_MDCD);
1937#endif /* CONFIG_CYZ_INTR */
1da177e4
LT
1938#else
1939#ifdef CONFIG_CYZ_INTR
02f1175c
JS
1940 cy_writel(&ch_ctrl[channel].intr_enable,
1941 C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
1942 C_IN_RXNNDT | C_IN_MDCD);
1da177e4 1943#else
02f1175c
JS
1944 cy_writel(&ch_ctrl[channel].intr_enable, C_IN_MDCD);
1945#endif /* CONFIG_CYZ_INTR */
1946#endif /* Z_WAKE */
1947
875b206b 1948 retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
02f1175c 1949 if (retval != 0) {
21719191
JS
1950 printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was "
1951 "%x\n", info->line, retval);
02f1175c 1952 }
1da177e4 1953
02f1175c 1954 /* Flush RX buffers before raising DTR and RTS */
875b206b 1955 retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L);
02f1175c 1956 if (retval != 0) {
21719191
JS
1957 printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was "
1958 "%x\n", info->line, retval);
02f1175c 1959 }
1da177e4 1960
02f1175c
JS
1961 /* set timeout !!! */
1962 /* set RTS and DTR !!! */
1963 cy_writel(&ch_ctrl[channel].rs_control,
db05c3b1 1964 readl(&ch_ctrl[channel].rs_control) | C_RS_RTS |
02f1175c 1965 C_RS_DTR);
9fa1b3b1 1966 retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
02f1175c 1967 if (retval != 0) {
21719191
JS
1968 printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was "
1969 "%x\n", info->line, retval);
02f1175c 1970 }
1da177e4 1971#ifdef CY_DEBUG_DTR
21719191 1972 printk(KERN_DEBUG "cyc:startup raising Z DTR\n");
1da177e4
LT
1973#endif
1974
02f1175c
JS
1975 /* enable send, recv, modem !!! */
1976
77451e53
AC
1977 info->port.flags |= ASYNC_INITIALIZED;
1978 if (info->port.tty)
1979 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
02f1175c
JS
1980 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1981 info->breakon = info->breakoff = 0;
1982 memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
1983 info->idle_stats.in_use =
1984 info->idle_stats.recv_idle =
1985 info->idle_stats.xmit_idle = jiffies;
1da177e4 1986
9fa1b3b1 1987 spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4 1988 }
1da177e4
LT
1989
1990#ifdef CY_DEBUG_OPEN
21719191 1991 printk(KERN_DEBUG "cyc startup done\n");
1da177e4
LT
1992#endif
1993 return 0;
1994
1995errout:
9fa1b3b1 1996 spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4 1997 return retval;
02f1175c 1998} /* startup */
1da177e4 1999
02f1175c 2000static void start_xmit(struct cyclades_port *info)
1da177e4 2001{
875b206b 2002 struct cyclades_card *card;
02f1175c
JS
2003 unsigned long flags;
2004 void __iomem *base_addr;
875b206b 2005 int chip, channel, index;
1da177e4 2006
02f1175c 2007 card = info->card;
875b206b
JS
2008 channel = info->line - card->first_line;
2009 if (!IS_CYC_Z(*card)) {
02f1175c
JS
2010 chip = channel >> 2;
2011 channel &= 0x03;
875b206b
JS
2012 index = card->bus_index;
2013 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
02f1175c 2014
9fa1b3b1 2015 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
2016 cy_writeb(base_addr + (CyCAR << index), channel);
2017 cy_writeb(base_addr + (CySRER << index),
db05c3b1 2018 readb(base_addr + (CySRER << index)) | CyTxRdy);
9fa1b3b1 2019 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c 2020 } else {
1da177e4 2021#ifdef CONFIG_CYZ_INTR
02f1175c 2022 int retval;
1da177e4 2023
9fa1b3b1 2024 spin_lock_irqsave(&card->card_lock, flags);
875b206b 2025 retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L);
02f1175c 2026 if (retval != 0) {
21719191
JS
2027 printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was "
2028 "%x\n", info->line, retval);
02f1175c 2029 }
9fa1b3b1 2030 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
2031#else /* CONFIG_CYZ_INTR */
2032 /* Don't have to do anything at this time */
2033#endif /* CONFIG_CYZ_INTR */
2034 }
2035} /* start_xmit */
1da177e4
LT
2036
2037/*
2038 * This routine shuts down a serial port; interrupts are disabled,
2039 * and DTR is dropped if the hangup on close termio flag is on.
2040 */
02f1175c 2041static void shutdown(struct cyclades_port *info)
1da177e4 2042{
875b206b 2043 struct cyclades_card *card;
02f1175c
JS
2044 unsigned long flags;
2045 void __iomem *base_addr;
875b206b 2046 int chip, channel, index;
02f1175c 2047
77451e53 2048 if (!(info->port.flags & ASYNC_INITIALIZED))
02f1175c 2049 return;
02f1175c
JS
2050
2051 card = info->card;
875b206b
JS
2052 channel = info->line - card->first_line;
2053 if (!IS_CYC_Z(*card)) {
02f1175c
JS
2054 chip = channel >> 2;
2055 channel &= 0x03;
875b206b
JS
2056 index = card->bus_index;
2057 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
1da177e4
LT
2058
2059#ifdef CY_DEBUG_OPEN
21719191
JS
2060 printk(KERN_DEBUG "cyc shutdown Y card %d, chip %d, "
2061 "channel %d, base_addr %p\n",
2062 card, chip, channel, base_addr);
1da177e4
LT
2063#endif
2064
9fa1b3b1 2065 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
2066
2067 /* Clear delta_msr_wait queue to avoid mem leaks. */
2068 wake_up_interruptible(&info->delta_msr_wait);
1da177e4 2069
77451e53 2070 if (info->port.xmit_buf) {
02f1175c 2071 unsigned char *temp;
77451e53
AC
2072 temp = info->port.xmit_buf;
2073 info->port.xmit_buf = NULL;
02f1175c
JS
2074 free_page((unsigned long)temp);
2075 }
2076 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
77451e53 2077 if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
02f1175c
JS
2078 cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
2079 cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
1da177e4 2080#ifdef CY_DEBUG_DTR
21719191
JS
2081 printk(KERN_DEBUG "cyc shutdown dropping DTR\n");
2082 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
db05c3b1
JS
2083 readb(base_addr + (CyMSVR1 << index)),
2084 readb(base_addr + (CyMSVR2 << index)));
1da177e4 2085#endif
02f1175c
JS
2086 }
2087 cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index);
2088 /* it may be appropriate to clear _XMIT at
2089 some later date (after testing)!!! */
2090
77451e53
AC
2091 if (info->port.tty)
2092 set_bit(TTY_IO_ERROR, &info->port.tty->flags);
2093 info->port.flags &= ~ASYNC_INITIALIZED;
9fa1b3b1 2094 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
2095 } else {
2096 struct FIRM_ID __iomem *firm_id;
2097 struct ZFW_CTRL __iomem *zfw_ctrl;
2098 struct BOARD_CTRL __iomem *board_ctrl;
2099 struct CH_CTRL __iomem *ch_ctrl;
2100 int retval;
2101
875b206b 2102 base_addr = card->base_addr;
1da177e4 2103#ifdef CY_DEBUG_OPEN
21719191
JS
2104 printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
2105 "base_addr %p\n", card, channel, base_addr);
1da177e4
LT
2106#endif
2107
02f1175c 2108 firm_id = base_addr + ID_ADDRESS;
15ed6cc0 2109 if (!ISZLOADED(*card))
02f1175c 2110 return;
1da177e4 2111
875b206b 2112 zfw_ctrl = card->base_addr +
db05c3b1 2113 (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c
JS
2114 board_ctrl = &zfw_ctrl->board_ctrl;
2115 ch_ctrl = zfw_ctrl->ch_ctrl;
1da177e4 2116
9fa1b3b1 2117 spin_lock_irqsave(&card->card_lock, flags);
1da177e4 2118
77451e53 2119 if (info->port.xmit_buf) {
02f1175c 2120 unsigned char *temp;
77451e53
AC
2121 temp = info->port.xmit_buf;
2122 info->port.xmit_buf = NULL;
02f1175c 2123 free_page((unsigned long)temp);
1da177e4 2124 }
02f1175c 2125
77451e53 2126 if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
02f1175c 2127 cy_writel(&ch_ctrl[channel].rs_control,
db05c3b1 2128 (__u32)(readl(&ch_ctrl[channel].rs_control) &
02f1175c 2129 ~(C_RS_RTS | C_RS_DTR)));
875b206b 2130 retval = cyz_issue_cmd(info->card, channel,
02f1175c
JS
2131 C_CM_IOCTLM, 0L);
2132 if (retval != 0) {
21719191
JS
2133 printk(KERN_ERR"cyc:shutdown retval on ttyC%d "
2134 "was %x\n", info->line, retval);
02f1175c 2135 }
1da177e4 2136#ifdef CY_DEBUG_DTR
21719191 2137 printk(KERN_DEBUG "cyc:shutdown dropping Z DTR\n");
1da177e4 2138#endif
02f1175c 2139 }
1da177e4 2140
77451e53
AC
2141 if (info->port.tty)
2142 set_bit(TTY_IO_ERROR, &info->port.tty->flags);
2143 info->port.flags &= ~ASYNC_INITIALIZED;
02f1175c 2144
9fa1b3b1 2145 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c 2146 }
1da177e4
LT
2147
2148#ifdef CY_DEBUG_OPEN
21719191 2149 printk(KERN_DEBUG "cyc shutdown done\n");
1da177e4 2150#endif
02f1175c 2151} /* shutdown */
1da177e4
LT
2152
2153/*
2154 * ------------------------------------------------------------
2155 * cy_open() and friends
2156 * ------------------------------------------------------------
2157 */
2158
2159static int
02f1175c
JS
2160block_til_ready(struct tty_struct *tty, struct file *filp,
2161 struct cyclades_port *info)
1da177e4 2162{
02f1175c
JS
2163 DECLARE_WAITQUEUE(wait, current);
2164 struct cyclades_card *cinfo;
2165 unsigned long flags;
2166 int chip, channel, index;
2167 int retval;
2168 void __iomem *base_addr;
2169
875b206b 2170 cinfo = info->card;
02f1175c
JS
2171 channel = info->line - cinfo->first_line;
2172
2173 /*
2174 * If the device is in the middle of being closed, then block
2175 * until it's done, and then try again.
2176 */
77451e53
AC
2177 if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
2178 wait_event_interruptible(info->port.close_wait,
2179 !(info->port.flags & ASYNC_CLOSING));
2180 return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
1da177e4 2181 }
02f1175c
JS
2182
2183 /*
2184 * If non-blocking mode is set, then make the check up front
2185 * and then exit.
2186 */
15ed6cc0
AC
2187 if ((filp->f_flags & O_NONBLOCK) ||
2188 (tty->flags & (1 << TTY_IO_ERROR))) {
77451e53 2189 info->port.flags |= ASYNC_NORMAL_ACTIVE;
02f1175c
JS
2190 return 0;
2191 }
2192
2193 /*
2194 * Block waiting for the carrier detect and the line to become
2195 * free (i.e., not in use by the callout). While we are in
77451e53 2196 * this loop, info->port.count is dropped by one, so that
02f1175c
JS
2197 * cy_close() knows when to free things. We restore it upon
2198 * exit, either normal or abnormal.
2199 */
2200 retval = 0;
77451e53 2201 add_wait_queue(&info->port.open_wait, &wait);
1da177e4 2202#ifdef CY_DEBUG_OPEN
21719191 2203 printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, "
77451e53 2204 "count = %d\n", info->line, info->port.count);
1da177e4 2205#endif
9fa1b3b1 2206 spin_lock_irqsave(&cinfo->card_lock, flags);
02f1175c 2207 if (!tty_hung_up_p(filp))
77451e53 2208 info->port.count--;
9fa1b3b1 2209 spin_unlock_irqrestore(&cinfo->card_lock, flags);
1da177e4 2210#ifdef CY_DEBUG_COUNT
21719191 2211 printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to "
77451e53 2212 "%d\n", current->pid, info->port.count);
1da177e4 2213#endif
77451e53 2214 info->port.blocked_open++;
02f1175c
JS
2215
2216 if (!IS_CYC_Z(*cinfo)) {
2217 chip = channel >> 2;
2218 channel &= 0x03;
2219 index = cinfo->bus_index;
2220 base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
2221
2222 while (1) {
9fa1b3b1 2223 spin_lock_irqsave(&cinfo->card_lock, flags);
02f1175c
JS
2224 if ((tty->termios->c_cflag & CBAUD)) {
2225 cy_writeb(base_addr + (CyCAR << index),
2226 (u_char) channel);
2227 cy_writeb(base_addr + (CyMSVR1 << index),
2228 CyRTS);
2229 cy_writeb(base_addr + (CyMSVR2 << index),
2230 CyDTR);
1da177e4 2231#ifdef CY_DEBUG_DTR
21719191
JS
2232 printk(KERN_DEBUG "cyc:block_til_ready raising "
2233 "DTR\n");
2234 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
db05c3b1
JS
2235 readb(base_addr + (CyMSVR1 << index)),
2236 readb(base_addr + (CyMSVR2 << index)));
1da177e4 2237#endif
02f1175c 2238 }
9fa1b3b1 2239 spin_unlock_irqrestore(&cinfo->card_lock, flags);
1da177e4 2240
02f1175c
JS
2241 set_current_state(TASK_INTERRUPTIBLE);
2242 if (tty_hung_up_p(filp) ||
77451e53
AC
2243 !(info->port.flags & ASYNC_INITIALIZED)) {
2244 retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
02f1175c
JS
2245 -EAGAIN : -ERESTARTSYS);
2246 break;
2247 }
1da177e4 2248
9fa1b3b1 2249 spin_lock_irqsave(&cinfo->card_lock, flags);
02f1175c
JS
2250 cy_writeb(base_addr + (CyCAR << index),
2251 (u_char) channel);
77451e53 2252 if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
db05c3b1 2253 (readb(base_addr +
02f1175c 2254 (CyMSVR1 << index)) & CyDCD))) {
9fa1b3b1 2255 spin_unlock_irqrestore(&cinfo->card_lock, flags);
02f1175c
JS
2256 break;
2257 }
9fa1b3b1 2258 spin_unlock_irqrestore(&cinfo->card_lock, flags);
1da177e4 2259
02f1175c
JS
2260 if (signal_pending(current)) {
2261 retval = -ERESTARTSYS;
2262 break;
2263 }
1da177e4 2264#ifdef CY_DEBUG_OPEN
21719191
JS
2265 printk(KERN_DEBUG "cyc block_til_ready blocking: "
2266 "ttyC%d, count = %d\n",
77451e53 2267 info->line, info->port.count);
1da177e4 2268#endif
02f1175c 2269 schedule();
1da177e4 2270 }
02f1175c
JS
2271 } else {
2272 struct FIRM_ID __iomem *firm_id;
2273 struct ZFW_CTRL __iomem *zfw_ctrl;
2274 struct BOARD_CTRL __iomem *board_ctrl;
2275 struct CH_CTRL __iomem *ch_ctrl;
02f1175c
JS
2276
2277 base_addr = cinfo->base_addr;
2278 firm_id = base_addr + ID_ADDRESS;
2279 if (!ISZLOADED(*cinfo)) {
cc0a8fbb 2280 __set_current_state(TASK_RUNNING);
77451e53 2281 remove_wait_queue(&info->port.open_wait, &wait);
02f1175c
JS
2282 return -EINVAL;
2283 }
2284
15ed6cc0
AC
2285 zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)
2286 & 0xfffff);
02f1175c
JS
2287 board_ctrl = &zfw_ctrl->board_ctrl;
2288 ch_ctrl = zfw_ctrl->ch_ctrl;
2289
2290 while (1) {
2291 if ((tty->termios->c_cflag & CBAUD)) {
2292 cy_writel(&ch_ctrl[channel].rs_control,
db05c3b1
JS
2293 readl(&ch_ctrl[channel].rs_control) |
2294 C_RS_RTS | C_RS_DTR);
9fa1b3b1 2295 retval = cyz_issue_cmd(cinfo,
db05c3b1 2296 channel, C_CM_IOCTLM, 0L);
02f1175c 2297 if (retval != 0) {
21719191
JS
2298 printk(KERN_ERR "cyc:block_til_ready "
2299 "retval on ttyC%d was %x\n",
02f1175c
JS
2300 info->line, retval);
2301 }
1da177e4 2302#ifdef CY_DEBUG_DTR
21719191
JS
2303 printk(KERN_DEBUG "cyc:block_til_ready raising "
2304 "Z DTR\n");
1da177e4 2305#endif
02f1175c 2306 }
1da177e4 2307
02f1175c
JS
2308 set_current_state(TASK_INTERRUPTIBLE);
2309 if (tty_hung_up_p(filp) ||
77451e53
AC
2310 !(info->port.flags & ASYNC_INITIALIZED)) {
2311 retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
02f1175c
JS
2312 -EAGAIN : -ERESTARTSYS);
2313 break;
2314 }
77451e53 2315 if (!(info->port.flags & ASYNC_CLOSING) && (C_CLOCAL(tty) ||
db05c3b1 2316 (readl(&ch_ctrl[channel].rs_status) &
02f1175c
JS
2317 C_RS_DCD))) {
2318 break;
2319 }
2320 if (signal_pending(current)) {
2321 retval = -ERESTARTSYS;
2322 break;
2323 }
1da177e4 2324#ifdef CY_DEBUG_OPEN
21719191
JS
2325 printk(KERN_DEBUG "cyc block_til_ready blocking: "
2326 "ttyC%d, count = %d\n",
77451e53 2327 info->line, info->port.count);
1da177e4 2328#endif
02f1175c
JS
2329 schedule();
2330 }
1da177e4 2331 }
cc0a8fbb 2332 __set_current_state(TASK_RUNNING);
77451e53 2333 remove_wait_queue(&info->port.open_wait, &wait);
02f1175c 2334 if (!tty_hung_up_p(filp)) {
77451e53 2335 info->port.count++;
1da177e4 2336#ifdef CY_DEBUG_COUNT
21719191 2337 printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing "
77451e53 2338 "count to %d\n", current->pid, info->port.count);
1da177e4 2339#endif
02f1175c 2340 }
77451e53 2341 info->port.blocked_open--;
1da177e4 2342#ifdef CY_DEBUG_OPEN
21719191 2343 printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, "
77451e53 2344 "count = %d\n", info->line, info->port.count);
1da177e4 2345#endif
02f1175c
JS
2346 if (retval)
2347 return retval;
77451e53 2348 info->port.flags |= ASYNC_NORMAL_ACTIVE;
02f1175c
JS
2349 return 0;
2350} /* block_til_ready */
1da177e4
LT
2351
2352/*
2353 * This routine is called whenever a serial port is opened. It
2354 * performs the serial-specific initialization for the tty structure.
2355 */
02f1175c 2356static int cy_open(struct tty_struct *tty, struct file *filp)
1da177e4 2357{
02f1175c 2358 struct cyclades_port *info;
65f76a82
JS
2359 unsigned int i, line;
2360 int retval;
1da177e4 2361
02f1175c 2362 line = tty->index;
15ed6cc0 2363 if (tty->index < 0 || NR_PORTS <= line)
02f1175c 2364 return -ENODEV;
15ed6cc0 2365
dd025c0c
JS
2366 for (i = 0; i < NR_CARDS; i++)
2367 if (line < cy_card[i].first_line + cy_card[i].nports &&
2368 line >= cy_card[i].first_line)
2369 break;
2370 if (i >= NR_CARDS)
2371 return -ENODEV;
2372 info = &cy_card[i].ports[line - cy_card[i].first_line];
15ed6cc0 2373 if (info->line < 0)
02f1175c 2374 return -ENODEV;
1da177e4 2375
02f1175c
JS
2376 /* If the card's firmware hasn't been loaded,
2377 treat it as absent from the system. This
2378 will make the user pay attention.
2379 */
875b206b
JS
2380 if (IS_CYC_Z(*info->card)) {
2381 struct cyclades_card *cinfo = info->card;
02f1175c
JS
2382 struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
2383
2384 if (!ISZLOADED(*cinfo)) {
101b8159
JS
2385 if (cinfo->hw_ver == ZE_V1 && Z_FPGA_CHECK(*cinfo) &&
2386 readl(&firm_id->signature) ==
2387 ZFIRM_HLT) {
21719191
JS
2388 printk(KERN_ERR "cyc:Cyclades-Z Error: you "
2389 "need an external power supply for "
2390 "this number of ports.\nFirmware "
2391 "halted.\n");
02f1175c 2392 } else {
21719191
JS
2393 printk(KERN_ERR "cyc:Cyclades-Z firmware not "
2394 "yet loaded\n");
02f1175c
JS
2395 }
2396 return -ENODEV;
2397 }
2398#ifdef CONFIG_CYZ_INTR
2399 else {
2400 /* In case this Z board is operating in interrupt mode, its
2401 interrupts should be enabled as soon as the first open
2402 happens to one of its ports. */
2403 if (!cinfo->intr_enabled) {
2404 struct ZFW_CTRL __iomem *zfw_ctrl;
2405 struct BOARD_CTRL __iomem *board_ctrl;
97e87f8e 2406 u16 intr;
02f1175c
JS
2407
2408 zfw_ctrl = cinfo->base_addr +
db05c3b1
JS
2409 (readl(&firm_id->zfwctrl_addr) &
2410 0xfffff);
02f1175c
JS
2411
2412 board_ctrl = &zfw_ctrl->board_ctrl;
2413
2414 /* Enable interrupts on the PLX chip */
97e87f8e
JS
2415 intr = readw(&cinfo->ctl_addr.p9060->
2416 intr_ctrl_stat) | 0x0900;
2417 cy_writew(&cinfo->ctl_addr.p9060->
2418 intr_ctrl_stat, intr);
02f1175c
JS
2419 /* Enable interrupts on the FW */
2420 retval = cyz_issue_cmd(cinfo, 0,
2421 C_CM_IRQ_ENBL, 0L);
2422 if (retval != 0) {
21719191
JS
2423 printk(KERN_ERR "cyc:IRQ enable retval "
2424 "was %x\n", retval);
02f1175c
JS
2425 }
2426 cinfo->nports =
db05c3b1 2427 (int)readl(&board_ctrl->n_channel);
02f1175c
JS
2428 cinfo->intr_enabled = 1;
2429 }
1da177e4 2430 }
02f1175c
JS
2431#endif /* CONFIG_CYZ_INTR */
2432 /* Make sure this Z port really exists in hardware */
2433 if (info->line > (cinfo->first_line + cinfo->nports - 1))
2434 return -ENODEV;
1da177e4 2435 }
1da177e4 2436#ifdef CY_DEBUG_OTHER
21719191 2437 printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
1da177e4 2438#endif
02f1175c 2439 tty->driver_data = info;
77451e53 2440 info->port.tty = tty;
15ed6cc0 2441 if (serial_paranoia_check(info, tty->name, "cy_open"))
02f1175c 2442 return -ENODEV;
15ed6cc0 2443
1da177e4 2444#ifdef CY_DEBUG_OPEN
21719191 2445 printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
77451e53 2446 info->port.count);
1da177e4 2447#endif
77451e53 2448 info->port.count++;
1da177e4 2449#ifdef CY_DEBUG_COUNT
21719191 2450 printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n",
77451e53 2451 current->pid, info->port.count);
1da177e4 2452#endif
1da177e4 2453
02f1175c
JS
2454 /*
2455 * If the port is the middle of closing, bail out now
2456 */
77451e53
AC
2457 if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
2458 wait_event_interruptible(info->port.close_wait,
2459 !(info->port.flags & ASYNC_CLOSING));
2460 return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
02f1175c 2461 }
1da177e4 2462
02f1175c
JS
2463 /*
2464 * Start up serial port
2465 */
2466 retval = startup(info);
15ed6cc0 2467 if (retval)
02f1175c 2468 return retval;
1da177e4 2469
02f1175c
JS
2470 retval = block_til_ready(tty, filp, info);
2471 if (retval) {
1da177e4 2472#ifdef CY_DEBUG_OPEN
21719191
JS
2473 printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready "
2474 "with %d\n", retval);
1da177e4 2475#endif
02f1175c
JS
2476 return retval;
2477 }
1da177e4 2478
02f1175c 2479 info->throttle = 0;
1da177e4 2480
02f1175c 2481#ifdef CY_DEBUG_OPEN
21719191 2482 printk(KERN_DEBUG "cyc:cy_open done\n");
02f1175c
JS
2483#endif
2484 return 0;
2485} /* cy_open */
1da177e4
LT
2486
2487/*
2488 * cy_wait_until_sent() --- wait until the transmitter is empty
2489 */
02f1175c 2490static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
1da177e4 2491{
875b206b 2492 struct cyclades_card *card;
cab9bdd1 2493 struct cyclades_port *info = tty->driver_data;
02f1175c 2494 void __iomem *base_addr;
875b206b 2495 int chip, channel, index;
02f1175c
JS
2496 unsigned long orig_jiffies;
2497 int char_time;
2498
2499 if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
2500 return;
2501
2502 if (info->xmit_fifo_size == 0)
2503 return; /* Just in case.... */
1da177e4 2504
02f1175c 2505 orig_jiffies = jiffies;
978e595f 2506 lock_kernel();
02f1175c
JS
2507 /*
2508 * Set the check interval to be 1/5 of the estimated time to
2509 * send a single character, and make it at least 1. The check
2510 * interval should also be less than the timeout.
2511 *
2512 * Note: we have to use pretty tight timings here to satisfy
2513 * the NIST-PCTS.
2514 */
2515 char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
2516 char_time = char_time / 5;
2517 if (char_time <= 0)
2518 char_time = 1;
2519 if (timeout < 0)
2520 timeout = 0;
2521 if (timeout)
2522 char_time = min(char_time, timeout);
2523 /*
2524 * If the transmitter hasn't cleared in twice the approximate
2525 * amount of time to send the entire FIFO, it probably won't
2526 * ever clear. This assumes the UART isn't doing flow
2527 * control, which is currently the case. Hence, if it ever
2528 * takes longer than info->timeout, this is probably due to a
2529 * UART bug of some kind. So, we clamp the timeout parameter at
2530 * 2*info->timeout.
2531 */
2532 if (!timeout || timeout > 2 * info->timeout)
2533 timeout = 2 * info->timeout;
1da177e4 2534#ifdef CY_DEBUG_WAIT_UNTIL_SENT
21719191
JS
2535 printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...",
2536 timeout, char_time, jiffies);
1da177e4 2537#endif
02f1175c 2538 card = info->card;
875b206b
JS
2539 channel = (info->line) - (card->first_line);
2540 if (!IS_CYC_Z(*card)) {
02f1175c
JS
2541 chip = channel >> 2;
2542 channel &= 0x03;
875b206b
JS
2543 index = card->bus_index;
2544 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
db05c3b1 2545 while (readb(base_addr + (CySRER << index)) & CyTxRdy) {
1da177e4 2546#ifdef CY_DEBUG_WAIT_UNTIL_SENT
21719191 2547 printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies);
1da177e4 2548#endif
02f1175c
JS
2549 if (msleep_interruptible(jiffies_to_msecs(char_time)))
2550 break;
2551 if (timeout && time_after(jiffies, orig_jiffies +
2552 timeout))
2553 break;
2554 }
1da177e4 2555 }
02f1175c
JS
2556 /* Run one more char cycle */
2557 msleep_interruptible(jiffies_to_msecs(char_time * 5));
978e595f 2558 unlock_kernel();
1da177e4 2559#ifdef CY_DEBUG_WAIT_UNTIL_SENT
21719191 2560 printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
1da177e4
LT
2561#endif
2562}
2563
978e595f
AC
2564static void cy_flush_buffer(struct tty_struct *tty)
2565{
2566 struct cyclades_port *info = tty->driver_data;
2567 struct cyclades_card *card;
2568 int channel, retval;
2569 unsigned long flags;
2570
2571#ifdef CY_DEBUG_IO
2572 printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
2573#endif
2574
2575 if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
2576 return;
2577
2578 card = info->card;
2579 channel = info->line - card->first_line;
2580
2581 spin_lock_irqsave(&card->card_lock, flags);
2582 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
2583 spin_unlock_irqrestore(&card->card_lock, flags);
2584
2585 if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board
2586 buffers as well */
2587 spin_lock_irqsave(&card->card_lock, flags);
2588 retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
2589 if (retval != 0) {
2590 printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
2591 "was %x\n", info->line, retval);
2592 }
2593 spin_unlock_irqrestore(&card->card_lock, flags);
2594 }
2595 tty_wakeup(tty);
2596} /* cy_flush_buffer */
2597
2598
1da177e4
LT
2599/*
2600 * This routine is called when a particular tty device is closed.
2601 */
02f1175c 2602static void cy_close(struct tty_struct *tty, struct file *filp)
1da177e4 2603{
cab9bdd1 2604 struct cyclades_port *info = tty->driver_data;
9fa1b3b1 2605 struct cyclades_card *card;
02f1175c 2606 unsigned long flags;
1da177e4
LT
2607
2608#ifdef CY_DEBUG_OTHER
21719191 2609 printk(KERN_DEBUG "cyc:cy_close ttyC%d\n", info->line);
1da177e4
LT
2610#endif
2611
15ed6cc0 2612 if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
02f1175c 2613 return;
1da177e4 2614
9fa1b3b1
JS
2615 card = info->card;
2616
2617 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
2618 /* If the TTY is being hung up, nothing to do */
2619 if (tty_hung_up_p(filp)) {
9fa1b3b1 2620 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
2621 return;
2622 }
1da177e4 2623#ifdef CY_DEBUG_OPEN
21719191 2624 printk(KERN_DEBUG "cyc:cy_close ttyC%d, count = %d\n", info->line,
77451e53 2625 info->port.count);
1da177e4 2626#endif
77451e53 2627 if ((tty->count == 1) && (info->port.count != 1)) {
02f1175c
JS
2628 /*
2629 * Uh, oh. tty->count is 1, which means that the tty
2630 * structure will be freed. Info->count should always
2631 * be one in these conditions. If it's greater than
2632 * one, we've got real problems, since it means the
2633 * serial port won't be shutdown.
2634 */
21719191 2635 printk(KERN_ERR "cyc:cy_close: bad serial port count; "
77451e53
AC
2636 "tty->count is 1, info->port.count is %d\n", info->port.count);
2637 info->port.count = 1;
02f1175c 2638 }
1da177e4 2639#ifdef CY_DEBUG_COUNT
21719191 2640 printk(KERN_DEBUG "cyc:cy_close at (%d): decrementing count to %d\n",
77451e53 2641 current->pid, info->port.count - 1);
1da177e4 2642#endif
77451e53 2643 if (--info->port.count < 0) {
1da177e4 2644#ifdef CY_DEBUG_COUNT
21719191 2645 printk(KERN_DEBUG "cyc:cyc_close setting count to 0\n");
1da177e4 2646#endif
77451e53 2647 info->port.count = 0;
1da177e4 2648 }
77451e53 2649 if (info->port.count) {
9fa1b3b1 2650 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
2651 return;
2652 }
77451e53 2653 info->port.flags |= ASYNC_CLOSING;
1da177e4 2654
02f1175c
JS
2655 /*
2656 * Now we wait for the transmit buffer to clear; and we notify
2657 * the line discipline to only process XON/XOFF characters.
2658 */
2659 tty->closing = 1;
9fa1b3b1 2660 spin_unlock_irqrestore(&card->card_lock, flags);
44b7d1b3
AC
2661 if (info->port.closing_wait != CY_CLOSING_WAIT_NONE)
2662 tty_wait_until_sent(tty, info->port.closing_wait);
15ed6cc0 2663
9fa1b3b1 2664 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 2665
9fa1b3b1
JS
2666 if (!IS_CYC_Z(*card)) {
2667 int channel = info->line - card->first_line;
2668 int index = card->bus_index;
2669 void __iomem *base_addr = card->base_addr +
02f1175c
JS
2670 (cy_chip_offset[channel >> 2] << index);
2671 /* Stop accepting input */
2672 channel &= 0x03;
2673 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
2674 cy_writeb(base_addr + (CySRER << index),
db05c3b1 2675 readb(base_addr + (CySRER << index)) & ~CyRxData);
77451e53 2676 if (info->port.flags & ASYNC_INITIALIZED) {
15ed6cc0
AC
2677 /* Waiting for on-board buffers to be empty before
2678 closing the port */
9fa1b3b1 2679 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c 2680 cy_wait_until_sent(tty, info->timeout);
9fa1b3b1 2681 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
2682 }
2683 } else {
2684#ifdef Z_WAKE
15ed6cc0
AC
2685 /* Waiting for on-board buffers to be empty before closing
2686 the port */
9fa1b3b1 2687 void __iomem *base_addr = card->base_addr;
02f1175c
JS
2688 struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
2689 struct ZFW_CTRL __iomem *zfw_ctrl =
db05c3b1 2690 base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c 2691 struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
9fa1b3b1 2692 int channel = info->line - card->first_line;
02f1175c
JS
2693 int retval;
2694
db05c3b1 2695 if (readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) {
9fa1b3b1 2696 retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
02f1175c 2697 if (retval != 0) {
21719191
JS
2698 printk(KERN_DEBUG "cyc:cy_close retval on "
2699 "ttyC%d was %x\n", info->line, retval);
02f1175c 2700 }
9fa1b3b1 2701 spin_unlock_irqrestore(&card->card_lock, flags);
2c7fea99 2702 wait_for_completion_interruptible(&info->shutdown_wait);
9fa1b3b1 2703 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 2704 }
1da177e4 2705#endif
02f1175c
JS
2706 }
2707
9fa1b3b1 2708 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c 2709 shutdown(info);
978e595f 2710 cy_flush_buffer(tty);
02f1175c 2711 tty_ldisc_flush(tty);
9fa1b3b1 2712 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
2713
2714 tty->closing = 0;
77451e53
AC
2715 info->port.tty = NULL;
2716 if (info->port.blocked_open) {
9fa1b3b1 2717 spin_unlock_irqrestore(&card->card_lock, flags);
44b7d1b3 2718 if (info->port.close_delay) {
02f1175c 2719 msleep_interruptible(jiffies_to_msecs
44b7d1b3 2720 (info->port.close_delay));
02f1175c 2721 }
77451e53 2722 wake_up_interruptible(&info->port.open_wait);
9fa1b3b1 2723 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 2724 }
77451e53
AC
2725 info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
2726 wake_up_interruptible(&info->port.close_wait);
1da177e4
LT
2727
2728#ifdef CY_DEBUG_OTHER
21719191 2729 printk(KERN_DEBUG "cyc:cy_close done\n");
1da177e4
LT
2730#endif
2731
9fa1b3b1 2732 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c 2733} /* cy_close */
1da177e4
LT
2734
2735/* This routine gets called when tty_write has put something into
2736 * the write_queue. The characters may come from user space or
2737 * kernel space.
2738 *
2739 * This routine will return the number of characters actually
2740 * accepted for writing.
2741 *
2742 * If the port is not already transmitting stuff, start it off by
2743 * enabling interrupts. The interrupt service routine will then
2744 * ensure that the characters are sent.
2745 * If the port is already active, there is no need to kick it.
2746 *
2747 */
02f1175c 2748static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
1da177e4 2749{
cab9bdd1 2750 struct cyclades_port *info = tty->driver_data;
02f1175c
JS
2751 unsigned long flags;
2752 int c, ret = 0;
1da177e4
LT
2753
2754#ifdef CY_DEBUG_IO
21719191 2755 printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line);
1da177e4
LT
2756#endif
2757
15ed6cc0 2758 if (serial_paranoia_check(info, tty->name, "cy_write"))
02f1175c 2759 return 0;
1da177e4 2760
77451e53 2761 if (!info->port.xmit_buf)
02f1175c 2762 return 0;
1da177e4 2763
9fa1b3b1 2764 spin_lock_irqsave(&info->card->card_lock, flags);
02f1175c 2765 while (1) {
1a4e2351
HH
2766 c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1));
2767 c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head));
02f1175c
JS
2768
2769 if (c <= 0)
2770 break;
2771
77451e53 2772 memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
02f1175c
JS
2773 info->xmit_head = (info->xmit_head + c) &
2774 (SERIAL_XMIT_SIZE - 1);
2775 info->xmit_cnt += c;
2776 buf += c;
2777 count -= c;
2778 ret += c;
2779 }
9fa1b3b1 2780 spin_unlock_irqrestore(&info->card->card_lock, flags);
02f1175c
JS
2781
2782 info->idle_stats.xmit_bytes += ret;
2783 info->idle_stats.xmit_idle = jiffies;
2784
15ed6cc0 2785 if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped)
02f1175c 2786 start_xmit(info);
15ed6cc0 2787
02f1175c
JS
2788 return ret;
2789} /* cy_write */
1da177e4
LT
2790
2791/*
2792 * This routine is called by the kernel to write a single
2793 * character to the tty device. If the kernel uses this routine,
2794 * it must call the flush_chars() routine (if defined) when it is
2795 * done stuffing characters into the driver. If there is no room
2796 * in the queue, the character is ignored.
2797 */
76b25a55 2798static int cy_put_char(struct tty_struct *tty, unsigned char ch)
1da177e4 2799{
cab9bdd1 2800 struct cyclades_port *info = tty->driver_data;
02f1175c 2801 unsigned long flags;
1da177e4
LT
2802
2803#ifdef CY_DEBUG_IO
21719191 2804 printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line);
1da177e4
LT
2805#endif
2806
02f1175c 2807 if (serial_paranoia_check(info, tty->name, "cy_put_char"))
76b25a55 2808 return 0;
1da177e4 2809
77451e53 2810 if (!info->port.xmit_buf)
76b25a55 2811 return 0;
1da177e4 2812
9fa1b3b1 2813 spin_lock_irqsave(&info->card->card_lock, flags);
90cc3018 2814 if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
9fa1b3b1 2815 spin_unlock_irqrestore(&info->card->card_lock, flags);
76b25a55 2816 return 0;
02f1175c 2817 }
1da177e4 2818
77451e53 2819 info->port.xmit_buf[info->xmit_head++] = ch;
02f1175c
JS
2820 info->xmit_head &= SERIAL_XMIT_SIZE - 1;
2821 info->xmit_cnt++;
1da177e4
LT
2822 info->idle_stats.xmit_bytes++;
2823 info->idle_stats.xmit_idle = jiffies;
9fa1b3b1 2824 spin_unlock_irqrestore(&info->card->card_lock, flags);
76b25a55 2825 return 1;
02f1175c 2826} /* cy_put_char */
1da177e4
LT
2827
2828/*
2829 * This routine is called by the kernel after it has written a
15ed6cc0 2830 * series of characters to the tty device using put_char().
1da177e4 2831 */
02f1175c 2832static void cy_flush_chars(struct tty_struct *tty)
1da177e4 2833{
cab9bdd1 2834 struct cyclades_port *info = tty->driver_data;
02f1175c 2835
1da177e4 2836#ifdef CY_DEBUG_IO
21719191 2837 printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line);
1da177e4
LT
2838#endif
2839
02f1175c
JS
2840 if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
2841 return;
1da177e4 2842
02f1175c 2843 if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
77451e53 2844 !info->port.xmit_buf)
02f1175c 2845 return;
1da177e4 2846
02f1175c
JS
2847 start_xmit(info);
2848} /* cy_flush_chars */
1da177e4
LT
2849
2850/*
2851 * This routine returns the numbers of characters the tty driver
2852 * will accept for queuing to be written. This number is subject
2853 * to change as output buffers get emptied, or if the output flow
2854 * control is activated.
2855 */
02f1175c 2856static int cy_write_room(struct tty_struct *tty)
1da177e4 2857{
cab9bdd1 2858 struct cyclades_port *info = tty->driver_data;
02f1175c
JS
2859 int ret;
2860
1da177e4 2861#ifdef CY_DEBUG_IO
21719191 2862 printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line);
1da177e4
LT
2863#endif
2864
02f1175c
JS
2865 if (serial_paranoia_check(info, tty->name, "cy_write_room"))
2866 return 0;
2867 ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
2868 if (ret < 0)
2869 ret = 0;
2870 return ret;
2871} /* cy_write_room */
1da177e4 2872
02f1175c 2873static int cy_chars_in_buffer(struct tty_struct *tty)
1da177e4 2874{
875b206b 2875 struct cyclades_card *card;
cab9bdd1 2876 struct cyclades_port *info = tty->driver_data;
875b206b 2877 int channel;
1da177e4 2878
02f1175c
JS
2879 if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
2880 return 0;
2881
2882 card = info->card;
875b206b 2883 channel = (info->line) - (card->first_line);
1da177e4
LT
2884
2885#ifdef Z_EXT_CHARS_IN_BUFFER
02f1175c
JS
2886 if (!IS_CYC_Z(cy_card[card])) {
2887#endif /* Z_EXT_CHARS_IN_BUFFER */
1da177e4 2888#ifdef CY_DEBUG_IO
21719191
JS
2889 printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
2890 info->line, info->xmit_cnt);
1da177e4 2891#endif
02f1175c 2892 return info->xmit_cnt;
1da177e4 2893#ifdef Z_EXT_CHARS_IN_BUFFER
02f1175c 2894 } else {
ad39c300
JS
2895 static struct FIRM_ID *firm_id;
2896 static struct ZFW_CTRL *zfw_ctrl;
2897 static struct CH_CTRL *ch_ctrl;
2898 static struct BUF_CTRL *buf_ctrl;
02f1175c 2899 int char_count;
ad39c300 2900 __u32 tx_put, tx_get, tx_bufsize;
02f1175c 2901
978e595f 2902 lock_kernel();
875b206b
JS
2903 firm_id = card->base_addr + ID_ADDRESS;
2904 zfw_ctrl = card->base_addr +
db05c3b1 2905 (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c
JS
2906 ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
2907 buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
2908
db05c3b1
JS
2909 tx_get = readl(&buf_ctrl->tx_get);
2910 tx_put = readl(&buf_ctrl->tx_put);
2911 tx_bufsize = readl(&buf_ctrl->tx_bufsize);
02f1175c
JS
2912 if (tx_put >= tx_get)
2913 char_count = tx_put - tx_get;
2914 else
2915 char_count = tx_put - tx_get + tx_bufsize;
1da177e4 2916#ifdef CY_DEBUG_IO
21719191
JS
2917 printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
2918 info->line, info->xmit_cnt + char_count);
1da177e4 2919#endif
978e595f 2920 unlock_kernel();
096dcfce 2921 return info->xmit_cnt + char_count;
02f1175c
JS
2922 }
2923#endif /* Z_EXT_CHARS_IN_BUFFER */
2924} /* cy_chars_in_buffer */
1da177e4
LT
2925
2926/*
2927 * ------------------------------------------------------------
2928 * cy_ioctl() and friends
2929 * ------------------------------------------------------------
2930 */
2931
1a86b5e3 2932static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
1da177e4 2933{
02f1175c 2934 int co, co_val, bpr;
1a86b5e3 2935 __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
02f1175c 2936 25000000);
1da177e4 2937
02f1175c
JS
2938 if (baud == 0) {
2939 info->tbpr = info->tco = info->rbpr = info->rco = 0;
2940 return;
2941 }
1da177e4 2942
02f1175c
JS
2943 /* determine which prescaler to use */
2944 for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
2945 if (cy_clock / co_val / baud > 63)
2946 break;
2947 }
1da177e4 2948
02f1175c
JS
2949 bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
2950 if (bpr > 255)
2951 bpr = 255;
1da177e4 2952
02f1175c
JS
2953 info->tbpr = info->rbpr = bpr;
2954 info->tco = info->rco = co;
1da177e4
LT
2955}
2956
2957/*
2958 * This routine finds or computes the various line characteristics.
2959 * It used to be called config_setup
2960 */
02f1175c 2961static void set_line_char(struct cyclades_port *info)
1da177e4 2962{
875b206b 2963 struct cyclades_card *card;
02f1175c
JS
2964 unsigned long flags;
2965 void __iomem *base_addr;
875b206b 2966 int chip, channel, index;
02f1175c
JS
2967 unsigned cflag, iflag;
2968 unsigned short chip_number;
2969 int baud, baud_rate = 0;
2970 int i;
2971
77451e53 2972 if (!info->port.tty || !info->port.tty->termios)
02f1175c 2973 return;
15ed6cc0
AC
2974
2975 if (info->line == -1)
02f1175c 2976 return;
15ed6cc0 2977
77451e53
AC
2978 cflag = info->port.tty->termios->c_cflag;
2979 iflag = info->port.tty->termios->c_iflag;
1da177e4 2980
02f1175c
JS
2981 /*
2982 * Set up the tty->alt_speed kludge
2983 */
77451e53
AC
2984 if (info->port.tty) {
2985 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2986 info->port.tty->alt_speed = 57600;
2987 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2988 info->port.tty->alt_speed = 115200;
2989 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2990 info->port.tty->alt_speed = 230400;
2991 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2992 info->port.tty->alt_speed = 460800;
1da177e4 2993 }
02f1175c
JS
2994
2995 card = info->card;
875b206b 2996 channel = info->line - card->first_line;
02f1175c
JS
2997 chip_number = channel / 4;
2998
875b206b 2999 if (!IS_CYC_Z(*card)) {
02f1175c 3000
875b206b 3001 index = card->bus_index;
02f1175c
JS
3002
3003 /* baud rate */
77451e53
AC
3004 baud = tty_get_baud_rate(info->port.tty);
3005 if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c
JS
3006 ASYNC_SPD_CUST) {
3007 if (info->custom_divisor)
3008 baud_rate = info->baud / info->custom_divisor;
3009 else
3010 baud_rate = info->baud;
3011 } else if (baud > CD1400_MAX_SPEED) {
3012 baud = CD1400_MAX_SPEED;
3013 }
3014 /* find the baud index */
3015 for (i = 0; i < 20; i++) {
15ed6cc0 3016 if (baud == baud_table[i])
02f1175c 3017 break;
02f1175c 3018 }
15ed6cc0 3019 if (i == 20)
02f1175c 3020 i = 19; /* CD1400_MAX_SPEED */
02f1175c 3021
77451e53 3022 if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c
JS
3023 ASYNC_SPD_CUST) {
3024 cyy_baud_calc(info, baud_rate);
3025 } else {
3026 if (info->chip_rev >= CD1400_REV_J) {
3027 /* It is a CD1400 rev. J or later */
3028 info->tbpr = baud_bpr_60[i]; /* Tx BPR */
3029 info->tco = baud_co_60[i]; /* Tx CO */
3030 info->rbpr = baud_bpr_60[i]; /* Rx BPR */
3031 info->rco = baud_co_60[i]; /* Rx CO */
3032 } else {
3033 info->tbpr = baud_bpr_25[i]; /* Tx BPR */
3034 info->tco = baud_co_25[i]; /* Tx CO */
3035 info->rbpr = baud_bpr_25[i]; /* Rx BPR */
3036 info->rco = baud_co_25[i]; /* Rx CO */
3037 }
3038 }
3039 if (baud_table[i] == 134) {
3040 /* get it right for 134.5 baud */
3041 info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
3042 2;
77451e53 3043 } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c
JS
3044 ASYNC_SPD_CUST) {
3045 info->timeout = (info->xmit_fifo_size * HZ * 15 /
3046 baud_rate) + 2;
3047 } else if (baud_table[i]) {
3048 info->timeout = (info->xmit_fifo_size * HZ * 15 /
3049 baud_table[i]) + 2;
3050 /* this needs to be propagated into the card info */
3051 } else {
3052 info->timeout = 0;
3053 }
3054 /* By tradition (is it a standard?) a baud rate of zero
3055 implies the line should be/has been closed. A bit
3056 later in this routine such a test is performed. */
3057
3058 /* byte size and parity */
3059 info->cor5 = 0;
3060 info->cor4 = 0;
3061 /* receive threshold */
3062 info->cor3 = (info->default_threshold ?
3063 info->default_threshold : baud_cor3[i]);
3064 info->cor2 = CyETC;
3065 switch (cflag & CSIZE) {
3066 case CS5:
3067 info->cor1 = Cy_5_BITS;
3068 break;
3069 case CS6:
3070 info->cor1 = Cy_6_BITS;
3071 break;
3072 case CS7:
3073 info->cor1 = Cy_7_BITS;
3074 break;
3075 case CS8:
3076 info->cor1 = Cy_8_BITS;
3077 break;
3078 }
15ed6cc0 3079 if (cflag & CSTOPB)
02f1175c 3080 info->cor1 |= Cy_2_STOP;
15ed6cc0 3081
02f1175c 3082 if (cflag & PARENB) {
15ed6cc0 3083 if (cflag & PARODD)
02f1175c 3084 info->cor1 |= CyPARITY_O;
15ed6cc0 3085 else
02f1175c 3086 info->cor1 |= CyPARITY_E;
15ed6cc0 3087 } else
02f1175c 3088 info->cor1 |= CyPARITY_NONE;
02f1175c
JS
3089
3090 /* CTS flow control flag */
3091 if (cflag & CRTSCTS) {
77451e53 3092 info->port.flags |= ASYNC_CTS_FLOW;
02f1175c
JS
3093 info->cor2 |= CyCtsAE;
3094 } else {
77451e53 3095 info->port.flags &= ~ASYNC_CTS_FLOW;
02f1175c
JS
3096 info->cor2 &= ~CyCtsAE;
3097 }
3098 if (cflag & CLOCAL)
77451e53 3099 info->port.flags &= ~ASYNC_CHECK_CD;
02f1175c 3100 else
77451e53 3101 info->port.flags |= ASYNC_CHECK_CD;
1da177e4
LT
3102
3103 /***********************************************
3104 The hardware option, CyRtsAO, presents RTS when
3105 the chip has characters to send. Since most modems
3106 use RTS as reverse (inbound) flow control, this
3107 option is not used. If inbound flow control is
3108 necessary, DTR can be programmed to provide the
3109 appropriate signals for use with a non-standard
3110 cable. Contact Marcio Saito for details.
3111 ***********************************************/
3112
02f1175c
JS
3113 chip = channel >> 2;
3114 channel &= 0x03;
875b206b 3115 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
1da177e4 3116
9fa1b3b1 3117 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
3118 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
3119
3120 /* tx and rx baud rate */
3121
3122 cy_writeb(base_addr + (CyTCOR << index), info->tco);
3123 cy_writeb(base_addr + (CyTBPR << index), info->tbpr);
3124 cy_writeb(base_addr + (CyRCOR << index), info->rco);
3125 cy_writeb(base_addr + (CyRBPR << index), info->rbpr);
3126
3127 /* set line characteristics according configuration */
3128
3129 cy_writeb(base_addr + (CySCHR1 << index),
77451e53
AC
3130 START_CHAR(info->port.tty));
3131 cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->port.tty));
02f1175c
JS
3132 cy_writeb(base_addr + (CyCOR1 << index), info->cor1);
3133 cy_writeb(base_addr + (CyCOR2 << index), info->cor2);
3134 cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
3135 cy_writeb(base_addr + (CyCOR4 << index), info->cor4);
3136 cy_writeb(base_addr + (CyCOR5 << index), info->cor5);
3137
3138 cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
3139 CyCOR3ch, index);
3140
15ed6cc0
AC
3141 /* !!! Is this needed? */
3142 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
02f1175c
JS
3143 cy_writeb(base_addr + (CyRTPR << index),
3144 (info->default_timeout ? info->default_timeout : 0x02));
3145 /* 10ms rx timeout */
3146
77451e53 3147 if (C_CLOCAL(info->port.tty)) {
02f1175c
JS
3148 /* without modem intr */
3149 cy_writeb(base_addr + (CySRER << index),
db05c3b1 3150 readb(base_addr + (CySRER << index)) | CyMdmCh);
02f1175c
JS
3151 /* act on 1->0 modem transitions */
3152 if ((cflag & CRTSCTS) && info->rflow) {
3153 cy_writeb(base_addr + (CyMCOR1 << index),
3154 (CyCTS | rflow_thr[i]));
3155 } else {
3156 cy_writeb(base_addr + (CyMCOR1 << index),
3157 CyCTS);
3158 }
3159 /* act on 0->1 modem transitions */
3160 cy_writeb(base_addr + (CyMCOR2 << index), CyCTS);
1da177e4 3161 } else {
02f1175c
JS
3162 /* without modem intr */
3163 cy_writeb(base_addr + (CySRER << index),
db05c3b1 3164 readb(base_addr +
02f1175c
JS
3165 (CySRER << index)) | CyMdmCh);
3166 /* act on 1->0 modem transitions */
3167 if ((cflag & CRTSCTS) && info->rflow) {
3168 cy_writeb(base_addr + (CyMCOR1 << index),
3169 (CyDSR | CyCTS | CyRI | CyDCD |
3170 rflow_thr[i]));
3171 } else {
3172 cy_writeb(base_addr + (CyMCOR1 << index),
3173 CyDSR | CyCTS | CyRI | CyDCD);
3174 }
3175 /* act on 0->1 modem transitions */
3176 cy_writeb(base_addr + (CyMCOR2 << index),
3177 CyDSR | CyCTS | CyRI | CyDCD);
1da177e4 3178 }
02f1175c
JS
3179
3180 if (i == 0) { /* baud rate is zero, turn off line */
3181 if (info->rtsdtr_inv) {
3182 cy_writeb(base_addr + (CyMSVR1 << index),
3183 ~CyRTS);
3184 } else {
3185 cy_writeb(base_addr + (CyMSVR2 << index),
3186 ~CyDTR);
3187 }
1da177e4 3188#ifdef CY_DEBUG_DTR
21719191
JS
3189 printk(KERN_DEBUG "cyc:set_line_char dropping DTR\n");
3190 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
db05c3b1
JS
3191 readb(base_addr + (CyMSVR1 << index)),
3192 readb(base_addr + (CyMSVR2 << index)));
1da177e4 3193#endif
02f1175c
JS
3194 } else {
3195 if (info->rtsdtr_inv) {
3196 cy_writeb(base_addr + (CyMSVR1 << index),
3197 CyRTS);
3198 } else {
3199 cy_writeb(base_addr + (CyMSVR2 << index),
3200 CyDTR);
3201 }
1da177e4 3202#ifdef CY_DEBUG_DTR
21719191
JS
3203 printk(KERN_DEBUG "cyc:set_line_char raising DTR\n");
3204 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
db05c3b1
JS
3205 readb(base_addr + (CyMSVR1 << index)),
3206 readb(base_addr + (CyMSVR2 << index)));
1da177e4 3207#endif
02f1175c 3208 }
1da177e4 3209
77451e53
AC
3210 if (info->port.tty)
3211 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
9fa1b3b1 3212 spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4 3213
1da177e4 3214 } else {
02f1175c
JS
3215 struct FIRM_ID __iomem *firm_id;
3216 struct ZFW_CTRL __iomem *zfw_ctrl;
3217 struct BOARD_CTRL __iomem *board_ctrl;
3218 struct CH_CTRL __iomem *ch_ctrl;
3219 struct BUF_CTRL __iomem *buf_ctrl;
1a86b5e3 3220 __u32 sw_flow;
02f1175c 3221 int retval;
1da177e4 3222
875b206b 3223 firm_id = card->base_addr + ID_ADDRESS;
15ed6cc0 3224 if (!ISZLOADED(*card))
02f1175c 3225 return;
1da177e4 3226
875b206b 3227 zfw_ctrl = card->base_addr +
db05c3b1 3228 (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c
JS
3229 board_ctrl = &zfw_ctrl->board_ctrl;
3230 ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
3231 buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
3232
3233 /* baud rate */
77451e53
AC
3234 baud = tty_get_baud_rate(info->port.tty);
3235 if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c
JS
3236 ASYNC_SPD_CUST) {
3237 if (info->custom_divisor)
3238 baud_rate = info->baud / info->custom_divisor;
3239 else
3240 baud_rate = info->baud;
3241 } else if (baud > CYZ_MAX_SPEED) {
3242 baud = CYZ_MAX_SPEED;
3243 }
3244 cy_writel(&ch_ctrl->comm_baud, baud);
3245
3246 if (baud == 134) {
3247 /* get it right for 134.5 baud */
3248 info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
3249 2;
77451e53 3250 } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
02f1175c
JS
3251 ASYNC_SPD_CUST) {
3252 info->timeout = (info->xmit_fifo_size * HZ * 15 /
3253 baud_rate) + 2;
3254 } else if (baud) {
3255 info->timeout = (info->xmit_fifo_size * HZ * 15 /
3256 baud) + 2;
3257 /* this needs to be propagated into the card info */
3258 } else {
3259 info->timeout = 0;
3260 }
1da177e4 3261
02f1175c
JS
3262 /* byte size and parity */
3263 switch (cflag & CSIZE) {
3264 case CS5:
3265 cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5);
3266 break;
3267 case CS6:
3268 cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6);
3269 break;
3270 case CS7:
3271 cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7);
3272 break;
3273 case CS8:
3274 cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8);
3275 break;
3276 }
3277 if (cflag & CSTOPB) {
3278 cy_writel(&ch_ctrl->comm_data_l,
db05c3b1 3279 readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
02f1175c
JS
3280 } else {
3281 cy_writel(&ch_ctrl->comm_data_l,
db05c3b1 3282 readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
02f1175c
JS
3283 }
3284 if (cflag & PARENB) {
15ed6cc0 3285 if (cflag & PARODD)
02f1175c 3286 cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
15ed6cc0 3287 else
02f1175c 3288 cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
15ed6cc0 3289 } else
02f1175c 3290 cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
1da177e4 3291
02f1175c
JS
3292 /* CTS flow control flag */
3293 if (cflag & CRTSCTS) {
3294 cy_writel(&ch_ctrl->hw_flow,
db05c3b1 3295 readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
02f1175c 3296 } else {
db05c3b1
JS
3297 cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) &
3298 ~(C_RS_CTS | C_RS_RTS));
02f1175c
JS
3299 }
3300 /* As the HW flow control is done in firmware, the driver
3301 doesn't need to care about it */
77451e53 3302 info->port.flags &= ~ASYNC_CTS_FLOW;
02f1175c
JS
3303
3304 /* XON/XOFF/XANY flow control flags */
3305 sw_flow = 0;
3306 if (iflag & IXON) {
3307 sw_flow |= C_FL_OXX;
3308 if (iflag & IXANY)
3309 sw_flow |= C_FL_OIXANY;
3310 }
3311 cy_writel(&ch_ctrl->sw_flow, sw_flow);
3312
875b206b 3313 retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
02f1175c 3314 if (retval != 0) {
21719191
JS
3315 printk(KERN_ERR "cyc:set_line_char retval on ttyC%d "
3316 "was %x\n", info->line, retval);
02f1175c
JS
3317 }
3318
3319 /* CD sensitivity */
15ed6cc0 3320 if (cflag & CLOCAL)
77451e53 3321 info->port.flags &= ~ASYNC_CHECK_CD;
15ed6cc0 3322 else
77451e53 3323 info->port.flags |= ASYNC_CHECK_CD;
1da177e4 3324
02f1175c
JS
3325 if (baud == 0) { /* baud rate is zero, turn off line */
3326 cy_writel(&ch_ctrl->rs_control,
db05c3b1 3327 readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
1da177e4 3328#ifdef CY_DEBUG_DTR
21719191 3329 printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n");
1da177e4 3330#endif
02f1175c
JS
3331 } else {
3332 cy_writel(&ch_ctrl->rs_control,
db05c3b1 3333 readl(&ch_ctrl->rs_control) | C_RS_DTR);
1da177e4 3334#ifdef CY_DEBUG_DTR
21719191 3335 printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n");
1da177e4 3336#endif
02f1175c 3337 }
1da177e4 3338
15ed6cc0 3339 retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
02f1175c 3340 if (retval != 0) {
21719191
JS
3341 printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
3342 "was %x\n", info->line, retval);
02f1175c 3343 }
1da177e4 3344
77451e53
AC
3345 if (info->port.tty)
3346 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
1da177e4 3347 }
02f1175c 3348} /* set_line_char */
1da177e4
LT
3349
3350static int
02f1175c 3351get_serial_info(struct cyclades_port *info,
15ed6cc0 3352 struct serial_struct __user *retinfo)
1da177e4 3353{
02f1175c 3354 struct serial_struct tmp;
875b206b 3355 struct cyclades_card *cinfo = info->card;
1da177e4 3356
02f1175c
JS
3357 if (!retinfo)
3358 return -EFAULT;
3359 memset(&tmp, 0, sizeof(tmp));
3360 tmp.type = info->type;
3361 tmp.line = info->line;
875b206b
JS
3362 tmp.port = (info->card - cy_card) * 0x100 + info->line -
3363 cinfo->first_line;
02f1175c 3364 tmp.irq = cinfo->irq;
77451e53 3365 tmp.flags = info->port.flags;
44b7d1b3
AC
3366 tmp.close_delay = info->port.close_delay;
3367 tmp.closing_wait = info->port.closing_wait;
02f1175c
JS
3368 tmp.baud_base = info->baud;
3369 tmp.custom_divisor = info->custom_divisor;
3370 tmp.hub6 = 0; /*!!! */
3371 return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
3372} /* get_serial_info */
1da177e4
LT
3373
3374static int
02f1175c 3375set_serial_info(struct cyclades_port *info,
15ed6cc0 3376 struct serial_struct __user *new_info)
1da177e4 3377{
02f1175c
JS
3378 struct serial_struct new_serial;
3379 struct cyclades_port old_info;
3380
3381 if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
3382 return -EFAULT;
3383 old_info = *info;
3384
3385 if (!capable(CAP_SYS_ADMIN)) {
44b7d1b3 3386 if (new_serial.close_delay != info->port.close_delay ||
02f1175c
JS
3387 new_serial.baud_base != info->baud ||
3388 (new_serial.flags & ASYNC_FLAGS &
3389 ~ASYNC_USR_MASK) !=
77451e53 3390 (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
02f1175c 3391 return -EPERM;
77451e53 3392 info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
02f1175c
JS
3393 (new_serial.flags & ASYNC_USR_MASK);
3394 info->baud = new_serial.baud_base;
3395 info->custom_divisor = new_serial.custom_divisor;
3396 goto check_and_exit;
3397 }
3398
3399 /*
3400 * OK, past this point, all the error checking has been done.
3401 * At this point, we start making changes.....
3402 */
3403
3404 info->baud = new_serial.baud_base;
3405 info->custom_divisor = new_serial.custom_divisor;
77451e53 3406 info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
02f1175c 3407 (new_serial.flags & ASYNC_FLAGS);
44b7d1b3
AC
3408 info->port.close_delay = new_serial.close_delay * HZ / 100;
3409 info->port.closing_wait = new_serial.closing_wait * HZ / 100;
1da177e4
LT
3410
3411check_and_exit:
77451e53 3412 if (info->port.flags & ASYNC_INITIALIZED) {
02f1175c
JS
3413 set_line_char(info);
3414 return 0;
3415 } else {
3416 return startup(info);
3417 }
3418} /* set_serial_info */
1da177e4
LT
3419
3420/*
3421 * get_lsr_info - get line status register info
3422 *
3423 * Purpose: Let user call ioctl() to get info when the UART physically
3424 * is emptied. On bus types like RS485, the transmitter must
3425 * release the bus after transmitting. This must be done when
3426 * the transmit shift register is empty, not be done when the
3427 * transmit holding register is empty. This functionality
3428 * allows an RS485 driver to be written in user space.
3429 */
15ed6cc0 3430static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
1da177e4 3431{
875b206b
JS
3432 struct cyclades_card *card;
3433 int chip, channel, index;
02f1175c
JS
3434 unsigned char status;
3435 unsigned int result;
3436 unsigned long flags;
3437 void __iomem *base_addr;
1da177e4 3438
02f1175c 3439 card = info->card;
875b206b
JS
3440 channel = (info->line) - (card->first_line);
3441 if (!IS_CYC_Z(*card)) {
02f1175c
JS
3442 chip = channel >> 2;
3443 channel &= 0x03;
875b206b
JS
3444 index = card->bus_index;
3445 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
02f1175c 3446
9fa1b3b1 3447 spin_lock_irqsave(&card->card_lock, flags);
db05c3b1 3448 status = readb(base_addr + (CySRER << index)) &
02f1175c 3449 (CyTxRdy | CyTxMpty);
9fa1b3b1 3450 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3451 result = (status ? 0 : TIOCSER_TEMT);
3452 } else {
3453 /* Not supported yet */
3454 return -EINVAL;
3455 }
3456 return put_user(result, (unsigned long __user *)value);
1da177e4
LT
3457}
3458
02f1175c 3459static int cy_tiocmget(struct tty_struct *tty, struct file *file)
1da177e4 3460{
cab9bdd1 3461 struct cyclades_port *info = tty->driver_data;
875b206b
JS
3462 struct cyclades_card *card;
3463 int chip, channel, index;
02f1175c
JS
3464 void __iomem *base_addr;
3465 unsigned long flags;
3466 unsigned char status;
3467 unsigned long lstatus;
3468 unsigned int result;
3469 struct FIRM_ID __iomem *firm_id;
3470 struct ZFW_CTRL __iomem *zfw_ctrl;
3471 struct BOARD_CTRL __iomem *board_ctrl;
3472 struct CH_CTRL __iomem *ch_ctrl;
3473
bf9d8929 3474 if (serial_paranoia_check(info, tty->name, __func__))
02f1175c 3475 return -ENODEV;
1da177e4 3476
7b130c0e
AC
3477 lock_kernel();
3478
02f1175c 3479 card = info->card;
875b206b
JS
3480 channel = info->line - card->first_line;
3481 if (!IS_CYC_Z(*card)) {
02f1175c
JS
3482 chip = channel >> 2;
3483 channel &= 0x03;
875b206b
JS
3484 index = card->bus_index;
3485 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
1da177e4 3486
9fa1b3b1 3487 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 3488 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
db05c3b1
JS
3489 status = readb(base_addr + (CyMSVR1 << index));
3490 status |= readb(base_addr + (CyMSVR2 << index));
9fa1b3b1 3491 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3492
3493 if (info->rtsdtr_inv) {
3494 result = ((status & CyRTS) ? TIOCM_DTR : 0) |
3495 ((status & CyDTR) ? TIOCM_RTS : 0);
3496 } else {
3497 result = ((status & CyRTS) ? TIOCM_RTS : 0) |
3498 ((status & CyDTR) ? TIOCM_DTR : 0);
3499 }
3500 result |= ((status & CyDCD) ? TIOCM_CAR : 0) |
3501 ((status & CyRI) ? TIOCM_RNG : 0) |
3502 ((status & CyDSR) ? TIOCM_DSR : 0) |
3503 ((status & CyCTS) ? TIOCM_CTS : 0);
1da177e4 3504 } else {
875b206b
JS
3505 base_addr = card->base_addr;
3506 firm_id = card->base_addr + ID_ADDRESS;
3507 if (ISZLOADED(*card)) {
3508 zfw_ctrl = card->base_addr +
db05c3b1 3509 (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c
JS
3510 board_ctrl = &zfw_ctrl->board_ctrl;
3511 ch_ctrl = zfw_ctrl->ch_ctrl;
db05c3b1 3512 lstatus = readl(&ch_ctrl[channel].rs_status);
02f1175c
JS
3513 result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
3514 ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
3515 ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
3516 ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
3517 ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
3518 ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
3519 } else {
3520 result = 0;
7b130c0e 3521 unlock_kernel();
02f1175c
JS
3522 return -ENODEV;
3523 }
1da177e4 3524
02f1175c 3525 }
7b130c0e 3526 unlock_kernel();
02f1175c
JS
3527 return result;
3528} /* cy_tiomget */
1da177e4
LT
3529
3530static int
3531cy_tiocmset(struct tty_struct *tty, struct file *file,
02f1175c 3532 unsigned int set, unsigned int clear)
1da177e4 3533{
cab9bdd1 3534 struct cyclades_port *info = tty->driver_data;
875b206b
JS
3535 struct cyclades_card *card;
3536 int chip, channel, index;
02f1175c
JS
3537 void __iomem *base_addr;
3538 unsigned long flags;
3539 struct FIRM_ID __iomem *firm_id;
3540 struct ZFW_CTRL __iomem *zfw_ctrl;
3541 struct BOARD_CTRL __iomem *board_ctrl;
3542 struct CH_CTRL __iomem *ch_ctrl;
3543 int retval;
3544
bf9d8929 3545 if (serial_paranoia_check(info, tty->name, __func__))
02f1175c
JS
3546 return -ENODEV;
3547
3548 card = info->card;
875b206b
JS
3549 channel = (info->line) - (card->first_line);
3550 if (!IS_CYC_Z(*card)) {
02f1175c
JS
3551 chip = channel >> 2;
3552 channel &= 0x03;
875b206b
JS
3553 index = card->bus_index;
3554 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
02f1175c
JS
3555
3556 if (set & TIOCM_RTS) {
9fa1b3b1 3557 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
3558 cy_writeb(base_addr + (CyCAR << index),
3559 (u_char) channel);
3560 if (info->rtsdtr_inv) {
3561 cy_writeb(base_addr + (CyMSVR2 << index),
3562 CyDTR);
3563 } else {
3564 cy_writeb(base_addr + (CyMSVR1 << index),
3565 CyRTS);
3566 }
9fa1b3b1 3567 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3568 }
3569 if (clear & TIOCM_RTS) {
9fa1b3b1 3570 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
3571 cy_writeb(base_addr + (CyCAR << index),
3572 (u_char) channel);
3573 if (info->rtsdtr_inv) {
3574 cy_writeb(base_addr + (CyMSVR2 << index),
3575 ~CyDTR);
3576 } else {
3577 cy_writeb(base_addr + (CyMSVR1 << index),
3578 ~CyRTS);
3579 }
9fa1b3b1 3580 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3581 }
3582 if (set & TIOCM_DTR) {
9fa1b3b1 3583 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
3584 cy_writeb(base_addr + (CyCAR << index),
3585 (u_char) channel);
3586 if (info->rtsdtr_inv) {
3587 cy_writeb(base_addr + (CyMSVR1 << index),
3588 CyRTS);
3589 } else {
3590 cy_writeb(base_addr + (CyMSVR2 << index),
3591 CyDTR);
3592 }
1da177e4 3593#ifdef CY_DEBUG_DTR
21719191
JS
3594 printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
3595 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
db05c3b1
JS
3596 readb(base_addr + (CyMSVR1 << index)),
3597 readb(base_addr + (CyMSVR2 << index)));
1da177e4 3598#endif
9fa1b3b1 3599 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3600 }
3601 if (clear & TIOCM_DTR) {
9fa1b3b1 3602 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
3603 cy_writeb(base_addr + (CyCAR << index),
3604 (u_char) channel);
3605 if (info->rtsdtr_inv) {
3606 cy_writeb(base_addr + (CyMSVR1 << index),
3607 ~CyRTS);
3608 } else {
3609 cy_writeb(base_addr + (CyMSVR2 << index),
3610 ~CyDTR);
3611 }
1da177e4
LT
3612
3613#ifdef CY_DEBUG_DTR
21719191
JS
3614 printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
3615 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
db05c3b1
JS
3616 readb(base_addr + (CyMSVR1 << index)),
3617 readb(base_addr + (CyMSVR2 << index)));
1da177e4 3618#endif
9fa1b3b1 3619 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3620 }
3621 } else {
875b206b 3622 base_addr = card->base_addr;
02f1175c 3623
875b206b
JS
3624 firm_id = card->base_addr + ID_ADDRESS;
3625 if (ISZLOADED(*card)) {
3626 zfw_ctrl = card->base_addr +
db05c3b1 3627 (readl(&firm_id->zfwctrl_addr) & 0xfffff);
02f1175c
JS
3628 board_ctrl = &zfw_ctrl->board_ctrl;
3629 ch_ctrl = zfw_ctrl->ch_ctrl;
3630
3631 if (set & TIOCM_RTS) {
9fa1b3b1 3632 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 3633 cy_writel(&ch_ctrl[channel].rs_control,
db05c3b1
JS
3634 readl(&ch_ctrl[channel].rs_control) |
3635 C_RS_RTS);
9fa1b3b1 3636 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3637 }
3638 if (clear & TIOCM_RTS) {
9fa1b3b1 3639 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 3640 cy_writel(&ch_ctrl[channel].rs_control,
db05c3b1
JS
3641 readl(&ch_ctrl[channel].rs_control) &
3642 ~C_RS_RTS);
9fa1b3b1 3643 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3644 }
3645 if (set & TIOCM_DTR) {
9fa1b3b1 3646 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 3647 cy_writel(&ch_ctrl[channel].rs_control,
db05c3b1
JS
3648 readl(&ch_ctrl[channel].rs_control) |
3649 C_RS_DTR);
1da177e4 3650#ifdef CY_DEBUG_DTR
21719191
JS
3651 printk(KERN_DEBUG "cyc:set_modem_info raising "
3652 "Z DTR\n");
1da177e4 3653#endif
9fa1b3b1 3654 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3655 }
3656 if (clear & TIOCM_DTR) {
9fa1b3b1 3657 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 3658 cy_writel(&ch_ctrl[channel].rs_control,
db05c3b1
JS
3659 readl(&ch_ctrl[channel].rs_control) &
3660 ~C_RS_DTR);
1da177e4 3661#ifdef CY_DEBUG_DTR
21719191
JS
3662 printk(KERN_DEBUG "cyc:set_modem_info clearing "
3663 "Z DTR\n");
1da177e4 3664#endif
9fa1b3b1 3665 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3666 }
3667 } else {
3668 return -ENODEV;
3669 }
9fa1b3b1
JS
3670 spin_lock_irqsave(&card->card_lock, flags);
3671 retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
02f1175c 3672 if (retval != 0) {
21719191
JS
3673 printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
3674 "was %x\n", info->line, retval);
02f1175c 3675 }
9fa1b3b1 3676 spin_unlock_irqrestore(&card->card_lock, flags);
1da177e4 3677 }
02f1175c
JS
3678 return 0;
3679} /* cy_tiocmset */
1da177e4
LT
3680
3681/*
3682 * cy_break() --- routine which turns the break handling on or off
3683 */
9e98966c 3684static int cy_break(struct tty_struct *tty, int break_state)
1da177e4 3685{
cab9bdd1 3686 struct cyclades_port *info = tty->driver_data;
9fa1b3b1 3687 struct cyclades_card *card;
02f1175c 3688 unsigned long flags;
9e98966c 3689 int retval = 0;
1da177e4 3690
02f1175c 3691 if (serial_paranoia_check(info, tty->name, "cy_break"))
9e98966c 3692 return -EINVAL;
1da177e4 3693
9fa1b3b1
JS
3694 card = info->card;
3695
3696 spin_lock_irqsave(&card->card_lock, flags);
3697 if (!IS_CYC_Z(*card)) {
02f1175c
JS
3698 /* Let the transmit ISR take care of this (since it
3699 requires stuffing characters into the output stream).
3700 */
3701 if (break_state == -1) {
3702 if (!info->breakon) {
3703 info->breakon = 1;
3704 if (!info->xmit_cnt) {
9fa1b3b1 3705 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c 3706 start_xmit(info);
9fa1b3b1 3707 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
3708 }
3709 }
3710 } else {
3711 if (!info->breakoff) {
3712 info->breakoff = 1;
3713 if (!info->xmit_cnt) {
9fa1b3b1 3714 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c 3715 start_xmit(info);
9fa1b3b1 3716 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
3717 }
3718 }
1da177e4 3719 }
1da177e4 3720 } else {
02f1175c 3721 if (break_state == -1) {
9fa1b3b1
JS
3722 retval = cyz_issue_cmd(card,
3723 info->line - card->first_line,
02f1175c
JS
3724 C_CM_SET_BREAK, 0L);
3725 if (retval != 0) {
21719191
JS
3726 printk(KERN_ERR "cyc:cy_break (set) retval on "
3727 "ttyC%d was %x\n", info->line, retval);
02f1175c
JS
3728 }
3729 } else {
9fa1b3b1
JS
3730 retval = cyz_issue_cmd(card,
3731 info->line - card->first_line,
02f1175c
JS
3732 C_CM_CLR_BREAK, 0L);
3733 if (retval != 0) {
21719191
JS
3734 printk(KERN_DEBUG "cyc:cy_break (clr) retval "
3735 "on ttyC%d was %x\n", info->line,
3736 retval);
02f1175c 3737 }
1da177e4 3738 }
1da177e4 3739 }
9fa1b3b1 3740 spin_unlock_irqrestore(&card->card_lock, flags);
9e98966c 3741 return retval;
02f1175c 3742} /* cy_break */
1da177e4 3743
15ed6cc0
AC
3744static int get_mon_info(struct cyclades_port *info,
3745 struct cyclades_monitor __user *mon)
1da177e4
LT
3746{
3747
02f1175c
JS
3748 if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
3749 return -EFAULT;
3750 info->mon.int_count = 0;
3751 info->mon.char_count = 0;
3752 info->mon.char_max = 0;
3753 info->mon.char_last = 0;
3754 return 0;
3755} /* get_mon_info */
1da177e4 3756
02f1175c 3757static int set_threshold(struct cyclades_port *info, unsigned long value)
1da177e4 3758{
875b206b 3759 struct cyclades_card *card;
02f1175c 3760 void __iomem *base_addr;
875b206b 3761 int channel, chip, index;
02f1175c 3762 unsigned long flags;
1da177e4 3763
02f1175c 3764 card = info->card;
875b206b
JS
3765 channel = info->line - card->first_line;
3766 if (!IS_CYC_Z(*card)) {
02f1175c
JS
3767 chip = channel >> 2;
3768 channel &= 0x03;
875b206b 3769 index = card->bus_index;
02f1175c 3770 base_addr =
875b206b 3771 card->base_addr + (cy_chip_offset[chip] << index);
02f1175c
JS
3772
3773 info->cor3 &= ~CyREC_FIFO;
3774 info->cor3 |= value & CyREC_FIFO;
1da177e4 3775
9fa1b3b1 3776 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
3777 cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
3778 cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index);
9fa1b3b1 3779 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3780 }
3781 return 0;
3782} /* set_threshold */
1da177e4 3783
15ed6cc0
AC
3784static int get_threshold(struct cyclades_port *info,
3785 unsigned long __user *value)
1da177e4 3786{
875b206b 3787 struct cyclades_card *card;
02f1175c 3788 void __iomem *base_addr;
875b206b 3789 int channel, chip, index;
02f1175c 3790 unsigned long tmp;
1da177e4 3791
02f1175c 3792 card = info->card;
875b206b
JS
3793 channel = info->line - card->first_line;
3794 if (!IS_CYC_Z(*card)) {
02f1175c
JS
3795 chip = channel >> 2;
3796 channel &= 0x03;
875b206b
JS
3797 index = card->bus_index;
3798 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
02f1175c 3799
db05c3b1 3800 tmp = readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO;
02f1175c 3801 return put_user(tmp, value);
02f1175c 3802 }
f7429034 3803 return 0;
02f1175c 3804} /* get_threshold */
1da177e4 3805
15ed6cc0
AC
3806static int set_default_threshold(struct cyclades_port *info,
3807 unsigned long value)
1da177e4 3808{
02f1175c
JS
3809 info->default_threshold = value & 0x0f;
3810 return 0;
3811} /* set_default_threshold */
1da177e4 3812
15ed6cc0
AC
3813static int get_default_threshold(struct cyclades_port *info,
3814 unsigned long __user *value)
1da177e4 3815{
02f1175c
JS
3816 return put_user(info->default_threshold, value);
3817} /* get_default_threshold */
1da177e4 3818
02f1175c 3819static int set_timeout(struct cyclades_port *info, unsigned long value)
1da177e4 3820{
875b206b 3821 struct cyclades_card *card;
02f1175c 3822 void __iomem *base_addr;
875b206b 3823 int channel, chip, index;
02f1175c 3824 unsigned long flags;
1da177e4 3825
02f1175c 3826 card = info->card;
875b206b
JS
3827 channel = info->line - card->first_line;
3828 if (!IS_CYC_Z(*card)) {
02f1175c
JS
3829 chip = channel >> 2;
3830 channel &= 0x03;
875b206b
JS
3831 index = card->bus_index;
3832 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
1da177e4 3833
9fa1b3b1 3834 spin_lock_irqsave(&card->card_lock, flags);
02f1175c 3835 cy_writeb(base_addr + (CyRTPR << index), value & 0xff);
9fa1b3b1 3836 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
3837 }
3838 return 0;
3839} /* set_timeout */
1da177e4 3840
15ed6cc0
AC
3841static int get_timeout(struct cyclades_port *info,
3842 unsigned long __user *value)
1da177e4 3843{
875b206b 3844 struct cyclades_card *card;
02f1175c 3845 void __iomem *base_addr;
875b206b 3846 int channel, chip, index;
02f1175c 3847 unsigned long tmp;
1da177e4 3848
02f1175c 3849 card = info->card;
875b206b
JS
3850 channel = info->line - card->first_line;
3851 if (!IS_CYC_Z(*card)) {
02f1175c
JS
3852 chip = channel >> 2;
3853 channel &= 0x03;
875b206b
JS
3854 index = card->bus_index;
3855 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
02f1175c 3856
db05c3b1 3857 tmp = readb(base_addr + (CyRTPR << index));
02f1175c 3858 return put_user(tmp, value);
02f1175c 3859 }
f7429034 3860 return 0;
02f1175c 3861} /* get_timeout */
1da177e4 3862
02f1175c 3863static int set_default_timeout(struct cyclades_port *info, unsigned long value)
1da177e4 3864{
02f1175c
JS
3865 info->default_timeout = value & 0xff;
3866 return 0;
3867} /* set_default_timeout */
1da177e4 3868
15ed6cc0
AC
3869static int get_default_timeout(struct cyclades_port *info,
3870 unsigned long __user *value)
1da177e4 3871{
02f1175c
JS
3872 return put_user(info->default_timeout, value);
3873} /* get_default_timeout */
1da177e4
LT
3874
3875/*
3876 * This routine allows the tty driver to implement device-
3877 * specific ioctl's. If the ioctl number passed in cmd is
3878 * not recognized by the driver, it should return ENOIOCTLCMD.
3879 */
3880static int
02f1175c
JS
3881cy_ioctl(struct tty_struct *tty, struct file *file,
3882 unsigned int cmd, unsigned long arg)
1da177e4 3883{
cab9bdd1 3884 struct cyclades_port *info = tty->driver_data;
02f1175c
JS
3885 struct cyclades_icount cprev, cnow; /* kernel counter temps */
3886 struct serial_icounter_struct __user *p_cuser; /* user space */
3887 int ret_val = 0;
3888 unsigned long flags;
3889 void __user *argp = (void __user *)arg;
3890
3891 if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
3892 return -ENODEV;
1da177e4
LT
3893
3894#ifdef CY_DEBUG_OTHER
21719191
JS
3895 printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
3896 info->line, cmd, arg);
1da177e4 3897#endif
7b130c0e 3898 lock_kernel();
1da177e4 3899
02f1175c
JS
3900 switch (cmd) {
3901 case CYGETMON:
3902 ret_val = get_mon_info(info, argp);
3903 break;
3904 case CYGETTHRESH:
3905 ret_val = get_threshold(info, argp);
3906 break;
3907 case CYSETTHRESH:
3908 ret_val = set_threshold(info, arg);
3909 break;
3910 case CYGETDEFTHRESH:
3911 ret_val = get_default_threshold(info, argp);
3912 break;
3913 case CYSETDEFTHRESH:
3914 ret_val = set_default_threshold(info, arg);
3915 break;
3916 case CYGETTIMEOUT:
3917 ret_val = get_timeout(info, argp);
3918 break;
3919 case CYSETTIMEOUT:
3920 ret_val = set_timeout(info, arg);
3921 break;
3922 case CYGETDEFTIMEOUT:
3923 ret_val = get_default_timeout(info, argp);
3924 break;
3925 case CYSETDEFTIMEOUT:
3926 ret_val = set_default_timeout(info, arg);
3927 break;
1da177e4 3928 case CYSETRFLOW:
02f1175c
JS
3929 info->rflow = (int)arg;
3930 ret_val = 0;
3931 break;
1da177e4 3932 case CYGETRFLOW:
02f1175c
JS
3933 ret_val = info->rflow;
3934 break;
1da177e4 3935 case CYSETRTSDTR_INV:
02f1175c
JS
3936 info->rtsdtr_inv = (int)arg;
3937 ret_val = 0;
3938 break;
1da177e4 3939 case CYGETRTSDTR_INV:
02f1175c
JS
3940 ret_val = info->rtsdtr_inv;
3941 break;
1da177e4 3942 case CYGETCD1400VER:
02f1175c
JS
3943 ret_val = info->chip_rev;
3944 break;
1da177e4
LT
3945#ifndef CONFIG_CYZ_INTR
3946 case CYZSETPOLLCYCLE:
02f1175c
JS
3947 cyz_polling_cycle = (arg * HZ) / 1000;
3948 ret_val = 0;
3949 break;
1da177e4 3950 case CYZGETPOLLCYCLE:
02f1175c
JS
3951 ret_val = (cyz_polling_cycle * 1000) / HZ;
3952 break;
3953#endif /* CONFIG_CYZ_INTR */
1da177e4 3954 case CYSETWAIT:
44b7d1b3 3955 info->port.closing_wait = (unsigned short)arg * HZ / 100;
02f1175c
JS
3956 ret_val = 0;
3957 break;
1da177e4 3958 case CYGETWAIT:
44b7d1b3 3959 ret_val = info->port.closing_wait / (HZ / 100);
02f1175c
JS
3960 break;
3961 case TIOCGSERIAL:
3962 ret_val = get_serial_info(info, argp);
3963 break;
3964 case TIOCSSERIAL:
3965 ret_val = set_serial_info(info, argp);
3966 break;
3967 case TIOCSERGETLSR: /* Get line status register */
3968 ret_val = get_lsr_info(info, argp);
3969 break;
3970 /*
3971 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
3972 * - mask passed in arg for lines of interest
3973 * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
3974 * Caller should use TIOCGICOUNT to see which one it was
3975 */
1da177e4 3976 case TIOCMIWAIT:
9fa1b3b1 3977 spin_lock_irqsave(&info->card->card_lock, flags);
02f1175c 3978 /* note the counters on entry */
2c7fea99 3979 cnow = info->icount;
9fa1b3b1 3980 spin_unlock_irqrestore(&info->card->card_lock, flags);
2c7fea99
JS
3981 ret_val = wait_event_interruptible(info->delta_msr_wait, ({
3982 cprev = cnow;
9fa1b3b1 3983 spin_lock_irqsave(&info->card->card_lock, flags);
02f1175c 3984 cnow = info->icount; /* atomic copy */
9fa1b3b1 3985 spin_unlock_irqrestore(&info->card->card_lock, flags);
02f1175c 3986
2c7fea99
JS
3987 ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
3988 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
3989 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
3990 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts));
3991 }));
3992 break;
1da177e4 3993
02f1175c
JS
3994 /*
3995 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
3996 * Return: write counters to the user passed counter struct
3997 * NB: both 1->0 and 0->1 transitions are counted except for
3998 * RI where only 0->1 is counted.
3999 */
1da177e4 4000 case TIOCGICOUNT:
9fa1b3b1 4001 spin_lock_irqsave(&info->card->card_lock, flags);
02f1175c 4002 cnow = info->icount;
9fa1b3b1 4003 spin_unlock_irqrestore(&info->card->card_lock, flags);
02f1175c
JS
4004 p_cuser = argp;
4005 ret_val = put_user(cnow.cts, &p_cuser->cts);
4006 if (ret_val)
7b130c0e 4007 break;
02f1175c
JS
4008 ret_val = put_user(cnow.dsr, &p_cuser->dsr);
4009 if (ret_val)
7b130c0e 4010 break;
02f1175c
JS
4011 ret_val = put_user(cnow.rng, &p_cuser->rng);
4012 if (ret_val)
7b130c0e 4013 break;
02f1175c
JS
4014 ret_val = put_user(cnow.dcd, &p_cuser->dcd);
4015 if (ret_val)
7b130c0e 4016 break;
02f1175c
JS
4017 ret_val = put_user(cnow.rx, &p_cuser->rx);
4018 if (ret_val)
7b130c0e 4019 break;
02f1175c
JS
4020 ret_val = put_user(cnow.tx, &p_cuser->tx);
4021 if (ret_val)
7b130c0e 4022 break;
02f1175c
JS
4023 ret_val = put_user(cnow.frame, &p_cuser->frame);
4024 if (ret_val)
7b130c0e 4025 break;
02f1175c
JS
4026 ret_val = put_user(cnow.overrun, &p_cuser->overrun);
4027 if (ret_val)
7b130c0e 4028 break;
02f1175c
JS
4029 ret_val = put_user(cnow.parity, &p_cuser->parity);
4030 if (ret_val)
7b130c0e 4031 break;
02f1175c
JS
4032 ret_val = put_user(cnow.brk, &p_cuser->brk);
4033 if (ret_val)
7b130c0e 4034 break;
02f1175c
JS
4035 ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
4036 if (ret_val)
7b130c0e 4037 break;
02f1175c
JS
4038 ret_val = 0;
4039 break;
4040 default:
4041 ret_val = -ENOIOCTLCMD;
4042 }
7b130c0e 4043 unlock_kernel();
1da177e4
LT
4044
4045#ifdef CY_DEBUG_OTHER
21719191 4046 printk(KERN_DEBUG "cyc:cy_ioctl done\n");
1da177e4 4047#endif
02f1175c
JS
4048 return ret_val;
4049} /* cy_ioctl */
1da177e4
LT
4050
4051/*
4052 * This routine allows the tty driver to be notified when
4053 * device's termios settings have changed. Note that a
4054 * well-designed tty driver should be prepared to accept the case
4055 * where old == NULL, and try to do something rational.
4056 */
02f1175c 4057static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
1da177e4 4058{
cab9bdd1 4059 struct cyclades_port *info = tty->driver_data;
1da177e4
LT
4060
4061#ifdef CY_DEBUG_OTHER
21719191 4062 printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
1da177e4
LT
4063#endif
4064
02f1175c
JS
4065 set_line_char(info);
4066
4067 if ((old_termios->c_cflag & CRTSCTS) &&
4068 !(tty->termios->c_cflag & CRTSCTS)) {
4069 tty->hw_stopped = 0;
4070 cy_start(tty);
4071 }
1da177e4 4072#if 0
02f1175c
JS
4073 /*
4074 * No need to wake up processes in open wait, since they
4075 * sample the CLOCAL flag once, and don't recheck it.
4076 * XXX It's not clear whether the current behavior is correct
4077 * or not. Hence, this may change.....
4078 */
4079 if (!(old_termios->c_cflag & CLOCAL) &&
4080 (tty->termios->c_cflag & CLOCAL))
77451e53 4081 wake_up_interruptible(&info->port.open_wait);
1da177e4 4082#endif
02f1175c 4083} /* cy_set_termios */
1da177e4
LT
4084
4085/* This function is used to send a high-priority XON/XOFF character to
4086 the device.
4087*/
02f1175c 4088static void cy_send_xchar(struct tty_struct *tty, char ch)
1da177e4 4089{
cab9bdd1 4090 struct cyclades_port *info = tty->driver_data;
875b206b
JS
4091 struct cyclades_card *card;
4092 int channel;
1da177e4 4093
02f1175c 4094 if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
1da177e4
LT
4095 return;
4096
02f1175c 4097 info->x_char = ch;
1da177e4
LT
4098
4099 if (ch)
02f1175c 4100 cy_start(tty);
1da177e4
LT
4101
4102 card = info->card;
875b206b 4103 channel = info->line - card->first_line;
1da177e4 4104
875b206b 4105 if (IS_CYC_Z(*card)) {
02f1175c 4106 if (ch == STOP_CHAR(tty))
875b206b 4107 cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
02f1175c 4108 else if (ch == START_CHAR(tty))
875b206b 4109 cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L);
1da177e4
LT
4110 }
4111}
4112
4113/* This routine is called by the upper-layer tty layer to signal
4114 that incoming characters should be throttled because the input
4115 buffers are close to full.
4116 */
02f1175c 4117static void cy_throttle(struct tty_struct *tty)
1da177e4 4118{
cab9bdd1 4119 struct cyclades_port *info = tty->driver_data;
875b206b 4120 struct cyclades_card *card;
02f1175c
JS
4121 unsigned long flags;
4122 void __iomem *base_addr;
875b206b 4123 int chip, channel, index;
1da177e4
LT
4124
4125#ifdef CY_DEBUG_THROTTLE
02f1175c 4126 char buf[64];
1da177e4 4127
21719191 4128 printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf),
02f1175c 4129 tty->ldisc.chars_in_buffer(tty), info->line);
1da177e4
LT
4130#endif
4131
15ed6cc0 4132 if (serial_paranoia_check(info, tty->name, "cy_throttle"))
02f1175c 4133 return;
02f1175c
JS
4134
4135 card = info->card;
4136
4137 if (I_IXOFF(tty)) {
875b206b 4138 if (!IS_CYC_Z(*card))
02f1175c
JS
4139 cy_send_xchar(tty, STOP_CHAR(tty));
4140 else
4141 info->throttle = 1;
4142 }
1da177e4 4143
02f1175c 4144 if (tty->termios->c_cflag & CRTSCTS) {
875b206b
JS
4145 channel = info->line - card->first_line;
4146 if (!IS_CYC_Z(*card)) {
02f1175c
JS
4147 chip = channel >> 2;
4148 channel &= 0x03;
875b206b
JS
4149 index = card->bus_index;
4150 base_addr = card->base_addr +
02f1175c
JS
4151 (cy_chip_offset[chip] << index);
4152
9fa1b3b1 4153 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
4154 cy_writeb(base_addr + (CyCAR << index),
4155 (u_char) channel);
4156 if (info->rtsdtr_inv) {
4157 cy_writeb(base_addr + (CyMSVR2 << index),
4158 ~CyDTR);
4159 } else {
4160 cy_writeb(base_addr + (CyMSVR1 << index),
4161 ~CyRTS);
4162 }
9fa1b3b1 4163 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
4164 } else {
4165 info->throttle = 1;
4166 }
4167 }
02f1175c 4168} /* cy_throttle */
1da177e4
LT
4169
4170/*
4171 * This routine notifies the tty driver that it should signal
4172 * that characters can now be sent to the tty without fear of
4173 * overrunning the input buffers of the line disciplines.
4174 */
02f1175c 4175static void cy_unthrottle(struct tty_struct *tty)
1da177e4 4176{
cab9bdd1 4177 struct cyclades_port *info = tty->driver_data;
875b206b 4178 struct cyclades_card *card;
02f1175c
JS
4179 unsigned long flags;
4180 void __iomem *base_addr;
875b206b 4181 int chip, channel, index;
1da177e4
LT
4182
4183#ifdef CY_DEBUG_THROTTLE
02f1175c
JS
4184 char buf[64];
4185
21719191 4186 printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
15ed6cc0 4187 tty_name(tty, buf), tty_chars_in_buffer(tty), info->line);
1da177e4
LT
4188#endif
4189
15ed6cc0 4190 if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
02f1175c 4191 return;
1da177e4 4192
02f1175c
JS
4193 if (I_IXOFF(tty)) {
4194 if (info->x_char)
4195 info->x_char = 0;
4196 else
4197 cy_send_xchar(tty, START_CHAR(tty));
1da177e4 4198 }
1da177e4 4199
02f1175c
JS
4200 if (tty->termios->c_cflag & CRTSCTS) {
4201 card = info->card;
875b206b
JS
4202 channel = info->line - card->first_line;
4203 if (!IS_CYC_Z(*card)) {
02f1175c
JS
4204 chip = channel >> 2;
4205 channel &= 0x03;
875b206b
JS
4206 index = card->bus_index;
4207 base_addr = card->base_addr +
02f1175c
JS
4208 (cy_chip_offset[chip] << index);
4209
9fa1b3b1 4210 spin_lock_irqsave(&card->card_lock, flags);
02f1175c
JS
4211 cy_writeb(base_addr + (CyCAR << index),
4212 (u_char) channel);
4213 if (info->rtsdtr_inv) {
4214 cy_writeb(base_addr + (CyMSVR2 << index),
4215 CyDTR);
4216 } else {
4217 cy_writeb(base_addr + (CyMSVR1 << index),
4218 CyRTS);
4219 }
9fa1b3b1 4220 spin_unlock_irqrestore(&card->card_lock, flags);
02f1175c
JS
4221 } else {
4222 info->throttle = 0;
4223 }
4224 }
02f1175c 4225} /* cy_unthrottle */
1da177e4
LT
4226
4227/* cy_start and cy_stop provide software output flow control as a
4228 function of XON/XOFF, software CTS, and other such stuff.
4229*/
02f1175c 4230static void cy_stop(struct tty_struct *tty)
1da177e4 4231{
02f1175c 4232 struct cyclades_card *cinfo;
cab9bdd1 4233 struct cyclades_port *info = tty->driver_data;
02f1175c
JS
4234 void __iomem *base_addr;
4235 int chip, channel, index;
4236 unsigned long flags;
1da177e4
LT
4237
4238#ifdef CY_DEBUG_OTHER
21719191 4239 printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line);
1da177e4
LT
4240#endif
4241
02f1175c
JS
4242 if (serial_paranoia_check(info, tty->name, "cy_stop"))
4243 return;
1da177e4 4244
875b206b 4245 cinfo = info->card;
02f1175c
JS
4246 channel = info->line - cinfo->first_line;
4247 if (!IS_CYC_Z(*cinfo)) {
4248 index = cinfo->bus_index;
4249 chip = channel >> 2;
4250 channel &= 0x03;
9fa1b3b1 4251 base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
1da177e4 4252
9fa1b3b1 4253 spin_lock_irqsave(&cinfo->card_lock, flags);
02f1175c
JS
4254 cy_writeb(base_addr + (CyCAR << index),
4255 (u_char)(channel & 0x0003)); /* index channel */
4256 cy_writeb(base_addr + (CySRER << index),
db05c3b1 4257 readb(base_addr + (CySRER << index)) & ~CyTxRdy);
9fa1b3b1 4258 spin_unlock_irqrestore(&cinfo->card_lock, flags);
02f1175c 4259 }
02f1175c 4260} /* cy_stop */
1da177e4 4261
02f1175c 4262static void cy_start(struct tty_struct *tty)
1da177e4 4263{
02f1175c 4264 struct cyclades_card *cinfo;
cab9bdd1 4265 struct cyclades_port *info = tty->driver_data;
02f1175c
JS
4266 void __iomem *base_addr;
4267 int chip, channel, index;
4268 unsigned long flags;
1da177e4
LT
4269
4270#ifdef CY_DEBUG_OTHER
21719191 4271 printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line);
1da177e4
LT
4272#endif
4273
02f1175c
JS
4274 if (serial_paranoia_check(info, tty->name, "cy_start"))
4275 return;
1da177e4 4276
875b206b 4277 cinfo = info->card;
02f1175c
JS
4278 channel = info->line - cinfo->first_line;
4279 index = cinfo->bus_index;
4280 if (!IS_CYC_Z(*cinfo)) {
4281 chip = channel >> 2;
4282 channel &= 0x03;
9fa1b3b1 4283 base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
1da177e4 4284
9fa1b3b1 4285 spin_lock_irqsave(&cinfo->card_lock, flags);
15ed6cc0
AC
4286 cy_writeb(base_addr + (CyCAR << index),
4287 (u_char) (channel & 0x0003)); /* index channel */
02f1175c 4288 cy_writeb(base_addr + (CySRER << index),
db05c3b1 4289 readb(base_addr + (CySRER << index)) | CyTxRdy);
9fa1b3b1 4290 spin_unlock_irqrestore(&cinfo->card_lock, flags);
02f1175c 4291 }
02f1175c 4292} /* cy_start */
1da177e4 4293
1da177e4
LT
4294/*
4295 * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
4296 */
02f1175c 4297static void cy_hangup(struct tty_struct *tty)
1da177e4 4298{
cab9bdd1 4299 struct cyclades_port *info = tty->driver_data;
02f1175c 4300
1da177e4 4301#ifdef CY_DEBUG_OTHER
21719191 4302 printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line);
1da177e4
LT
4303#endif
4304
02f1175c
JS
4305 if (serial_paranoia_check(info, tty->name, "cy_hangup"))
4306 return;
1da177e4 4307
02f1175c
JS
4308 cy_flush_buffer(tty);
4309 shutdown(info);
77451e53 4310 info->port.count = 0;
1da177e4 4311#ifdef CY_DEBUG_COUNT
21719191
JS
4312 printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n",
4313 current->pid);
1da177e4 4314#endif
77451e53
AC
4315 info->port.tty = NULL;
4316 info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
4317 wake_up_interruptible(&info->port.open_wait);
02f1175c 4318} /* cy_hangup */
1da177e4
LT
4319
4320/*
4321 * ---------------------------------------------------------------------
4322 * cy_init() and friends
4323 *
4324 * cy_init() is called at boot-time to initialize the serial driver.
4325 * ---------------------------------------------------------------------
4326 */
4327
dd025c0c 4328static int __devinit cy_init_card(struct cyclades_card *cinfo)
0809e267
JS
4329{
4330 struct cyclades_port *info;
65f76a82 4331 unsigned int nports, port;
0809e267 4332 unsigned short chip_number;
65f76a82 4333 int uninitialized_var(index);
0809e267 4334
3046d50e
JS
4335 spin_lock_init(&cinfo->card_lock);
4336
c2ad4c75 4337 if (IS_CYC_Z(*cinfo)) { /* Cyclades-Z */
101b8159 4338 nports = (cinfo->hw_ver == ZE_V1) ? ZE_V1_NPORTS : 8;
0809e267
JS
4339 cinfo->intr_enabled = 0;
4340 cinfo->nports = 0; /* Will be correctly set later, after
4341 Z FW is loaded */
3046d50e
JS
4342 } else {
4343 index = cinfo->bus_index;
4344 nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
4345 }
4346
dd025c0c
JS
4347 cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL);
4348 if (cinfo->ports == NULL) {
4349 printk(KERN_ERR "Cyclades: cannot allocate ports\n");
3137553d 4350 cinfo->nports = 0;
dd025c0c
JS
4351 return -ENOMEM;
4352 }
4353
3046d50e
JS
4354 for (port = cinfo->first_line; port < cinfo->first_line + nports;
4355 port++) {
dd025c0c 4356 info = &cinfo->ports[port - cinfo->first_line];
44b7d1b3 4357 tty_port_init(&info->port);
3046d50e 4358 info->magic = CYCLADES_MAGIC;
875b206b 4359 info->card = cinfo;
3046d50e 4360 info->line = port;
3046d50e 4361
44b7d1b3
AC
4362 info->port.closing_wait = CLOSING_WAIT_DELAY;
4363 info->port.close_delay = 5 * HZ / 10;
77451e53 4364 info->port.flags = STD_COM_FLAGS;
2c7fea99 4365 init_completion(&info->shutdown_wait);
3046d50e
JS
4366 init_waitqueue_head(&info->delta_msr_wait);
4367
4368 if (IS_CYC_Z(*cinfo)) {
0809e267 4369 info->type = PORT_STARTECH;
101b8159 4370 if (cinfo->hw_ver == ZO_V1)
0809e267
JS
4371 info->xmit_fifo_size = CYZ_FIFO_SIZE;
4372 else
3046d50e 4373 info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
0809e267 4374#ifdef CONFIG_CYZ_INTR
3991428d
JS
4375 setup_timer(&cyz_rx_full_timer[port],
4376 cyz_rx_restart, (unsigned long)info);
0809e267 4377#endif
3046d50e 4378 } else {
0809e267 4379 info->type = PORT_CIRRUS;
0809e267 4380 info->xmit_fifo_size = CyMAX_CHAR_FIFO;
3046d50e 4381 info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
0809e267
JS
4382 info->cor2 = CyETC;
4383 info->cor3 = 0x08; /* _very_ small rcv threshold */
3046d50e 4384
0809e267 4385 chip_number = (port - cinfo->first_line) / 4;
15ed6cc0
AC
4386 info->chip_rev = readb(cinfo->base_addr +
4387 (cy_chip_offset[chip_number] << index) +
4388 (CyGFRCR << index));
4389
4390 if (info->chip_rev >= CD1400_REV_J) {
0809e267
JS
4391 /* It is a CD1400 rev. J or later */
4392 info->tbpr = baud_bpr_60[13]; /* Tx BPR */
4393 info->tco = baud_co_60[13]; /* Tx CO */
4394 info->rbpr = baud_bpr_60[13]; /* Rx BPR */
4395 info->rco = baud_co_60[13]; /* Rx CO */
0809e267
JS
4396 info->rtsdtr_inv = 1;
4397 } else {
4398 info->tbpr = baud_bpr_25[13]; /* Tx BPR */
4399 info->tco = baud_co_25[13]; /* Tx CO */
4400 info->rbpr = baud_bpr_25[13]; /* Rx BPR */
4401 info->rco = baud_co_25[13]; /* Rx CO */
0809e267
JS
4402 info->rtsdtr_inv = 0;
4403 }
3046d50e
JS
4404 info->read_status_mask = CyTIMEOUT | CySPECHAR |
4405 CyBREAK | CyPARITY | CyFRAME | CyOVERRUN;
0809e267 4406 }
3046d50e 4407
0809e267 4408 }
3046d50e
JS
4409
4410#ifndef CONFIG_CYZ_INTR
4411 if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) {
4412 mod_timer(&cyz_timerlist, jiffies + 1);
4413#ifdef CY_PCI_DEBUG
4414 printk(KERN_DEBUG "Cyclades-Z polling initialized\n");
4415#endif
4416 }
4417#endif
dd025c0c 4418 return 0;
0809e267
JS
4419}
4420
1da177e4
LT
4421/* initialize chips on Cyclom-Y card -- return number of valid
4422 chips (which is number of ports/4) */
31b4f0a1
JS
4423static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
4424 int index)
1da177e4 4425{
02f1175c
JS
4426 unsigned int chip_number;
4427 void __iomem *base_addr;
4428
4429 cy_writeb(true_base_addr + (Cy_HwReset << index), 0);
4430 /* Cy_HwReset is 0x1400 */
4431 cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0);
4432 /* Cy_ClrIntr is 0x1800 */
4433 udelay(500L);
4434
15ed6cc0
AC
4435 for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD;
4436 chip_number++) {
02f1175c
JS
4437 base_addr =
4438 true_base_addr + (cy_chip_offset[chip_number] << index);
4439 mdelay(1);
db05c3b1 4440 if (readb(base_addr + (CyCCR << index)) != 0x00) {
02f1175c
JS
4441 /*************
4442 printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
4443 chip_number, (unsigned long)base_addr);
4444 *************/
4445 return chip_number;
4446 }
4447
4448 cy_writeb(base_addr + (CyGFRCR << index), 0);
4449 udelay(10L);
4450
4451 /* The Cyclom-16Y does not decode address bit 9 and therefore
4452 cannot distinguish between references to chip 0 and a non-
4453 existent chip 4. If the preceding clearing of the supposed
4454 chip 4 GFRCR register appears at chip 0, there is no chip 4
4455 and this must be a Cyclom-16Y, not a Cyclom-32Ye.
4456 */
db05c3b1 4457 if (chip_number == 4 && readb(true_base_addr +
02f1175c
JS
4458 (cy_chip_offset[0] << index) +
4459 (CyGFRCR << index)) == 0) {
4460 return chip_number;
4461 }
4462
4463 cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
4464 mdelay(1);
4465
db05c3b1 4466 if (readb(base_addr + (CyGFRCR << index)) == 0x00) {
02f1175c
JS
4467 /*
4468 printk(" chip #%d at %#6lx is not responding ",
4469 chip_number, (unsigned long)base_addr);
4470 printk("(GFRCR stayed 0)\n",
4471 */
4472 return chip_number;
4473 }
db05c3b1 4474 if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) !=
02f1175c
JS
4475 0x40) {
4476 /*
4477 printk(" chip #%d at %#6lx is not valid (GFRCR == "
4478 "%#2x)\n",
4479 chip_number, (unsigned long)base_addr,
4480 base_addr[CyGFRCR<<index]);
4481 */
4482 return chip_number;
4483 }
4484 cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
db05c3b1 4485 if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
02f1175c
JS
4486 /* It is a CD1400 rev. J or later */
4487 /* Impossible to reach 5ms with this chip.
4488 Changed to 2ms instead (f = 500 Hz). */
4489 cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS);
4490 } else {
4491 /* f = 200 Hz */
4492 cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS);
4493 }
1da177e4 4494
02f1175c
JS
4495 /*
4496 printk(" chip #%d at %#6lx is rev 0x%2x\n",
4497 chip_number, (unsigned long)base_addr,
db05c3b1 4498 readb(base_addr+(CyGFRCR<<index)));
02f1175c
JS
4499 */
4500 }
4501 return chip_number;
4502} /* cyy_init_card */
1da177e4
LT
4503
4504/*
4505 * ---------------------------------------------------------------------
4506 * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
4507 * sets global variables and return the number of ISA boards found.
4508 * ---------------------------------------------------------------------
4509 */
02f1175c 4510static int __init cy_detect_isa(void)
1da177e4
LT
4511{
4512#ifdef CONFIG_ISA
02f1175c
JS
4513 unsigned short cy_isa_irq, nboard;
4514 void __iomem *cy_isa_address;
4515 unsigned short i, j, cy_isa_nchan;
1da177e4 4516#ifdef MODULE
02f1175c 4517 int isparam = 0;
1da177e4
LT
4518#endif
4519
02f1175c 4520 nboard = 0;
1da177e4
LT
4521
4522#ifdef MODULE
4523 /* Check for module parameters */
02f1175c
JS
4524 for (i = 0; i < NR_CARDS; i++) {
4525 if (maddr[i] || i) {
4526 isparam = 1;
4527 cy_isa_addresses[i] = maddr[i];
4528 }
4529 if (!maddr[i])
4530 break;
1da177e4
LT
4531 }
4532#endif
4533
02f1175c
JS
4534 /* scan the address table probing for Cyclom-Y/ISA boards */
4535 for (i = 0; i < NR_ISA_ADDRS; i++) {
4536 unsigned int isa_address = cy_isa_addresses[i];
15ed6cc0 4537 if (isa_address == 0x0000)
096dcfce 4538 return nboard;
1da177e4 4539
02f1175c 4540 /* probe for CD1400... */
cd989b3a 4541 cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin);
3137553d
JS
4542 if (cy_isa_address == NULL) {
4543 printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
4544 "address\n");
4545 continue;
4546 }
02f1175c
JS
4547 cy_isa_nchan = CyPORTS_PER_CHIP *
4548 cyy_init_card(cy_isa_address, 0);
4549 if (cy_isa_nchan == 0) {
3137553d 4550 iounmap(cy_isa_address);
02f1175c
JS
4551 continue;
4552 }
1da177e4
LT
4553#ifdef MODULE
4554 if (isparam && irq[i])
02f1175c 4555 cy_isa_irq = irq[i];
1da177e4
LT
4556 else
4557#endif
02f1175c
JS
4558 /* find out the board's irq by probing */
4559 cy_isa_irq = detect_isa_irq(cy_isa_address);
4560 if (cy_isa_irq == 0) {
21719191
JS
4561 printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the "
4562 "IRQ could not be detected.\n",
02f1175c 4563 (unsigned long)cy_isa_address);
3137553d 4564 iounmap(cy_isa_address);
02f1175c
JS
4565 continue;
4566 }
4567
4568 if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
21719191
JS
4569 printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
4570 "more channels are available. Change NR_PORTS "
4571 "in cyclades.c and recompile kernel.\n",
02f1175c 4572 (unsigned long)cy_isa_address);
3137553d 4573 iounmap(cy_isa_address);
096dcfce 4574 return nboard;
02f1175c
JS
4575 }
4576 /* fill the next cy_card structure available */
4577 for (j = 0; j < NR_CARDS; j++) {
f7429034 4578 if (cy_card[j].base_addr == NULL)
02f1175c
JS
4579 break;
4580 }
4581 if (j == NR_CARDS) { /* no more cy_cards available */
21719191
JS
4582 printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
4583 "more cards can be used. Change NR_CARDS in "
4584 "cyclades.c and recompile kernel.\n",
02f1175c 4585 (unsigned long)cy_isa_address);
3137553d 4586 iounmap(cy_isa_address);
096dcfce 4587 return nboard;
02f1175c
JS
4588 }
4589
4590 /* allocate IRQ */
4591 if (request_irq(cy_isa_irq, cyy_interrupt,
4592 IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) {
21719191
JS
4593 printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
4594 "could not allocate IRQ#%d.\n",
4595 (unsigned long)cy_isa_address, cy_isa_irq);
3137553d 4596 iounmap(cy_isa_address);
096dcfce 4597 return nboard;
02f1175c
JS
4598 }
4599
4600 /* set cy_card */
4601 cy_card[j].base_addr = cy_isa_address;
97e87f8e 4602 cy_card[j].ctl_addr.p9050 = NULL;
02f1175c
JS
4603 cy_card[j].irq = (int)cy_isa_irq;
4604 cy_card[j].bus_index = 0;
4605 cy_card[j].first_line = cy_next_channel;
4606 cy_card[j].num_chips = cy_isa_nchan / 4;
3137553d
JS
4607 if (cy_init_card(&cy_card[j])) {
4608 cy_card[j].base_addr = NULL;
4609 free_irq(cy_isa_irq, &cy_card[j]);
4610 iounmap(cy_isa_address);
4611 continue;
4612 }
02f1175c
JS
4613 nboard++;
4614
21719191
JS
4615 printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: "
4616 "%d channels starting from port %d\n",
02f1175c
JS
4617 j + 1, (unsigned long)cy_isa_address,
4618 (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
21719191
JS
4619 cy_isa_irq, cy_isa_nchan, cy_next_channel);
4620
6ad1ccc1
JS
4621 for (j = cy_next_channel;
4622 j < cy_next_channel + cy_isa_nchan; j++)
4623 tty_register_device(cy_serial_driver, j, NULL);
02f1175c
JS
4624 cy_next_channel += cy_isa_nchan;
4625 }
096dcfce 4626 return nboard;
1da177e4 4627#else
096dcfce 4628 return 0;
02f1175c
JS
4629#endif /* CONFIG_ISA */
4630} /* cy_detect_isa */
1da177e4 4631
58936d8d 4632#ifdef CONFIG_PCI
054f5b0a
JS
4633static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
4634{
4635 unsigned int a;
4636
4637 for (a = 0; a < size && *str; a++, str++)
4638 if (*str & 0x80)
4639 return -EINVAL;
4640
4641 for (; a < size; a++, str++)
4642 if (*str)
4643 return -EINVAL;
4644
4645 return 0;
4646}
4647
f61e761e 4648static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
054f5b0a
JS
4649 unsigned int size)
4650{
4651 for (; size > 0; size--) {
4652 cy_writel(fpga, *data++);
4653 udelay(10);
4654 }
4655}
4656
4657static void __devinit plx_init(struct pci_dev *pdev, int irq,
4658 struct RUNTIME_9060 __iomem *addr)
1da177e4 4659{
02f1175c 4660 /* Reset PLX */
054f5b0a 4661 cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
02f1175c 4662 udelay(100L);
054f5b0a 4663 cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
02f1175c
JS
4664
4665 /* Reload Config. Registers from EEPROM */
054f5b0a 4666 cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
02f1175c 4667 udelay(100L);
054f5b0a
JS
4668 cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
4669
4670 /* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
4671 * the IRQ is lost and, thus, we have to re-write it to the PCI config.
4672 * registers. This will remain here until we find a permanent fix.
4673 */
4674 pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
4675}
4676
4677static int __devinit __cyz_load_fw(const struct firmware *fw,
4678 const char *name, const u32 mailbox, void __iomem *base,
4679 void __iomem *fpga)
4680{
f61e761e
DW
4681 const void *ptr = fw->data;
4682 const struct zfile_header *h = ptr;
4683 const struct zfile_config *c, *cs;
4684 const struct zfile_block *b, *bs;
054f5b0a
JS
4685 unsigned int a, tmp, len = fw->size;
4686#define BAD_FW KERN_ERR "Bad firmware: "
4687 if (len < sizeof(*h)) {
4688 printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
4689 return -EINVAL;
4690 }
4691
4692 cs = ptr + h->config_offset;
4693 bs = ptr + h->block_offset;
4694
4695 if ((void *)(cs + h->n_config) > ptr + len ||
4696 (void *)(bs + h->n_blocks) > ptr + len) {
4697 printk(BAD_FW "too short");
4698 return -EINVAL;
4699 }
4700
4701 if (cyc_isfwstr(h->name, sizeof(h->name)) ||
4702 cyc_isfwstr(h->date, sizeof(h->date))) {
4703 printk(BAD_FW "bad formatted header string\n");
4704 return -EINVAL;
4705 }
4706
4707 if (strncmp(name, h->name, sizeof(h->name))) {
4708 printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
4709 return -EINVAL;
4710 }
4711
4712 tmp = 0;
4713 for (c = cs; c < cs + h->n_config; c++) {
4714 for (a = 0; a < c->n_blocks; a++)
4715 if (c->block_list[a] > h->n_blocks) {
4716 printk(BAD_FW "bad block ref number in cfgs\n");
4717 return -EINVAL;
4718 }
4719 if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
4720 tmp++;
4721 }
4722 if (!tmp) {
4723 printk(BAD_FW "nothing appropriate\n");
4724 return -EINVAL;
4725 }
4726
4727 for (b = bs; b < bs + h->n_blocks; b++)
4728 if (b->file_offset + b->size > len) {
4729 printk(BAD_FW "bad block data offset\n");
4730 return -EINVAL;
4731 }
4732
4733 /* everything is OK, let's seek'n'load it */
4734 for (c = cs; c < cs + h->n_config; c++)
4735 if (c->mailbox == mailbox && c->function == 0)
4736 break;
4737
4738 for (a = 0; a < c->n_blocks; a++) {
4739 b = &bs[c->block_list[a]];
4740 if (b->type == ZBLOCK_FPGA) {
4741 if (fpga != NULL)
4742 cyz_fpga_copy(fpga, ptr + b->file_offset,
4743 b->size);
4744 } else {
4745 if (base != NULL)
4746 memcpy_toio(base + b->ram_offset,
4747 ptr + b->file_offset, b->size);
4748 }
4749 }
4750#undef BAD_FW
4751 return 0;
4752}
4753
4754static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
4755 struct RUNTIME_9060 __iomem *ctl_addr, int irq)
4756{
4757 const struct firmware *fw;
4758 struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
4759 struct CUSTOM_REG __iomem *cust = base_addr;
4760 struct ZFW_CTRL __iomem *pt_zfwctrl;
c4923b4f 4761 void __iomem *tmp;
054f5b0a
JS
4762 u32 mailbox, status;
4763 unsigned int i;
4764 int retval;
4765
4766 retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
4767 if (retval) {
4768 dev_err(&pdev->dev, "can't get firmware\n");
4769 goto err;
4770 }
4771
4772 /* Check whether the firmware is already loaded and running. If
4773 positive, skip this board */
4774 if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
4775 u32 cntval = readl(base_addr + 0x190);
4776
4777 udelay(100);
4778 if (cntval != readl(base_addr + 0x190)) {
4779 /* FW counter is working, FW is running */
4780 dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
4781 "Skipping board.\n");
4782 retval = 0;
4783 goto err_rel;
4784 }
4785 }
4786
4787 /* start boot */
4788 cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
4789 ~0x00030800UL);
4790
4791 mailbox = readl(&ctl_addr->mail_box_0);
4792
4793 if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) {
4794 /* stops CPU and set window to beginning of RAM */
4795 cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
4796 cy_writel(&cust->cpu_stop, 0);
4797 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
4798 udelay(100);
4799 }
4800
4801 plx_init(pdev, irq, ctl_addr);
4802
4803 if (mailbox != 0) {
4804 /* load FPGA */
4805 retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
4806 base_addr);
4807 if (retval)
4808 goto err_rel;
4809 if (!Z_FPGA_LOADED(ctl_addr)) {
4810 dev_err(&pdev->dev, "fw upload successful, but fw is "
4811 "not loaded\n");
4812 goto err_rel;
4813 }
4814 }
4815
4816 /* stops CPU and set window to beginning of RAM */
4817 cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
4818 cy_writel(&cust->cpu_stop, 0);
4819 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
4820 udelay(100);
4821
4822 /* clear memory */
c4923b4f 4823 for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
054f5b0a
JS
4824 cy_writeb(tmp, 255);
4825 if (mailbox != 0) {
4826 /* set window to last 512K of RAM */
4827 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
c4923b4f 4828 for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
054f5b0a
JS
4829 cy_writeb(tmp, 255);
4830 /* set window to beginning of RAM */
4831 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
054f5b0a
JS
4832 }
4833
4834 retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
4835 release_firmware(fw);
4836 if (retval)
4837 goto err;
4838
4839 /* finish boot and start boards */
4840 cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
4841 cy_writel(&cust->cpu_start, 0);
4842 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
4843 i = 0;
4844 while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
4845 msleep(100);
4846 if (status != ZFIRM_ID) {
4847 if (status == ZFIRM_HLT) {
4848 dev_err(&pdev->dev, "you need an external power supply "
4849 "for this number of ports. Firmware halted and "
4850 "board reset.\n");
4851 retval = -EIO;
4852 goto err;
4853 }
4854 dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
4855 "some more time\n", status);
4856 while ((status = readl(&fid->signature)) != ZFIRM_ID &&
4857 i++ < 200)
4858 msleep(100);
4859 if (status != ZFIRM_ID) {
4860 dev_err(&pdev->dev, "Board not started in 20 seconds! "
4861 "Giving up. (fid->signature = 0x%x)\n",
4862 status);
4863 dev_info(&pdev->dev, "*** Warning ***: if you are "
4864 "upgrading the FW, please power cycle the "
4865 "system before loading the new FW to the "
4866 "Cyclades-Z.\n");
4867
4868 if (Z_FPGA_LOADED(ctl_addr))
4869 plx_init(pdev, irq, ctl_addr);
4870
4871 retval = -EIO;
4872 goto err;
4873 }
4874 dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
4875 i / 10);
4876 }
4877 pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
4878
4879 dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
4880 base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
4881 base_addr + readl(&fid->zfwctrl_addr));
4882
4883 dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
4884 readl(&pt_zfwctrl->board_ctrl.fw_version),
4885 readl(&pt_zfwctrl->board_ctrl.n_channel));
4886
4887 if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) {
4888 dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
4889 "check the connection between the Z host card and the "
4890 "serial expanders.\n");
4891
4892 if (Z_FPGA_LOADED(ctl_addr))
4893 plx_init(pdev, irq, ctl_addr);
4894
4895 dev_info(&pdev->dev, "Null number of ports detected. Board "
4896 "reset.\n");
4897 retval = 0;
4898 goto err;
4899 }
4900
4901 cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
4902 cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
4903
4904 /*
4905 Early firmware failed to start looking for commands.
4906 This enables firmware interrupts for those commands.
4907 */
4908 cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
4909 (1 << 17));
4910 cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
4911 0x00030800UL);
4912
054f5b0a
JS
4913 return 0;
4914err_rel:
4915 release_firmware(fw);
4916err:
4917 return retval;
1da177e4
LT
4918}
4919
58936d8d
JS
4920static int __devinit cy_pci_probe(struct pci_dev *pdev,
4921 const struct pci_device_id *ent)
1da177e4 4922{
3137553d
JS
4923 void __iomem *addr0 = NULL, *addr2 = NULL;
4924 char *card_name = NULL;
101b8159 4925 u32 uninitialized_var(mailbox);
3137553d
JS
4926 unsigned int device_id, nchan = 0, card_no, i;
4927 unsigned char plx_ver;
4928 int retval, irq;
02f1175c 4929
58936d8d
JS
4930 retval = pci_enable_device(pdev);
4931 if (retval) {
4932 dev_err(&pdev->dev, "cannot enable device\n");
3137553d 4933 goto err;
58936d8d 4934 }
1da177e4 4935
58936d8d 4936 /* read PCI configuration area */
3137553d 4937 irq = pdev->irq;
58936d8d 4938 device_id = pdev->device & ~PCI_DEVICE_ID_MASK;
1da177e4 4939
3137553d
JS
4940#if defined(__alpha__)
4941 if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
4942 dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low "
4943 "addresses on Alpha systems.\n");
4944 retval = -EIO;
4945 goto err_dis;
4946 }
4947#endif
4948 if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
4949 dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low "
4950 "addresses\n");
4951 retval = -EIO;
4952 goto err_dis;
4953 }
4954
4955 if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
4956 dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring "
4957 "it...\n");
4958 pdev->resource[2].flags &= ~IORESOURCE_IO;
4959 }
4960
4961 retval = pci_request_regions(pdev, "cyclades");
4962 if (retval) {
4963 dev_err(&pdev->dev, "failed to reserve resources\n");
4964 goto err_dis;
4965 }
4966
4967 retval = -EIO;
58936d8d
JS
4968 if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
4969 device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
3137553d 4970 card_name = "Cyclom-Y";
1da177e4 4971
24e6fd4c
JS
4972 addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
4973 CyPCI_Yctl);
3137553d
JS
4974 if (addr0 == NULL) {
4975 dev_err(&pdev->dev, "can't remap ctl region\n");
4976 goto err_reg;
58936d8d 4977 }
24e6fd4c
JS
4978 addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
4979 CyPCI_Ywin);
3137553d
JS
4980 if (addr2 == NULL) {
4981 dev_err(&pdev->dev, "can't remap base region\n");
4982 goto err_unmap;
58936d8d 4983 }
1da177e4 4984
3137553d
JS
4985 nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1);
4986 if (nchan == 0) {
21719191
JS
4987 dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
4988 "Serial-Modules\n");
c847d47c 4989 goto err_unmap;
58936d8d 4990 }
58936d8d 4991 } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
3137553d 4992 struct RUNTIME_9060 __iomem *ctl_addr;
21719191 4993
24e6fd4c
JS
4994 ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
4995 CyPCI_Zctl);
3137553d
JS
4996 if (addr0 == NULL) {
4997 dev_err(&pdev->dev, "can't remap ctl region\n");
4998 goto err_reg;
4999 }
58936d8d
JS
5000
5001 /* Disable interrupts on the PLX before resetting it */
97e87f8e
JS
5002 cy_writew(&ctl_addr->intr_ctrl_stat,
5003 readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
58936d8d 5004
054f5b0a 5005 plx_init(pdev, irq, addr0);
02f1175c 5006
101b8159 5007 mailbox = readl(&ctl_addr->mail_box_0);
58936d8d 5008
24e6fd4c
JS
5009 addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
5010 mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
3137553d
JS
5011 if (addr2 == NULL) {
5012 dev_err(&pdev->dev, "can't remap base region\n");
5013 goto err_unmap;
58936d8d
JS
5014 }
5015
5016 if (mailbox == ZE_V1) {
3137553d
JS
5017 card_name = "Cyclades-Ze";
5018
3137553d 5019 nchan = ZE_V1_NPORTS;
58936d8d 5020 } else {
3137553d 5021 card_name = "Cyclades-8Zo";
ace08c3c 5022 nchan = 8;
1da177e4
LT
5023
5024#ifdef CY_PCI_DEBUG
3137553d
JS
5025 if (mailbox == ZO_V1) {
5026 cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
5027 dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA "
5028 "id %lx, ver %lx\n", (ulong)(0xff &
5029 readl(&((struct CUSTOM_REG *)addr2)->
5030 fpga_id)), (ulong)(0xff &
5031 readl(&((struct CUSTOM_REG *)addr2)->
5032 fpga_version)));
5033 cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
5034 } else {
5035 dev_info(&pdev->dev, "Cyclades-Z/PCI: New "
5036 "Cyclades-Z board. FPGA not loaded\n");
5037 }
1da177e4 5038#endif
3137553d
JS
5039 /* The following clears the firmware id word. This
5040 ensures that the driver will not attempt to talk to
5041 the board until it has been properly initialized.
5042 */
5043 if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
5044 cy_writel(addr2 + ID_ADDRESS, 0L);
58936d8d 5045 }
ace08c3c
JS
5046
5047 retval = cyz_load_fw(pdev, addr2, addr0, irq);
5048 if (retval)
5049 goto err_unmap;
3137553d
JS
5050 }
5051
5052 if ((cy_next_channel + nchan) > NR_PORTS) {
5053 dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
5054 "channels are available. Change NR_PORTS in "
5055 "cyclades.c and recompile kernel.\n");
5056 goto err_unmap;
5057 }
5058 /* fill the next cy_card structure available */
5059 for (card_no = 0; card_no < NR_CARDS; card_no++) {
5060 if (cy_card[card_no].base_addr == NULL)
5061 break;
5062 }
5063 if (card_no == NR_CARDS) { /* no more cy_cards available */
5064 dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
5065 "more cards can be used. Change NR_CARDS in "
5066 "cyclades.c and recompile kernel.\n");
5067 goto err_unmap;
5068 }
5069
5070 if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
5071 device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
5072 /* allocate IRQ */
5073 retval = request_irq(irq, cyy_interrupt,
5074 IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
5075 if (retval) {
5076 dev_err(&pdev->dev, "could not allocate IRQ\n");
5077 goto err_unmap;
58936d8d 5078 }
3137553d
JS
5079 cy_card[card_no].num_chips = nchan / 4;
5080 } else {
101b8159
JS
5081 cy_card[card_no].hw_ver = mailbox;
5082 cy_card[card_no].num_chips = (unsigned int)-1;
02f1175c 5083#ifdef CONFIG_CYZ_INTR
58936d8d 5084 /* allocate IRQ only if board has an IRQ */
3137553d
JS
5085 if (irq != 0 && irq != 255) {
5086 retval = request_irq(irq, cyz_interrupt,
58936d8d 5087 IRQF_SHARED, "Cyclades-Z",
3137553d 5088 &cy_card[card_no]);
58936d8d 5089 if (retval) {
21719191 5090 dev_err(&pdev->dev, "could not allocate IRQ\n");
3137553d 5091 goto err_unmap;
02f1175c 5092 }
58936d8d 5093 }
02f1175c 5094#endif /* CONFIG_CYZ_INTR */
3137553d 5095 }
02f1175c 5096
3137553d
JS
5097 /* set cy_card */
5098 cy_card[card_no].base_addr = addr2;
97e87f8e 5099 cy_card[card_no].ctl_addr.p9050 = addr0;
3137553d
JS
5100 cy_card[card_no].irq = irq;
5101 cy_card[card_no].bus_index = 1;
5102 cy_card[card_no].first_line = cy_next_channel;
5103 retval = cy_init_card(&cy_card[card_no]);
5104 if (retval)
5105 goto err_null;
58936d8d 5106
3137553d 5107 pci_set_drvdata(pdev, &cy_card[card_no]);
58936d8d 5108
3137553d
JS
5109 if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
5110 device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
5111 /* enable interrupts in the PCI interface */
5112 plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
5113 switch (plx_ver) {
5114 case PLX_9050:
3137553d
JS
5115 cy_writeb(addr0 + 0x4c, 0x43);
5116 break;
5117
5118 case PLX_9060:
5119 case PLX_9080:
5120 default: /* Old boards, use PLX_9060 */
97e87f8e
JS
5121 {
5122 struct RUNTIME_9060 __iomem *ctl_addr = addr0;
5123 plx_init(pdev, irq, ctl_addr);
5124 cy_writew(&ctl_addr->intr_ctrl_stat,
5125 readw(&ctl_addr->intr_ctrl_stat) | 0x0900);
3137553d
JS
5126 break;
5127 }
97e87f8e 5128 }
58936d8d
JS
5129 }
5130
3137553d
JS
5131 dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
5132 "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
5133 for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
5134 tty_register_device(cy_serial_driver, i, &pdev->dev);
5135 cy_next_channel += nchan;
5136
58936d8d 5137 return 0;
3137553d
JS
5138err_null:
5139 cy_card[card_no].base_addr = NULL;
5140 free_irq(irq, &cy_card[card_no]);
5141err_unmap:
24e6fd4c 5142 iounmap(addr0);
3137553d 5143 if (addr2)
24e6fd4c 5144 iounmap(addr2);
3137553d
JS
5145err_reg:
5146 pci_release_regions(pdev);
5147err_dis:
5148 pci_disable_device(pdev);
5149err:
5150 return retval;
58936d8d 5151}
58936d8d 5152
6747cd93 5153static void __devexit cy_pci_remove(struct pci_dev *pdev)
58936d8d 5154{
38d09093 5155 struct cyclades_card *cinfo = pci_get_drvdata(pdev);
f3851e73 5156 unsigned int i;
38d09093 5157
85c93fa9 5158 /* non-Z with old PLX */
c2ad4c75
JS
5159 if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
5160 PLX_9050)
97e87f8e 5161 cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
85c93fa9
JS
5162 else
5163#ifndef CONFIG_CYZ_INTR
c2ad4c75 5164 if (!IS_CYC_Z(*cinfo))
85c93fa9 5165#endif
97e87f8e
JS
5166 cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat,
5167 readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) &
5168 ~0x0900);
85c93fa9 5169
24e6fd4c 5170 iounmap(cinfo->base_addr);
97e87f8e
JS
5171 if (cinfo->ctl_addr.p9050)
5172 iounmap(cinfo->ctl_addr.p9050);
38d09093
JS
5173 if (cinfo->irq
5174#ifndef CONFIG_CYZ_INTR
c2ad4c75 5175 && !IS_CYC_Z(*cinfo)
38d09093
JS
5176#endif /* CONFIG_CYZ_INTR */
5177 )
5178 free_irq(cinfo->irq, cinfo);
5179 pci_release_regions(pdev);
5180
5181 cinfo->base_addr = NULL;
6ad1ccc1
JS
5182 for (i = cinfo->first_line; i < cinfo->first_line +
5183 cinfo->nports; i++)
5184 tty_unregister_device(cy_serial_driver, i);
dd025c0c
JS
5185 cinfo->nports = 0;
5186 kfree(cinfo->ports);
38d09093
JS
5187}
5188
6747cd93
JS
5189static struct pci_driver cy_pci_driver = {
5190 .name = "cyclades",
5191 .id_table = cy_pci_dev_id,
5192 .probe = cy_pci_probe,
5193 .remove = __devexit_p(cy_pci_remove)
5194};
5195#endif
5196
444697d6 5197static int cyclades_proc_show(struct seq_file *m, void *v)
1da177e4 5198{
02f1175c 5199 struct cyclades_port *info;
dd025c0c 5200 unsigned int i, j;
02f1175c
JS
5201 __u32 cur_jifs = jiffies;
5202
444697d6 5203 seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn "
02f1175c
JS
5204 "IdleIn Overruns Ldisc\n");
5205
02f1175c 5206 /* Output one line for each known port */
dd025c0c
JS
5207 for (i = 0; i < NR_CARDS; i++)
5208 for (j = 0; j < cy_card[i].nports; j++) {
5209 info = &cy_card[i].ports[j];
5210
77451e53 5211 if (info->port.count)
444697d6 5212 seq_printf(m, "%3d %8lu %10lu %8lu "
dd025c0c
JS
5213 "%10lu %8lu %9lu %6ld\n", info->line,
5214 (cur_jifs - info->idle_stats.in_use) /
5215 HZ, info->idle_stats.xmit_bytes,
5216 (cur_jifs - info->idle_stats.xmit_idle)/
5217 HZ, info->idle_stats.recv_bytes,
5218 (cur_jifs - info->idle_stats.recv_idle)/
5219 HZ, info->idle_stats.overruns,
a352def2 5220 /* FIXME: double check locking */
77451e53 5221 (long)info->port.tty->ldisc.ops->num);
dd025c0c 5222 else
444697d6 5223 seq_printf(m, "%3d %8lu %10lu %8lu "
dd025c0c
JS
5224 "%10lu %8lu %9lu %6ld\n",
5225 info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
02f1175c 5226 }
444697d6
AD
5227 return 0;
5228}
5229
5230static int cyclades_proc_open(struct inode *inode, struct file *file)
5231{
5232 return single_open(file, cyclades_proc_show, NULL);
1da177e4
LT
5233}
5234
444697d6
AD
5235static const struct file_operations cyclades_proc_fops = {
5236 .owner = THIS_MODULE,
5237 .open = cyclades_proc_open,
5238 .read = seq_read,
5239 .llseek = seq_lseek,
5240 .release = single_release,
5241};
5242
1da177e4
LT
5243/* The serial driver boot-time initialization code!
5244 Hardware I/O ports are mapped to character special devices on a
5245 first found, first allocated manner. That is, this code searches
5246 for Cyclom cards in the system. As each is found, it is probed
5247 to discover how many chips (and thus how many ports) are present.
5248 These ports are mapped to the tty ports 32 and upward in monotonic
5249 fashion. If an 8-port card is replaced with a 16-port card, the
5250 port mapping on a following card will shift.
5251
5252 This approach is different from what is used in the other serial
5253 device driver because the Cyclom is more properly a multiplexer,
5254 not just an aggregation of serial ports on one card.
5255
5256 If there are more cards with more ports than have been
5257 statically allocated above, a warning is printed and the
5258 extra ports are ignored.
5259 */
5260
b68e31d0 5261static const struct tty_operations cy_ops = {
02f1175c
JS
5262 .open = cy_open,
5263 .close = cy_close,
5264 .write = cy_write,
5265 .put_char = cy_put_char,
5266 .flush_chars = cy_flush_chars,
5267 .write_room = cy_write_room,
5268 .chars_in_buffer = cy_chars_in_buffer,
5269 .flush_buffer = cy_flush_buffer,
5270 .ioctl = cy_ioctl,
5271 .throttle = cy_throttle,
5272 .unthrottle = cy_unthrottle,
5273 .set_termios = cy_set_termios,
5274 .stop = cy_stop,
5275 .start = cy_start,
5276 .hangup = cy_hangup,
5277 .break_ctl = cy_break,
5278 .wait_until_sent = cy_wait_until_sent,
02f1175c
JS
5279 .tiocmget = cy_tiocmget,
5280 .tiocmset = cy_tiocmset,
444697d6 5281 .proc_fops = &cyclades_proc_fops,
1da177e4
LT
5282};
5283
02f1175c 5284static int __init cy_init(void)
1da177e4 5285{
dd025c0c 5286 unsigned int nboards;
9dacf3b2 5287 int retval = -ENOMEM;
02f1175c
JS
5288
5289 cy_serial_driver = alloc_tty_driver(NR_PORTS);
5290 if (!cy_serial_driver)
9dacf3b2 5291 goto err;
21719191
JS
5292
5293 printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n",
5294 __DATE__, __TIME__);
02f1175c
JS
5295
5296 /* Initialize the tty_driver structure */
5297
5298 cy_serial_driver->owner = THIS_MODULE;
5299 cy_serial_driver->driver_name = "cyclades";
5300 cy_serial_driver->name = "ttyC";
5301 cy_serial_driver->major = CYCLADES_MAJOR;
5302 cy_serial_driver->minor_start = 0;
5303 cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
5304 cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
5305 cy_serial_driver->init_termios = tty_std_termios;
5306 cy_serial_driver->init_termios.c_cflag =
5307 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
6ad1ccc1 5308 cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
02f1175c
JS
5309 tty_set_operations(cy_serial_driver, &cy_ops);
5310
9dacf3b2
JS
5311 retval = tty_register_driver(cy_serial_driver);
5312 if (retval) {
5313 printk(KERN_ERR "Couldn't register Cyclades serial driver\n");
5314 goto err_frtty;
5315 }
02f1175c 5316
02f1175c
JS
5317 /* the code below is responsible to find the boards. Each different
5318 type of board has its own detection routine. If a board is found,
5319 the next cy_card structure available is set by the detection
5320 routine. These functions are responsible for checking the
5321 availability of cy_card and cy_port data structures and updating
5322 the cy_next_channel. */
5323
5324 /* look for isa boards */
14a55a67 5325 nboards = cy_detect_isa();
02f1175c 5326
6747cd93 5327#ifdef CONFIG_PCI
02f1175c 5328 /* look for pci boards */
6747cd93 5329 retval = pci_register_driver(&cy_pci_driver);
d941ea7d
JJ
5330 if (retval && !nboards) {
5331 tty_unregister_driver(cy_serial_driver);
5332 goto err_frtty;
5333 }
6747cd93 5334#endif
9dacf3b2
JS
5335
5336 return 0;
9dacf3b2
JS
5337err_frtty:
5338 put_tty_driver(cy_serial_driver);
5339err:
5340 return retval;
02f1175c 5341} /* cy_init */
1da177e4 5342
02f1175c 5343static void __exit cy_cleanup_module(void)
1da177e4 5344{
dd025c0c 5345 struct cyclades_card *card;
65f76a82 5346 unsigned int i, e1;
1da177e4
LT
5347
5348#ifndef CONFIG_CYZ_INTR
b7050906 5349 del_timer_sync(&cyz_timerlist);
1da177e4
LT
5350#endif /* CONFIG_CYZ_INTR */
5351
15ed6cc0
AC
5352 e1 = tty_unregister_driver(cy_serial_driver);
5353 if (e1)
21719191
JS
5354 printk(KERN_ERR "failed to unregister Cyclades serial "
5355 "driver(%d)\n", e1);
1da177e4 5356
6747cd93
JS
5357#ifdef CONFIG_PCI
5358 pci_unregister_driver(&cy_pci_driver);
5359#endif
5360
02f1175c 5361 for (i = 0; i < NR_CARDS; i++) {
dd025c0c
JS
5362 card = &cy_card[i];
5363 if (card->base_addr) {
85c93fa9 5364 /* clear interrupt */
dd025c0c
JS
5365 cy_writeb(card->base_addr + Cy_ClrIntr, 0);
5366 iounmap(card->base_addr);
97e87f8e
JS
5367 if (card->ctl_addr.p9050)
5368 iounmap(card->ctl_addr.p9050);
dd025c0c 5369 if (card->irq
1da177e4 5370#ifndef CONFIG_CYZ_INTR
dd025c0c 5371 && !IS_CYC_Z(*card)
1da177e4 5372#endif /* CONFIG_CYZ_INTR */
02f1175c 5373 )
dd025c0c 5374 free_irq(card->irq, card);
65f76a82 5375 for (e1 = card->first_line; e1 < card->first_line +
dd025c0c 5376 card->nports; e1++)
6ad1ccc1 5377 tty_unregister_device(cy_serial_driver, e1);
dd025c0c 5378 kfree(card->ports);
02f1175c
JS
5379 }
5380 }
f2462bfe
JS
5381
5382 put_tty_driver(cy_serial_driver);
1da177e4
LT
5383} /* cy_cleanup_module */
5384
5385module_init(cy_init);
5386module_exit(cy_cleanup_module);
5387
5388MODULE_LICENSE("GPL");
c8e1693a 5389MODULE_VERSION(CY_VERSION);
9f56fad7 5390MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
This page took 1.254102 seconds and 5 git commands to generate.