]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/char/specialix.c
[PATCH] tty: switch to ktermios and new framework
[net-next-2.6.git] / drivers / char / specialix.c
CommitLineData
1da177e4
LT
1/*
2 * specialix.c -- specialix IO8+ multiport serial driver.
3 *
4 * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
5 * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com)
6 *
7 * Specialix pays for the development and support of this driver.
8 * Please DO contact io8-linux@specialix.co.uk if you require
9 * support. But please read the documentation (specialix.txt)
10 * first.
11 *
12 * This driver was developped in the BitWizard linux device
13 * driver service. If you require a linux device driver for your
14 * product, please contact devices@BitWizard.nl for a quote.
15 *
16 * This code is firmly based on the riscom/8 serial driver,
17 * written by Dmitry Gorodchanin. The specialix IO8+ card
18 * programming information was obtained from the CL-CD1865 Data
19 * Book, and Specialix document number 6200059: IO8+ Hardware
20 * Functional Specification.
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License as
24 * published by the Free Software Foundation; either version 2 of
25 * the License, or (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be
28 * useful, but WITHOUT ANY WARRANTY; without even the implied
29 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
30 * PURPOSE. See the GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public
33 * License along with this program; if not, write to the Free
34 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
35 * USA.
36 *
37 * Revision history:
38 *
39 * Revision 1.0: April 1st 1997.
40 * Initial release for alpha testing.
d61780c0
JG
41 * Revision 1.1: April 14th 1997.
42 * Incorporated Richard Hudsons suggestions,
1da177e4
LT
43 * removed some debugging printk's.
44 * Revision 1.2: April 15th 1997.
45 * Ported to 2.1.x kernels.
d61780c0
JG
46 * Revision 1.3: April 17th 1997
47 * Backported to 2.0. (Compatibility macros).
1da177e4 48 * Revision 1.4: April 18th 1997
d61780c0
JG
49 * Fixed DTR/RTS bug that caused the card to indicate
50 * "don't send data" to a modem after the password prompt.
1da177e4
LT
51 * Fixed bug for premature (fake) interrupts.
52 * Revision 1.5: April 19th 1997
d61780c0 53 * fixed a minor typo in the header file, cleanup a little.
1da177e4
LT
54 * performance warnings are now MAXed at once per minute.
55 * Revision 1.6: May 23 1997
56 * Changed the specialix=... format to include interrupt.
57 * Revision 1.7: May 27 1997
58 * Made many more debug printk's a compile time option.
59 * Revision 1.8: Jul 1 1997
60 * port to linux-2.1.43 kernel.
61 * Revision 1.9: Oct 9 1998
62 * Added stuff for the IO8+/PCI version.
d61780c0
JG
63 * Revision 1.10: Oct 22 1999 / Jan 21 2000.
64 * Added stuff for setserial.
1da177e4 65 * Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
d61780c0 66 *
1da177e4
LT
67 */
68
69#define VERSION "1.11"
70
71
72/*
73 * There is a bunch of documentation about the card, jumpers, config
74 * settings, restrictions, cables, device names and numbers in
75 * Documentation/specialix.txt
76 */
77
1da177e4
LT
78#include <linux/module.h>
79
80#include <asm/io.h>
81#include <linux/kernel.h>
82#include <linux/sched.h>
83#include <linux/ioport.h>
84#include <linux/interrupt.h>
85#include <linux/errno.h>
86#include <linux/tty.h>
33f0f88f 87#include <linux/tty_flip.h>
1da177e4
LT
88#include <linux/mm.h>
89#include <linux/serial.h>
90#include <linux/fcntl.h>
91#include <linux/major.h>
92#include <linux/delay.h>
1da177e4
LT
93#include <linux/pci.h>
94#include <linux/init.h>
95#include <asm/uaccess.h>
96
97#include "specialix_io8.h"
98#include "cd1865.h"
99
100
101/*
102 This driver can spew a whole lot of debugging output at you. If you
103 need maximum performance, you should disable the DEBUG define. To
104 aid in debugging in the field, I'm leaving the compile-time debug
105 features enabled, and disable them "runtime". That allows me to
106 instruct people with problems to enable debugging without requiring
107 them to recompile...
108*/
109#define DEBUG
110
111static int sx_debug;
112static int sx_rxfifo = SPECIALIX_RXFIFO;
113
114#ifdef DEBUG
115#define dprintk(f, str...) if (sx_debug & f) printk (str)
116#else
117#define dprintk(f, str...) /* nothing */
118#endif
119
120#define SX_DEBUG_FLOW 0x0001
121#define SX_DEBUG_DATA 0x0002
122#define SX_DEBUG_PROBE 0x0004
123#define SX_DEBUG_CHAN 0x0008
124#define SX_DEBUG_INIT 0x0010
125#define SX_DEBUG_RX 0x0020
126#define SX_DEBUG_TX 0x0040
127#define SX_DEBUG_IRQ 0x0080
128#define SX_DEBUG_OPEN 0x0100
129#define SX_DEBUG_TERMIOS 0x0200
130#define SX_DEBUG_SIGNALS 0x0400
131#define SX_DEBUG_FIFO 0x0800
132
133
134#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__FUNCTION__)
135#define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __FUNCTION__)
136
137#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
138
139
140/* Configurable options: */
141
142/* Am I paranoid or not ? ;-) */
143#define SPECIALIX_PARANOIA_CHECK
144
145/* Do I trust the IRQ from the card? (enabeling it doesn't seem to help)
146 When the IRQ routine leaves the chip in a state that is keeps on
147 requiring attention, the timer doesn't help either. */
148#undef SPECIALIX_TIMER
149
150#ifdef SPECIALIX_TIMER
151static int sx_poll = HZ;
152#endif
153
154
155
d61780c0 156/*
1da177e4
LT
157 * The following defines are mostly for testing purposes. But if you need
158 * some nice reporting in your syslog, you can define them also.
159 */
160#undef SX_REPORT_FIFO
161#undef SX_REPORT_OVERRUN
162
163
164
165#ifdef CONFIG_SPECIALIX_RTSCTS
166#define SX_CRTSCTS(bla) 1
167#else
168#define SX_CRTSCTS(tty) C_CRTSCTS(tty)
169#endif
170
171
172/* Used to be outb (0xff, 0x80); */
173#define short_pause() udelay (1)
174
175
176#define SPECIALIX_LEGAL_FLAGS \
177 (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \
178 ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \
179 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
180
181#undef RS_EVENT_WRITE_WAKEUP
182#define RS_EVENT_WRITE_WAKEUP 0
183
184static struct tty_driver *specialix_driver;
1da177e4 185
1da177e4
LT
186static struct specialix_board sx_board[SX_NBOARD] = {
187 { 0, SX_IOBASE1, 9, },
188 { 0, SX_IOBASE2, 11, },
189 { 0, SX_IOBASE3, 12, },
190 { 0, SX_IOBASE4, 15, },
191};
192
193static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
194
195
196#ifdef SPECIALIX_TIMER
197static struct timer_list missed_irq_timer;
7d12e780 198static irqreturn_t sx_interrupt(int irq, void * dev_id);
1da177e4
LT
199#endif
200
201
202
203static inline int sx_paranoia_check(struct specialix_port const * port,
204 char *name, const char *routine)
205{
206#ifdef SPECIALIX_PARANOIA_CHECK
207 static const char *badmagic =
208 KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
209 static const char *badinfo =
210 KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
d61780c0 211
1da177e4
LT
212 if (!port) {
213 printk(badinfo, name, routine);
214 return 1;
215 }
216 if (port->magic != SPECIALIX_MAGIC) {
217 printk(badmagic, name, routine);
218 return 1;
219 }
220#endif
221 return 0;
222}
223
224
225/*
d61780c0 226 *
1da177e4 227 * Service functions for specialix IO8+ driver.
d61780c0 228 *
1da177e4
LT
229 */
230
231/* Get board number from pointer */
232static inline int board_No (struct specialix_board * bp)
233{
234 return bp - sx_board;
235}
236
237
238/* Get port number from pointer */
239static inline int port_No (struct specialix_port const * port)
240{
d61780c0 241 return SX_PORT(port - sx_port);
1da177e4
LT
242}
243
244
245/* Get pointer to board from pointer to port */
246static inline struct specialix_board * port_Board(struct specialix_port const * port)
247{
248 return &sx_board[SX_BOARD(port - sx_port)];
249}
250
251
252/* Input Byte from CL CD186x register */
253static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
254{
255 bp->reg = reg | 0x80;
256 outb (reg | 0x80, bp->base + SX_ADDR_REG);
257 return inb (bp->base + SX_DATA_REG);
258}
259
260
261/* Output Byte to CL CD186x register */
262static inline void sx_out(struct specialix_board * bp, unsigned short reg,
263 unsigned char val)
264{
265 bp->reg = reg | 0x80;
266 outb (reg | 0x80, bp->base + SX_ADDR_REG);
267 outb (val, bp->base + SX_DATA_REG);
268}
269
270
271/* Input Byte from CL CD186x register */
272static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
273{
274 bp->reg = reg;
275 outb (reg, bp->base + SX_ADDR_REG);
276 return inb (bp->base + SX_DATA_REG);
277}
278
279
280/* Output Byte to CL CD186x register */
281static inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
282 unsigned char val)
283{
284 bp->reg = reg;
285 outb (reg, bp->base + SX_ADDR_REG);
286 outb (val, bp->base + SX_DATA_REG);
287}
288
289
290/* Wait for Channel Command Register ready */
291static inline void sx_wait_CCR(struct specialix_board * bp)
292{
293 unsigned long delay, flags;
294 unsigned char ccr;
295
296 for (delay = SX_CCR_TIMEOUT; delay; delay--) {
297 spin_lock_irqsave(&bp->lock, flags);
298 ccr = sx_in(bp, CD186x_CCR);
299 spin_unlock_irqrestore(&bp->lock, flags);
300 if (!ccr)
301 return;
302 udelay (1);
303 }
d61780c0 304
1da177e4
LT
305 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
306}
307
308
309/* Wait for Channel Command Register ready */
310static inline void sx_wait_CCR_off(struct specialix_board * bp)
311{
312 unsigned long delay;
313 unsigned char crr;
314 unsigned long flags;
315
316 for (delay = SX_CCR_TIMEOUT; delay; delay--) {
317 spin_lock_irqsave(&bp->lock, flags);
318 crr = sx_in_off(bp, CD186x_CCR);
319 spin_unlock_irqrestore(&bp->lock, flags);
320 if (!crr)
321 return;
322 udelay (1);
323 }
d61780c0 324
1da177e4
LT
325 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
326}
327
328
329/*
330 * specialix IO8+ IO range functions.
331 */
332
d61780c0 333static inline int sx_request_io_range(struct specialix_board * bp)
1da177e4 334{
d61780c0
JG
335 return request_region(bp->base,
336 bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
337 "specialix IO8+") == NULL;
1da177e4
LT
338}
339
340
341static inline void sx_release_io_range(struct specialix_board * bp)
342{
d61780c0 343 release_region(bp->base,
1da177e4
LT
344 bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
345}
346
d61780c0 347
1da177e4 348/* Must be called with enabled interrupts */
d61780c0 349/* Ugly. Very ugly. Don't use this for anything else than initialization
1da177e4
LT
350 code */
351static inline void sx_long_delay(unsigned long delay)
352{
353 unsigned long i;
d61780c0 354
1da177e4
LT
355 for (i = jiffies + delay; time_after(i, jiffies); ) ;
356}
357
358
359
360/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
361static int sx_set_irq ( struct specialix_board *bp)
362{
363 int virq;
364 int i;
365 unsigned long flags;
366
d61780c0 367 if (bp->flags & SX_BOARD_IS_PCI)
1da177e4
LT
368 return 1;
369 switch (bp->irq) {
370 /* In the same order as in the docs... */
371 case 15: virq = 0;break;
372 case 12: virq = 1;break;
373 case 11: virq = 2;break;
374 case 9: virq = 3;break;
375 default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq);
376 return 0;
377 }
378 spin_lock_irqsave(&bp->lock, flags);
379 for (i=0;i<2;i++) {
380 sx_out(bp, CD186x_CAR, i);
381 sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
382 }
383 spin_unlock_irqrestore(&bp->lock, flags);
384 return 1;
385}
386
387
388/* Reset and setup CD186x chip */
389static int sx_init_CD186x(struct specialix_board * bp)
390{
391 unsigned long flags;
392 int scaler;
393 int rv = 1;
394
395 func_enter();
396 sx_wait_CCR_off(bp); /* Wait for CCR ready */
397 spin_lock_irqsave(&bp->lock, flags);
398 sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */
399 spin_unlock_irqrestore(&bp->lock, flags);
400 sx_long_delay(HZ/20); /* Delay 0.05 sec */
401 spin_lock_irqsave(&bp->lock, flags);
402 sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */
403 sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */
404 sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT); /* Prio for modem intr */
405 sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */
406 sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */
407 /* Set RegAckEn */
408 sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
d61780c0 409
1da177e4
LT
410 /* Setting up prescaler. We need 4 ticks per 1 ms */
411 scaler = SX_OSCFREQ/SPECIALIX_TPS;
412
413 sx_out_off(bp, CD186x_PPRH, scaler >> 8);
414 sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
415 spin_unlock_irqrestore(&bp->lock, flags);
416
417 if (!sx_set_irq (bp)) {
418 /* Figure out how to pass this along... */
419 printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq);
420 rv = 0;
421 }
422
423 func_exit();
424 return rv;
425}
426
427
428static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
429{
430 int i;
431 int t;
432 unsigned long flags;
433
434 spin_lock_irqsave(&bp->lock, flags);
435 for (i=0, t=0;i<8;i++) {
436 sx_out_off (bp, CD186x_CAR, i);
d61780c0 437 if (sx_in_off (bp, reg) & bit)
1da177e4
LT
438 t |= 1 << i;
439 }
440 spin_unlock_irqrestore(&bp->lock, flags);
441
442 return t;
443}
444
445
446#ifdef SPECIALIX_TIMER
447void missed_irq (unsigned long data)
448{
449 unsigned char irq;
450 unsigned long flags;
451 struct specialix_board *bp = (struct specialix_board *)data;
452
453 spin_lock_irqsave(&bp->lock, flags);
454 irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) &
455 (SRSR_RREQint |
456 SRSR_TREQint |
457 SRSR_MREQint);
458 spin_unlock_irqrestore(&bp->lock, flags);
459 if (irq) {
460 printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
d61780c0 461 sx_interrupt (((struct specialix_board *)data)->irq,
1da177e4
LT
462 (void*)data, NULL);
463 }
464 missed_irq_timer.expires = jiffies + sx_poll;
465 add_timer (&missed_irq_timer);
466}
467#endif
468
469
470
471/* Main probing routine, also sets irq. */
472static int sx_probe(struct specialix_board *bp)
473{
474 unsigned char val1, val2;
475#if 0
476 int irqs = 0;
477 int retries;
478#endif
479 int rev;
480 int chip;
481
482 func_enter();
483
d61780c0 484 if (sx_request_io_range(bp)) {
1da177e4
LT
485 func_exit();
486 return 1;
487 }
488
489 /* Are the I/O ports here ? */
490 sx_out_off(bp, CD186x_PPRL, 0x5a);
491 short_pause ();
492 val1 = sx_in_off(bp, CD186x_PPRL);
493
494 sx_out_off(bp, CD186x_PPRL, 0xa5);
495 short_pause ();
496 val2 = sx_in_off(bp, CD186x_PPRL);
497
d61780c0 498
1da177e4
LT
499 if ((val1 != 0x5a) || (val2 != 0xa5)) {
500 printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
501 board_No(bp), bp->base);
d61780c0 502 sx_release_io_range(bp);
1da177e4
LT
503 func_exit();
504 return 1;
505 }
506
d61780c0 507 /* Check the DSR lines that Specialix uses as board
1da177e4
LT
508 identification */
509 val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
510 val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
511 dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
512 board_No(bp), val1, val2);
513
514 /* They managed to switch the bit order between the docs and
515 the IO8+ card. The new PCI card now conforms to old docs.
516 They changed the PCI docs to reflect the situation on the
517 old card. */
518 val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
519 if (val1 != val2) {
520 printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
521 board_No(bp), val2, bp->base, val1);
d61780c0 522 sx_release_io_range(bp);
1da177e4
LT
523 func_exit();
524 return 1;
525 }
526
527
528#if 0
529 /* It's time to find IRQ for this board */
530 for (retries = 0; retries < 5 && irqs <= 0; retries++) {
531 irqs = probe_irq_on();
532 sx_init_CD186x(bp); /* Reset CD186x chip */
533 sx_out(bp, CD186x_CAR, 2); /* Select port 2 */
534 sx_wait_CCR(bp);
535 sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
536 sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
d61780c0 537 sx_long_delay(HZ/20);
1da177e4
LT
538 irqs = probe_irq_off(irqs);
539
540 dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
541 dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
542 dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
543 dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR));
544 dprintk (SX_DEBUG_INIT, "\n");
545
546 /* Reset CD186x again */
547 if (!sx_init_CD186x(bp)) {
548 /* Hmmm. This is dead code anyway. */
549 }
550
551 dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
d61780c0
JG
552 val1, val2, val3);
553
1da177e4 554 }
d61780c0 555
1da177e4
LT
556#if 0
557 if (irqs <= 0) {
558 printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
559 board_No(bp), bp->base);
d61780c0 560 sx_release_io_range(bp);
1da177e4
LT
561 func_exit();
562 return 1;
563 }
564#endif
565 printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
566 if (irqs > 0)
567 bp->irq = irqs;
568#endif
569 /* Reset CD186x again */
570 if (!sx_init_CD186x(bp)) {
d61780c0 571 sx_release_io_range(bp);
1da177e4 572 func_exit();
d61780c0 573 return 1;
1da177e4
LT
574 }
575
576 sx_request_io_range(bp);
577 bp->flags |= SX_BOARD_PRESENT;
d61780c0 578
1da177e4
LT
579 /* Chip revcode pkgtype
580 GFRCR SRCR bit 7
581 CD180 rev B 0x81 0
582 CD180 rev C 0x82 0
583 CD1864 rev A 0x82 1
d61780c0 584 CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
1da177e4
LT
585 CD1865 rev B 0x84 1
586 -- Thanks to Gwen Wang, Cirrus Logic.
587 */
588
589 switch (sx_in_off(bp, CD186x_GFRCR)) {
590 case 0x82:chip = 1864;rev='A';break;
591 case 0x83:chip = 1865;rev='A';break;
592 case 0x84:chip = 1865;rev='B';break;
593 case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */
594 default:chip=-1;rev='x';
595 }
596
597 dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
598
599#ifdef SPECIALIX_TIMER
600 init_timer (&missed_irq_timer);
601 missed_irq_timer.function = missed_irq;
602 missed_irq_timer.data = (unsigned long) bp;
603 missed_irq_timer.expires = jiffies + sx_poll;
604 add_timer (&missed_irq_timer);
605#endif
606
607 printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
608 board_No(bp),
609 bp->base, bp->irq,
610 chip, rev);
611
612 func_exit();
613 return 0;
614}
615
d61780c0
JG
616/*
617 *
1da177e4
LT
618 * Interrupt processing routines.
619 * */
620
621static inline void sx_mark_event(struct specialix_port * port, int event)
622{
623 func_enter();
624
625 set_bit(event, &port->event);
626 schedule_work(&port->tqueue);
627
628 func_exit();
629}
630
631
632static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
633 unsigned char const * what)
634{
635 unsigned char channel;
636 struct specialix_port * port = NULL;
637
638 channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
639 dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel);
640 if (channel < CD186x_NCH) {
641 port = &sx_port[board_No(bp) * SX_NPORT + channel];
642 dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%x\n",board_No(bp) * SX_NPORT + channel, port, port->flags & ASYNC_INITIALIZED);
643
644 if (port->flags & ASYNC_INITIALIZED) {
645 dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
646 func_exit();
647 return port;
648 }
649 }
d61780c0 650 printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
1da177e4
LT
651 board_No(bp), what, channel);
652 return NULL;
653}
654
655
656static inline void sx_receive_exc(struct specialix_board * bp)
657{
658 struct specialix_port *port;
659 struct tty_struct *tty;
660 unsigned char status;
33f0f88f 661 unsigned char ch, flag;
1da177e4
LT
662
663 func_enter();
664
665 port = sx_get_port(bp, "Receive");
666 if (!port) {
667 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
668 func_exit();
669 return;
670 }
671 tty = port->tty;
d61780c0 672
1da177e4
LT
673 status = sx_in(bp, CD186x_RCSR);
674
675 dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
676 if (status & RCSR_OE) {
677 port->overrun++;
678 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
679 board_No(bp), port_No(port), port->overrun);
680 }
681 status &= port->mark_mask;
682
683 /* This flip buffer check needs to be below the reading of the
684 status register to reset the chip's IRQ.... */
33f0f88f 685 if (tty_buffer_request_room(tty, 1) == 0) {
1da177e4
LT
686 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
687 board_No(bp), port_No(port));
688 func_exit();
689 return;
690 }
691
692 ch = sx_in(bp, CD186x_RDR);
693 if (!status) {
694 func_exit();
695 return;
696 }
697 if (status & RCSR_TOUT) {
d61780c0 698 printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
1da177e4
LT
699 board_No(bp), port_No(port));
700 func_exit();
701 return;
d61780c0 702
1da177e4
LT
703 } else if (status & RCSR_BREAK) {
704 dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
705 board_No(bp), port_No(port));
33f0f88f 706 flag = TTY_BREAK;
1da177e4
LT
707 if (port->flags & ASYNC_SAK)
708 do_SAK(tty);
d61780c0
JG
709
710 } else if (status & RCSR_PE)
33f0f88f 711 flag = TTY_PARITY;
d61780c0
JG
712
713 else if (status & RCSR_FE)
33f0f88f 714 flag = TTY_FRAME;
d61780c0 715
1da177e4 716 else if (status & RCSR_OE)
33f0f88f 717 flag = TTY_OVERRUN;
d61780c0 718
1da177e4 719 else
33f0f88f 720 flag = TTY_NORMAL;
1da177e4 721
33f0f88f
AC
722 if(tty_insert_flip_char(tty, ch, flag))
723 tty_flip_buffer_push(tty);
1da177e4
LT
724 func_exit();
725}
726
727
728static inline void sx_receive(struct specialix_board * bp)
729{
730 struct specialix_port *port;
731 struct tty_struct *tty;
732 unsigned char count;
733
734 func_enter();
d61780c0 735
1da177e4
LT
736 if (!(port = sx_get_port(bp, "Receive"))) {
737 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
738 func_exit();
739 return;
740 }
741 tty = port->tty;
d61780c0 742
1da177e4
LT
743 count = sx_in(bp, CD186x_RDCR);
744 dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
745 port->hits[count > 8 ? 9 : count]++;
d61780c0 746
33f0f88f 747 tty_buffer_request_room(tty, count);
1da177e4 748
33f0f88f
AC
749 while (count--)
750 tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
751 tty_flip_buffer_push(tty);
1da177e4
LT
752 func_exit();
753}
754
755
756static inline void sx_transmit(struct specialix_board * bp)
757{
758 struct specialix_port *port;
759 struct tty_struct *tty;
760 unsigned char count;
761
762 func_enter();
763 if (!(port = sx_get_port(bp, "Transmit"))) {
764 func_exit();
765 return;
766 }
767 dprintk (SX_DEBUG_TX, "port: %p\n", port);
768 tty = port->tty;
d61780c0 769
1da177e4
LT
770 if (port->IER & IER_TXEMPTY) {
771 /* FIFO drained */
772 sx_out(bp, CD186x_CAR, port_No(port));
773 port->IER &= ~IER_TXEMPTY;
774 sx_out(bp, CD186x_IER, port->IER);
775 func_exit();
776 return;
777 }
d61780c0 778
1da177e4
LT
779 if ((port->xmit_cnt <= 0 && !port->break_length)
780 || tty->stopped || tty->hw_stopped) {
781 sx_out(bp, CD186x_CAR, port_No(port));
782 port->IER &= ~IER_TXRDY;
783 sx_out(bp, CD186x_IER, port->IER);
784 func_exit();
785 return;
786 }
d61780c0 787
1da177e4
LT
788 if (port->break_length) {
789 if (port->break_length > 0) {
790 if (port->COR2 & COR2_ETC) {
791 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
792 sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
793 port->COR2 &= ~COR2_ETC;
794 }
795 count = min_t(int, port->break_length, 0xff);
796 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
797 sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
798 sx_out(bp, CD186x_TDR, count);
799 if (!(port->break_length -= count))
800 port->break_length--;
801 } else {
802 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
803 sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
804 sx_out(bp, CD186x_COR2, port->COR2);
805 sx_wait_CCR(bp);
806 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
807 port->break_length = 0;
808 }
809
810 func_exit();
811 return;
812 }
d61780c0 813
1da177e4
LT
814 count = CD186x_NFIFO;
815 do {
816 sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
817 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
818 if (--port->xmit_cnt <= 0)
819 break;
820 } while (--count > 0);
d61780c0 821
1da177e4
LT
822 if (port->xmit_cnt <= 0) {
823 sx_out(bp, CD186x_CAR, port_No(port));
824 port->IER &= ~IER_TXRDY;
825 sx_out(bp, CD186x_IER, port->IER);
826 }
827 if (port->xmit_cnt <= port->wakeup_chars)
828 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
829
830 func_exit();
831}
832
833
834static inline void sx_check_modem(struct specialix_board * bp)
835{
836 struct specialix_port *port;
837 struct tty_struct *tty;
838 unsigned char mcr;
839 int msvr_cd;
840
841 dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
842 if (!(port = sx_get_port(bp, "Modem")))
843 return;
d61780c0 844
1da177e4 845 tty = port->tty;
d61780c0 846
1da177e4
LT
847 mcr = sx_in(bp, CD186x_MCR);
848 printk ("mcr = %02x.\n", mcr);
849
850 if ((mcr & MCR_CDCHG)) {
851 dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
852 msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
853 if (msvr_cd) {
854 dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
855 wake_up_interruptible(&port->open_wait);
856 } else {
857 dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
858 schedule_work(&port->tqueue_hangup);
859 }
860 }
d61780c0 861
1da177e4
LT
862#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
863 if (mcr & MCR_CTSCHG) {
864 if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
865 tty->hw_stopped = 0;
866 port->IER |= IER_TXRDY;
867 if (port->xmit_cnt <= port->wakeup_chars)
868 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
869 } else {
870 tty->hw_stopped = 1;
871 port->IER &= ~IER_TXRDY;
872 }
873 sx_out(bp, CD186x_IER, port->IER);
874 }
875 if (mcr & MCR_DSSXHG) {
876 if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
877 tty->hw_stopped = 0;
878 port->IER |= IER_TXRDY;
879 if (port->xmit_cnt <= port->wakeup_chars)
880 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
881 } else {
882 tty->hw_stopped = 1;
883 port->IER &= ~IER_TXRDY;
884 }
885 sx_out(bp, CD186x_IER, port->IER);
886 }
887#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
d61780c0 888
1da177e4
LT
889 /* Clear change bits */
890 sx_out(bp, CD186x_MCR, 0);
891}
892
893
894/* The main interrupt processing routine */
7d12e780 895static irqreturn_t sx_interrupt(int irq, void *dev_id)
1da177e4
LT
896{
897 unsigned char status;
898 unsigned char ack;
899 struct specialix_board *bp;
900 unsigned long loop = 0;
901 int saved_reg;
902 unsigned long flags;
903
904 func_enter();
905
906 bp = dev_id;
907 spin_lock_irqsave(&bp->lock, flags);
908
909 dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
c7bec5ab 910 if (!(bp->flags & SX_BOARD_ACTIVE)) {
1da177e4
LT
911 dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
912 spin_unlock_irqrestore(&bp->lock, flags);
913 func_exit();
914 return IRQ_NONE;
915 }
916
917 saved_reg = bp->reg;
918
919 while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
920 (SRSR_RREQint |
921 SRSR_TREQint |
d61780c0 922 SRSR_MREQint)))) {
1da177e4
LT
923 if (status & SRSR_RREQint) {
924 ack = sx_in(bp, CD186x_RRAR);
925
926 if (ack == (SX_ID | GIVR_IT_RCV))
927 sx_receive(bp);
928 else if (ack == (SX_ID | GIVR_IT_REXC))
929 sx_receive_exc(bp);
930 else
931 printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
932 board_No(bp), status, ack);
d61780c0 933
1da177e4
LT
934 } else if (status & SRSR_TREQint) {
935 ack = sx_in(bp, CD186x_TRAR);
936
937 if (ack == (SX_ID | GIVR_IT_TX))
938 sx_transmit(bp);
939 else
940 printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
941 board_No(bp), status, ack, port_No (sx_get_port (bp, "Int")));
942 } else if (status & SRSR_MREQint) {
943 ack = sx_in(bp, CD186x_MRAR);
944
d61780c0 945 if (ack == (SX_ID | GIVR_IT_MODEM))
1da177e4
LT
946 sx_check_modem(bp);
947 else
948 printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
949 board_No(bp), status, ack);
d61780c0
JG
950
951 }
1da177e4
LT
952
953 sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
954 }
955 bp->reg = saved_reg;
956 outb (bp->reg, bp->base + SX_ADDR_REG);
957 spin_unlock_irqrestore(&bp->lock, flags);
958 func_exit();
959 return IRQ_HANDLED;
960}
961
962
963/*
964 * Routines for open & close processing.
965 */
966
967static void turn_ints_off (struct specialix_board *bp)
968{
969 unsigned long flags;
970
971 func_enter();
972 if (bp->flags & SX_BOARD_IS_PCI) {
973 /* This was intended for enabeling the interrupt on the
974 * PCI card. However it seems that it's already enabled
975 * and as PCI interrupts can be shared, there is no real
976 * reason to have to turn it off. */
977 }
978
979 spin_lock_irqsave(&bp->lock, flags);
980 (void) sx_in_off (bp, 0); /* Turn off interrupts. */
981 spin_unlock_irqrestore(&bp->lock, flags);
982
983 func_exit();
984}
985
986static void turn_ints_on (struct specialix_board *bp)
987{
988 unsigned long flags;
989
990 func_enter();
991
992 if (bp->flags & SX_BOARD_IS_PCI) {
993 /* play with the PCI chip. See comment above. */
994 }
995 spin_lock_irqsave(&bp->lock, flags);
996 (void) sx_in (bp, 0); /* Turn ON interrupts. */
997 spin_unlock_irqrestore(&bp->lock, flags);
998
999 func_exit();
1000}
1001
1002
1003/* Called with disabled interrupts */
1004static inline int sx_setup_board(struct specialix_board * bp)
1005{
1006 int error;
1007
d61780c0 1008 if (bp->flags & SX_BOARD_ACTIVE)
1da177e4
LT
1009 return 0;
1010
1011 if (bp->flags & SX_BOARD_IS_PCI)
0f2ed4c6 1012 error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
1da177e4 1013 else
0f2ed4c6 1014 error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp);
1da177e4 1015
d61780c0 1016 if (error)
1da177e4
LT
1017 return error;
1018
1019 turn_ints_on (bp);
1020 bp->flags |= SX_BOARD_ACTIVE;
1021
1022 return 0;
1023}
1024
1025
1026/* Called with disabled interrupts */
1027static inline void sx_shutdown_board(struct specialix_board *bp)
1028{
1029 func_enter();
1030
1031 if (!(bp->flags & SX_BOARD_ACTIVE)) {
1032 func_exit();
1033 return;
1034 }
1035
1036 bp->flags &= ~SX_BOARD_ACTIVE;
d61780c0 1037
1da177e4
LT
1038 dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
1039 bp->irq, board_No (bp));
1040 free_irq(bp->irq, bp);
1041
1042 turn_ints_off (bp);
1043
1044
1045 func_exit();
1046}
1047
1048
1049/*
d61780c0 1050 * Setting up port characteristics.
1da177e4
LT
1051 * Must be called with disabled interrupts
1052 */
1053static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
1054{
1055 struct tty_struct *tty;
1056 unsigned long baud;
1057 long tmp;
1058 unsigned char cor1 = 0, cor3 = 0;
1059 unsigned char mcor1 = 0, mcor2 = 0;
1060 static unsigned long again;
1061 unsigned long flags;
1062
1063 func_enter();
1064
1065 if (!(tty = port->tty) || !tty->termios) {
1066 func_exit();
1067 return;
1068 }
1069
1070 port->IER = 0;
1071 port->COR2 = 0;
1072 /* Select port on the board */
1073 spin_lock_irqsave(&bp->lock, flags);
1074 sx_out(bp, CD186x_CAR, port_No(port));
1075
1076 /* The Specialix board doens't implement the RTS lines.
1077 They are used to set the IRQ level. Don't touch them. */
1078 if (SX_CRTSCTS(tty))
1079 port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1080 else
1081 port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1082 spin_unlock_irqrestore(&bp->lock, flags);
1083 dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
67cc0161 1084 baud = tty_get_baud_rate(tty);
d61780c0 1085
67cc0161 1086 if (baud == 38400) {
1da177e4 1087 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
a4bb2cf1 1088 baud = 57600;
1da177e4 1089 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
a4bb2cf1 1090 baud = 115200;
1da177e4 1091 }
d61780c0 1092
67cc0161 1093 if (!baud) {
1da177e4
LT
1094 /* Drop DTR & exit */
1095 dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
1096 if (!SX_CRTSCTS (tty)) {
1097 port -> MSVR &= ~ MSVR_DTR;
1098 spin_lock_irqsave(&bp->lock, flags);
1099 sx_out(bp, CD186x_MSVR, port->MSVR );
1100 spin_unlock_irqrestore(&bp->lock, flags);
d61780c0 1101 }
1da177e4
LT
1102 else
1103 dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
1104 return;
1105 } else {
1106 /* Set DTR on */
1107 if (!SX_CRTSCTS (tty)) {
1108 port ->MSVR |= MSVR_DTR;
1109 }
1110 }
d61780c0 1111
1da177e4 1112 /*
d61780c0 1113 * Now we must calculate some speed depended things
1da177e4
LT
1114 */
1115
1116 /* Set baud rate for port */
1117 tmp = port->custom_divisor ;
1118 if ( tmp )
1119 printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"
1120 "This is an untested option, please be carefull.\n",
1121 port_No (port), tmp);
1122 else
67cc0161 1123 tmp = (((SX_OSCFREQ + baud/2) / baud +
1da177e4
LT
1124 CD186x_TPC/2) / CD186x_TPC);
1125
d61780c0 1126 if ((tmp < 0x10) && time_before(again, jiffies)) {
1da177e4
LT
1127 again = jiffies + HZ * 60;
1128 /* Page 48 of version 2.0 of the CL-CD1865 databook */
1129 if (tmp >= 12) {
1130 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1131 "Performance degradation is possible.\n"
1132 "Read specialix.txt for more info.\n",
1133 port_No (port), tmp);
1134 } else {
1135 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1136 "Warning: overstressing Cirrus chip. "
1137 "This might not work.\n"
d61780c0 1138 "Read specialix.txt for more info.\n",
1da177e4
LT
1139 port_No (port), tmp);
1140 }
1141 }
1142 spin_lock_irqsave(&bp->lock, flags);
d61780c0
JG
1143 sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
1144 sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
1145 sx_out(bp, CD186x_RBPRL, tmp & 0xff);
1da177e4
LT
1146 sx_out(bp, CD186x_TBPRL, tmp & 0xff);
1147 spin_unlock_irqrestore(&bp->lock, flags);
a4bb2cf1 1148 if (port->custom_divisor)
1da177e4 1149 baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
a4bb2cf1 1150 baud = (baud + 5) / 10; /* Estimated CPS */
1da177e4
LT
1151
1152 /* Two timer ticks seems enough to wakeup something like SLIP driver */
d61780c0 1153 tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
1da177e4
LT
1154 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
1155 SERIAL_XMIT_SIZE - 1 : tmp);
d61780c0 1156
1da177e4
LT
1157 /* Receiver timeout will be transmission time for 1.5 chars */
1158 tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
1159 tmp = (tmp > 0xff) ? 0xff : tmp;
1160 spin_lock_irqsave(&bp->lock, flags);
1161 sx_out(bp, CD186x_RTPR, tmp);
1162 spin_unlock_irqrestore(&bp->lock, flags);
1163 switch (C_CSIZE(tty)) {
1164 case CS5:
1165 cor1 |= COR1_5BITS;
1166 break;
1167 case CS6:
1168 cor1 |= COR1_6BITS;
1169 break;
1170 case CS7:
1171 cor1 |= COR1_7BITS;
1172 break;
1173 case CS8:
1174 cor1 |= COR1_8BITS;
1175 break;
1176 }
d61780c0
JG
1177
1178 if (C_CSTOPB(tty))
1da177e4 1179 cor1 |= COR1_2SB;
d61780c0 1180
1da177e4
LT
1181 cor1 |= COR1_IGNORE;
1182 if (C_PARENB(tty)) {
1183 cor1 |= COR1_NORMPAR;
d61780c0 1184 if (C_PARODD(tty))
1da177e4 1185 cor1 |= COR1_ODDP;
d61780c0 1186 if (I_INPCK(tty))
1da177e4
LT
1187 cor1 &= ~COR1_IGNORE;
1188 }
1189 /* Set marking of some errors */
1190 port->mark_mask = RCSR_OE | RCSR_TOUT;
d61780c0 1191 if (I_INPCK(tty))
1da177e4 1192 port->mark_mask |= RCSR_FE | RCSR_PE;
d61780c0 1193 if (I_BRKINT(tty) || I_PARMRK(tty))
1da177e4 1194 port->mark_mask |= RCSR_BREAK;
d61780c0 1195 if (I_IGNPAR(tty))
1da177e4
LT
1196 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
1197 if (I_IGNBRK(tty)) {
1198 port->mark_mask &= ~RCSR_BREAK;
d61780c0 1199 if (I_IGNPAR(tty))
1da177e4
LT
1200 /* Real raw mode. Ignore all */
1201 port->mark_mask &= ~RCSR_OE;
1202 }
1203 /* Enable Hardware Flow Control */
1204 if (C_CRTSCTS(tty)) {
1205#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
1206 port->IER |= IER_DSR | IER_CTS;
1207 mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
1208 mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
1209 spin_lock_irqsave(&bp->lock, flags);
1210 tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
1211 spin_unlock_irqrestore(&bp->lock, flags);
1212#else
d61780c0 1213 port->COR2 |= COR2_CTSAE;
1da177e4
LT
1214#endif
1215 }
1216 /* Enable Software Flow Control. FIXME: I'm not sure about this */
1217 /* Some people reported that it works, but I still doubt it */
1218 if (I_IXON(tty)) {
1219 port->COR2 |= COR2_TXIBE;
1220 cor3 |= (COR3_FCT | COR3_SCDE);
1221 if (I_IXANY(tty))
1222 port->COR2 |= COR2_IXM;
1223 spin_lock_irqsave(&bp->lock, flags);
1224 sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
1225 sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
1226 sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
1227 sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
1228 spin_unlock_irqrestore(&bp->lock, flags);
1229 }
1230 if (!C_CLOCAL(tty)) {
1231 /* Enable CD check */
1232 port->IER |= IER_CD;
1233 mcor1 |= MCOR1_CDZD;
1234 mcor2 |= MCOR2_CDOD;
1235 }
d61780c0
JG
1236
1237 if (C_CREAD(tty))
1da177e4
LT
1238 /* Enable receiver */
1239 port->IER |= IER_RXD;
d61780c0 1240
1da177e4
LT
1241 /* Set input FIFO size (1-8 bytes) */
1242 cor3 |= sx_rxfifo;
1243 /* Setting up CD186x channel registers */
1244 spin_lock_irqsave(&bp->lock, flags);
1245 sx_out(bp, CD186x_COR1, cor1);
1246 sx_out(bp, CD186x_COR2, port->COR2);
1247 sx_out(bp, CD186x_COR3, cor3);
1248 spin_unlock_irqrestore(&bp->lock, flags);
1249 /* Make CD186x know about registers change */
1250 sx_wait_CCR(bp);
1251 spin_lock_irqsave(&bp->lock, flags);
1252 sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1253 /* Setting up modem option registers */
1254 dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
1255 sx_out(bp, CD186x_MCOR1, mcor1);
1256 sx_out(bp, CD186x_MCOR2, mcor2);
1257 spin_unlock_irqrestore(&bp->lock, flags);
1258 /* Enable CD186x transmitter & receiver */
1259 sx_wait_CCR(bp);
1260 spin_lock_irqsave(&bp->lock, flags);
1261 sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
1262 /* Enable interrupts */
1263 sx_out(bp, CD186x_IER, port->IER);
1264 /* And finally set the modem lines... */
1265 sx_out(bp, CD186x_MSVR, port->MSVR);
1266 spin_unlock_irqrestore(&bp->lock, flags);
1267
1268 func_exit();
1269}
1270
1271
1272/* Must be called with interrupts enabled */
1273static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
1274{
1275 unsigned long flags;
1276
1277 func_enter();
1278
1279 if (port->flags & ASYNC_INITIALIZED) {
1280 func_exit();
1281 return 0;
1282 }
d61780c0 1283
1da177e4
LT
1284 if (!port->xmit_buf) {
1285 /* We may sleep in get_zeroed_page() */
1286 unsigned long tmp;
d61780c0 1287
1da177e4
LT
1288 if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
1289 func_exit();
1290 return -ENOMEM;
1291 }
1292
1293 if (port->xmit_buf) {
1294 free_page(tmp);
1295 func_exit();
1296 return -ERESTARTSYS;
1297 }
1298 port->xmit_buf = (unsigned char *) tmp;
1299 }
d61780c0 1300
1da177e4
LT
1301 spin_lock_irqsave(&port->lock, flags);
1302
d61780c0 1303 if (port->tty)
1da177e4
LT
1304 clear_bit(TTY_IO_ERROR, &port->tty->flags);
1305
1306 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1307 sx_change_speed(bp, port);
1308 port->flags |= ASYNC_INITIALIZED;
1309
1310 spin_unlock_irqrestore(&port->lock, flags);
1311
d61780c0 1312
1da177e4
LT
1313 func_exit();
1314 return 0;
1315}
1316
1317
1318/* Must be called with interrupts disabled */
1319static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
1320{
1321 struct tty_struct *tty;
1322 int i;
1323 unsigned long flags;
d61780c0 1324
1da177e4
LT
1325 func_enter();
1326
1327 if (!(port->flags & ASYNC_INITIALIZED)) {
1328 func_exit();
1329 return;
1330 }
d61780c0 1331
1da177e4
LT
1332 if (sx_debug & SX_DEBUG_FIFO) {
1333 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
1334 board_No(bp), port_No(port), port->overrun);
1335 for (i = 0; i < 10; i++) {
1336 dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
1337 }
1338 dprintk(SX_DEBUG_FIFO, "].\n");
1339 }
1340
1341 if (port->xmit_buf) {
1342 free_page((unsigned long) port->xmit_buf);
1343 port->xmit_buf = NULL;
1344 }
1345
1346 /* Select port */
1347 spin_lock_irqsave(&bp->lock, flags);
1348 sx_out(bp, CD186x_CAR, port_No(port));
1349
1350 if (!(tty = port->tty) || C_HUPCL(tty)) {
1351 /* Drop DTR */
1352 sx_out(bp, CD186x_MSVDTR, 0);
1353 }
1354 spin_unlock_irqrestore(&bp->lock, flags);
1355 /* Reset port */
1356 sx_wait_CCR(bp);
1357 spin_lock_irqsave(&bp->lock, flags);
1358 sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
1359 /* Disable all interrupts from this port */
1360 port->IER = 0;
1361 sx_out(bp, CD186x_IER, port->IER);
1362 spin_unlock_irqrestore(&bp->lock, flags);
1363 if (tty)
1364 set_bit(TTY_IO_ERROR, &tty->flags);
1365 port->flags &= ~ASYNC_INITIALIZED;
d61780c0
JG
1366
1367 if (!bp->count)
1da177e4
LT
1368 sx_shutdown_board(bp);
1369 func_exit();
1370}
1371
d61780c0 1372
1da177e4
LT
1373static int block_til_ready(struct tty_struct *tty, struct file * filp,
1374 struct specialix_port *port)
1375{
1376 DECLARE_WAITQUEUE(wait, current);
1377 struct specialix_board *bp = port_Board(port);
1378 int retval;
1379 int do_clocal = 0;
1380 int CD;
1381 unsigned long flags;
1382
1383 func_enter();
1384
1385 /*
1386 * If the device is in the middle of being closed, then block
1387 * until it's done, and then try again.
1388 */
1389 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
1390 interruptible_sleep_on(&port->close_wait);
1391 if (port->flags & ASYNC_HUP_NOTIFY) {
1392 func_exit();
1393 return -EAGAIN;
1394 } else {
1395 func_exit();
1396 return -ERESTARTSYS;
1397 }
1398 }
d61780c0 1399
1da177e4
LT
1400 /*
1401 * If non-blocking mode is set, or the port is not enabled,
1402 * then make the check up front and then exit.
1403 */
1404 if ((filp->f_flags & O_NONBLOCK) ||
1405 (tty->flags & (1 << TTY_IO_ERROR))) {
1406 port->flags |= ASYNC_NORMAL_ACTIVE;
1407 func_exit();
1408 return 0;
1409 }
1410
1411 if (C_CLOCAL(tty))
1412 do_clocal = 1;
1413
1414 /*
1415 * Block waiting for the carrier detect and the line to become
1416 * free (i.e., not in use by the callout). While we are in
1417 * this loop, info->count is dropped by one, so that
1418 * rs_close() knows when to free things. We restore it upon
1419 * exit, either normal or abnormal.
1420 */
1421 retval = 0;
1422 add_wait_queue(&port->open_wait, &wait);
1423 spin_lock_irqsave(&port->lock, flags);
1424 if (!tty_hung_up_p(filp)) {
1425 port->count--;
1426 }
1427 spin_unlock_irqrestore(&port->lock, flags);
1428 port->blocked_open++;
1429 while (1) {
1430 spin_lock_irqsave(&bp->lock, flags);
1431 sx_out(bp, CD186x_CAR, port_No(port));
1432 CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
1433 if (SX_CRTSCTS (tty)) {
1434 /* Activate RTS */
1435 port->MSVR |= MSVR_DTR; /* WTF? */
1436 sx_out (bp, CD186x_MSVR, port->MSVR);
1437 } else {
1438 /* Activate DTR */
1439 port->MSVR |= MSVR_DTR;
1440 sx_out (bp, CD186x_MSVR, port->MSVR);
1441 }
1442 spin_unlock_irqrestore(&bp->lock, flags);
1443 set_current_state(TASK_INTERRUPTIBLE);
1444 if (tty_hung_up_p(filp) ||
1445 !(port->flags & ASYNC_INITIALIZED)) {
1446 if (port->flags & ASYNC_HUP_NOTIFY)
1447 retval = -EAGAIN;
1448 else
d61780c0 1449 retval = -ERESTARTSYS;
1da177e4
LT
1450 break;
1451 }
1452 if (!(port->flags & ASYNC_CLOSING) &&
1453 (do_clocal || CD))
1454 break;
1455 if (signal_pending(current)) {
1456 retval = -ERESTARTSYS;
1457 break;
1458 }
1459 schedule();
1460 }
1461
1462 set_current_state(TASK_RUNNING);
1463 remove_wait_queue(&port->open_wait, &wait);
1464 spin_lock_irqsave(&port->lock, flags);
1465 if (!tty_hung_up_p(filp)) {
1466 port->count++;
1467 }
1468 port->blocked_open--;
1469 spin_unlock_irqrestore(&port->lock, flags);
1470 if (retval) {
1471 func_exit();
1472 return retval;
1473 }
1474
1475 port->flags |= ASYNC_NORMAL_ACTIVE;
1476 func_exit();
1477 return 0;
d61780c0 1478}
1da177e4
LT
1479
1480
1481static int sx_open(struct tty_struct * tty, struct file * filp)
1482{
1483 int board;
1484 int error;
1485 struct specialix_port * port;
1486 struct specialix_board * bp;
1487 int i;
1488 unsigned long flags;
1489
1490 func_enter();
1491
1492 board = SX_BOARD(tty->index);
1493
1494 if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
1495 func_exit();
1496 return -ENODEV;
1497 }
d61780c0 1498
1da177e4
LT
1499 bp = &sx_board[board];
1500 port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
1501 port->overrun = 0;
1502 for (i = 0; i < 10; i++)
1503 port->hits[i]=0;
1504
1505 dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
1506 board, bp, port, SX_PORT(tty->index));
1507
1508 if (sx_paranoia_check(port, tty->name, "sx_open")) {
1509 func_enter();
1510 return -ENODEV;
1511 }
1512
1513 if ((error = sx_setup_board(bp))) {
1514 func_exit();
1515 return error;
1516 }
1517
1518 spin_lock_irqsave(&bp->lock, flags);
1519 port->count++;
1520 bp->count++;
1521 tty->driver_data = port;
1522 port->tty = tty;
1523 spin_unlock_irqrestore(&bp->lock, flags);
1524
1525 if ((error = sx_setup_port(bp, port))) {
1526 func_enter();
1527 return error;
1528 }
d61780c0 1529
1da177e4
LT
1530 if ((error = block_til_ready(tty, filp, port))) {
1531 func_enter();
1532 return error;
1533 }
1534
1535 func_exit();
1536 return 0;
1537}
1538
1539
1540static void sx_close(struct tty_struct * tty, struct file * filp)
1541{
1542 struct specialix_port *port = (struct specialix_port *) tty->driver_data;
1543 struct specialix_board *bp;
1544 unsigned long flags;
1545 unsigned long timeout;
d61780c0 1546
1da177e4
LT
1547 func_enter();
1548 if (!port || sx_paranoia_check(port, tty->name, "close")) {
1549 func_exit();
1550 return;
1551 }
1552 spin_lock_irqsave(&port->lock, flags);
1553
1554 if (tty_hung_up_p(filp)) {
1555 spin_unlock_irqrestore(&port->lock, flags);
1556 func_exit();
1557 return;
1558 }
d61780c0 1559
1da177e4
LT
1560 bp = port_Board(port);
1561 if ((tty->count == 1) && (port->count != 1)) {
1562 printk(KERN_ERR "sx%d: sx_close: bad port count;"
1563 " tty->count is 1, port count is %d\n",
1564 board_No(bp), port->count);
1565 port->count = 1;
1566 }
1567
1568 if (port->count > 1) {
1569 port->count--;
1570 bp->count--;
1571
1572 spin_unlock_irqrestore(&port->lock, flags);
1573
1574 func_exit();
1575 return;
1576 }
1577 port->flags |= ASYNC_CLOSING;
1578 /*
d61780c0 1579 * Now we wait for the transmit buffer to clear; and we notify
1da177e4
LT
1580 * the line discipline to only process XON/XOFF characters.
1581 */
1582 tty->closing = 1;
1583 spin_unlock_irqrestore(&port->lock, flags);
1584 dprintk (SX_DEBUG_OPEN, "Closing\n");
1585 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
1586 tty_wait_until_sent(tty, port->closing_wait);
1587 }
1588 /*
1589 * At this point we stop accepting input. To do this, we
1590 * disable the receive line status interrupts, and tell the
1591 * interrupt driver to stop checking the data ready bit in the
1592 * line status register.
1593 */
1594 dprintk (SX_DEBUG_OPEN, "Closed\n");
1595 port->IER &= ~IER_RXD;
1596 if (port->flags & ASYNC_INITIALIZED) {
1597 port->IER &= ~IER_TXRDY;
1598 port->IER |= IER_TXEMPTY;
1599 spin_lock_irqsave(&bp->lock, flags);
1600 sx_out(bp, CD186x_CAR, port_No(port));
1601 sx_out(bp, CD186x_IER, port->IER);
1602 spin_unlock_irqrestore(&bp->lock, flags);
1603 /*
1604 * Before we drop DTR, make sure the UART transmitter
1605 * has completely drained; this is especially
1606 * important if there is a transmit FIFO!
1607 */
1608 timeout = jiffies+HZ;
1609 while(port->IER & IER_TXEMPTY) {
1610 set_current_state (TASK_INTERRUPTIBLE);
1611 msleep_interruptible(jiffies_to_msecs(port->timeout));
1612 if (time_after(jiffies, timeout)) {
1613 printk (KERN_INFO "Timeout waiting for close\n");
1614 break;
1615 }
1616 }
1617
1618 }
1619
1620 if (--bp->count < 0) {
1621 printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
1622 board_No(bp), bp->count, tty->index);
1623 bp->count = 0;
1624 }
1625 if (--port->count < 0) {
1626 printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
1627 board_No(bp), port_No(port), port->count);
1628 port->count = 0;
1629 }
1630
1631 sx_shutdown_port(bp, port);
1632 if (tty->driver->flush_buffer)
1633 tty->driver->flush_buffer(tty);
1634 tty_ldisc_flush(tty);
1635 spin_lock_irqsave(&port->lock, flags);
1636 tty->closing = 0;
1637 port->event = 0;
1638 port->tty = NULL;
1639 spin_unlock_irqrestore(&port->lock, flags);
1640 if (port->blocked_open) {
1641 if (port->close_delay) {
1642 msleep_interruptible(jiffies_to_msecs(port->close_delay));
1643 }
1644 wake_up_interruptible(&port->open_wait);
1645 }
1646 port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1647 wake_up_interruptible(&port->close_wait);
1648
1649 func_exit();
1650}
1651
1652
d61780c0 1653static int sx_write(struct tty_struct * tty,
1da177e4
LT
1654 const unsigned char *buf, int count)
1655{
1656 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1657 struct specialix_board *bp;
1658 int c, total = 0;
1659 unsigned long flags;
1660
1661 func_enter();
1662 if (sx_paranoia_check(port, tty->name, "sx_write")) {
1663 func_exit();
1664 return 0;
1665 }
d61780c0 1666
1da177e4
LT
1667 bp = port_Board(port);
1668
365e0223 1669 if (!port->xmit_buf) {
1da177e4
LT
1670 func_exit();
1671 return 0;
1672 }
1673
1674 while (1) {
1675 spin_lock_irqsave(&port->lock, flags);
1676 c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1677 SERIAL_XMIT_SIZE - port->xmit_head));
1678 if (c <= 0) {
1679 spin_unlock_irqrestore(&port->lock, flags);
1680 break;
1681 }
1682 memcpy(port->xmit_buf + port->xmit_head, buf, c);
1683 port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1684 port->xmit_cnt += c;
1685 spin_unlock_irqrestore(&port->lock, flags);
1686
1687 buf += c;
1688 count -= c;
1689 total += c;
1690 }
1691
1692 spin_lock_irqsave(&bp->lock, flags);
1693 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1694 !(port->IER & IER_TXRDY)) {
1695 port->IER |= IER_TXRDY;
1696 sx_out(bp, CD186x_CAR, port_No(port));
1697 sx_out(bp, CD186x_IER, port->IER);
1698 }
1699 spin_unlock_irqrestore(&bp->lock, flags);
1700 func_exit();
1701
1702 return total;
1703}
1704
1705
1706static void sx_put_char(struct tty_struct * tty, unsigned char ch)
1707{
1708 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1709 unsigned long flags;
1710 struct specialix_board * bp;
1711
1712 func_enter();
1713
1714 if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
1715 func_exit();
1716 return;
1717 }
1718 dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
326f28e9 1719 if (!port->xmit_buf) {
1da177e4
LT
1720 func_exit();
1721 return;
1722 }
1723 bp = port_Board(port);
1724 spin_lock_irqsave(&port->lock, flags);
1725
1726 dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf);
1727 if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) {
1728 spin_unlock_irqrestore(&port->lock, flags);
1729 dprintk (SX_DEBUG_TX, "Exit size\n");
1730 func_exit();
1731 return;
1732 }
1733 dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
1734 port->xmit_buf[port->xmit_head++] = ch;
1735 port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1736 port->xmit_cnt++;
1737 spin_unlock_irqrestore(&port->lock, flags);
1738
1739 func_exit();
1740}
1741
1742
1743static void sx_flush_chars(struct tty_struct * tty)
1744{
1745 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1746 unsigned long flags;
1747 struct specialix_board * bp = port_Board(port);
1748
1749 func_enter();
1750
1751 if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
1752 func_exit();
1753 return;
1754 }
1755 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1756 !port->xmit_buf) {
1757 func_exit();
1758 return;
1759 }
1760 spin_lock_irqsave(&bp->lock, flags);
1761 port->IER |= IER_TXRDY;
1762 sx_out(port_Board(port), CD186x_CAR, port_No(port));
1763 sx_out(port_Board(port), CD186x_IER, port->IER);
1764 spin_unlock_irqrestore(&bp->lock, flags);
1765
1766 func_exit();
1767}
1768
1769
1770static int sx_write_room(struct tty_struct * tty)
1771{
1772 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1773 int ret;
1774
1775 func_enter();
1776
1777 if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
1778 func_exit();
1779 return 0;
1780 }
1781
1782 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1783 if (ret < 0)
1784 ret = 0;
1785
1786 func_exit();
1787 return ret;
1788}
1789
1790
1791static int sx_chars_in_buffer(struct tty_struct *tty)
1792{
1793 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1794
1795 func_enter();
d61780c0 1796
1da177e4
LT
1797 if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
1798 func_exit();
1799 return 0;
1800 }
1801 func_exit();
1802 return port->xmit_cnt;
1803}
1804
1805
1806static void sx_flush_buffer(struct tty_struct *tty)
1807{
1808 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1809 unsigned long flags;
1810 struct specialix_board * bp;
1811
1812 func_enter();
1813
1814 if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
1815 func_exit();
1816 return;
1817 }
1818
1819 bp = port_Board(port);
1820 spin_lock_irqsave(&port->lock, flags);
1821 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1822 spin_unlock_irqrestore(&port->lock, flags);
1823 tty_wakeup(tty);
1824
1825 func_exit();
1826}
1827
1828
1829static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1830{
1831 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1832 struct specialix_board * bp;
1833 unsigned char status;
1834 unsigned int result;
1835 unsigned long flags;
1836
1837 func_enter();
1838
1839 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1840 func_exit();
1841 return -ENODEV;
1842 }
1843
1844 bp = port_Board(port);
1845 spin_lock_irqsave (&bp->lock, flags);
1846 sx_out(bp, CD186x_CAR, port_No(port));
1847 status = sx_in(bp, CD186x_MSVR);
1848 spin_unlock_irqrestore(&bp->lock, flags);
1849 dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
1850 port_No(port), status, sx_in (bp, CD186x_CAR));
1851 dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
1852 if (SX_CRTSCTS(port->tty)) {
d61780c0 1853 result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
1da177e4
LT
1854 | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
1855 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1856 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1857 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1858 } else {
d61780c0 1859 result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
1da177e4
LT
1860 | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1861 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1862 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1863 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1864 }
1865
1866 func_exit();
1867
1868 return result;
1869}
1870
1871
1872static int sx_tiocmset(struct tty_struct *tty, struct file *file,
1873 unsigned int set, unsigned int clear)
1874{
1875 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1876 unsigned long flags;
1877 struct specialix_board *bp;
1878
1879 func_enter();
1880
1881 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1882 func_exit();
1883 return -ENODEV;
1884 }
1885
1886 bp = port_Board(port);
1887
1888 spin_lock_irqsave(&port->lock, flags);
1889 /* if (set & TIOCM_RTS)
1890 port->MSVR |= MSVR_RTS; */
1891 /* if (set & TIOCM_DTR)
1892 port->MSVR |= MSVR_DTR; */
1893
1894 if (SX_CRTSCTS(port->tty)) {
1895 if (set & TIOCM_RTS)
1896 port->MSVR |= MSVR_DTR;
1897 } else {
1898 if (set & TIOCM_DTR)
1899 port->MSVR |= MSVR_DTR;
1900 }
1901
1902 /* if (clear & TIOCM_RTS)
1903 port->MSVR &= ~MSVR_RTS; */
1904 /* if (clear & TIOCM_DTR)
1905 port->MSVR &= ~MSVR_DTR; */
1906 if (SX_CRTSCTS(port->tty)) {
1907 if (clear & TIOCM_RTS)
1908 port->MSVR &= ~MSVR_DTR;
1909 } else {
1910 if (clear & TIOCM_DTR)
1911 port->MSVR &= ~MSVR_DTR;
1912 }
1913 spin_lock_irqsave(&bp->lock, flags);
1914 sx_out(bp, CD186x_CAR, port_No(port));
1915 sx_out(bp, CD186x_MSVR, port->MSVR);
1916 spin_unlock_irqrestore(&bp->lock, flags);
1917 spin_unlock_irqrestore(&port->lock, flags);
1918 func_exit();
1919 return 0;
1920}
1921
1922
1923static inline void sx_send_break(struct specialix_port * port, unsigned long length)
1924{
1925 struct specialix_board *bp = port_Board(port);
1926 unsigned long flags;
d61780c0 1927
1da177e4
LT
1928 func_enter();
1929
1930 spin_lock_irqsave (&port->lock, flags);
1931 port->break_length = SPECIALIX_TPS / HZ * length;
1932 port->COR2 |= COR2_ETC;
1933 port->IER |= IER_TXRDY;
1934 spin_lock_irqsave(&bp->lock, flags);
1935 sx_out(bp, CD186x_CAR, port_No(port));
1936 sx_out(bp, CD186x_COR2, port->COR2);
1937 sx_out(bp, CD186x_IER, port->IER);
1938 spin_unlock_irqrestore(&bp->lock, flags);
1939 spin_unlock_irqrestore (&port->lock, flags);
1940 sx_wait_CCR(bp);
1941 spin_lock_irqsave(&bp->lock, flags);
1942 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
1943 spin_unlock_irqrestore(&bp->lock, flags);
1944 sx_wait_CCR(bp);
1945
1946 func_exit();
1947}
1948
1949
1950static inline int sx_set_serial_info(struct specialix_port * port,
1951 struct serial_struct __user * newinfo)
1952{
1953 struct serial_struct tmp;
1954 struct specialix_board *bp = port_Board(port);
1955 int change_speed;
1956
1957 func_enter();
1958 /*
e49332bd 1959 if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) {
1da177e4 1960 func_exit();
e49332bd 1961 return -EFAULT;
1da177e4
LT
1962 }
1963 */
1964 if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
1965 func_enter();
1966 return -EFAULT;
1967 }
d61780c0
JG
1968
1969#if 0
1da177e4
LT
1970 if ((tmp.irq != bp->irq) ||
1971 (tmp.port != bp->base) ||
1972 (tmp.type != PORT_CIRRUS) ||
1973 (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
1974 (tmp.custom_divisor != 0) ||
1975 (tmp.xmit_fifo_size != CD186x_NFIFO) ||
1976 (tmp.flags & ~SPECIALIX_LEGAL_FLAGS)) {
1977 func_exit();
1978 return -EINVAL;
1979 }
d61780c0 1980#endif
1da177e4
LT
1981
1982 change_speed = ((port->flags & ASYNC_SPD_MASK) !=
1983 (tmp.flags & ASYNC_SPD_MASK));
1984 change_speed |= (tmp.custom_divisor != port->custom_divisor);
d61780c0 1985
1da177e4
LT
1986 if (!capable(CAP_SYS_ADMIN)) {
1987 if ((tmp.close_delay != port->close_delay) ||
1988 (tmp.closing_wait != port->closing_wait) ||
1989 ((tmp.flags & ~ASYNC_USR_MASK) !=
1990 (port->flags & ~ASYNC_USR_MASK))) {
1991 func_exit();
1992 return -EPERM;
1993 }
1994 port->flags = ((port->flags & ~ASYNC_USR_MASK) |
1995 (tmp.flags & ASYNC_USR_MASK));
1996 port->custom_divisor = tmp.custom_divisor;
1997 } else {
1998 port->flags = ((port->flags & ~ASYNC_FLAGS) |
1999 (tmp.flags & ASYNC_FLAGS));
2000 port->close_delay = tmp.close_delay;
2001 port->closing_wait = tmp.closing_wait;
2002 port->custom_divisor = tmp.custom_divisor;
2003 }
2004 if (change_speed) {
2005 sx_change_speed(bp, port);
2006 }
2007 func_exit();
2008 return 0;
2009}
2010
2011
2012static inline int sx_get_serial_info(struct specialix_port * port,
2013 struct serial_struct __user *retinfo)
2014{
2015 struct serial_struct tmp;
2016 struct specialix_board *bp = port_Board(port);
d61780c0 2017
1da177e4
LT
2018 func_enter();
2019
2020 /*
e49332bd
JJ
2021 if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
2022 return -EFAULT;
1da177e4
LT
2023 */
2024
2025 memset(&tmp, 0, sizeof(tmp));
2026 tmp.type = PORT_CIRRUS;
2027 tmp.line = port - sx_port;
2028 tmp.port = bp->base;
2029 tmp.irq = bp->irq;
2030 tmp.flags = port->flags;
2031 tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
2032 tmp.close_delay = port->close_delay * HZ/100;
2033 tmp.closing_wait = port->closing_wait * HZ/100;
2034 tmp.custom_divisor = port->custom_divisor;
2035 tmp.xmit_fifo_size = CD186x_NFIFO;
2036 if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
2037 func_exit();
2038 return -EFAULT;
2039 }
2040
2041 func_exit();
2042 return 0;
2043}
2044
2045
d61780c0 2046static int sx_ioctl(struct tty_struct * tty, struct file * filp,
1da177e4
LT
2047 unsigned int cmd, unsigned long arg)
2048{
2049 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2050 int retval;
2051 void __user *argp = (void __user *)arg;
2052
2053 func_enter();
2054
2055 if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
2056 func_exit();
2057 return -ENODEV;
2058 }
d61780c0 2059
1da177e4
LT
2060 switch (cmd) {
2061 case TCSBRK: /* SVID version: non-zero arg --> no break */
2062 retval = tty_check_change(tty);
2063 if (retval) {
2064 func_exit();
2065 return retval;
2066 }
2067 tty_wait_until_sent(tty, 0);
2068 if (!arg)
2069 sx_send_break(port, HZ/4); /* 1/4 second */
2070 return 0;
2071 case TCSBRKP: /* support for POSIX tcsendbreak() */
2072 retval = tty_check_change(tty);
2073 if (retval) {
2074 func_exit();
2075 return retval;
2076 }
2077 tty_wait_until_sent(tty, 0);
2078 sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
2079 func_exit();
2080 return 0;
2081 case TIOCGSOFTCAR:
2082 if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) {
2083 func_exit();
2084 return -EFAULT;
2085 }
2086 func_exit();
2087 return 0;
2088 case TIOCSSOFTCAR:
2089 if (get_user(arg, (unsigned long __user *) argp)) {
2090 func_exit();
2091 return -EFAULT;
2092 }
2093 tty->termios->c_cflag =
2094 ((tty->termios->c_cflag & ~CLOCAL) |
2095 (arg ? CLOCAL : 0));
2096 func_exit();
2097 return 0;
2098 case TIOCGSERIAL:
2099 func_exit();
2100 return sx_get_serial_info(port, argp);
d61780c0 2101 case TIOCSSERIAL:
1da177e4
LT
2102 func_exit();
2103 return sx_set_serial_info(port, argp);
2104 default:
2105 func_exit();
2106 return -ENOIOCTLCMD;
2107 }
2108 func_exit();
2109 return 0;
2110}
2111
2112
2113static void sx_throttle(struct tty_struct * tty)
2114{
2115 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2116 struct specialix_board *bp;
2117 unsigned long flags;
2118
2119 func_enter();
2120
2121 if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
2122 func_exit();
2123 return;
2124 }
d61780c0 2125
1da177e4 2126 bp = port_Board(port);
d61780c0 2127
1da177e4 2128 /* Use DTR instead of RTS ! */
d61780c0 2129 if (SX_CRTSCTS (tty))
1da177e4
LT
2130 port->MSVR &= ~MSVR_DTR;
2131 else {
2132 /* Auch!!! I think the system shouldn't call this then. */
2133 /* Or maybe we're supposed (allowed?) to do our side of hw
d61780c0 2134 handshake anyway, even when hardware handshake is off.
1da177e4
LT
2135 When you see this in your logs, please report.... */
2136 printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
2137 port_No (port));
2138 }
2139 spin_lock_irqsave(&bp->lock, flags);
2140 sx_out(bp, CD186x_CAR, port_No(port));
2141 spin_unlock_irqrestore(&bp->lock, flags);
2142 if (I_IXOFF(tty)) {
2143 spin_unlock_irqrestore(&bp->lock, flags);
2144 sx_wait_CCR(bp);
2145 spin_lock_irqsave(&bp->lock, flags);
2146 sx_out(bp, CD186x_CCR, CCR_SSCH2);
2147 spin_unlock_irqrestore(&bp->lock, flags);
2148 sx_wait_CCR(bp);
2149 }
2150 spin_lock_irqsave(&bp->lock, flags);
2151 sx_out(bp, CD186x_MSVR, port->MSVR);
2152 spin_unlock_irqrestore(&bp->lock, flags);
2153
2154 func_exit();
2155}
2156
2157
2158static void sx_unthrottle(struct tty_struct * tty)
2159{
2160 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2161 struct specialix_board *bp;
2162 unsigned long flags;
2163
2164 func_enter();
d61780c0 2165
1da177e4
LT
2166 if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
2167 func_exit();
2168 return;
2169 }
d61780c0 2170
1da177e4 2171 bp = port_Board(port);
d61780c0 2172
1da177e4
LT
2173 spin_lock_irqsave(&port->lock, flags);
2174 /* XXXX Use DTR INSTEAD???? */
2175 if (SX_CRTSCTS(tty)) {
2176 port->MSVR |= MSVR_DTR;
2177 } /* Else clause: see remark in "sx_throttle"... */
2178 spin_lock_irqsave(&bp->lock, flags);
2179 sx_out(bp, CD186x_CAR, port_No(port));
2180 spin_unlock_irqrestore(&bp->lock, flags);
2181 if (I_IXOFF(tty)) {
2182 spin_unlock_irqrestore(&port->lock, flags);
2183 sx_wait_CCR(bp);
2184 spin_lock_irqsave(&bp->lock, flags);
2185 sx_out(bp, CD186x_CCR, CCR_SSCH1);
2186 spin_unlock_irqrestore(&bp->lock, flags);
2187 sx_wait_CCR(bp);
2188 spin_lock_irqsave(&port->lock, flags);
2189 }
2190 spin_lock_irqsave(&bp->lock, flags);
2191 sx_out(bp, CD186x_MSVR, port->MSVR);
2192 spin_unlock_irqrestore(&bp->lock, flags);
2193 spin_unlock_irqrestore(&port->lock, flags);
2194
2195 func_exit();
2196}
2197
2198
2199static void sx_stop(struct tty_struct * tty)
2200{
2201 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2202 struct specialix_board *bp;
2203 unsigned long flags;
2204
2205 func_enter();
d61780c0 2206
1da177e4
LT
2207 if (sx_paranoia_check(port, tty->name, "sx_stop")) {
2208 func_exit();
2209 return;
2210 }
2211
2212 bp = port_Board(port);
d61780c0 2213
1da177e4
LT
2214 spin_lock_irqsave(&port->lock, flags);
2215 port->IER &= ~IER_TXRDY;
2216 spin_lock_irqsave(&bp->lock, flags);
2217 sx_out(bp, CD186x_CAR, port_No(port));
2218 sx_out(bp, CD186x_IER, port->IER);
2219 spin_unlock_irqrestore(&bp->lock, flags);
2220 spin_unlock_irqrestore(&port->lock, flags);
2221
2222 func_exit();
2223}
2224
2225
2226static void sx_start(struct tty_struct * tty)
2227{
2228 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2229 struct specialix_board *bp;
2230 unsigned long flags;
2231
2232 func_enter();
d61780c0 2233
1da177e4
LT
2234 if (sx_paranoia_check(port, tty->name, "sx_start")) {
2235 func_exit();
2236 return;
2237 }
d61780c0 2238
1da177e4 2239 bp = port_Board(port);
d61780c0 2240
1da177e4
LT
2241 spin_lock_irqsave(&port->lock, flags);
2242 if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
2243 port->IER |= IER_TXRDY;
2244 spin_lock_irqsave(&bp->lock, flags);
2245 sx_out(bp, CD186x_CAR, port_No(port));
2246 sx_out(bp, CD186x_IER, port->IER);
2247 spin_unlock_irqrestore(&bp->lock, flags);
2248 }
2249 spin_unlock_irqrestore(&port->lock, flags);
2250
2251 func_exit();
2252}
2253
2254
2255/*
2256 * This routine is called from the work-queue when the interrupt
2257 * routine has signalled that a hangup has occurred. The path of
2258 * hangup processing is:
2259 *
2260 * serial interrupt routine -> (workqueue) ->
2261 * do_sx_hangup() -> tty->hangup() -> sx_hangup()
d61780c0 2262 *
1da177e4 2263 */
c4028958 2264static void do_sx_hangup(struct work_struct *work)
1da177e4 2265{
c4028958
DH
2266 struct specialix_port *port =
2267 container_of(work, struct specialix_port, tqueue_hangup);
1da177e4 2268 struct tty_struct *tty;
d61780c0 2269
1da177e4
LT
2270 func_enter();
2271
2272 tty = port->tty;
2273 if (tty)
2274 tty_hangup(tty); /* FIXME: module removal race here */
2275
2276 func_exit();
2277}
2278
2279
2280static void sx_hangup(struct tty_struct * tty)
2281{
2282 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2283 struct specialix_board *bp;
2284 unsigned long flags;
2285
2286 func_enter();
2287
2288 if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
2289 func_exit();
2290 return;
2291 }
d61780c0 2292
1da177e4 2293 bp = port_Board(port);
d61780c0 2294
1da177e4
LT
2295 sx_shutdown_port(bp, port);
2296 spin_lock_irqsave(&port->lock, flags);
2297 port->event = 0;
2298 bp->count -= port->count;
2299 if (bp->count < 0) {
2300 printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n",
2301 board_No(bp), bp->count, tty->index);
2302 bp->count = 0;
2303 }
2304 port->count = 0;
2305 port->flags &= ~ASYNC_NORMAL_ACTIVE;
2306 port->tty = NULL;
2307 spin_unlock_irqrestore(&port->lock, flags);
2308 wake_up_interruptible(&port->open_wait);
2309
2310 func_exit();
2311}
2312
2313
2314static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios)
2315{
2316 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2317 unsigned long flags;
2318 struct specialix_board * bp;
d61780c0 2319
1da177e4
LT
2320 if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
2321 return;
d61780c0 2322
1da177e4
LT
2323 if (tty->termios->c_cflag == old_termios->c_cflag &&
2324 tty->termios->c_iflag == old_termios->c_iflag)
2325 return;
2326
2327 bp = port_Board(port);
2328 spin_lock_irqsave(&port->lock, flags);
2329 sx_change_speed(port_Board(port), port);
2330 spin_unlock_irqrestore(&port->lock, flags);
2331
2332 if ((old_termios->c_cflag & CRTSCTS) &&
2333 !(tty->termios->c_cflag & CRTSCTS)) {
2334 tty->hw_stopped = 0;
2335 sx_start(tty);
2336 }
2337}
2338
2339
c4028958 2340static void do_softint(struct work_struct *work)
1da177e4 2341{
c4028958
DH
2342 struct specialix_port *port =
2343 container_of(work, struct specialix_port, tqueue);
1da177e4
LT
2344 struct tty_struct *tty;
2345
2346 func_enter();
2347
2348 if(!(tty = port->tty)) {
2349 func_exit();
2350 return;
2351 }
2352
2353 if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
2354 tty_wakeup(tty);
2355 //wake_up_interruptible(&tty->write_wait);
2356 }
2357
2358 func_exit();
2359}
2360
b68e31d0 2361static const struct tty_operations sx_ops = {
1da177e4
LT
2362 .open = sx_open,
2363 .close = sx_close,
2364 .write = sx_write,
2365 .put_char = sx_put_char,
2366 .flush_chars = sx_flush_chars,
2367 .write_room = sx_write_room,
2368 .chars_in_buffer = sx_chars_in_buffer,
2369 .flush_buffer = sx_flush_buffer,
2370 .ioctl = sx_ioctl,
2371 .throttle = sx_throttle,
2372 .unthrottle = sx_unthrottle,
2373 .set_termios = sx_set_termios,
2374 .stop = sx_stop,
2375 .start = sx_start,
2376 .hangup = sx_hangup,
2377 .tiocmget = sx_tiocmget,
2378 .tiocmset = sx_tiocmset,
2379};
2380
2381static int sx_init_drivers(void)
2382{
2383 int error;
2384 int i;
2385
2386 func_enter();
2387
2388 specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
2389 if (!specialix_driver) {
2390 printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
2391 func_exit();
2392 return 1;
2393 }
d61780c0 2394
1da177e4
LT
2395 specialix_driver->owner = THIS_MODULE;
2396 specialix_driver->name = "ttyW";
2397 specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
2398 specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
2399 specialix_driver->subtype = SERIAL_TYPE_NORMAL;
2400 specialix_driver->init_termios = tty_std_termios;
2401 specialix_driver->init_termios.c_cflag =
2402 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2403 specialix_driver->flags = TTY_DRIVER_REAL_RAW;
2404 tty_set_operations(specialix_driver, &sx_ops);
2405
2406 if ((error = tty_register_driver(specialix_driver))) {
2407 put_tty_driver(specialix_driver);
1da177e4
LT
2408 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2409 error);
2410 func_exit();
2411 return 1;
2412 }
2413 memset(sx_port, 0, sizeof(sx_port));
2414 for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
2415 sx_port[i].magic = SPECIALIX_MAGIC;
c4028958
DH
2416 INIT_WORK(&sx_port[i].tqueue, do_softint);
2417 INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup);
1da177e4
LT
2418 sx_port[i].close_delay = 50 * HZ/100;
2419 sx_port[i].closing_wait = 3000 * HZ/100;
2420 init_waitqueue_head(&sx_port[i].open_wait);
2421 init_waitqueue_head(&sx_port[i].close_wait);
2422 spin_lock_init(&sx_port[i].lock);
2423 }
d61780c0 2424
1da177e4
LT
2425 func_exit();
2426 return 0;
2427}
2428
2429static void sx_release_drivers(void)
2430{
2431 func_enter();
2432
1da177e4
LT
2433 tty_unregister_driver(specialix_driver);
2434 put_tty_driver(specialix_driver);
2435 func_exit();
2436}
2437
d61780c0
JG
2438/*
2439 * This routine must be called by kernel at boot time
1da177e4
LT
2440 */
2441static int __init specialix_init(void)
2442{
2443 int i;
2444 int found = 0;
2445
2446 func_enter();
2447
2448 printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
2449 printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2450#ifdef CONFIG_SPECIALIX_RTSCTS
2451 printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
2452#else
2453 printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2454#endif
d61780c0 2455
1da177e4 2456 for (i = 0; i < SX_NBOARD; i++)
34af946a 2457 spin_lock_init(&sx_board[i].lock);
1da177e4
LT
2458
2459 if (sx_init_drivers()) {
2460 func_exit();
2461 return -EIO;
2462 }
2463
d61780c0 2464 for (i = 0; i < SX_NBOARD; i++)
1da177e4
LT
2465 if (sx_board[i].base && !sx_probe(&sx_board[i]))
2466 found++;
2467
2468#ifdef CONFIG_PCI
2469 {
2470 struct pci_dev *pdev = NULL;
2471
2472 i=0;
2473 while (i < SX_NBOARD) {
2474 if (sx_board[i].flags & SX_BOARD_PRESENT) {
2475 i++;
2476 continue;
2477 }
d61780c0
JG
2478 pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
2479 PCI_DEVICE_ID_SPECIALIX_IO8,
1da177e4
LT
2480 pdev);
2481 if (!pdev) break;
2482
2483 if (pci_enable_device(pdev))
2484 continue;
2485
2486 sx_board[i].irq = pdev->irq;
2487
2488 sx_board[i].base = pci_resource_start (pdev, 2);
2489
2490 sx_board[i].flags |= SX_BOARD_IS_PCI;
2491 if (!sx_probe(&sx_board[i]))
2492 found ++;
2493 }
2494 }
2495#endif
2496
2497 if (!found) {
2498 sx_release_drivers();
2499 printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
2500 func_exit();
2501 return -EIO;
2502 }
2503
2504 func_exit();
2505 return 0;
2506}
2507
2508static int iobase[SX_NBOARD] = {0,};
2509
2510static int irq [SX_NBOARD] = {0,};
2511
2512module_param_array(iobase, int, NULL, 0);
2513module_param_array(irq, int, NULL, 0);
2514module_param(sx_debug, int, 0);
2515module_param(sx_rxfifo, int, 0);
2516#ifdef SPECIALIX_TIMER
2517module_param(sx_poll, int, 0);
2518#endif
2519
2520/*
2521 * You can setup up to 4 boards.
2522 * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
d61780c0
JG
2523 * You should specify the IRQs too in that case "irq=....,...".
2524 *
1da177e4 2525 * More than 4 boards in one computer is not possible, as the card can
d61780c0 2526 * only use 4 different interrupts.
1da177e4
LT
2527 *
2528 */
2529static int __init specialix_init_module(void)
2530{
2531 int i;
2532
2533 func_enter();
2534
1da177e4
LT
2535 if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
2536 for(i = 0; i < SX_NBOARD; i++) {
2537 sx_board[i].base = iobase[i];
2538 sx_board[i].irq = irq[i];
2539 sx_board[i].count= 0;
2540 }
2541 }
2542
2543 func_exit();
2544
2545 return specialix_init();
2546}
d61780c0 2547
1da177e4
LT
2548static void __exit specialix_exit_module(void)
2549{
2550 int i;
d61780c0 2551
1da177e4
LT
2552 func_enter();
2553
2554 sx_release_drivers();
2555 for (i = 0; i < SX_NBOARD; i++)
d61780c0 2556 if (sx_board[i].flags & SX_BOARD_PRESENT)
1da177e4
LT
2557 sx_release_io_range(&sx_board[i]);
2558#ifdef SPECIALIX_TIMER
2559 del_timer (&missed_irq_timer);
2560#endif
2561
2562 func_exit();
2563}
2564
7691030b
CS
2565static struct pci_device_id specialx_pci_tbl[] __devinitdata = {
2566 { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
2567 { }
2568};
2569MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
2570
1da177e4
LT
2571module_init(specialix_init_module);
2572module_exit(specialix_exit_module);
2573
2574MODULE_LICENSE("GPL");