blob: b1a7a8cb65ea0252f0cbc0c5194dbc9ad9c8dcd9 [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
Harvey Harrisonbf9d8922008-04-30 00:55:10 -0700387#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
388#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__func__)
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", \
Harvey Harrisonbf9d8922008-04-30 00:55:10 -0700391 __func__, 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:
Andrew Morton32fb3ca2008-05-06 20:42:35 -0700973 printk(KERN_INFO "sx: Invalid wordsize: %u\n",
974 (unsigned int)CFLAG & CSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 break;
976 }
977
Jiri Slaby15b611f2006-12-08 02:39:04 -0800978 sx_write_channel_byte(port, hi_prtcl,
979 (I_IXON(port->gs.tty) ? SP_TXEN : 0) |
980 (I_IXOFF(port->gs.tty) ? SP_RXEN : 0) |
981 (I_IXANY(port->gs.tty) ? SP_TANY : 0) | SP_DCEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Jiri Slaby15b611f2006-12-08 02:39:04 -0800983 sx_write_channel_byte(port, hi_break,
984 (I_IGNBRK(port->gs.tty) ? BR_IGN : 0 |
985 I_BRKINT(port->gs.tty) ? BR_INT : 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
Jiri Slaby15b611f2006-12-08 02:39:04 -0800987 sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.tty));
988 sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.tty));
989 sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.tty));
990 sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
992 sx_reconfigure_port(port);
993
994 /* Tell line discipline whether we will do input cooking */
Jiri Slaby15b611f2006-12-08 02:39:04 -0800995 if (I_OTHER(port->gs.tty)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
997 } else {
998 set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags);
999 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001000 sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
Andrew Morton32fb3ca2008-05-06 20:42:35 -07001001 (unsigned int)port->gs.tty->termios->c_iflag,
1002 I_OTHER(port->gs.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
1004/* Tell line discipline whether we will do output cooking.
1005 * If OPOST is set and no other output flags are set then we can do output
1006 * processing. Even if only *one* other flag in the O_OTHER group is set
1007 * we do cooking in software.
1008 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001009 if (O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
1011 } else {
1012 clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags);
1013 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08001014 sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
Andrew Morton32fb3ca2008-05-06 20:42:35 -07001015 (unsigned int)port->gs.tty->termios->c_oflag,
1016 O_OTHER(port->gs.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 /* port->c_dcd = sx_get_CD (port); */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001018 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return 0;
1020}
1021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022/* ********************************************************************** *
1023 * the interrupt related routines *
1024 * ********************************************************************** */
1025
1026/* Note:
1027 Other drivers use the macro "MIN" to calculate how much to copy.
1028 This has the disadvantage that it will evaluate parts twice. That's
1029 expensive when it's IO (and the compiler cannot optimize those away!).
1030 Moreover, I'm not sure that you're race-free.
1031
1032 I assign a value, and then only allow the value to decrease. This
1033 is always safe. This makes the code a few lines longer, and you
1034 know I'm dead against that, but I think it is required in this
1035 case. */
1036
Jiri Slaby15b611f2006-12-08 02:39:04 -08001037static void sx_transmit_chars(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038{
1039 int c;
1040 int tx_ip;
1041 int txroom;
1042
Jiri Slaby15b611f2006-12-08 02:39:04 -08001043 func_enter2();
1044 sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
1045 port, port->gs.xmit_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
Jiri Slaby15b611f2006-12-08 02:39:04 -08001047 if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 return;
1049 }
1050
1051 while (1) {
1052 c = port->gs.xmit_cnt;
1053
Jiri Slaby15b611f2006-12-08 02:39:04 -08001054 sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
1055 tx_ip = sx_read_channel_byte(port, hi_txipos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
1057 /* Took me 5 minutes to deduce this formula.
1058 Luckily it is literally in the manual in section 6.5.4.3.5 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001059 txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
1060 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
1062 /* Don't copy more bytes than there is room for in the buffer */
1063 if (c > txroom)
1064 c = txroom;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001065 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
1067 /* Don't copy past the end of the hardware transmit buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001068 if (c > 0x100 - tx_ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 c = 0x100 - tx_ip;
1070
Jiri Slaby15b611f2006-12-08 02:39:04 -08001071 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
1073 /* Don't copy pas the end of the source buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001074 if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
1076
Jiri Slaby15b611f2006-12-08 02:39:04 -08001077 sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
1078 c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
Jiri Slaby15b611f2006-12-08 02:39:04 -08001080 /* If for one reason or another, we can't copy more data, we're
1081 done! */
1082 if (c == 0)
1083 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Jiri Slaby15b611f2006-12-08 02:39:04 -08001085 memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
1086 tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 /* Update the pointer in the card */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001089 sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
1091 /* Update the kernel buffer end */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001092 port->gs.xmit_tail = (port->gs.xmit_tail + c) &
1093 (SERIAL_XMIT_SIZE - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095 /* This one last. (this is essential)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001096 It would allow others to start putting more data into the
1097 buffer! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 port->gs.xmit_cnt -= c;
1099 }
1100
1101 if (port->gs.xmit_cnt == 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001102 sx_disable_tx_interrupts(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 }
1104
1105 if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
1106 tty_wakeup(port->gs.tty);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001107 sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
1108 port->gs.wakeup_chars);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 }
1110
Jiri Slaby15b611f2006-12-08 02:39:04 -08001111 clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
1112 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113}
1114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115/* Note the symmetry between receiving chars and transmitting them!
1116 Note: The kernel should have implemented both a receive buffer and
1117 a transmit buffer. */
1118
1119/* Inlined: Called only once. Remove the inline when you add another call */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001120static inline void sx_receive_chars(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
1122 int c;
1123 int rx_op;
1124 struct tty_struct *tty;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001125 int copied = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08001126 unsigned char *rp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
Jiri Slaby15b611f2006-12-08 02:39:04 -08001128 func_enter2();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 tty = port->gs.tty;
1130 while (1) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001131 rx_op = sx_read_channel_byte(port, hi_rxopos);
1132 c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Jiri Slaby15b611f2006-12-08 02:39:04 -08001134 sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001136 /* Don't copy past the end of the hardware receive buffer */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001137 if (rx_op + c > 0x100)
1138 c = 0x100 - rx_op;
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001139
Jiri Slaby15b611f2006-12-08 02:39:04 -08001140 sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
Marc Zyngierd904ffd2006-02-27 12:08:00 +01001141
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 /* Don't copy more bytes than there is room for in the buffer */
Alan Cox33f0f882006-01-09 20:54:13 -08001143
1144 c = tty_prepare_flip_string(tty, &rp, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
Jiri Slaby15b611f2006-12-08 02:39:04 -08001146 sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 /* If for one reason or another, we can't copy more data, we're done! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001149 if (c == 0)
1150 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Jiri Slaby15b611f2006-12-08 02:39:04 -08001152 sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
1153 "%d at %lx\n", c, read_sx_byte(port->board,
1154 CHAN_OFFSET(port, hi_rxbuf) + rx_op),
1155 CHAN_OFFSET(port, hi_rxbuf));
1156 memcpy_fromio(rp, port->board->base +
1157 CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
1159 /* This one last. ( Not essential.)
Jiri Slaby15b611f2006-12-08 02:39:04 -08001160 It allows the card to start putting more data into the
1161 buffer!
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 Update the pointer in the card */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001163 sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 copied += c;
1166 }
1167 if (copied) {
1168 struct timeval tv;
1169
Jiri Slaby15b611f2006-12-08 02:39:04 -08001170 do_gettimeofday(&tv);
1171 sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
1172 "chars): %d.%06d (%d/%d)\n", port->line,
1173 copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
1174 tty->raw, tty->real_raw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
Jiri Slaby15b611f2006-12-08 02:39:04 -08001176 /* Tell the rest of the system the news. Great news. New
1177 characters! */
1178 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 /* tty_schedule_flip (tty); */
1180 }
1181
Jiri Slaby15b611f2006-12-08 02:39:04 -08001182 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183}
1184
1185/* Inlined: it is called only once. Remove the inline if you add another
1186 call */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001187static inline void sx_check_modem_signals(struct sx_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188{
1189 int hi_state;
1190 int c_dcd;
1191
Jiri Slaby15b611f2006-12-08 02:39:04 -08001192 hi_state = sx_read_channel_byte(port, hi_state);
1193 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
1194 port->c_dcd, sx_get_CD(port));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 if (hi_state & ST_BREAK) {
1197 hi_state &= ~ST_BREAK;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001198 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
1199 sx_write_channel_byte(port, hi_state, hi_state);
1200 gs_got_break(&port->gs);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 }
1202 if (hi_state & ST_DCD) {
1203 hi_state &= ~ST_DCD;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001204 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
1205 sx_write_channel_byte(port, hi_state, hi_state);
1206 c_dcd = sx_get_CD(port);
1207 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 if (c_dcd != port->c_dcd) {
1209 port->c_dcd = c_dcd;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001210 if (sx_get_CD(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 /* DCD went UP */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001212 if ((sx_read_channel_byte(port, hi_hstat) !=
1213 HS_IDLE_CLOSED) &&
1214 !(port->gs.tty->termios->
1215 c_cflag & CLOCAL)) {
1216 /* Are we blocking in open? */
1217 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1218 "active, unblocking open\n");
1219 wake_up_interruptible(&port->gs.
1220 open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001222 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1223 "raised. Ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
1225 } else {
1226 /* DCD went down! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001227 if (!(port->gs.tty->termios->c_cflag & CLOCAL)){
1228 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1229 "dropped. hanging up....\n");
1230 tty_hangup(port->gs.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001232 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
1233 "dropped. ignoring.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
1235 }
1236 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001237 sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
1238 "DCD changed, but it didn't.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 }
1240 }
1241}
1242
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243/* This is what an interrupt routine should look like.
1244 * Small, elegant, clear.
1245 */
1246
Jiri Slaby15b611f2006-12-08 02:39:04 -08001247static irqreturn_t sx_interrupt(int irq, void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248{
1249 struct sx_board *board = ptr;
1250 struct sx_port *port;
1251 int i;
1252
Jiri Slaby15b611f2006-12-08 02:39:04 -08001253 func_enter();
1254 sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
1255 board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
1257 /* AAargh! The order in which to do these things is essential and
1258 not trivial.
1259
1260 - Rate limit goes before "recursive". Otherwise a series of
Jiri Slaby15b611f2006-12-08 02:39:04 -08001261 recursive calls will hang the machine in the interrupt routine.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
1263 - hardware twiddling goes before "recursive". Otherwise when we
Jiri Slaby15b611f2006-12-08 02:39:04 -08001264 poll the card, and a recursive interrupt happens, we won't
1265 ack the card, so it might keep on interrupting us. (especially
1266 level sensitive interrupt systems like PCI).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
1268 - Rate limit goes before hardware twiddling. Otherwise we won't
Jiri Slaby15b611f2006-12-08 02:39:04 -08001269 catch a card that has gone bonkers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 - The "initialized" test goes after the hardware twiddling. Otherwise
Jiri Slaby15b611f2006-12-08 02:39:04 -08001272 the card will stick us in the interrupt routine again.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274 - The initialized test goes before recursive.
Jiri Slaby15b611f2006-12-08 02:39:04 -08001275 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277#ifdef IRQ_RATE_LIMIT
1278 /* Aaargh! I'm ashamed. This costs more lines-of-code than the
Jiri Slaby15b611f2006-12-08 02:39:04 -08001279 actual interrupt routine!. (Well, used to when I wrote that
1280 comment) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 {
1282 static int lastjif;
Jiri Slaby15b611f2006-12-08 02:39:04 -08001283 static int nintr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
1285 if (lastjif == jiffies) {
1286 if (++nintr > IRQ_RATE_LIMIT) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001287 free_irq(board->irq, board);
1288 printk(KERN_ERR "sx: Too many interrupts. "
1289 "Turning off interrupt %d.\n",
1290 board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 }
1292 } else {
1293 lastjif = jiffies;
1294 nintr = 0;
1295 }
1296 }
1297#endif
1298
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 if (board->irq == irq) {
1300 /* Tell the card we've noticed the interrupt. */
1301
Jiri Slaby15b611f2006-12-08 02:39:04 -08001302 sx_write_board_word(board, cc_int_pending, 0);
1303 if (IS_SX_BOARD(board)) {
1304 write_sx_byte(board, SX_RESET_IRQ, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 } else if (IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001306 inb(board->eisa_base + 0xc03);
1307 write_sx_word(board, 8, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001309 write_sx_byte(board, SI2_ISA_INTCLEAR,
1310 SI2_ISA_INTCLEAR_CLEAR);
1311 write_sx_byte(board, SI2_ISA_INTCLEAR,
1312 SI2_ISA_INTCLEAR_SET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 }
1314 }
1315
1316 if (!sx_initialized)
1317 return IRQ_HANDLED;
1318 if (!(board->flags & SX_BOARD_INITIALIZED))
1319 return IRQ_HANDLED;
1320
Jiri Slaby15b611f2006-12-08 02:39:04 -08001321 if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
1322 printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 return IRQ_HANDLED;
1324 }
1325
Jiri Slaby15b611f2006-12-08 02:39:04 -08001326 for (i = 0; i < board->nports; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 port = &board->ports[i];
1328 if (port->gs.flags & GS_ACTIVE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001329 if (sx_read_channel_byte(port, hi_state)) {
1330 sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
1331 "modem signal change?... \n",i);
1332 sx_check_modem_signals(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 }
1334 if (port->gs.xmit_cnt) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001335 sx_transmit_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 }
1337 if (!(port->gs.flags & SX_RX_THROTTLE)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08001338 sx_receive_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 }
1340 }
1341 }
1342
Jiri Slaby15b611f2006-12-08 02:39:04 -08001343 clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Jiri Slaby15b611f2006-12-08 02:39:04 -08001345 sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
1346 board->irq);
1347 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 return IRQ_HANDLED;
1349}
1350
Jiri Slaby15b611f2006-12-08 02:39:04 -08001351static void sx_pollfunc(unsigned long data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001353 struct sx_board *board = (struct sx_board *)data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Jiri Slaby15b611f2006-12-08 02:39:04 -08001355 func_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Jiri Slaby15b611f2006-12-08 02:39:04 -08001357 sx_interrupt(0, board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Jiri Slabyc9594642006-12-08 02:39:05 -08001359 mod_timer(&board->timer, jiffies + sx_poll);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001360 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361}
1362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363/* ********************************************************************** *
1364 * Here are the routines that actually *
1365 * interface with the generic_serial driver *
1366 * ********************************************************************** */
1367
1368/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
1369/* Hmm. Ok I figured it out. You don't. */
1370
Jiri Slaby15b611f2006-12-08 02:39:04 -08001371static void sx_disable_tx_interrupts(void *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
Jiri Slaby15b611f2006-12-08 02:39:04 -08001373 struct sx_port *port = ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 func_enter2();
1375
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, "
Pavel Emelyanovba25f9d2007-10-18 23:40:40 -07001473 "np=%d)\n", task_pid_nr(current), line, tty,
Jiri Slaby15b611f2006-12-08 02:39:04 -08001474 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",
Harvey Harrisonbf9d8922008-04-30 00:55:10 -07001580 __func__, port, port->gs.count);
Jiri Slaby15b611f2006-12-08 02:39:04 -08001581 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();
Alan Cox341339e2008-04-30 00:53:24 -07001850 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
Jiri Slaby15b611f2006-12-08 02:39:04 -08001852 if (flag)
1853 rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
1854 else
1855 rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
1856 if (rv != 1)
1857 printk(KERN_ERR "sx: couldn't send break (%x).\n",
1858 read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
Alan Cox341339e2008-04-30 00:53:24 -07001859 unlock_kernel();
Jiri Slaby15b611f2006-12-08 02:39:04 -08001860 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861}
1862
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1864{
1865 struct sx_port *port = tty->driver_data;
1866 return sx_getsignals(port);
1867}
1868
1869static int sx_tiocmset(struct tty_struct *tty, struct file *file,
Jiri Slaby15b611f2006-12-08 02:39:04 -08001870 unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871{
1872 struct sx_port *port = tty->driver_data;
1873 int rts = -1, dtr = -1;
1874
1875 if (set & TIOCM_RTS)
1876 rts = 1;
1877 if (set & TIOCM_DTR)
1878 dtr = 1;
1879 if (clear & TIOCM_RTS)
1880 rts = 0;
1881 if (clear & TIOCM_DTR)
1882 dtr = 0;
1883
1884 sx_setsignals(port, dtr, rts);
1885 sx_reconfigure_port(port);
1886 return 0;
1887}
1888
Jiri Slaby15b611f2006-12-08 02:39:04 -08001889static int sx_ioctl(struct tty_struct *tty, struct file *filp,
1890 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891{
1892 int rc;
1893 struct sx_port *port = tty->driver_data;
1894 void __user *argp = (void __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895
1896 /* func_enter2(); */
1897
1898 rc = 0;
Alan Cox341339e2008-04-30 00:53:24 -07001899 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 case TIOCGSERIAL:
1902 rc = gs_getserial(&port->gs, argp);
1903 break;
1904 case TIOCSSERIAL:
1905 rc = gs_setserial(&port->gs, argp);
1906 break;
1907 default:
1908 rc = -ENOIOCTLCMD;
1909 break;
1910 }
Alan Cox341339e2008-04-30 00:53:24 -07001911 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
1913 /* func_exit(); */
1914 return rc;
1915}
1916
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917/* The throttle/unthrottle scheme for the Specialix card is different
1918 * from other drivers and deserves some explanation.
1919 * The Specialix hardware takes care of XON/XOFF
1920 * and CTS/RTS flow control itself. This means that all we have to
1921 * do when signalled by the upper tty layer to throttle/unthrottle is
1922 * to make a note of it here. When we come to read characters from the
1923 * rx buffers on the card (sx_receive_chars()) we look to see if the
1924 * upper layer can accept more (as noted here in sx_rx_throt[]).
1925 * If it can't we simply don't remove chars from the cards buffer.
1926 * When the tty layer can accept chars, we again note that here and when
1927 * sx_receive_chars() is called it will remove them from the cards buffer.
1928 * The card will notice that a ports buffer has drained below some low
1929 * water mark and will unflow control the line itself, using whatever
1930 * flow control scheme is in use for that port. -- Simon Allen
1931 */
1932
Jiri Slaby15b611f2006-12-08 02:39:04 -08001933static void sx_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934{
1935 struct sx_port *port = (struct sx_port *)tty->driver_data;
1936
1937 func_enter2();
1938 /* If the port is using any type of input flow
1939 * control then throttle the port.
1940 */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001941 if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 port->gs.flags |= SX_RX_THROTTLE;
1943 }
1944 func_exit();
1945}
1946
Jiri Slaby15b611f2006-12-08 02:39:04 -08001947static void sx_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948{
1949 struct sx_port *port = (struct sx_port *)tty->driver_data;
1950
1951 func_enter2();
1952 /* Always unthrottle even if flow control is not enabled on
1953 * this port in case we disabled flow control while the port
1954 * was throttled
1955 */
1956 port->gs.flags &= ~SX_RX_THROTTLE;
1957 func_exit();
1958 return;
1959}
1960
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961/* ********************************************************************** *
1962 * Here are the initialization routines. *
1963 * ********************************************************************** */
1964
Jiri Slaby15b611f2006-12-08 02:39:04 -08001965static int sx_init_board(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966{
1967 int addr;
1968 int chans;
1969 int type;
1970
1971 func_enter();
1972
1973 /* This is preceded by downloading the download code. */
1974
1975 board->flags |= SX_BOARD_INITIALIZED;
1976
Jiri Slaby15b611f2006-12-08 02:39:04 -08001977 if (read_sx_byte(board, 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 /* CF boards may need this. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001979 write_sx_byte(board, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980
1981 /* This resets the processor again, to make sure it didn't do any
1982 foolish things while we were downloading the image */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001983 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 return 0;
1985
Jiri Slaby15b611f2006-12-08 02:39:04 -08001986 sx_start_board(board);
1987 udelay(10);
1988 if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
1989 printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 return 0;
1991 }
1992
1993 /* Ok. So now the processor on the card is running. It gathered
1994 some info for us... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08001995 sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
1996 if (sx_debug & SX_DEBUG_INIT)
1997 my_hd_io(board->base, 0x10);
1998 sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
1999 if (sx_debug & SX_DEBUG_INIT)
2000 my_hd_io(board->base + 0x80, 0x30);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
Jiri Slaby15b611f2006-12-08 02:39:04 -08002002 sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
2003 "V%x.%02x,\n",
2004 read_sx_byte(board, 0), read_sx_byte(board, 1),
2005 read_sx_byte(board, 5), read_sx_byte(board, 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
Jiri Slaby15b611f2006-12-08 02:39:04 -08002007 if (read_sx_byte(board, 0) == 0xff) {
2008 printk(KERN_INFO "sx: No modules found. Sorry.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 board->nports = 0;
2010 return 0;
2011 }
2012
2013 chans = 0;
2014
2015 if (IS_SX_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002016 sx_write_board_word(board, cc_int_count, sx_maxints);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 } else {
2018 if (sx_maxints)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002019 sx_write_board_word(board, cc_int_count,
2020 SI_PROCESSOR_CLOCK / 8 / sx_maxints);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 }
2022
2023 /* grab the first module type... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002024 /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
2025 board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
2026 mc_chip));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027
2028 /* XXX byteorder */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002029 for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
2030 type = sx_read_module_byte(board, addr, mc_chip);
2031 sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
2032 addr, read_sx_byte(board, addr + 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
Jiri Slaby15b611f2006-12-08 02:39:04 -08002034 chans += sx_read_module_byte(board, addr, mc_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035
Jiri Slaby15b611f2006-12-08 02:39:04 -08002036 sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
2037 "panels\n",
2038 mod_type_s(type),
2039 pan_type_s(sx_read_module_byte(board, addr,
2040 mc_mods) & 0xf),
2041 pan_type_s(sx_read_module_byte(board, addr,
2042 mc_mods) >> 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043
Jiri Slaby15b611f2006-12-08 02:39:04 -08002044 sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
2045 "version: %x\n",
2046 sx_read_module_byte(board, addr, mc_rev1),
2047 sx_read_module_byte(board, addr, mc_rev2),
2048 sx_read_module_byte(board, addr, mc_mtaasic_rev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
2050 /* The following combinations are illegal: It should theoretically
2051 work, but timing problems make the bus HANG. */
2052
Jiri Slaby15b611f2006-12-08 02:39:04 -08002053 if (mod_compat_type(type) != board->ta_type) {
2054 printk(KERN_ERR "sx: This is an invalid "
2055 "configuration.\nDon't mix TA/MTA/SXDC on the "
2056 "same hostadapter.\n");
2057 chans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 break;
2059 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002060 if ((IS_EISA_BOARD(board) ||
2061 IS_SI_BOARD(board)) &&
2062 (mod_compat_type(type) == 4)) {
2063 printk(KERN_ERR "sx: This is an invalid "
2064 "configuration.\nDon't use SXDCs on an SI/XIO "
2065 "adapter.\n");
2066 chans = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 break;
2068 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002069#if 0 /* Problem fixed: firmware 3.05 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 if (IS_SX_BOARD(board) && (type == TA8)) {
2071 /* There are some issues with the firmware and the DCD/RTS
2072 lines. It might work if you tie them together or something.
Jiri Slaby15b611f2006-12-08 02:39:04 -08002073 It might also work if you get a newer sx_firmware. Therefore
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 this is just a warning. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002075 printk(KERN_WARNING
2076 "sx: The SX host doesn't work too well "
2077 "with the TA8 adapters.\nSpecialix is working on it.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 }
2079#endif
2080 }
2081
2082 if (chans) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002083 if (board->irq > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 /* fixed irq, probably PCI */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002085 if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */
2086 if (request_irq(board->irq, sx_interrupt,
2087 IRQF_SHARED | IRQF_DISABLED,
2088 "sx", board)) {
2089 printk(KERN_ERR "sx: Cannot allocate "
2090 "irq %d.\n", board->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 board->irq = 0;
2092 }
2093 } else
2094 board->irq = 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002095 } else if (board->irq < 0 && sx_irqmask) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 /* auto-allocate irq */
2097 int irqnr;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002098 int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
2099 SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
2100 for (irqnr = 15; irqnr > 0; irqnr--)
2101 if (irqmask & (1 << irqnr))
2102 if (!request_irq(irqnr, sx_interrupt,
2103 IRQF_SHARED | IRQF_DISABLED,
2104 "sx", board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 break;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002106 if (!irqnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
2108 board->irq = irqnr;
2109 } else
2110 board->irq = 0;
2111
2112 if (board->irq) {
2113 /* Found a valid interrupt, start up interrupts! */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002114 sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
2115 board->irq);
2116 sx_start_interrupts(board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 board->poll = sx_slowpoll;
2118 board->flags |= SX_IRQ_ALLOCATED;
2119 } else {
2120 /* no irq: setup board for polled operation */
2121 board->poll = sx_poll;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002122 sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
2123 board->poll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 }
2125
Jiri Slaby15b611f2006-12-08 02:39:04 -08002126 /* The timer should be initialized anyway: That way we can
2127 safely del_timer it when the module is unloaded. */
Jiri Slabyc9594642006-12-08 02:39:05 -08002128 setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
Jiri Slabyc9594642006-12-08 02:39:05 -08002130 if (board->poll)
2131 mod_timer(&board->timer, jiffies + board->poll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 } else {
2133 board->irq = 0;
2134 }
2135
2136 board->nports = chans;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002137 sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138
2139 func_exit();
2140 return chans;
2141}
2142
Jiri Slabycda52652006-12-08 02:39:00 -08002143static void __devinit printheader(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144{
2145 static int header_printed;
2146
2147 if (!header_printed) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002148 printk(KERN_INFO "Specialix SX driver "
2149 "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
2150 printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 header_printed = 1;
2152 }
2153}
2154
Jiri Slaby15b611f2006-12-08 02:39:04 -08002155static int __devinit probe_sx(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
2157 struct vpd_prom vpdp;
2158 char *p;
2159 int i;
2160
2161 func_enter();
2162
Jiri Slaby15b611f2006-12-08 02:39:04 -08002163 if (!IS_CF_BOARD(board)) {
2164 sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
2165 board->base + SX_VPD_ROM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
2167 if (sx_debug & SX_DEBUG_PROBE)
2168 my_hd_io(board->base + SX_VPD_ROM, 0x40);
2169
Jiri Slaby15b611f2006-12-08 02:39:04 -08002170 p = (char *)&vpdp;
2171 for (i = 0; i < sizeof(struct vpd_prom); i++)
2172 *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173
2174 if (sx_debug & SX_DEBUG_PROBE)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002175 my_hd(&vpdp, 0x20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176
Jiri Slaby15b611f2006-12-08 02:39:04 -08002177 sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178
Jiri Slaby15b611f2006-12-08 02:39:04 -08002179 if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
2180 sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
2181 "'%s'\n", vpdp.identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 return 0;
2183 }
2184 }
2185
Jiri Slaby15b611f2006-12-08 02:39:04 -08002186 printheader();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187
Jiri Slaby15b611f2006-12-08 02:39:04 -08002188 if (!IS_CF_BOARD(board)) {
2189 printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
2190 board->hw_base);
2191 printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
2192 "uniq ID:%08x, ",
2193 vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
2194 printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
Jiri Slaby15b611f2006-12-08 02:39:04 -08002196 if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
2197 SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
2198 SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
2199 /* This might be a bit harsh. This was the primary
2200 reason the SX/ISA card didn't work at first... */
2201 printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
2202 "card. Sorry: giving up.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 return (0);
2204 }
2205
Jiri Slaby15b611f2006-12-08 02:39:04 -08002206 if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
2207 SX_ISA_UNIQUEID1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 if (((unsigned long)board->hw_base) & 0x8000) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002209 printk(KERN_WARNING "sx: Warning: There may be "
2210 "hardware problems with the card at "
2211 "%lx.\n", board->hw_base);
2212 printk(KERN_WARNING "sx: Read sx.txt for more "
2213 "info.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 }
2215 }
2216 }
2217
2218 board->nports = -1;
2219
2220 /* This resets the processor, and keeps it off the bus. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002221 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 return 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002223 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 func_exit();
2226 return 1;
2227}
2228
Jiri Slaby927a6f92006-12-08 02:39:02 -08002229#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
2231/* Specialix probes for this card at 32k increments from 640k to 16M.
2232 I consider machines with less than 16M unlikely nowadays, so I'm
2233 not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA
2234 card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves
2235 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
2236
Jiri Slaby15b611f2006-12-08 02:39:04 -08002237static int __devinit probe_si(struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238{
2239 int i;
2240
2241 func_enter();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002242 sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
2243 "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
2245 if (sx_debug & SX_DEBUG_PROBE)
2246 my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
2247
2248 if (!IS_EISA_BOARD(board)) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002249 if (IS_SI1_BOARD(board)) {
2250 for (i = 0; i < 8; i++) {
2251 write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
2252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002254 for (i = 0; i < 8; i++) {
2255 if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
2256 != i) {
2257 func_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 return 0;
2259 }
2260 }
2261 }
2262
2263 /* Now we're pretty much convinced that there is an SI board here,
2264 but to prevent trouble, we'd better double check that we don't
2265 have an SI1 board when we're probing for an SI2 board.... */
2266
Jiri Slaby15b611f2006-12-08 02:39:04 -08002267 write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
2268 if (IS_SI1_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 /* This should be an SI1 board, which has this
2270 location writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002271 if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
2272 func_exit();
2273 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 } else {
2276 /* This should be an SI2 board, which has the bottom
2277 3 bits non-writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002278 if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
2279 func_exit();
2280 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 }
2283
2284 /* Now we're pretty much convinced that there is an SI board here,
2285 but to prevent trouble, we'd better double check that we don't
2286 have an SI1 board when we're probing for an SI2 board.... */
2287
Jiri Slaby15b611f2006-12-08 02:39:04 -08002288 write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
2289 if (IS_SI1_BOARD(board)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 /* This should be an SI1 board, which has this
2291 location writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002292 if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 func_exit();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002294 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 } else {
2297 /* This should be an SI2 board, which has the bottom
2298 3 bits non-writable... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002299 if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
2300 func_exit();
2301 return 0;
Marc Zyngier04a3d312006-02-26 12:02:56 +01002302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 }
2304
Jiri Slaby15b611f2006-12-08 02:39:04 -08002305 printheader();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
Jiri Slaby15b611f2006-12-08 02:39:04 -08002307 printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 /* Compared to the SX boards, it is a complete guess as to what
Jiri Slaby15b611f2006-12-08 02:39:04 -08002309 this card is up to... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
2311 board->nports = -1;
2312
2313 /* This resets the processor, and keeps it off the bus. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002314 if (!sx_reset(board))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 return 0;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002316 sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 func_exit();
2319 return 1;
2320}
Jiri Slaby927a6f92006-12-08 02:39:02 -08002321#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002323static const struct tty_operations sx_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 .break_ctl = sx_break,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002325 .open = sx_open,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 .close = gs_close,
2327 .write = gs_write,
2328 .put_char = gs_put_char,
2329 .flush_chars = gs_flush_chars,
2330 .write_room = gs_write_room,
2331 .chars_in_buffer = gs_chars_in_buffer,
2332 .flush_buffer = gs_flush_buffer,
2333 .ioctl = sx_ioctl,
2334 .throttle = sx_throttle,
2335 .unthrottle = sx_unthrottle,
2336 .set_termios = gs_set_termios,
2337 .stop = gs_stop,
2338 .start = gs_start,
2339 .hangup = gs_hangup,
2340 .tiocmget = sx_tiocmget,
2341 .tiocmset = sx_tiocmset,
2342};
2343
2344static int sx_init_drivers(void)
2345{
2346 int error;
2347
2348 func_enter();
2349
2350 sx_driver = alloc_tty_driver(sx_nports);
2351 if (!sx_driver)
2352 return 1;
2353 sx_driver->owner = THIS_MODULE;
2354 sx_driver->driver_name = "specialix_sx";
2355 sx_driver->name = "ttyX";
2356 sx_driver->major = SX_NORMAL_MAJOR;
2357 sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
2358 sx_driver->subtype = SERIAL_TYPE_NORMAL;
2359 sx_driver->init_termios = tty_std_termios;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002360 sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Alan Cox606d0992006-12-08 02:38:45 -08002361 sx_driver->init_termios.c_ispeed = 9600;
2362 sx_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 sx_driver->flags = TTY_DRIVER_REAL_RAW;
2364 tty_set_operations(sx_driver, &sx_ops);
2365
2366 if ((error = tty_register_driver(sx_driver))) {
2367 put_tty_driver(sx_driver);
2368 printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
Jiri Slaby15b611f2006-12-08 02:39:04 -08002369 error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 return 1;
2371 }
2372 func_exit();
2373 return 0;
2374}
2375
Jiri Slaby15b611f2006-12-08 02:39:04 -08002376static int sx_init_portstructs(int nboards, int nports)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377{
2378 struct sx_board *board;
2379 struct sx_port *port;
2380 int i, j;
2381 int addr, chans;
2382 int portno;
2383
2384 func_enter();
2385
2386 /* Many drivers statically allocate the maximum number of ports
Jiri Slaby15b611f2006-12-08 02:39:04 -08002387 There is no reason not to allocate them dynamically.
2388 Is there? -- REW */
Jiri Slaby4a7cb692006-12-08 02:38:59 -08002389 sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 if (!sx_ports)
2391 return -ENOMEM;
2392
2393 port = sx_ports;
2394 for (i = 0; i < nboards; i++) {
2395 board = &boards[i];
2396 board->ports = port;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002397 for (j = 0; j < boards[i].nports; j++) {
2398 sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 port->gs.magic = SX_MAGIC;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002400 port->gs.close_delay = HZ / 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 port->gs.closing_wait = 30 * HZ;
2402 port->board = board;
2403 port->gs.rd = &sx_real_driver;
2404#ifdef NEW_WRITE_LOCKING
Ingo Molnar81861d72006-03-23 03:00:44 -08002405 port->gs.port_write_mutex = MUTEX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406#endif
Ingo Molnar34af9462006-06-27 02:53:55 -07002407 spin_lock_init(&port->gs.driver_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 /*
2409 * Initializing wait queue
2410 */
2411 init_waitqueue_head(&port->gs.open_wait);
Jiri Slaby15b611f2006-12-08 02:39:04 -08002412 init_waitqueue_head(&port->gs.close_wait);
2413
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 port++;
2415 }
2416 }
2417
2418 port = sx_ports;
2419 portno = 0;
2420 for (i = 0; i < nboards; i++) {
2421 board = &boards[i];
2422 board->port_base = portno;
2423 /* Possibly the configuration was rejected. */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002424 sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
2425 board->nports);
2426 if (board->nports <= 0)
2427 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 /* XXX byteorder ?? */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002429 for (addr = 0x80; addr != 0;
2430 addr = read_sx_word(board, addr) & 0x7fff) {
2431 chans = sx_read_module_byte(board, addr, mc_type);
2432 sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
2433 "channels\n", addr, chans);
2434 sx_dprintk(SX_DEBUG_PROBE, "Port at");
2435 for (j = 0; j < chans; j++) {
2436 /* The "sx-way" is the way it SHOULD be done.
2437 That way in the future, the firmware may for
2438 example pack the structures a bit more
2439 efficient. Neil tells me it isn't going to
2440 happen anytime soon though. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 if (IS_SX_BOARD(board))
Jiri Slaby15b611f2006-12-08 02:39:04 -08002442 port->ch_base = sx_read_module_word(
2443 board, addr + j * 2,
2444 mc_chan_pointer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 else
Jiri Slaby15b611f2006-12-08 02:39:04 -08002446 port->ch_base = addr + 0x100 + 0x300 *j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
Jiri Slaby15b611f2006-12-08 02:39:04 -08002448 sx_dprintk(SX_DEBUG_PROBE, " %x",
2449 port->ch_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 port->line = portno++;
2451 port++;
2452 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002453 sx_dprintk(SX_DEBUG_PROBE, "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 }
2455 /* This has to be done earlier. */
2456 /* board->flags |= SX_BOARD_INITIALIZED; */
2457 }
2458
2459 func_exit();
2460 return 0;
2461}
2462
Jiri Slaby18f813e2006-12-08 02:39:01 -08002463static unsigned int sx_find_free_board(void)
2464{
2465 unsigned int i;
2466
Jiri Slaby15b611f2006-12-08 02:39:04 -08002467 for (i = 0; i < SX_NBOARDS; i++)
Jiri Slaby18f813e2006-12-08 02:39:01 -08002468 if (!(boards[i].flags & SX_BOARD_PRESENT))
2469 break;
2470
2471 return i;
2472}
2473
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474static void __exit sx_release_drivers(void)
2475{
2476 func_enter();
2477 tty_unregister_driver(sx_driver);
2478 put_tty_driver(sx_driver);
2479 func_exit();
2480}
2481
Jiri Slaby39103492006-12-08 02:39:07 -08002482static void __devexit sx_remove_card(struct sx_board *board,
2483 struct pci_dev *pdev)
Jiri Slaby18f813e2006-12-08 02:39:01 -08002484{
2485 if (board->flags & SX_BOARD_INITIALIZED) {
2486 /* The board should stop messing with us. (actually I mean the
2487 interrupt) */
2488 sx_reset(board);
2489 if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
2490 free_irq(board->irq, board);
2491
2492 /* It is safe/allowed to del_timer a non-active timer */
2493 del_timer(&board->timer);
Jiri Slaby30f42182006-12-08 02:39:08 -08002494 if (pdev) {
Jiri Slaby3468a332006-12-13 00:34:20 -08002495#ifdef CONFIG_PCI
Jiri Slaby39103492006-12-08 02:39:07 -08002496 pci_iounmap(pdev, board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002497 pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
Jiri Slaby3468a332006-12-13 00:34:20 -08002498#endif
Jiri Slaby30f42182006-12-08 02:39:08 -08002499 } else {
Jiri Slaby39103492006-12-08 02:39:07 -08002500 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002501 release_region(board->hw_base, board->hw_len);
2502 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002503
Jiri Slaby15b611f2006-12-08 02:39:04 -08002504 board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002505 }
2506}
2507
2508#ifdef CONFIG_EISA
2509
2510static int __devinit sx_eisa_probe(struct device *dev)
2511{
2512 struct eisa_device *edev = to_eisa_device(dev);
2513 struct sx_board *board;
2514 unsigned long eisa_slot = edev->base_addr;
2515 unsigned int i;
2516 int retval = -EIO;
2517
Jiri Slaby42f63842006-12-08 02:39:03 -08002518 mutex_lock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002519 i = sx_find_free_board();
Jiri Slaby42f63842006-12-08 02:39:03 -08002520 if (i == SX_NBOARDS) {
2521 mutex_unlock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002522 goto err;
Jiri Slaby42f63842006-12-08 02:39:03 -08002523 }
2524 board = &boards[i];
2525 board->flags |= SX_BOARD_PRESENT;
2526 mutex_unlock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002527
2528 dev_info(dev, "XIO : Signature found in EISA slot %lu, "
Jiri Slaby15b611f2006-12-08 02:39:04 -08002529 "Product %d Rev %d (REPORT THIS TO LKLM)\n",
2530 eisa_slot >> 12,
2531 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
2532 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
Jiri Slaby18f813e2006-12-08 02:39:01 -08002533
Jiri Slaby18f813e2006-12-08 02:39:01 -08002534 board->eisa_base = eisa_slot;
2535 board->flags &= ~SX_BOARD_TYPE;
2536 board->flags |= SI_EISA_BOARD;
2537
2538 board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
Jiri Slaby15b611f2006-12-08 02:39:04 -08002539 inb(eisa_slot + 0xc00)) << 16;
Jiri Slaby30f42182006-12-08 02:39:08 -08002540 board->hw_len = SI2_EISA_WINDOW_LEN;
2541 if (!request_region(board->hw_base, board->hw_len, "sx")) {
2542 dev_err(dev, "can't request region\n");
2543 goto err_flag;
2544 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002545 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002546 board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
Jiri Slaby30f42182006-12-08 02:39:08 -08002547 if (!board->base) {
2548 dev_err(dev, "can't remap memory\n");
2549 goto err_reg;
2550 }
Jiri Slaby18f813e2006-12-08 02:39:01 -08002551
2552 sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
2553 sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
2554 board->irq = inb(eisa_slot + 0xc02) >> 4;
2555 sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
2556
2557 if (!probe_si(board))
2558 goto err_unmap;
2559
2560 dev_set_drvdata(dev, board);
2561
2562 return 0;
2563err_unmap:
2564 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002565err_reg:
2566 release_region(board->hw_base, board->hw_len);
2567err_flag:
Jiri Slaby42f63842006-12-08 02:39:03 -08002568 board->flags &= ~SX_BOARD_PRESENT;
Jiri Slaby18f813e2006-12-08 02:39:01 -08002569err:
2570 return retval;
2571}
2572
2573static int __devexit sx_eisa_remove(struct device *dev)
2574{
2575 struct sx_board *board = dev_get_drvdata(dev);
2576
Jiri Slaby39103492006-12-08 02:39:07 -08002577 sx_remove_card(board, NULL);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002578
2579 return 0;
2580}
2581
2582static struct eisa_device_id sx_eisa_tbl[] = {
2583 { "SLX" },
2584 { "" }
2585};
Jiri Slaby15b611f2006-12-08 02:39:04 -08002586
Jiri Slaby18f813e2006-12-08 02:39:01 -08002587MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
2588
2589static struct eisa_driver sx_eisadriver = {
2590 .id_table = sx_eisa_tbl,
2591 .driver = {
2592 .name = "sx",
2593 .probe = sx_eisa_probe,
2594 .remove = __devexit_p(sx_eisa_remove),
2595 }
2596};
2597
2598#endif
2599
Jiri Slaby3468a332006-12-13 00:34:20 -08002600#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 /********************************************************
2602 * Setting bit 17 in the CNTRL register of the PLX 9050 *
2603 * chip forces a retry on writes while a read is pending.*
2604 * This is to prevent the card locking up on Intel Xeon *
2605 * multiprocessor systems with the NX chipset. -- NV *
2606 ********************************************************/
2607
2608/* Newer cards are produced with this bit set from the configuration
2609 EEprom. As the bit is read/write for the CPU, we can fix it here,
2610 if we detect that it isn't set correctly. -- REW */
2611
Jiri Slabycda52652006-12-08 02:39:00 -08002612static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613{
2614 unsigned int hwbase;
2615 void __iomem *rebase;
2616 unsigned int t;
2617
Jiri Slaby15b611f2006-12-08 02:39:04 -08002618#define CNTRL_REG_OFFSET 0x50
2619#define CNTRL_REG_GOODVALUE 0x18260000
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
2621 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
2622 hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
Alan Cox24cb2332008-04-30 00:54:19 -07002623 rebase = ioremap_nocache(hwbase, 0x80);
Jiri Slaby15b611f2006-12-08 02:39:04 -08002624 t = readl(rebase + CNTRL_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 if (t != CNTRL_REG_GOODVALUE) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002626 printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
2627 "%08x\n", t, CNTRL_REG_GOODVALUE);
2628 writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 }
2630 iounmap(rebase);
2631}
Jiri Slaby3468a332006-12-13 00:34:20 -08002632#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
Jiri Slaby5572e102006-12-08 02:38:58 -08002634static int __devinit sx_pci_probe(struct pci_dev *pdev,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002635 const struct pci_device_id *ent)
Jiri Slaby5572e102006-12-08 02:38:58 -08002636{
Jiri Slaby3468a332006-12-13 00:34:20 -08002637#ifdef CONFIG_PCI
Jiri Slaby5572e102006-12-08 02:38:58 -08002638 struct sx_board *board;
Jiri Slaby39103492006-12-08 02:39:07 -08002639 unsigned int i, reg;
Jiri Slaby5572e102006-12-08 02:38:58 -08002640 int retval = -EIO;
2641
Jiri Slaby42f63842006-12-08 02:39:03 -08002642 mutex_lock(&sx_boards_lock);
Jiri Slaby18f813e2006-12-08 02:39:01 -08002643 i = sx_find_free_board();
Jiri Slaby42f63842006-12-08 02:39:03 -08002644 if (i == SX_NBOARDS) {
2645 mutex_unlock(&sx_boards_lock);
Jiri Slaby5572e102006-12-08 02:38:58 -08002646 goto err;
Jiri Slaby42f63842006-12-08 02:39:03 -08002647 }
2648 board = &boards[i];
2649 board->flags |= SX_BOARD_PRESENT;
2650 mutex_unlock(&sx_boards_lock);
Jiri Slaby5572e102006-12-08 02:38:58 -08002651
2652 retval = pci_enable_device(pdev);
2653 if (retval)
Jiri Slaby42f63842006-12-08 02:39:03 -08002654 goto err_flag;
Jiri Slaby5572e102006-12-08 02:38:58 -08002655
2656 board->flags &= ~SX_BOARD_TYPE;
2657 board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
Jiri Slaby15b611f2006-12-08 02:39:04 -08002658 SX_CFPCI_BOARD;
Jiri Slaby5572e102006-12-08 02:38:58 -08002659
2660 /* CF boards use base address 3.... */
Jiri Slaby39103492006-12-08 02:39:07 -08002661 reg = IS_CF_BOARD(board) ? 3 : 2;
Jiri Slaby30f42182006-12-08 02:39:08 -08002662 retval = pci_request_region(pdev, reg, "sx");
2663 if (retval) {
2664 dev_err(&pdev->dev, "can't request region\n");
2665 goto err_flag;
2666 }
Jiri Slaby39103492006-12-08 02:39:07 -08002667 board->hw_base = pci_resource_start(pdev, reg);
Jiri Slaby5572e102006-12-08 02:38:58 -08002668 board->base2 =
Jiri Slaby39103492006-12-08 02:39:07 -08002669 board->base = pci_iomap(pdev, reg, WINDOW_LEN(board));
Jiri Slaby5572e102006-12-08 02:38:58 -08002670 if (!board->base) {
2671 dev_err(&pdev->dev, "ioremap failed\n");
Jiri Slaby30f42182006-12-08 02:39:08 -08002672 goto err_reg;
Jiri Slaby5572e102006-12-08 02:38:58 -08002673 }
2674
2675 /* Most of the stuff on the CF board is offset by 0x18000 .... */
Jiri Slaby15b611f2006-12-08 02:39:04 -08002676 if (IS_CF_BOARD(board))
Jiri Slaby5572e102006-12-08 02:38:58 -08002677 board->base += 0x18000;
2678
2679 board->irq = pdev->irq;
2680
2681 dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
Jiri Slaby15b611f2006-12-08 02:39:04 -08002682 board->irq, board->flags);
Jiri Slaby5572e102006-12-08 02:38:58 -08002683
2684 if (!probe_sx(board)) {
2685 retval = -EIO;
2686 goto err_unmap;
2687 }
2688
2689 fix_sx_pci(pdev, board);
2690
2691 pci_set_drvdata(pdev, board);
2692
2693 return 0;
2694err_unmap:
Jiri Slaby39103492006-12-08 02:39:07 -08002695 pci_iounmap(pdev, board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002696err_reg:
2697 pci_release_region(pdev, reg);
Jiri Slaby42f63842006-12-08 02:39:03 -08002698err_flag:
2699 board->flags &= ~SX_BOARD_PRESENT;
Jiri Slaby5572e102006-12-08 02:38:58 -08002700err:
2701 return retval;
Jiri Slaby3468a332006-12-13 00:34:20 -08002702#else
2703 return -ENODEV;
2704#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002705}
2706
2707static void __devexit sx_pci_remove(struct pci_dev *pdev)
2708{
2709 struct sx_board *board = pci_get_drvdata(pdev);
2710
Jiri Slaby39103492006-12-08 02:39:07 -08002711 sx_remove_card(board, pdev);
Jiri Slaby5572e102006-12-08 02:38:58 -08002712}
2713
2714/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
2715 its because the standard requires it. So check for SUBVENDOR_ID. */
2716static struct pci_device_id sx_pci_tbl[] = {
2717 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
Jiri Slabyc14d4442007-07-10 17:22:25 -07002718 .subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
Jiri Slaby5572e102006-12-08 02:38:58 -08002719 { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
Jiri Slabyc14d4442007-07-10 17:22:25 -07002720 .subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
Jiri Slaby5572e102006-12-08 02:38:58 -08002721 { 0 }
2722};
Jiri Slaby15b611f2006-12-08 02:39:04 -08002723
Jiri Slaby5572e102006-12-08 02:38:58 -08002724MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
2725
2726static struct pci_driver sx_pcidriver = {
2727 .name = "sx",
2728 .id_table = sx_pci_tbl,
2729 .probe = sx_pci_probe,
2730 .remove = __devexit_p(sx_pci_remove)
2731};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
Jiri Slaby15b611f2006-12-08 02:39:04 -08002733static int __init sx_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734{
Jiri Slaby18f813e2006-12-08 02:39:01 -08002735#ifdef CONFIG_EISA
2736 int retval1;
2737#endif
Jiri Slaby927a6f92006-12-08 02:39:02 -08002738#ifdef CONFIG_ISA
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 struct sx_board *board;
Jiri Slaby927a6f92006-12-08 02:39:02 -08002740 unsigned int i;
2741#endif
2742 unsigned int found = 0;
2743 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 func_enter();
Jiri Slaby15b611f2006-12-08 02:39:04 -08002746 sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
2747 sx_debug);
2748 if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
2749 printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
2750 "value. Assuming -1.\n(%p)\n", &sx_debug);
2751 sx_debug = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 }
2753
2754 if (misc_register(&sx_fw_device) < 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002755 printk(KERN_ERR "SX: Unable to register firmware loader "
2756 "driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 return -EIO;
2758 }
Jiri Slaby927a6f92006-12-08 02:39:02 -08002759#ifdef CONFIG_ISA
Jiri Slaby15b611f2006-12-08 02:39:04 -08002760 for (i = 0; i < NR_SX_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 board = &boards[found];
2762 board->hw_base = sx_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002763 board->hw_len = SX_WINDOW_LEN;
2764 if (!request_region(board->hw_base, board->hw_len, "sx"))
2765 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002767 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002768 if (!board->base)
2769 goto err_sx_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002771 board->flags |= SX_ISA_BOARD;
2772 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773
Jiri Slaby15b611f2006-12-08 02:39:04 -08002774 if (probe_sx(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002775 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 found++;
2777 } else {
2778 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002779err_sx_reg:
2780 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 }
2782 }
2783
Jiri Slaby15b611f2006-12-08 02:39:04 -08002784 for (i = 0; i < NR_SI_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 board = &boards[found];
2786 board->hw_base = si_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002787 board->hw_len = SI2_ISA_WINDOW_LEN;
2788 if (!request_region(board->hw_base, board->hw_len, "sx"))
2789 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002791 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002792 if (!board->base)
2793 goto err_si_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002795 board->flags |= SI_ISA_BOARD;
2796 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
Jiri Slaby15b611f2006-12-08 02:39:04 -08002798 if (probe_si(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002799 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 found++;
2801 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002802 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002803err_si_reg:
2804 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 }
2806 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002807 for (i = 0; i < NR_SI1_ADDRS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 board = &boards[found];
2809 board->hw_base = si1_probe_addrs[i];
Jiri Slaby30f42182006-12-08 02:39:08 -08002810 board->hw_len = SI1_ISA_WINDOW_LEN;
2811 if (!request_region(board->hw_base, board->hw_len, "sx"))
2812 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 board->base2 =
Alan Cox24cb2332008-04-30 00:54:19 -07002814 board->base = ioremap_nocache(board->hw_base, board->hw_len);
Jiri Slaby30f42182006-12-08 02:39:08 -08002815 if (!board->base)
2816 goto err_si1_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 board->flags &= ~SX_BOARD_TYPE;
Jiri Slaby15b611f2006-12-08 02:39:04 -08002818 board->flags |= SI1_ISA_BOARD;
2819 board->irq = sx_irqmask ? -1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
Jiri Slaby15b611f2006-12-08 02:39:04 -08002821 if (probe_si(board)) {
Jiri Slaby42f63842006-12-08 02:39:03 -08002822 board->flags |= SX_BOARD_PRESENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 found++;
2824 } else {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002825 iounmap(board->base);
Jiri Slaby30f42182006-12-08 02:39:08 -08002826err_si1_reg:
2827 release_region(board->hw_base, board->hw_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 }
2829 }
Jiri Slaby927a6f92006-12-08 02:39:02 -08002830#endif
Jiri Slaby18f813e2006-12-08 02:39:01 -08002831#ifdef CONFIG_EISA
2832 retval1 = eisa_driver_register(&sx_eisadriver);
2833#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002834 retval = pci_register_driver(&sx_pcidriver);
2835
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 if (found) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002837 printk(KERN_INFO "sx: total of %d boards detected.\n", found);
Jiri Slaby5572e102006-12-08 02:38:58 -08002838 retval = 0;
2839 } else if (retval) {
Jiri Slaby18f813e2006-12-08 02:39:01 -08002840#ifdef CONFIG_EISA
Jiri Slaby7eb99762006-12-08 02:39:06 -08002841 retval = retval1;
Jiri Slaby18f813e2006-12-08 02:39:01 -08002842 if (retval1)
2843#endif
Jiri Slaby15b611f2006-12-08 02:39:04 -08002844 misc_deregister(&sx_fw_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 }
2846
2847 func_exit();
Jiri Slaby5572e102006-12-08 02:38:58 -08002848 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849}
2850
Jiri Slaby15b611f2006-12-08 02:39:04 -08002851static void __exit sx_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852{
Jiri Slaby15b611f2006-12-08 02:39:04 -08002853 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854
2855 func_enter();
Jiri Slaby18f813e2006-12-08 02:39:01 -08002856#ifdef CONFIG_EISA
2857 eisa_driver_unregister(&sx_eisadriver);
2858#endif
Jiri Slaby5572e102006-12-08 02:38:58 -08002859 pci_unregister_driver(&sx_pcidriver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860
Jiri Slaby55e70712006-12-08 02:39:03 -08002861 for (i = 0; i < SX_NBOARDS; i++)
Jiri Slaby39103492006-12-08 02:39:07 -08002862 sx_remove_card(&boards[i], NULL);
Jiri Slaby55e70712006-12-08 02:39:03 -08002863
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 if (misc_deregister(&sx_fw_device) < 0) {
Jiri Slaby15b611f2006-12-08 02:39:04 -08002865 printk(KERN_INFO "sx: couldn't deregister firmware loader "
2866 "device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 }
Jiri Slaby15b611f2006-12-08 02:39:04 -08002868 sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
2869 sx_initialized);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 if (sx_initialized)
Jiri Slaby15b611f2006-12-08 02:39:04 -08002871 sx_release_drivers();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872
Jiri Slaby15b611f2006-12-08 02:39:04 -08002873 kfree(sx_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 func_exit();
2875}
2876
2877module_init(sx_init);
2878module_exit(sx_exit);