blob: 518f2a25d91ec6b1a208c6fe233c505a7395aa47 [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>
219#include <linux/init.h>
220#include <linux/miscdevice.h>
221#include <linux/bitops.h>
222
223#include <asm/io.h>
224#include <asm/uaccess.h>
225
226/* The 3.0.0 version of sxboards/sxwindow.h uses BYTE and WORD.... */
227#define BYTE u8
228#define WORD u16
229
230/* .... but the 3.0.4 version uses _u8 and _u16. */
231#define _u8 u8
232#define _u16 u16
233
234#include "sxboards.h"
235#include "sxwindow.h"
236
237#include <linux/generic_serial.h>
238#include "sx.h"
239
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240/* I don't think that this driver can handle more than 256 ports on
241 one machine. You'll have to increase the number of boards in sx.h
242 if you want more than 4 boards. */
243
244#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
245#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
246#endif
247
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248/* Configurable options:
249 (Don't be too sure that it'll work if you toggle them) */
250
251/* Am I paranoid or not ? ;-) */
252#undef SX_PARANOIA_CHECK
253
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
255 Hz, but it is user configurable. I don't recommend going above 1000
256 Hz. The interrupt ratelimit might trigger if the interrupt is
257 shared with a very active other device. */
258#define IRQ_RATE_LIMIT 20
259
260/* Sharing interrupts is possible now. If the other device wants more
261 than 2000 interrupts per second, we'd gracefully decline further
262 interrupts. That's not what we want. On the other hand, if the
263 other device interrupts 2000 times a second, don't use the SX
264 interrupt. Use polling. */
265#undef IRQ_RATE_LIMIT
266
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267#if 0
268/* Not implemented */
269/*
270 * The following defines are mostly for testing purposes. But if you need
271 * some nice reporting in your syslog, you can define them also.
272 */
273#define SX_REPORT_FIFO
274#define SX_REPORT_OVERRUN
Jiri Slaby15b611f2006-12-08 02:39:04 -0800275#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
277/* Function prototypes */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800278static void sx_disable_tx_interrupts(void *ptr);
279static void sx_enable_tx_interrupts(void *ptr);
280static void sx_disable_rx_interrupts(void *ptr);
281static void sx_enable_rx_interrupts(void *ptr);
Alan Cox31f35932009-01-02 13:45:05 +0000282static int sx_carrier_raised(struct tty_port *port);
Jiri Slaby15b611f2006-12-08 02:39:04 -0800283static void sx_shutdown_port(void *ptr);
284static int sx_set_real_termios(void *ptr);
285static void sx_close(void *ptr);
286static int sx_chars_in_buffer(void *ptr);
287static int sx_init_board(struct sx_board *board);
288static int sx_init_portstructs(int nboards, int nports);
Alan Cox11af7472008-07-25 01:48:15 -0700289static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
290 unsigned long arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291static int sx_init_drivers(void);
292
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293static struct tty_driver *sx_driver;
294
Jiri Slaby42f63842006-12-08 02:39:03 -0800295static DEFINE_MUTEX(sx_boards_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296static struct sx_board boards[SX_NBOARDS];
297static struct sx_port *sx_ports;
298static int sx_initialized;
299static int sx_nports;
300static int sx_debug;
301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302/* You can have the driver poll your card.
303 - Set sx_poll to 1 to poll every timer tick (10ms on Intel).
304 This is used when the card cannot use an interrupt for some reason.
305
306 - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If
307 the driver misses an interrupt (report this if it DOES happen to you!)
308 everything will continue to work....
309 */
310static int sx_poll = 1;
311static int sx_slowpoll;
312
313/* The card limits the number of interrupts per second.
314 At 115k2 "100" should be sufficient.
315 If you're using higher baudrates, you can increase this...
316 */
317
318static int sx_maxints = 100;
319
Jiri Slaby927a6f92006-12-08 02:39:02 -0800320#ifdef CONFIG_ISA
321
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322/* These are the only open spaces in my computer. Yours may have more
323 or less.... -- REW
324 duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
325*/
Jiri Slaby15b611f2006-12-08 02:39:04 -0800326static int sx_probe_addrs[] = {
327 0xc0000, 0xd0000, 0xe0000,
328 0xc8000, 0xd8000, 0xe8000
329};
330static int si_probe_addrs[] = {
331 0xc0000, 0xd0000, 0xe0000,
332 0xc8000, 0xd8000, 0xe8000, 0xa0000
333};
334static int si1_probe_addrs[] = {
335 0xd0000
336};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Tobias Klauserfe971072006-01-09 20:54:02 -0800338#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
339#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
340#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
Jiri Slaby927a6f92006-12-08 02:39:02 -0800342module_param_array(sx_probe_addrs, int, NULL, 0);
343module_param_array(si_probe_addrs, int, NULL, 0);
344#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
346/* Set the mask to all-ones. This alas, only supports 32 interrupts.
347 Some architectures may need more. */
348static int sx_irqmask = -1;
349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350module_param(sx_poll, int, 0);
351module_param(sx_slowpoll, int, 0);
352module_param(sx_maxints, int, 0);
353module_param(sx_debug, int, 0);
354module_param(sx_irqmask, int, 0);
355
356MODULE_LICENSE("GPL");
357
358static struct real_driver sx_real_driver = {
359 sx_disable_tx_interrupts,
360 sx_enable_tx_interrupts,
361 sx_disable_rx_interrupts,
362 sx_enable_rx_interrupts,
Jiri Slaby15b611f2006-12-08 02:39:04 -0800363 sx_shutdown_port,
364 sx_set_real_termios,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 sx_chars_in_buffer,
366 sx_close,
367};
368
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369/*
370 This driver can spew a whole lot of debugging output at you. If you
371 need maximum performance, you should disable the DEBUG define. To
372 aid in debugging in the field, I'm leaving the compile-time debug
373 features enabled, and disable them "runtime". That allows me to
374 instruct people with problems to enable debugging without requiring
375 them to recompile...
376*/
377#define DEBUG
378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379#ifdef DEBUG
Jiri Slaby15b611f2006-12-08 02:39:04 -0800380#define sx_dprintk(f, str...) if (sx_debug & f) printk (str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381#else
Jiri Slaby15b611f2006-12-08 02:39:04 -0800382#define sx_dprintk(f, str...) /* nothing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383#endif
384
Harvey Harrisonbf9d8922008-04-30 00:55:10 -0700385#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
386#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Jiri Slaby15b611f2006-12-08 02:39:04 -0800388#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
Harvey Harrisonbf9d8922008-04-30 00:55:10 -0700389 __func__, port->line)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391/*
392 * Firmware loader driver specific routines
393 *
394 */
395
Arjan van de Ven62322d22006-07-03 00:24:21 -0700396static const struct file_operations sx_fw_fops = {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800397 .owner = THIS_MODULE,
Alan Cox11af7472008-07-25 01:48:15 -0700398 .unlocked_ioctl = sx_fw_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399};
400
401static struct miscdevice sx_fw_device = {
402 SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
403};
404
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405#ifdef SX_PARANOIA_CHECK
406
407/* This doesn't work. Who's paranoid around here? Not me! */
408
Jiri Slaby15b611f2006-12-08 02:39:04 -0800409static inline int sx_paranoia_check(struct sx_port const *port,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 char *name, const char *routine)
411{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800412 static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
413 "number for device %s in %s\n";
414 static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
415 "device %s in %s\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 if (!port) {
418 printk(badinfo, name, routine);
419 return 1;
420 }
421 if (port->magic != SX_MAGIC) {
422 printk(badmagic, name, routine);
423 return 1;
424 }
425
426 return 0;
427}
428#else
429#define sx_paranoia_check(a,b,c) 0
430#endif
431
432/* The timeouts. First try 30 times as fast as possible. Then give
433 the card some time to breathe between accesses. (Otherwise the
434 processor on the card might not be able to access its OWN bus... */
435
436#define TIMEOUT_1 30
437#define TIMEOUT_2 1000000
438
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439#ifdef DEBUG
440static void my_hd_io(void __iomem *p, int len)
441{
442 int i, j, ch;
443 unsigned char __iomem *addr = p;
444
Jiri Slaby15b611f2006-12-08 02:39:04 -0800445 for (i = 0; i < len; i += 16) {
446 printk("%p ", addr + i);
447 for (j = 0; j < 16; j++) {
448 printk("%02x %s", readb(addr + j + i),
449 (j == 7) ? " " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800451 for (j = 0; j < 16; j++) {
452 ch = readb(addr + j + i);
453 printk("%c", (ch < 0x20) ? '.' :
454 ((ch > 0x7f) ? '.' : ch));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800456 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 }
458}
459static void my_hd(void *p, int len)
460{
461 int i, j, ch;
462 unsigned char *addr = p;
463
Jiri Slaby15b611f2006-12-08 02:39:04 -0800464 for (i = 0; i < len; i += 16) {
465 printk("%p ", addr + i);
466 for (j = 0; j < 16; j++) {
467 printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800469 for (j = 0; j < 16; j++) {
470 ch = addr[j + i];
471 printk("%c", (ch < 0x20) ? '.' :
472 ((ch > 0x7f) ? '.' : ch));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800474 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 }
476}
477#endif
478
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479/* This needs redoing for Alpha -- REW -- Done. */
480
Jiri Slaby15b611f2006-12-08 02:39:04 -0800481static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800483 writeb(byte, board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}
485
Jiri Slaby15b611f2006-12-08 02:39:04 -0800486static inline u8 read_sx_byte(struct sx_board *board, int offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800488 return readb(board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489}
490
Jiri Slaby15b611f2006-12-08 02:39:04 -0800491static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800493 writew(word, board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
Jiri Slaby15b611f2006-12-08 02:39:04 -0800496static inline u16 read_sx_word(struct sx_board *board, int offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800498 return readw(board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499}
500
Jiri Slaby15b611f2006-12-08 02:39:04 -0800501static int sx_busy_wait_eq(struct sx_board *board,
502 int offset, int mask, int correctval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503{
504 int i;
505
Jiri Slaby15b611f2006-12-08 02:39:04 -0800506 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Jiri Slaby15b611f2006-12-08 02:39:04 -0800508 for (i = 0; i < TIMEOUT_1; i++)
509 if ((read_sx_byte(board, offset) & mask) == correctval) {
510 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 return 1;
512 }
513
Jiri Slaby15b611f2006-12-08 02:39:04 -0800514 for (i = 0; i < TIMEOUT_2; i++) {
515 if ((read_sx_byte(board, offset) & mask) == correctval) {
516 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 return 1;
518 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800519 udelay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 }
521
Jiri Slaby15b611f2006-12-08 02:39:04 -0800522 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 return 0;
524}
525
Jiri Slaby15b611f2006-12-08 02:39:04 -0800526static int sx_busy_wait_neq(struct sx_board *board,
527 int offset, int mask, int badval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528{
529 int i;
530
Jiri Slaby15b611f2006-12-08 02:39:04 -0800531 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
Jiri Slaby15b611f2006-12-08 02:39:04 -0800533 for (i = 0; i < TIMEOUT_1; i++)
534 if ((read_sx_byte(board, offset) & mask) != badval) {
535 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 return 1;
537 }
538
Jiri Slaby15b611f2006-12-08 02:39:04 -0800539 for (i = 0; i < TIMEOUT_2; i++) {
540 if ((read_sx_byte(board, offset) & mask) != badval) {
541 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 return 1;
543 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800544 udelay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 }
546
Jiri Slaby15b611f2006-12-08 02:39:04 -0800547 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 return 0;
549}
550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551/* 5.6.4 of 6210028 r2.3 */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800552static int sx_reset(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800554 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Jiri Slaby15b611f2006-12-08 02:39:04 -0800556 if (IS_SX_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Jiri Slaby15b611f2006-12-08 02:39:04 -0800558 write_sx_byte(board, SX_CONFIG, 0);
559 write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Jiri Slaby15b611f2006-12-08 02:39:04 -0800561 if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
562 printk(KERN_INFO "sx: Card doesn't respond to "
563 "reset...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 return 0;
565 }
566 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800567 outb(board->irq << 4, board->eisa_base + 0xc02);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800569 write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 } else {
571 /* Gory details of the SI/ISA board */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800572 write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
573 write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
574 write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
575 write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
576 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
577 write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 }
579
Jiri Slaby15b611f2006-12-08 02:39:04 -0800580 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 return 1;
582}
583
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584/* This doesn't work on machines where "NULL" isn't 0 */
585/* If you have one of those, someone will need to write
586 the equivalent of this, which will amount to about 3 lines. I don't
587 want to complicate this right now. -- REW
588 (See, I do write comments every now and then :-) */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800589#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
Jiri Slaby15b611f2006-12-08 02:39:04 -0800591#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))
592#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem))
593#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
595#define sx_write_channel_byte(port, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800596 write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
598#define sx_read_channel_byte(port, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800599 read_sx_byte (port->board, CHAN_OFFSET (port, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
601#define sx_write_channel_word(port, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800602 write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
604#define sx_read_channel_word(port, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800605 read_sx_word (port->board, CHAN_OFFSET (port, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
607#define sx_write_module_byte(board, addr, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800608 write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
610#define sx_read_module_byte(board, addr, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800611 read_sx_byte (board, MODU_OFFSET (board, addr, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
613#define sx_write_module_word(board, addr, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800614 write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
616#define sx_read_module_word(board, addr, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800617 read_sx_word (board, MODU_OFFSET (board, addr, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
619#define sx_write_board_byte(board, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800620 write_sx_byte (board, BRD_OFFSET (board, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622#define sx_read_board_byte(board, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800623 read_sx_byte (board, BRD_OFFSET (board, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
625#define sx_write_board_word(board, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800626 write_sx_word (board, BRD_OFFSET (board, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
628#define sx_read_board_word(board, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800629 read_sx_word (board, BRD_OFFSET (board, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
Jiri Slaby15b611f2006-12-08 02:39:04 -0800631static int sx_start_board(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800633 if (IS_SX_BOARD(board)) {
634 write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 } else if (IS_EISA_BOARD(board)) {
636 write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
Jiri Slaby15b611f2006-12-08 02:39:04 -0800637 outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800639 write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
640 write_sx_byte(board, SI1_ISA_INTCL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 } else {
642 /* Don't bug me about the clear_set.
643 I haven't the foggiest idea what it's about -- REW */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800644 write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
645 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 }
647 return 1;
648}
649
650#define SX_IRQ_REG_VAL(board) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800651 ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
653/* Note. The SX register is write-only. Therefore, we have to enable the
654 bus too. This is a no-op, if you don't mess with this driver... */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800655static int sx_start_interrupts(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656{
657
658 /* Don't call this with board->irq == 0 */
659
660 if (IS_SX_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800661 write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
662 SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800664 inb(board->eisa_base + 0xc03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800666 write_sx_byte(board, SI1_ISA_INTCL, 0);
667 write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 } else {
669 switch (board->irq) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800670 case 11:
671 write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
672 break;
673 case 12:
674 write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
675 break;
676 case 15:
677 write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
678 break;
679 default:
680 printk(KERN_INFO "sx: SI/XIO card doesn't support "
681 "interrupt %d.\n", board->irq);
682 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800684 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
686
687 return 1;
688}
689
Jiri Slaby15b611f2006-12-08 02:39:04 -0800690static int sx_send_command(struct sx_port *port,
691 int command, int mask, int newstat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800693 func_enter2();
694 write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
695 func_exit();
696 return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
697 newstat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
Jiri Slaby15b611f2006-12-08 02:39:04 -0800700static char *mod_type_s(int module_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
702 switch (module_type) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800703 case TA4:
704 return "TA4";
705 case TA8:
706 return "TA8";
707 case TA4_ASIC:
708 return "TA4_ASIC";
709 case TA8_ASIC:
710 return "TA8_ASIC";
711 case MTA_CD1400:
712 return "MTA_CD1400";
713 case SXDC:
714 return "SXDC";
715 default:
716 return "Unknown/invalid";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 }
718}
719
Jiri Slaby15b611f2006-12-08 02:39:04 -0800720static char *pan_type_s(int pan_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721{
722 switch (pan_type) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800723 case MOD_RS232DB25:
724 return "MOD_RS232DB25";
725 case MOD_RS232RJ45:
726 return "MOD_RS232RJ45";
727 case MOD_RS422DB25:
728 return "MOD_RS422DB25";
729 case MOD_PARALLEL:
730 return "MOD_PARALLEL";
731 case MOD_2_RS232DB25:
732 return "MOD_2_RS232DB25";
733 case MOD_2_RS232RJ45:
734 return "MOD_2_RS232RJ45";
735 case MOD_2_RS422DB25:
736 return "MOD_2_RS422DB25";
737 case MOD_RS232DB25MALE:
738 return "MOD_RS232DB25MALE";
739 case MOD_2_PARALLEL:
740 return "MOD_2_PARALLEL";
741 case MOD_BLANK:
742 return "empty";
743 default:
744 return "invalid";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 }
746}
747
Jiri Slaby15b611f2006-12-08 02:39:04 -0800748static int mod_compat_type(int module_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749{
750 return module_type >> 4;
751}
752
753static void sx_reconfigure_port(struct sx_port *port)
754{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800755 if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
756 if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
757 printk(KERN_WARNING "sx: Sent reconfigure command, but "
758 "card didn't react.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 }
760 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800761 sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
762 "port isn't open (%02x).\n",
763 sx_read_channel_byte(port, hi_hstat));
764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765}
766
Jiri Slaby15b611f2006-12-08 02:39:04 -0800767static void sx_setsignals(struct sx_port *port, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768{
769 int t;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800770 func_enter2();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
Jiri Slaby15b611f2006-12-08 02:39:04 -0800772 t = sx_read_channel_byte(port, hi_op);
773 if (dtr >= 0)
774 t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
775 if (rts >= 0)
776 t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
777 sx_write_channel_byte(port, hi_op, t);
778 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779
Jiri Slaby15b611f2006-12-08 02:39:04 -0800780 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781}
782
Jiri Slaby15b611f2006-12-08 02:39:04 -0800783static int sx_getsignals(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800785 int i_stat, o_stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Jiri Slaby15b611f2006-12-08 02:39:04 -0800787 o_stat = sx_read_channel_byte(port, hi_op);
788 i_stat = sx_read_channel_byte(port, hi_ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
Jiri Slaby15b611f2006-12-08 02:39:04 -0800790 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) "
791 "%02x/%02x\n",
792 (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
Alan Cox31f35932009-01-02 13:45:05 +0000793 port->c_dcd, tty_port_carrier_raised(&port->gs.port),
Jiri Slaby15b611f2006-12-08 02:39:04 -0800794 sx_read_channel_byte(port, hi_ip),
795 sx_read_channel_byte(port, hi_state));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
Jiri Slaby15b611f2006-12-08 02:39:04 -0800797 return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
798 ((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
799 ((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
800 ((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
801 ((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
802 ((i_stat & IP_RI) ? TIOCM_RNG : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803}
804
Jiri Slaby15b611f2006-12-08 02:39:04 -0800805static void sx_set_baud(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806{
807 int t;
808
809 if (port->board->ta_type == MOD_SXDC) {
810 switch (port->gs.baud) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800811 /* Save some typing work... */
812#define e(x) case x: t = BAUD_ ## x; break
813 e(50);
814 e(75);
815 e(110);
816 e(150);
817 e(200);
818 e(300);
819 e(600);
820 e(1200);
821 e(1800);
822 e(2000);
823 e(2400);
824 e(4800);
825 e(7200);
826 e(9600);
827 e(14400);
828 e(19200);
829 e(28800);
830 e(38400);
831 e(56000);
832 e(57600);
833 e(64000);
834 e(76800);
835 e(115200);
836 e(128000);
837 e(150000);
838 e(230400);
839 e(256000);
840 e(460800);
841 e(921600);
842 case 134:
843 t = BAUD_134_5;
844 break;
845 case 0:
846 t = -1;
847 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 default:
849 /* Can I return "invalid"? */
850 t = BAUD_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800851 printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
852 port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 break;
854 }
855#undef e
856 if (t > 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800857/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
858 sx_setsignals(port, 1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 /* XXX This is not TA & MTA compatible */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800860 sx_write_channel_byte(port, hi_csr, 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
Jiri Slaby15b611f2006-12-08 02:39:04 -0800862 sx_write_channel_byte(port, hi_txbaud, t);
863 sx_write_channel_byte(port, hi_rxbaud, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800865 sx_setsignals(port, 0, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 }
867 } else {
868 switch (port->gs.baud) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800869#define e(x) case x: t = CSR_ ## x; break
870 e(75);
871 e(150);
872 e(300);
873 e(600);
874 e(1200);
875 e(2400);
876 e(4800);
877 e(1800);
878 e(9600);
879 e(19200);
880 e(57600);
881 e(38400);
882/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
883 case 110:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 if (port->board->ta_type == MOD_TA) {
885 t = CSR_110;
886 break;
887 } else {
888 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800889 printk(KERN_INFO "sx: Unsupported baud rate: "
890 "%d.\n", port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 break;
892 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800893 case 115200:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 if (port->board->ta_type == MOD_TA) {
895 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800896 printk(KERN_INFO "sx: Unsupported baud rate: "
897 "%d.\n", port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 break;
899 } else {
900 t = CSR_110;
901 break;
902 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800903 case 0:
904 t = -1;
905 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 default:
907 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800908 printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
909 port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 break;
911 }
912#undef e
913 if (t >= 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800914 sx_setsignals(port, 1, -1);
915 sx_write_channel_byte(port, hi_csr, t * 0x11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800917 sx_setsignals(port, 0, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919 }
920}
921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
923 better. -- REW */
924
Jiri Slaby15b611f2006-12-08 02:39:04 -0800925static int sx_set_real_termios(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926{
927 struct sx_port *port = ptr;
928
929 func_enter2();
930
Alan Coxb5391e22008-07-16 21:55:20 +0100931 if (!port->gs.port.tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 return 0;
933
934 /* What is this doing here? -- REW
935 Ha! figured it out. It is to allow you to get DTR active again
936 if you've dropped it with stty 0. Moved to set_baud, where it
937 belongs (next to the drop dtr if baud == 0) -- REW */
938 /* sx_setsignals (port, 1, -1); */
939
Jiri Slaby15b611f2006-12-08 02:39:04 -0800940 sx_set_baud(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941
Alan Coxb5391e22008-07-16 21:55:20 +0100942#define CFLAG port->gs.port.tty->termios->c_cflag
Jiri Slaby15b611f2006-12-08 02:39:04 -0800943 sx_write_channel_byte(port, hi_mr1,
Alan Coxb5391e22008-07-16 21:55:20 +0100944 (C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) |
945 (C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) |
946 (C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) |
Jiri Slaby15b611f2006-12-08 02:39:04 -0800947 (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
948 (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
949 (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
950 (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Jiri Slaby15b611f2006-12-08 02:39:04 -0800952 sx_write_channel_byte(port, hi_mr2,
Alan Coxb5391e22008-07-16 21:55:20 +0100953 (C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) |
954 (C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP :
Jiri Slaby15b611f2006-12-08 02:39:04 -0800955 MR2_1_STOP));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
957 switch (CFLAG & CSIZE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800958 case CS8:
959 sx_write_channel_byte(port, hi_mask, 0xff);
960 break;
961 case CS7:
962 sx_write_channel_byte(port, hi_mask, 0x7f);
963 break;
964 case CS6:
965 sx_write_channel_byte(port, hi_mask, 0x3f);
966 break;
967 case CS5:
968 sx_write_channel_byte(port, hi_mask, 0x1f);
969 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 default:
Andrew Morton32fb3ca2008-05-06 20:42:35 -0700971 printk(KERN_INFO "sx: Invalid wordsize: %u\n",
972 (unsigned int)CFLAG & CSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 break;
974 }
975
Jiri Slaby15b611f2006-12-08 02:39:04 -0800976 sx_write_channel_byte(port, hi_prtcl,
Alan Coxb5391e22008-07-16 21:55:20 +0100977 (I_IXON(port->gs.port.tty) ? SP_TXEN : 0) |
978 (I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) |
979 (I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980
Jiri Slaby15b611f2006-12-08 02:39:04 -0800981 sx_write_channel_byte(port, hi_break,
Alan Coxb5391e22008-07-16 21:55:20 +0100982 (I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 |
983 I_BRKINT(port->gs.port.tty) ? BR_INT : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
Alan Coxb5391e22008-07-16 21:55:20 +0100985 sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty));
986 sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty));
987 sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty));
988 sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
990 sx_reconfigure_port(port);
991
992 /* Tell line discipline whether we will do input cooking */
Alan Coxb5391e22008-07-16 21:55:20 +0100993 if (I_OTHER(port->gs.port.tty)) {
994 clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 } else {
Alan Coxb5391e22008-07-16 21:55:20 +0100996 set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800998 sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
Alan Coxb5391e22008-07-16 21:55:20 +0100999 (unsigned int)port->gs.port.tty->termios->c_iflag,
1000 I_OTHER(port->gs.port.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
1002/* Tell line discipline whether we will do output cooking.
1003 * If OPOST is set and no other output flags are set then we can do output
1004 * processing. Even if only *one* other flag in the O_OTHER group is set
1005 * we do cooking in software.
1006 */
Alan Coxb5391e22008-07-16 21:55:20 +01001007 if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) {
1008 set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 } else {
Alan Coxb5391e22008-07-16 21:55:20 +01001010 clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001012 sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001013 (unsigned int)port->gs.port.tty->termios->c_oflag,
1014 O_OTHER(port->gs.port.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 /* port->c_dcd = sx_get_CD (port); */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001016 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 return 0;
1018}
1019
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020/* ********************************************************************** *
1021 * the interrupt related routines *
1022 * ********************************************************************** */
1023
1024/* Note:
1025 Other drivers use the macro "MIN" to calculate how much to copy.
1026 This has the disadvantage that it will evaluate parts twice. That's
1027 expensive when it's IO (and the compiler cannot optimize those away!).
1028 Moreover, I'm not sure that you're race-free.
1029
1030 I assign a value, and then only allow the value to decrease. This
1031 is always safe. This makes the code a few lines longer, and you
1032 know I'm dead against that, but I think it is required in this
1033 case. */
1034
Jiri Slaby15b611f2006-12-08 02:39:04 -08001035static void sx_transmit_chars(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036{
1037 int c;
1038 int tx_ip;
1039 int txroom;
1040
Jiri Slaby15b611f2006-12-08 02:39:04 -08001041 func_enter2();
1042 sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
1043 port, port->gs.xmit_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
Jiri Slaby15b611f2006-12-08 02:39:04 -08001045 if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 return;
1047 }
1048
1049 while (1) {
1050 c = port->gs.xmit_cnt;
1051
Jiri Slaby15b611f2006-12-08 02:39:04 -08001052 sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
1053 tx_ip = sx_read_channel_byte(port, hi_txipos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
1055 /* Took me 5 minutes to deduce this formula.
1056 Luckily it is literally in the manual in section 6.5.4.3.5 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001057 txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
1058 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060 /* Don't copy more bytes than there is room for in the buffer */
1061 if (c > txroom)
1062 c = txroom;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001063 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
1065 /* Don't copy past the end of the hardware transmit buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001066 if (c > 0x100 - tx_ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 c = 0x100 - tx_ip;
1068
Jiri Slaby15b611f2006-12-08 02:39:04 -08001069 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
1071 /* Don't copy pas the end of the source buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001072 if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
1074
Jiri Slaby15b611f2006-12-08 02:39:04 -08001075 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
1076 c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Jiri Slaby15b611f2006-12-08 02:39:04 -08001078 /* If for one reason or another, we can't copy more data, we're
1079 done! */
1080 if (c == 0)
1081 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Jiri Slaby15b611f2006-12-08 02:39:04 -08001083 memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
1084 tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
1086 /* Update the pointer in the card */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001087 sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
1089 /* Update the kernel buffer end */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001090 port->gs.xmit_tail = (port->gs.xmit_tail + c) &
1091 (SERIAL_XMIT_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
1093 /* This one last. (this is essential)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001094 It would allow others to start putting more data into the
1095 buffer! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 port->gs.xmit_cnt -= c;
1097 }
1098
1099 if (port->gs.xmit_cnt == 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001100 sx_disable_tx_interrupts(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 }
1102
Alan Coxb5391e22008-07-16 21:55:20 +01001103 if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
1104 tty_wakeup(port->gs.port.tty);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001105 sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
1106 port->gs.wakeup_chars);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 }
1108
Jiri Slaby15b611f2006-12-08 02:39:04 -08001109 clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
1110 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111}
1112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113/* Note the symmetry between receiving chars and transmitting them!
1114 Note: The kernel should have implemented both a receive buffer and
1115 a transmit buffer. */
1116
1117/* Inlined: Called only once. Remove the inline when you add another call */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001118static inline void sx_receive_chars(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
1120 int c;
1121 int rx_op;
1122 struct tty_struct *tty;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001123 int copied = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08001124 unsigned char *rp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
Jiri Slaby15b611f2006-12-08 02:39:04 -08001126 func_enter2();
Alan Coxb5391e22008-07-16 21:55:20 +01001127 tty = port->gs.port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 while (1) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001129 rx_op = sx_read_channel_byte(port, hi_rxopos);
1130 c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
Jiri Slaby15b611f2006-12-08 02:39:04 -08001132 sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001134 /* Don't copy past the end of the hardware receive buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001135 if (rx_op + c > 0x100)
1136 c = 0x100 - rx_op;
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001137
Jiri Slaby15b611f2006-12-08 02:39:04 -08001138 sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 /* Don't copy more bytes than there is room for in the buffer */
Alan Cox33f0f882006-01-09 20:54:13 -08001141
1142 c = tty_prepare_flip_string(tty, &rp, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Jiri Slaby15b611f2006-12-08 02:39:04 -08001144 sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 /* If for one reason or another, we can't copy more data, we're done! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001147 if (c == 0)
1148 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
Jiri Slaby15b611f2006-12-08 02:39:04 -08001150 sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
1151 "%d at %lx\n", c, read_sx_byte(port->board,
1152 CHAN_OFFSET(port, hi_rxbuf) + rx_op),
1153 CHAN_OFFSET(port, hi_rxbuf));
1154 memcpy_fromio(rp, port->board->base +
1155 CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
1157 /* This one last. ( Not essential.)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001158 It allows the card to start putting more data into the
1159 buffer!
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 Update the pointer in the card */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001161 sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
1163 copied += c;
1164 }
1165 if (copied) {
1166 struct timeval tv;
1167
Jiri Slaby15b611f2006-12-08 02:39:04 -08001168 do_gettimeofday(&tv);
1169 sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
1170 "chars): %d.%06d (%d/%d)\n", port->line,
1171 copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
1172 tty->raw, tty->real_raw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
Jiri Slaby15b611f2006-12-08 02:39:04 -08001174 /* Tell the rest of the system the news. Great news. New
1175 characters! */
1176 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 /* tty_schedule_flip (tty); */
1178 }
1179
Jiri Slaby15b611f2006-12-08 02:39:04 -08001180 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181}
1182
1183/* Inlined: it is called only once. Remove the inline if you add another
1184 call */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001185static inline void sx_check_modem_signals(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186{
1187 int hi_state;
1188 int c_dcd;
1189
Jiri Slaby15b611f2006-12-08 02:39:04 -08001190 hi_state = sx_read_channel_byte(port, hi_state);
1191 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
Alan Cox31f35932009-01-02 13:45:05 +00001192 port->c_dcd, tty_port_carrier_raised(&port->gs.port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
1194 if (hi_state & ST_BREAK) {
1195 hi_state &= ~ST_BREAK;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001196 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
1197 sx_write_channel_byte(port, hi_state, hi_state);
1198 gs_got_break(&port->gs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 }
1200 if (hi_state & ST_DCD) {
1201 hi_state &= ~ST_DCD;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001202 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
1203 sx_write_channel_byte(port, hi_state, hi_state);
Alan Cox31f35932009-01-02 13:45:05 +00001204 c_dcd = tty_port_carrier_raised(&port->gs.port);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001205 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 if (c_dcd != port->c_dcd) {
1207 port->c_dcd = c_dcd;
Alan Cox31f35932009-01-02 13:45:05 +00001208 if (tty_port_carrier_raised(&port->gs.port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 /* DCD went UP */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001210 if ((sx_read_channel_byte(port, hi_hstat) !=
1211 HS_IDLE_CLOSED) &&
Alan Coxb5391e22008-07-16 21:55:20 +01001212 !(port->gs.port.tty->termios->
Jiri Slaby15b611f2006-12-08 02:39:04 -08001213 c_cflag & CLOCAL)) {
1214 /* Are we blocking in open? */
1215 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1216 "active, unblocking open\n");
Alan Coxb5391e22008-07-16 21:55:20 +01001217 wake_up_interruptible(&port->gs.port.
Jiri Slaby15b611f2006-12-08 02:39:04 -08001218 open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001220 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1221 "raised. Ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 }
1223 } else {
1224 /* DCD went down! */
Alan Coxb5391e22008-07-16 21:55:20 +01001225 if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){
Jiri Slaby15b611f2006-12-08 02:39:04 -08001226 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1227 "dropped. hanging up....\n");
Alan Coxb5391e22008-07-16 21:55:20 +01001228 tty_hangup(port->gs.port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001230 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1231 "dropped. ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 }
1233 }
1234 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001235 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
1236 "DCD changed, but it didn't.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 }
1238 }
1239}
1240
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241/* This is what an interrupt routine should look like.
1242 * Small, elegant, clear.
1243 */
1244
Jiri Slaby15b611f2006-12-08 02:39:04 -08001245static irqreturn_t sx_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246{
1247 struct sx_board *board = ptr;
1248 struct sx_port *port;
1249 int i;
1250
Jiri Slaby15b611f2006-12-08 02:39:04 -08001251 func_enter();
1252 sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
1253 board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
1255 /* AAargh! The order in which to do these things is essential and
1256 not trivial.
1257
1258 - Rate limit goes before "recursive". Otherwise a series of
Jiri Slaby15b611f2006-12-08 02:39:04 -08001259 recursive calls will hang the machine in the interrupt routine.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
1261 - hardware twiddling goes before "recursive". Otherwise when we
Jiri Slaby15b611f2006-12-08 02:39:04 -08001262 poll the card, and a recursive interrupt happens, we won't
1263 ack the card, so it might keep on interrupting us. (especially
1264 level sensitive interrupt systems like PCI).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
1266 - Rate limit goes before hardware twiddling. Otherwise we won't
Jiri Slaby15b611f2006-12-08 02:39:04 -08001267 catch a card that has gone bonkers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
1269 - The "initialized" test goes after the hardware twiddling. Otherwise
Jiri Slaby15b611f2006-12-08 02:39:04 -08001270 the card will stick us in the interrupt routine again.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
1272 - The initialized test goes before recursive.
Jiri Slaby15b611f2006-12-08 02:39:04 -08001273 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
1275#ifdef IRQ_RATE_LIMIT
1276 /* Aaargh! I'm ashamed. This costs more lines-of-code than the
Jiri Slaby15b611f2006-12-08 02:39:04 -08001277 actual interrupt routine!. (Well, used to when I wrote that
1278 comment) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 {
1280 static int lastjif;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001281 static int nintr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
1283 if (lastjif == jiffies) {
1284 if (++nintr > IRQ_RATE_LIMIT) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001285 free_irq(board->irq, board);
1286 printk(KERN_ERR "sx: Too many interrupts. "
1287 "Turning off interrupt %d.\n",
1288 board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 }
1290 } else {
1291 lastjif = jiffies;
1292 nintr = 0;
1293 }
1294 }
1295#endif
1296
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 if (board->irq == irq) {
1298 /* Tell the card we've noticed the interrupt. */
1299
Jiri Slaby15b611f2006-12-08 02:39:04 -08001300 sx_write_board_word(board, cc_int_pending, 0);
1301 if (IS_SX_BOARD(board)) {
1302 write_sx_byte(board, SX_RESET_IRQ, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001304 inb(board->eisa_base + 0xc03);
1305 write_sx_word(board, 8, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001307 write_sx_byte(board, SI2_ISA_INTCLEAR,
1308 SI2_ISA_INTCLEAR_CLEAR);
1309 write_sx_byte(board, SI2_ISA_INTCLEAR,
1310 SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 }
1312 }
1313
1314 if (!sx_initialized)
1315 return IRQ_HANDLED;
1316 if (!(board->flags & SX_BOARD_INITIALIZED))
1317 return IRQ_HANDLED;
1318
Jiri Slaby15b611f2006-12-08 02:39:04 -08001319 if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
1320 printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 return IRQ_HANDLED;
1322 }
1323
Jiri Slaby15b611f2006-12-08 02:39:04 -08001324 for (i = 0; i < board->nports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 port = &board->ports[i];
Alan Coxb5391e22008-07-16 21:55:20 +01001326 if (port->gs.port.flags & GS_ACTIVE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001327 if (sx_read_channel_byte(port, hi_state)) {
1328 sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
1329 "modem signal change?... \n",i);
1330 sx_check_modem_signals(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 }
1332 if (port->gs.xmit_cnt) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001333 sx_transmit_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 }
Alan Coxb5391e22008-07-16 21:55:20 +01001335 if (!(port->gs.port.flags & SX_RX_THROTTLE)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001336 sx_receive_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 }
1338 }
1339 }
1340
Jiri Slaby15b611f2006-12-08 02:39:04 -08001341 clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Jiri Slaby15b611f2006-12-08 02:39:04 -08001343 sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
1344 board->irq);
1345 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 return IRQ_HANDLED;
1347}
1348
Jiri Slaby15b611f2006-12-08 02:39:04 -08001349static void sx_pollfunc(unsigned long data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001351 struct sx_board *board = (struct sx_board *)data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Jiri Slaby15b611f2006-12-08 02:39:04 -08001353 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Jiri Slaby15b611f2006-12-08 02:39:04 -08001355 sx_interrupt(0, board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Jiri Slabyc9594642006-12-08 02:39:05 -08001357 mod_timer(&board->timer, jiffies + sx_poll);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001358 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359}
1360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361/* ********************************************************************** *
1362 * Here are the routines that actually *
1363 * interface with the generic_serial driver *
1364 * ********************************************************************** */
1365
1366/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
1367/* Hmm. Ok I figured it out. You don't. */
1368
Jiri Slaby15b611f2006-12-08 02:39:04 -08001369static void sx_disable_tx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001371 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 func_enter2();
1373
Alan Coxb5391e22008-07-16 21:55:20 +01001374 port->gs.port.flags &= ~GS_TX_INTEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376 func_exit();
1377}
1378
Jiri Slaby15b611f2006-12-08 02:39:04 -08001379static void sx_enable_tx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001381 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 int data_in_buffer;
1383 func_enter2();
1384
1385 /* First transmit the characters that we're supposed to */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001386 sx_transmit_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
1388 /* The sx card will never interrupt us if we don't fill the buffer
1389 past 25%. So we keep considering interrupts off if that's the case. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001390 data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
1391 sx_read_channel_byte(port, hi_txopos)) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
1393 /* XXX Must be "HIGH_WATER" for SI card according to doc. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001394 if (data_in_buffer < LOW_WATER)
Alan Coxb5391e22008-07-16 21:55:20 +01001395 port->gs.port.flags &= ~GS_TX_INTEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
1397 func_exit();
1398}
1399
Jiri Slaby15b611f2006-12-08 02:39:04 -08001400static void sx_disable_rx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401{
1402 /* struct sx_port *port = ptr; */
1403 func_enter();
1404
1405 func_exit();
1406}
1407
Jiri Slaby15b611f2006-12-08 02:39:04 -08001408static void sx_enable_rx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409{
1410 /* struct sx_port *port = ptr; */
1411 func_enter();
1412
1413 func_exit();
1414}
1415
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416/* Jeez. Isn't this simple? */
Alan Cox31f35932009-01-02 13:45:05 +00001417static int sx_carrier_raised(struct tty_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418{
Alan Cox31f35932009-01-02 13:45:05 +00001419 struct sx_port *sp = container_of(port, struct sx_port, gs.port);
1420 return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421}
1422
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423/* Jeez. Isn't this simple? */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001424static int sx_chars_in_buffer(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425{
1426 struct sx_port *port = ptr;
1427 func_enter2();
1428
1429 func_exit();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001430 return ((sx_read_channel_byte(port, hi_txipos) -
1431 sx_read_channel_byte(port, hi_txopos)) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432}
1433
Jiri Slaby15b611f2006-12-08 02:39:04 -08001434static void sx_shutdown_port(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001436 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
1438 func_enter();
1439
Alan Coxb5391e22008-07-16 21:55:20 +01001440 port->gs.port.flags &= ~GS_ACTIVE;
1441 if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001442 sx_setsignals(port, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 sx_reconfigure_port(port);
1444 }
1445
1446 func_exit();
1447}
1448
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449/* ********************************************************************** *
1450 * Here are the routines that actually *
1451 * interface with the rest of the system *
1452 * ********************************************************************** */
1453
Jiri Slaby15b611f2006-12-08 02:39:04 -08001454static int sx_open(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455{
1456 struct sx_port *port;
1457 int retval, line;
1458 unsigned long flags;
1459
1460 func_enter();
1461
1462 if (!sx_initialized) {
1463 return -EIO;
1464 }
1465
1466 line = tty->index;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001467 sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
Pavel Emelyanovba25f9d2007-10-18 23:40:40 -07001468 "np=%d)\n", task_pid_nr(current), line, tty,
Jiri Slaby15b611f2006-12-08 02:39:04 -08001469 current->signal->tty, sx_nports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
1472 return -ENODEV;
1473
Jiri Slaby15b611f2006-12-08 02:39:04 -08001474 port = &sx_ports[line];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
Jiri Slaby15b611f2006-12-08 02:39:04 -08001476 1 -> 0 transition. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Jiri Slaby15b611f2006-12-08 02:39:04 -08001478 sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
1480 spin_lock_irqsave(&port->gs.driver_lock, flags);
1481
1482 tty->driver_data = port;
Alan Coxb5391e22008-07-16 21:55:20 +01001483 port->gs.port.tty = tty;
1484 port->gs.port.count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 spin_unlock_irqrestore(&port->gs.driver_lock, flags);
1486
Jiri Slaby15b611f2006-12-08 02:39:04 -08001487 sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
1489 /*
1490 * Start up serial port
1491 */
1492 retval = gs_init_port(&port->gs);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001493 sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 if (retval) {
Alan Coxb5391e22008-07-16 21:55:20 +01001495 port->gs.port.count--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 return retval;
1497 }
1498
Alan Coxb5391e22008-07-16 21:55:20 +01001499 port->gs.port.flags |= GS_ACTIVE;
1500 if (port->gs.port.count <= 1)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001501 sx_setsignals(port, 1, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
1503#if 0
1504 if (sx_debug & SX_DEBUG_OPEN)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001505 my_hd(port, sizeof(*port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506#else
1507 if (sx_debug & SX_DEBUG_OPEN)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001508 my_hd_io(port->board->base + port->ch_base, sizeof(*port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509#endif
1510
Alan Coxb5391e22008-07-16 21:55:20 +01001511 if (port->gs.port.count <= 1) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001512 if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
1513 printk(KERN_ERR "sx: Card didn't respond to LOPEN "
1514 "command.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 spin_lock_irqsave(&port->gs.driver_lock, flags);
Alan Coxb5391e22008-07-16 21:55:20 +01001516 port->gs.port.count--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 spin_unlock_irqrestore(&port->gs.driver_lock, flags);
1518 return -EIO;
1519 }
1520 }
1521
1522 retval = gs_block_til_ready(port, filp);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001523 sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001524 retval, port->gs.port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
1526 if (retval) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001527/*
Alan Coxb5391e22008-07-16 21:55:20 +01001528 * Don't lower gs.port.count here because sx_close() will be called later
Jiri Slaby15b611f2006-12-08 02:39:04 -08001529 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
1531 return retval;
1532 }
1533 /* tty->low_latency = 1; */
1534
Alan Cox31f35932009-01-02 13:45:05 +00001535 port->c_dcd = sx_carrier_raised(&port->gs.port);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001536 sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
1538 func_exit();
1539 return 0;
1540
1541}
1542
Jiri Slaby15b611f2006-12-08 02:39:04 -08001543static void sx_close(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001545 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 /* Give the port 5 seconds to close down. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001547 int to = 5 * HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
Jiri Slaby15b611f2006-12-08 02:39:04 -08001549 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
Jiri Slaby15b611f2006-12-08 02:39:04 -08001551 sx_setsignals(port, 0, 0);
1552 sx_reconfigure_port(port);
1553 sx_send_command(port, HS_CLOSE, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Jiri Slaby15b611f2006-12-08 02:39:04 -08001555 while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 if (msleep_interruptible(10))
1557 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001558 if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) {
1559 if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED)
1560 != 1) {
1561 printk(KERN_ERR "sx: sent the force_close command, but "
1562 "card didn't react\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 } else
Jiri Slaby15b611f2006-12-08 02:39:04 -08001564 sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
1565 "command.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 }
1567
Jiri Slaby15b611f2006-12-08 02:39:04 -08001568 sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001569 5 * HZ - to - 1, port->gs.port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
Alan Coxb5391e22008-07-16 21:55:20 +01001571 if (port->gs.port.count) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001572 sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001573 port->gs.port.count);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001574 /*printk("%s SETTING port count to zero: %p count: %d\n",
Alan Coxb5391e22008-07-16 21:55:20 +01001575 __func__, port, port->gs.port.count);
1576 port->gs.port.count = 0;*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 }
1578
Jiri Slaby15b611f2006-12-08 02:39:04 -08001579 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580}
1581
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582/* This is relatively thorough. But then again it is only 20 lines. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001583#define MARCHUP for (i = min; i < max; i++)
1584#define MARCHDOWN for (i = max - 1; i >= min; i--)
1585#define W0 write_sx_byte(board, i, 0x55)
1586#define W1 write_sx_byte(board, i, 0xaa)
1587#define R0 if (read_sx_byte(board, i) != 0x55) return 1
1588#define R1 if (read_sx_byte(board, i) != 0xaa) return 1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589
1590/* This memtest takes a human-noticable time. You normally only do it
1591 once a boot, so I guess that it is worth it. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001592static int do_memtest(struct sx_board *board, int min, int max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593{
1594 int i;
1595
1596 /* This is a marchb. Theoretically, marchb catches much more than
1597 simpler tests. In practise, the longer test just catches more
1598 intermittent errors. -- REW
1599 (For the theory behind memory testing see:
1600 Testing Semiconductor Memories by A.J. van de Goor.) */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001601 MARCHUP {
1602 W0;
1603 }
1604 MARCHUP {
1605 R0;
1606 W1;
1607 R1;
1608 W0;
1609 R0;
1610 W1;
1611 }
1612 MARCHUP {
1613 R1;
1614 W0;
1615 W1;
1616 }
1617 MARCHDOWN {
1618 R1;
1619 W0;
1620 W1;
1621 W0;
1622 }
1623 MARCHDOWN {
1624 R0;
1625 W1;
1626 W0;
1627 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
1629 return 0;
1630}
1631
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632#undef MARCHUP
1633#undef MARCHDOWN
1634#undef W0
1635#undef W1
1636#undef R0
1637#undef R1
1638
Jiri Slaby15b611f2006-12-08 02:39:04 -08001639#define MARCHUP for (i = min; i < max; i += 2)
1640#define MARCHDOWN for (i = max - 1; i >= min; i -= 2)
1641#define W0 write_sx_word(board, i, 0x55aa)
1642#define W1 write_sx_word(board, i, 0xaa55)
1643#define R0 if (read_sx_word(board, i) != 0x55aa) return 1
1644#define R1 if (read_sx_word(board, i) != 0xaa55) return 1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
1646#if 0
1647/* This memtest takes a human-noticable time. You normally only do it
1648 once a boot, so I guess that it is worth it. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001649static int do_memtest_w(struct sx_board *board, int min, int max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650{
1651 int i;
1652
Jiri Slaby15b611f2006-12-08 02:39:04 -08001653 MARCHUP {
1654 W0;
1655 }
1656 MARCHUP {
1657 R0;
1658 W1;
1659 R1;
1660 W0;
1661 R0;
1662 W1;
1663 }
1664 MARCHUP {
1665 R1;
1666 W0;
1667 W1;
1668 }
1669 MARCHDOWN {
1670 R1;
1671 W0;
1672 W1;
1673 W0;
1674 }
1675 MARCHDOWN {
1676 R0;
1677 W1;
1678 W0;
1679 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
1681 return 0;
1682}
1683#endif
1684
Alan Cox11af7472008-07-25 01:48:15 -07001685static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
1686 unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687{
Alan Cox11af7472008-07-25 01:48:15 -07001688 long rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 int __user *descr = (int __user *)arg;
1690 int i;
1691 static struct sx_board *board = NULL;
1692 int nbytes, offset;
1693 unsigned long data;
1694 char *tmp;
1695
1696 func_enter();
1697
Alan Cox11af7472008-07-25 01:48:15 -07001698 if (!capable(CAP_SYS_RAWIO))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 return -EPERM;
Alan Cox11af7472008-07-25 01:48:15 -07001700
1701 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
Jiri Slaby15b611f2006-12-08 02:39:04 -08001703 sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
Jiri Slaby15b611f2006-12-08 02:39:04 -08001705 if (!board)
1706 board = &boards[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 if (board->flags & SX_BOARD_PRESENT) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001708 sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
1709 board->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001711 sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
1712 board->flags);
1713 for (i = 0; i < SX_NBOARDS; i++)
1714 sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
1715 sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
Dan Carpenter736d5452009-02-04 15:12:20 -08001716 rc = -EIO;
1717 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 }
1719
1720 switch (cmd) {
1721 case SXIO_SET_BOARD:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001722 sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
Alan Cox11af7472008-07-25 01:48:15 -07001723 rc = -EIO;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001724 if (arg >= SX_NBOARDS)
Alan Cox11af7472008-07-25 01:48:15 -07001725 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001726 sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
1727 if (!(boards[arg].flags & SX_BOARD_PRESENT))
Alan Cox11af7472008-07-25 01:48:15 -07001728 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001729 sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 board = &boards[arg];
Alan Cox11af7472008-07-25 01:48:15 -07001731 rc = 0;
1732 /* FIXME: And this does ... nothing?? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 break;
1734 case SXIO_GET_TYPE:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001735 rc = -ENOENT; /* If we manage to miss one, return error. */
1736 if (IS_SX_BOARD(board))
1737 rc = SX_TYPE_SX;
1738 if (IS_CF_BOARD(board))
1739 rc = SX_TYPE_CF;
1740 if (IS_SI_BOARD(board))
1741 rc = SX_TYPE_SI;
1742 if (IS_SI1_BOARD(board))
1743 rc = SX_TYPE_SI;
1744 if (IS_EISA_BOARD(board))
1745 rc = SX_TYPE_SI;
Alan Cox11af7472008-07-25 01:48:15 -07001746 sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 break;
1748 case SXIO_DO_RAMTEST:
Ilpo Järvinen9b6d2512009-02-20 15:38:45 -08001749 if (sx_initialized) { /* Already initialized: better not ramtest the board. */
Dan Carpenter736d5452009-02-04 15:12:20 -08001750 rc = -EPERM;
1751 break;
Ilpo Järvinen9b6d2512009-02-20 15:38:45 -08001752 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001753 if (IS_SX_BOARD(board)) {
1754 rc = do_memtest(board, 0, 0x7000);
1755 if (!rc)
1756 rc = do_memtest(board, 0, 0x7000);
1757 /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001759 rc = do_memtest(board, 0, 0x7ff8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
1761 }
Alan Cox11af7472008-07-25 01:48:15 -07001762 sx_dprintk(SX_DEBUG_FIRMWARE,
1763 "returning memtest result= %ld\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 break;
1765 case SXIO_DOWNLOAD:
Alan Cox11af7472008-07-25 01:48:15 -07001766 if (sx_initialized) {/* Already initialized */
1767 rc = -EEXIST;
1768 break;
1769 }
1770 if (!sx_reset(board)) {
1771 rc = -EIO;
1772 break;
1773 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001774 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Jiri Slaby15b611f2006-12-08 02:39:04 -08001776 tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
Alan Cox11af7472008-07-25 01:48:15 -07001777 if (!tmp) {
1778 rc = -ENOMEM;
1779 break;
1780 }
1781 /* FIXME: check returns */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001782 get_user(nbytes, descr++);
1783 get_user(offset, descr++);
1784 get_user(data, descr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 while (nbytes && data) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001786 for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
1787 if (copy_from_user(tmp, (char __user *)data + i,
1788 (i + SX_CHUNK_SIZE > nbytes) ?
1789 nbytes - i : SX_CHUNK_SIZE)) {
1790 kfree(tmp);
Alan Cox11af7472008-07-25 01:48:15 -07001791 rc = -EFAULT;
Dan Carpenterb28fe282009-02-20 15:38:46 -08001792 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001794 memcpy_toio(board->base2 + offset + i, tmp,
1795 (i + SX_CHUNK_SIZE > nbytes) ?
1796 nbytes - i : SX_CHUNK_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 }
1798
Jiri Slaby15b611f2006-12-08 02:39:04 -08001799 get_user(nbytes, descr++);
1800 get_user(offset, descr++);
1801 get_user(data, descr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001803 kfree(tmp);
1804 sx_nports += sx_init_board(board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 rc = sx_nports;
1806 break;
1807 case SXIO_INIT:
Alan Cox11af7472008-07-25 01:48:15 -07001808 if (sx_initialized) { /* Already initialized */
1809 rc = -EEXIST;
1810 break;
1811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 /* This is not allowed until all boards are initialized... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001813 for (i = 0; i < SX_NBOARDS; i++) {
1814 if ((boards[i].flags & SX_BOARD_PRESENT) &&
Alan Cox11af7472008-07-25 01:48:15 -07001815 !(boards[i].flags & SX_BOARD_INITIALIZED)) {
1816 rc = -EIO;
1817 break;
1818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001820 for (i = 0; i < SX_NBOARDS; i++)
1821 if (!(boards[i].flags & SX_BOARD_PRESENT))
1822 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
Jiri Slaby15b611f2006-12-08 02:39:04 -08001824 sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
1825 "%d channels, first board: %d ports\n",
1826 i, sx_nports, boards[0].nports);
1827 rc = sx_init_portstructs(i, sx_nports);
1828 sx_init_drivers();
1829 if (rc >= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 sx_initialized++;
1831 break;
1832 case SXIO_SETDEBUG:
1833 sx_debug = arg;
1834 break;
1835 case SXIO_GETDEBUG:
1836 rc = sx_debug;
1837 break;
1838 case SXIO_GETGSDEBUG:
1839 case SXIO_SETGSDEBUG:
1840 rc = -EINVAL;
1841 break;
1842 case SXIO_GETNPORTS:
1843 rc = sx_nports;
1844 break;
1845 default:
Alan Cox11af7472008-07-25 01:48:15 -07001846 rc = -ENOTTY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 break;
1848 }
Dan Carpenter736d5452009-02-04 15:12:20 -08001849out:
Alan Cox11af7472008-07-25 01:48:15 -07001850 unlock_kernel();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001851 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 return rc;
1853}
1854
Alan Cox9e989662008-07-22 11:18:03 +01001855static int sx_break(struct tty_struct *tty, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856{
1857 struct sx_port *port = tty->driver_data;
1858 int rv;
1859
Jiri Slaby15b611f2006-12-08 02:39:04 -08001860 func_enter();
Alan Cox341339e2008-04-30 00:53:24 -07001861 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Jiri Slaby15b611f2006-12-08 02:39:04 -08001863 if (flag)
1864 rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
1865 else
1866 rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
1867 if (rv != 1)
1868 printk(KERN_ERR "sx: couldn't send break (%x).\n",
1869 read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
Alan Cox341339e2008-04-30 00:53:24 -07001870 unlock_kernel();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001871 func_exit();
Alan Cox9e989662008-07-22 11:18:03 +01001872 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873}
1874
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1876{
1877 struct sx_port *port = tty->driver_data;
1878 return sx_getsignals(port);
1879}
1880
1881static int sx_tiocmset(struct tty_struct *tty, struct file *file,
Jiri Slaby15b611f2006-12-08 02:39:04 -08001882 unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883{
1884 struct sx_port *port = tty->driver_data;
1885 int rts = -1, dtr = -1;
1886
1887 if (set & TIOCM_RTS)
1888 rts = 1;
1889 if (set & TIOCM_DTR)
1890 dtr = 1;
1891 if (clear & TIOCM_RTS)
1892 rts = 0;
1893 if (clear & TIOCM_DTR)
1894 dtr = 0;
1895
1896 sx_setsignals(port, dtr, rts);
1897 sx_reconfigure_port(port);
1898 return 0;
1899}
1900
Jiri Slaby15b611f2006-12-08 02:39:04 -08001901static int sx_ioctl(struct tty_struct *tty, struct file *filp,
1902 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
1904 int rc;
1905 struct sx_port *port = tty->driver_data;
1906 void __user *argp = (void __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907
1908 /* func_enter2(); */
1909
1910 rc = 0;
Alan Cox341339e2008-04-30 00:53:24 -07001911 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 case TIOCGSERIAL:
1914 rc = gs_getserial(&port->gs, argp);
1915 break;
1916 case TIOCSSERIAL:
1917 rc = gs_setserial(&port->gs, argp);
1918 break;
1919 default:
1920 rc = -ENOIOCTLCMD;
1921 break;
1922 }
Alan Cox341339e2008-04-30 00:53:24 -07001923 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924
1925 /* func_exit(); */
1926 return rc;
1927}
1928
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929/* The throttle/unthrottle scheme for the Specialix card is different
1930 * from other drivers and deserves some explanation.
1931 * The Specialix hardware takes care of XON/XOFF
1932 * and CTS/RTS flow control itself. This means that all we have to
1933 * do when signalled by the upper tty layer to throttle/unthrottle is
1934 * to make a note of it here. When we come to read characters from the
1935 * rx buffers on the card (sx_receive_chars()) we look to see if the
1936 * upper layer can accept more (as noted here in sx_rx_throt[]).
1937 * If it can't we simply don't remove chars from the cards buffer.
1938 * When the tty layer can accept chars, we again note that here and when
1939 * sx_receive_chars() is called it will remove them from the cards buffer.
1940 * The card will notice that a ports buffer has drained below some low
1941 * water mark and will unflow control the line itself, using whatever
1942 * flow control scheme is in use for that port. -- Simon Allen
1943 */
1944
Jiri Slaby15b611f2006-12-08 02:39:04 -08001945static void sx_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946{
Alan Coxc9f19e92009-01-02 13:47:26 +00001947 struct sx_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948
1949 func_enter2();
1950 /* If the port is using any type of input flow
1951 * control then throttle the port.
1952 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001953 if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
Alan Coxb5391e22008-07-16 21:55:20 +01001954 port->gs.port.flags |= SX_RX_THROTTLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 }
1956 func_exit();
1957}
1958
Jiri Slaby15b611f2006-12-08 02:39:04 -08001959static void sx_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960{
Alan Coxc9f19e92009-01-02 13:47:26 +00001961 struct sx_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962
1963 func_enter2();
1964 /* Always unthrottle even if flow control is not enabled on
1965 * this port in case we disabled flow control while the port
1966 * was throttled
1967 */
Alan Coxb5391e22008-07-16 21:55:20 +01001968 port->gs.port.flags &= ~SX_RX_THROTTLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 func_exit();
1970 return;
1971}
1972
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973/* ********************************************************************** *
1974 * Here are the initialization routines. *
1975 * ********************************************************************** */
1976
Jiri Slaby15b611f2006-12-08 02:39:04 -08001977static int sx_init_board(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978{
1979 int addr;
1980 int chans;
1981 int type;
1982
1983 func_enter();
1984
1985 /* This is preceded by downloading the download code. */
1986
1987 board->flags |= SX_BOARD_INITIALIZED;
1988
Jiri Slaby15b611f2006-12-08 02:39:04 -08001989 if (read_sx_byte(board, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 /* CF boards may need this. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001991 write_sx_byte(board, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
1993 /* This resets the processor again, to make sure it didn't do any
1994 foolish things while we were downloading the image */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001995 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 return 0;
1997
Jiri Slaby15b611f2006-12-08 02:39:04 -08001998 sx_start_board(board);
1999 udelay(10);
2000 if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
2001 printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 return 0;
2003 }
2004
2005 /* Ok. So now the processor on the card is running. It gathered
2006 some info for us... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002007 sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
2008 if (sx_debug & SX_DEBUG_INIT)
2009 my_hd_io(board->base, 0x10);
2010 sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
2011 if (sx_debug & SX_DEBUG_INIT)
2012 my_hd_io(board->base + 0x80, 0x30);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Jiri Slaby15b611f2006-12-08 02:39:04 -08002014 sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
2015 "V%x.%02x,\n",
2016 read_sx_byte(board, 0), read_sx_byte(board, 1),
2017 read_sx_byte(board, 5), read_sx_byte(board, 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
Jiri Slaby15b611f2006-12-08 02:39:04 -08002019 if (read_sx_byte(board, 0) == 0xff) {
2020 printk(KERN_INFO "sx: No modules found. Sorry.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 board->nports = 0;
2022 return 0;
2023 }
2024
2025 chans = 0;
2026
2027 if (IS_SX_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002028 sx_write_board_word(board, cc_int_count, sx_maxints);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 } else {
2030 if (sx_maxints)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002031 sx_write_board_word(board, cc_int_count,
2032 SI_PROCESSOR_CLOCK / 8 / sx_maxints);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
2034
2035 /* grab the first module type... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002036 /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
2037 board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
2038 mc_chip));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
2040 /* XXX byteorder */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002041 for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
2042 type = sx_read_module_byte(board, addr, mc_chip);
2043 sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
2044 addr, read_sx_byte(board, addr + 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
Jiri Slaby15b611f2006-12-08 02:39:04 -08002046 chans += sx_read_module_byte(board, addr, mc_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047
Jiri Slaby15b611f2006-12-08 02:39:04 -08002048 sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
2049 "panels\n",
2050 mod_type_s(type),
2051 pan_type_s(sx_read_module_byte(board, addr,
2052 mc_mods) & 0xf),
2053 pan_type_s(sx_read_module_byte(board, addr,
2054 mc_mods) >> 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055
Jiri Slaby15b611f2006-12-08 02:39:04 -08002056 sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
2057 "version: %x\n",
2058 sx_read_module_byte(board, addr, mc_rev1),
2059 sx_read_module_byte(board, addr, mc_rev2),
2060 sx_read_module_byte(board, addr, mc_mtaasic_rev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
2062 /* The following combinations are illegal: It should theoretically
2063 work, but timing problems make the bus HANG. */
2064
Jiri Slaby15b611f2006-12-08 02:39:04 -08002065 if (mod_compat_type(type) != board->ta_type) {
2066 printk(KERN_ERR "sx: This is an invalid "
2067 "configuration.\nDon't mix TA/MTA/SXDC on the "
2068 "same hostadapter.\n");
2069 chans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 break;
2071 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002072 if ((IS_EISA_BOARD(board) ||
2073 IS_SI_BOARD(board)) &&
2074 (mod_compat_type(type) == 4)) {
2075 printk(KERN_ERR "sx: This is an invalid "
2076 "configuration.\nDon't use SXDCs on an SI/XIO "
2077 "adapter.\n");
2078 chans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 break;
2080 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002081#if 0 /* Problem fixed: firmware 3.05 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 if (IS_SX_BOARD(board) && (type == TA8)) {
2083 /* There are some issues with the firmware and the DCD/RTS
2084 lines. It might work if you tie them together or something.
Jiri Slaby15b611f2006-12-08 02:39:04 -08002085 It might also work if you get a newer sx_firmware. Therefore
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 this is just a warning. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002087 printk(KERN_WARNING
2088 "sx: The SX host doesn't work too well "
2089 "with the TA8 adapters.\nSpecialix is working on it.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 }
2091#endif
2092 }
2093
2094 if (chans) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002095 if (board->irq > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 /* fixed irq, probably PCI */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002097 if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */
2098 if (request_irq(board->irq, sx_interrupt,
2099 IRQF_SHARED | IRQF_DISABLED,
2100 "sx", board)) {
2101 printk(KERN_ERR "sx: Cannot allocate "
2102 "irq %d.\n", board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 board->irq = 0;
2104 }
2105 } else
2106 board->irq = 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002107 } else if (board->irq < 0 && sx_irqmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 /* auto-allocate irq */
2109 int irqnr;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002110 int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
2111 SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
2112 for (irqnr = 15; irqnr > 0; irqnr--)
2113 if (irqmask & (1 << irqnr))
2114 if (!request_irq(irqnr, sx_interrupt,
2115 IRQF_SHARED | IRQF_DISABLED,
2116 "sx", board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002118 if (!irqnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
2120 board->irq = irqnr;
2121 } else
2122 board->irq = 0;
2123
2124 if (board->irq) {
2125 /* Found a valid interrupt, start up interrupts! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002126 sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
2127 board->irq);
2128 sx_start_interrupts(board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 board->poll = sx_slowpoll;
2130 board->flags |= SX_IRQ_ALLOCATED;
2131 } else {
2132 /* no irq: setup board for polled operation */
2133 board->poll = sx_poll;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002134 sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
2135 board->poll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 }
2137
Jiri Slaby15b611f2006-12-08 02:39:04 -08002138 /* The timer should be initialized anyway: That way we can
2139 safely del_timer it when the module is unloaded. */
Jiri Slabyc9594642006-12-08 02:39:05 -08002140 setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141
Jiri Slabyc9594642006-12-08 02:39:05 -08002142 if (board->poll)
2143 mod_timer(&board->timer, jiffies + board->poll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 } else {
2145 board->irq = 0;
2146 }
2147
2148 board->nports = chans;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002149 sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150
2151 func_exit();
2152 return chans;
2153}
2154
Jiri Slabycda52652006-12-08 02:39:00 -08002155static void __devinit printheader(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
2157 static int header_printed;
2158
2159 if (!header_printed) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002160 printk(KERN_INFO "Specialix SX driver "
2161 "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
2162 printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 header_printed = 1;
2164 }
2165}
2166
Jiri Slaby15b611f2006-12-08 02:39:04 -08002167static int __devinit probe_sx(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168{
2169 struct vpd_prom vpdp;
2170 char *p;
2171 int i;
2172
2173 func_enter();
2174
Jiri Slaby15b611f2006-12-08 02:39:04 -08002175 if (!IS_CF_BOARD(board)) {
2176 sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
2177 board->base + SX_VPD_ROM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178
2179 if (sx_debug & SX_DEBUG_PROBE)
2180 my_hd_io(board->base + SX_VPD_ROM, 0x40);
2181
Jiri Slaby15b611f2006-12-08 02:39:04 -08002182 p = (char *)&vpdp;
2183 for (i = 0; i < sizeof(struct vpd_prom); i++)
2184 *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185
2186 if (sx_debug & SX_DEBUG_PROBE)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002187 my_hd(&vpdp, 0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
Jiri Slaby15b611f2006-12-08 02:39:04 -08002189 sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Jiri Slaby15b611f2006-12-08 02:39:04 -08002191 if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
2192 sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
2193 "'%s'\n", vpdp.identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 return 0;
2195 }
2196 }
2197
Jiri Slaby15b611f2006-12-08 02:39:04 -08002198 printheader();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199
Jiri Slaby15b611f2006-12-08 02:39:04 -08002200 if (!IS_CF_BOARD(board)) {
2201 printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
2202 board->hw_base);
2203 printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
2204 "uniq ID:%08x, ",
2205 vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
2206 printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
Jiri Slaby15b611f2006-12-08 02:39:04 -08002208 if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
2209 SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
2210 SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
2211 /* This might be a bit harsh. This was the primary
2212 reason the SX/ISA card didn't work at first... */
2213 printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
2214 "card. Sorry: giving up.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 return (0);
2216 }
2217
Jiri Slaby15b611f2006-12-08 02:39:04 -08002218 if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
2219 SX_ISA_UNIQUEID1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 if (((unsigned long)board->hw_base) & 0x8000) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002221 printk(KERN_WARNING "sx: Warning: There may be "
2222 "hardware problems with the card at "
2223 "%lx.\n", board->hw_base);
2224 printk(KERN_WARNING "sx: Read sx.txt for more "
2225 "info.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 }
2227 }
2228 }
2229
2230 board->nports = -1;
2231
2232 /* This resets the processor, and keeps it off the bus. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002233 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 return 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002235 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 func_exit();
2238 return 1;
2239}
2240
Jiri Slaby927a6f92006-12-08 02:39:02 -08002241#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
2243/* Specialix probes for this card at 32k increments from 640k to 16M.
2244 I consider machines with less than 16M unlikely nowadays, so I'm
2245 not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA
2246 card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves
2247 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
2248
Jiri Slaby15b611f2006-12-08 02:39:04 -08002249static int __devinit probe_si(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250{
2251 int i;
2252
2253 func_enter();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002254 sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
2255 "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256
2257 if (sx_debug & SX_DEBUG_PROBE)
2258 my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
2259
2260 if (!IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002261 if (IS_SI1_BOARD(board)) {
2262 for (i = 0; i < 8; i++) {
2263 write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
2264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002266 for (i = 0; i < 8; i++) {
2267 if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
2268 != i) {
2269 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 return 0;
2271 }
2272 }
2273 }
2274
2275 /* Now we're pretty much convinced that there is an SI board here,
2276 but to prevent trouble, we'd better double check that we don't
2277 have an SI1 board when we're probing for an SI2 board.... */
2278
Jiri Slaby15b611f2006-12-08 02:39:04 -08002279 write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
2280 if (IS_SI1_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 /* This should be an SI1 board, which has this
2282 location writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002283 if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
2284 func_exit();
2285 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002286 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 } else {
2288 /* This should be an SI2 board, which has the bottom
2289 3 bits non-writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002290 if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
2291 func_exit();
2292 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 }
2295
2296 /* Now we're pretty much convinced that there is an SI board here,
2297 but to prevent trouble, we'd better double check that we don't
2298 have an SI1 board when we're probing for an SI2 board.... */
2299
Jiri Slaby15b611f2006-12-08 02:39:04 -08002300 write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
2301 if (IS_SI1_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 /* This should be an SI1 board, which has this
2303 location writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002304 if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 func_exit();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002306 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002307 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 } else {
2309 /* This should be an SI2 board, which has the bottom
2310 3 bits non-writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002311 if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
2312 func_exit();
2313 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002314 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 }
2316
Jiri Slaby15b611f2006-12-08 02:39:04 -08002317 printheader();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318
Jiri Slaby15b611f2006-12-08 02:39:04 -08002319 printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 /* Compared to the SX boards, it is a complete guess as to what
Jiri Slaby15b611f2006-12-08 02:39:04 -08002321 this card is up to... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
2323 board->nports = -1;
2324
2325 /* This resets the processor, and keeps it off the bus. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002326 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 return 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002328 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 func_exit();
2331 return 1;
2332}
Jiri Slaby927a6f92006-12-08 02:39:02 -08002333#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002335static const struct tty_operations sx_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 .break_ctl = sx_break,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002337 .open = sx_open,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 .close = gs_close,
2339 .write = gs_write,
2340 .put_char = gs_put_char,
2341 .flush_chars = gs_flush_chars,
2342 .write_room = gs_write_room,
2343 .chars_in_buffer = gs_chars_in_buffer,
2344 .flush_buffer = gs_flush_buffer,
2345 .ioctl = sx_ioctl,
2346 .throttle = sx_throttle,
2347 .unthrottle = sx_unthrottle,
2348 .set_termios = gs_set_termios,
2349 .stop = gs_stop,
2350 .start = gs_start,
2351 .hangup = gs_hangup,
2352 .tiocmget = sx_tiocmget,
2353 .tiocmset = sx_tiocmset,
2354};
2355
Alan Cox31f35932009-01-02 13:45:05 +00002356static const struct tty_port_operations sx_port_ops = {
2357 .carrier_raised = sx_carrier_raised,
2358};
2359
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360static int sx_init_drivers(void)
2361{
2362 int error;
2363
2364 func_enter();
2365
2366 sx_driver = alloc_tty_driver(sx_nports);
2367 if (!sx_driver)
2368 return 1;
2369 sx_driver->owner = THIS_MODULE;
2370 sx_driver->driver_name = "specialix_sx";
2371 sx_driver->name = "ttyX";
2372 sx_driver->major = SX_NORMAL_MAJOR;
2373 sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
2374 sx_driver->subtype = SERIAL_TYPE_NORMAL;
2375 sx_driver->init_termios = tty_std_termios;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002376 sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Alan Cox606d0992006-12-08 02:38:45 -08002377 sx_driver->init_termios.c_ispeed = 9600;
2378 sx_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 sx_driver->flags = TTY_DRIVER_REAL_RAW;
2380 tty_set_operations(sx_driver, &sx_ops);
2381
2382 if ((error = tty_register_driver(sx_driver))) {
2383 put_tty_driver(sx_driver);
2384 printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
Jiri Slaby15b611f2006-12-08 02:39:04 -08002385 error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 return 1;
2387 }
2388 func_exit();
2389 return 0;
2390}
2391
Jiri Slaby15b611f2006-12-08 02:39:04 -08002392static int sx_init_portstructs(int nboards, int nports)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393{
2394 struct sx_board *board;
2395 struct sx_port *port;
2396 int i, j;
2397 int addr, chans;
2398 int portno;
2399
2400 func_enter();
2401
2402 /* Many drivers statically allocate the maximum number of ports
Jiri Slaby15b611f2006-12-08 02:39:04 -08002403 There is no reason not to allocate them dynamically.
2404 Is there? -- REW */
Jiri Slaby4a7cb692006-12-08 02:38:59 -08002405 sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 if (!sx_ports)
2407 return -ENOMEM;
2408
2409 port = sx_ports;
2410 for (i = 0; i < nboards; i++) {
2411 board = &boards[i];
2412 board->ports = port;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002413 for (j = 0; j < boards[i].nports; j++) {
2414 sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
Alan Cox44b7d1b2008-07-16 21:57:18 +01002415 tty_port_init(&port->gs.port);
Alan Cox31f35932009-01-02 13:45:05 +00002416 port->gs.port.ops = &sx_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 port->gs.magic = SX_MAGIC;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002418 port->gs.close_delay = HZ / 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 port->gs.closing_wait = 30 * HZ;
2420 port->board = board;
2421 port->gs.rd = &sx_real_driver;
2422#ifdef NEW_WRITE_LOCKING
Ingo Molnar81861d72006-03-23 03:00:44 -08002423 port->gs.port_write_mutex = MUTEX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424#endif
Ingo Molnar34af9462006-06-27 02:53:55 -07002425 spin_lock_init(&port->gs.driver_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 /*
2427 * Initializing wait queue
2428 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 port++;
2430 }
2431 }
2432
2433 port = sx_ports;
2434 portno = 0;
2435 for (i = 0; i < nboards; i++) {
2436 board = &boards[i];
2437 board->port_base = portno;
2438 /* Possibly the configuration was rejected. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002439 sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
2440 board->nports);
2441 if (board->nports <= 0)
2442 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 /* XXX byteorder ?? */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002444 for (addr = 0x80; addr != 0;
2445 addr = read_sx_word(board, addr) & 0x7fff) {
2446 chans = sx_read_module_byte(board, addr, mc_type);
2447 sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
2448 "channels\n", addr, chans);
2449 sx_dprintk(SX_DEBUG_PROBE, "Port at");
2450 for (j = 0; j < chans; j++) {
2451 /* The "sx-way" is the way it SHOULD be done.
2452 That way in the future, the firmware may for
2453 example pack the structures a bit more
2454 efficient. Neil tells me it isn't going to
2455 happen anytime soon though. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 if (IS_SX_BOARD(board))
Jiri Slaby15b611f2006-12-08 02:39:04 -08002457 port->ch_base = sx_read_module_word(
2458 board, addr + j * 2,
2459 mc_chan_pointer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 else
Jiri Slaby15b611f2006-12-08 02:39:04 -08002461 port->ch_base = addr + 0x100 + 0x300 *j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
Jiri Slaby15b611f2006-12-08 02:39:04 -08002463 sx_dprintk(SX_DEBUG_PROBE, " %x",
2464 port->ch_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 port->line = portno++;
2466 port++;
2467 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002468 sx_dprintk(SX_DEBUG_PROBE, "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 }
2470 /* This has to be done earlier. */
2471 /* board->flags |= SX_BOARD_INITIALIZED; */
2472 }
2473
2474 func_exit();
2475 return 0;
2476}
2477
Jiri Slaby18f813e2006-12-08 02:39:01 -08002478static unsigned int sx_find_free_board(void)
2479{
2480 unsigned int i;
2481
Jiri Slaby15b611f2006-12-08 02:39:04 -08002482 for (i = 0; i < SX_NBOARDS; i++)
Jiri Slaby18f813e2006-12-08 02:39:01 -08002483 if (!(boards[i].flags & SX_BOARD_PRESENT))
2484 break;
2485
2486 return i;
2487}
2488
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489static void __exit sx_release_drivers(void)
2490{
2491 func_enter();
2492 tty_unregister_driver(sx_driver);
2493 put_tty_driver(sx_driver);
2494 func_exit();
2495}
2496
Jiri Slaby39103492006-12-08 02:39:07 -08002497static void __devexit sx_remove_card(struct sx_board *board,
2498 struct pci_dev *pdev)
Jiri Slaby18f813e2006-12-08 02:39:01 -08002499{
2500 if (board->flags & SX_BOARD_INITIALIZED) {
2501 /* The board should stop messing with us. (actually I mean the
2502 interrupt) */
2503 sx_reset(board);
2504 if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
2505 free_irq(board->irq, board);
2506
2507 /* It is safe/allowed to del_timer a non-active timer */
2508 del_timer(&board->timer);
Jiri Slaby30f42182006-12-08 02:39:08 -08002509 if (pdev) {
Jiri Slaby3468a332006-12-13 00:34:20 -08002510#ifdef CONFIG_PCI
Jiri Slabyda1cfe12008-10-18 20:27:44 -07002511 iounmap(board->base2);
Jiri Slaby30f42182006-12-08 02:39:08 -08002512 pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
Jiri Slaby3468a332006-12-13 00:34:20 -08002513#endif
Jiri Slaby30f42182006-12-08 02:39:08 -08002514 } else {
Jiri Slaby39103492006-12-08 02:39:07 -08002515 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002516 release_region(board->hw_base, board->hw_len);
2517 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002518
Jiri Slaby15b611f2006-12-08 02:39:04 -08002519 board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002520 }
2521}
2522
2523#ifdef CONFIG_EISA
2524
2525static int __devinit sx_eisa_probe(struct device *dev)
2526{
2527 struct eisa_device *edev = to_eisa_device(dev);
2528 struct sx_board *board;
2529 unsigned long eisa_slot = edev->base_addr;
2530 unsigned int i;
2531 int retval = -EIO;
2532
Jiri Slaby42f63842006-12-08 02:39:03 -08002533 mutex_lock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002534 i = sx_find_free_board();
Jiri Slaby42f63842006-12-08 02:39:03 -08002535 if (i == SX_NBOARDS) {
2536 mutex_unlock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002537 goto err;
Jiri Slaby42f63842006-12-08 02:39:03 -08002538 }
2539 board = &boards[i];
2540 board->flags |= SX_BOARD_PRESENT;
2541 mutex_unlock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002542
2543 dev_info(dev, "XIO : Signature found in EISA slot %lu, "
Jiri Slaby15b611f2006-12-08 02:39:04 -08002544 "Product %d Rev %d (REPORT THIS TO LKLM)\n",
2545 eisa_slot >> 12,
2546 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
2547 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
Jiri Slaby18f813e2006-12-08 02:39:01 -08002548
Jiri Slaby18f813e2006-12-08 02:39:01 -08002549 board->eisa_base = eisa_slot;
2550 board->flags &= ~SX_BOARD_TYPE;
2551 board->flags |= SI_EISA_BOARD;
2552
2553 board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
Jiri Slaby15b611f2006-12-08 02:39:04 -08002554 inb(eisa_slot + 0xc00)) << 16;
Jiri Slaby30f42182006-12-08 02:39:08 -08002555 board->hw_len = SI2_EISA_WINDOW_LEN;
2556 if (!request_region(board->hw_base, board->hw_len, "sx")) {
2557 dev_err(dev, "can't request region\n");
2558 goto err_flag;
2559 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002560 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002561 board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
Jiri Slaby30f42182006-12-08 02:39:08 -08002562 if (!board->base) {
2563 dev_err(dev, "can't remap memory\n");
2564 goto err_reg;
2565 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002566
2567 sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
2568 sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
2569 board->irq = inb(eisa_slot + 0xc02) >> 4;
2570 sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
2571
2572 if (!probe_si(board))
2573 goto err_unmap;
2574
2575 dev_set_drvdata(dev, board);
2576
2577 return 0;
2578err_unmap:
2579 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002580err_reg:
2581 release_region(board->hw_base, board->hw_len);
2582err_flag:
Jiri Slaby42f63842006-12-08 02:39:03 -08002583 board->flags &= ~SX_BOARD_PRESENT;
Jiri Slaby18f813e2006-12-08 02:39:01 -08002584err:
2585 return retval;
2586}
2587
2588static int __devexit sx_eisa_remove(struct device *dev)
2589{
2590 struct sx_board *board = dev_get_drvdata(dev);
2591
Jiri Slaby39103492006-12-08 02:39:07 -08002592 sx_remove_card(board, NULL);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002593
2594 return 0;
2595}
2596
2597static struct eisa_device_id sx_eisa_tbl[] = {
2598 { "SLX" },
2599 { "" }
2600};
Jiri Slaby15b611f2006-12-08 02:39:04 -08002601
Jiri Slaby18f813e2006-12-08 02:39:01 -08002602MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
2603
2604static struct eisa_driver sx_eisadriver = {
2605 .id_table = sx_eisa_tbl,
2606 .driver = {
2607 .name = "sx",
2608 .probe = sx_eisa_probe,
2609 .remove = __devexit_p(sx_eisa_remove),
2610 }
2611};
2612
2613#endif
2614
Jiri Slaby3468a332006-12-13 00:34:20 -08002615#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 /********************************************************
2617 * Setting bit 17 in the CNTRL register of the PLX 9050 *
2618 * chip forces a retry on writes while a read is pending.*
2619 * This is to prevent the card locking up on Intel Xeon *
2620 * multiprocessor systems with the NX chipset. -- NV *
2621 ********************************************************/
2622
2623/* Newer cards are produced with this bit set from the configuration
2624 EEprom. As the bit is read/write for the CPU, we can fix it here,
2625 if we detect that it isn't set correctly. -- REW */
2626
Jiri Slabycda52652006-12-08 02:39:00 -08002627static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628{
2629 unsigned int hwbase;
2630 void __iomem *rebase;
2631 unsigned int t;
2632
Jiri Slaby15b611f2006-12-08 02:39:04 -08002633#define CNTRL_REG_OFFSET 0x50
2634#define CNTRL_REG_GOODVALUE 0x18260000
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
2636 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
2637 hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
Alan Cox24cb2332008-04-30 00:54:19 -07002638 rebase = ioremap_nocache(hwbase, 0x80);
Jiri Slaby15b611f2006-12-08 02:39:04 -08002639 t = readl(rebase + CNTRL_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 if (t != CNTRL_REG_GOODVALUE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002641 printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
2642 "%08x\n", t, CNTRL_REG_GOODVALUE);
2643 writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 }
2645 iounmap(rebase);
2646}
Jiri Slaby3468a332006-12-13 00:34:20 -08002647#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
Jiri Slaby5572e102006-12-08 02:38:58 -08002649static int __devinit sx_pci_probe(struct pci_dev *pdev,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002650 const struct pci_device_id *ent)
Jiri Slaby5572e102006-12-08 02:38:58 -08002651{
Jiri Slaby3468a332006-12-13 00:34:20 -08002652#ifdef CONFIG_PCI
Jiri Slaby5572e102006-12-08 02:38:58 -08002653 struct sx_board *board;
Jiri Slaby39103492006-12-08 02:39:07 -08002654 unsigned int i, reg;
Jiri Slaby5572e102006-12-08 02:38:58 -08002655 int retval = -EIO;
2656
Jiri Slaby42f63842006-12-08 02:39:03 -08002657 mutex_lock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002658 i = sx_find_free_board();
Jiri Slaby42f63842006-12-08 02:39:03 -08002659 if (i == SX_NBOARDS) {
2660 mutex_unlock(&sx_boards_lock);
Jiri Slaby5572e102006-12-08 02:38:58 -08002661 goto err;
Jiri Slaby42f63842006-12-08 02:39:03 -08002662 }
2663 board = &boards[i];
2664 board->flags |= SX_BOARD_PRESENT;
2665 mutex_unlock(&sx_boards_lock);
Jiri Slaby5572e102006-12-08 02:38:58 -08002666
2667 retval = pci_enable_device(pdev);
2668 if (retval)
Jiri Slaby42f63842006-12-08 02:39:03 -08002669 goto err_flag;
Jiri Slaby5572e102006-12-08 02:38:58 -08002670
2671 board->flags &= ~SX_BOARD_TYPE;
2672 board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
Jiri Slaby15b611f2006-12-08 02:39:04 -08002673 SX_CFPCI_BOARD;
Jiri Slaby5572e102006-12-08 02:38:58 -08002674
2675 /* CF boards use base address 3.... */
Jiri Slaby39103492006-12-08 02:39:07 -08002676 reg = IS_CF_BOARD(board) ? 3 : 2;
Jiri Slaby30f42182006-12-08 02:39:08 -08002677 retval = pci_request_region(pdev, reg, "sx");
2678 if (retval) {
2679 dev_err(&pdev->dev, "can't request region\n");
2680 goto err_flag;
2681 }
Jiri Slaby39103492006-12-08 02:39:07 -08002682 board->hw_base = pci_resource_start(pdev, reg);
Jiri Slaby5572e102006-12-08 02:38:58 -08002683 board->base2 =
Jiri Slabyda1cfe12008-10-18 20:27:44 -07002684 board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board));
Jiri Slaby5572e102006-12-08 02:38:58 -08002685 if (!board->base) {
2686 dev_err(&pdev->dev, "ioremap failed\n");
Jiri Slaby30f42182006-12-08 02:39:08 -08002687 goto err_reg;
Jiri Slaby5572e102006-12-08 02:38:58 -08002688 }
2689
2690 /* Most of the stuff on the CF board is offset by 0x18000 .... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002691 if (IS_CF_BOARD(board))
Jiri Slaby5572e102006-12-08 02:38:58 -08002692 board->base += 0x18000;
2693
2694 board->irq = pdev->irq;
2695
2696 dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002697 board->irq, board->flags);
Jiri Slaby5572e102006-12-08 02:38:58 -08002698
2699 if (!probe_sx(board)) {
2700 retval = -EIO;
2701 goto err_unmap;
2702 }
2703
2704 fix_sx_pci(pdev, board);
2705
2706 pci_set_drvdata(pdev, board);
2707
2708 return 0;
2709err_unmap:
Jiri Slabyda1cfe12008-10-18 20:27:44 -07002710 iounmap(board->base2);
Jiri Slaby30f42182006-12-08 02:39:08 -08002711err_reg:
2712 pci_release_region(pdev, reg);
Jiri Slaby42f63842006-12-08 02:39:03 -08002713err_flag:
2714 board->flags &= ~SX_BOARD_PRESENT;
Jiri Slaby5572e102006-12-08 02:38:58 -08002715err:
2716 return retval;
Jiri Slaby3468a332006-12-13 00:34:20 -08002717#else
2718 return -ENODEV;
2719#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002720}
2721
2722static void __devexit sx_pci_remove(struct pci_dev *pdev)
2723{
2724 struct sx_board *board = pci_get_drvdata(pdev);
2725
Jiri Slaby39103492006-12-08 02:39:07 -08002726 sx_remove_card(board, pdev);
Jiri Slaby5572e102006-12-08 02:38:58 -08002727}
2728
2729/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
2730 its because the standard requires it. So check for SUBVENDOR_ID. */
2731static struct pci_device_id sx_pci_tbl[] = {
2732 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
Jiri Slabyc14d4442007-07-10 17:22:25 -07002733 .subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
Jiri Slaby5572e102006-12-08 02:38:58 -08002734 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
Jiri Slabyc14d4442007-07-10 17:22:25 -07002735 .subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
Jiri Slaby5572e102006-12-08 02:38:58 -08002736 { 0 }
2737};
Jiri Slaby15b611f2006-12-08 02:39:04 -08002738
Jiri Slaby5572e102006-12-08 02:38:58 -08002739MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
2740
2741static struct pci_driver sx_pcidriver = {
2742 .name = "sx",
2743 .id_table = sx_pci_tbl,
2744 .probe = sx_pci_probe,
2745 .remove = __devexit_p(sx_pci_remove)
2746};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747
Jiri Slaby15b611f2006-12-08 02:39:04 -08002748static int __init sx_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749{
Jiri Slaby18f813e2006-12-08 02:39:01 -08002750#ifdef CONFIG_EISA
2751 int retval1;
2752#endif
Jiri Slaby927a6f92006-12-08 02:39:02 -08002753#ifdef CONFIG_ISA
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754 struct sx_board *board;
Jiri Slaby927a6f92006-12-08 02:39:02 -08002755 unsigned int i;
2756#endif
2757 unsigned int found = 0;
2758 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 func_enter();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002761 sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
2762 sx_debug);
2763 if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
2764 printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
2765 "value. Assuming -1.\n(%p)\n", &sx_debug);
2766 sx_debug = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 }
2768
2769 if (misc_register(&sx_fw_device) < 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002770 printk(KERN_ERR "SX: Unable to register firmware loader "
2771 "driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 return -EIO;
2773 }
Jiri Slaby927a6f92006-12-08 02:39:02 -08002774#ifdef CONFIG_ISA
Jiri Slaby15b611f2006-12-08 02:39:04 -08002775 for (i = 0; i < NR_SX_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 board = &boards[found];
2777 board->hw_base = sx_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002778 board->hw_len = SX_WINDOW_LEN;
2779 if (!request_region(board->hw_base, board->hw_len, "sx"))
2780 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002782 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002783 if (!board->base)
2784 goto err_sx_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002786 board->flags |= SX_ISA_BOARD;
2787 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788
Jiri Slaby15b611f2006-12-08 02:39:04 -08002789 if (probe_sx(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002790 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 found++;
2792 } else {
2793 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002794err_sx_reg:
2795 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 }
2797 }
2798
Jiri Slaby15b611f2006-12-08 02:39:04 -08002799 for (i = 0; i < NR_SI_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 board = &boards[found];
2801 board->hw_base = si_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002802 board->hw_len = SI2_ISA_WINDOW_LEN;
2803 if (!request_region(board->hw_base, board->hw_len, "sx"))
2804 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002806 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002807 if (!board->base)
2808 goto err_si_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002810 board->flags |= SI_ISA_BOARD;
2811 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
Jiri Slaby15b611f2006-12-08 02:39:04 -08002813 if (probe_si(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002814 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 found++;
2816 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002817 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002818err_si_reg:
2819 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 }
2821 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002822 for (i = 0; i < NR_SI1_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 board = &boards[found];
2824 board->hw_base = si1_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002825 board->hw_len = SI1_ISA_WINDOW_LEN;
2826 if (!request_region(board->hw_base, board->hw_len, "sx"))
2827 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002829 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002830 if (!board->base)
2831 goto err_si1_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002833 board->flags |= SI1_ISA_BOARD;
2834 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
Jiri Slaby15b611f2006-12-08 02:39:04 -08002836 if (probe_si(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002837 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 found++;
2839 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002840 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002841err_si1_reg:
2842 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 }
2844 }
Jiri Slaby927a6f92006-12-08 02:39:02 -08002845#endif
Jiri Slaby18f813e2006-12-08 02:39:01 -08002846#ifdef CONFIG_EISA
2847 retval1 = eisa_driver_register(&sx_eisadriver);
2848#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002849 retval = pci_register_driver(&sx_pcidriver);
2850
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851 if (found) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002852 printk(KERN_INFO "sx: total of %d boards detected.\n", found);
Jiri Slaby5572e102006-12-08 02:38:58 -08002853 retval = 0;
2854 } else if (retval) {
Jiri Slaby18f813e2006-12-08 02:39:01 -08002855#ifdef CONFIG_EISA
Jiri Slaby7eb99762006-12-08 02:39:06 -08002856 retval = retval1;
Jiri Slaby18f813e2006-12-08 02:39:01 -08002857 if (retval1)
2858#endif
Jiri Slaby15b611f2006-12-08 02:39:04 -08002859 misc_deregister(&sx_fw_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 }
2861
2862 func_exit();
Jiri Slaby5572e102006-12-08 02:38:58 -08002863 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864}
2865
Jiri Slaby15b611f2006-12-08 02:39:04 -08002866static void __exit sx_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867{
Jiri Slaby15b611f2006-12-08 02:39:04 -08002868 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869
2870 func_enter();
Jiri Slaby18f813e2006-12-08 02:39:01 -08002871#ifdef CONFIG_EISA
2872 eisa_driver_unregister(&sx_eisadriver);
2873#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002874 pci_unregister_driver(&sx_pcidriver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875
Jiri Slaby55e70712006-12-08 02:39:03 -08002876 for (i = 0; i < SX_NBOARDS; i++)
Jiri Slaby39103492006-12-08 02:39:07 -08002877 sx_remove_card(&boards[i], NULL);
Jiri Slaby55e70712006-12-08 02:39:03 -08002878
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 if (misc_deregister(&sx_fw_device) < 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002880 printk(KERN_INFO "sx: couldn't deregister firmware loader "
2881 "device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002883 sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
2884 sx_initialized);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885 if (sx_initialized)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002886 sx_release_drivers();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
Jiri Slaby15b611f2006-12-08 02:39:04 -08002888 kfree(sx_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 func_exit();
2890}
2891
2892module_init(sx_init);
2893module_exit(sx_exit);