blob: e53f16865397c491fa4afac65988c49b0f391ff9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* sx.c -- driver for the Specialix SX series cards.
2 *
3 * This driver will also support the older SI, and XIO cards.
4 *
5 *
6 * (C) 1998 - 2004 R.E.Wolff@BitWizard.nl
7 *
8 * Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
9 * version of this driver. Some fragments may have been copied. (none
10 * yet :-)
11 *
12 * Specialix pays for the development and support of this driver.
13 * Please DO contact support@specialix.co.uk if you require
14 * support. But please read the documentation (sx.txt) first.
15 *
16 *
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License as
20 * published by the Free Software Foundation; either version 2 of
21 * the License, or (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be
24 * useful, but WITHOUT ANY WARRANTY; without even the implied
25 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
26 * PURPOSE. See the GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public
29 * License along with this program; if not, write to the Free
30 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
31 * USA.
32 *
33 * Revision history:
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff
35 * - Fixed module and port counting
36 * - Fixed signal handling
37 * - Fixed an Ooops
38 *
39 * Revision 1.32 2000/03/07 09:00:00 wolff,pvdl
40 * - Fixed some sx_dprintk typos
41 * - added detection for an invalid board/module configuration
42 *
43 * Revision 1.31 2000/03/06 12:00:00 wolff,pvdl
44 * - Added support for EISA
45 *
46 * Revision 1.30 2000/01/21 17:43:06 wolff
47 * - Added support for SX+
48 *
49 * Revision 1.26 1999/08/05 15:22:14 wolff
50 * - Port to 2.3.x
51 * - Reformatted to Linus' liking.
52 *
53 * Revision 1.25 1999/07/30 14:24:08 wolff
54 * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0).
55 *
56 * Revision 1.24 1999/07/28 09:41:52 wolff
57 * - I noticed the remark about use-count straying in sx.txt. I checked
58 * sx_open, and found a few places where that could happen. I hope it's
59 * fixed now.
60 *
61 * Revision 1.23 1999/07/28 08:56:06 wolff
62 * - Fixed crash when sx_firmware run twice.
63 * - Added sx_slowpoll as a module parameter (I guess nobody really wanted
64 * to change it from the default... )
65 * - Fixed a stupid editing problem I introduced in 1.22.
66 * - Fixed dropping characters on a termios change.
67 *
68 * Revision 1.22 1999/07/26 21:01:43 wolff
69 * Russell Brown noticed that I had overlooked 4 out of six modem control
70 * signals in sx_getsignals. Ooops.
71 *
72 * Revision 1.21 1999/07/23 09:11:33 wolff
73 * I forgot to free dynamically allocated memory when the driver is unloaded.
74 *
75 * Revision 1.20 1999/07/20 06:25:26 wolff
76 * The "closing wait" wasn't honoured. Thanks to James Griffiths for
77 * reporting this.
78 *
79 * Revision 1.19 1999/07/11 08:59:59 wolff
80 * Fixed an oops in close, when an open was pending. Changed the memtest
81 * a bit. Should also test the board in word-mode, however my card fails the
82 * memtest then. I still have to figure out what is wrong...
83 *
84 * Revision 1.18 1999/06/10 09:38:42 wolff
85 * Changed the format of the firmware revision from %04x to %x.%02x .
86 *
87 * Revision 1.17 1999/06/04 09:44:35 wolff
88 * fixed problem: reference to pci stuff when config_pci was off...
89 * Thanks to Jorge Novo for noticing this.
90 *
91 * Revision 1.16 1999/06/02 08:30:15 wolff
92 * added/removed the workaround for the DCD bug in the Firmware.
93 * A bit more debugging code to locate that...
94 *
95 * Revision 1.15 1999/06/01 11:35:30 wolff
96 * when DCD is left low (floating?), on TA's the firmware first tells us
97 * that DCD is high, but after a short while suddenly comes to the
98 * conclusion that it is low. All this would be fine, if it weren't that
99 * Unix requires us to send a "hangup" signal in that case. This usually
100 * all happens BEFORE the program has had a chance to ioctl the device
101 * into clocal mode..
102 *
103 * Revision 1.14 1999/05/25 11:18:59 wolff
104 * Added PCI-fix.
105 * Added checks for return code of sx_sendcommand.
106 * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...)
107 *
108 * Revision 1.13 1999/04/29 15:18:01 wolff
109 * Fixed an "oops" that showed on SuSE 6.0 systems.
110 * Activate DTR again after stty 0.
111 *
112 * Revision 1.12 1999/04/29 07:49:52 wolff
113 * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming
114 * the connection would be dropped anyway. That is not always the case,
115 * and confuses people).
116 * Told the card to always monitor the modem signals.
117 * Added support for dynamic gs_debug adjustments.
118 * Now tells the rest of the system the number of ports.
119 *
120 * Revision 1.11 1999/04/24 11:11:30 wolff
121 * Fixed two stupid typos in the memory test.
122 *
123 * Revision 1.10 1999/04/24 10:53:39 wolff
124 * Added some of Christian's suggestions.
125 * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the
126 * card to send the signal to the process.....)
127 *
128 * Revision 1.9 1999/04/23 07:26:38 wolff
129 * Included Christian Lademann's 2.0 compile-warning fixes and interrupt
130 * assignment redesign.
131 * Cleanup of some other stuff.
132 *
133 * Revision 1.8 1999/04/16 13:05:30 wolff
134 * fixed a DCD change unnoticed bug.
135 *
136 * Revision 1.7 1999/04/14 22:19:51 wolff
137 * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!)
138 *
139 * Revision 1.6 1999/04/13 18:40:20 wolff
140 * changed misc-minor to 161, as assigned by HPA.
141 *
142 * Revision 1.5 1999/04/13 15:12:25 wolff
143 * Fixed use-count leak when "hangup" occurred.
144 * Added workaround for a stupid-PCIBIOS bug.
145 *
146 *
147 * Revision 1.4 1999/04/01 22:47:40 wolff
148 * Fixed < 1M linux-2.0 problem.
149 * (vremap isn't compatible with ioremap in that case)
150 *
151 * Revision 1.3 1999/03/31 13:45:45 wolff
152 * Firmware loading is now done through a separate IOCTL.
153 *
154 * Revision 1.2 1999/03/28 12:22:29 wolff
155 * rcs cleanup
156 *
157 * Revision 1.1 1999/03/28 12:10:34 wolff
158 * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS).
159 *
160 * Revision 0.12 1999/03/28 09:20:10 wolff
161 * Fixed problem in 0.11, continueing cleanup.
162 *
163 * Revision 0.11 1999/03/28 08:46:44 wolff
164 * cleanup. Not good.
165 *
166 * Revision 0.10 1999/03/28 08:09:43 wolff
167 * Fixed loosing characters on close.
168 *
169 * Revision 0.9 1999/03/21 22:52:01 wolff
170 * Ported back to 2.2.... (minor things)
171 *
172 * Revision 0.8 1999/03/21 22:40:33 wolff
173 * Port to 2.0
174 *
175 * Revision 0.7 1999/03/21 19:06:34 wolff
176 * Fixed hangup processing.
177 *
178 * Revision 0.6 1999/02/05 08:45:14 wolff
179 * fixed real_raw problems. Inclusion into kernel imminent.
180 *
181 * Revision 0.5 1998/12/21 23:51:06 wolff
182 * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it
183 * shouldn't have. THATs why I want to have transmit interrupts even when
184 * the buffer is empty.
185 *
186 * Revision 0.4 1998/12/17 09:34:46 wolff
187 * PPP works. ioctl works. Basically works!
188 *
189 * Revision 0.3 1998/12/15 13:05:18 wolff
190 * It works! Wow! Gotta start implementing IOCTL and stuff....
191 *
192 * Revision 0.2 1998/12/01 08:33:53 wolff
193 * moved over to 2.1.130
194 *
195 * Revision 0.1 1998/11/03 21:23:51 wolff
196 * Initial revision. Detects SX card.
197 *
198 * */
199
Jiri Slaby11c83872006-12-08 02:38:56 -0800200#define SX_VERSION 1.33
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203#include <linux/kdev_t.h>
204#include <linux/kernel.h>
205#include <linux/sched.h>
206#include <linux/ioport.h>
207#include <linux/interrupt.h>
208#include <linux/errno.h>
209#include <linux/tty.h>
210#include <linux/tty_flip.h>
211#include <linux/mm.h>
212#include <linux/serial.h>
213#include <linux/fcntl.h>
214#include <linux/major.h>
215#include <linux/delay.h>
Jiri Slaby18f813e2006-12-08 02:39:01 -0800216#include <linux/eisa.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217#include <linux/pci.h>
218#include <linux/slab.h>
Alexey Dobriyan405f5572009-07-11 22:08:37 +0400219#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220#include <linux/init.h>
221#include <linux/miscdevice.h>
222#include <linux/bitops.h>
223
224#include <asm/io.h>
225#include <asm/uaccess.h>
226
227/* The 3.0.0 version of sxboards/sxwindow.h uses BYTE and WORD.... */
228#define BYTE u8
229#define WORD u16
230
231/* .... but the 3.0.4 version uses _u8 and _u16. */
232#define _u8 u8
233#define _u16 u16
234
235#include "sxboards.h"
236#include "sxwindow.h"
237
238#include <linux/generic_serial.h>
239#include "sx.h"
240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241/* I don't think that this driver can handle more than 256 ports on
242 one machine. You'll have to increase the number of boards in sx.h
243 if you want more than 4 boards. */
244
245#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
246#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
247#endif
248
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249/* Configurable options:
250 (Don't be too sure that it'll work if you toggle them) */
251
252/* Am I paranoid or not ? ;-) */
253#undef SX_PARANOIA_CHECK
254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
256 Hz, but it is user configurable. I don't recommend going above 1000
257 Hz. The interrupt ratelimit might trigger if the interrupt is
258 shared with a very active other device. */
259#define IRQ_RATE_LIMIT 20
260
261/* Sharing interrupts is possible now. If the other device wants more
262 than 2000 interrupts per second, we'd gracefully decline further
263 interrupts. That's not what we want. On the other hand, if the
264 other device interrupts 2000 times a second, don't use the SX
265 interrupt. Use polling. */
266#undef IRQ_RATE_LIMIT
267
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268#if 0
269/* Not implemented */
270/*
271 * The following defines are mostly for testing purposes. But if you need
272 * some nice reporting in your syslog, you can define them also.
273 */
274#define SX_REPORT_FIFO
275#define SX_REPORT_OVERRUN
Jiri Slaby15b611f2006-12-08 02:39:04 -0800276#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
278/* Function prototypes */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800279static void sx_disable_tx_interrupts(void *ptr);
280static void sx_enable_tx_interrupts(void *ptr);
281static void sx_disable_rx_interrupts(void *ptr);
282static void sx_enable_rx_interrupts(void *ptr);
Alan Cox31f35932009-01-02 13:45:05 +0000283static int sx_carrier_raised(struct tty_port *port);
Jiri Slaby15b611f2006-12-08 02:39:04 -0800284static void sx_shutdown_port(void *ptr);
285static int sx_set_real_termios(void *ptr);
286static void sx_close(void *ptr);
287static int sx_chars_in_buffer(void *ptr);
288static int sx_init_board(struct sx_board *board);
289static int sx_init_portstructs(int nboards, int nports);
Alan Cox11af7472008-07-25 01:48:15 -0700290static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
291 unsigned long arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292static int sx_init_drivers(void);
293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294static struct tty_driver *sx_driver;
295
Jiri Slaby42f63842006-12-08 02:39:03 -0800296static DEFINE_MUTEX(sx_boards_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297static struct sx_board boards[SX_NBOARDS];
298static struct sx_port *sx_ports;
299static int sx_initialized;
300static int sx_nports;
301static int sx_debug;
302
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303/* You can have the driver poll your card.
304 - Set sx_poll to 1 to poll every timer tick (10ms on Intel).
305 This is used when the card cannot use an interrupt for some reason.
306
307 - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If
308 the driver misses an interrupt (report this if it DOES happen to you!)
309 everything will continue to work....
310 */
311static int sx_poll = 1;
312static int sx_slowpoll;
313
314/* The card limits the number of interrupts per second.
315 At 115k2 "100" should be sufficient.
316 If you're using higher baudrates, you can increase this...
317 */
318
319static int sx_maxints = 100;
320
Jiri Slaby927a6f92006-12-08 02:39:02 -0800321#ifdef CONFIG_ISA
322
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323/* These are the only open spaces in my computer. Yours may have more
324 or less.... -- REW
325 duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
326*/
Jiri Slaby15b611f2006-12-08 02:39:04 -0800327static int sx_probe_addrs[] = {
328 0xc0000, 0xd0000, 0xe0000,
329 0xc8000, 0xd8000, 0xe8000
330};
331static int si_probe_addrs[] = {
332 0xc0000, 0xd0000, 0xe0000,
333 0xc8000, 0xd8000, 0xe8000, 0xa0000
334};
335static int si1_probe_addrs[] = {
336 0xd0000
337};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Tobias Klauserfe971072006-01-09 20:54:02 -0800339#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
340#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
341#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
Jiri Slaby927a6f92006-12-08 02:39:02 -0800343module_param_array(sx_probe_addrs, int, NULL, 0);
344module_param_array(si_probe_addrs, int, NULL, 0);
345#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
347/* Set the mask to all-ones. This alas, only supports 32 interrupts.
348 Some architectures may need more. */
349static int sx_irqmask = -1;
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351module_param(sx_poll, int, 0);
352module_param(sx_slowpoll, int, 0);
353module_param(sx_maxints, int, 0);
354module_param(sx_debug, int, 0);
355module_param(sx_irqmask, int, 0);
356
357MODULE_LICENSE("GPL");
358
359static struct real_driver sx_real_driver = {
360 sx_disable_tx_interrupts,
361 sx_enable_tx_interrupts,
362 sx_disable_rx_interrupts,
363 sx_enable_rx_interrupts,
Jiri Slaby15b611f2006-12-08 02:39:04 -0800364 sx_shutdown_port,
365 sx_set_real_termios,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 sx_chars_in_buffer,
367 sx_close,
368};
369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370/*
371 This driver can spew a whole lot of debugging output at you. If you
372 need maximum performance, you should disable the DEBUG define. To
373 aid in debugging in the field, I'm leaving the compile-time debug
374 features enabled, and disable them "runtime". That allows me to
375 instruct people with problems to enable debugging without requiring
376 them to recompile...
377*/
378#define DEBUG
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380#ifdef DEBUG
Jiri Slaby15b611f2006-12-08 02:39:04 -0800381#define sx_dprintk(f, str...) if (sx_debug & f) printk (str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382#else
Jiri Slaby15b611f2006-12-08 02:39:04 -0800383#define sx_dprintk(f, str...) /* nothing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384#endif
385
Harvey Harrisonbf9d8922008-04-30 00:55:10 -0700386#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
387#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Jiri Slaby15b611f2006-12-08 02:39:04 -0800389#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
Harvey Harrisonbf9d8922008-04-30 00:55:10 -0700390 __func__, port->line)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
392/*
393 * Firmware loader driver specific routines
394 *
395 */
396
Arjan van de Ven62322d22006-07-03 00:24:21 -0700397static const struct file_operations sx_fw_fops = {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800398 .owner = THIS_MODULE,
Alan Cox11af7472008-07-25 01:48:15 -0700399 .unlocked_ioctl = sx_fw_ioctl,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200400 .llseek = noop_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401};
402
403static struct miscdevice sx_fw_device = {
404 SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
405};
406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407#ifdef SX_PARANOIA_CHECK
408
409/* This doesn't work. Who's paranoid around here? Not me! */
410
Jiri Slaby15b611f2006-12-08 02:39:04 -0800411static inline int sx_paranoia_check(struct sx_port const *port,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 char *name, const char *routine)
413{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800414 static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
415 "number for device %s in %s\n";
416 static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
417 "device %s in %s\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 if (!port) {
420 printk(badinfo, name, routine);
421 return 1;
422 }
423 if (port->magic != SX_MAGIC) {
424 printk(badmagic, name, routine);
425 return 1;
426 }
427
428 return 0;
429}
430#else
431#define sx_paranoia_check(a,b,c) 0
432#endif
433
434/* The timeouts. First try 30 times as fast as possible. Then give
435 the card some time to breathe between accesses. (Otherwise the
436 processor on the card might not be able to access its OWN bus... */
437
438#define TIMEOUT_1 30
439#define TIMEOUT_2 1000000
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441#ifdef DEBUG
442static void my_hd_io(void __iomem *p, int len)
443{
444 int i, j, ch;
445 unsigned char __iomem *addr = p;
446
Jiri Slaby15b611f2006-12-08 02:39:04 -0800447 for (i = 0; i < len; i += 16) {
448 printk("%p ", addr + i);
449 for (j = 0; j < 16; j++) {
450 printk("%02x %s", readb(addr + j + i),
451 (j == 7) ? " " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800453 for (j = 0; j < 16; j++) {
454 ch = readb(addr + j + i);
455 printk("%c", (ch < 0x20) ? '.' :
456 ((ch > 0x7f) ? '.' : ch));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800458 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 }
460}
461static void my_hd(void *p, int len)
462{
463 int i, j, ch;
464 unsigned char *addr = p;
465
Jiri Slaby15b611f2006-12-08 02:39:04 -0800466 for (i = 0; i < len; i += 16) {
467 printk("%p ", addr + i);
468 for (j = 0; j < 16; j++) {
469 printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800471 for (j = 0; j < 16; j++) {
472 ch = addr[j + i];
473 printk("%c", (ch < 0x20) ? '.' :
474 ((ch > 0x7f) ? '.' : ch));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800476 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 }
478}
479#endif
480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481/* This needs redoing for Alpha -- REW -- Done. */
482
Jiri Slaby15b611f2006-12-08 02:39:04 -0800483static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800485 writeb(byte, board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486}
487
Jiri Slaby15b611f2006-12-08 02:39:04 -0800488static inline u8 read_sx_byte(struct sx_board *board, int offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800490 return readb(board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491}
492
Jiri Slaby15b611f2006-12-08 02:39:04 -0800493static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800495 writew(word, board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496}
497
Jiri Slaby15b611f2006-12-08 02:39:04 -0800498static inline u16 read_sx_word(struct sx_board *board, int offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800500 return readw(board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501}
502
Jiri Slaby15b611f2006-12-08 02:39:04 -0800503static int sx_busy_wait_eq(struct sx_board *board,
504 int offset, int mask, int correctval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505{
506 int i;
507
Jiri Slaby15b611f2006-12-08 02:39:04 -0800508 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
Jiri Slaby15b611f2006-12-08 02:39:04 -0800510 for (i = 0; i < TIMEOUT_1; i++)
511 if ((read_sx_byte(board, offset) & mask) == correctval) {
512 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 return 1;
514 }
515
Jiri Slaby15b611f2006-12-08 02:39:04 -0800516 for (i = 0; i < TIMEOUT_2; i++) {
517 if ((read_sx_byte(board, offset) & mask) == correctval) {
518 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 return 1;
520 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800521 udelay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 }
523
Jiri Slaby15b611f2006-12-08 02:39:04 -0800524 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 return 0;
526}
527
Jiri Slaby15b611f2006-12-08 02:39:04 -0800528static int sx_busy_wait_neq(struct sx_board *board,
529 int offset, int mask, int badval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
531 int i;
532
Jiri Slaby15b611f2006-12-08 02:39:04 -0800533 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Jiri Slaby15b611f2006-12-08 02:39:04 -0800535 for (i = 0; i < TIMEOUT_1; i++)
536 if ((read_sx_byte(board, offset) & mask) != badval) {
537 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 return 1;
539 }
540
Jiri Slaby15b611f2006-12-08 02:39:04 -0800541 for (i = 0; i < TIMEOUT_2; i++) {
542 if ((read_sx_byte(board, offset) & mask) != badval) {
543 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 return 1;
545 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800546 udelay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 }
548
Jiri Slaby15b611f2006-12-08 02:39:04 -0800549 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 return 0;
551}
552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553/* 5.6.4 of 6210028 r2.3 */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800554static int sx_reset(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800556 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Jiri Slaby15b611f2006-12-08 02:39:04 -0800558 if (IS_SX_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
Jiri Slaby15b611f2006-12-08 02:39:04 -0800560 write_sx_byte(board, SX_CONFIG, 0);
561 write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Jiri Slaby15b611f2006-12-08 02:39:04 -0800563 if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
564 printk(KERN_INFO "sx: Card doesn't respond to "
565 "reset...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 return 0;
567 }
568 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800569 outb(board->irq << 4, board->eisa_base + 0xc02);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800571 write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 } else {
573 /* Gory details of the SI/ISA board */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800574 write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
575 write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
576 write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
577 write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
578 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
579 write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 }
581
Jiri Slaby15b611f2006-12-08 02:39:04 -0800582 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 return 1;
584}
585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586/* This doesn't work on machines where "NULL" isn't 0 */
587/* If you have one of those, someone will need to write
588 the equivalent of this, which will amount to about 3 lines. I don't
589 want to complicate this right now. -- REW
590 (See, I do write comments every now and then :-) */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800591#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Jiri Slaby15b611f2006-12-08 02:39:04 -0800593#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))
594#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem))
595#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
597#define sx_write_channel_byte(port, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800598 write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600#define sx_read_channel_byte(port, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800601 read_sx_byte (port->board, CHAN_OFFSET (port, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
603#define sx_write_channel_word(port, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800604 write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
606#define sx_read_channel_word(port, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800607 read_sx_word (port->board, CHAN_OFFSET (port, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
609#define sx_write_module_byte(board, addr, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800610 write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
612#define sx_read_module_byte(board, addr, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800613 read_sx_byte (board, MODU_OFFSET (board, addr, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
615#define sx_write_module_word(board, addr, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800616 write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
618#define sx_read_module_word(board, addr, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800619 read_sx_word (board, MODU_OFFSET (board, addr, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621#define sx_write_board_byte(board, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800622 write_sx_byte (board, BRD_OFFSET (board, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
624#define sx_read_board_byte(board, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800625 read_sx_byte (board, BRD_OFFSET (board, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627#define sx_write_board_word(board, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800628 write_sx_word (board, BRD_OFFSET (board, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630#define sx_read_board_word(board, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800631 read_sx_word (board, BRD_OFFSET (board, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Jiri Slaby15b611f2006-12-08 02:39:04 -0800633static int sx_start_board(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800635 if (IS_SX_BOARD(board)) {
636 write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 } else if (IS_EISA_BOARD(board)) {
638 write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
Jiri Slaby15b611f2006-12-08 02:39:04 -0800639 outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800641 write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
642 write_sx_byte(board, SI1_ISA_INTCL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 } else {
644 /* Don't bug me about the clear_set.
645 I haven't the foggiest idea what it's about -- REW */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800646 write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
647 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 }
649 return 1;
650}
651
652#define SX_IRQ_REG_VAL(board) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800653 ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
655/* Note. The SX register is write-only. Therefore, we have to enable the
656 bus too. This is a no-op, if you don't mess with this driver... */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800657static int sx_start_interrupts(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
659
660 /* Don't call this with board->irq == 0 */
661
662 if (IS_SX_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800663 write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
664 SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800666 inb(board->eisa_base + 0xc03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800668 write_sx_byte(board, SI1_ISA_INTCL, 0);
669 write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 } else {
671 switch (board->irq) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800672 case 11:
673 write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
674 break;
675 case 12:
676 write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
677 break;
678 case 15:
679 write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
680 break;
681 default:
682 printk(KERN_INFO "sx: SI/XIO card doesn't support "
683 "interrupt %d.\n", board->irq);
684 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800686 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 }
688
689 return 1;
690}
691
Jiri Slaby15b611f2006-12-08 02:39:04 -0800692static int sx_send_command(struct sx_port *port,
693 int command, int mask, int newstat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800695 func_enter2();
696 write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
697 func_exit();
698 return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
699 newstat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700}
701
Jiri Slaby15b611f2006-12-08 02:39:04 -0800702static char *mod_type_s(int module_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
704 switch (module_type) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800705 case TA4:
706 return "TA4";
707 case TA8:
708 return "TA8";
709 case TA4_ASIC:
710 return "TA4_ASIC";
711 case TA8_ASIC:
712 return "TA8_ASIC";
713 case MTA_CD1400:
714 return "MTA_CD1400";
715 case SXDC:
716 return "SXDC";
717 default:
718 return "Unknown/invalid";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 }
720}
721
Jiri Slaby15b611f2006-12-08 02:39:04 -0800722static char *pan_type_s(int pan_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723{
724 switch (pan_type) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800725 case MOD_RS232DB25:
726 return "MOD_RS232DB25";
727 case MOD_RS232RJ45:
728 return "MOD_RS232RJ45";
729 case MOD_RS422DB25:
730 return "MOD_RS422DB25";
731 case MOD_PARALLEL:
732 return "MOD_PARALLEL";
733 case MOD_2_RS232DB25:
734 return "MOD_2_RS232DB25";
735 case MOD_2_RS232RJ45:
736 return "MOD_2_RS232RJ45";
737 case MOD_2_RS422DB25:
738 return "MOD_2_RS422DB25";
739 case MOD_RS232DB25MALE:
740 return "MOD_RS232DB25MALE";
741 case MOD_2_PARALLEL:
742 return "MOD_2_PARALLEL";
743 case MOD_BLANK:
744 return "empty";
745 default:
746 return "invalid";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 }
748}
749
Jiri Slaby15b611f2006-12-08 02:39:04 -0800750static int mod_compat_type(int module_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751{
752 return module_type >> 4;
753}
754
755static void sx_reconfigure_port(struct sx_port *port)
756{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800757 if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
758 if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
759 printk(KERN_WARNING "sx: Sent reconfigure command, but "
760 "card didn't react.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 }
762 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800763 sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
764 "port isn't open (%02x).\n",
765 sx_read_channel_byte(port, hi_hstat));
766 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767}
768
Jiri Slaby15b611f2006-12-08 02:39:04 -0800769static void sx_setsignals(struct sx_port *port, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770{
771 int t;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800772 func_enter2();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Jiri Slaby15b611f2006-12-08 02:39:04 -0800774 t = sx_read_channel_byte(port, hi_op);
775 if (dtr >= 0)
776 t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
777 if (rts >= 0)
778 t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
779 sx_write_channel_byte(port, hi_op, t);
780 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
Jiri Slaby15b611f2006-12-08 02:39:04 -0800782 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783}
784
Jiri Slaby15b611f2006-12-08 02:39:04 -0800785static int sx_getsignals(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800787 int i_stat, o_stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
Jiri Slaby15b611f2006-12-08 02:39:04 -0800789 o_stat = sx_read_channel_byte(port, hi_op);
790 i_stat = sx_read_channel_byte(port, hi_ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Jiri Slaby15b611f2006-12-08 02:39:04 -0800792 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) "
793 "%02x/%02x\n",
794 (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
Alan Cox31f35932009-01-02 13:45:05 +0000795 port->c_dcd, tty_port_carrier_raised(&port->gs.port),
Jiri Slaby15b611f2006-12-08 02:39:04 -0800796 sx_read_channel_byte(port, hi_ip),
797 sx_read_channel_byte(port, hi_state));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
Jiri Slaby15b611f2006-12-08 02:39:04 -0800799 return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
800 ((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
801 ((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
802 ((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
803 ((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
804 ((i_stat & IP_RI) ? TIOCM_RNG : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805}
806
Jiri Slaby15b611f2006-12-08 02:39:04 -0800807static void sx_set_baud(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808{
809 int t;
810
811 if (port->board->ta_type == MOD_SXDC) {
812 switch (port->gs.baud) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800813 /* Save some typing work... */
814#define e(x) case x: t = BAUD_ ## x; break
815 e(50);
816 e(75);
817 e(110);
818 e(150);
819 e(200);
820 e(300);
821 e(600);
822 e(1200);
823 e(1800);
824 e(2000);
825 e(2400);
826 e(4800);
827 e(7200);
828 e(9600);
829 e(14400);
830 e(19200);
831 e(28800);
832 e(38400);
833 e(56000);
834 e(57600);
835 e(64000);
836 e(76800);
837 e(115200);
838 e(128000);
839 e(150000);
840 e(230400);
841 e(256000);
842 e(460800);
843 e(921600);
844 case 134:
845 t = BAUD_134_5;
846 break;
847 case 0:
848 t = -1;
849 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 default:
851 /* Can I return "invalid"? */
852 t = BAUD_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800853 printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
854 port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 break;
856 }
857#undef e
858 if (t > 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800859/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
860 sx_setsignals(port, 1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 /* XXX This is not TA & MTA compatible */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800862 sx_write_channel_byte(port, hi_csr, 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Jiri Slaby15b611f2006-12-08 02:39:04 -0800864 sx_write_channel_byte(port, hi_txbaud, t);
865 sx_write_channel_byte(port, hi_rxbaud, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800867 sx_setsignals(port, 0, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 }
869 } else {
870 switch (port->gs.baud) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800871#define e(x) case x: t = CSR_ ## x; break
872 e(75);
873 e(150);
874 e(300);
875 e(600);
876 e(1200);
877 e(2400);
878 e(4800);
879 e(1800);
880 e(9600);
881 e(19200);
882 e(57600);
883 e(38400);
884/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
885 case 110:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 if (port->board->ta_type == MOD_TA) {
887 t = CSR_110;
888 break;
889 } else {
890 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800891 printk(KERN_INFO "sx: Unsupported baud rate: "
892 "%d.\n", port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 break;
894 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800895 case 115200:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 if (port->board->ta_type == MOD_TA) {
897 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800898 printk(KERN_INFO "sx: Unsupported baud rate: "
899 "%d.\n", port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 break;
901 } else {
902 t = CSR_110;
903 break;
904 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800905 case 0:
906 t = -1;
907 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 default:
909 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800910 printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
911 port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 break;
913 }
914#undef e
915 if (t >= 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800916 sx_setsignals(port, 1, -1);
917 sx_write_channel_byte(port, hi_csr, t * 0x11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800919 sx_setsignals(port, 0, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921 }
922}
923
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
925 better. -- REW */
926
Jiri Slaby15b611f2006-12-08 02:39:04 -0800927static int sx_set_real_termios(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928{
929 struct sx_port *port = ptr;
930
931 func_enter2();
932
Alan Coxb5391e22008-07-16 21:55:20 +0100933 if (!port->gs.port.tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 return 0;
935
936 /* What is this doing here? -- REW
937 Ha! figured it out. It is to allow you to get DTR active again
938 if you've dropped it with stty 0. Moved to set_baud, where it
939 belongs (next to the drop dtr if baud == 0) -- REW */
940 /* sx_setsignals (port, 1, -1); */
941
Jiri Slaby15b611f2006-12-08 02:39:04 -0800942 sx_set_baud(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Alan Coxb5391e22008-07-16 21:55:20 +0100944#define CFLAG port->gs.port.tty->termios->c_cflag
Jiri Slaby15b611f2006-12-08 02:39:04 -0800945 sx_write_channel_byte(port, hi_mr1,
Alan Coxb5391e22008-07-16 21:55:20 +0100946 (C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) |
947 (C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) |
948 (C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) |
Jiri Slaby15b611f2006-12-08 02:39:04 -0800949 (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
950 (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
951 (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
952 (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Jiri Slaby15b611f2006-12-08 02:39:04 -0800954 sx_write_channel_byte(port, hi_mr2,
Alan Coxb5391e22008-07-16 21:55:20 +0100955 (C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) |
956 (C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP :
Jiri Slaby15b611f2006-12-08 02:39:04 -0800957 MR2_1_STOP));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
959 switch (CFLAG & CSIZE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800960 case CS8:
961 sx_write_channel_byte(port, hi_mask, 0xff);
962 break;
963 case CS7:
964 sx_write_channel_byte(port, hi_mask, 0x7f);
965 break;
966 case CS6:
967 sx_write_channel_byte(port, hi_mask, 0x3f);
968 break;
969 case CS5:
970 sx_write_channel_byte(port, hi_mask, 0x1f);
971 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 default:
Andrew Morton32fb3ca2008-05-06 20:42:35 -0700973 printk(KERN_INFO "sx: Invalid wordsize: %u\n",
974 (unsigned int)CFLAG & CSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 break;
976 }
977
Jiri Slaby15b611f2006-12-08 02:39:04 -0800978 sx_write_channel_byte(port, hi_prtcl,
Alan Coxb5391e22008-07-16 21:55:20 +0100979 (I_IXON(port->gs.port.tty) ? SP_TXEN : 0) |
980 (I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) |
981 (I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Jiri Slaby15b611f2006-12-08 02:39:04 -0800983 sx_write_channel_byte(port, hi_break,
Alan Coxb5391e22008-07-16 21:55:20 +0100984 (I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 |
985 I_BRKINT(port->gs.port.tty) ? BR_INT : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
Alan Coxb5391e22008-07-16 21:55:20 +0100987 sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty));
988 sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty));
989 sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty));
990 sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
992 sx_reconfigure_port(port);
993
994 /* Tell line discipline whether we will do input cooking */
Alan Coxb5391e22008-07-16 21:55:20 +0100995 if (I_OTHER(port->gs.port.tty)) {
996 clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 } else {
Alan Coxb5391e22008-07-16 21:55:20 +0100998 set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001000 sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
Alan Coxb5391e22008-07-16 21:55:20 +01001001 (unsigned int)port->gs.port.tty->termios->c_iflag,
1002 I_OTHER(port->gs.port.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
1004/* Tell line discipline whether we will do output cooking.
1005 * If OPOST is set and no other output flags are set then we can do output
1006 * processing. Even if only *one* other flag in the O_OTHER group is set
1007 * we do cooking in software.
1008 */
Alan Coxb5391e22008-07-16 21:55:20 +01001009 if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) {
1010 set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 } else {
Alan Coxb5391e22008-07-16 21:55:20 +01001012 clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001014 sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001015 (unsigned int)port->gs.port.tty->termios->c_oflag,
1016 O_OTHER(port->gs.port.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 /* port->c_dcd = sx_get_CD (port); */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001018 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return 0;
1020}
1021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022/* ********************************************************************** *
1023 * the interrupt related routines *
1024 * ********************************************************************** */
1025
1026/* Note:
1027 Other drivers use the macro "MIN" to calculate how much to copy.
1028 This has the disadvantage that it will evaluate parts twice. That's
1029 expensive when it's IO (and the compiler cannot optimize those away!).
1030 Moreover, I'm not sure that you're race-free.
1031
1032 I assign a value, and then only allow the value to decrease. This
1033 is always safe. This makes the code a few lines longer, and you
1034 know I'm dead against that, but I think it is required in this
1035 case. */
1036
Jiri Slaby15b611f2006-12-08 02:39:04 -08001037static void sx_transmit_chars(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038{
1039 int c;
1040 int tx_ip;
1041 int txroom;
1042
Jiri Slaby15b611f2006-12-08 02:39:04 -08001043 func_enter2();
1044 sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
1045 port, port->gs.xmit_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Jiri Slaby15b611f2006-12-08 02:39:04 -08001047 if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 return;
1049 }
1050
1051 while (1) {
1052 c = port->gs.xmit_cnt;
1053
Jiri Slaby15b611f2006-12-08 02:39:04 -08001054 sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
1055 tx_ip = sx_read_channel_byte(port, hi_txipos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
1057 /* Took me 5 minutes to deduce this formula.
1058 Luckily it is literally in the manual in section 6.5.4.3.5 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001059 txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
1060 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
1062 /* Don't copy more bytes than there is room for in the buffer */
1063 if (c > txroom)
1064 c = txroom;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001065 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
1067 /* Don't copy past the end of the hardware transmit buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001068 if (c > 0x100 - tx_ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 c = 0x100 - tx_ip;
1070
Jiri Slaby15b611f2006-12-08 02:39:04 -08001071 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
1073 /* Don't copy pas the end of the source buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001074 if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
1076
Jiri Slaby15b611f2006-12-08 02:39:04 -08001077 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
1078 c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
Jiri Slaby15b611f2006-12-08 02:39:04 -08001080 /* If for one reason or another, we can't copy more data, we're
1081 done! */
1082 if (c == 0)
1083 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Jiri Slaby15b611f2006-12-08 02:39:04 -08001085 memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
1086 tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 /* Update the pointer in the card */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001089 sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
1091 /* Update the kernel buffer end */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001092 port->gs.xmit_tail = (port->gs.xmit_tail + c) &
1093 (SERIAL_XMIT_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095 /* This one last. (this is essential)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001096 It would allow others to start putting more data into the
1097 buffer! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 port->gs.xmit_cnt -= c;
1099 }
1100
1101 if (port->gs.xmit_cnt == 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001102 sx_disable_tx_interrupts(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 }
1104
Alan Coxb5391e22008-07-16 21:55:20 +01001105 if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
1106 tty_wakeup(port->gs.port.tty);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001107 sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
1108 port->gs.wakeup_chars);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 }
1110
Jiri Slaby15b611f2006-12-08 02:39:04 -08001111 clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
1112 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113}
1114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115/* Note the symmetry between receiving chars and transmitting them!
1116 Note: The kernel should have implemented both a receive buffer and
1117 a transmit buffer. */
1118
1119/* Inlined: Called only once. Remove the inline when you add another call */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001120static inline void sx_receive_chars(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
1122 int c;
1123 int rx_op;
1124 struct tty_struct *tty;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001125 int copied = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08001126 unsigned char *rp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
Jiri Slaby15b611f2006-12-08 02:39:04 -08001128 func_enter2();
Alan Coxb5391e22008-07-16 21:55:20 +01001129 tty = port->gs.port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 while (1) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001131 rx_op = sx_read_channel_byte(port, hi_rxopos);
1132 c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Jiri Slaby15b611f2006-12-08 02:39:04 -08001134 sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001136 /* Don't copy past the end of the hardware receive buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001137 if (rx_op + c > 0x100)
1138 c = 0x100 - rx_op;
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001139
Jiri Slaby15b611f2006-12-08 02:39:04 -08001140 sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001141
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 /* Don't copy more bytes than there is room for in the buffer */
Alan Cox33f0f882006-01-09 20:54:13 -08001143
1144 c = tty_prepare_flip_string(tty, &rp, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Jiri Slaby15b611f2006-12-08 02:39:04 -08001146 sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 /* If for one reason or another, we can't copy more data, we're done! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001149 if (c == 0)
1150 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Jiri Slaby15b611f2006-12-08 02:39:04 -08001152 sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
1153 "%d at %lx\n", c, read_sx_byte(port->board,
1154 CHAN_OFFSET(port, hi_rxbuf) + rx_op),
1155 CHAN_OFFSET(port, hi_rxbuf));
1156 memcpy_fromio(rp, port->board->base +
1157 CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
1159 /* This one last. ( Not essential.)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001160 It allows the card to start putting more data into the
1161 buffer!
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 Update the pointer in the card */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001163 sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 copied += c;
1166 }
1167 if (copied) {
1168 struct timeval tv;
1169
Jiri Slaby15b611f2006-12-08 02:39:04 -08001170 do_gettimeofday(&tv);
1171 sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
1172 "chars): %d.%06d (%d/%d)\n", port->line,
1173 copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
1174 tty->raw, tty->real_raw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
Jiri Slaby15b611f2006-12-08 02:39:04 -08001176 /* Tell the rest of the system the news. Great news. New
1177 characters! */
1178 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 /* tty_schedule_flip (tty); */
1180 }
1181
Jiri Slaby15b611f2006-12-08 02:39:04 -08001182 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183}
1184
1185/* Inlined: it is called only once. Remove the inline if you add another
1186 call */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001187static inline void sx_check_modem_signals(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188{
1189 int hi_state;
1190 int c_dcd;
1191
Jiri Slaby15b611f2006-12-08 02:39:04 -08001192 hi_state = sx_read_channel_byte(port, hi_state);
1193 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
Alan Cox31f35932009-01-02 13:45:05 +00001194 port->c_dcd, tty_port_carrier_raised(&port->gs.port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 if (hi_state & ST_BREAK) {
1197 hi_state &= ~ST_BREAK;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001198 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
1199 sx_write_channel_byte(port, hi_state, hi_state);
1200 gs_got_break(&port->gs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 }
1202 if (hi_state & ST_DCD) {
1203 hi_state &= ~ST_DCD;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001204 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
1205 sx_write_channel_byte(port, hi_state, hi_state);
Alan Cox31f35932009-01-02 13:45:05 +00001206 c_dcd = tty_port_carrier_raised(&port->gs.port);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001207 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 if (c_dcd != port->c_dcd) {
1209 port->c_dcd = c_dcd;
Alan Cox31f35932009-01-02 13:45:05 +00001210 if (tty_port_carrier_raised(&port->gs.port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 /* DCD went UP */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001212 if ((sx_read_channel_byte(port, hi_hstat) !=
1213 HS_IDLE_CLOSED) &&
Alan Coxb5391e22008-07-16 21:55:20 +01001214 !(port->gs.port.tty->termios->
Jiri Slaby15b611f2006-12-08 02:39:04 -08001215 c_cflag & CLOCAL)) {
1216 /* Are we blocking in open? */
1217 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1218 "active, unblocking open\n");
Alan Coxb5391e22008-07-16 21:55:20 +01001219 wake_up_interruptible(&port->gs.port.
Jiri Slaby15b611f2006-12-08 02:39:04 -08001220 open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001222 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1223 "raised. Ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
1225 } else {
1226 /* DCD went down! */
Alan Coxb5391e22008-07-16 21:55:20 +01001227 if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){
Jiri Slaby15b611f2006-12-08 02:39:04 -08001228 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1229 "dropped. hanging up....\n");
Alan Coxb5391e22008-07-16 21:55:20 +01001230 tty_hangup(port->gs.port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001232 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1233 "dropped. ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
1235 }
1236 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001237 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
1238 "DCD changed, but it didn't.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 }
1240 }
1241}
1242
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243/* This is what an interrupt routine should look like.
1244 * Small, elegant, clear.
1245 */
1246
Jiri Slaby15b611f2006-12-08 02:39:04 -08001247static irqreturn_t sx_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248{
1249 struct sx_board *board = ptr;
1250 struct sx_port *port;
1251 int i;
1252
Jiri Slaby15b611f2006-12-08 02:39:04 -08001253 func_enter();
1254 sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
1255 board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
1257 /* AAargh! The order in which to do these things is essential and
1258 not trivial.
1259
1260 - Rate limit goes before "recursive". Otherwise a series of
Jiri Slaby15b611f2006-12-08 02:39:04 -08001261 recursive calls will hang the machine in the interrupt routine.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
1263 - hardware twiddling goes before "recursive". Otherwise when we
Jiri Slaby15b611f2006-12-08 02:39:04 -08001264 poll the card, and a recursive interrupt happens, we won't
1265 ack the card, so it might keep on interrupting us. (especially
1266 level sensitive interrupt systems like PCI).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
1268 - Rate limit goes before hardware twiddling. Otherwise we won't
Jiri Slaby15b611f2006-12-08 02:39:04 -08001269 catch a card that has gone bonkers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 - The "initialized" test goes after the hardware twiddling. Otherwise
Jiri Slaby15b611f2006-12-08 02:39:04 -08001272 the card will stick us in the interrupt routine again.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274 - The initialized test goes before recursive.
Jiri Slaby15b611f2006-12-08 02:39:04 -08001275 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277#ifdef IRQ_RATE_LIMIT
1278 /* Aaargh! I'm ashamed. This costs more lines-of-code than the
Jiri Slaby15b611f2006-12-08 02:39:04 -08001279 actual interrupt routine!. (Well, used to when I wrote that
1280 comment) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 {
1282 static int lastjif;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001283 static int nintr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
1285 if (lastjif == jiffies) {
1286 if (++nintr > IRQ_RATE_LIMIT) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001287 free_irq(board->irq, board);
1288 printk(KERN_ERR "sx: Too many interrupts. "
1289 "Turning off interrupt %d.\n",
1290 board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 }
1292 } else {
1293 lastjif = jiffies;
1294 nintr = 0;
1295 }
1296 }
1297#endif
1298
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 if (board->irq == irq) {
1300 /* Tell the card we've noticed the interrupt. */
1301
Jiri Slaby15b611f2006-12-08 02:39:04 -08001302 sx_write_board_word(board, cc_int_pending, 0);
1303 if (IS_SX_BOARD(board)) {
1304 write_sx_byte(board, SX_RESET_IRQ, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001306 inb(board->eisa_base + 0xc03);
1307 write_sx_word(board, 8, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001309 write_sx_byte(board, SI2_ISA_INTCLEAR,
1310 SI2_ISA_INTCLEAR_CLEAR);
1311 write_sx_byte(board, SI2_ISA_INTCLEAR,
1312 SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 }
1314 }
1315
1316 if (!sx_initialized)
1317 return IRQ_HANDLED;
1318 if (!(board->flags & SX_BOARD_INITIALIZED))
1319 return IRQ_HANDLED;
1320
Jiri Slaby15b611f2006-12-08 02:39:04 -08001321 if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
1322 printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 return IRQ_HANDLED;
1324 }
1325
Jiri Slaby15b611f2006-12-08 02:39:04 -08001326 for (i = 0; i < board->nports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 port = &board->ports[i];
Alan Coxb5391e22008-07-16 21:55:20 +01001328 if (port->gs.port.flags & GS_ACTIVE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001329 if (sx_read_channel_byte(port, hi_state)) {
1330 sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
1331 "modem signal change?... \n",i);
1332 sx_check_modem_signals(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 }
1334 if (port->gs.xmit_cnt) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001335 sx_transmit_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 }
Alan Coxb5391e22008-07-16 21:55:20 +01001337 if (!(port->gs.port.flags & SX_RX_THROTTLE)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001338 sx_receive_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 }
1340 }
1341 }
1342
Jiri Slaby15b611f2006-12-08 02:39:04 -08001343 clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Jiri Slaby15b611f2006-12-08 02:39:04 -08001345 sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
1346 board->irq);
1347 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 return IRQ_HANDLED;
1349}
1350
Jiri Slaby15b611f2006-12-08 02:39:04 -08001351static void sx_pollfunc(unsigned long data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001353 struct sx_board *board = (struct sx_board *)data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Jiri Slaby15b611f2006-12-08 02:39:04 -08001355 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Jiri Slaby15b611f2006-12-08 02:39:04 -08001357 sx_interrupt(0, board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Jiri Slabyc9594642006-12-08 02:39:05 -08001359 mod_timer(&board->timer, jiffies + sx_poll);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001360 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361}
1362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363/* ********************************************************************** *
1364 * Here are the routines that actually *
1365 * interface with the generic_serial driver *
1366 * ********************************************************************** */
1367
1368/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
1369/* Hmm. Ok I figured it out. You don't. */
1370
Jiri Slaby15b611f2006-12-08 02:39:04 -08001371static void sx_disable_tx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001373 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 func_enter2();
1375
Alan Coxb5391e22008-07-16 21:55:20 +01001376 port->gs.port.flags &= ~GS_TX_INTEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
1378 func_exit();
1379}
1380
Jiri Slaby15b611f2006-12-08 02:39:04 -08001381static void sx_enable_tx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001383 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 int data_in_buffer;
1385 func_enter2();
1386
1387 /* First transmit the characters that we're supposed to */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001388 sx_transmit_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390 /* The sx card will never interrupt us if we don't fill the buffer
1391 past 25%. So we keep considering interrupts off if that's the case. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001392 data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
1393 sx_read_channel_byte(port, hi_txopos)) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
1395 /* XXX Must be "HIGH_WATER" for SI card according to doc. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001396 if (data_in_buffer < LOW_WATER)
Alan Coxb5391e22008-07-16 21:55:20 +01001397 port->gs.port.flags &= ~GS_TX_INTEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
1399 func_exit();
1400}
1401
Jiri Slaby15b611f2006-12-08 02:39:04 -08001402static void sx_disable_rx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403{
1404 /* struct sx_port *port = ptr; */
1405 func_enter();
1406
1407 func_exit();
1408}
1409
Jiri Slaby15b611f2006-12-08 02:39:04 -08001410static void sx_enable_rx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411{
1412 /* struct sx_port *port = ptr; */
1413 func_enter();
1414
1415 func_exit();
1416}
1417
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418/* Jeez. Isn't this simple? */
Alan Cox31f35932009-01-02 13:45:05 +00001419static int sx_carrier_raised(struct tty_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420{
Alan Cox31f35932009-01-02 13:45:05 +00001421 struct sx_port *sp = container_of(port, struct sx_port, gs.port);
1422 return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423}
1424
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425/* Jeez. Isn't this simple? */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001426static int sx_chars_in_buffer(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427{
1428 struct sx_port *port = ptr;
1429 func_enter2();
1430
1431 func_exit();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001432 return ((sx_read_channel_byte(port, hi_txipos) -
1433 sx_read_channel_byte(port, hi_txopos)) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434}
1435
Jiri Slaby15b611f2006-12-08 02:39:04 -08001436static void sx_shutdown_port(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001438 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
1440 func_enter();
1441
Alan Coxb5391e22008-07-16 21:55:20 +01001442 port->gs.port.flags &= ~GS_ACTIVE;
1443 if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001444 sx_setsignals(port, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 sx_reconfigure_port(port);
1446 }
1447
1448 func_exit();
1449}
1450
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451/* ********************************************************************** *
1452 * Here are the routines that actually *
1453 * interface with the rest of the system *
1454 * ********************************************************************** */
1455
Jiri Slaby15b611f2006-12-08 02:39:04 -08001456static int sx_open(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457{
1458 struct sx_port *port;
1459 int retval, line;
1460 unsigned long flags;
1461
1462 func_enter();
1463
1464 if (!sx_initialized) {
1465 return -EIO;
1466 }
1467
1468 line = tty->index;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001469 sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
Pavel Emelyanovba25f9d2007-10-18 23:40:40 -07001470 "np=%d)\n", task_pid_nr(current), line, tty,
Jiri Slaby15b611f2006-12-08 02:39:04 -08001471 current->signal->tty, sx_nports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
1473 if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
1474 return -ENODEV;
1475
Jiri Slaby15b611f2006-12-08 02:39:04 -08001476 port = &sx_ports[line];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
Jiri Slaby15b611f2006-12-08 02:39:04 -08001478 1 -> 0 transition. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
Jiri Slaby15b611f2006-12-08 02:39:04 -08001480 sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
1482 spin_lock_irqsave(&port->gs.driver_lock, flags);
1483
1484 tty->driver_data = port;
Alan Coxb5391e22008-07-16 21:55:20 +01001485 port->gs.port.tty = tty;
1486 port->gs.port.count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 spin_unlock_irqrestore(&port->gs.driver_lock, flags);
1488
Jiri Slaby15b611f2006-12-08 02:39:04 -08001489 sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
1491 /*
1492 * Start up serial port
1493 */
1494 retval = gs_init_port(&port->gs);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001495 sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 if (retval) {
Alan Coxb5391e22008-07-16 21:55:20 +01001497 port->gs.port.count--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 return retval;
1499 }
1500
Alan Coxb5391e22008-07-16 21:55:20 +01001501 port->gs.port.flags |= GS_ACTIVE;
1502 if (port->gs.port.count <= 1)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001503 sx_setsignals(port, 1, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
1505#if 0
1506 if (sx_debug & SX_DEBUG_OPEN)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001507 my_hd(port, sizeof(*port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508#else
1509 if (sx_debug & SX_DEBUG_OPEN)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001510 my_hd_io(port->board->base + port->ch_base, sizeof(*port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511#endif
1512
Alan Coxb5391e22008-07-16 21:55:20 +01001513 if (port->gs.port.count <= 1) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001514 if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
1515 printk(KERN_ERR "sx: Card didn't respond to LOPEN "
1516 "command.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 spin_lock_irqsave(&port->gs.driver_lock, flags);
Alan Coxb5391e22008-07-16 21:55:20 +01001518 port->gs.port.count--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 spin_unlock_irqrestore(&port->gs.driver_lock, flags);
1520 return -EIO;
1521 }
1522 }
1523
1524 retval = gs_block_til_ready(port, filp);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001525 sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001526 retval, port->gs.port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
1528 if (retval) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001529/*
Alan Coxb5391e22008-07-16 21:55:20 +01001530 * Don't lower gs.port.count here because sx_close() will be called later
Jiri Slaby15b611f2006-12-08 02:39:04 -08001531 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
1533 return retval;
1534 }
1535 /* tty->low_latency = 1; */
1536
Alan Cox31f35932009-01-02 13:45:05 +00001537 port->c_dcd = sx_carrier_raised(&port->gs.port);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001538 sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539
1540 func_exit();
1541 return 0;
1542
1543}
1544
Jiri Slaby15b611f2006-12-08 02:39:04 -08001545static void sx_close(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001547 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 /* Give the port 5 seconds to close down. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001549 int to = 5 * HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
Jiri Slaby15b611f2006-12-08 02:39:04 -08001551 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552
Jiri Slaby15b611f2006-12-08 02:39:04 -08001553 sx_setsignals(port, 0, 0);
1554 sx_reconfigure_port(port);
1555 sx_send_command(port, HS_CLOSE, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
Jiri Slaby15b611f2006-12-08 02:39:04 -08001557 while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 if (msleep_interruptible(10))
1559 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001560 if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) {
1561 if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED)
1562 != 1) {
1563 printk(KERN_ERR "sx: sent the force_close command, but "
1564 "card didn't react\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 } else
Jiri Slaby15b611f2006-12-08 02:39:04 -08001566 sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
1567 "command.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 }
1569
Jiri Slaby15b611f2006-12-08 02:39:04 -08001570 sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001571 5 * HZ - to - 1, port->gs.port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
Alan Coxb5391e22008-07-16 21:55:20 +01001573 if (port->gs.port.count) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001574 sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001575 port->gs.port.count);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001576 /*printk("%s SETTING port count to zero: %p count: %d\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001577 __func__, port, port->gs.port.count);
1578 port->gs.port.count = 0;*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 }
1580
Jiri Slaby15b611f2006-12-08 02:39:04 -08001581 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582}
1583
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584/* This is relatively thorough. But then again it is only 20 lines. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001585#define MARCHUP for (i = min; i < max; i++)
1586#define MARCHDOWN for (i = max - 1; i >= min; i--)
1587#define W0 write_sx_byte(board, i, 0x55)
1588#define W1 write_sx_byte(board, i, 0xaa)
1589#define R0 if (read_sx_byte(board, i) != 0x55) return 1
1590#define R1 if (read_sx_byte(board, i) != 0xaa) return 1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
1592/* This memtest takes a human-noticable time. You normally only do it
1593 once a boot, so I guess that it is worth it. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001594static int do_memtest(struct sx_board *board, int min, int max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595{
1596 int i;
1597
1598 /* This is a marchb. Theoretically, marchb catches much more than
1599 simpler tests. In practise, the longer test just catches more
1600 intermittent errors. -- REW
1601 (For the theory behind memory testing see:
1602 Testing Semiconductor Memories by A.J. van de Goor.) */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001603 MARCHUP {
1604 W0;
1605 }
1606 MARCHUP {
1607 R0;
1608 W1;
1609 R1;
1610 W0;
1611 R0;
1612 W1;
1613 }
1614 MARCHUP {
1615 R1;
1616 W0;
1617 W1;
1618 }
1619 MARCHDOWN {
1620 R1;
1621 W0;
1622 W1;
1623 W0;
1624 }
1625 MARCHDOWN {
1626 R0;
1627 W1;
1628 W0;
1629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630
1631 return 0;
1632}
1633
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634#undef MARCHUP
1635#undef MARCHDOWN
1636#undef W0
1637#undef W1
1638#undef R0
1639#undef R1
1640
Jiri Slaby15b611f2006-12-08 02:39:04 -08001641#define MARCHUP for (i = min; i < max; i += 2)
1642#define MARCHDOWN for (i = max - 1; i >= min; i -= 2)
1643#define W0 write_sx_word(board, i, 0x55aa)
1644#define W1 write_sx_word(board, i, 0xaa55)
1645#define R0 if (read_sx_word(board, i) != 0x55aa) return 1
1646#define R1 if (read_sx_word(board, i) != 0xaa55) return 1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
1648#if 0
1649/* This memtest takes a human-noticable time. You normally only do it
1650 once a boot, so I guess that it is worth it. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001651static int do_memtest_w(struct sx_board *board, int min, int max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652{
1653 int i;
1654
Jiri Slaby15b611f2006-12-08 02:39:04 -08001655 MARCHUP {
1656 W0;
1657 }
1658 MARCHUP {
1659 R0;
1660 W1;
1661 R1;
1662 W0;
1663 R0;
1664 W1;
1665 }
1666 MARCHUP {
1667 R1;
1668 W0;
1669 W1;
1670 }
1671 MARCHDOWN {
1672 R1;
1673 W0;
1674 W1;
1675 W0;
1676 }
1677 MARCHDOWN {
1678 R0;
1679 W1;
1680 W0;
1681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
1683 return 0;
1684}
1685#endif
1686
Alan Cox11af7472008-07-25 01:48:15 -07001687static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
1688 unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689{
Alan Cox11af7472008-07-25 01:48:15 -07001690 long rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 int __user *descr = (int __user *)arg;
1692 int i;
1693 static struct sx_board *board = NULL;
1694 int nbytes, offset;
1695 unsigned long data;
1696 char *tmp;
1697
1698 func_enter();
1699
Alan Cox11af7472008-07-25 01:48:15 -07001700 if (!capable(CAP_SYS_RAWIO))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 return -EPERM;
Alan Cox11af7472008-07-25 01:48:15 -07001702
Arnd Bergmannec79d602010-06-01 22:53:01 +02001703 tty_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
Jiri Slaby15b611f2006-12-08 02:39:04 -08001705 sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
Jiri Slaby15b611f2006-12-08 02:39:04 -08001707 if (!board)
1708 board = &boards[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 if (board->flags & SX_BOARD_PRESENT) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001710 sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
1711 board->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001713 sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
1714 board->flags);
1715 for (i = 0; i < SX_NBOARDS; i++)
1716 sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
1717 sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
Dan Carpenter736d5452009-02-04 15:12:20 -08001718 rc = -EIO;
1719 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 }
1721
1722 switch (cmd) {
1723 case SXIO_SET_BOARD:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001724 sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
Alan Cox11af7472008-07-25 01:48:15 -07001725 rc = -EIO;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001726 if (arg >= SX_NBOARDS)
Alan Cox11af7472008-07-25 01:48:15 -07001727 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001728 sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
1729 if (!(boards[arg].flags & SX_BOARD_PRESENT))
Alan Cox11af7472008-07-25 01:48:15 -07001730 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001731 sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 board = &boards[arg];
Alan Cox11af7472008-07-25 01:48:15 -07001733 rc = 0;
1734 /* FIXME: And this does ... nothing?? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 break;
1736 case SXIO_GET_TYPE:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001737 rc = -ENOENT; /* If we manage to miss one, return error. */
1738 if (IS_SX_BOARD(board))
1739 rc = SX_TYPE_SX;
1740 if (IS_CF_BOARD(board))
1741 rc = SX_TYPE_CF;
1742 if (IS_SI_BOARD(board))
1743 rc = SX_TYPE_SI;
1744 if (IS_SI1_BOARD(board))
1745 rc = SX_TYPE_SI;
1746 if (IS_EISA_BOARD(board))
1747 rc = SX_TYPE_SI;
Alan Cox11af7472008-07-25 01:48:15 -07001748 sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 break;
1750 case SXIO_DO_RAMTEST:
Ilpo Järvinen9b6d2512009-02-20 15:38:45 -08001751 if (sx_initialized) { /* Already initialized: better not ramtest the board. */
Dan Carpenter736d5452009-02-04 15:12:20 -08001752 rc = -EPERM;
1753 break;
Ilpo Järvinen9b6d2512009-02-20 15:38:45 -08001754 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001755 if (IS_SX_BOARD(board)) {
1756 rc = do_memtest(board, 0, 0x7000);
1757 if (!rc)
1758 rc = do_memtest(board, 0, 0x7000);
1759 /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001761 rc = do_memtest(board, 0, 0x7ff8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
1763 }
Alan Cox11af7472008-07-25 01:48:15 -07001764 sx_dprintk(SX_DEBUG_FIRMWARE,
1765 "returning memtest result= %ld\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 break;
1767 case SXIO_DOWNLOAD:
Alan Cox11af7472008-07-25 01:48:15 -07001768 if (sx_initialized) {/* Already initialized */
1769 rc = -EEXIST;
1770 break;
1771 }
1772 if (!sx_reset(board)) {
1773 rc = -EIO;
1774 break;
1775 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001776 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
Jiri Slaby15b611f2006-12-08 02:39:04 -08001778 tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
Alan Cox11af7472008-07-25 01:48:15 -07001779 if (!tmp) {
1780 rc = -ENOMEM;
1781 break;
1782 }
1783 /* FIXME: check returns */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001784 get_user(nbytes, descr++);
1785 get_user(offset, descr++);
1786 get_user(data, descr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 while (nbytes && data) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001788 for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
1789 if (copy_from_user(tmp, (char __user *)data + i,
1790 (i + SX_CHUNK_SIZE > nbytes) ?
1791 nbytes - i : SX_CHUNK_SIZE)) {
1792 kfree(tmp);
Alan Cox11af7472008-07-25 01:48:15 -07001793 rc = -EFAULT;
Dan Carpenterb28fe282009-02-20 15:38:46 -08001794 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001796 memcpy_toio(board->base2 + offset + i, tmp,
1797 (i + SX_CHUNK_SIZE > nbytes) ?
1798 nbytes - i : SX_CHUNK_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 }
1800
Jiri Slaby15b611f2006-12-08 02:39:04 -08001801 get_user(nbytes, descr++);
1802 get_user(offset, descr++);
1803 get_user(data, descr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001805 kfree(tmp);
1806 sx_nports += sx_init_board(board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 rc = sx_nports;
1808 break;
1809 case SXIO_INIT:
Alan Cox11af7472008-07-25 01:48:15 -07001810 if (sx_initialized) { /* Already initialized */
1811 rc = -EEXIST;
1812 break;
1813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 /* This is not allowed until all boards are initialized... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001815 for (i = 0; i < SX_NBOARDS; i++) {
1816 if ((boards[i].flags & SX_BOARD_PRESENT) &&
Alan Cox11af7472008-07-25 01:48:15 -07001817 !(boards[i].flags & SX_BOARD_INITIALIZED)) {
1818 rc = -EIO;
1819 break;
1820 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001822 for (i = 0; i < SX_NBOARDS; i++)
1823 if (!(boards[i].flags & SX_BOARD_PRESENT))
1824 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
Jiri Slaby15b611f2006-12-08 02:39:04 -08001826 sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
1827 "%d channels, first board: %d ports\n",
1828 i, sx_nports, boards[0].nports);
1829 rc = sx_init_portstructs(i, sx_nports);
1830 sx_init_drivers();
1831 if (rc >= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 sx_initialized++;
1833 break;
1834 case SXIO_SETDEBUG:
1835 sx_debug = arg;
1836 break;
1837 case SXIO_GETDEBUG:
1838 rc = sx_debug;
1839 break;
1840 case SXIO_GETGSDEBUG:
1841 case SXIO_SETGSDEBUG:
1842 rc = -EINVAL;
1843 break;
1844 case SXIO_GETNPORTS:
1845 rc = sx_nports;
1846 break;
1847 default:
Alan Cox11af7472008-07-25 01:48:15 -07001848 rc = -ENOTTY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 break;
1850 }
Dan Carpenter736d5452009-02-04 15:12:20 -08001851out:
Arnd Bergmannec79d602010-06-01 22:53:01 +02001852 tty_unlock();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001853 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 return rc;
1855}
1856
Alan Cox9e989662008-07-22 11:18:03 +01001857static int sx_break(struct tty_struct *tty, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858{
1859 struct sx_port *port = tty->driver_data;
1860 int rv;
1861
Jiri Slaby15b611f2006-12-08 02:39:04 -08001862 func_enter();
Arnd Bergmannec79d602010-06-01 22:53:01 +02001863 tty_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Jiri Slaby15b611f2006-12-08 02:39:04 -08001865 if (flag)
1866 rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
1867 else
1868 rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
1869 if (rv != 1)
1870 printk(KERN_ERR "sx: couldn't send break (%x).\n",
1871 read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
Arnd Bergmannec79d602010-06-01 22:53:01 +02001872 tty_unlock();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001873 func_exit();
Alan Cox9e989662008-07-22 11:18:03 +01001874 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875}
1876
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1878{
1879 struct sx_port *port = tty->driver_data;
1880 return sx_getsignals(port);
1881}
1882
1883static int sx_tiocmset(struct tty_struct *tty, struct file *file,
Jiri Slaby15b611f2006-12-08 02:39:04 -08001884 unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885{
1886 struct sx_port *port = tty->driver_data;
1887 int rts = -1, dtr = -1;
1888
1889 if (set & TIOCM_RTS)
1890 rts = 1;
1891 if (set & TIOCM_DTR)
1892 dtr = 1;
1893 if (clear & TIOCM_RTS)
1894 rts = 0;
1895 if (clear & TIOCM_DTR)
1896 dtr = 0;
1897
1898 sx_setsignals(port, dtr, rts);
1899 sx_reconfigure_port(port);
1900 return 0;
1901}
1902
Jiri Slaby15b611f2006-12-08 02:39:04 -08001903static int sx_ioctl(struct tty_struct *tty, struct file *filp,
1904 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905{
1906 int rc;
1907 struct sx_port *port = tty->driver_data;
1908 void __user *argp = (void __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
1910 /* func_enter2(); */
1911
1912 rc = 0;
Arnd Bergmannec79d602010-06-01 22:53:01 +02001913 tty_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 case TIOCGSERIAL:
1916 rc = gs_getserial(&port->gs, argp);
1917 break;
1918 case TIOCSSERIAL:
1919 rc = gs_setserial(&port->gs, argp);
1920 break;
1921 default:
1922 rc = -ENOIOCTLCMD;
1923 break;
1924 }
Arnd Bergmannec79d602010-06-01 22:53:01 +02001925 tty_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926
1927 /* func_exit(); */
1928 return rc;
1929}
1930
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931/* The throttle/unthrottle scheme for the Specialix card is different
1932 * from other drivers and deserves some explanation.
1933 * The Specialix hardware takes care of XON/XOFF
1934 * and CTS/RTS flow control itself. This means that all we have to
1935 * do when signalled by the upper tty layer to throttle/unthrottle is
1936 * to make a note of it here. When we come to read characters from the
1937 * rx buffers on the card (sx_receive_chars()) we look to see if the
1938 * upper layer can accept more (as noted here in sx_rx_throt[]).
1939 * If it can't we simply don't remove chars from the cards buffer.
1940 * When the tty layer can accept chars, we again note that here and when
1941 * sx_receive_chars() is called it will remove them from the cards buffer.
1942 * The card will notice that a ports buffer has drained below some low
1943 * water mark and will unflow control the line itself, using whatever
1944 * flow control scheme is in use for that port. -- Simon Allen
1945 */
1946
Jiri Slaby15b611f2006-12-08 02:39:04 -08001947static void sx_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948{
Alan Coxc9f19e92009-01-02 13:47:26 +00001949 struct sx_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
1951 func_enter2();
1952 /* If the port is using any type of input flow
1953 * control then throttle the port.
1954 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001955 if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
Alan Coxb5391e22008-07-16 21:55:20 +01001956 port->gs.port.flags |= SX_RX_THROTTLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 }
1958 func_exit();
1959}
1960
Jiri Slaby15b611f2006-12-08 02:39:04 -08001961static void sx_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962{
Alan Coxc9f19e92009-01-02 13:47:26 +00001963 struct sx_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964
1965 func_enter2();
1966 /* Always unthrottle even if flow control is not enabled on
1967 * this port in case we disabled flow control while the port
1968 * was throttled
1969 */
Alan Coxb5391e22008-07-16 21:55:20 +01001970 port->gs.port.flags &= ~SX_RX_THROTTLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 func_exit();
1972 return;
1973}
1974
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975/* ********************************************************************** *
1976 * Here are the initialization routines. *
1977 * ********************************************************************** */
1978
Jiri Slaby15b611f2006-12-08 02:39:04 -08001979static int sx_init_board(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980{
1981 int addr;
1982 int chans;
1983 int type;
1984
1985 func_enter();
1986
1987 /* This is preceded by downloading the download code. */
1988
1989 board->flags |= SX_BOARD_INITIALIZED;
1990
Jiri Slaby15b611f2006-12-08 02:39:04 -08001991 if (read_sx_byte(board, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 /* CF boards may need this. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001993 write_sx_byte(board, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
1995 /* This resets the processor again, to make sure it didn't do any
1996 foolish things while we were downloading the image */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001997 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 return 0;
1999
Jiri Slaby15b611f2006-12-08 02:39:04 -08002000 sx_start_board(board);
2001 udelay(10);
2002 if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
2003 printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 return 0;
2005 }
2006
2007 /* Ok. So now the processor on the card is running. It gathered
2008 some info for us... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002009 sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
2010 if (sx_debug & SX_DEBUG_INIT)
2011 my_hd_io(board->base, 0x10);
2012 sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
2013 if (sx_debug & SX_DEBUG_INIT)
2014 my_hd_io(board->base + 0x80, 0x30);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015
Jiri Slaby15b611f2006-12-08 02:39:04 -08002016 sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
2017 "V%x.%02x,\n",
2018 read_sx_byte(board, 0), read_sx_byte(board, 1),
2019 read_sx_byte(board, 5), read_sx_byte(board, 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
Jiri Slaby15b611f2006-12-08 02:39:04 -08002021 if (read_sx_byte(board, 0) == 0xff) {
2022 printk(KERN_INFO "sx: No modules found. Sorry.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 board->nports = 0;
2024 return 0;
2025 }
2026
2027 chans = 0;
2028
2029 if (IS_SX_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002030 sx_write_board_word(board, cc_int_count, sx_maxints);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 } else {
2032 if (sx_maxints)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002033 sx_write_board_word(board, cc_int_count,
2034 SI_PROCESSOR_CLOCK / 8 / sx_maxints);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 }
2036
2037 /* grab the first module type... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002038 /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
2039 board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
2040 mc_chip));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
2042 /* XXX byteorder */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002043 for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
2044 type = sx_read_module_byte(board, addr, mc_chip);
2045 sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
2046 addr, read_sx_byte(board, addr + 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047
Jiri Slaby15b611f2006-12-08 02:39:04 -08002048 chans += sx_read_module_byte(board, addr, mc_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
Jiri Slaby15b611f2006-12-08 02:39:04 -08002050 sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
2051 "panels\n",
2052 mod_type_s(type),
2053 pan_type_s(sx_read_module_byte(board, addr,
2054 mc_mods) & 0xf),
2055 pan_type_s(sx_read_module_byte(board, addr,
2056 mc_mods) >> 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
Jiri Slaby15b611f2006-12-08 02:39:04 -08002058 sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
2059 "version: %x\n",
2060 sx_read_module_byte(board, addr, mc_rev1),
2061 sx_read_module_byte(board, addr, mc_rev2),
2062 sx_read_module_byte(board, addr, mc_mtaasic_rev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
2064 /* The following combinations are illegal: It should theoretically
2065 work, but timing problems make the bus HANG. */
2066
Jiri Slaby15b611f2006-12-08 02:39:04 -08002067 if (mod_compat_type(type) != board->ta_type) {
2068 printk(KERN_ERR "sx: This is an invalid "
2069 "configuration.\nDon't mix TA/MTA/SXDC on the "
2070 "same hostadapter.\n");
2071 chans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 break;
2073 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002074 if ((IS_EISA_BOARD(board) ||
2075 IS_SI_BOARD(board)) &&
2076 (mod_compat_type(type) == 4)) {
2077 printk(KERN_ERR "sx: This is an invalid "
2078 "configuration.\nDon't use SXDCs on an SI/XIO "
2079 "adapter.\n");
2080 chans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 break;
2082 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002083#if 0 /* Problem fixed: firmware 3.05 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 if (IS_SX_BOARD(board) && (type == TA8)) {
2085 /* There are some issues with the firmware and the DCD/RTS
2086 lines. It might work if you tie them together or something.
Jiri Slaby15b611f2006-12-08 02:39:04 -08002087 It might also work if you get a newer sx_firmware. Therefore
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 this is just a warning. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002089 printk(KERN_WARNING
2090 "sx: The SX host doesn't work too well "
2091 "with the TA8 adapters.\nSpecialix is working on it.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 }
2093#endif
2094 }
2095
2096 if (chans) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002097 if (board->irq > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 /* fixed irq, probably PCI */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002099 if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */
2100 if (request_irq(board->irq, sx_interrupt,
2101 IRQF_SHARED | IRQF_DISABLED,
2102 "sx", board)) {
2103 printk(KERN_ERR "sx: Cannot allocate "
2104 "irq %d.\n", board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 board->irq = 0;
2106 }
2107 } else
2108 board->irq = 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002109 } else if (board->irq < 0 && sx_irqmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 /* auto-allocate irq */
2111 int irqnr;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002112 int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
2113 SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
2114 for (irqnr = 15; irqnr > 0; irqnr--)
2115 if (irqmask & (1 << irqnr))
2116 if (!request_irq(irqnr, sx_interrupt,
2117 IRQF_SHARED | IRQF_DISABLED,
2118 "sx", board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002120 if (!irqnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
2122 board->irq = irqnr;
2123 } else
2124 board->irq = 0;
2125
2126 if (board->irq) {
2127 /* Found a valid interrupt, start up interrupts! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002128 sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
2129 board->irq);
2130 sx_start_interrupts(board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 board->poll = sx_slowpoll;
2132 board->flags |= SX_IRQ_ALLOCATED;
2133 } else {
2134 /* no irq: setup board for polled operation */
2135 board->poll = sx_poll;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002136 sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
2137 board->poll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 }
2139
Jiri Slaby15b611f2006-12-08 02:39:04 -08002140 /* The timer should be initialized anyway: That way we can
2141 safely del_timer it when the module is unloaded. */
Jiri Slabyc9594642006-12-08 02:39:05 -08002142 setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143
Jiri Slabyc9594642006-12-08 02:39:05 -08002144 if (board->poll)
2145 mod_timer(&board->timer, jiffies + board->poll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 } else {
2147 board->irq = 0;
2148 }
2149
2150 board->nports = chans;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002151 sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152
2153 func_exit();
2154 return chans;
2155}
2156
Jiri Slabycda52652006-12-08 02:39:00 -08002157static void __devinit printheader(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158{
2159 static int header_printed;
2160
2161 if (!header_printed) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002162 printk(KERN_INFO "Specialix SX driver "
2163 "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
2164 printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 header_printed = 1;
2166 }
2167}
2168
Jiri Slaby15b611f2006-12-08 02:39:04 -08002169static int __devinit probe_sx(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170{
2171 struct vpd_prom vpdp;
2172 char *p;
2173 int i;
2174
2175 func_enter();
2176
Jiri Slaby15b611f2006-12-08 02:39:04 -08002177 if (!IS_CF_BOARD(board)) {
2178 sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
2179 board->base + SX_VPD_ROM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
2181 if (sx_debug & SX_DEBUG_PROBE)
2182 my_hd_io(board->base + SX_VPD_ROM, 0x40);
2183
Jiri Slaby15b611f2006-12-08 02:39:04 -08002184 p = (char *)&vpdp;
2185 for (i = 0; i < sizeof(struct vpd_prom); i++)
2186 *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187
2188 if (sx_debug & SX_DEBUG_PROBE)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002189 my_hd(&vpdp, 0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Jiri Slaby15b611f2006-12-08 02:39:04 -08002191 sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192
Jiri Slaby15b611f2006-12-08 02:39:04 -08002193 if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
2194 sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
2195 "'%s'\n", vpdp.identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 return 0;
2197 }
2198 }
2199
Jiri Slaby15b611f2006-12-08 02:39:04 -08002200 printheader();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201
Jiri Slaby15b611f2006-12-08 02:39:04 -08002202 if (!IS_CF_BOARD(board)) {
2203 printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
2204 board->hw_base);
2205 printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
2206 "uniq ID:%08x, ",
2207 vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
2208 printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209
Jiri Slaby15b611f2006-12-08 02:39:04 -08002210 if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
2211 SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
2212 SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
2213 /* This might be a bit harsh. This was the primary
2214 reason the SX/ISA card didn't work at first... */
2215 printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
2216 "card. Sorry: giving up.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 return (0);
2218 }
2219
Jiri Slaby15b611f2006-12-08 02:39:04 -08002220 if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
2221 SX_ISA_UNIQUEID1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 if (((unsigned long)board->hw_base) & 0x8000) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002223 printk(KERN_WARNING "sx: Warning: There may be "
2224 "hardware problems with the card at "
2225 "%lx.\n", board->hw_base);
2226 printk(KERN_WARNING "sx: Read sx.txt for more "
2227 "info.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 }
2229 }
2230 }
2231
2232 board->nports = -1;
2233
2234 /* This resets the processor, and keeps it off the bus. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002235 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 return 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002237 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 func_exit();
2240 return 1;
2241}
2242
Jiri Slaby927a6f92006-12-08 02:39:02 -08002243#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
2245/* Specialix probes for this card at 32k increments from 640k to 16M.
2246 I consider machines with less than 16M unlikely nowadays, so I'm
2247 not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA
2248 card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves
2249 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
2250
Jiri Slaby15b611f2006-12-08 02:39:04 -08002251static int __devinit probe_si(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252{
2253 int i;
2254
2255 func_enter();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002256 sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
2257 "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
2259 if (sx_debug & SX_DEBUG_PROBE)
2260 my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
2261
2262 if (!IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002263 if (IS_SI1_BOARD(board)) {
2264 for (i = 0; i < 8; i++) {
2265 write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
2266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002268 for (i = 0; i < 8; i++) {
2269 if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
2270 != i) {
2271 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 return 0;
2273 }
2274 }
2275 }
2276
2277 /* Now we're pretty much convinced that there is an SI board here,
2278 but to prevent trouble, we'd better double check that we don't
2279 have an SI1 board when we're probing for an SI2 board.... */
2280
Jiri Slaby15b611f2006-12-08 02:39:04 -08002281 write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
2282 if (IS_SI1_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 /* This should be an SI1 board, which has this
2284 location writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002285 if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
2286 func_exit();
2287 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 } else {
2290 /* This should be an SI2 board, which has the bottom
2291 3 bits non-writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002292 if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
2293 func_exit();
2294 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 }
2297
2298 /* Now we're pretty much convinced that there is an SI board here,
2299 but to prevent trouble, we'd better double check that we don't
2300 have an SI1 board when we're probing for an SI2 board.... */
2301
Jiri Slaby15b611f2006-12-08 02:39:04 -08002302 write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
2303 if (IS_SI1_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 /* This should be an SI1 board, which has this
2305 location writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002306 if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 func_exit();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002308 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 } else {
2311 /* This should be an SI2 board, which has the bottom
2312 3 bits non-writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002313 if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
2314 func_exit();
2315 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 }
2318
Jiri Slaby15b611f2006-12-08 02:39:04 -08002319 printheader();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320
Jiri Slaby15b611f2006-12-08 02:39:04 -08002321 printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 /* Compared to the SX boards, it is a complete guess as to what
Jiri Slaby15b611f2006-12-08 02:39:04 -08002323 this card is up to... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324
2325 board->nports = -1;
2326
2327 /* This resets the processor, and keeps it off the bus. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002328 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 return 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002330 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 func_exit();
2333 return 1;
2334}
Jiri Slaby927a6f92006-12-08 02:39:02 -08002335#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002337static const struct tty_operations sx_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 .break_ctl = sx_break,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002339 .open = sx_open,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 .close = gs_close,
2341 .write = gs_write,
2342 .put_char = gs_put_char,
2343 .flush_chars = gs_flush_chars,
2344 .write_room = gs_write_room,
2345 .chars_in_buffer = gs_chars_in_buffer,
2346 .flush_buffer = gs_flush_buffer,
2347 .ioctl = sx_ioctl,
2348 .throttle = sx_throttle,
2349 .unthrottle = sx_unthrottle,
2350 .set_termios = gs_set_termios,
2351 .stop = gs_stop,
2352 .start = gs_start,
2353 .hangup = gs_hangup,
2354 .tiocmget = sx_tiocmget,
2355 .tiocmset = sx_tiocmset,
2356};
2357
Alan Cox31f35932009-01-02 13:45:05 +00002358static const struct tty_port_operations sx_port_ops = {
2359 .carrier_raised = sx_carrier_raised,
2360};
2361
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362static int sx_init_drivers(void)
2363{
2364 int error;
2365
2366 func_enter();
2367
2368 sx_driver = alloc_tty_driver(sx_nports);
2369 if (!sx_driver)
2370 return 1;
2371 sx_driver->owner = THIS_MODULE;
2372 sx_driver->driver_name = "specialix_sx";
2373 sx_driver->name = "ttyX";
2374 sx_driver->major = SX_NORMAL_MAJOR;
2375 sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
2376 sx_driver->subtype = SERIAL_TYPE_NORMAL;
2377 sx_driver->init_termios = tty_std_termios;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002378 sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Alan Cox606d0992006-12-08 02:38:45 -08002379 sx_driver->init_termios.c_ispeed = 9600;
2380 sx_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 sx_driver->flags = TTY_DRIVER_REAL_RAW;
2382 tty_set_operations(sx_driver, &sx_ops);
2383
2384 if ((error = tty_register_driver(sx_driver))) {
2385 put_tty_driver(sx_driver);
2386 printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
Jiri Slaby15b611f2006-12-08 02:39:04 -08002387 error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 return 1;
2389 }
2390 func_exit();
2391 return 0;
2392}
2393
Jiri Slaby15b611f2006-12-08 02:39:04 -08002394static int sx_init_portstructs(int nboards, int nports)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395{
2396 struct sx_board *board;
2397 struct sx_port *port;
2398 int i, j;
2399 int addr, chans;
2400 int portno;
2401
2402 func_enter();
2403
2404 /* Many drivers statically allocate the maximum number of ports
Jiri Slaby15b611f2006-12-08 02:39:04 -08002405 There is no reason not to allocate them dynamically.
2406 Is there? -- REW */
Jiri Slaby4a7cb692006-12-08 02:38:59 -08002407 sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 if (!sx_ports)
2409 return -ENOMEM;
2410
2411 port = sx_ports;
2412 for (i = 0; i < nboards; i++) {
2413 board = &boards[i];
2414 board->ports = port;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002415 for (j = 0; j < boards[i].nports; j++) {
2416 sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
Alan Cox44b7d1b2008-07-16 21:57:18 +01002417 tty_port_init(&port->gs.port);
Alan Cox31f35932009-01-02 13:45:05 +00002418 port->gs.port.ops = &sx_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 port->gs.magic = SX_MAGIC;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002420 port->gs.close_delay = HZ / 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 port->gs.closing_wait = 30 * HZ;
2422 port->board = board;
2423 port->gs.rd = &sx_real_driver;
2424#ifdef NEW_WRITE_LOCKING
Ingo Molnar81861d72006-03-23 03:00:44 -08002425 port->gs.port_write_mutex = MUTEX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426#endif
Ingo Molnar34af9462006-06-27 02:53:55 -07002427 spin_lock_init(&port->gs.driver_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 /*
2429 * Initializing wait queue
2430 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 port++;
2432 }
2433 }
2434
2435 port = sx_ports;
2436 portno = 0;
2437 for (i = 0; i < nboards; i++) {
2438 board = &boards[i];
2439 board->port_base = portno;
2440 /* Possibly the configuration was rejected. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002441 sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
2442 board->nports);
2443 if (board->nports <= 0)
2444 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 /* XXX byteorder ?? */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002446 for (addr = 0x80; addr != 0;
2447 addr = read_sx_word(board, addr) & 0x7fff) {
2448 chans = sx_read_module_byte(board, addr, mc_type);
2449 sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
2450 "channels\n", addr, chans);
2451 sx_dprintk(SX_DEBUG_PROBE, "Port at");
2452 for (j = 0; j < chans; j++) {
2453 /* The "sx-way" is the way it SHOULD be done.
2454 That way in the future, the firmware may for
2455 example pack the structures a bit more
2456 efficient. Neil tells me it isn't going to
2457 happen anytime soon though. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 if (IS_SX_BOARD(board))
Jiri Slaby15b611f2006-12-08 02:39:04 -08002459 port->ch_base = sx_read_module_word(
2460 board, addr + j * 2,
2461 mc_chan_pointer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 else
Jiri Slaby15b611f2006-12-08 02:39:04 -08002463 port->ch_base = addr + 0x100 + 0x300 *j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
Jiri Slaby15b611f2006-12-08 02:39:04 -08002465 sx_dprintk(SX_DEBUG_PROBE, " %x",
2466 port->ch_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 port->line = portno++;
2468 port++;
2469 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002470 sx_dprintk(SX_DEBUG_PROBE, "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 }
2472 /* This has to be done earlier. */
2473 /* board->flags |= SX_BOARD_INITIALIZED; */
2474 }
2475
2476 func_exit();
2477 return 0;
2478}
2479
Jiri Slaby18f813e2006-12-08 02:39:01 -08002480static unsigned int sx_find_free_board(void)
2481{
2482 unsigned int i;
2483
Jiri Slaby15b611f2006-12-08 02:39:04 -08002484 for (i = 0; i < SX_NBOARDS; i++)
Jiri Slaby18f813e2006-12-08 02:39:01 -08002485 if (!(boards[i].flags & SX_BOARD_PRESENT))
2486 break;
2487
2488 return i;
2489}
2490
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491static void __exit sx_release_drivers(void)
2492{
2493 func_enter();
2494 tty_unregister_driver(sx_driver);
2495 put_tty_driver(sx_driver);
2496 func_exit();
2497}
2498
Jiri Slaby39103492006-12-08 02:39:07 -08002499static void __devexit sx_remove_card(struct sx_board *board,
2500 struct pci_dev *pdev)
Jiri Slaby18f813e2006-12-08 02:39:01 -08002501{
2502 if (board->flags & SX_BOARD_INITIALIZED) {
2503 /* The board should stop messing with us. (actually I mean the
2504 interrupt) */
2505 sx_reset(board);
2506 if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
2507 free_irq(board->irq, board);
2508
2509 /* It is safe/allowed to del_timer a non-active timer */
2510 del_timer(&board->timer);
Jiri Slaby30f42182006-12-08 02:39:08 -08002511 if (pdev) {
Jiri Slaby3468a332006-12-13 00:34:20 -08002512#ifdef CONFIG_PCI
Jiri Slabyda1cfe12008-10-18 20:27:44 -07002513 iounmap(board->base2);
Jiri Slaby30f42182006-12-08 02:39:08 -08002514 pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
Jiri Slaby3468a332006-12-13 00:34:20 -08002515#endif
Jiri Slaby30f42182006-12-08 02:39:08 -08002516 } else {
Jiri Slaby39103492006-12-08 02:39:07 -08002517 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002518 release_region(board->hw_base, board->hw_len);
2519 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002520
Jiri Slaby15b611f2006-12-08 02:39:04 -08002521 board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002522 }
2523}
2524
2525#ifdef CONFIG_EISA
2526
2527static int __devinit sx_eisa_probe(struct device *dev)
2528{
2529 struct eisa_device *edev = to_eisa_device(dev);
2530 struct sx_board *board;
2531 unsigned long eisa_slot = edev->base_addr;
2532 unsigned int i;
2533 int retval = -EIO;
2534
Jiri Slaby42f63842006-12-08 02:39:03 -08002535 mutex_lock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002536 i = sx_find_free_board();
Jiri Slaby42f63842006-12-08 02:39:03 -08002537 if (i == SX_NBOARDS) {
2538 mutex_unlock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002539 goto err;
Jiri Slaby42f63842006-12-08 02:39:03 -08002540 }
2541 board = &boards[i];
2542 board->flags |= SX_BOARD_PRESENT;
2543 mutex_unlock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002544
2545 dev_info(dev, "XIO : Signature found in EISA slot %lu, "
Jiri Slaby15b611f2006-12-08 02:39:04 -08002546 "Product %d Rev %d (REPORT THIS TO LKLM)\n",
2547 eisa_slot >> 12,
2548 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
2549 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
Jiri Slaby18f813e2006-12-08 02:39:01 -08002550
Jiri Slaby18f813e2006-12-08 02:39:01 -08002551 board->eisa_base = eisa_slot;
2552 board->flags &= ~SX_BOARD_TYPE;
2553 board->flags |= SI_EISA_BOARD;
2554
2555 board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
Jiri Slaby15b611f2006-12-08 02:39:04 -08002556 inb(eisa_slot + 0xc00)) << 16;
Jiri Slaby30f42182006-12-08 02:39:08 -08002557 board->hw_len = SI2_EISA_WINDOW_LEN;
2558 if (!request_region(board->hw_base, board->hw_len, "sx")) {
2559 dev_err(dev, "can't request region\n");
2560 goto err_flag;
2561 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002562 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002563 board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
Jiri Slaby30f42182006-12-08 02:39:08 -08002564 if (!board->base) {
2565 dev_err(dev, "can't remap memory\n");
2566 goto err_reg;
2567 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002568
2569 sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
2570 sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
2571 board->irq = inb(eisa_slot + 0xc02) >> 4;
2572 sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
2573
2574 if (!probe_si(board))
2575 goto err_unmap;
2576
2577 dev_set_drvdata(dev, board);
2578
2579 return 0;
2580err_unmap:
2581 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002582err_reg:
2583 release_region(board->hw_base, board->hw_len);
2584err_flag:
Jiri Slaby42f63842006-12-08 02:39:03 -08002585 board->flags &= ~SX_BOARD_PRESENT;
Jiri Slaby18f813e2006-12-08 02:39:01 -08002586err:
2587 return retval;
2588}
2589
2590static int __devexit sx_eisa_remove(struct device *dev)
2591{
2592 struct sx_board *board = dev_get_drvdata(dev);
2593
Jiri Slaby39103492006-12-08 02:39:07 -08002594 sx_remove_card(board, NULL);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002595
2596 return 0;
2597}
2598
2599static struct eisa_device_id sx_eisa_tbl[] = {
2600 { "SLX" },
2601 { "" }
2602};
Jiri Slaby15b611f2006-12-08 02:39:04 -08002603
Jiri Slaby18f813e2006-12-08 02:39:01 -08002604MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
2605
2606static struct eisa_driver sx_eisadriver = {
2607 .id_table = sx_eisa_tbl,
2608 .driver = {
2609 .name = "sx",
2610 .probe = sx_eisa_probe,
2611 .remove = __devexit_p(sx_eisa_remove),
2612 }
2613};
2614
2615#endif
2616
Jiri Slaby3468a332006-12-13 00:34:20 -08002617#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 /********************************************************
2619 * Setting bit 17 in the CNTRL register of the PLX 9050 *
2620 * chip forces a retry on writes while a read is pending.*
2621 * This is to prevent the card locking up on Intel Xeon *
2622 * multiprocessor systems with the NX chipset. -- NV *
2623 ********************************************************/
2624
2625/* Newer cards are produced with this bit set from the configuration
2626 EEprom. As the bit is read/write for the CPU, we can fix it here,
2627 if we detect that it isn't set correctly. -- REW */
2628
Jiri Slabycda52652006-12-08 02:39:00 -08002629static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630{
2631 unsigned int hwbase;
2632 void __iomem *rebase;
2633 unsigned int t;
2634
Jiri Slaby15b611f2006-12-08 02:39:04 -08002635#define CNTRL_REG_OFFSET 0x50
2636#define CNTRL_REG_GOODVALUE 0x18260000
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637
2638 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
2639 hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
Alan Cox24cb2332008-04-30 00:54:19 -07002640 rebase = ioremap_nocache(hwbase, 0x80);
Jiri Slaby15b611f2006-12-08 02:39:04 -08002641 t = readl(rebase + CNTRL_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 if (t != CNTRL_REG_GOODVALUE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002643 printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
2644 "%08x\n", t, CNTRL_REG_GOODVALUE);
2645 writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 }
2647 iounmap(rebase);
2648}
Jiri Slaby3468a332006-12-13 00:34:20 -08002649#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650
Jiri Slaby5572e102006-12-08 02:38:58 -08002651static int __devinit sx_pci_probe(struct pci_dev *pdev,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002652 const struct pci_device_id *ent)
Jiri Slaby5572e102006-12-08 02:38:58 -08002653{
Jiri Slaby3468a332006-12-13 00:34:20 -08002654#ifdef CONFIG_PCI
Jiri Slaby5572e102006-12-08 02:38:58 -08002655 struct sx_board *board;
Jiri Slaby39103492006-12-08 02:39:07 -08002656 unsigned int i, reg;
Jiri Slaby5572e102006-12-08 02:38:58 -08002657 int retval = -EIO;
2658
Jiri Slaby42f63842006-12-08 02:39:03 -08002659 mutex_lock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002660 i = sx_find_free_board();
Jiri Slaby42f63842006-12-08 02:39:03 -08002661 if (i == SX_NBOARDS) {
2662 mutex_unlock(&sx_boards_lock);
Jiri Slaby5572e102006-12-08 02:38:58 -08002663 goto err;
Jiri Slaby42f63842006-12-08 02:39:03 -08002664 }
2665 board = &boards[i];
2666 board->flags |= SX_BOARD_PRESENT;
2667 mutex_unlock(&sx_boards_lock);
Jiri Slaby5572e102006-12-08 02:38:58 -08002668
2669 retval = pci_enable_device(pdev);
2670 if (retval)
Jiri Slaby42f63842006-12-08 02:39:03 -08002671 goto err_flag;
Jiri Slaby5572e102006-12-08 02:38:58 -08002672
2673 board->flags &= ~SX_BOARD_TYPE;
2674 board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
Jiri Slaby15b611f2006-12-08 02:39:04 -08002675 SX_CFPCI_BOARD;
Jiri Slaby5572e102006-12-08 02:38:58 -08002676
2677 /* CF boards use base address 3.... */
Jiri Slaby39103492006-12-08 02:39:07 -08002678 reg = IS_CF_BOARD(board) ? 3 : 2;
Jiri Slaby30f42182006-12-08 02:39:08 -08002679 retval = pci_request_region(pdev, reg, "sx");
2680 if (retval) {
2681 dev_err(&pdev->dev, "can't request region\n");
2682 goto err_flag;
2683 }
Jiri Slaby39103492006-12-08 02:39:07 -08002684 board->hw_base = pci_resource_start(pdev, reg);
Jiri Slaby5572e102006-12-08 02:38:58 -08002685 board->base2 =
Jiri Slabyda1cfe12008-10-18 20:27:44 -07002686 board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board));
Jiri Slaby5572e102006-12-08 02:38:58 -08002687 if (!board->base) {
2688 dev_err(&pdev->dev, "ioremap failed\n");
Jiri Slaby30f42182006-12-08 02:39:08 -08002689 goto err_reg;
Jiri Slaby5572e102006-12-08 02:38:58 -08002690 }
2691
2692 /* Most of the stuff on the CF board is offset by 0x18000 .... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002693 if (IS_CF_BOARD(board))
Jiri Slaby5572e102006-12-08 02:38:58 -08002694 board->base += 0x18000;
2695
2696 board->irq = pdev->irq;
2697
2698 dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002699 board->irq, board->flags);
Jiri Slaby5572e102006-12-08 02:38:58 -08002700
2701 if (!probe_sx(board)) {
2702 retval = -EIO;
2703 goto err_unmap;
2704 }
2705
2706 fix_sx_pci(pdev, board);
2707
2708 pci_set_drvdata(pdev, board);
2709
2710 return 0;
2711err_unmap:
Jiri Slabyda1cfe12008-10-18 20:27:44 -07002712 iounmap(board->base2);
Jiri Slaby30f42182006-12-08 02:39:08 -08002713err_reg:
2714 pci_release_region(pdev, reg);
Jiri Slaby42f63842006-12-08 02:39:03 -08002715err_flag:
2716 board->flags &= ~SX_BOARD_PRESENT;
Jiri Slaby5572e102006-12-08 02:38:58 -08002717err:
2718 return retval;
Jiri Slaby3468a332006-12-13 00:34:20 -08002719#else
2720 return -ENODEV;
2721#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002722}
2723
2724static void __devexit sx_pci_remove(struct pci_dev *pdev)
2725{
2726 struct sx_board *board = pci_get_drvdata(pdev);
2727
Jiri Slaby39103492006-12-08 02:39:07 -08002728 sx_remove_card(board, pdev);
Jiri Slaby5572e102006-12-08 02:38:58 -08002729}
2730
2731/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
2732 its because the standard requires it. So check for SUBVENDOR_ID. */
2733static struct pci_device_id sx_pci_tbl[] = {
2734 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
Jiri Slabyc14d4442007-07-10 17:22:25 -07002735 .subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
Jiri Slaby5572e102006-12-08 02:38:58 -08002736 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
Jiri Slabyc14d4442007-07-10 17:22:25 -07002737 .subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
Jiri Slaby5572e102006-12-08 02:38:58 -08002738 { 0 }
2739};
Jiri Slaby15b611f2006-12-08 02:39:04 -08002740
Jiri Slaby5572e102006-12-08 02:38:58 -08002741MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
2742
2743static struct pci_driver sx_pcidriver = {
2744 .name = "sx",
2745 .id_table = sx_pci_tbl,
2746 .probe = sx_pci_probe,
2747 .remove = __devexit_p(sx_pci_remove)
2748};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749
Jiri Slaby15b611f2006-12-08 02:39:04 -08002750static int __init sx_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751{
Jiri Slaby18f813e2006-12-08 02:39:01 -08002752#ifdef CONFIG_EISA
2753 int retval1;
2754#endif
Jiri Slaby927a6f92006-12-08 02:39:02 -08002755#ifdef CONFIG_ISA
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 struct sx_board *board;
Jiri Slaby927a6f92006-12-08 02:39:02 -08002757 unsigned int i;
2758#endif
2759 unsigned int found = 0;
2760 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 func_enter();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002763 sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
2764 sx_debug);
2765 if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
2766 printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
2767 "value. Assuming -1.\n(%p)\n", &sx_debug);
2768 sx_debug = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 }
2770
2771 if (misc_register(&sx_fw_device) < 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002772 printk(KERN_ERR "SX: Unable to register firmware loader "
2773 "driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 return -EIO;
2775 }
Jiri Slaby927a6f92006-12-08 02:39:02 -08002776#ifdef CONFIG_ISA
Jiri Slaby15b611f2006-12-08 02:39:04 -08002777 for (i = 0; i < NR_SX_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 board = &boards[found];
2779 board->hw_base = sx_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002780 board->hw_len = SX_WINDOW_LEN;
2781 if (!request_region(board->hw_base, board->hw_len, "sx"))
2782 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002784 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002785 if (!board->base)
2786 goto err_sx_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002788 board->flags |= SX_ISA_BOARD;
2789 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790
Jiri Slaby15b611f2006-12-08 02:39:04 -08002791 if (probe_sx(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002792 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 found++;
2794 } else {
2795 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002796err_sx_reg:
2797 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 }
2799 }
2800
Jiri Slaby15b611f2006-12-08 02:39:04 -08002801 for (i = 0; i < NR_SI_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 board = &boards[found];
2803 board->hw_base = si_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002804 board->hw_len = SI2_ISA_WINDOW_LEN;
2805 if (!request_region(board->hw_base, board->hw_len, "sx"))
2806 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002808 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002809 if (!board->base)
2810 goto err_si_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002812 board->flags |= SI_ISA_BOARD;
2813 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
Jiri Slaby15b611f2006-12-08 02:39:04 -08002815 if (probe_si(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002816 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 found++;
2818 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002819 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002820err_si_reg:
2821 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 }
2823 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002824 for (i = 0; i < NR_SI1_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 board = &boards[found];
2826 board->hw_base = si1_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002827 board->hw_len = SI1_ISA_WINDOW_LEN;
2828 if (!request_region(board->hw_base, board->hw_len, "sx"))
2829 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002831 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002832 if (!board->base)
2833 goto err_si1_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002835 board->flags |= SI1_ISA_BOARD;
2836 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837
Jiri Slaby15b611f2006-12-08 02:39:04 -08002838 if (probe_si(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002839 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 found++;
2841 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002842 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002843err_si1_reg:
2844 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 }
2846 }
Jiri Slaby927a6f92006-12-08 02:39:02 -08002847#endif
Jiri Slaby18f813e2006-12-08 02:39:01 -08002848#ifdef CONFIG_EISA
2849 retval1 = eisa_driver_register(&sx_eisadriver);
2850#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002851 retval = pci_register_driver(&sx_pcidriver);
2852
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853 if (found) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002854 printk(KERN_INFO "sx: total of %d boards detected.\n", found);
Jiri Slaby5572e102006-12-08 02:38:58 -08002855 retval = 0;
2856 } else if (retval) {
Jiri Slaby18f813e2006-12-08 02:39:01 -08002857#ifdef CONFIG_EISA
Jiri Slaby7eb99762006-12-08 02:39:06 -08002858 retval = retval1;
Jiri Slaby18f813e2006-12-08 02:39:01 -08002859 if (retval1)
2860#endif
Jiri Slaby15b611f2006-12-08 02:39:04 -08002861 misc_deregister(&sx_fw_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 }
2863
2864 func_exit();
Jiri Slaby5572e102006-12-08 02:38:58 -08002865 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866}
2867
Jiri Slaby15b611f2006-12-08 02:39:04 -08002868static void __exit sx_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869{
Jiri Slaby15b611f2006-12-08 02:39:04 -08002870 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871
2872 func_enter();
Jiri Slaby18f813e2006-12-08 02:39:01 -08002873#ifdef CONFIG_EISA
2874 eisa_driver_unregister(&sx_eisadriver);
2875#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002876 pci_unregister_driver(&sx_pcidriver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877
Jiri Slaby55e70712006-12-08 02:39:03 -08002878 for (i = 0; i < SX_NBOARDS; i++)
Jiri Slaby39103492006-12-08 02:39:07 -08002879 sx_remove_card(&boards[i], NULL);
Jiri Slaby55e70712006-12-08 02:39:03 -08002880
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 if (misc_deregister(&sx_fw_device) < 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002882 printk(KERN_INFO "sx: couldn't deregister firmware loader "
2883 "device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002885 sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
2886 sx_initialized);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 if (sx_initialized)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002888 sx_release_drivers();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889
Jiri Slaby15b611f2006-12-08 02:39:04 -08002890 kfree(sx_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 func_exit();
2892}
2893
2894module_init(sx_init);
2895module_exit(sx_exit);