blob: 401ebab26018e17d34e8d27477488512386cb59d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001
2/* sx.c -- driver for the Specialix SX series cards.
3 *
4 * This driver will also support the older SI, and XIO cards.
5 *
6 *
7 * (C) 1998 - 2004 R.E.Wolff@BitWizard.nl
8 *
9 * Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
10 * version of this driver. Some fragments may have been copied. (none
11 * yet :-)
12 *
13 * Specialix pays for the development and support of this driver.
14 * Please DO contact support@specialix.co.uk if you require
15 * support. But please read the documentation (sx.txt) first.
16 *
17 *
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License as
21 * published by the Free Software Foundation; either version 2 of
22 * the License, or (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be
25 * useful, but WITHOUT ANY WARRANTY; without even the implied
26 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
27 * PURPOSE. See the GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public
30 * License along with this program; if not, write to the Free
31 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
32 * USA.
33 *
34 * Revision history:
Linus Torvalds1da177e2005-04-16 15:20:36 -070035 * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff
36 * - Fixed module and port counting
37 * - Fixed signal handling
38 * - Fixed an Ooops
39 *
40 * Revision 1.32 2000/03/07 09:00:00 wolff,pvdl
41 * - Fixed some sx_dprintk typos
42 * - added detection for an invalid board/module configuration
43 *
44 * Revision 1.31 2000/03/06 12:00:00 wolff,pvdl
45 * - Added support for EISA
46 *
47 * Revision 1.30 2000/01/21 17:43:06 wolff
48 * - Added support for SX+
49 *
50 * Revision 1.26 1999/08/05 15:22:14 wolff
51 * - Port to 2.3.x
52 * - Reformatted to Linus' liking.
53 *
54 * Revision 1.25 1999/07/30 14:24:08 wolff
55 * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0).
56 *
57 * Revision 1.24 1999/07/28 09:41:52 wolff
58 * - I noticed the remark about use-count straying in sx.txt. I checked
59 * sx_open, and found a few places where that could happen. I hope it's
60 * fixed now.
61 *
62 * Revision 1.23 1999/07/28 08:56:06 wolff
63 * - Fixed crash when sx_firmware run twice.
64 * - Added sx_slowpoll as a module parameter (I guess nobody really wanted
65 * to change it from the default... )
66 * - Fixed a stupid editing problem I introduced in 1.22.
67 * - Fixed dropping characters on a termios change.
68 *
69 * Revision 1.22 1999/07/26 21:01:43 wolff
70 * Russell Brown noticed that I had overlooked 4 out of six modem control
71 * signals in sx_getsignals. Ooops.
72 *
73 * Revision 1.21 1999/07/23 09:11:33 wolff
74 * I forgot to free dynamically allocated memory when the driver is unloaded.
75 *
76 * Revision 1.20 1999/07/20 06:25:26 wolff
77 * The "closing wait" wasn't honoured. Thanks to James Griffiths for
78 * reporting this.
79 *
80 * Revision 1.19 1999/07/11 08:59:59 wolff
81 * Fixed an oops in close, when an open was pending. Changed the memtest
82 * a bit. Should also test the board in word-mode, however my card fails the
83 * memtest then. I still have to figure out what is wrong...
84 *
85 * Revision 1.18 1999/06/10 09:38:42 wolff
86 * Changed the format of the firmware revision from %04x to %x.%02x .
87 *
88 * Revision 1.17 1999/06/04 09:44:35 wolff
89 * fixed problem: reference to pci stuff when config_pci was off...
90 * Thanks to Jorge Novo for noticing this.
91 *
92 * Revision 1.16 1999/06/02 08:30:15 wolff
93 * added/removed the workaround for the DCD bug in the Firmware.
94 * A bit more debugging code to locate that...
95 *
96 * Revision 1.15 1999/06/01 11:35:30 wolff
97 * when DCD is left low (floating?), on TA's the firmware first tells us
98 * that DCD is high, but after a short while suddenly comes to the
99 * conclusion that it is low. All this would be fine, if it weren't that
100 * Unix requires us to send a "hangup" signal in that case. This usually
101 * all happens BEFORE the program has had a chance to ioctl the device
102 * into clocal mode..
103 *
104 * Revision 1.14 1999/05/25 11:18:59 wolff
105 * Added PCI-fix.
106 * Added checks for return code of sx_sendcommand.
107 * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...)
108 *
109 * Revision 1.13 1999/04/29 15:18:01 wolff
110 * Fixed an "oops" that showed on SuSE 6.0 systems.
111 * Activate DTR again after stty 0.
112 *
113 * Revision 1.12 1999/04/29 07:49:52 wolff
114 * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming
115 * the connection would be dropped anyway. That is not always the case,
116 * and confuses people).
117 * Told the card to always monitor the modem signals.
118 * Added support for dynamic gs_debug adjustments.
119 * Now tells the rest of the system the number of ports.
120 *
121 * Revision 1.11 1999/04/24 11:11:30 wolff
122 * Fixed two stupid typos in the memory test.
123 *
124 * Revision 1.10 1999/04/24 10:53:39 wolff
125 * Added some of Christian's suggestions.
126 * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the
127 * card to send the signal to the process.....)
128 *
129 * Revision 1.9 1999/04/23 07:26:38 wolff
130 * Included Christian Lademann's 2.0 compile-warning fixes and interrupt
131 * assignment redesign.
132 * Cleanup of some other stuff.
133 *
134 * Revision 1.8 1999/04/16 13:05:30 wolff
135 * fixed a DCD change unnoticed bug.
136 *
137 * Revision 1.7 1999/04/14 22:19:51 wolff
138 * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!)
139 *
140 * Revision 1.6 1999/04/13 18:40:20 wolff
141 * changed misc-minor to 161, as assigned by HPA.
142 *
143 * Revision 1.5 1999/04/13 15:12:25 wolff
144 * Fixed use-count leak when "hangup" occurred.
145 * Added workaround for a stupid-PCIBIOS bug.
146 *
147 *
148 * Revision 1.4 1999/04/01 22:47:40 wolff
149 * Fixed < 1M linux-2.0 problem.
150 * (vremap isn't compatible with ioremap in that case)
151 *
152 * Revision 1.3 1999/03/31 13:45:45 wolff
153 * Firmware loading is now done through a separate IOCTL.
154 *
155 * Revision 1.2 1999/03/28 12:22:29 wolff
156 * rcs cleanup
157 *
158 * Revision 1.1 1999/03/28 12:10:34 wolff
159 * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS).
160 *
161 * Revision 0.12 1999/03/28 09:20:10 wolff
162 * Fixed problem in 0.11, continueing cleanup.
163 *
164 * Revision 0.11 1999/03/28 08:46:44 wolff
165 * cleanup. Not good.
166 *
167 * Revision 0.10 1999/03/28 08:09:43 wolff
168 * Fixed loosing characters on close.
169 *
170 * Revision 0.9 1999/03/21 22:52:01 wolff
171 * Ported back to 2.2.... (minor things)
172 *
173 * Revision 0.8 1999/03/21 22:40:33 wolff
174 * Port to 2.0
175 *
176 * Revision 0.7 1999/03/21 19:06:34 wolff
177 * Fixed hangup processing.
178 *
179 * Revision 0.6 1999/02/05 08:45:14 wolff
180 * fixed real_raw problems. Inclusion into kernel imminent.
181 *
182 * Revision 0.5 1998/12/21 23:51:06 wolff
183 * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it
184 * shouldn't have. THATs why I want to have transmit interrupts even when
185 * the buffer is empty.
186 *
187 * Revision 0.4 1998/12/17 09:34:46 wolff
188 * PPP works. ioctl works. Basically works!
189 *
190 * Revision 0.3 1998/12/15 13:05:18 wolff
191 * It works! Wow! Gotta start implementing IOCTL and stuff....
192 *
193 * Revision 0.2 1998/12/01 08:33:53 wolff
194 * moved over to 2.1.130
195 *
196 * Revision 0.1 1998/11/03 21:23:51 wolff
197 * Initial revision. Detects SX card.
198 *
199 * */
200
Jiri Slaby11c83872006-12-08 02:38:56 -0800201#define SX_VERSION 1.33
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204#include <linux/kdev_t.h>
205#include <linux/kernel.h>
206#include <linux/sched.h>
207#include <linux/ioport.h>
208#include <linux/interrupt.h>
209#include <linux/errno.h>
210#include <linux/tty.h>
211#include <linux/tty_flip.h>
212#include <linux/mm.h>
213#include <linux/serial.h>
214#include <linux/fcntl.h>
215#include <linux/major.h>
216#include <linux/delay.h>
Jiri Slaby18f813e2006-12-08 02:39:01 -0800217#include <linux/eisa.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218#include <linux/pci.h>
219#include <linux/slab.h>
220#include <linux/init.h>
221#include <linux/miscdevice.h>
222#include <linux/bitops.h>
223
224#include <asm/io.h>
225#include <asm/uaccess.h>
226
227/* The 3.0.0 version of sxboards/sxwindow.h uses BYTE and WORD.... */
228#define BYTE u8
229#define WORD u16
230
231/* .... but the 3.0.4 version uses _u8 and _u16. */
232#define _u8 u8
233#define _u16 u16
234
235#include "sxboards.h"
236#include "sxwindow.h"
237
238#include <linux/generic_serial.h>
239#include "sx.h"
240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241/* I don't think that this driver can handle more than 256 ports on
242 one machine. You'll have to increase the number of boards in sx.h
243 if you want more than 4 boards. */
244
245#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
246#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
247#endif
248
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249/* Configurable options:
250 (Don't be too sure that it'll work if you toggle them) */
251
252/* Am I paranoid or not ? ;-) */
253#undef SX_PARANOIA_CHECK
254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
256 Hz, but it is user configurable. I don't recommend going above 1000
257 Hz. The interrupt ratelimit might trigger if the interrupt is
258 shared with a very active other device. */
259#define IRQ_RATE_LIMIT 20
260
261/* Sharing interrupts is possible now. If the other device wants more
262 than 2000 interrupts per second, we'd gracefully decline further
263 interrupts. That's not what we want. On the other hand, if the
264 other device interrupts 2000 times a second, don't use the SX
265 interrupt. Use polling. */
266#undef IRQ_RATE_LIMIT
267
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268#if 0
269/* Not implemented */
270/*
271 * The following defines are mostly for testing purposes. But if you need
272 * some nice reporting in your syslog, you can define them also.
273 */
274#define SX_REPORT_FIFO
275#define SX_REPORT_OVERRUN
Jiri Slaby15b611f2006-12-08 02:39:04 -0800276#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
278/* Function prototypes */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800279static void sx_disable_tx_interrupts(void *ptr);
280static void sx_enable_tx_interrupts(void *ptr);
281static void sx_disable_rx_interrupts(void *ptr);
282static void sx_enable_rx_interrupts(void *ptr);
283static int sx_get_CD(void *ptr);
284static void sx_shutdown_port(void *ptr);
285static int sx_set_real_termios(void *ptr);
286static void sx_close(void *ptr);
287static int sx_chars_in_buffer(void *ptr);
288static int sx_init_board(struct sx_board *board);
289static int sx_init_portstructs(int nboards, int nports);
290static int sx_fw_ioctl(struct inode *inode, struct file *filp,
291 unsigned int cmd, unsigned long arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292static int sx_init_drivers(void);
293
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294static struct tty_driver *sx_driver;
295
Jiri Slaby42f63842006-12-08 02:39:03 -0800296static DEFINE_MUTEX(sx_boards_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297static struct sx_board boards[SX_NBOARDS];
298static struct sx_port *sx_ports;
299static int sx_initialized;
300static int sx_nports;
301static int sx_debug;
302
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303/* You can have the driver poll your card.
304 - Set sx_poll to 1 to poll every timer tick (10ms on Intel).
305 This is used when the card cannot use an interrupt for some reason.
306
307 - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If
308 the driver misses an interrupt (report this if it DOES happen to you!)
309 everything will continue to work....
310 */
311static int sx_poll = 1;
312static int sx_slowpoll;
313
314/* The card limits the number of interrupts per second.
315 At 115k2 "100" should be sufficient.
316 If you're using higher baudrates, you can increase this...
317 */
318
319static int sx_maxints = 100;
320
Jiri Slaby927a6f92006-12-08 02:39:02 -0800321#ifdef CONFIG_ISA
322
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323/* These are the only open spaces in my computer. Yours may have more
324 or less.... -- REW
325 duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
326*/
Jiri Slaby15b611f2006-12-08 02:39:04 -0800327static int sx_probe_addrs[] = {
328 0xc0000, 0xd0000, 0xe0000,
329 0xc8000, 0xd8000, 0xe8000
330};
331static int si_probe_addrs[] = {
332 0xc0000, 0xd0000, 0xe0000,
333 0xc8000, 0xd8000, 0xe8000, 0xa0000
334};
335static int si1_probe_addrs[] = {
336 0xd0000
337};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Tobias Klauserfe971072006-01-09 20:54:02 -0800339#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
340#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
341#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
Jiri Slaby927a6f92006-12-08 02:39:02 -0800343module_param_array(sx_probe_addrs, int, NULL, 0);
344module_param_array(si_probe_addrs, int, NULL, 0);
345#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
347/* Set the mask to all-ones. This alas, only supports 32 interrupts.
348 Some architectures may need more. */
349static int sx_irqmask = -1;
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351module_param(sx_poll, int, 0);
352module_param(sx_slowpoll, int, 0);
353module_param(sx_maxints, int, 0);
354module_param(sx_debug, int, 0);
355module_param(sx_irqmask, int, 0);
356
357MODULE_LICENSE("GPL");
358
359static struct real_driver sx_real_driver = {
360 sx_disable_tx_interrupts,
361 sx_enable_tx_interrupts,
362 sx_disable_rx_interrupts,
363 sx_enable_rx_interrupts,
364 sx_get_CD,
Jiri Slaby15b611f2006-12-08 02:39:04 -0800365 sx_shutdown_port,
366 sx_set_real_termios,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 sx_chars_in_buffer,
368 sx_close,
369};
370
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371/*
372 This driver can spew a whole lot of debugging output at you. If you
373 need maximum performance, you should disable the DEBUG define. To
374 aid in debugging in the field, I'm leaving the compile-time debug
375 features enabled, and disable them "runtime". That allows me to
376 instruct people with problems to enable debugging without requiring
377 them to recompile...
378*/
379#define DEBUG
380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381#ifdef DEBUG
Jiri Slaby15b611f2006-12-08 02:39:04 -0800382#define sx_dprintk(f, str...) if (sx_debug & f) printk (str)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383#else
Jiri Slaby15b611f2006-12-08 02:39:04 -0800384#define sx_dprintk(f, str...) /* nothing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385#endif
386
Jiri Slaby15b611f2006-12-08 02:39:04 -0800387#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
388#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__FUNCTION__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Jiri Slaby15b611f2006-12-08 02:39:04 -0800390#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
391 __FUNCTION__, port->line)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393/*
394 * Firmware loader driver specific routines
395 *
396 */
397
Arjan van de Ven62322d22006-07-03 00:24:21 -0700398static const struct file_operations sx_fw_fops = {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800399 .owner = THIS_MODULE,
400 .ioctl = sx_fw_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401};
402
403static struct miscdevice sx_fw_device = {
404 SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
405};
406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407#ifdef SX_PARANOIA_CHECK
408
409/* This doesn't work. Who's paranoid around here? Not me! */
410
Jiri Slaby15b611f2006-12-08 02:39:04 -0800411static inline int sx_paranoia_check(struct sx_port const *port,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 char *name, const char *routine)
413{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800414 static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
415 "number for device %s in %s\n";
416 static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
417 "device %s in %s\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 if (!port) {
420 printk(badinfo, name, routine);
421 return 1;
422 }
423 if (port->magic != SX_MAGIC) {
424 printk(badmagic, name, routine);
425 return 1;
426 }
427
428 return 0;
429}
430#else
431#define sx_paranoia_check(a,b,c) 0
432#endif
433
434/* The timeouts. First try 30 times as fast as possible. Then give
435 the card some time to breathe between accesses. (Otherwise the
436 processor on the card might not be able to access its OWN bus... */
437
438#define TIMEOUT_1 30
439#define TIMEOUT_2 1000000
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441#ifdef DEBUG
442static void my_hd_io(void __iomem *p, int len)
443{
444 int i, j, ch;
445 unsigned char __iomem *addr = p;
446
Jiri Slaby15b611f2006-12-08 02:39:04 -0800447 for (i = 0; i < len; i += 16) {
448 printk("%p ", addr + i);
449 for (j = 0; j < 16; j++) {
450 printk("%02x %s", readb(addr + j + i),
451 (j == 7) ? " " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800453 for (j = 0; j < 16; j++) {
454 ch = readb(addr + j + i);
455 printk("%c", (ch < 0x20) ? '.' :
456 ((ch > 0x7f) ? '.' : ch));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800458 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 }
460}
461static void my_hd(void *p, int len)
462{
463 int i, j, ch;
464 unsigned char *addr = p;
465
Jiri Slaby15b611f2006-12-08 02:39:04 -0800466 for (i = 0; i < len; i += 16) {
467 printk("%p ", addr + i);
468 for (j = 0; j < 16; j++) {
469 printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800471 for (j = 0; j < 16; j++) {
472 ch = addr[j + i];
473 printk("%c", (ch < 0x20) ? '.' :
474 ((ch > 0x7f) ? '.' : ch));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800476 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 }
478}
479#endif
480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481/* This needs redoing for Alpha -- REW -- Done. */
482
Jiri Slaby15b611f2006-12-08 02:39:04 -0800483static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800485 writeb(byte, board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486}
487
Jiri Slaby15b611f2006-12-08 02:39:04 -0800488static inline u8 read_sx_byte(struct sx_board *board, int offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800490 return readb(board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491}
492
Jiri Slaby15b611f2006-12-08 02:39:04 -0800493static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800495 writew(word, board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496}
497
Jiri Slaby15b611f2006-12-08 02:39:04 -0800498static inline u16 read_sx_word(struct sx_board *board, int offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800500 return readw(board->base + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501}
502
Jiri Slaby15b611f2006-12-08 02:39:04 -0800503static int sx_busy_wait_eq(struct sx_board *board,
504 int offset, int mask, int correctval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505{
506 int i;
507
Jiri Slaby15b611f2006-12-08 02:39:04 -0800508 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
Jiri Slaby15b611f2006-12-08 02:39:04 -0800510 for (i = 0; i < TIMEOUT_1; i++)
511 if ((read_sx_byte(board, offset) & mask) == correctval) {
512 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 return 1;
514 }
515
Jiri Slaby15b611f2006-12-08 02:39:04 -0800516 for (i = 0; i < TIMEOUT_2; i++) {
517 if ((read_sx_byte(board, offset) & mask) == correctval) {
518 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 return 1;
520 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800521 udelay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 }
523
Jiri Slaby15b611f2006-12-08 02:39:04 -0800524 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 return 0;
526}
527
Jiri Slaby15b611f2006-12-08 02:39:04 -0800528static int sx_busy_wait_neq(struct sx_board *board,
529 int offset, int mask, int badval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
531 int i;
532
Jiri Slaby15b611f2006-12-08 02:39:04 -0800533 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Jiri Slaby15b611f2006-12-08 02:39:04 -0800535 for (i = 0; i < TIMEOUT_1; i++)
536 if ((read_sx_byte(board, offset) & mask) != badval) {
537 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 return 1;
539 }
540
Jiri Slaby15b611f2006-12-08 02:39:04 -0800541 for (i = 0; i < TIMEOUT_2; i++) {
542 if ((read_sx_byte(board, offset) & mask) != badval) {
543 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 return 1;
545 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800546 udelay(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 }
548
Jiri Slaby15b611f2006-12-08 02:39:04 -0800549 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 return 0;
551}
552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553/* 5.6.4 of 6210028 r2.3 */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800554static int sx_reset(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800556 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Jiri Slaby15b611f2006-12-08 02:39:04 -0800558 if (IS_SX_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
Jiri Slaby15b611f2006-12-08 02:39:04 -0800560 write_sx_byte(board, SX_CONFIG, 0);
561 write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Jiri Slaby15b611f2006-12-08 02:39:04 -0800563 if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
564 printk(KERN_INFO "sx: Card doesn't respond to "
565 "reset...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 return 0;
567 }
568 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800569 outb(board->irq << 4, board->eisa_base + 0xc02);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800571 write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 } else {
573 /* Gory details of the SI/ISA board */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800574 write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
575 write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
576 write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
577 write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
578 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
579 write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 }
581
Jiri Slaby15b611f2006-12-08 02:39:04 -0800582 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 return 1;
584}
585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586/* This doesn't work on machines where "NULL" isn't 0 */
587/* If you have one of those, someone will need to write
588 the equivalent of this, which will amount to about 3 lines. I don't
589 want to complicate this right now. -- REW
590 (See, I do write comments every now and then :-) */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800591#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Jiri Slaby15b611f2006-12-08 02:39:04 -0800593#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))
594#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem))
595#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
597#define sx_write_channel_byte(port, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800598 write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
600#define sx_read_channel_byte(port, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800601 read_sx_byte (port->board, CHAN_OFFSET (port, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
603#define sx_write_channel_word(port, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800604 write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
606#define sx_read_channel_word(port, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800607 read_sx_word (port->board, CHAN_OFFSET (port, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
609#define sx_write_module_byte(board, addr, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800610 write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
612#define sx_read_module_byte(board, addr, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800613 read_sx_byte (board, MODU_OFFSET (board, addr, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
615#define sx_write_module_word(board, addr, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800616 write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
618#define sx_read_module_word(board, addr, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800619 read_sx_word (board, MODU_OFFSET (board, addr, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621#define sx_write_board_byte(board, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800622 write_sx_byte (board, BRD_OFFSET (board, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
624#define sx_read_board_byte(board, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800625 read_sx_byte (board, BRD_OFFSET (board, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627#define sx_write_board_word(board, elem, val) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800628 write_sx_word (board, BRD_OFFSET (board, elem), val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630#define sx_read_board_word(board, elem) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800631 read_sx_word (board, BRD_OFFSET (board, elem))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Jiri Slaby15b611f2006-12-08 02:39:04 -0800633static int sx_start_board(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800635 if (IS_SX_BOARD(board)) {
636 write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 } else if (IS_EISA_BOARD(board)) {
638 write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
Jiri Slaby15b611f2006-12-08 02:39:04 -0800639 outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800641 write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
642 write_sx_byte(board, SI1_ISA_INTCL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 } else {
644 /* Don't bug me about the clear_set.
645 I haven't the foggiest idea what it's about -- REW */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800646 write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
647 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 }
649 return 1;
650}
651
652#define SX_IRQ_REG_VAL(board) \
Jiri Slaby15b611f2006-12-08 02:39:04 -0800653 ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
655/* Note. The SX register is write-only. Therefore, we have to enable the
656 bus too. This is a no-op, if you don't mess with this driver... */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800657static int sx_start_interrupts(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
659
660 /* Don't call this with board->irq == 0 */
661
662 if (IS_SX_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800663 write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
664 SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800666 inb(board->eisa_base + 0xc03);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 } else if (IS_SI1_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800668 write_sx_byte(board, SI1_ISA_INTCL, 0);
669 write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 } else {
671 switch (board->irq) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800672 case 11:
673 write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
674 break;
675 case 12:
676 write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
677 break;
678 case 15:
679 write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
680 break;
681 default:
682 printk(KERN_INFO "sx: SI/XIO card doesn't support "
683 "interrupt %d.\n", board->irq);
684 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800686 write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 }
688
689 return 1;
690}
691
Jiri Slaby15b611f2006-12-08 02:39:04 -0800692static int sx_send_command(struct sx_port *port,
693 int command, int mask, int newstat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800695 func_enter2();
696 write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
697 func_exit();
698 return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
699 newstat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700}
701
Jiri Slaby15b611f2006-12-08 02:39:04 -0800702static char *mod_type_s(int module_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
704 switch (module_type) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800705 case TA4:
706 return "TA4";
707 case TA8:
708 return "TA8";
709 case TA4_ASIC:
710 return "TA4_ASIC";
711 case TA8_ASIC:
712 return "TA8_ASIC";
713 case MTA_CD1400:
714 return "MTA_CD1400";
715 case SXDC:
716 return "SXDC";
717 default:
718 return "Unknown/invalid";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 }
720}
721
Jiri Slaby15b611f2006-12-08 02:39:04 -0800722static char *pan_type_s(int pan_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723{
724 switch (pan_type) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800725 case MOD_RS232DB25:
726 return "MOD_RS232DB25";
727 case MOD_RS232RJ45:
728 return "MOD_RS232RJ45";
729 case MOD_RS422DB25:
730 return "MOD_RS422DB25";
731 case MOD_PARALLEL:
732 return "MOD_PARALLEL";
733 case MOD_2_RS232DB25:
734 return "MOD_2_RS232DB25";
735 case MOD_2_RS232RJ45:
736 return "MOD_2_RS232RJ45";
737 case MOD_2_RS422DB25:
738 return "MOD_2_RS422DB25";
739 case MOD_RS232DB25MALE:
740 return "MOD_RS232DB25MALE";
741 case MOD_2_PARALLEL:
742 return "MOD_2_PARALLEL";
743 case MOD_BLANK:
744 return "empty";
745 default:
746 return "invalid";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 }
748}
749
Jiri Slaby15b611f2006-12-08 02:39:04 -0800750static int mod_compat_type(int module_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751{
752 return module_type >> 4;
753}
754
755static void sx_reconfigure_port(struct sx_port *port)
756{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800757 if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
758 if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
759 printk(KERN_WARNING "sx: Sent reconfigure command, but "
760 "card didn't react.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 }
762 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800763 sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
764 "port isn't open (%02x).\n",
765 sx_read_channel_byte(port, hi_hstat));
766 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767}
768
Jiri Slaby15b611f2006-12-08 02:39:04 -0800769static void sx_setsignals(struct sx_port *port, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770{
771 int t;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800772 func_enter2();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Jiri Slaby15b611f2006-12-08 02:39:04 -0800774 t = sx_read_channel_byte(port, hi_op);
775 if (dtr >= 0)
776 t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
777 if (rts >= 0)
778 t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
779 sx_write_channel_byte(port, hi_op, t);
780 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
Jiri Slaby15b611f2006-12-08 02:39:04 -0800782 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783}
784
Jiri Slaby15b611f2006-12-08 02:39:04 -0800785static int sx_getsignals(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
Jiri Slaby15b611f2006-12-08 02:39:04 -0800787 int i_stat, o_stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
Jiri Slaby15b611f2006-12-08 02:39:04 -0800789 o_stat = sx_read_channel_byte(port, hi_op);
790 i_stat = sx_read_channel_byte(port, hi_ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Jiri Slaby15b611f2006-12-08 02:39:04 -0800792 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) "
793 "%02x/%02x\n",
794 (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
795 port->c_dcd, sx_get_CD(port),
796 sx_read_channel_byte(port, hi_ip),
797 sx_read_channel_byte(port, hi_state));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
Jiri Slaby15b611f2006-12-08 02:39:04 -0800799 return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
800 ((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
801 ((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
802 ((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
803 ((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
804 ((i_stat & IP_RI) ? TIOCM_RNG : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805}
806
Jiri Slaby15b611f2006-12-08 02:39:04 -0800807static void sx_set_baud(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808{
809 int t;
810
811 if (port->board->ta_type == MOD_SXDC) {
812 switch (port->gs.baud) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800813 /* Save some typing work... */
814#define e(x) case x: t = BAUD_ ## x; break
815 e(50);
816 e(75);
817 e(110);
818 e(150);
819 e(200);
820 e(300);
821 e(600);
822 e(1200);
823 e(1800);
824 e(2000);
825 e(2400);
826 e(4800);
827 e(7200);
828 e(9600);
829 e(14400);
830 e(19200);
831 e(28800);
832 e(38400);
833 e(56000);
834 e(57600);
835 e(64000);
836 e(76800);
837 e(115200);
838 e(128000);
839 e(150000);
840 e(230400);
841 e(256000);
842 e(460800);
843 e(921600);
844 case 134:
845 t = BAUD_134_5;
846 break;
847 case 0:
848 t = -1;
849 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 default:
851 /* Can I return "invalid"? */
852 t = BAUD_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800853 printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
854 port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 break;
856 }
857#undef e
858 if (t > 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800859/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
860 sx_setsignals(port, 1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 /* XXX This is not TA & MTA compatible */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800862 sx_write_channel_byte(port, hi_csr, 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Jiri Slaby15b611f2006-12-08 02:39:04 -0800864 sx_write_channel_byte(port, hi_txbaud, t);
865 sx_write_channel_byte(port, hi_rxbaud, t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800867 sx_setsignals(port, 0, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 }
869 } else {
870 switch (port->gs.baud) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800871#define e(x) case x: t = CSR_ ## x; break
872 e(75);
873 e(150);
874 e(300);
875 e(600);
876 e(1200);
877 e(2400);
878 e(4800);
879 e(1800);
880 e(9600);
881 e(19200);
882 e(57600);
883 e(38400);
884/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
885 case 110:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 if (port->board->ta_type == MOD_TA) {
887 t = CSR_110;
888 break;
889 } else {
890 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800891 printk(KERN_INFO "sx: Unsupported baud rate: "
892 "%d.\n", port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 break;
894 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800895 case 115200:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 if (port->board->ta_type == MOD_TA) {
897 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800898 printk(KERN_INFO "sx: Unsupported baud rate: "
899 "%d.\n", port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 break;
901 } else {
902 t = CSR_110;
903 break;
904 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800905 case 0:
906 t = -1;
907 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 default:
909 t = CSR_9600;
Jiri Slaby15b611f2006-12-08 02:39:04 -0800910 printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
911 port->gs.baud);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 break;
913 }
914#undef e
915 if (t >= 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800916 sx_setsignals(port, 1, -1);
917 sx_write_channel_byte(port, hi_csr, t * 0x11);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800919 sx_setsignals(port, 0, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921 }
922}
923
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
925 better. -- REW */
926
Jiri Slaby15b611f2006-12-08 02:39:04 -0800927static int sx_set_real_termios(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928{
929 struct sx_port *port = ptr;
930
931 func_enter2();
932
933 if (!port->gs.tty)
934 return 0;
935
936 /* What is this doing here? -- REW
937 Ha! figured it out. It is to allow you to get DTR active again
938 if you've dropped it with stty 0. Moved to set_baud, where it
939 belongs (next to the drop dtr if baud == 0) -- REW */
940 /* sx_setsignals (port, 1, -1); */
941
Jiri Slaby15b611f2006-12-08 02:39:04 -0800942 sx_set_baud(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
944#define CFLAG port->gs.tty->termios->c_cflag
Jiri Slaby15b611f2006-12-08 02:39:04 -0800945 sx_write_channel_byte(port, hi_mr1,
946 (C_PARENB(port->gs.tty) ? MR1_WITH : MR1_NONE) |
947 (C_PARODD(port->gs.tty) ? MR1_ODD : MR1_EVEN) |
948 (C_CRTSCTS(port->gs.tty) ? MR1_RTS_RXFLOW : 0) |
949 (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
950 (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
951 (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
952 (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Jiri Slaby15b611f2006-12-08 02:39:04 -0800954 sx_write_channel_byte(port, hi_mr2,
955 (C_CRTSCTS(port->gs.tty) ? MR2_CTS_TXFLOW : 0) |
956 (C_CSTOPB(port->gs.tty) ? MR2_2_STOP :
957 MR2_1_STOP));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
959 switch (CFLAG & CSIZE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -0800960 case CS8:
961 sx_write_channel_byte(port, hi_mask, 0xff);
962 break;
963 case CS7:
964 sx_write_channel_byte(port, hi_mask, 0x7f);
965 break;
966 case CS6:
967 sx_write_channel_byte(port, hi_mask, 0x3f);
968 break;
969 case CS5:
970 sx_write_channel_byte(port, hi_mask, 0x1f);
971 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 default:
Jiri Slaby15b611f2006-12-08 02:39:04 -0800973 printk(KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 break;
975 }
976
Jiri Slaby15b611f2006-12-08 02:39:04 -0800977 sx_write_channel_byte(port, hi_prtcl,
978 (I_IXON(port->gs.tty) ? SP_TXEN : 0) |
979 (I_IXOFF(port->gs.tty) ? SP_RXEN : 0) |
980 (I_IXANY(port->gs.tty) ? SP_TANY : 0) | SP_DCEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
Jiri Slaby15b611f2006-12-08 02:39:04 -0800982 sx_write_channel_byte(port, hi_break,
983 (I_IGNBRK(port->gs.tty) ? BR_IGN : 0 |
984 I_BRKINT(port->gs.tty) ? BR_INT : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Jiri Slaby15b611f2006-12-08 02:39:04 -0800986 sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.tty));
987 sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.tty));
988 sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.tty));
989 sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990
991 sx_reconfigure_port(port);
992
993 /* Tell line discipline whether we will do input cooking */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800994 if (I_OTHER(port->gs.tty)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
996 } else {
997 set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
998 }
Jiri Slaby15b611f2006-12-08 02:39:04 -0800999 sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
1000 port->gs.tty->termios->c_iflag, I_OTHER(port->gs.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 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001007 if (O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
1009 } else {
1010 clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
1011 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001012 sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
1013 port->gs.tty->termios->c_oflag, O_OTHER(port->gs.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 /* port->c_dcd = sx_get_CD (port); */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001015 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return 0;
1017}
1018
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019/* ********************************************************************** *
1020 * the interrupt related routines *
1021 * ********************************************************************** */
1022
1023/* Note:
1024 Other drivers use the macro "MIN" to calculate how much to copy.
1025 This has the disadvantage that it will evaluate parts twice. That's
1026 expensive when it's IO (and the compiler cannot optimize those away!).
1027 Moreover, I'm not sure that you're race-free.
1028
1029 I assign a value, and then only allow the value to decrease. This
1030 is always safe. This makes the code a few lines longer, and you
1031 know I'm dead against that, but I think it is required in this
1032 case. */
1033
Jiri Slaby15b611f2006-12-08 02:39:04 -08001034static void sx_transmit_chars(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035{
1036 int c;
1037 int tx_ip;
1038 int txroom;
1039
Jiri Slaby15b611f2006-12-08 02:39:04 -08001040 func_enter2();
1041 sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
1042 port, port->gs.xmit_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Jiri Slaby15b611f2006-12-08 02:39:04 -08001044 if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 return;
1046 }
1047
1048 while (1) {
1049 c = port->gs.xmit_cnt;
1050
Jiri Slaby15b611f2006-12-08 02:39:04 -08001051 sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
1052 tx_ip = sx_read_channel_byte(port, hi_txipos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
1054 /* Took me 5 minutes to deduce this formula.
1055 Luckily it is literally in the manual in section 6.5.4.3.5 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001056 txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
1057 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
1059 /* Don't copy more bytes than there is room for in the buffer */
1060 if (c > txroom)
1061 c = txroom;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001062 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
1064 /* Don't copy past the end of the hardware transmit buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001065 if (c > 0x100 - tx_ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 c = 0x100 - tx_ip;
1067
Jiri Slaby15b611f2006-12-08 02:39:04 -08001068 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 /* Don't copy pas the end of the source buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001071 if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
1073
Jiri Slaby15b611f2006-12-08 02:39:04 -08001074 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
1075 c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
Jiri Slaby15b611f2006-12-08 02:39:04 -08001077 /* If for one reason or another, we can't copy more data, we're
1078 done! */
1079 if (c == 0)
1080 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081
Jiri Slaby15b611f2006-12-08 02:39:04 -08001082 memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
1083 tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
1085 /* Update the pointer in the card */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001086 sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 /* Update the kernel buffer end */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001089 port->gs.xmit_tail = (port->gs.xmit_tail + c) &
1090 (SERIAL_XMIT_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
1092 /* This one last. (this is essential)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001093 It would allow others to start putting more data into the
1094 buffer! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 port->gs.xmit_cnt -= c;
1096 }
1097
1098 if (port->gs.xmit_cnt == 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001099 sx_disable_tx_interrupts(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101
1102 if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
1103 tty_wakeup(port->gs.tty);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001104 sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
1105 port->gs.wakeup_chars);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 }
1107
Jiri Slaby15b611f2006-12-08 02:39:04 -08001108 clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
1109 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110}
1111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112/* Note the symmetry between receiving chars and transmitting them!
1113 Note: The kernel should have implemented both a receive buffer and
1114 a transmit buffer. */
1115
1116/* Inlined: Called only once. Remove the inline when you add another call */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001117static inline void sx_receive_chars(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118{
1119 int c;
1120 int rx_op;
1121 struct tty_struct *tty;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001122 int copied = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08001123 unsigned char *rp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Jiri Slaby15b611f2006-12-08 02:39:04 -08001125 func_enter2();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 tty = port->gs.tty;
1127 while (1) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001128 rx_op = sx_read_channel_byte(port, hi_rxopos);
1129 c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
Jiri Slaby15b611f2006-12-08 02:39:04 -08001131 sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001133 /* Don't copy past the end of the hardware receive buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001134 if (rx_op + c > 0x100)
1135 c = 0x100 - rx_op;
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001136
Jiri Slaby15b611f2006-12-08 02:39:04 -08001137 sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 /* Don't copy more bytes than there is room for in the buffer */
Alan Cox33f0f882006-01-09 20:54:13 -08001140
1141 c = tty_prepare_flip_string(tty, &rp, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Jiri Slaby15b611f2006-12-08 02:39:04 -08001143 sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 /* If for one reason or another, we can't copy more data, we're done! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001146 if (c == 0)
1147 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Jiri Slaby15b611f2006-12-08 02:39:04 -08001149 sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
1150 "%d at %lx\n", c, read_sx_byte(port->board,
1151 CHAN_OFFSET(port, hi_rxbuf) + rx_op),
1152 CHAN_OFFSET(port, hi_rxbuf));
1153 memcpy_fromio(rp, port->board->base +
1154 CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155
1156 /* This one last. ( Not essential.)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001157 It allows the card to start putting more data into the
1158 buffer!
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 Update the pointer in the card */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001160 sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
1162 copied += c;
1163 }
1164 if (copied) {
1165 struct timeval tv;
1166
Jiri Slaby15b611f2006-12-08 02:39:04 -08001167 do_gettimeofday(&tv);
1168 sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
1169 "chars): %d.%06d (%d/%d)\n", port->line,
1170 copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
1171 tty->raw, tty->real_raw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
Jiri Slaby15b611f2006-12-08 02:39:04 -08001173 /* Tell the rest of the system the news. Great news. New
1174 characters! */
1175 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 /* tty_schedule_flip (tty); */
1177 }
1178
Jiri Slaby15b611f2006-12-08 02:39:04 -08001179 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180}
1181
1182/* Inlined: it is called only once. Remove the inline if you add another
1183 call */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001184static inline void sx_check_modem_signals(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185{
1186 int hi_state;
1187 int c_dcd;
1188
Jiri Slaby15b611f2006-12-08 02:39:04 -08001189 hi_state = sx_read_channel_byte(port, hi_state);
1190 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
1191 port->c_dcd, sx_get_CD(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
1193 if (hi_state & ST_BREAK) {
1194 hi_state &= ~ST_BREAK;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001195 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
1196 sx_write_channel_byte(port, hi_state, hi_state);
1197 gs_got_break(&port->gs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 }
1199 if (hi_state & ST_DCD) {
1200 hi_state &= ~ST_DCD;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001201 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
1202 sx_write_channel_byte(port, hi_state, hi_state);
1203 c_dcd = sx_get_CD(port);
1204 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 if (c_dcd != port->c_dcd) {
1206 port->c_dcd = c_dcd;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001207 if (sx_get_CD(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 /* DCD went UP */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001209 if ((sx_read_channel_byte(port, hi_hstat) !=
1210 HS_IDLE_CLOSED) &&
1211 !(port->gs.tty->termios->
1212 c_cflag & CLOCAL)) {
1213 /* Are we blocking in open? */
1214 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1215 "active, unblocking open\n");
1216 wake_up_interruptible(&port->gs.
1217 open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001219 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1220 "raised. Ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 }
1222 } else {
1223 /* DCD went down! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001224 if (!(port->gs.tty->termios->c_cflag & CLOCAL)){
1225 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1226 "dropped. hanging up....\n");
1227 tty_hangup(port->gs.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001229 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1230 "dropped. ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 }
1232 }
1233 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001234 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
1235 "DCD changed, but it didn't.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 }
1237 }
1238}
1239
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240/* This is what an interrupt routine should look like.
1241 * Small, elegant, clear.
1242 */
1243
Jiri Slaby15b611f2006-12-08 02:39:04 -08001244static irqreturn_t sx_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245{
1246 struct sx_board *board = ptr;
1247 struct sx_port *port;
1248 int i;
1249
Jiri Slaby15b611f2006-12-08 02:39:04 -08001250 func_enter();
1251 sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
1252 board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
1254 /* AAargh! The order in which to do these things is essential and
1255 not trivial.
1256
1257 - Rate limit goes before "recursive". Otherwise a series of
Jiri Slaby15b611f2006-12-08 02:39:04 -08001258 recursive calls will hang the machine in the interrupt routine.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
1260 - hardware twiddling goes before "recursive". Otherwise when we
Jiri Slaby15b611f2006-12-08 02:39:04 -08001261 poll the card, and a recursive interrupt happens, we won't
1262 ack the card, so it might keep on interrupting us. (especially
1263 level sensitive interrupt systems like PCI).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
1265 - Rate limit goes before hardware twiddling. Otherwise we won't
Jiri Slaby15b611f2006-12-08 02:39:04 -08001266 catch a card that has gone bonkers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
1268 - The "initialized" test goes after the hardware twiddling. Otherwise
Jiri Slaby15b611f2006-12-08 02:39:04 -08001269 the card will stick us in the interrupt routine again.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 - The initialized test goes before recursive.
Jiri Slaby15b611f2006-12-08 02:39:04 -08001272 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274#ifdef IRQ_RATE_LIMIT
1275 /* Aaargh! I'm ashamed. This costs more lines-of-code than the
Jiri Slaby15b611f2006-12-08 02:39:04 -08001276 actual interrupt routine!. (Well, used to when I wrote that
1277 comment) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 {
1279 static int lastjif;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001280 static int nintr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
1282 if (lastjif == jiffies) {
1283 if (++nintr > IRQ_RATE_LIMIT) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001284 free_irq(board->irq, board);
1285 printk(KERN_ERR "sx: Too many interrupts. "
1286 "Turning off interrupt %d.\n",
1287 board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 }
1289 } else {
1290 lastjif = jiffies;
1291 nintr = 0;
1292 }
1293 }
1294#endif
1295
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 if (board->irq == irq) {
1297 /* Tell the card we've noticed the interrupt. */
1298
Jiri Slaby15b611f2006-12-08 02:39:04 -08001299 sx_write_board_word(board, cc_int_pending, 0);
1300 if (IS_SX_BOARD(board)) {
1301 write_sx_byte(board, SX_RESET_IRQ, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001303 inb(board->eisa_base + 0xc03);
1304 write_sx_word(board, 8, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001306 write_sx_byte(board, SI2_ISA_INTCLEAR,
1307 SI2_ISA_INTCLEAR_CLEAR);
1308 write_sx_byte(board, SI2_ISA_INTCLEAR,
1309 SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 }
1311 }
1312
1313 if (!sx_initialized)
1314 return IRQ_HANDLED;
1315 if (!(board->flags & SX_BOARD_INITIALIZED))
1316 return IRQ_HANDLED;
1317
Jiri Slaby15b611f2006-12-08 02:39:04 -08001318 if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
1319 printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 return IRQ_HANDLED;
1321 }
1322
Jiri Slaby15b611f2006-12-08 02:39:04 -08001323 for (i = 0; i < board->nports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 port = &board->ports[i];
1325 if (port->gs.flags & GS_ACTIVE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001326 if (sx_read_channel_byte(port, hi_state)) {
1327 sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
1328 "modem signal change?... \n",i);
1329 sx_check_modem_signals(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 }
1331 if (port->gs.xmit_cnt) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001332 sx_transmit_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 }
1334 if (!(port->gs.flags & SX_RX_THROTTLE)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001335 sx_receive_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 }
1337 }
1338 }
1339
Jiri Slaby15b611f2006-12-08 02:39:04 -08001340 clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Jiri Slaby15b611f2006-12-08 02:39:04 -08001342 sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
1343 board->irq);
1344 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 return IRQ_HANDLED;
1346}
1347
Jiri Slaby15b611f2006-12-08 02:39:04 -08001348static void sx_pollfunc(unsigned long data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001350 struct sx_board *board = (struct sx_board *)data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Jiri Slaby15b611f2006-12-08 02:39:04 -08001352 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Jiri Slaby15b611f2006-12-08 02:39:04 -08001354 sx_interrupt(0, board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
1356 init_timer(&board->timer);
1357
1358 board->timer.expires = jiffies + sx_poll;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001359 add_timer(&board->timer);
1360 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361}
1362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363/* ********************************************************************** *
1364 * Here are the routines that actually *
1365 * interface with the generic_serial driver *
1366 * ********************************************************************** */
1367
1368/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
1369/* Hmm. Ok I figured it out. You don't. */
1370
Jiri Slaby15b611f2006-12-08 02:39:04 -08001371static void sx_disable_tx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001373 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 func_enter2();
1375
1376 port->gs.flags &= ~GS_TX_INTEN;
1377
1378 func_exit();
1379}
1380
Jiri Slaby15b611f2006-12-08 02:39:04 -08001381static void sx_enable_tx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001383 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 int data_in_buffer;
1385 func_enter2();
1386
1387 /* First transmit the characters that we're supposed to */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001388 sx_transmit_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390 /* The sx card will never interrupt us if we don't fill the buffer
1391 past 25%. So we keep considering interrupts off if that's the case. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001392 data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
1393 sx_read_channel_byte(port, hi_txopos)) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
1395 /* XXX Must be "HIGH_WATER" for SI card according to doc. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001396 if (data_in_buffer < LOW_WATER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 port->gs.flags &= ~GS_TX_INTEN;
1398
1399 func_exit();
1400}
1401
Jiri Slaby15b611f2006-12-08 02:39:04 -08001402static void sx_disable_rx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403{
1404 /* struct sx_port *port = ptr; */
1405 func_enter();
1406
1407 func_exit();
1408}
1409
Jiri Slaby15b611f2006-12-08 02:39:04 -08001410static void sx_enable_rx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411{
1412 /* struct sx_port *port = ptr; */
1413 func_enter();
1414
1415 func_exit();
1416}
1417
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418/* Jeez. Isn't this simple? */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001419static int sx_get_CD(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420{
1421 struct sx_port *port = ptr;
1422 func_enter2();
1423
1424 func_exit();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001425 return ((sx_read_channel_byte(port, hi_ip) & IP_DCD) != 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426}
1427
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428/* Jeez. Isn't this simple? */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001429static int sx_chars_in_buffer(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430{
1431 struct sx_port *port = ptr;
1432 func_enter2();
1433
1434 func_exit();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001435 return ((sx_read_channel_byte(port, hi_txipos) -
1436 sx_read_channel_byte(port, hi_txopos)) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437}
1438
Jiri Slaby15b611f2006-12-08 02:39:04 -08001439static void sx_shutdown_port(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001441 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
1443 func_enter();
1444
Jiri Slaby15b611f2006-12-08 02:39:04 -08001445 port->gs.flags &= ~GS_ACTIVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001447 sx_setsignals(port, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 sx_reconfigure_port(port);
1449 }
1450
1451 func_exit();
1452}
1453
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454/* ********************************************************************** *
1455 * Here are the routines that actually *
1456 * interface with the rest of the system *
1457 * ********************************************************************** */
1458
Jiri Slaby15b611f2006-12-08 02:39:04 -08001459static int sx_open(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460{
1461 struct sx_port *port;
1462 int retval, line;
1463 unsigned long flags;
1464
1465 func_enter();
1466
1467 if (!sx_initialized) {
1468 return -EIO;
1469 }
1470
1471 line = tty->index;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001472 sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
1473 "np=%d)\n", current->pid, line, tty,
1474 current->signal->tty, sx_nports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
1476 if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
1477 return -ENODEV;
1478
Jiri Slaby15b611f2006-12-08 02:39:04 -08001479 port = &sx_ports[line];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
Jiri Slaby15b611f2006-12-08 02:39:04 -08001481 1 -> 0 transition. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
Jiri Slaby15b611f2006-12-08 02:39:04 -08001483 sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
1485 spin_lock_irqsave(&port->gs.driver_lock, flags);
1486
1487 tty->driver_data = port;
1488 port->gs.tty = tty;
1489 port->gs.count++;
1490 spin_unlock_irqrestore(&port->gs.driver_lock, flags);
1491
Jiri Slaby15b611f2006-12-08 02:39:04 -08001492 sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
1494 /*
1495 * Start up serial port
1496 */
1497 retval = gs_init_port(&port->gs);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001498 sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 if (retval) {
1500 port->gs.count--;
1501 return retval;
1502 }
1503
1504 port->gs.flags |= GS_ACTIVE;
1505 if (port->gs.count <= 1)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001506 sx_setsignals(port, 1, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
1508#if 0
1509 if (sx_debug & SX_DEBUG_OPEN)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001510 my_hd(port, sizeof(*port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511#else
1512 if (sx_debug & SX_DEBUG_OPEN)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001513 my_hd_io(port->board->base + port->ch_base, sizeof(*port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514#endif
1515
1516 if (port->gs.count <= 1) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001517 if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
1518 printk(KERN_ERR "sx: Card didn't respond to LOPEN "
1519 "command.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 spin_lock_irqsave(&port->gs.driver_lock, flags);
1521 port->gs.count--;
1522 spin_unlock_irqrestore(&port->gs.driver_lock, flags);
1523 return -EIO;
1524 }
1525 }
1526
1527 retval = gs_block_til_ready(port, filp);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001528 sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
1529 retval, port->gs.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
1531 if (retval) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001532/*
1533 * Don't lower gs.count here because sx_close() will be called later
1534 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
1536 return retval;
1537 }
1538 /* tty->low_latency = 1; */
1539
Jiri Slaby15b611f2006-12-08 02:39:04 -08001540 port->c_dcd = sx_get_CD(port);
1541 sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542
1543 func_exit();
1544 return 0;
1545
1546}
1547
Jiri Slaby15b611f2006-12-08 02:39:04 -08001548static void sx_close(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001550 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 /* Give the port 5 seconds to close down. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001552 int to = 5 * HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Jiri Slaby15b611f2006-12-08 02:39:04 -08001554 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
Jiri Slaby15b611f2006-12-08 02:39:04 -08001556 sx_setsignals(port, 0, 0);
1557 sx_reconfigure_port(port);
1558 sx_send_command(port, HS_CLOSE, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
Jiri Slaby15b611f2006-12-08 02:39:04 -08001560 while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 if (msleep_interruptible(10))
1562 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001563 if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) {
1564 if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED)
1565 != 1) {
1566 printk(KERN_ERR "sx: sent the force_close command, but "
1567 "card didn't react\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 } else
Jiri Slaby15b611f2006-12-08 02:39:04 -08001569 sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
1570 "command.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 }
1572
Jiri Slaby15b611f2006-12-08 02:39:04 -08001573 sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
1574 5 * HZ - to - 1, port->gs.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
Jiri Slaby15b611f2006-12-08 02:39:04 -08001576 if (port->gs.count) {
1577 sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
1578 port->gs.count);
1579 /*printk("%s SETTING port count to zero: %p count: %d\n",
1580 __FUNCTION__, port, port->gs.count);
1581 port->gs.count = 0;*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 }
1583
Jiri Slaby15b611f2006-12-08 02:39:04 -08001584 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585}
1586
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587/* This is relatively thorough. But then again it is only 20 lines. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001588#define MARCHUP for (i = min; i < max; i++)
1589#define MARCHDOWN for (i = max - 1; i >= min; i--)
1590#define W0 write_sx_byte(board, i, 0x55)
1591#define W1 write_sx_byte(board, i, 0xaa)
1592#define R0 if (read_sx_byte(board, i) != 0x55) return 1
1593#define R1 if (read_sx_byte(board, i) != 0xaa) return 1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
1595/* This memtest takes a human-noticable time. You normally only do it
1596 once a boot, so I guess that it is worth it. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001597static int do_memtest(struct sx_board *board, int min, int max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598{
1599 int i;
1600
1601 /* This is a marchb. Theoretically, marchb catches much more than
1602 simpler tests. In practise, the longer test just catches more
1603 intermittent errors. -- REW
1604 (For the theory behind memory testing see:
1605 Testing Semiconductor Memories by A.J. van de Goor.) */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001606 MARCHUP {
1607 W0;
1608 }
1609 MARCHUP {
1610 R0;
1611 W1;
1612 R1;
1613 W0;
1614 R0;
1615 W1;
1616 }
1617 MARCHUP {
1618 R1;
1619 W0;
1620 W1;
1621 }
1622 MARCHDOWN {
1623 R1;
1624 W0;
1625 W1;
1626 W0;
1627 }
1628 MARCHDOWN {
1629 R0;
1630 W1;
1631 W0;
1632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
1634 return 0;
1635}
1636
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637#undef MARCHUP
1638#undef MARCHDOWN
1639#undef W0
1640#undef W1
1641#undef R0
1642#undef R1
1643
Jiri Slaby15b611f2006-12-08 02:39:04 -08001644#define MARCHUP for (i = min; i < max; i += 2)
1645#define MARCHDOWN for (i = max - 1; i >= min; i -= 2)
1646#define W0 write_sx_word(board, i, 0x55aa)
1647#define W1 write_sx_word(board, i, 0xaa55)
1648#define R0 if (read_sx_word(board, i) != 0x55aa) return 1
1649#define R1 if (read_sx_word(board, i) != 0xaa55) return 1
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
1651#if 0
1652/* This memtest takes a human-noticable time. You normally only do it
1653 once a boot, so I guess that it is worth it. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001654static int do_memtest_w(struct sx_board *board, int min, int max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655{
1656 int i;
1657
Jiri Slaby15b611f2006-12-08 02:39:04 -08001658 MARCHUP {
1659 W0;
1660 }
1661 MARCHUP {
1662 R0;
1663 W1;
1664 R1;
1665 W0;
1666 R0;
1667 W1;
1668 }
1669 MARCHUP {
1670 R1;
1671 W0;
1672 W1;
1673 }
1674 MARCHDOWN {
1675 R1;
1676 W0;
1677 W1;
1678 W0;
1679 }
1680 MARCHDOWN {
1681 R0;
1682 W1;
1683 W0;
1684 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
1686 return 0;
1687}
1688#endif
1689
Jiri Slaby15b611f2006-12-08 02:39:04 -08001690static int sx_fw_ioctl(struct inode *inode, struct file *filp,
1691 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692{
1693 int rc = 0;
1694 int __user *descr = (int __user *)arg;
1695 int i;
1696 static struct sx_board *board = NULL;
1697 int nbytes, offset;
1698 unsigned long data;
1699 char *tmp;
1700
1701 func_enter();
1702
Jiri Slaby15b611f2006-12-08 02:39:04 -08001703#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 /* Removed superuser check: Sysops can use the permissions on the device
1705 file to restrict access. Recommendation: Root only. (root.root 600) */
1706 if (!capable(CAP_SYS_ADMIN)) {
1707 return -EPERM;
1708 }
1709#endif
1710
Jiri Slaby15b611f2006-12-08 02:39:04 -08001711 sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712
Jiri Slaby15b611f2006-12-08 02:39:04 -08001713 if (!board)
1714 board = &boards[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 if (board->flags & SX_BOARD_PRESENT) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001716 sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
1717 board->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001719 sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
1720 board->flags);
1721 for (i = 0; i < SX_NBOARDS; i++)
1722 sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
1723 sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 return -EIO;
1725 }
1726
1727 switch (cmd) {
1728 case SXIO_SET_BOARD:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001729 sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
1730 if (arg >= SX_NBOARDS)
1731 return -EIO;
1732 sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
1733 if (!(boards[arg].flags & SX_BOARD_PRESENT))
1734 return -EIO;
1735 sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 board = &boards[arg];
1737 break;
1738 case SXIO_GET_TYPE:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001739 rc = -ENOENT; /* If we manage to miss one, return error. */
1740 if (IS_SX_BOARD(board))
1741 rc = SX_TYPE_SX;
1742 if (IS_CF_BOARD(board))
1743 rc = SX_TYPE_CF;
1744 if (IS_SI_BOARD(board))
1745 rc = SX_TYPE_SI;
1746 if (IS_SI1_BOARD(board))
1747 rc = SX_TYPE_SI;
1748 if (IS_EISA_BOARD(board))
1749 rc = SX_TYPE_SI;
1750 sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 break;
1752 case SXIO_DO_RAMTEST:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001753 if (sx_initialized) /* Already initialized: better not ramtest the board. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 return -EPERM;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001755 if (IS_SX_BOARD(board)) {
1756 rc = do_memtest(board, 0, 0x7000);
1757 if (!rc)
1758 rc = do_memtest(board, 0, 0x7000);
1759 /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001761 rc = do_memtest(board, 0, 0x7ff8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
1763 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001764 sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n",
1765 rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 break;
1767 case SXIO_DOWNLOAD:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001768 if (sx_initialized) /* Already initialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 return -EEXIST;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001770 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 return -EIO;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001772 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
Jiri Slaby15b611f2006-12-08 02:39:04 -08001774 tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
1775 if (!tmp)
1776 return -ENOMEM;
1777 get_user(nbytes, descr++);
1778 get_user(offset, descr++);
1779 get_user(data, descr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 while (nbytes && data) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001781 for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
1782 if (copy_from_user(tmp, (char __user *)data + i,
1783 (i + SX_CHUNK_SIZE > nbytes) ?
1784 nbytes - i : SX_CHUNK_SIZE)) {
1785 kfree(tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 return -EFAULT;
1787 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001788 memcpy_toio(board->base2 + offset + i, tmp,
1789 (i + SX_CHUNK_SIZE > nbytes) ?
1790 nbytes - i : SX_CHUNK_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 }
1792
Jiri Slaby15b611f2006-12-08 02:39:04 -08001793 get_user(nbytes, descr++);
1794 get_user(offset, descr++);
1795 get_user(data, descr++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001797 kfree(tmp);
1798 sx_nports += sx_init_board(board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 rc = sx_nports;
1800 break;
1801 case SXIO_INIT:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001802 if (sx_initialized) /* Already initialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 return -EEXIST;
1804 /* This is not allowed until all boards are initialized... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001805 for (i = 0; i < SX_NBOARDS; i++) {
1806 if ((boards[i].flags & SX_BOARD_PRESENT) &&
1807 !(boards[i].flags & SX_BOARD_INITIALIZED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 return -EIO;
1809 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001810 for (i = 0; i < SX_NBOARDS; i++)
1811 if (!(boards[i].flags & SX_BOARD_PRESENT))
1812 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
Jiri Slaby15b611f2006-12-08 02:39:04 -08001814 sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
1815 "%d channels, first board: %d ports\n",
1816 i, sx_nports, boards[0].nports);
1817 rc = sx_init_portstructs(i, sx_nports);
1818 sx_init_drivers();
1819 if (rc >= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 sx_initialized++;
1821 break;
1822 case SXIO_SETDEBUG:
1823 sx_debug = arg;
1824 break;
1825 case SXIO_GETDEBUG:
1826 rc = sx_debug;
1827 break;
1828 case SXIO_GETGSDEBUG:
1829 case SXIO_SETGSDEBUG:
1830 rc = -EINVAL;
1831 break;
1832 case SXIO_GETNPORTS:
1833 rc = sx_nports;
1834 break;
1835 default:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001836 printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n",
1837 cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 break;
1839 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001840 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 return rc;
1842}
1843
Jiri Slaby15b611f2006-12-08 02:39:04 -08001844static void sx_break(struct tty_struct *tty, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845{
1846 struct sx_port *port = tty->driver_data;
1847 int rv;
1848
Jiri Slaby15b611f2006-12-08 02:39:04 -08001849 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850
Jiri Slaby15b611f2006-12-08 02:39:04 -08001851 if (flag)
1852 rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
1853 else
1854 rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
1855 if (rv != 1)
1856 printk(KERN_ERR "sx: couldn't send break (%x).\n",
1857 read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
Jiri Slaby15b611f2006-12-08 02:39:04 -08001859 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860}
1861
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1863{
1864 struct sx_port *port = tty->driver_data;
1865 return sx_getsignals(port);
1866}
1867
1868static int sx_tiocmset(struct tty_struct *tty, struct file *file,
Jiri Slaby15b611f2006-12-08 02:39:04 -08001869 unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870{
1871 struct sx_port *port = tty->driver_data;
1872 int rts = -1, dtr = -1;
1873
1874 if (set & TIOCM_RTS)
1875 rts = 1;
1876 if (set & TIOCM_DTR)
1877 dtr = 1;
1878 if (clear & TIOCM_RTS)
1879 rts = 0;
1880 if (clear & TIOCM_DTR)
1881 dtr = 0;
1882
1883 sx_setsignals(port, dtr, rts);
1884 sx_reconfigure_port(port);
1885 return 0;
1886}
1887
Jiri Slaby15b611f2006-12-08 02:39:04 -08001888static int sx_ioctl(struct tty_struct *tty, struct file *filp,
1889 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890{
1891 int rc;
1892 struct sx_port *port = tty->driver_data;
1893 void __user *argp = (void __user *)arg;
1894 int ival;
1895
1896 /* func_enter2(); */
1897
1898 rc = 0;
1899 switch (cmd) {
1900 case TIOCGSOFTCAR:
1901 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
Jiri Slaby15b611f2006-12-08 02:39:04 -08001902 (unsigned __user *)argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 break;
1904 case TIOCSSOFTCAR:
Jiri Slaby15b611f2006-12-08 02:39:04 -08001905 if ((rc = get_user(ival, (unsigned __user *)argp)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 tty->termios->c_cflag =
1907 (tty->termios->c_cflag & ~CLOCAL) |
1908 (ival ? CLOCAL : 0);
1909 }
1910 break;
1911 case TIOCGSERIAL:
1912 rc = gs_getserial(&port->gs, argp);
1913 break;
1914 case TIOCSSERIAL:
1915 rc = gs_setserial(&port->gs, argp);
1916 break;
1917 default:
1918 rc = -ENOIOCTLCMD;
1919 break;
1920 }
1921
1922 /* func_exit(); */
1923 return rc;
1924}
1925
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926/* The throttle/unthrottle scheme for the Specialix card is different
1927 * from other drivers and deserves some explanation.
1928 * The Specialix hardware takes care of XON/XOFF
1929 * and CTS/RTS flow control itself. This means that all we have to
1930 * do when signalled by the upper tty layer to throttle/unthrottle is
1931 * to make a note of it here. When we come to read characters from the
1932 * rx buffers on the card (sx_receive_chars()) we look to see if the
1933 * upper layer can accept more (as noted here in sx_rx_throt[]).
1934 * If it can't we simply don't remove chars from the cards buffer.
1935 * When the tty layer can accept chars, we again note that here and when
1936 * sx_receive_chars() is called it will remove them from the cards buffer.
1937 * The card will notice that a ports buffer has drained below some low
1938 * water mark and will unflow control the line itself, using whatever
1939 * flow control scheme is in use for that port. -- Simon Allen
1940 */
1941
Jiri Slaby15b611f2006-12-08 02:39:04 -08001942static void sx_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943{
1944 struct sx_port *port = (struct sx_port *)tty->driver_data;
1945
1946 func_enter2();
1947 /* If the port is using any type of input flow
1948 * control then throttle the port.
1949 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001950 if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 port->gs.flags |= SX_RX_THROTTLE;
1952 }
1953 func_exit();
1954}
1955
Jiri Slaby15b611f2006-12-08 02:39:04 -08001956static void sx_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957{
1958 struct sx_port *port = (struct sx_port *)tty->driver_data;
1959
1960 func_enter2();
1961 /* Always unthrottle even if flow control is not enabled on
1962 * this port in case we disabled flow control while the port
1963 * was throttled
1964 */
1965 port->gs.flags &= ~SX_RX_THROTTLE;
1966 func_exit();
1967 return;
1968}
1969
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970/* ********************************************************************** *
1971 * Here are the initialization routines. *
1972 * ********************************************************************** */
1973
Jiri Slaby15b611f2006-12-08 02:39:04 -08001974static int sx_init_board(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975{
1976 int addr;
1977 int chans;
1978 int type;
1979
1980 func_enter();
1981
1982 /* This is preceded by downloading the download code. */
1983
1984 board->flags |= SX_BOARD_INITIALIZED;
1985
Jiri Slaby15b611f2006-12-08 02:39:04 -08001986 if (read_sx_byte(board, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 /* CF boards may need this. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001988 write_sx_byte(board, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
1990 /* This resets the processor again, to make sure it didn't do any
1991 foolish things while we were downloading the image */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001992 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 return 0;
1994
Jiri Slaby15b611f2006-12-08 02:39:04 -08001995 sx_start_board(board);
1996 udelay(10);
1997 if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
1998 printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 return 0;
2000 }
2001
2002 /* Ok. So now the processor on the card is running. It gathered
2003 some info for us... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002004 sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
2005 if (sx_debug & SX_DEBUG_INIT)
2006 my_hd_io(board->base, 0x10);
2007 sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
2008 if (sx_debug & SX_DEBUG_INIT)
2009 my_hd_io(board->base + 0x80, 0x30);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
Jiri Slaby15b611f2006-12-08 02:39:04 -08002011 sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
2012 "V%x.%02x,\n",
2013 read_sx_byte(board, 0), read_sx_byte(board, 1),
2014 read_sx_byte(board, 5), read_sx_byte(board, 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015
Jiri Slaby15b611f2006-12-08 02:39:04 -08002016 if (read_sx_byte(board, 0) == 0xff) {
2017 printk(KERN_INFO "sx: No modules found. Sorry.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 board->nports = 0;
2019 return 0;
2020 }
2021
2022 chans = 0;
2023
2024 if (IS_SX_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002025 sx_write_board_word(board, cc_int_count, sx_maxints);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 } else {
2027 if (sx_maxints)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002028 sx_write_board_word(board, cc_int_count,
2029 SI_PROCESSOR_CLOCK / 8 / sx_maxints);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 }
2031
2032 /* grab the first module type... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002033 /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
2034 board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
2035 mc_chip));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
2037 /* XXX byteorder */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002038 for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
2039 type = sx_read_module_byte(board, addr, mc_chip);
2040 sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
2041 addr, read_sx_byte(board, addr + 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
Jiri Slaby15b611f2006-12-08 02:39:04 -08002043 chans += sx_read_module_byte(board, addr, mc_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
Jiri Slaby15b611f2006-12-08 02:39:04 -08002045 sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
2046 "panels\n",
2047 mod_type_s(type),
2048 pan_type_s(sx_read_module_byte(board, addr,
2049 mc_mods) & 0xf),
2050 pan_type_s(sx_read_module_byte(board, addr,
2051 mc_mods) >> 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052
Jiri Slaby15b611f2006-12-08 02:39:04 -08002053 sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
2054 "version: %x\n",
2055 sx_read_module_byte(board, addr, mc_rev1),
2056 sx_read_module_byte(board, addr, mc_rev2),
2057 sx_read_module_byte(board, addr, mc_mtaasic_rev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058
2059 /* The following combinations are illegal: It should theoretically
2060 work, but timing problems make the bus HANG. */
2061
Jiri Slaby15b611f2006-12-08 02:39:04 -08002062 if (mod_compat_type(type) != board->ta_type) {
2063 printk(KERN_ERR "sx: This is an invalid "
2064 "configuration.\nDon't mix TA/MTA/SXDC on the "
2065 "same hostadapter.\n");
2066 chans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 break;
2068 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002069 if ((IS_EISA_BOARD(board) ||
2070 IS_SI_BOARD(board)) &&
2071 (mod_compat_type(type) == 4)) {
2072 printk(KERN_ERR "sx: This is an invalid "
2073 "configuration.\nDon't use SXDCs on an SI/XIO "
2074 "adapter.\n");
2075 chans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 break;
2077 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002078#if 0 /* Problem fixed: firmware 3.05 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 if (IS_SX_BOARD(board) && (type == TA8)) {
2080 /* There are some issues with the firmware and the DCD/RTS
2081 lines. It might work if you tie them together or something.
Jiri Slaby15b611f2006-12-08 02:39:04 -08002082 It might also work if you get a newer sx_firmware. Therefore
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 this is just a warning. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002084 printk(KERN_WARNING
2085 "sx: The SX host doesn't work too well "
2086 "with the TA8 adapters.\nSpecialix is working on it.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 }
2088#endif
2089 }
2090
2091 if (chans) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002092 if (board->irq > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 /* fixed irq, probably PCI */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002094 if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */
2095 if (request_irq(board->irq, sx_interrupt,
2096 IRQF_SHARED | IRQF_DISABLED,
2097 "sx", board)) {
2098 printk(KERN_ERR "sx: Cannot allocate "
2099 "irq %d.\n", board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 board->irq = 0;
2101 }
2102 } else
2103 board->irq = 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002104 } else if (board->irq < 0 && sx_irqmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 /* auto-allocate irq */
2106 int irqnr;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002107 int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
2108 SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
2109 for (irqnr = 15; irqnr > 0; irqnr--)
2110 if (irqmask & (1 << irqnr))
2111 if (!request_irq(irqnr, sx_interrupt,
2112 IRQF_SHARED | IRQF_DISABLED,
2113 "sx", board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002115 if (!irqnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
2117 board->irq = irqnr;
2118 } else
2119 board->irq = 0;
2120
2121 if (board->irq) {
2122 /* Found a valid interrupt, start up interrupts! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002123 sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
2124 board->irq);
2125 sx_start_interrupts(board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 board->poll = sx_slowpoll;
2127 board->flags |= SX_IRQ_ALLOCATED;
2128 } else {
2129 /* no irq: setup board for polled operation */
2130 board->poll = sx_poll;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002131 sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
2132 board->poll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 }
2134
Jiri Slaby15b611f2006-12-08 02:39:04 -08002135 /* The timer should be initialized anyway: That way we can
2136 safely del_timer it when the module is unloaded. */
2137 init_timer(&board->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138
2139 if (board->poll) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002140 board->timer.data = (unsigned long)board;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 board->timer.function = sx_pollfunc;
2142 board->timer.expires = jiffies + board->poll;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002143 add_timer(&board->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 }
2145 } else {
2146 board->irq = 0;
2147 }
2148
2149 board->nports = chans;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002150 sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
2152 func_exit();
2153 return chans;
2154}
2155
Jiri Slabycda52652006-12-08 02:39:00 -08002156static void __devinit printheader(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157{
2158 static int header_printed;
2159
2160 if (!header_printed) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002161 printk(KERN_INFO "Specialix SX driver "
2162 "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
2163 printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 header_printed = 1;
2165 }
2166}
2167
Jiri Slaby15b611f2006-12-08 02:39:04 -08002168static int __devinit probe_sx(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169{
2170 struct vpd_prom vpdp;
2171 char *p;
2172 int i;
2173
2174 func_enter();
2175
Jiri Slaby15b611f2006-12-08 02:39:04 -08002176 if (!IS_CF_BOARD(board)) {
2177 sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
2178 board->base + SX_VPD_ROM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
2180 if (sx_debug & SX_DEBUG_PROBE)
2181 my_hd_io(board->base + SX_VPD_ROM, 0x40);
2182
Jiri Slaby15b611f2006-12-08 02:39:04 -08002183 p = (char *)&vpdp;
2184 for (i = 0; i < sizeof(struct vpd_prom); i++)
2185 *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186
2187 if (sx_debug & SX_DEBUG_PROBE)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002188 my_hd(&vpdp, 0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
Jiri Slaby15b611f2006-12-08 02:39:04 -08002190 sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191
Jiri Slaby15b611f2006-12-08 02:39:04 -08002192 if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
2193 sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
2194 "'%s'\n", vpdp.identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 return 0;
2196 }
2197 }
2198
Jiri Slaby15b611f2006-12-08 02:39:04 -08002199 printheader();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
Jiri Slaby15b611f2006-12-08 02:39:04 -08002201 if (!IS_CF_BOARD(board)) {
2202 printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
2203 board->hw_base);
2204 printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
2205 "uniq ID:%08x, ",
2206 vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
2207 printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208
Jiri Slaby15b611f2006-12-08 02:39:04 -08002209 if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
2210 SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
2211 SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
2212 /* This might be a bit harsh. This was the primary
2213 reason the SX/ISA card didn't work at first... */
2214 printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
2215 "card. Sorry: giving up.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 return (0);
2217 }
2218
Jiri Slaby15b611f2006-12-08 02:39:04 -08002219 if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
2220 SX_ISA_UNIQUEID1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 if (((unsigned long)board->hw_base) & 0x8000) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002222 printk(KERN_WARNING "sx: Warning: There may be "
2223 "hardware problems with the card at "
2224 "%lx.\n", board->hw_base);
2225 printk(KERN_WARNING "sx: Read sx.txt for more "
2226 "info.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 }
2228 }
2229 }
2230
2231 board->nports = -1;
2232
2233 /* This resets the processor, and keeps it off the bus. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002234 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 return 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002236 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 func_exit();
2239 return 1;
2240}
2241
Jiri Slaby927a6f92006-12-08 02:39:02 -08002242#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243
2244/* Specialix probes for this card at 32k increments from 640k to 16M.
2245 I consider machines with less than 16M unlikely nowadays, so I'm
2246 not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA
2247 card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves
2248 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
2249
Jiri Slaby15b611f2006-12-08 02:39:04 -08002250static int __devinit probe_si(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251{
2252 int i;
2253
2254 func_enter();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002255 sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
2256 "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
2258 if (sx_debug & SX_DEBUG_PROBE)
2259 my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
2260
2261 if (!IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002262 if (IS_SI1_BOARD(board)) {
2263 for (i = 0; i < 8; i++) {
2264 write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
2265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002267 for (i = 0; i < 8; i++) {
2268 if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
2269 != i) {
2270 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 return 0;
2272 }
2273 }
2274 }
2275
2276 /* Now we're pretty much convinced that there is an SI board here,
2277 but to prevent trouble, we'd better double check that we don't
2278 have an SI1 board when we're probing for an SI2 board.... */
2279
Jiri Slaby15b611f2006-12-08 02:39:04 -08002280 write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
2281 if (IS_SI1_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 /* This should be an SI1 board, which has this
2283 location writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002284 if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
2285 func_exit();
2286 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 } else {
2289 /* This should be an SI2 board, which has the bottom
2290 3 bits non-writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002291 if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
2292 func_exit();
2293 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 }
2296
2297 /* Now we're pretty much convinced that there is an SI board here,
2298 but to prevent trouble, we'd better double check that we don't
2299 have an SI1 board when we're probing for an SI2 board.... */
2300
Jiri Slaby15b611f2006-12-08 02:39:04 -08002301 write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
2302 if (IS_SI1_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 /* This should be an SI1 board, which has this
2304 location writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002305 if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 func_exit();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002307 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 } else {
2310 /* This should be an SI2 board, which has the bottom
2311 3 bits non-writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002312 if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
2313 func_exit();
2314 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 }
2317
Jiri Slaby15b611f2006-12-08 02:39:04 -08002318 printheader();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319
Jiri Slaby15b611f2006-12-08 02:39:04 -08002320 printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 /* Compared to the SX boards, it is a complete guess as to what
Jiri Slaby15b611f2006-12-08 02:39:04 -08002322 this card is up to... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
2324 board->nports = -1;
2325
2326 /* This resets the processor, and keeps it off the bus. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002327 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 return 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002329 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 func_exit();
2332 return 1;
2333}
Jiri Slaby927a6f92006-12-08 02:39:02 -08002334#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002336static const struct tty_operations sx_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 .break_ctl = sx_break,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002338 .open = sx_open,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 .close = gs_close,
2340 .write = gs_write,
2341 .put_char = gs_put_char,
2342 .flush_chars = gs_flush_chars,
2343 .write_room = gs_write_room,
2344 .chars_in_buffer = gs_chars_in_buffer,
2345 .flush_buffer = gs_flush_buffer,
2346 .ioctl = sx_ioctl,
2347 .throttle = sx_throttle,
2348 .unthrottle = sx_unthrottle,
2349 .set_termios = gs_set_termios,
2350 .stop = gs_stop,
2351 .start = gs_start,
2352 .hangup = gs_hangup,
2353 .tiocmget = sx_tiocmget,
2354 .tiocmset = sx_tiocmset,
2355};
2356
2357static int sx_init_drivers(void)
2358{
2359 int error;
2360
2361 func_enter();
2362
2363 sx_driver = alloc_tty_driver(sx_nports);
2364 if (!sx_driver)
2365 return 1;
2366 sx_driver->owner = THIS_MODULE;
2367 sx_driver->driver_name = "specialix_sx";
2368 sx_driver->name = "ttyX";
2369 sx_driver->major = SX_NORMAL_MAJOR;
2370 sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
2371 sx_driver->subtype = SERIAL_TYPE_NORMAL;
2372 sx_driver->init_termios = tty_std_termios;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002373 sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Alan Cox606d0992006-12-08 02:38:45 -08002374 sx_driver->init_termios.c_ispeed = 9600;
2375 sx_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 sx_driver->flags = TTY_DRIVER_REAL_RAW;
2377 tty_set_operations(sx_driver, &sx_ops);
2378
2379 if ((error = tty_register_driver(sx_driver))) {
2380 put_tty_driver(sx_driver);
2381 printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
Jiri Slaby15b611f2006-12-08 02:39:04 -08002382 error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 return 1;
2384 }
2385 func_exit();
2386 return 0;
2387}
2388
Jiri Slaby15b611f2006-12-08 02:39:04 -08002389static int sx_init_portstructs(int nboards, int nports)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390{
2391 struct sx_board *board;
2392 struct sx_port *port;
2393 int i, j;
2394 int addr, chans;
2395 int portno;
2396
2397 func_enter();
2398
2399 /* Many drivers statically allocate the maximum number of ports
Jiri Slaby15b611f2006-12-08 02:39:04 -08002400 There is no reason not to allocate them dynamically.
2401 Is there? -- REW */
Jiri Slaby4a7cb692006-12-08 02:38:59 -08002402 sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 if (!sx_ports)
2404 return -ENOMEM;
2405
2406 port = sx_ports;
2407 for (i = 0; i < nboards; i++) {
2408 board = &boards[i];
2409 board->ports = port;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002410 for (j = 0; j < boards[i].nports; j++) {
2411 sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 port->gs.magic = SX_MAGIC;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002413 port->gs.close_delay = HZ / 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 port->gs.closing_wait = 30 * HZ;
2415 port->board = board;
2416 port->gs.rd = &sx_real_driver;
2417#ifdef NEW_WRITE_LOCKING
Ingo Molnar81861d72006-03-23 03:00:44 -08002418 port->gs.port_write_mutex = MUTEX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419#endif
Ingo Molnar34af9462006-06-27 02:53:55 -07002420 spin_lock_init(&port->gs.driver_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 /*
2422 * Initializing wait queue
2423 */
2424 init_waitqueue_head(&port->gs.open_wait);
Jiri Slaby15b611f2006-12-08 02:39:04 -08002425 init_waitqueue_head(&port->gs.close_wait);
2426
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 port++;
2428 }
2429 }
2430
2431 port = sx_ports;
2432 portno = 0;
2433 for (i = 0; i < nboards; i++) {
2434 board = &boards[i];
2435 board->port_base = portno;
2436 /* Possibly the configuration was rejected. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002437 sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
2438 board->nports);
2439 if (board->nports <= 0)
2440 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 /* XXX byteorder ?? */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002442 for (addr = 0x80; addr != 0;
2443 addr = read_sx_word(board, addr) & 0x7fff) {
2444 chans = sx_read_module_byte(board, addr, mc_type);
2445 sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
2446 "channels\n", addr, chans);
2447 sx_dprintk(SX_DEBUG_PROBE, "Port at");
2448 for (j = 0; j < chans; j++) {
2449 /* The "sx-way" is the way it SHOULD be done.
2450 That way in the future, the firmware may for
2451 example pack the structures a bit more
2452 efficient. Neil tells me it isn't going to
2453 happen anytime soon though. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 if (IS_SX_BOARD(board))
Jiri Slaby15b611f2006-12-08 02:39:04 -08002455 port->ch_base = sx_read_module_word(
2456 board, addr + j * 2,
2457 mc_chan_pointer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 else
Jiri Slaby15b611f2006-12-08 02:39:04 -08002459 port->ch_base = addr + 0x100 + 0x300 *j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
Jiri Slaby15b611f2006-12-08 02:39:04 -08002461 sx_dprintk(SX_DEBUG_PROBE, " %x",
2462 port->ch_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 port->line = portno++;
2464 port++;
2465 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002466 sx_dprintk(SX_DEBUG_PROBE, "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 }
2468 /* This has to be done earlier. */
2469 /* board->flags |= SX_BOARD_INITIALIZED; */
2470 }
2471
2472 func_exit();
2473 return 0;
2474}
2475
Jiri Slaby18f813e2006-12-08 02:39:01 -08002476static unsigned int sx_find_free_board(void)
2477{
2478 unsigned int i;
2479
Jiri Slaby15b611f2006-12-08 02:39:04 -08002480 for (i = 0; i < SX_NBOARDS; i++)
Jiri Slaby18f813e2006-12-08 02:39:01 -08002481 if (!(boards[i].flags & SX_BOARD_PRESENT))
2482 break;
2483
2484 return i;
2485}
2486
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487static void __exit sx_release_drivers(void)
2488{
2489 func_enter();
2490 tty_unregister_driver(sx_driver);
2491 put_tty_driver(sx_driver);
2492 func_exit();
2493}
2494
Jiri Slaby18f813e2006-12-08 02:39:01 -08002495static void __devexit sx_remove_card(struct sx_board *board)
2496{
2497 if (board->flags & SX_BOARD_INITIALIZED) {
2498 /* The board should stop messing with us. (actually I mean the
2499 interrupt) */
2500 sx_reset(board);
2501 if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
2502 free_irq(board->irq, board);
2503
2504 /* It is safe/allowed to del_timer a non-active timer */
2505 del_timer(&board->timer);
2506 iounmap(board->base);
2507
Jiri Slaby15b611f2006-12-08 02:39:04 -08002508 board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002509 }
2510}
2511
2512#ifdef CONFIG_EISA
2513
2514static int __devinit sx_eisa_probe(struct device *dev)
2515{
2516 struct eisa_device *edev = to_eisa_device(dev);
2517 struct sx_board *board;
2518 unsigned long eisa_slot = edev->base_addr;
2519 unsigned int i;
2520 int retval = -EIO;
2521
Jiri Slaby42f63842006-12-08 02:39:03 -08002522 mutex_lock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002523 i = sx_find_free_board();
Jiri Slaby42f63842006-12-08 02:39:03 -08002524 if (i == SX_NBOARDS) {
2525 mutex_unlock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002526 goto err;
Jiri Slaby42f63842006-12-08 02:39:03 -08002527 }
2528 board = &boards[i];
2529 board->flags |= SX_BOARD_PRESENT;
2530 mutex_unlock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002531
2532 dev_info(dev, "XIO : Signature found in EISA slot %lu, "
Jiri Slaby15b611f2006-12-08 02:39:04 -08002533 "Product %d Rev %d (REPORT THIS TO LKLM)\n",
2534 eisa_slot >> 12,
2535 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
2536 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
Jiri Slaby18f813e2006-12-08 02:39:01 -08002537
Jiri Slaby18f813e2006-12-08 02:39:01 -08002538 board->eisa_base = eisa_slot;
2539 board->flags &= ~SX_BOARD_TYPE;
2540 board->flags |= SI_EISA_BOARD;
2541
2542 board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
Jiri Slaby15b611f2006-12-08 02:39:04 -08002543 inb(eisa_slot + 0xc00)) << 16;
Jiri Slaby18f813e2006-12-08 02:39:01 -08002544 board->base2 =
2545 board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
2546
2547 sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
2548 sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
2549 board->irq = inb(eisa_slot + 0xc02) >> 4;
2550 sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
2551
2552 if (!probe_si(board))
2553 goto err_unmap;
2554
2555 dev_set_drvdata(dev, board);
2556
2557 return 0;
2558err_unmap:
2559 iounmap(board->base);
Jiri Slaby42f63842006-12-08 02:39:03 -08002560 board->flags &= ~SX_BOARD_PRESENT;
Jiri Slaby18f813e2006-12-08 02:39:01 -08002561err:
2562 return retval;
2563}
2564
2565static int __devexit sx_eisa_remove(struct device *dev)
2566{
2567 struct sx_board *board = dev_get_drvdata(dev);
2568
2569 sx_remove_card(board);
2570
2571 return 0;
2572}
2573
2574static struct eisa_device_id sx_eisa_tbl[] = {
2575 { "SLX" },
2576 { "" }
2577};
Jiri Slaby15b611f2006-12-08 02:39:04 -08002578
Jiri Slaby18f813e2006-12-08 02:39:01 -08002579MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
2580
2581static struct eisa_driver sx_eisadriver = {
2582 .id_table = sx_eisa_tbl,
2583 .driver = {
2584 .name = "sx",
2585 .probe = sx_eisa_probe,
2586 .remove = __devexit_p(sx_eisa_remove),
2587 }
2588};
2589
2590#endif
2591
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 /********************************************************
2593 * Setting bit 17 in the CNTRL register of the PLX 9050 *
2594 * chip forces a retry on writes while a read is pending.*
2595 * This is to prevent the card locking up on Intel Xeon *
2596 * multiprocessor systems with the NX chipset. -- NV *
2597 ********************************************************/
2598
2599/* Newer cards are produced with this bit set from the configuration
2600 EEprom. As the bit is read/write for the CPU, we can fix it here,
2601 if we detect that it isn't set correctly. -- REW */
2602
Jiri Slabycda52652006-12-08 02:39:00 -08002603static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604{
2605 unsigned int hwbase;
2606 void __iomem *rebase;
2607 unsigned int t;
2608
Jiri Slaby15b611f2006-12-08 02:39:04 -08002609#define CNTRL_REG_OFFSET 0x50
2610#define CNTRL_REG_GOODVALUE 0x18260000
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
2612 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
2613 hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
2614 rebase = ioremap(hwbase, 0x80);
Jiri Slaby15b611f2006-12-08 02:39:04 -08002615 t = readl(rebase + CNTRL_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 if (t != CNTRL_REG_GOODVALUE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002617 printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
2618 "%08x\n", t, CNTRL_REG_GOODVALUE);
2619 writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 }
2621 iounmap(rebase);
2622}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623
Jiri Slaby5572e102006-12-08 02:38:58 -08002624static int __devinit sx_pci_probe(struct pci_dev *pdev,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002625 const struct pci_device_id *ent)
Jiri Slaby5572e102006-12-08 02:38:58 -08002626{
2627 struct sx_board *board;
2628 unsigned int i;
2629 int retval = -EIO;
2630
Jiri Slaby42f63842006-12-08 02:39:03 -08002631 mutex_lock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002632 i = sx_find_free_board();
Jiri Slaby42f63842006-12-08 02:39:03 -08002633 if (i == SX_NBOARDS) {
2634 mutex_unlock(&sx_boards_lock);
Jiri Slaby5572e102006-12-08 02:38:58 -08002635 goto err;
Jiri Slaby42f63842006-12-08 02:39:03 -08002636 }
2637 board = &boards[i];
2638 board->flags |= SX_BOARD_PRESENT;
2639 mutex_unlock(&sx_boards_lock);
Jiri Slaby5572e102006-12-08 02:38:58 -08002640
2641 retval = pci_enable_device(pdev);
2642 if (retval)
Jiri Slaby42f63842006-12-08 02:39:03 -08002643 goto err_flag;
Jiri Slaby5572e102006-12-08 02:38:58 -08002644
2645 board->flags &= ~SX_BOARD_TYPE;
2646 board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
Jiri Slaby15b611f2006-12-08 02:39:04 -08002647 SX_CFPCI_BOARD;
Jiri Slaby5572e102006-12-08 02:38:58 -08002648
2649 /* CF boards use base address 3.... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002650 if (IS_CF_BOARD(board))
Jiri Slaby5572e102006-12-08 02:38:58 -08002651 board->hw_base = pci_resource_start(pdev, 3);
2652 else
2653 board->hw_base = pci_resource_start(pdev, 2);
2654 board->base2 =
Jiri Slaby15b611f2006-12-08 02:39:04 -08002655 board->base = ioremap(board->hw_base, WINDOW_LEN(board));
Jiri Slaby5572e102006-12-08 02:38:58 -08002656 if (!board->base) {
2657 dev_err(&pdev->dev, "ioremap failed\n");
Jiri Slaby42f63842006-12-08 02:39:03 -08002658 goto err_flag;
Jiri Slaby5572e102006-12-08 02:38:58 -08002659 }
2660
2661 /* Most of the stuff on the CF board is offset by 0x18000 .... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002662 if (IS_CF_BOARD(board))
Jiri Slaby5572e102006-12-08 02:38:58 -08002663 board->base += 0x18000;
2664
2665 board->irq = pdev->irq;
2666
2667 dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002668 board->irq, board->flags);
Jiri Slaby5572e102006-12-08 02:38:58 -08002669
2670 if (!probe_sx(board)) {
2671 retval = -EIO;
2672 goto err_unmap;
2673 }
2674
2675 fix_sx_pci(pdev, board);
2676
2677 pci_set_drvdata(pdev, board);
2678
2679 return 0;
2680err_unmap:
2681 iounmap(board->base2);
Jiri Slaby42f63842006-12-08 02:39:03 -08002682err_flag:
2683 board->flags &= ~SX_BOARD_PRESENT;
Jiri Slaby5572e102006-12-08 02:38:58 -08002684err:
2685 return retval;
2686}
2687
2688static void __devexit sx_pci_remove(struct pci_dev *pdev)
2689{
2690 struct sx_board *board = pci_get_drvdata(pdev);
2691
Jiri Slaby18f813e2006-12-08 02:39:01 -08002692 sx_remove_card(board);
Jiri Slaby5572e102006-12-08 02:38:58 -08002693}
2694
2695/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
2696 its because the standard requires it. So check for SUBVENDOR_ID. */
2697static struct pci_device_id sx_pci_tbl[] = {
2698 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002699 .subvendor = 0x0200,.subdevice = PCI_ANY_ID },
Jiri Slaby5572e102006-12-08 02:38:58 -08002700 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002701 .subvendor = 0x0300,.subdevice = PCI_ANY_ID },
Jiri Slaby5572e102006-12-08 02:38:58 -08002702 { 0 }
2703};
Jiri Slaby15b611f2006-12-08 02:39:04 -08002704
Jiri Slaby5572e102006-12-08 02:38:58 -08002705MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
2706
2707static struct pci_driver sx_pcidriver = {
2708 .name = "sx",
2709 .id_table = sx_pci_tbl,
2710 .probe = sx_pci_probe,
2711 .remove = __devexit_p(sx_pci_remove)
2712};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713
Jiri Slaby15b611f2006-12-08 02:39:04 -08002714static int __init sx_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715{
Jiri Slaby18f813e2006-12-08 02:39:01 -08002716#ifdef CONFIG_EISA
2717 int retval1;
2718#endif
Jiri Slaby927a6f92006-12-08 02:39:02 -08002719#ifdef CONFIG_ISA
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 struct sx_board *board;
Jiri Slaby927a6f92006-12-08 02:39:02 -08002721 unsigned int i;
2722#endif
2723 unsigned int found = 0;
2724 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 func_enter();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002727 sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
2728 sx_debug);
2729 if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
2730 printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
2731 "value. Assuming -1.\n(%p)\n", &sx_debug);
2732 sx_debug = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 }
2734
2735 if (misc_register(&sx_fw_device) < 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002736 printk(KERN_ERR "SX: Unable to register firmware loader "
2737 "driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 return -EIO;
2739 }
Jiri Slaby927a6f92006-12-08 02:39:02 -08002740#ifdef CONFIG_ISA
Jiri Slaby15b611f2006-12-08 02:39:04 -08002741 for (i = 0; i < NR_SX_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 board = &boards[found];
2743 board->hw_base = sx_probe_addrs[i];
2744 board->base2 =
2745 board->base = ioremap(board->hw_base, SX_WINDOW_LEN);
2746 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002747 board->flags |= SX_ISA_BOARD;
2748 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749
Jiri Slaby15b611f2006-12-08 02:39:04 -08002750 if (probe_sx(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002751 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 found++;
2753 } else {
2754 iounmap(board->base);
2755 }
2756 }
2757
Jiri Slaby15b611f2006-12-08 02:39:04 -08002758 for (i = 0; i < NR_SI_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 board = &boards[found];
2760 board->hw_base = si_probe_addrs[i];
2761 board->base2 =
2762 board->base = ioremap(board->hw_base, SI2_ISA_WINDOW_LEN);
2763 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002764 board->flags |= SI_ISA_BOARD;
2765 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766
Jiri Slaby15b611f2006-12-08 02:39:04 -08002767 if (probe_si(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002768 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 found++;
2770 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002771 iounmap(board->base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 }
2773 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002774 for (i = 0; i < NR_SI1_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 board = &boards[found];
2776 board->hw_base = si1_probe_addrs[i];
2777 board->base2 =
2778 board->base = ioremap(board->hw_base, SI1_ISA_WINDOW_LEN);
2779 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002780 board->flags |= SI1_ISA_BOARD;
2781 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782
Jiri Slaby15b611f2006-12-08 02:39:04 -08002783 if (probe_si(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002784 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 found++;
2786 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002787 iounmap(board->base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 }
2789 }
Jiri Slaby927a6f92006-12-08 02:39:02 -08002790#endif
Jiri Slaby18f813e2006-12-08 02:39:01 -08002791#ifdef CONFIG_EISA
2792 retval1 = eisa_driver_register(&sx_eisadriver);
2793#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002794 retval = pci_register_driver(&sx_pcidriver);
2795
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 if (found) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002797 printk(KERN_INFO "sx: total of %d boards detected.\n", found);
Jiri Slaby5572e102006-12-08 02:38:58 -08002798 retval = 0;
2799 } else if (retval) {
Jiri Slaby18f813e2006-12-08 02:39:01 -08002800#ifdef CONFIG_EISA
2801 if (retval1)
2802#endif
Jiri Slaby15b611f2006-12-08 02:39:04 -08002803 misc_deregister(&sx_fw_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 }
2805
2806 func_exit();
Jiri Slaby5572e102006-12-08 02:38:58 -08002807 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808}
2809
Jiri Slaby15b611f2006-12-08 02:39:04 -08002810static void __exit sx_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811{
Jiri Slaby15b611f2006-12-08 02:39:04 -08002812 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
2814 func_enter();
Jiri Slaby18f813e2006-12-08 02:39:01 -08002815#ifdef CONFIG_EISA
2816 eisa_driver_unregister(&sx_eisadriver);
2817#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002818 pci_unregister_driver(&sx_pcidriver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
Jiri Slaby55e70712006-12-08 02:39:03 -08002820 for (i = 0; i < SX_NBOARDS; i++)
2821 sx_remove_card(&boards[i]);
2822
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 if (misc_deregister(&sx_fw_device) < 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002824 printk(KERN_INFO "sx: couldn't deregister firmware loader "
2825 "device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002827 sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
2828 sx_initialized);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 if (sx_initialized)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002830 sx_release_drivers();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831
Jiri Slaby15b611f2006-12-08 02:39:04 -08002832 kfree(sx_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 func_exit();
2834}
2835
2836module_init(sx_init);
2837module_exit(sx_exit);