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 unsigned long baud_table[] = {
187 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
188 9600, 19200, 38400, 57600, 115200, 0,
191 static struct specialix_board sx_board[SX_NBOARD] = {
192 { 0, SX_IOBASE1, 9, },
193 { 0, SX_IOBASE2, 11, },
194 { 0, SX_IOBASE3, 12, },
195 { 0, SX_IOBASE4, 15, },
198 static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
201 #ifdef SPECIALIX_TIMER
202 static struct timer_list missed_irq_timer;
203 static irqreturn_t sx_interrupt(int irq, void * dev_id, struct pt_regs * regs);
208 static inline int sx_paranoia_check(struct specialix_port const * port,
209 char *name, const char *routine)
211 #ifdef SPECIALIX_PARANOIA_CHECK
212 static const char *badmagic =
213 KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
214 static const char *badinfo =
215 KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
218 printk(badinfo, name, routine);
221 if (port->magic != SPECIALIX_MAGIC) {
222 printk(badmagic, name, routine);
232 * Service functions for specialix IO8+ driver.
236 /* Get board number from pointer */
237 static inline int board_No (struct specialix_board * bp)
239 return bp - sx_board;
243 /* Get port number from pointer */
244 static inline int port_No (struct specialix_port const * port)
246 return SX_PORT(port - sx_port);
250 /* Get pointer to board from pointer to port */
251 static inline struct specialix_board * port_Board(struct specialix_port const * port)
253 return &sx_board[SX_BOARD(port - sx_port)];
257 /* Input Byte from CL CD186x register */
258 static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
260 bp->reg = reg | 0x80;
261 outb (reg | 0x80, bp->base + SX_ADDR_REG);
262 return inb (bp->base + SX_DATA_REG);
266 /* Output Byte to CL CD186x register */
267 static inline void sx_out(struct specialix_board * bp, unsigned short reg,
270 bp->reg = reg | 0x80;
271 outb (reg | 0x80, bp->base + SX_ADDR_REG);
272 outb (val, bp->base + SX_DATA_REG);
276 /* Input Byte from CL CD186x register */
277 static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
280 outb (reg, bp->base + SX_ADDR_REG);
281 return inb (bp->base + SX_DATA_REG);
285 /* Output Byte to CL CD186x register */
286 static inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
290 outb (reg, bp->base + SX_ADDR_REG);
291 outb (val, bp->base + SX_DATA_REG);
295 /* Wait for Channel Command Register ready */
296 static inline void sx_wait_CCR(struct specialix_board * bp)
298 unsigned long delay, flags;
301 for (delay = SX_CCR_TIMEOUT; delay; delay--) {
302 spin_lock_irqsave(&bp->lock, flags);
303 ccr = sx_in(bp, CD186x_CCR);
304 spin_unlock_irqrestore(&bp->lock, flags);
310 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
314 /* Wait for Channel Command Register ready */
315 static inline void sx_wait_CCR_off(struct specialix_board * bp)
321 for (delay = SX_CCR_TIMEOUT; delay; delay--) {
322 spin_lock_irqsave(&bp->lock, flags);
323 crr = sx_in_off(bp, CD186x_CCR);
324 spin_unlock_irqrestore(&bp->lock, flags);
330 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
335 * specialix IO8+ IO range functions.
338 static inline int sx_request_io_range(struct specialix_board * bp)
340 return request_region(bp->base,
341 bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
342 "specialix IO8+") == NULL;
346 static inline void sx_release_io_range(struct specialix_board * bp)
348 release_region(bp->base,
349 bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
353 /* Must be called with enabled interrupts */
354 /* Ugly. Very ugly. Don't use this for anything else than initialization
356 static inline void sx_long_delay(unsigned long delay)
360 for (i = jiffies + delay; time_after(i, jiffies); ) ;
365 /* Set the IRQ using the RTS lines that run to the PAL on the board.... */
366 static int sx_set_irq ( struct specialix_board *bp)
372 if (bp->flags & SX_BOARD_IS_PCI)
375 /* In the same order as in the docs... */
376 case 15: virq = 0;break;
377 case 12: virq = 1;break;
378 case 11: virq = 2;break;
379 case 9: virq = 3;break;
380 default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq);
383 spin_lock_irqsave(&bp->lock, flags);
385 sx_out(bp, CD186x_CAR, i);
386 sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
388 spin_unlock_irqrestore(&bp->lock, flags);
393 /* Reset and setup CD186x chip */
394 static int sx_init_CD186x(struct specialix_board * bp)
401 sx_wait_CCR_off(bp); /* Wait for CCR ready */
402 spin_lock_irqsave(&bp->lock, flags);
403 sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */
404 spin_unlock_irqrestore(&bp->lock, flags);
405 sx_long_delay(HZ/20); /* Delay 0.05 sec */
406 spin_lock_irqsave(&bp->lock, flags);
407 sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */
408 sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */
409 sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT); /* Prio for modem intr */
410 sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */
411 sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */
413 sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
415 /* Setting up prescaler. We need 4 ticks per 1 ms */
416 scaler = SX_OSCFREQ/SPECIALIX_TPS;
418 sx_out_off(bp, CD186x_PPRH, scaler >> 8);
419 sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
420 spin_unlock_irqrestore(&bp->lock, flags);
422 if (!sx_set_irq (bp)) {
423 /* Figure out how to pass this along... */
424 printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq);
433 static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
439 spin_lock_irqsave(&bp->lock, flags);
440 for (i=0, t=0;i<8;i++) {
441 sx_out_off (bp, CD186x_CAR, i);
442 if (sx_in_off (bp, reg) & bit)
445 spin_unlock_irqrestore(&bp->lock, flags);
451 #ifdef SPECIALIX_TIMER
452 void missed_irq (unsigned long data)
456 struct specialix_board *bp = (struct specialix_board *)data;
458 spin_lock_irqsave(&bp->lock, flags);
459 irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) &
463 spin_unlock_irqrestore(&bp->lock, flags);
465 printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
466 sx_interrupt (((struct specialix_board *)data)->irq,
469 missed_irq_timer.expires = jiffies + sx_poll;
470 add_timer (&missed_irq_timer);
476 /* Main probing routine, also sets irq. */
477 static int sx_probe(struct specialix_board *bp)
479 unsigned char val1, val2;
489 if (sx_request_io_range(bp)) {
494 /* Are the I/O ports here ? */
495 sx_out_off(bp, CD186x_PPRL, 0x5a);
497 val1 = sx_in_off(bp, CD186x_PPRL);
499 sx_out_off(bp, CD186x_PPRL, 0xa5);
501 val2 = sx_in_off(bp, CD186x_PPRL);
504 if ((val1 != 0x5a) || (val2 != 0xa5)) {
505 printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
506 board_No(bp), bp->base);
507 sx_release_io_range(bp);
512 /* Check the DSR lines that Specialix uses as board
514 val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
515 val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
516 dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
517 board_No(bp), val1, val2);
519 /* They managed to switch the bit order between the docs and
520 the IO8+ card. The new PCI card now conforms to old docs.
521 They changed the PCI docs to reflect the situation on the
523 val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
525 printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
526 board_No(bp), val2, bp->base, val1);
527 sx_release_io_range(bp);
534 /* It's time to find IRQ for this board */
535 for (retries = 0; retries < 5 && irqs <= 0; retries++) {
536 irqs = probe_irq_on();
537 sx_init_CD186x(bp); /* Reset CD186x chip */
538 sx_out(bp, CD186x_CAR, 2); /* Select port 2 */
540 sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
541 sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
542 sx_long_delay(HZ/20);
543 irqs = probe_irq_off(irqs);
545 dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
546 dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
547 dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
548 dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR));
549 dprintk (SX_DEBUG_INIT, "\n");
551 /* Reset CD186x again */
552 if (!sx_init_CD186x(bp)) {
553 /* Hmmm. This is dead code anyway. */
556 dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
563 printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
564 board_No(bp), bp->base);
565 sx_release_io_range(bp);
570 printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
574 /* Reset CD186x again */
575 if (!sx_init_CD186x(bp)) {
576 sx_release_io_range(bp);
581 sx_request_io_range(bp);
582 bp->flags |= SX_BOARD_PRESENT;
584 /* Chip revcode pkgtype
589 CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
591 -- Thanks to Gwen Wang, Cirrus Logic.
594 switch (sx_in_off(bp, CD186x_GFRCR)) {
595 case 0x82:chip = 1864;rev='A';break;
596 case 0x83:chip = 1865;rev='A';break;
597 case 0x84:chip = 1865;rev='B';break;
598 case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */
599 default:chip=-1;rev='x';
602 dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
604 #ifdef SPECIALIX_TIMER
605 init_timer (&missed_irq_timer);
606 missed_irq_timer.function = missed_irq;
607 missed_irq_timer.data = (unsigned long) bp;
608 missed_irq_timer.expires = jiffies + sx_poll;
609 add_timer (&missed_irq_timer);
612 printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
623 * Interrupt processing routines.
626 static inline void sx_mark_event(struct specialix_port * port, int event)
630 set_bit(event, &port->event);
631 schedule_work(&port->tqueue);
637 static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
638 unsigned char const * what)
640 unsigned char channel;
641 struct specialix_port * port = NULL;
643 channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
644 dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel);
645 if (channel < CD186x_NCH) {
646 port = &sx_port[board_No(bp) * SX_NPORT + channel];
647 dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%x\n",board_No(bp) * SX_NPORT + channel, port, port->flags & ASYNC_INITIALIZED);
649 if (port->flags & ASYNC_INITIALIZED) {
650 dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
655 printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
656 board_No(bp), what, channel);
661 static inline void sx_receive_exc(struct specialix_board * bp)
663 struct specialix_port *port;
664 struct tty_struct *tty;
665 unsigned char status;
666 unsigned char ch, flag;
670 port = sx_get_port(bp, "Receive");
672 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
678 status = sx_in(bp, CD186x_RCSR);
680 dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
681 if (status & RCSR_OE) {
683 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
684 board_No(bp), port_No(port), port->overrun);
686 status &= port->mark_mask;
688 /* This flip buffer check needs to be below the reading of the
689 status register to reset the chip's IRQ.... */
690 if (tty_buffer_request_room(tty, 1) == 0) {
691 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
692 board_No(bp), port_No(port));
697 ch = sx_in(bp, CD186x_RDR);
702 if (status & RCSR_TOUT) {
703 printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
704 board_No(bp), port_No(port));
708 } else if (status & RCSR_BREAK) {
709 dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
710 board_No(bp), port_No(port));
712 if (port->flags & ASYNC_SAK)
715 } else if (status & RCSR_PE)
718 else if (status & RCSR_FE)
721 else if (status & RCSR_OE)
727 if(tty_insert_flip_char(tty, ch, flag))
728 tty_flip_buffer_push(tty);
733 static inline void sx_receive(struct specialix_board * bp)
735 struct specialix_port *port;
736 struct tty_struct *tty;
741 if (!(port = sx_get_port(bp, "Receive"))) {
742 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
748 count = sx_in(bp, CD186x_RDCR);
749 dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
750 port->hits[count > 8 ? 9 : count]++;
752 tty_buffer_request_room(tty, count);
755 tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
756 tty_flip_buffer_push(tty);
761 static inline void sx_transmit(struct specialix_board * bp)
763 struct specialix_port *port;
764 struct tty_struct *tty;
768 if (!(port = sx_get_port(bp, "Transmit"))) {
772 dprintk (SX_DEBUG_TX, "port: %p\n", port);
775 if (port->IER & IER_TXEMPTY) {
777 sx_out(bp, CD186x_CAR, port_No(port));
778 port->IER &= ~IER_TXEMPTY;
779 sx_out(bp, CD186x_IER, port->IER);
784 if ((port->xmit_cnt <= 0 && !port->break_length)
785 || tty->stopped || tty->hw_stopped) {
786 sx_out(bp, CD186x_CAR, port_No(port));
787 port->IER &= ~IER_TXRDY;
788 sx_out(bp, CD186x_IER, port->IER);
793 if (port->break_length) {
794 if (port->break_length > 0) {
795 if (port->COR2 & COR2_ETC) {
796 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
797 sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
798 port->COR2 &= ~COR2_ETC;
800 count = min_t(int, port->break_length, 0xff);
801 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
802 sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
803 sx_out(bp, CD186x_TDR, count);
804 if (!(port->break_length -= count))
805 port->break_length--;
807 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
808 sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
809 sx_out(bp, CD186x_COR2, port->COR2);
811 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
812 port->break_length = 0;
819 count = CD186x_NFIFO;
821 sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
822 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
823 if (--port->xmit_cnt <= 0)
825 } while (--count > 0);
827 if (port->xmit_cnt <= 0) {
828 sx_out(bp, CD186x_CAR, port_No(port));
829 port->IER &= ~IER_TXRDY;
830 sx_out(bp, CD186x_IER, port->IER);
832 if (port->xmit_cnt <= port->wakeup_chars)
833 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
839 static inline void sx_check_modem(struct specialix_board * bp)
841 struct specialix_port *port;
842 struct tty_struct *tty;
846 dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
847 if (!(port = sx_get_port(bp, "Modem")))
852 mcr = sx_in(bp, CD186x_MCR);
853 printk ("mcr = %02x.\n", mcr);
855 if ((mcr & MCR_CDCHG)) {
856 dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
857 msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
859 dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
860 wake_up_interruptible(&port->open_wait);
862 dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
863 schedule_work(&port->tqueue_hangup);
867 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
868 if (mcr & MCR_CTSCHG) {
869 if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
871 port->IER |= IER_TXRDY;
872 if (port->xmit_cnt <= port->wakeup_chars)
873 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
876 port->IER &= ~IER_TXRDY;
878 sx_out(bp, CD186x_IER, port->IER);
880 if (mcr & MCR_DSSXHG) {
881 if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
883 port->IER |= IER_TXRDY;
884 if (port->xmit_cnt <= port->wakeup_chars)
885 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
888 port->IER &= ~IER_TXRDY;
890 sx_out(bp, CD186x_IER, port->IER);
892 #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
894 /* Clear change bits */
895 sx_out(bp, CD186x_MCR, 0);
899 /* The main interrupt processing routine */
900 static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
902 unsigned char status;
904 struct specialix_board *bp;
905 unsigned long loop = 0;
912 spin_lock_irqsave(&bp->lock, flags);
914 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);
915 if (!bp || !(bp->flags & SX_BOARD_ACTIVE)) {
916 dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
917 spin_unlock_irqrestore(&bp->lock, flags);
924 while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
928 if (status & SRSR_RREQint) {
929 ack = sx_in(bp, CD186x_RRAR);
931 if (ack == (SX_ID | GIVR_IT_RCV))
933 else if (ack == (SX_ID | GIVR_IT_REXC))
936 printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
937 board_No(bp), status, ack);
939 } else if (status & SRSR_TREQint) {
940 ack = sx_in(bp, CD186x_TRAR);
942 if (ack == (SX_ID | GIVR_IT_TX))
945 printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
946 board_No(bp), status, ack, port_No (sx_get_port (bp, "Int")));
947 } else if (status & SRSR_MREQint) {
948 ack = sx_in(bp, CD186x_MRAR);
950 if (ack == (SX_ID | GIVR_IT_MODEM))
953 printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
954 board_No(bp), status, ack);
958 sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
961 outb (bp->reg, bp->base + SX_ADDR_REG);
962 spin_unlock_irqrestore(&bp->lock, flags);
969 * Routines for open & close processing.
972 static void turn_ints_off (struct specialix_board *bp)
977 if (bp->flags & SX_BOARD_IS_PCI) {
978 /* This was intended for enabeling the interrupt on the
979 * PCI card. However it seems that it's already enabled
980 * and as PCI interrupts can be shared, there is no real
981 * reason to have to turn it off. */
984 spin_lock_irqsave(&bp->lock, flags);
985 (void) sx_in_off (bp, 0); /* Turn off interrupts. */
986 spin_unlock_irqrestore(&bp->lock, flags);
991 static void turn_ints_on (struct specialix_board *bp)
997 if (bp->flags & SX_BOARD_IS_PCI) {
998 /* play with the PCI chip. See comment above. */
1000 spin_lock_irqsave(&bp->lock, flags);
1001 (void) sx_in (bp, 0); /* Turn ON interrupts. */
1002 spin_unlock_irqrestore(&bp->lock, flags);
1008 /* Called with disabled interrupts */
1009 static inline int sx_setup_board(struct specialix_board * bp)
1013 if (bp->flags & SX_BOARD_ACTIVE)
1016 if (bp->flags & SX_BOARD_IS_PCI)
1017 error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
1019 error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp);
1025 bp->flags |= SX_BOARD_ACTIVE;
1031 /* Called with disabled interrupts */
1032 static inline void sx_shutdown_board(struct specialix_board *bp)
1036 if (!(bp->flags & SX_BOARD_ACTIVE)) {
1041 bp->flags &= ~SX_BOARD_ACTIVE;
1043 dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
1044 bp->irq, board_No (bp));
1045 free_irq(bp->irq, bp);
1055 * Setting up port characteristics.
1056 * Must be called with disabled interrupts
1058 static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
1060 struct tty_struct *tty;
1063 unsigned char cor1 = 0, cor3 = 0;
1064 unsigned char mcor1 = 0, mcor2 = 0;
1065 static unsigned long again;
1066 unsigned long flags;
1070 if (!(tty = port->tty) || !tty->termios) {
1077 /* Select port on the board */
1078 spin_lock_irqsave(&bp->lock, flags);
1079 sx_out(bp, CD186x_CAR, port_No(port));
1081 /* The Specialix board doens't implement the RTS lines.
1082 They are used to set the IRQ level. Don't touch them. */
1083 if (SX_CRTSCTS(tty))
1084 port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1086 port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1087 spin_unlock_irqrestore(&bp->lock, flags);
1088 dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
1089 baud = tty_get_baud_rate(tty);
1091 if (baud == 38400) {
1092 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1094 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
1099 /* Drop DTR & exit */
1100 dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
1101 if (!SX_CRTSCTS (tty)) {
1102 port -> MSVR &= ~ MSVR_DTR;
1103 spin_lock_irqsave(&bp->lock, flags);
1104 sx_out(bp, CD186x_MSVR, port->MSVR );
1105 spin_unlock_irqrestore(&bp->lock, flags);
1108 dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
1112 if (!SX_CRTSCTS (tty)) {
1113 port ->MSVR |= MSVR_DTR;
1118 * Now we must calculate some speed depended things
1121 /* Set baud rate for port */
1122 tmp = port->custom_divisor ;
1124 printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"
1125 "This is an untested option, please be carefull.\n",
1126 port_No (port), tmp);
1128 tmp = (((SX_OSCFREQ + baud/2) / baud +
1129 CD186x_TPC/2) / CD186x_TPC);
1131 if ((tmp < 0x10) && time_before(again, jiffies)) {
1132 again = jiffies + HZ * 60;
1133 /* Page 48 of version 2.0 of the CL-CD1865 databook */
1135 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1136 "Performance degradation is possible.\n"
1137 "Read specialix.txt for more info.\n",
1138 port_No (port), tmp);
1140 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1141 "Warning: overstressing Cirrus chip. "
1142 "This might not work.\n"
1143 "Read specialix.txt for more info.\n",
1144 port_No (port), tmp);
1147 spin_lock_irqsave(&bp->lock, flags);
1148 sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
1149 sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
1150 sx_out(bp, CD186x_RBPRL, tmp & 0xff);
1151 sx_out(bp, CD186x_TBPRL, tmp & 0xff);
1152 spin_unlock_irqrestore(&bp->lock, flags);
1153 if (port->custom_divisor) {
1154 baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
1155 baud = ( baud + 5 ) / 10;
1157 baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */
1159 /* Two timer ticks seems enough to wakeup something like SLIP driver */
1160 tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
1161 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
1162 SERIAL_XMIT_SIZE - 1 : tmp);
1164 /* Receiver timeout will be transmission time for 1.5 chars */
1165 tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
1166 tmp = (tmp > 0xff) ? 0xff : tmp;
1167 spin_lock_irqsave(&bp->lock, flags);
1168 sx_out(bp, CD186x_RTPR, tmp);
1169 spin_unlock_irqrestore(&bp->lock, flags);
1170 switch (C_CSIZE(tty)) {
1188 cor1 |= COR1_IGNORE;
1189 if (C_PARENB(tty)) {
1190 cor1 |= COR1_NORMPAR;
1194 cor1 &= ~COR1_IGNORE;
1196 /* Set marking of some errors */
1197 port->mark_mask = RCSR_OE | RCSR_TOUT;
1199 port->mark_mask |= RCSR_FE | RCSR_PE;
1200 if (I_BRKINT(tty) || I_PARMRK(tty))
1201 port->mark_mask |= RCSR_BREAK;
1203 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
1204 if (I_IGNBRK(tty)) {
1205 port->mark_mask &= ~RCSR_BREAK;
1207 /* Real raw mode. Ignore all */
1208 port->mark_mask &= ~RCSR_OE;
1210 /* Enable Hardware Flow Control */
1211 if (C_CRTSCTS(tty)) {
1212 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
1213 port->IER |= IER_DSR | IER_CTS;
1214 mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
1215 mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
1216 spin_lock_irqsave(&bp->lock, flags);
1217 tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
1218 spin_unlock_irqrestore(&bp->lock, flags);
1220 port->COR2 |= COR2_CTSAE;
1223 /* Enable Software Flow Control. FIXME: I'm not sure about this */
1224 /* Some people reported that it works, but I still doubt it */
1226 port->COR2 |= COR2_TXIBE;
1227 cor3 |= (COR3_FCT | COR3_SCDE);
1229 port->COR2 |= COR2_IXM;
1230 spin_lock_irqsave(&bp->lock, flags);
1231 sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
1232 sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
1233 sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
1234 sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
1235 spin_unlock_irqrestore(&bp->lock, flags);
1237 if (!C_CLOCAL(tty)) {
1238 /* Enable CD check */
1239 port->IER |= IER_CD;
1240 mcor1 |= MCOR1_CDZD;
1241 mcor2 |= MCOR2_CDOD;
1245 /* Enable receiver */
1246 port->IER |= IER_RXD;
1248 /* Set input FIFO size (1-8 bytes) */
1250 /* Setting up CD186x channel registers */
1251 spin_lock_irqsave(&bp->lock, flags);
1252 sx_out(bp, CD186x_COR1, cor1);
1253 sx_out(bp, CD186x_COR2, port->COR2);
1254 sx_out(bp, CD186x_COR3, cor3);
1255 spin_unlock_irqrestore(&bp->lock, flags);
1256 /* Make CD186x know about registers change */
1258 spin_lock_irqsave(&bp->lock, flags);
1259 sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1260 /* Setting up modem option registers */
1261 dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
1262 sx_out(bp, CD186x_MCOR1, mcor1);
1263 sx_out(bp, CD186x_MCOR2, mcor2);
1264 spin_unlock_irqrestore(&bp->lock, flags);
1265 /* Enable CD186x transmitter & receiver */
1267 spin_lock_irqsave(&bp->lock, flags);
1268 sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
1269 /* Enable interrupts */
1270 sx_out(bp, CD186x_IER, port->IER);
1271 /* And finally set the modem lines... */
1272 sx_out(bp, CD186x_MSVR, port->MSVR);
1273 spin_unlock_irqrestore(&bp->lock, flags);
1279 /* Must be called with interrupts enabled */
1280 static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
1282 unsigned long flags;
1286 if (port->flags & ASYNC_INITIALIZED) {
1291 if (!port->xmit_buf) {
1292 /* We may sleep in get_zeroed_page() */
1295 if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
1300 if (port->xmit_buf) {
1303 return -ERESTARTSYS;
1305 port->xmit_buf = (unsigned char *) tmp;
1308 spin_lock_irqsave(&port->lock, flags);
1311 clear_bit(TTY_IO_ERROR, &port->tty->flags);
1313 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1314 sx_change_speed(bp, port);
1315 port->flags |= ASYNC_INITIALIZED;
1317 spin_unlock_irqrestore(&port->lock, flags);
1325 /* Must be called with interrupts disabled */
1326 static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
1328 struct tty_struct *tty;
1330 unsigned long flags;
1334 if (!(port->flags & ASYNC_INITIALIZED)) {
1339 if (sx_debug & SX_DEBUG_FIFO) {
1340 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
1341 board_No(bp), port_No(port), port->overrun);
1342 for (i = 0; i < 10; i++) {
1343 dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
1345 dprintk(SX_DEBUG_FIFO, "].\n");
1348 if (port->xmit_buf) {
1349 free_page((unsigned long) port->xmit_buf);
1350 port->xmit_buf = NULL;
1354 spin_lock_irqsave(&bp->lock, flags);
1355 sx_out(bp, CD186x_CAR, port_No(port));
1357 if (!(tty = port->tty) || C_HUPCL(tty)) {
1359 sx_out(bp, CD186x_MSVDTR, 0);
1361 spin_unlock_irqrestore(&bp->lock, flags);
1364 spin_lock_irqsave(&bp->lock, flags);
1365 sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
1366 /* Disable all interrupts from this port */
1368 sx_out(bp, CD186x_IER, port->IER);
1369 spin_unlock_irqrestore(&bp->lock, flags);
1371 set_bit(TTY_IO_ERROR, &tty->flags);
1372 port->flags &= ~ASYNC_INITIALIZED;
1375 sx_shutdown_board(bp);
1380 static int block_til_ready(struct tty_struct *tty, struct file * filp,
1381 struct specialix_port *port)
1383 DECLARE_WAITQUEUE(wait, current);
1384 struct specialix_board *bp = port_Board(port);
1388 unsigned long flags;
1393 * If the device is in the middle of being closed, then block
1394 * until it's done, and then try again.
1396 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
1397 interruptible_sleep_on(&port->close_wait);
1398 if (port->flags & ASYNC_HUP_NOTIFY) {
1403 return -ERESTARTSYS;
1408 * If non-blocking mode is set, or the port is not enabled,
1409 * then make the check up front and then exit.
1411 if ((filp->f_flags & O_NONBLOCK) ||
1412 (tty->flags & (1 << TTY_IO_ERROR))) {
1413 port->flags |= ASYNC_NORMAL_ACTIVE;
1422 * Block waiting for the carrier detect and the line to become
1423 * free (i.e., not in use by the callout). While we are in
1424 * this loop, info->count is dropped by one, so that
1425 * rs_close() knows when to free things. We restore it upon
1426 * exit, either normal or abnormal.
1429 add_wait_queue(&port->open_wait, &wait);
1430 spin_lock_irqsave(&port->lock, flags);
1431 if (!tty_hung_up_p(filp)) {
1434 spin_unlock_irqrestore(&port->lock, flags);
1435 port->blocked_open++;
1437 spin_lock_irqsave(&bp->lock, flags);
1438 sx_out(bp, CD186x_CAR, port_No(port));
1439 CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
1440 if (SX_CRTSCTS (tty)) {
1442 port->MSVR |= MSVR_DTR; /* WTF? */
1443 sx_out (bp, CD186x_MSVR, port->MSVR);
1446 port->MSVR |= MSVR_DTR;
1447 sx_out (bp, CD186x_MSVR, port->MSVR);
1449 spin_unlock_irqrestore(&bp->lock, flags);
1450 set_current_state(TASK_INTERRUPTIBLE);
1451 if (tty_hung_up_p(filp) ||
1452 !(port->flags & ASYNC_INITIALIZED)) {
1453 if (port->flags & ASYNC_HUP_NOTIFY)
1456 retval = -ERESTARTSYS;
1459 if (!(port->flags & ASYNC_CLOSING) &&
1462 if (signal_pending(current)) {
1463 retval = -ERESTARTSYS;
1469 set_current_state(TASK_RUNNING);
1470 remove_wait_queue(&port->open_wait, &wait);
1471 spin_lock_irqsave(&port->lock, flags);
1472 if (!tty_hung_up_p(filp)) {
1475 port->blocked_open--;
1476 spin_unlock_irqrestore(&port->lock, flags);
1482 port->flags |= ASYNC_NORMAL_ACTIVE;
1488 static int sx_open(struct tty_struct * tty, struct file * filp)
1492 struct specialix_port * port;
1493 struct specialix_board * bp;
1495 unsigned long flags;
1499 board = SX_BOARD(tty->index);
1501 if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
1506 bp = &sx_board[board];
1507 port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
1509 for (i = 0; i < 10; i++)
1512 dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
1513 board, bp, port, SX_PORT(tty->index));
1515 if (sx_paranoia_check(port, tty->name, "sx_open")) {
1520 if ((error = sx_setup_board(bp))) {
1525 spin_lock_irqsave(&bp->lock, flags);
1528 tty->driver_data = port;
1530 spin_unlock_irqrestore(&bp->lock, flags);
1532 if ((error = sx_setup_port(bp, port))) {
1537 if ((error = block_til_ready(tty, filp, port))) {
1547 static void sx_close(struct tty_struct * tty, struct file * filp)
1549 struct specialix_port *port = (struct specialix_port *) tty->driver_data;
1550 struct specialix_board *bp;
1551 unsigned long flags;
1552 unsigned long timeout;
1555 if (!port || sx_paranoia_check(port, tty->name, "close")) {
1559 spin_lock_irqsave(&port->lock, flags);
1561 if (tty_hung_up_p(filp)) {
1562 spin_unlock_irqrestore(&port->lock, flags);
1567 bp = port_Board(port);
1568 if ((tty->count == 1) && (port->count != 1)) {
1569 printk(KERN_ERR "sx%d: sx_close: bad port count;"
1570 " tty->count is 1, port count is %d\n",
1571 board_No(bp), port->count);
1575 if (port->count > 1) {
1579 spin_unlock_irqrestore(&port->lock, flags);
1584 port->flags |= ASYNC_CLOSING;
1586 * Now we wait for the transmit buffer to clear; and we notify
1587 * the line discipline to only process XON/XOFF characters.
1590 spin_unlock_irqrestore(&port->lock, flags);
1591 dprintk (SX_DEBUG_OPEN, "Closing\n");
1592 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
1593 tty_wait_until_sent(tty, port->closing_wait);
1596 * At this point we stop accepting input. To do this, we
1597 * disable the receive line status interrupts, and tell the
1598 * interrupt driver to stop checking the data ready bit in the
1599 * line status register.
1601 dprintk (SX_DEBUG_OPEN, "Closed\n");
1602 port->IER &= ~IER_RXD;
1603 if (port->flags & ASYNC_INITIALIZED) {
1604 port->IER &= ~IER_TXRDY;
1605 port->IER |= IER_TXEMPTY;
1606 spin_lock_irqsave(&bp->lock, flags);
1607 sx_out(bp, CD186x_CAR, port_No(port));
1608 sx_out(bp, CD186x_IER, port->IER);
1609 spin_unlock_irqrestore(&bp->lock, flags);
1611 * Before we drop DTR, make sure the UART transmitter
1612 * has completely drained; this is especially
1613 * important if there is a transmit FIFO!
1615 timeout = jiffies+HZ;
1616 while(port->IER & IER_TXEMPTY) {
1617 set_current_state (TASK_INTERRUPTIBLE);
1618 msleep_interruptible(jiffies_to_msecs(port->timeout));
1619 if (time_after(jiffies, timeout)) {
1620 printk (KERN_INFO "Timeout waiting for close\n");
1627 if (--bp->count < 0) {
1628 printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
1629 board_No(bp), bp->count, tty->index);
1632 if (--port->count < 0) {
1633 printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
1634 board_No(bp), port_No(port), port->count);
1638 sx_shutdown_port(bp, port);
1639 if (tty->driver->flush_buffer)
1640 tty->driver->flush_buffer(tty);
1641 tty_ldisc_flush(tty);
1642 spin_lock_irqsave(&port->lock, flags);
1646 spin_unlock_irqrestore(&port->lock, flags);
1647 if (port->blocked_open) {
1648 if (port->close_delay) {
1649 msleep_interruptible(jiffies_to_msecs(port->close_delay));
1651 wake_up_interruptible(&port->open_wait);
1653 port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1654 wake_up_interruptible(&port->close_wait);
1660 static int sx_write(struct tty_struct * tty,
1661 const unsigned char *buf, int count)
1663 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1664 struct specialix_board *bp;
1666 unsigned long flags;
1669 if (sx_paranoia_check(port, tty->name, "sx_write")) {
1674 bp = port_Board(port);
1676 if (!port->xmit_buf) {
1682 spin_lock_irqsave(&port->lock, flags);
1683 c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1684 SERIAL_XMIT_SIZE - port->xmit_head));
1686 spin_unlock_irqrestore(&port->lock, flags);
1689 memcpy(port->xmit_buf + port->xmit_head, buf, c);
1690 port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1691 port->xmit_cnt += c;
1692 spin_unlock_irqrestore(&port->lock, flags);
1699 spin_lock_irqsave(&bp->lock, flags);
1700 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1701 !(port->IER & IER_TXRDY)) {
1702 port->IER |= IER_TXRDY;
1703 sx_out(bp, CD186x_CAR, port_No(port));
1704 sx_out(bp, CD186x_IER, port->IER);
1706 spin_unlock_irqrestore(&bp->lock, flags);
1713 static void sx_put_char(struct tty_struct * tty, unsigned char ch)
1715 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1716 unsigned long flags;
1717 struct specialix_board * bp;
1721 if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
1725 dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
1726 if (!port->xmit_buf) {
1730 bp = port_Board(port);
1731 spin_lock_irqsave(&port->lock, flags);
1733 dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf);
1734 if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) {
1735 spin_unlock_irqrestore(&port->lock, flags);
1736 dprintk (SX_DEBUG_TX, "Exit size\n");
1740 dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
1741 port->xmit_buf[port->xmit_head++] = ch;
1742 port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1744 spin_unlock_irqrestore(&port->lock, flags);
1750 static void sx_flush_chars(struct tty_struct * tty)
1752 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1753 unsigned long flags;
1754 struct specialix_board * bp = port_Board(port);
1758 if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
1762 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1767 spin_lock_irqsave(&bp->lock, flags);
1768 port->IER |= IER_TXRDY;
1769 sx_out(port_Board(port), CD186x_CAR, port_No(port));
1770 sx_out(port_Board(port), CD186x_IER, port->IER);
1771 spin_unlock_irqrestore(&bp->lock, flags);
1777 static int sx_write_room(struct tty_struct * tty)
1779 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1784 if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
1789 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1798 static int sx_chars_in_buffer(struct tty_struct *tty)
1800 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1804 if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
1809 return port->xmit_cnt;
1813 static void sx_flush_buffer(struct tty_struct *tty)
1815 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1816 unsigned long flags;
1817 struct specialix_board * bp;
1821 if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
1826 bp = port_Board(port);
1827 spin_lock_irqsave(&port->lock, flags);
1828 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1829 spin_unlock_irqrestore(&port->lock, flags);
1836 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1838 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1839 struct specialix_board * bp;
1840 unsigned char status;
1841 unsigned int result;
1842 unsigned long flags;
1846 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1851 bp = port_Board(port);
1852 spin_lock_irqsave (&bp->lock, flags);
1853 sx_out(bp, CD186x_CAR, port_No(port));
1854 status = sx_in(bp, CD186x_MSVR);
1855 spin_unlock_irqrestore(&bp->lock, flags);
1856 dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
1857 port_No(port), status, sx_in (bp, CD186x_CAR));
1858 dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
1859 if (SX_CRTSCTS(port->tty)) {
1860 result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
1861 | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
1862 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1863 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1864 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1866 result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
1867 | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1868 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1869 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1870 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1879 static int sx_tiocmset(struct tty_struct *tty, struct file *file,
1880 unsigned int set, unsigned int clear)
1882 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1883 unsigned long flags;
1884 struct specialix_board *bp;
1888 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1893 bp = port_Board(port);
1895 spin_lock_irqsave(&port->lock, flags);
1896 /* if (set & TIOCM_RTS)
1897 port->MSVR |= MSVR_RTS; */
1898 /* if (set & TIOCM_DTR)
1899 port->MSVR |= MSVR_DTR; */
1901 if (SX_CRTSCTS(port->tty)) {
1902 if (set & TIOCM_RTS)
1903 port->MSVR |= MSVR_DTR;
1905 if (set & TIOCM_DTR)
1906 port->MSVR |= MSVR_DTR;
1909 /* if (clear & TIOCM_RTS)
1910 port->MSVR &= ~MSVR_RTS; */
1911 /* if (clear & TIOCM_DTR)
1912 port->MSVR &= ~MSVR_DTR; */
1913 if (SX_CRTSCTS(port->tty)) {
1914 if (clear & TIOCM_RTS)
1915 port->MSVR &= ~MSVR_DTR;
1917 if (clear & TIOCM_DTR)
1918 port->MSVR &= ~MSVR_DTR;
1920 spin_lock_irqsave(&bp->lock, flags);
1921 sx_out(bp, CD186x_CAR, port_No(port));
1922 sx_out(bp, CD186x_MSVR, port->MSVR);
1923 spin_unlock_irqrestore(&bp->lock, flags);
1924 spin_unlock_irqrestore(&port->lock, flags);
1930 static inline void sx_send_break(struct specialix_port * port, unsigned long length)
1932 struct specialix_board *bp = port_Board(port);
1933 unsigned long flags;
1937 spin_lock_irqsave (&port->lock, flags);
1938 port->break_length = SPECIALIX_TPS / HZ * length;
1939 port->COR2 |= COR2_ETC;
1940 port->IER |= IER_TXRDY;
1941 spin_lock_irqsave(&bp->lock, flags);
1942 sx_out(bp, CD186x_CAR, port_No(port));
1943 sx_out(bp, CD186x_COR2, port->COR2);
1944 sx_out(bp, CD186x_IER, port->IER);
1945 spin_unlock_irqrestore(&bp->lock, flags);
1946 spin_unlock_irqrestore (&port->lock, flags);
1948 spin_lock_irqsave(&bp->lock, flags);
1949 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
1950 spin_unlock_irqrestore(&bp->lock, flags);
1957 static inline int sx_set_serial_info(struct specialix_port * port,
1958 struct serial_struct __user * newinfo)
1960 struct serial_struct tmp;
1961 struct specialix_board *bp = port_Board(port);
1966 if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) {
1971 if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
1977 if ((tmp.irq != bp->irq) ||
1978 (tmp.port != bp->base) ||
1979 (tmp.type != PORT_CIRRUS) ||
1980 (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
1981 (tmp.custom_divisor != 0) ||
1982 (tmp.xmit_fifo_size != CD186x_NFIFO) ||
1983 (tmp.flags & ~SPECIALIX_LEGAL_FLAGS)) {
1989 change_speed = ((port->flags & ASYNC_SPD_MASK) !=
1990 (tmp.flags & ASYNC_SPD_MASK));
1991 change_speed |= (tmp.custom_divisor != port->custom_divisor);
1993 if (!capable(CAP_SYS_ADMIN)) {
1994 if ((tmp.close_delay != port->close_delay) ||
1995 (tmp.closing_wait != port->closing_wait) ||
1996 ((tmp.flags & ~ASYNC_USR_MASK) !=
1997 (port->flags & ~ASYNC_USR_MASK))) {
2001 port->flags = ((port->flags & ~ASYNC_USR_MASK) |
2002 (tmp.flags & ASYNC_USR_MASK));
2003 port->custom_divisor = tmp.custom_divisor;
2005 port->flags = ((port->flags & ~ASYNC_FLAGS) |
2006 (tmp.flags & ASYNC_FLAGS));
2007 port->close_delay = tmp.close_delay;
2008 port->closing_wait = tmp.closing_wait;
2009 port->custom_divisor = tmp.custom_divisor;
2012 sx_change_speed(bp, port);
2019 static inline int sx_get_serial_info(struct specialix_port * port,
2020 struct serial_struct __user *retinfo)
2022 struct serial_struct tmp;
2023 struct specialix_board *bp = port_Board(port);
2028 if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
2032 memset(&tmp, 0, sizeof(tmp));
2033 tmp.type = PORT_CIRRUS;
2034 tmp.line = port - sx_port;
2035 tmp.port = bp->base;
2037 tmp.flags = port->flags;
2038 tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
2039 tmp.close_delay = port->close_delay * HZ/100;
2040 tmp.closing_wait = port->closing_wait * HZ/100;
2041 tmp.custom_divisor = port->custom_divisor;
2042 tmp.xmit_fifo_size = CD186x_NFIFO;
2043 if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
2053 static int sx_ioctl(struct tty_struct * tty, struct file * filp,
2054 unsigned int cmd, unsigned long arg)
2056 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2058 void __user *argp = (void __user *)arg;
2062 if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
2068 case TCSBRK: /* SVID version: non-zero arg --> no break */
2069 retval = tty_check_change(tty);
2074 tty_wait_until_sent(tty, 0);
2076 sx_send_break(port, HZ/4); /* 1/4 second */
2078 case TCSBRKP: /* support for POSIX tcsendbreak() */
2079 retval = tty_check_change(tty);
2084 tty_wait_until_sent(tty, 0);
2085 sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
2089 if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) {
2096 if (get_user(arg, (unsigned long __user *) argp)) {
2100 tty->termios->c_cflag =
2101 ((tty->termios->c_cflag & ~CLOCAL) |
2102 (arg ? CLOCAL : 0));
2107 return sx_get_serial_info(port, argp);
2110 return sx_set_serial_info(port, argp);
2113 return -ENOIOCTLCMD;
2120 static void sx_throttle(struct tty_struct * tty)
2122 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2123 struct specialix_board *bp;
2124 unsigned long flags;
2128 if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
2133 bp = port_Board(port);
2135 /* Use DTR instead of RTS ! */
2136 if (SX_CRTSCTS (tty))
2137 port->MSVR &= ~MSVR_DTR;
2139 /* Auch!!! I think the system shouldn't call this then. */
2140 /* Or maybe we're supposed (allowed?) to do our side of hw
2141 handshake anyway, even when hardware handshake is off.
2142 When you see this in your logs, please report.... */
2143 printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
2146 spin_lock_irqsave(&bp->lock, flags);
2147 sx_out(bp, CD186x_CAR, port_No(port));
2148 spin_unlock_irqrestore(&bp->lock, flags);
2150 spin_unlock_irqrestore(&bp->lock, flags);
2152 spin_lock_irqsave(&bp->lock, flags);
2153 sx_out(bp, CD186x_CCR, CCR_SSCH2);
2154 spin_unlock_irqrestore(&bp->lock, flags);
2157 spin_lock_irqsave(&bp->lock, flags);
2158 sx_out(bp, CD186x_MSVR, port->MSVR);
2159 spin_unlock_irqrestore(&bp->lock, flags);
2165 static void sx_unthrottle(struct tty_struct * tty)
2167 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2168 struct specialix_board *bp;
2169 unsigned long flags;
2173 if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
2178 bp = port_Board(port);
2180 spin_lock_irqsave(&port->lock, flags);
2181 /* XXXX Use DTR INSTEAD???? */
2182 if (SX_CRTSCTS(tty)) {
2183 port->MSVR |= MSVR_DTR;
2184 } /* Else clause: see remark in "sx_throttle"... */
2185 spin_lock_irqsave(&bp->lock, flags);
2186 sx_out(bp, CD186x_CAR, port_No(port));
2187 spin_unlock_irqrestore(&bp->lock, flags);
2189 spin_unlock_irqrestore(&port->lock, flags);
2191 spin_lock_irqsave(&bp->lock, flags);
2192 sx_out(bp, CD186x_CCR, CCR_SSCH1);
2193 spin_unlock_irqrestore(&bp->lock, flags);
2195 spin_lock_irqsave(&port->lock, flags);
2197 spin_lock_irqsave(&bp->lock, flags);
2198 sx_out(bp, CD186x_MSVR, port->MSVR);
2199 spin_unlock_irqrestore(&bp->lock, flags);
2200 spin_unlock_irqrestore(&port->lock, flags);
2206 static void sx_stop(struct tty_struct * tty)
2208 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2209 struct specialix_board *bp;
2210 unsigned long flags;
2214 if (sx_paranoia_check(port, tty->name, "sx_stop")) {
2219 bp = port_Board(port);
2221 spin_lock_irqsave(&port->lock, flags);
2222 port->IER &= ~IER_TXRDY;
2223 spin_lock_irqsave(&bp->lock, flags);
2224 sx_out(bp, CD186x_CAR, port_No(port));
2225 sx_out(bp, CD186x_IER, port->IER);
2226 spin_unlock_irqrestore(&bp->lock, flags);
2227 spin_unlock_irqrestore(&port->lock, flags);
2233 static void sx_start(struct tty_struct * tty)
2235 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2236 struct specialix_board *bp;
2237 unsigned long flags;
2241 if (sx_paranoia_check(port, tty->name, "sx_start")) {
2246 bp = port_Board(port);
2248 spin_lock_irqsave(&port->lock, flags);
2249 if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
2250 port->IER |= IER_TXRDY;
2251 spin_lock_irqsave(&bp->lock, flags);
2252 sx_out(bp, CD186x_CAR, port_No(port));
2253 sx_out(bp, CD186x_IER, port->IER);
2254 spin_unlock_irqrestore(&bp->lock, flags);
2256 spin_unlock_irqrestore(&port->lock, flags);
2263 * This routine is called from the work-queue when the interrupt
2264 * routine has signalled that a hangup has occurred. The path of
2265 * hangup processing is:
2267 * serial interrupt routine -> (workqueue) ->
2268 * do_sx_hangup() -> tty->hangup() -> sx_hangup()
2271 static void do_sx_hangup(void *private_)
2273 struct specialix_port *port = (struct specialix_port *) private_;
2274 struct tty_struct *tty;
2280 tty_hangup(tty); /* FIXME: module removal race here */
2286 static void sx_hangup(struct tty_struct * tty)
2288 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2289 struct specialix_board *bp;
2290 unsigned long flags;
2294 if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
2299 bp = port_Board(port);
2301 sx_shutdown_port(bp, port);
2302 spin_lock_irqsave(&port->lock, flags);
2304 bp->count -= port->count;
2305 if (bp->count < 0) {
2306 printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n",
2307 board_No(bp), bp->count, tty->index);
2311 port->flags &= ~ASYNC_NORMAL_ACTIVE;
2313 spin_unlock_irqrestore(&port->lock, flags);
2314 wake_up_interruptible(&port->open_wait);
2320 static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios)
2322 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2323 unsigned long flags;
2324 struct specialix_board * bp;
2326 if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
2329 if (tty->termios->c_cflag == old_termios->c_cflag &&
2330 tty->termios->c_iflag == old_termios->c_iflag)
2333 bp = port_Board(port);
2334 spin_lock_irqsave(&port->lock, flags);
2335 sx_change_speed(port_Board(port), port);
2336 spin_unlock_irqrestore(&port->lock, flags);
2338 if ((old_termios->c_cflag & CRTSCTS) &&
2339 !(tty->termios->c_cflag & CRTSCTS)) {
2340 tty->hw_stopped = 0;
2346 static void do_softint(void *private_)
2348 struct specialix_port *port = (struct specialix_port *) private_;
2349 struct tty_struct *tty;
2353 if(!(tty = port->tty)) {
2358 if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
2360 //wake_up_interruptible(&tty->write_wait);
2366 static const struct tty_operations sx_ops = {
2370 .put_char = sx_put_char,
2371 .flush_chars = sx_flush_chars,
2372 .write_room = sx_write_room,
2373 .chars_in_buffer = sx_chars_in_buffer,
2374 .flush_buffer = sx_flush_buffer,
2376 .throttle = sx_throttle,
2377 .unthrottle = sx_unthrottle,
2378 .set_termios = sx_set_termios,
2381 .hangup = sx_hangup,
2382 .tiocmget = sx_tiocmget,
2383 .tiocmset = sx_tiocmset,
2386 static int sx_init_drivers(void)
2393 specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
2394 if (!specialix_driver) {
2395 printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
2400 specialix_driver->owner = THIS_MODULE;
2401 specialix_driver->name = "ttyW";
2402 specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
2403 specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
2404 specialix_driver->subtype = SERIAL_TYPE_NORMAL;
2405 specialix_driver->init_termios = tty_std_termios;
2406 specialix_driver->init_termios.c_cflag =
2407 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2408 specialix_driver->flags = TTY_DRIVER_REAL_RAW;
2409 tty_set_operations(specialix_driver, &sx_ops);
2411 if ((error = tty_register_driver(specialix_driver))) {
2412 put_tty_driver(specialix_driver);
2413 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2418 memset(sx_port, 0, sizeof(sx_port));
2419 for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
2420 sx_port[i].magic = SPECIALIX_MAGIC;
2421 INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]);
2422 INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]);
2423 sx_port[i].close_delay = 50 * HZ/100;
2424 sx_port[i].closing_wait = 3000 * HZ/100;
2425 init_waitqueue_head(&sx_port[i].open_wait);
2426 init_waitqueue_head(&sx_port[i].close_wait);
2427 spin_lock_init(&sx_port[i].lock);
2434 static void sx_release_drivers(void)
2438 tty_unregister_driver(specialix_driver);
2439 put_tty_driver(specialix_driver);
2444 * This routine must be called by kernel at boot time
2446 static int __init specialix_init(void)
2453 printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
2454 printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2455 #ifdef CONFIG_SPECIALIX_RTSCTS
2456 printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
2458 printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2461 for (i = 0; i < SX_NBOARD; i++)
2462 spin_lock_init(&sx_board[i].lock);
2464 if (sx_init_drivers()) {
2469 for (i = 0; i < SX_NBOARD; i++)
2470 if (sx_board[i].base && !sx_probe(&sx_board[i]))
2475 struct pci_dev *pdev = NULL;
2478 while (i < SX_NBOARD) {
2479 if (sx_board[i].flags & SX_BOARD_PRESENT) {
2483 pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
2484 PCI_DEVICE_ID_SPECIALIX_IO8,
2488 if (pci_enable_device(pdev))
2491 sx_board[i].irq = pdev->irq;
2493 sx_board[i].base = pci_resource_start (pdev, 2);
2495 sx_board[i].flags |= SX_BOARD_IS_PCI;
2496 if (!sx_probe(&sx_board[i]))
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");