2 * specialix.c -- specialix IO8+ multiport serial driver.
4 * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
5 * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com)
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)
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.
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.
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.
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.
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,
39 * Revision 1.0: April 1st 1997.
40 * Initial release for alpha testing.
41 * Revision 1.1: April 14th 1997.
42 * Incorporated Richard Hudsons suggestions,
43 * removed some debugging printk's.
44 * Revision 1.2: April 15th 1997.
45 * Ported to 2.1.x kernels.
46 * Revision 1.3: April 17th 1997
47 * Backported to 2.0. (Compatibility macros).
48 * Revision 1.4: April 18th 1997
49 * Fixed DTR/RTS bug that caused the card to indicate
50 * "don't send data" to a modem after the password prompt.
51 * Fixed bug for premature (fake) interrupts.
52 * Revision 1.5: April 19th 1997
53 * fixed a minor typo in the header file, cleanup a little.
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.
63 * Revision 1.10: Oct 22 1999 / Jan 21 2000.
64 * Added stuff for setserial.
65 * Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
69 #define VERSION "1.11"
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
78 #include <linux/module.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>
87 #include <linux/tty_flip.h>
89 #include <linux/serial.h>
90 #include <linux/fcntl.h>
91 #include <linux/major.h>
92 #include <linux/delay.h>
93 #include <linux/pci.h>
94 #include <linux/init.h>
95 #include <asm/uaccess.h>
97 #include "specialix_io8.h"
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
112 static int sx_rxfifo = SPECIALIX_RXFIFO;
115 #define dprintk(f, str...) if (sx_debug & f) printk (str)
117 #define dprintk(f, str...) /* nothing */
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
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__)
137 #define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
140 /* Configurable options: */
142 /* Am I paranoid or not ? ;-) */
143 #define SPECIALIX_PARANOIA_CHECK
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
150 #ifdef SPECIALIX_TIMER
151 static int sx_poll = HZ;
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.
160 #undef SX_REPORT_FIFO
161 #undef SX_REPORT_OVERRUN
165 #ifdef CONFIG_SPECIALIX_RTSCTS
166 #define SX_CRTSCTS(bla) 1
168 #define SX_CRTSCTS(tty) C_CRTSCTS(tty)
172 /* Used to be outb (0xff, 0x80); */
173 #define short_pause() udelay (1)
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)
181 #undef RS_EVENT_WRITE_WAKEUP
182 #define RS_EVENT_WRITE_WAKEUP 0
184 static struct tty_driver *specialix_driver;
186 static 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, },
193 static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
196 #ifdef SPECIALIX_TIMER
197 static struct timer_list missed_irq_timer;
198 static irqreturn_t sx_interrupt(int irq, void * dev_id);
203 static inline int sx_paranoia_check(struct specialix_port const * port,
204 char *name, const char *routine)
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";
213 printk(badinfo, name, routine);
216 if (port->magic != SPECIALIX_MAGIC) {
217 printk(badmagic, name, routine);
227 * Service functions for specialix IO8+ driver.
231 /* Get board number from pointer */
232 static inline int board_No (struct specialix_board * bp)
234 return bp - sx_board;
238 /* Get port number from pointer */
239 static inline int port_No (struct specialix_port const * port)
241 return SX_PORT(port - sx_port);
245 /* Get pointer to board from pointer to port */
246 static inline struct specialix_board * port_Board(struct specialix_port const * port)
248 return &sx_board[SX_BOARD(port - sx_port)];
252 /* Input Byte from CL CD186x register */
253 static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
255 bp->reg = reg | 0x80;
256 outb (reg | 0x80, bp->base + SX_ADDR_REG);
257 return inb (bp->base + SX_DATA_REG);
261 /* Output Byte to CL CD186x register */
262 static inline void sx_out(struct specialix_board * bp, unsigned short reg,
265 bp->reg = reg | 0x80;
266 outb (reg | 0x80, bp->base + SX_ADDR_REG);
267 outb (val, bp->base + SX_DATA_REG);
271 /* Input Byte from CL CD186x register */
272 static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
275 outb (reg, bp->base + SX_ADDR_REG);
276 return inb (bp->base + SX_DATA_REG);
280 /* Output Byte to CL CD186x register */
281 static inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
285 outb (reg, bp->base + SX_ADDR_REG);
286 outb (val, bp->base + SX_DATA_REG);
290 /* Wait for Channel Command Register ready */
291 static inline void sx_wait_CCR(struct specialix_board * bp)
293 unsigned long delay, flags;
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);
305 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
309 /* Wait for Channel Command Register ready */
310 static inline void sx_wait_CCR_off(struct specialix_board * bp)
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);
325 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
330 * specialix IO8+ IO range functions.
333 static inline int sx_request_io_range(struct specialix_board * bp)
335 return request_region(bp->base,
336 bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
337 "specialix IO8+") == NULL;
341 static inline void sx_release_io_range(struct specialix_board * bp)
343 release_region(bp->base,
344 bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
348 /* Must be called with enabled interrupts */
349 /* Ugly. Very ugly. Don't use this for anything else than initialization
351 static inline void sx_long_delay(unsigned long delay)
355 for (i = jiffies + delay; time_after(i, jiffies); ) ;
360 /* Set the IRQ using the RTS lines that run to the PAL on the board.... */
361 static int sx_set_irq ( struct specialix_board *bp)
367 if (bp->flags & SX_BOARD_IS_PCI)
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);
378 spin_lock_irqsave(&bp->lock, flags);
380 sx_out(bp, CD186x_CAR, i);
381 sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
383 spin_unlock_irqrestore(&bp->lock, flags);
388 /* Reset and setup CD186x chip */
389 static int sx_init_CD186x(struct specialix_board * bp)
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 */
408 sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
410 /* Setting up prescaler. We need 4 ticks per 1 ms */
411 scaler = SX_OSCFREQ/SPECIALIX_TPS;
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);
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);
428 static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
434 spin_lock_irqsave(&bp->lock, flags);
435 for (i=0, t=0;i<8;i++) {
436 sx_out_off (bp, CD186x_CAR, i);
437 if (sx_in_off (bp, reg) & bit)
440 spin_unlock_irqrestore(&bp->lock, flags);
446 #ifdef SPECIALIX_TIMER
447 void missed_irq (unsigned long data)
451 struct specialix_board *bp = (struct specialix_board *)data;
453 spin_lock_irqsave(&bp->lock, flags);
454 irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) &
458 spin_unlock_irqrestore(&bp->lock, flags);
460 printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
461 sx_interrupt (((struct specialix_board *)data)->irq,
464 missed_irq_timer.expires = jiffies + sx_poll;
465 add_timer (&missed_irq_timer);
471 /* Main probing routine, also sets irq. */
472 static int sx_probe(struct specialix_board *bp)
474 unsigned char val1, val2;
484 if (sx_request_io_range(bp)) {
489 /* Are the I/O ports here ? */
490 sx_out_off(bp, CD186x_PPRL, 0x5a);
492 val1 = sx_in_off(bp, CD186x_PPRL);
494 sx_out_off(bp, CD186x_PPRL, 0xa5);
496 val2 = sx_in_off(bp, CD186x_PPRL);
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);
502 sx_release_io_range(bp);
507 /* Check the DSR lines that Specialix uses as board
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);
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
518 val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
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);
522 sx_release_io_range(bp);
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 */
535 sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
536 sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
537 sx_long_delay(HZ/20);
538 irqs = probe_irq_off(irqs);
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");
546 /* Reset CD186x again */
547 if (!sx_init_CD186x(bp)) {
548 /* Hmmm. This is dead code anyway. */
551 dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
558 printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
559 board_No(bp), bp->base);
560 sx_release_io_range(bp);
565 printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
569 /* Reset CD186x again */
570 if (!sx_init_CD186x(bp)) {
571 sx_release_io_range(bp);
576 sx_request_io_range(bp);
577 bp->flags |= SX_BOARD_PRESENT;
579 /* Chip revcode pkgtype
584 CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
586 -- Thanks to Gwen Wang, Cirrus Logic.
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';
597 dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
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);
607 printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
618 * Interrupt processing routines.
621 static inline void sx_mark_event(struct specialix_port * port, int event)
625 set_bit(event, &port->event);
626 schedule_work(&port->tqueue);
632 static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
633 unsigned char const * what)
635 unsigned char channel;
636 struct specialix_port * port = NULL;
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);
644 if (port->flags & ASYNC_INITIALIZED) {
645 dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
650 printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
651 board_No(bp), what, channel);
656 static inline void sx_receive_exc(struct specialix_board * bp)
658 struct specialix_port *port;
659 struct tty_struct *tty;
660 unsigned char status;
661 unsigned char ch, flag;
665 port = sx_get_port(bp, "Receive");
667 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
673 status = sx_in(bp, CD186x_RCSR);
675 dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
676 if (status & RCSR_OE) {
678 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
679 board_No(bp), port_No(port), port->overrun);
681 status &= port->mark_mask;
683 /* This flip buffer check needs to be below the reading of the
684 status register to reset the chip's IRQ.... */
685 if (tty_buffer_request_room(tty, 1) == 0) {
686 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
687 board_No(bp), port_No(port));
692 ch = sx_in(bp, CD186x_RDR);
697 if (status & RCSR_TOUT) {
698 printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
699 board_No(bp), port_No(port));
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));
707 if (port->flags & ASYNC_SAK)
710 } else if (status & RCSR_PE)
713 else if (status & RCSR_FE)
716 else if (status & RCSR_OE)
722 if(tty_insert_flip_char(tty, ch, flag))
723 tty_flip_buffer_push(tty);
728 static inline void sx_receive(struct specialix_board * bp)
730 struct specialix_port *port;
731 struct tty_struct *tty;
736 if (!(port = sx_get_port(bp, "Receive"))) {
737 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
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]++;
747 tty_buffer_request_room(tty, count);
750 tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
751 tty_flip_buffer_push(tty);
756 static inline void sx_transmit(struct specialix_board * bp)
758 struct specialix_port *port;
759 struct tty_struct *tty;
763 if (!(port = sx_get_port(bp, "Transmit"))) {
767 dprintk (SX_DEBUG_TX, "port: %p\n", port);
770 if (port->IER & IER_TXEMPTY) {
772 sx_out(bp, CD186x_CAR, port_No(port));
773 port->IER &= ~IER_TXEMPTY;
774 sx_out(bp, CD186x_IER, port->IER);
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);
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;
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--;
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);
806 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
807 port->break_length = 0;
814 count = CD186x_NFIFO;
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)
820 } while (--count > 0);
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);
827 if (port->xmit_cnt <= port->wakeup_chars)
828 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
834 static inline void sx_check_modem(struct specialix_board * bp)
836 struct specialix_port *port;
837 struct tty_struct *tty;
841 dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
842 if (!(port = sx_get_port(bp, "Modem")))
847 mcr = sx_in(bp, CD186x_MCR);
848 printk ("mcr = %02x.\n", mcr);
850 if ((mcr & MCR_CDCHG)) {
851 dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
852 msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
854 dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
855 wake_up_interruptible(&port->open_wait);
857 dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
858 schedule_work(&port->tqueue_hangup);
862 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
863 if (mcr & MCR_CTSCHG) {
864 if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
866 port->IER |= IER_TXRDY;
867 if (port->xmit_cnt <= port->wakeup_chars)
868 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
871 port->IER &= ~IER_TXRDY;
873 sx_out(bp, CD186x_IER, port->IER);
875 if (mcr & MCR_DSSXHG) {
876 if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
878 port->IER |= IER_TXRDY;
879 if (port->xmit_cnt <= port->wakeup_chars)
880 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
883 port->IER &= ~IER_TXRDY;
885 sx_out(bp, CD186x_IER, port->IER);
887 #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
889 /* Clear change bits */
890 sx_out(bp, CD186x_MCR, 0);
894 /* The main interrupt processing routine */
895 static irqreturn_t sx_interrupt(int irq, void *dev_id)
897 unsigned char status;
899 struct specialix_board *bp;
900 unsigned long loop = 0;
907 spin_lock_irqsave(&bp->lock, flags);
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);
910 if (!(bp->flags & SX_BOARD_ACTIVE)) {
911 dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
912 spin_unlock_irqrestore(&bp->lock, flags);
919 while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
923 if (status & SRSR_RREQint) {
924 ack = sx_in(bp, CD186x_RRAR);
926 if (ack == (SX_ID | GIVR_IT_RCV))
928 else if (ack == (SX_ID | GIVR_IT_REXC))
931 printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
932 board_No(bp), status, ack);
934 } else if (status & SRSR_TREQint) {
935 ack = sx_in(bp, CD186x_TRAR);
937 if (ack == (SX_ID | GIVR_IT_TX))
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);
945 if (ack == (SX_ID | GIVR_IT_MODEM))
948 printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
949 board_No(bp), status, ack);
953 sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
956 outb (bp->reg, bp->base + SX_ADDR_REG);
957 spin_unlock_irqrestore(&bp->lock, flags);
964 * Routines for open & close processing.
967 static void turn_ints_off (struct specialix_board *bp)
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. */
979 spin_lock_irqsave(&bp->lock, flags);
980 (void) sx_in_off (bp, 0); /* Turn off interrupts. */
981 spin_unlock_irqrestore(&bp->lock, flags);
986 static void turn_ints_on (struct specialix_board *bp)
992 if (bp->flags & SX_BOARD_IS_PCI) {
993 /* play with the PCI chip. See comment above. */
995 spin_lock_irqsave(&bp->lock, flags);
996 (void) sx_in (bp, 0); /* Turn ON interrupts. */
997 spin_unlock_irqrestore(&bp->lock, flags);
1003 /* Called with disabled interrupts */
1004 static inline int sx_setup_board(struct specialix_board * bp)
1008 if (bp->flags & SX_BOARD_ACTIVE)
1011 if (bp->flags & SX_BOARD_IS_PCI)
1012 error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
1014 error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp);
1020 bp->flags |= SX_BOARD_ACTIVE;
1026 /* Called with disabled interrupts */
1027 static inline void sx_shutdown_board(struct specialix_board *bp)
1031 if (!(bp->flags & SX_BOARD_ACTIVE)) {
1036 bp->flags &= ~SX_BOARD_ACTIVE;
1038 dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
1039 bp->irq, board_No (bp));
1040 free_irq(bp->irq, bp);
1050 * Setting up port characteristics.
1051 * Must be called with disabled interrupts
1053 static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
1055 struct tty_struct *tty;
1058 unsigned char cor1 = 0, cor3 = 0;
1059 unsigned char mcor1 = 0, mcor2 = 0;
1060 static unsigned long again;
1061 unsigned long flags;
1065 if (!(tty = port->tty) || !tty->termios) {
1072 /* Select port on the board */
1073 spin_lock_irqsave(&bp->lock, flags);
1074 sx_out(bp, CD186x_CAR, port_No(port));
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);
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);
1084 baud = tty_get_baud_rate(tty);
1086 if (baud == 38400) {
1087 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1089 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
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);
1103 dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
1107 if (!SX_CRTSCTS (tty)) {
1108 port ->MSVR |= MSVR_DTR;
1113 * Now we must calculate some speed depended things
1116 /* Set baud rate for port */
1117 tmp = port->custom_divisor ;
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);
1123 tmp = (((SX_OSCFREQ + baud/2) / baud +
1124 CD186x_TPC/2) / CD186x_TPC);
1126 if ((tmp < 0x10) && time_before(again, jiffies)) {
1127 again = jiffies + HZ * 60;
1128 /* Page 48 of version 2.0 of the CL-CD1865 databook */
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);
1135 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1136 "Warning: overstressing Cirrus chip. "
1137 "This might not work.\n"
1138 "Read specialix.txt for more info.\n",
1139 port_No (port), tmp);
1142 spin_lock_irqsave(&bp->lock, flags);
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);
1146 sx_out(bp, CD186x_TBPRL, tmp & 0xff);
1147 spin_unlock_irqrestore(&bp->lock, flags);
1148 if (port->custom_divisor)
1149 baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
1150 baud = (baud + 5) / 10; /* Estimated CPS */
1152 /* Two timer ticks seems enough to wakeup something like SLIP driver */
1153 tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
1154 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
1155 SERIAL_XMIT_SIZE - 1 : tmp);
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)) {
1181 cor1 |= COR1_IGNORE;
1182 if (C_PARENB(tty)) {
1183 cor1 |= COR1_NORMPAR;
1187 cor1 &= ~COR1_IGNORE;
1189 /* Set marking of some errors */
1190 port->mark_mask = RCSR_OE | RCSR_TOUT;
1192 port->mark_mask |= RCSR_FE | RCSR_PE;
1193 if (I_BRKINT(tty) || I_PARMRK(tty))
1194 port->mark_mask |= RCSR_BREAK;
1196 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
1197 if (I_IGNBRK(tty)) {
1198 port->mark_mask &= ~RCSR_BREAK;
1200 /* Real raw mode. Ignore all */
1201 port->mark_mask &= ~RCSR_OE;
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);
1213 port->COR2 |= COR2_CTSAE;
1216 /* Enable Software Flow Control. FIXME: I'm not sure about this */
1217 /* Some people reported that it works, but I still doubt it */
1219 port->COR2 |= COR2_TXIBE;
1220 cor3 |= (COR3_FCT | COR3_SCDE);
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);
1230 if (!C_CLOCAL(tty)) {
1231 /* Enable CD check */
1232 port->IER |= IER_CD;
1233 mcor1 |= MCOR1_CDZD;
1234 mcor2 |= MCOR2_CDOD;
1238 /* Enable receiver */
1239 port->IER |= IER_RXD;
1241 /* Set input FIFO size (1-8 bytes) */
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 */
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 */
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);
1272 /* Must be called with interrupts enabled */
1273 static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
1275 unsigned long flags;
1279 if (port->flags & ASYNC_INITIALIZED) {
1284 if (!port->xmit_buf) {
1285 /* We may sleep in get_zeroed_page() */
1288 if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
1293 if (port->xmit_buf) {
1296 return -ERESTARTSYS;
1298 port->xmit_buf = (unsigned char *) tmp;
1301 spin_lock_irqsave(&port->lock, flags);
1304 clear_bit(TTY_IO_ERROR, &port->tty->flags);
1306 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1307 sx_change_speed(bp, port);
1308 port->flags |= ASYNC_INITIALIZED;
1310 spin_unlock_irqrestore(&port->lock, flags);
1318 /* Must be called with interrupts disabled */
1319 static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
1321 struct tty_struct *tty;
1323 unsigned long flags;
1327 if (!(port->flags & ASYNC_INITIALIZED)) {
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]);
1338 dprintk(SX_DEBUG_FIFO, "].\n");
1341 if (port->xmit_buf) {
1342 free_page((unsigned long) port->xmit_buf);
1343 port->xmit_buf = NULL;
1347 spin_lock_irqsave(&bp->lock, flags);
1348 sx_out(bp, CD186x_CAR, port_No(port));
1350 if (!(tty = port->tty) || C_HUPCL(tty)) {
1352 sx_out(bp, CD186x_MSVDTR, 0);
1354 spin_unlock_irqrestore(&bp->lock, flags);
1357 spin_lock_irqsave(&bp->lock, flags);
1358 sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
1359 /* Disable all interrupts from this port */
1361 sx_out(bp, CD186x_IER, port->IER);
1362 spin_unlock_irqrestore(&bp->lock, flags);
1364 set_bit(TTY_IO_ERROR, &tty->flags);
1365 port->flags &= ~ASYNC_INITIALIZED;
1368 sx_shutdown_board(bp);
1373 static int block_til_ready(struct tty_struct *tty, struct file * filp,
1374 struct specialix_port *port)
1376 DECLARE_WAITQUEUE(wait, current);
1377 struct specialix_board *bp = port_Board(port);
1381 unsigned long flags;
1386 * If the device is in the middle of being closed, then block
1387 * until it's done, and then try again.
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) {
1396 return -ERESTARTSYS;
1401 * If non-blocking mode is set, or the port is not enabled,
1402 * then make the check up front and then exit.
1404 if ((filp->f_flags & O_NONBLOCK) ||
1405 (tty->flags & (1 << TTY_IO_ERROR))) {
1406 port->flags |= ASYNC_NORMAL_ACTIVE;
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.
1422 add_wait_queue(&port->open_wait, &wait);
1423 spin_lock_irqsave(&port->lock, flags);
1424 if (!tty_hung_up_p(filp)) {
1427 spin_unlock_irqrestore(&port->lock, flags);
1428 port->blocked_open++;
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)) {
1435 port->MSVR |= MSVR_DTR; /* WTF? */
1436 sx_out (bp, CD186x_MSVR, port->MSVR);
1439 port->MSVR |= MSVR_DTR;
1440 sx_out (bp, CD186x_MSVR, port->MSVR);
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)
1449 retval = -ERESTARTSYS;
1452 if (!(port->flags & ASYNC_CLOSING) &&
1455 if (signal_pending(current)) {
1456 retval = -ERESTARTSYS;
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)) {
1468 port->blocked_open--;
1469 spin_unlock_irqrestore(&port->lock, flags);
1475 port->flags |= ASYNC_NORMAL_ACTIVE;
1481 static int sx_open(struct tty_struct * tty, struct file * filp)
1485 struct specialix_port * port;
1486 struct specialix_board * bp;
1488 unsigned long flags;
1492 board = SX_BOARD(tty->index);
1494 if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
1499 bp = &sx_board[board];
1500 port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
1502 for (i = 0; i < 10; i++)
1505 dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
1506 board, bp, port, SX_PORT(tty->index));
1508 if (sx_paranoia_check(port, tty->name, "sx_open")) {
1513 if ((error = sx_setup_board(bp))) {
1518 spin_lock_irqsave(&bp->lock, flags);
1521 tty->driver_data = port;
1523 spin_unlock_irqrestore(&bp->lock, flags);
1525 if ((error = sx_setup_port(bp, port))) {
1530 if ((error = block_til_ready(tty, filp, port))) {
1540 static void sx_close(struct tty_struct * tty, struct file * filp)
1542 struct specialix_port *port = (struct specialix_port *) tty->driver_data;
1543 struct specialix_board *bp;
1544 unsigned long flags;
1545 unsigned long timeout;
1548 if (!port || sx_paranoia_check(port, tty->name, "close")) {
1552 spin_lock_irqsave(&port->lock, flags);
1554 if (tty_hung_up_p(filp)) {
1555 spin_unlock_irqrestore(&port->lock, flags);
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);
1568 if (port->count > 1) {
1572 spin_unlock_irqrestore(&port->lock, flags);
1577 port->flags |= ASYNC_CLOSING;
1579 * Now we wait for the transmit buffer to clear; and we notify
1580 * the line discipline to only process XON/XOFF characters.
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);
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.
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);
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!
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");
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);
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);
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);
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));
1644 wake_up_interruptible(&port->open_wait);
1646 port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1647 wake_up_interruptible(&port->close_wait);
1653 static int sx_write(struct tty_struct * tty,
1654 const unsigned char *buf, int count)
1656 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1657 struct specialix_board *bp;
1659 unsigned long flags;
1662 if (sx_paranoia_check(port, tty->name, "sx_write")) {
1667 bp = port_Board(port);
1669 if (!port->xmit_buf) {
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));
1679 spin_unlock_irqrestore(&port->lock, flags);
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);
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);
1699 spin_unlock_irqrestore(&bp->lock, flags);
1706 static void sx_put_char(struct tty_struct * tty, unsigned char ch)
1708 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1709 unsigned long flags;
1710 struct specialix_board * bp;
1714 if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
1718 dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
1719 if (!port->xmit_buf) {
1723 bp = port_Board(port);
1724 spin_lock_irqsave(&port->lock, flags);
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");
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;
1737 spin_unlock_irqrestore(&port->lock, flags);
1743 static void sx_flush_chars(struct tty_struct * tty)
1745 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1746 unsigned long flags;
1747 struct specialix_board * bp = port_Board(port);
1751 if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
1755 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
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);
1770 static int sx_write_room(struct tty_struct * tty)
1772 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1777 if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
1782 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1791 static int sx_chars_in_buffer(struct tty_struct *tty)
1793 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1797 if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
1802 return port->xmit_cnt;
1806 static void sx_flush_buffer(struct tty_struct *tty)
1808 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1809 unsigned long flags;
1810 struct specialix_board * bp;
1814 if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
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);
1829 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
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;
1839 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
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)) {
1853 result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
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);
1859 result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
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);
1872 static int sx_tiocmset(struct tty_struct *tty, struct file *file,
1873 unsigned int set, unsigned int clear)
1875 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1876 unsigned long flags;
1877 struct specialix_board *bp;
1881 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1886 bp = port_Board(port);
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; */
1894 if (SX_CRTSCTS(port->tty)) {
1895 if (set & TIOCM_RTS)
1896 port->MSVR |= MSVR_DTR;
1898 if (set & TIOCM_DTR)
1899 port->MSVR |= MSVR_DTR;
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;
1910 if (clear & TIOCM_DTR)
1911 port->MSVR &= ~MSVR_DTR;
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);
1923 static inline void sx_send_break(struct specialix_port * port, unsigned long length)
1925 struct specialix_board *bp = port_Board(port);
1926 unsigned long flags;
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);
1941 spin_lock_irqsave(&bp->lock, flags);
1942 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
1943 spin_unlock_irqrestore(&bp->lock, flags);
1950 static inline int sx_set_serial_info(struct specialix_port * port,
1951 struct serial_struct __user * newinfo)
1953 struct serial_struct tmp;
1954 struct specialix_board *bp = port_Board(port);
1959 if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) {
1964 if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
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)) {
1982 change_speed = ((port->flags & ASYNC_SPD_MASK) !=
1983 (tmp.flags & ASYNC_SPD_MASK));
1984 change_speed |= (tmp.custom_divisor != port->custom_divisor);
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))) {
1994 port->flags = ((port->flags & ~ASYNC_USR_MASK) |
1995 (tmp.flags & ASYNC_USR_MASK));
1996 port->custom_divisor = tmp.custom_divisor;
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;
2005 sx_change_speed(bp, port);
2012 static inline int sx_get_serial_info(struct specialix_port * port,
2013 struct serial_struct __user *retinfo)
2015 struct serial_struct tmp;
2016 struct specialix_board *bp = port_Board(port);
2021 if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
2025 memset(&tmp, 0, sizeof(tmp));
2026 tmp.type = PORT_CIRRUS;
2027 tmp.line = port - sx_port;
2028 tmp.port = bp->base;
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))) {
2046 static int sx_ioctl(struct tty_struct * tty, struct file * filp,
2047 unsigned int cmd, unsigned long arg)
2049 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2051 void __user *argp = (void __user *)arg;
2055 if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
2061 case TCSBRK: /* SVID version: non-zero arg --> no break */
2062 retval = tty_check_change(tty);
2067 tty_wait_until_sent(tty, 0);
2069 sx_send_break(port, HZ/4); /* 1/4 second */
2071 case TCSBRKP: /* support for POSIX tcsendbreak() */
2072 retval = tty_check_change(tty);
2077 tty_wait_until_sent(tty, 0);
2078 sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
2082 if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) {
2089 if (get_user(arg, (unsigned long __user *) argp)) {
2093 tty->termios->c_cflag =
2094 ((tty->termios->c_cflag & ~CLOCAL) |
2095 (arg ? CLOCAL : 0));
2100 return sx_get_serial_info(port, argp);
2103 return sx_set_serial_info(port, argp);
2106 return -ENOIOCTLCMD;
2113 static void sx_throttle(struct tty_struct * tty)
2115 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2116 struct specialix_board *bp;
2117 unsigned long flags;
2121 if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
2126 bp = port_Board(port);
2128 /* Use DTR instead of RTS ! */
2129 if (SX_CRTSCTS (tty))
2130 port->MSVR &= ~MSVR_DTR;
2132 /* Auch!!! I think the system shouldn't call this then. */
2133 /* Or maybe we're supposed (allowed?) to do our side of hw
2134 handshake anyway, even when hardware handshake is off.
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",
2139 spin_lock_irqsave(&bp->lock, flags);
2140 sx_out(bp, CD186x_CAR, port_No(port));
2141 spin_unlock_irqrestore(&bp->lock, flags);
2143 spin_unlock_irqrestore(&bp->lock, flags);
2145 spin_lock_irqsave(&bp->lock, flags);
2146 sx_out(bp, CD186x_CCR, CCR_SSCH2);
2147 spin_unlock_irqrestore(&bp->lock, flags);
2150 spin_lock_irqsave(&bp->lock, flags);
2151 sx_out(bp, CD186x_MSVR, port->MSVR);
2152 spin_unlock_irqrestore(&bp->lock, flags);
2158 static void sx_unthrottle(struct tty_struct * tty)
2160 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2161 struct specialix_board *bp;
2162 unsigned long flags;
2166 if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
2171 bp = port_Board(port);
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);
2182 spin_unlock_irqrestore(&port->lock, flags);
2184 spin_lock_irqsave(&bp->lock, flags);
2185 sx_out(bp, CD186x_CCR, CCR_SSCH1);
2186 spin_unlock_irqrestore(&bp->lock, flags);
2188 spin_lock_irqsave(&port->lock, flags);
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);
2199 static void sx_stop(struct tty_struct * tty)
2201 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2202 struct specialix_board *bp;
2203 unsigned long flags;
2207 if (sx_paranoia_check(port, tty->name, "sx_stop")) {
2212 bp = port_Board(port);
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);
2226 static void sx_start(struct tty_struct * tty)
2228 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2229 struct specialix_board *bp;
2230 unsigned long flags;
2234 if (sx_paranoia_check(port, tty->name, "sx_start")) {
2239 bp = port_Board(port);
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);
2249 spin_unlock_irqrestore(&port->lock, flags);
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:
2260 * serial interrupt routine -> (workqueue) ->
2261 * do_sx_hangup() -> tty->hangup() -> sx_hangup()
2264 static void do_sx_hangup(struct work_struct *work)
2266 struct specialix_port *port =
2267 container_of(work, struct specialix_port, tqueue_hangup);
2268 struct tty_struct *tty;
2274 tty_hangup(tty); /* FIXME: module removal race here */
2280 static void sx_hangup(struct tty_struct * tty)
2282 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2283 struct specialix_board *bp;
2284 unsigned long flags;
2288 if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
2293 bp = port_Board(port);
2295 sx_shutdown_port(bp, port);
2296 spin_lock_irqsave(&port->lock, flags);
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);
2305 port->flags &= ~ASYNC_NORMAL_ACTIVE;
2307 spin_unlock_irqrestore(&port->lock, flags);
2308 wake_up_interruptible(&port->open_wait);
2314 static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
2316 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2317 unsigned long flags;
2318 struct specialix_board * bp;
2320 if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
2323 if (tty->termios->c_cflag == old_termios->c_cflag &&
2324 tty->termios->c_iflag == old_termios->c_iflag)
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);
2332 if ((old_termios->c_cflag & CRTSCTS) &&
2333 !(tty->termios->c_cflag & CRTSCTS)) {
2334 tty->hw_stopped = 0;
2340 static void do_softint(struct work_struct *work)
2342 struct specialix_port *port =
2343 container_of(work, struct specialix_port, tqueue);
2344 struct tty_struct *tty;
2348 if(!(tty = port->tty)) {
2353 if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
2355 //wake_up_interruptible(&tty->write_wait);
2361 static const struct tty_operations sx_ops = {
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,
2371 .throttle = sx_throttle,
2372 .unthrottle = sx_unthrottle,
2373 .set_termios = sx_set_termios,
2376 .hangup = sx_hangup,
2377 .tiocmget = sx_tiocmget,
2378 .tiocmset = sx_tiocmset,
2381 static int sx_init_drivers(void)
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");
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->init_termios.c_ispeed = 9600;
2404 specialix_driver->init_termios.c_ospeed = 9600;
2405 specialix_driver->flags = TTY_DRIVER_REAL_RAW;
2406 tty_set_operations(specialix_driver, &sx_ops);
2408 if ((error = tty_register_driver(specialix_driver))) {
2409 put_tty_driver(specialix_driver);
2410 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2415 memset(sx_port, 0, sizeof(sx_port));
2416 for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
2417 sx_port[i].magic = SPECIALIX_MAGIC;
2418 INIT_WORK(&sx_port[i].tqueue, do_softint);
2419 INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup);
2420 sx_port[i].close_delay = 50 * HZ/100;
2421 sx_port[i].closing_wait = 3000 * HZ/100;
2422 init_waitqueue_head(&sx_port[i].open_wait);
2423 init_waitqueue_head(&sx_port[i].close_wait);
2424 spin_lock_init(&sx_port[i].lock);
2431 static void sx_release_drivers(void)
2435 tty_unregister_driver(specialix_driver);
2436 put_tty_driver(specialix_driver);
2441 * This routine must be called by kernel at boot time
2443 static int __init specialix_init(void)
2450 printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
2451 printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2452 #ifdef CONFIG_SPECIALIX_RTSCTS
2453 printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
2455 printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2458 for (i = 0; i < SX_NBOARD; i++)
2459 spin_lock_init(&sx_board[i].lock);
2461 if (sx_init_drivers()) {
2466 for (i = 0; i < SX_NBOARD; i++)
2467 if (sx_board[i].base && !sx_probe(&sx_board[i]))
2472 struct pci_dev *pdev = NULL;
2475 while (i < SX_NBOARD) {
2476 if (sx_board[i].flags & SX_BOARD_PRESENT) {
2480 pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
2481 PCI_DEVICE_ID_SPECIALIX_IO8,
2485 if (pci_enable_device(pdev))
2488 sx_board[i].irq = pdev->irq;
2490 sx_board[i].base = pci_resource_start (pdev, 2);
2492 sx_board[i].flags |= SX_BOARD_IS_PCI;
2493 if (!sx_probe(&sx_board[i]))
2496 /* May exit pci_get sequence early with lots of boards */
2503 sx_release_drivers();
2504 printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
2513 static int iobase[SX_NBOARD] = {0,};
2515 static int irq [SX_NBOARD] = {0,};
2517 module_param_array(iobase, int, NULL, 0);
2518 module_param_array(irq, int, NULL, 0);
2519 module_param(sx_debug, int, 0);
2520 module_param(sx_rxfifo, int, 0);
2521 #ifdef SPECIALIX_TIMER
2522 module_param(sx_poll, int, 0);
2526 * You can setup up to 4 boards.
2527 * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
2528 * You should specify the IRQs too in that case "irq=....,...".
2530 * More than 4 boards in one computer is not possible, as the card can
2531 * only use 4 different interrupts.
2534 static int __init specialix_init_module(void)
2540 if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
2541 for(i = 0; i < SX_NBOARD; i++) {
2542 sx_board[i].base = iobase[i];
2543 sx_board[i].irq = irq[i];
2544 sx_board[i].count= 0;
2550 return specialix_init();
2553 static void __exit specialix_exit_module(void)
2559 sx_release_drivers();
2560 for (i = 0; i < SX_NBOARD; i++)
2561 if (sx_board[i].flags & SX_BOARD_PRESENT)
2562 sx_release_io_range(&sx_board[i]);
2563 #ifdef SPECIALIX_TIMER
2564 del_timer (&missed_irq_timer);
2570 static struct pci_device_id specialx_pci_tbl[] __devinitdata = {
2571 { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
2574 MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
2576 module_init(specialix_init_module);
2577 module_exit(specialix_exit_module);
2579 MODULE_LICENSE("GPL");