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/config.h>
79 #include <linux/module.h>
82 #include <linux/kernel.h>
83 #include <linux/sched.h>
84 #include <linux/ioport.h>
85 #include <linux/interrupt.h>
86 #include <linux/errno.h>
87 #include <linux/tty.h>
88 #include <linux/tty_flip.h>
90 #include <linux/serial.h>
91 #include <linux/fcntl.h>
92 #include <linux/major.h>
93 #include <linux/delay.h>
94 #include <linux/pci.h>
95 #include <linux/init.h>
96 #include <asm/uaccess.h>
98 #include "specialix_io8.h"
103 This driver can spew a whole lot of debugging output at you. If you
104 need maximum performance, you should disable the DEBUG define. To
105 aid in debugging in the field, I'm leaving the compile-time debug
106 features enabled, and disable them "runtime". That allows me to
107 instruct people with problems to enable debugging without requiring
113 static int sx_rxfifo = SPECIALIX_RXFIFO;
116 #define dprintk(f, str...) if (sx_debug & f) printk (str)
118 #define dprintk(f, str...) /* nothing */
121 #define SX_DEBUG_FLOW 0x0001
122 #define SX_DEBUG_DATA 0x0002
123 #define SX_DEBUG_PROBE 0x0004
124 #define SX_DEBUG_CHAN 0x0008
125 #define SX_DEBUG_INIT 0x0010
126 #define SX_DEBUG_RX 0x0020
127 #define SX_DEBUG_TX 0x0040
128 #define SX_DEBUG_IRQ 0x0080
129 #define SX_DEBUG_OPEN 0x0100
130 #define SX_DEBUG_TERMIOS 0x0200
131 #define SX_DEBUG_SIGNALS 0x0400
132 #define SX_DEBUG_FIFO 0x0800
135 #define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__FUNCTION__)
136 #define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __FUNCTION__)
138 #define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
141 /* Configurable options: */
143 /* Am I paranoid or not ? ;-) */
144 #define SPECIALIX_PARANOIA_CHECK
146 /* Do I trust the IRQ from the card? (enabeling it doesn't seem to help)
147 When the IRQ routine leaves the chip in a state that is keeps on
148 requiring attention, the timer doesn't help either. */
149 #undef SPECIALIX_TIMER
151 #ifdef SPECIALIX_TIMER
152 static int sx_poll = HZ;
158 * The following defines are mostly for testing purposes. But if you need
159 * some nice reporting in your syslog, you can define them also.
161 #undef SX_REPORT_FIFO
162 #undef SX_REPORT_OVERRUN
166 #ifdef CONFIG_SPECIALIX_RTSCTS
167 #define SX_CRTSCTS(bla) 1
169 #define SX_CRTSCTS(tty) C_CRTSCTS(tty)
173 /* Used to be outb (0xff, 0x80); */
174 #define short_pause() udelay (1)
177 #define SPECIALIX_LEGAL_FLAGS \
178 (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \
179 ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \
180 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
182 #undef RS_EVENT_WRITE_WAKEUP
183 #define RS_EVENT_WRITE_WAKEUP 0
185 static struct tty_driver *specialix_driver;
186 static unsigned char * tmp_buf;
188 static unsigned long baud_table[] = {
189 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
190 9600, 19200, 38400, 57600, 115200, 0,
193 static struct specialix_board sx_board[SX_NBOARD] = {
194 { 0, SX_IOBASE1, 9, },
195 { 0, SX_IOBASE2, 11, },
196 { 0, SX_IOBASE3, 12, },
197 { 0, SX_IOBASE4, 15, },
200 static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
203 #ifdef SPECIALIX_TIMER
204 static struct timer_list missed_irq_timer;
205 static irqreturn_t sx_interrupt(int irq, void * dev_id, struct pt_regs * regs);
210 static inline int sx_paranoia_check(struct specialix_port const * port,
211 char *name, const char *routine)
213 #ifdef SPECIALIX_PARANOIA_CHECK
214 static const char *badmagic =
215 KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
216 static const char *badinfo =
217 KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
220 printk(badinfo, name, routine);
223 if (port->magic != SPECIALIX_MAGIC) {
224 printk(badmagic, name, routine);
234 * Service functions for specialix IO8+ driver.
238 /* Get board number from pointer */
239 static inline int board_No (struct specialix_board * bp)
241 return bp - sx_board;
245 /* Get port number from pointer */
246 static inline int port_No (struct specialix_port const * port)
248 return SX_PORT(port - sx_port);
252 /* Get pointer to board from pointer to port */
253 static inline struct specialix_board * port_Board(struct specialix_port const * port)
255 return &sx_board[SX_BOARD(port - sx_port)];
259 /* Input Byte from CL CD186x register */
260 static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
262 bp->reg = reg | 0x80;
263 outb (reg | 0x80, bp->base + SX_ADDR_REG);
264 return inb (bp->base + SX_DATA_REG);
268 /* Output Byte to CL CD186x register */
269 static inline void sx_out(struct specialix_board * bp, unsigned short reg,
272 bp->reg = reg | 0x80;
273 outb (reg | 0x80, bp->base + SX_ADDR_REG);
274 outb (val, bp->base + SX_DATA_REG);
278 /* Input Byte from CL CD186x register */
279 static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
282 outb (reg, bp->base + SX_ADDR_REG);
283 return inb (bp->base + SX_DATA_REG);
287 /* Output Byte to CL CD186x register */
288 static inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
292 outb (reg, bp->base + SX_ADDR_REG);
293 outb (val, bp->base + SX_DATA_REG);
297 /* Wait for Channel Command Register ready */
298 static inline void sx_wait_CCR(struct specialix_board * bp)
300 unsigned long delay, flags;
303 for (delay = SX_CCR_TIMEOUT; delay; delay--) {
304 spin_lock_irqsave(&bp->lock, flags);
305 ccr = sx_in(bp, CD186x_CCR);
306 spin_unlock_irqrestore(&bp->lock, flags);
312 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
316 /* Wait for Channel Command Register ready */
317 static inline void sx_wait_CCR_off(struct specialix_board * bp)
323 for (delay = SX_CCR_TIMEOUT; delay; delay--) {
324 spin_lock_irqsave(&bp->lock, flags);
325 crr = sx_in_off(bp, CD186x_CCR);
326 spin_unlock_irqrestore(&bp->lock, flags);
332 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
337 * specialix IO8+ IO range functions.
340 static inline int sx_request_io_range(struct specialix_board * bp)
342 return request_region(bp->base,
343 bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
344 "specialix IO8+") == NULL;
348 static inline void sx_release_io_range(struct specialix_board * bp)
350 release_region(bp->base,
351 bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
355 /* Must be called with enabled interrupts */
356 /* Ugly. Very ugly. Don't use this for anything else than initialization
358 static inline void sx_long_delay(unsigned long delay)
362 for (i = jiffies + delay; time_after(i, jiffies); ) ;
367 /* Set the IRQ using the RTS lines that run to the PAL on the board.... */
368 static int sx_set_irq ( struct specialix_board *bp)
374 if (bp->flags & SX_BOARD_IS_PCI)
377 /* In the same order as in the docs... */
378 case 15: virq = 0;break;
379 case 12: virq = 1;break;
380 case 11: virq = 2;break;
381 case 9: virq = 3;break;
382 default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq);
385 spin_lock_irqsave(&bp->lock, flags);
387 sx_out(bp, CD186x_CAR, i);
388 sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
390 spin_unlock_irqrestore(&bp->lock, flags);
395 /* Reset and setup CD186x chip */
396 static int sx_init_CD186x(struct specialix_board * bp)
403 sx_wait_CCR_off(bp); /* Wait for CCR ready */
404 spin_lock_irqsave(&bp->lock, flags);
405 sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */
406 spin_unlock_irqrestore(&bp->lock, flags);
407 sx_long_delay(HZ/20); /* Delay 0.05 sec */
408 spin_lock_irqsave(&bp->lock, flags);
409 sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */
410 sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */
411 sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT); /* Prio for modem intr */
412 sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */
413 sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */
415 sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
417 /* Setting up prescaler. We need 4 ticks per 1 ms */
418 scaler = SX_OSCFREQ/SPECIALIX_TPS;
420 sx_out_off(bp, CD186x_PPRH, scaler >> 8);
421 sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
422 spin_unlock_irqrestore(&bp->lock, flags);
424 if (!sx_set_irq (bp)) {
425 /* Figure out how to pass this along... */
426 printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq);
435 static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
441 spin_lock_irqsave(&bp->lock, flags);
442 for (i=0, t=0;i<8;i++) {
443 sx_out_off (bp, CD186x_CAR, i);
444 if (sx_in_off (bp, reg) & bit)
447 spin_unlock_irqrestore(&bp->lock, flags);
453 #ifdef SPECIALIX_TIMER
454 void missed_irq (unsigned long data)
458 struct specialix_board *bp = (struct specialix_board *)data;
460 spin_lock_irqsave(&bp->lock, flags);
461 irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) &
465 spin_unlock_irqrestore(&bp->lock, flags);
467 printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
468 sx_interrupt (((struct specialix_board *)data)->irq,
471 missed_irq_timer.expires = jiffies + sx_poll;
472 add_timer (&missed_irq_timer);
478 /* Main probing routine, also sets irq. */
479 static int sx_probe(struct specialix_board *bp)
481 unsigned char val1, val2;
491 if (sx_request_io_range(bp)) {
496 /* Are the I/O ports here ? */
497 sx_out_off(bp, CD186x_PPRL, 0x5a);
499 val1 = sx_in_off(bp, CD186x_PPRL);
501 sx_out_off(bp, CD186x_PPRL, 0xa5);
503 val2 = sx_in_off(bp, CD186x_PPRL);
506 if ((val1 != 0x5a) || (val2 != 0xa5)) {
507 printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
508 board_No(bp), bp->base);
509 sx_release_io_range(bp);
514 /* Check the DSR lines that Specialix uses as board
516 val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
517 val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
518 dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
519 board_No(bp), val1, val2);
521 /* They managed to switch the bit order between the docs and
522 the IO8+ card. The new PCI card now conforms to old docs.
523 They changed the PCI docs to reflect the situation on the
525 val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
527 printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
528 board_No(bp), val2, bp->base, val1);
529 sx_release_io_range(bp);
536 /* It's time to find IRQ for this board */
537 for (retries = 0; retries < 5 && irqs <= 0; retries++) {
538 irqs = probe_irq_on();
539 sx_init_CD186x(bp); /* Reset CD186x chip */
540 sx_out(bp, CD186x_CAR, 2); /* Select port 2 */
542 sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
543 sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
544 sx_long_delay(HZ/20);
545 irqs = probe_irq_off(irqs);
547 dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
548 dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
549 dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
550 dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR));
551 dprintk (SX_DEBUG_INIT, "\n");
553 /* Reset CD186x again */
554 if (!sx_init_CD186x(bp)) {
555 /* Hmmm. This is dead code anyway. */
558 dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
565 printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
566 board_No(bp), bp->base);
567 sx_release_io_range(bp);
572 printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
576 /* Reset CD186x again */
577 if (!sx_init_CD186x(bp)) {
578 sx_release_io_range(bp);
583 sx_request_io_range(bp);
584 bp->flags |= SX_BOARD_PRESENT;
586 /* Chip revcode pkgtype
591 CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
593 -- Thanks to Gwen Wang, Cirrus Logic.
596 switch (sx_in_off(bp, CD186x_GFRCR)) {
597 case 0x82:chip = 1864;rev='A';break;
598 case 0x83:chip = 1865;rev='A';break;
599 case 0x84:chip = 1865;rev='B';break;
600 case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */
601 default:chip=-1;rev='x';
604 dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
606 #ifdef SPECIALIX_TIMER
607 init_timer (&missed_irq_timer);
608 missed_irq_timer.function = missed_irq;
609 missed_irq_timer.data = (unsigned long) bp;
610 missed_irq_timer.expires = jiffies + sx_poll;
611 add_timer (&missed_irq_timer);
614 printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
625 * Interrupt processing routines.
628 static inline void sx_mark_event(struct specialix_port * port, int event)
632 set_bit(event, &port->event);
633 schedule_work(&port->tqueue);
639 static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
640 unsigned char const * what)
642 unsigned char channel;
643 struct specialix_port * port = NULL;
645 channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
646 dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel);
647 if (channel < CD186x_NCH) {
648 port = &sx_port[board_No(bp) * SX_NPORT + channel];
649 dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%x\n",board_No(bp) * SX_NPORT + channel, port, port->flags & ASYNC_INITIALIZED);
651 if (port->flags & ASYNC_INITIALIZED) {
652 dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
657 printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
658 board_No(bp), what, channel);
663 static inline void sx_receive_exc(struct specialix_board * bp)
665 struct specialix_port *port;
666 struct tty_struct *tty;
667 unsigned char status;
668 unsigned char ch, flag;
672 port = sx_get_port(bp, "Receive");
674 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
680 status = sx_in(bp, CD186x_RCSR);
682 dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
683 if (status & RCSR_OE) {
685 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
686 board_No(bp), port_No(port), port->overrun);
688 status &= port->mark_mask;
690 /* This flip buffer check needs to be below the reading of the
691 status register to reset the chip's IRQ.... */
692 if (tty_buffer_request_room(tty, 1) == 0) {
693 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
694 board_No(bp), port_No(port));
699 ch = sx_in(bp, CD186x_RDR);
704 if (status & RCSR_TOUT) {
705 printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
706 board_No(bp), port_No(port));
710 } else if (status & RCSR_BREAK) {
711 dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
712 board_No(bp), port_No(port));
714 if (port->flags & ASYNC_SAK)
717 } else if (status & RCSR_PE)
720 else if (status & RCSR_FE)
723 else if (status & RCSR_OE)
729 if(tty_insert_flip_char(tty, ch, flag))
730 tty_flip_buffer_push(tty);
735 static inline void sx_receive(struct specialix_board * bp)
737 struct specialix_port *port;
738 struct tty_struct *tty;
743 if (!(port = sx_get_port(bp, "Receive"))) {
744 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
750 count = sx_in(bp, CD186x_RDCR);
751 dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
752 port->hits[count > 8 ? 9 : count]++;
754 tty_buffer_request_room(tty, count);
757 tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
758 tty_flip_buffer_push(tty);
763 static inline void sx_transmit(struct specialix_board * bp)
765 struct specialix_port *port;
766 struct tty_struct *tty;
770 if (!(port = sx_get_port(bp, "Transmit"))) {
774 dprintk (SX_DEBUG_TX, "port: %p\n", port);
777 if (port->IER & IER_TXEMPTY) {
779 sx_out(bp, CD186x_CAR, port_No(port));
780 port->IER &= ~IER_TXEMPTY;
781 sx_out(bp, CD186x_IER, port->IER);
786 if ((port->xmit_cnt <= 0 && !port->break_length)
787 || tty->stopped || tty->hw_stopped) {
788 sx_out(bp, CD186x_CAR, port_No(port));
789 port->IER &= ~IER_TXRDY;
790 sx_out(bp, CD186x_IER, port->IER);
795 if (port->break_length) {
796 if (port->break_length > 0) {
797 if (port->COR2 & COR2_ETC) {
798 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
799 sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
800 port->COR2 &= ~COR2_ETC;
802 count = min_t(int, port->break_length, 0xff);
803 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
804 sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
805 sx_out(bp, CD186x_TDR, count);
806 if (!(port->break_length -= count))
807 port->break_length--;
809 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
810 sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
811 sx_out(bp, CD186x_COR2, port->COR2);
813 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
814 port->break_length = 0;
821 count = CD186x_NFIFO;
823 sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
824 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
825 if (--port->xmit_cnt <= 0)
827 } while (--count > 0);
829 if (port->xmit_cnt <= 0) {
830 sx_out(bp, CD186x_CAR, port_No(port));
831 port->IER &= ~IER_TXRDY;
832 sx_out(bp, CD186x_IER, port->IER);
834 if (port->xmit_cnt <= port->wakeup_chars)
835 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
841 static inline void sx_check_modem(struct specialix_board * bp)
843 struct specialix_port *port;
844 struct tty_struct *tty;
848 dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
849 if (!(port = sx_get_port(bp, "Modem")))
854 mcr = sx_in(bp, CD186x_MCR);
855 printk ("mcr = %02x.\n", mcr);
857 if ((mcr & MCR_CDCHG)) {
858 dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
859 msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
861 dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
862 wake_up_interruptible(&port->open_wait);
864 dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
865 schedule_work(&port->tqueue_hangup);
869 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
870 if (mcr & MCR_CTSCHG) {
871 if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
873 port->IER |= IER_TXRDY;
874 if (port->xmit_cnt <= port->wakeup_chars)
875 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
878 port->IER &= ~IER_TXRDY;
880 sx_out(bp, CD186x_IER, port->IER);
882 if (mcr & MCR_DSSXHG) {
883 if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
885 port->IER |= IER_TXRDY;
886 if (port->xmit_cnt <= port->wakeup_chars)
887 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
890 port->IER &= ~IER_TXRDY;
892 sx_out(bp, CD186x_IER, port->IER);
894 #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
896 /* Clear change bits */
897 sx_out(bp, CD186x_MCR, 0);
901 /* The main interrupt processing routine */
902 static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
904 unsigned char status;
906 struct specialix_board *bp;
907 unsigned long loop = 0;
914 spin_lock_irqsave(&bp->lock, flags);
916 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);
917 if (!bp || !(bp->flags & SX_BOARD_ACTIVE)) {
918 dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
919 spin_unlock_irqrestore(&bp->lock, flags);
926 while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
930 if (status & SRSR_RREQint) {
931 ack = sx_in(bp, CD186x_RRAR);
933 if (ack == (SX_ID | GIVR_IT_RCV))
935 else if (ack == (SX_ID | GIVR_IT_REXC))
938 printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
939 board_No(bp), status, ack);
941 } else if (status & SRSR_TREQint) {
942 ack = sx_in(bp, CD186x_TRAR);
944 if (ack == (SX_ID | GIVR_IT_TX))
947 printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
948 board_No(bp), status, ack, port_No (sx_get_port (bp, "Int")));
949 } else if (status & SRSR_MREQint) {
950 ack = sx_in(bp, CD186x_MRAR);
952 if (ack == (SX_ID | GIVR_IT_MODEM))
955 printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
956 board_No(bp), status, ack);
960 sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
963 outb (bp->reg, bp->base + SX_ADDR_REG);
964 spin_unlock_irqrestore(&bp->lock, flags);
971 * Routines for open & close processing.
974 static void turn_ints_off (struct specialix_board *bp)
979 if (bp->flags & SX_BOARD_IS_PCI) {
980 /* This was intended for enabeling the interrupt on the
981 * PCI card. However it seems that it's already enabled
982 * and as PCI interrupts can be shared, there is no real
983 * reason to have to turn it off. */
986 spin_lock_irqsave(&bp->lock, flags);
987 (void) sx_in_off (bp, 0); /* Turn off interrupts. */
988 spin_unlock_irqrestore(&bp->lock, flags);
993 static void turn_ints_on (struct specialix_board *bp)
999 if (bp->flags & SX_BOARD_IS_PCI) {
1000 /* play with the PCI chip. See comment above. */
1002 spin_lock_irqsave(&bp->lock, flags);
1003 (void) sx_in (bp, 0); /* Turn ON interrupts. */
1004 spin_unlock_irqrestore(&bp->lock, flags);
1010 /* Called with disabled interrupts */
1011 static inline int sx_setup_board(struct specialix_board * bp)
1015 if (bp->flags & SX_BOARD_ACTIVE)
1018 if (bp->flags & SX_BOARD_IS_PCI)
1019 error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT | SA_SHIRQ, "specialix IO8+", bp);
1021 error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp);
1027 bp->flags |= SX_BOARD_ACTIVE;
1033 /* Called with disabled interrupts */
1034 static inline void sx_shutdown_board(struct specialix_board *bp)
1038 if (!(bp->flags & SX_BOARD_ACTIVE)) {
1043 bp->flags &= ~SX_BOARD_ACTIVE;
1045 dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
1046 bp->irq, board_No (bp));
1047 free_irq(bp->irq, bp);
1057 * Setting up port characteristics.
1058 * Must be called with disabled interrupts
1060 static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
1062 struct tty_struct *tty;
1065 unsigned char cor1 = 0, cor3 = 0;
1066 unsigned char mcor1 = 0, mcor2 = 0;
1067 static unsigned long again;
1068 unsigned long flags;
1072 if (!(tty = port->tty) || !tty->termios) {
1079 /* Select port on the board */
1080 spin_lock_irqsave(&bp->lock, flags);
1081 sx_out(bp, CD186x_CAR, port_No(port));
1083 /* The Specialix board doens't implement the RTS lines.
1084 They are used to set the IRQ level. Don't touch them. */
1085 if (SX_CRTSCTS(tty))
1086 port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1088 port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1089 spin_unlock_irqrestore(&bp->lock, flags);
1090 dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
1093 if (baud & CBAUDEX) {
1095 if (baud < 1 || baud > 2)
1096 port->tty->termios->c_cflag &= ~CBAUDEX;
1101 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1103 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
1108 if (!baud_table[baud]) {
1109 /* Drop DTR & exit */
1110 dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
1111 if (!SX_CRTSCTS (tty)) {
1112 port -> MSVR &= ~ MSVR_DTR;
1113 spin_lock_irqsave(&bp->lock, flags);
1114 sx_out(bp, CD186x_MSVR, port->MSVR );
1115 spin_unlock_irqrestore(&bp->lock, flags);
1118 dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
1122 if (!SX_CRTSCTS (tty)) {
1123 port ->MSVR |= MSVR_DTR;
1128 * Now we must calculate some speed depended things
1131 /* Set baud rate for port */
1132 tmp = port->custom_divisor ;
1134 printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"
1135 "This is an untested option, please be carefull.\n",
1136 port_No (port), tmp);
1138 tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
1139 CD186x_TPC/2) / CD186x_TPC);
1141 if ((tmp < 0x10) && time_before(again, jiffies)) {
1142 again = jiffies + HZ * 60;
1143 /* Page 48 of version 2.0 of the CL-CD1865 databook */
1145 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1146 "Performance degradation is possible.\n"
1147 "Read specialix.txt for more info.\n",
1148 port_No (port), tmp);
1150 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1151 "Warning: overstressing Cirrus chip. "
1152 "This might not work.\n"
1153 "Read specialix.txt for more info.\n",
1154 port_No (port), tmp);
1157 spin_lock_irqsave(&bp->lock, flags);
1158 sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
1159 sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
1160 sx_out(bp, CD186x_RBPRL, tmp & 0xff);
1161 sx_out(bp, CD186x_TBPRL, tmp & 0xff);
1162 spin_unlock_irqrestore(&bp->lock, flags);
1163 if (port->custom_divisor) {
1164 baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
1165 baud = ( baud + 5 ) / 10;
1167 baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */
1169 /* Two timer ticks seems enough to wakeup something like SLIP driver */
1170 tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
1171 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
1172 SERIAL_XMIT_SIZE - 1 : tmp);
1174 /* Receiver timeout will be transmission time for 1.5 chars */
1175 tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
1176 tmp = (tmp > 0xff) ? 0xff : tmp;
1177 spin_lock_irqsave(&bp->lock, flags);
1178 sx_out(bp, CD186x_RTPR, tmp);
1179 spin_unlock_irqrestore(&bp->lock, flags);
1180 switch (C_CSIZE(tty)) {
1198 cor1 |= COR1_IGNORE;
1199 if (C_PARENB(tty)) {
1200 cor1 |= COR1_NORMPAR;
1204 cor1 &= ~COR1_IGNORE;
1206 /* Set marking of some errors */
1207 port->mark_mask = RCSR_OE | RCSR_TOUT;
1209 port->mark_mask |= RCSR_FE | RCSR_PE;
1210 if (I_BRKINT(tty) || I_PARMRK(tty))
1211 port->mark_mask |= RCSR_BREAK;
1213 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
1214 if (I_IGNBRK(tty)) {
1215 port->mark_mask &= ~RCSR_BREAK;
1217 /* Real raw mode. Ignore all */
1218 port->mark_mask &= ~RCSR_OE;
1220 /* Enable Hardware Flow Control */
1221 if (C_CRTSCTS(tty)) {
1222 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
1223 port->IER |= IER_DSR | IER_CTS;
1224 mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
1225 mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
1226 spin_lock_irqsave(&bp->lock, flags);
1227 tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
1228 spin_unlock_irqrestore(&bp->lock, flags);
1230 port->COR2 |= COR2_CTSAE;
1233 /* Enable Software Flow Control. FIXME: I'm not sure about this */
1234 /* Some people reported that it works, but I still doubt it */
1236 port->COR2 |= COR2_TXIBE;
1237 cor3 |= (COR3_FCT | COR3_SCDE);
1239 port->COR2 |= COR2_IXM;
1240 spin_lock_irqsave(&bp->lock, flags);
1241 sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
1242 sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
1243 sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
1244 sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
1245 spin_unlock_irqrestore(&bp->lock, flags);
1247 if (!C_CLOCAL(tty)) {
1248 /* Enable CD check */
1249 port->IER |= IER_CD;
1250 mcor1 |= MCOR1_CDZD;
1251 mcor2 |= MCOR2_CDOD;
1255 /* Enable receiver */
1256 port->IER |= IER_RXD;
1258 /* Set input FIFO size (1-8 bytes) */
1260 /* Setting up CD186x channel registers */
1261 spin_lock_irqsave(&bp->lock, flags);
1262 sx_out(bp, CD186x_COR1, cor1);
1263 sx_out(bp, CD186x_COR2, port->COR2);
1264 sx_out(bp, CD186x_COR3, cor3);
1265 spin_unlock_irqrestore(&bp->lock, flags);
1266 /* Make CD186x know about registers change */
1268 spin_lock_irqsave(&bp->lock, flags);
1269 sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1270 /* Setting up modem option registers */
1271 dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
1272 sx_out(bp, CD186x_MCOR1, mcor1);
1273 sx_out(bp, CD186x_MCOR2, mcor2);
1274 spin_unlock_irqrestore(&bp->lock, flags);
1275 /* Enable CD186x transmitter & receiver */
1277 spin_lock_irqsave(&bp->lock, flags);
1278 sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
1279 /* Enable interrupts */
1280 sx_out(bp, CD186x_IER, port->IER);
1281 /* And finally set the modem lines... */
1282 sx_out(bp, CD186x_MSVR, port->MSVR);
1283 spin_unlock_irqrestore(&bp->lock, flags);
1289 /* Must be called with interrupts enabled */
1290 static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
1292 unsigned long flags;
1296 if (port->flags & ASYNC_INITIALIZED) {
1301 if (!port->xmit_buf) {
1302 /* We may sleep in get_zeroed_page() */
1305 if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
1310 if (port->xmit_buf) {
1313 return -ERESTARTSYS;
1315 port->xmit_buf = (unsigned char *) tmp;
1318 spin_lock_irqsave(&port->lock, flags);
1321 clear_bit(TTY_IO_ERROR, &port->tty->flags);
1323 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1324 sx_change_speed(bp, port);
1325 port->flags |= ASYNC_INITIALIZED;
1327 spin_unlock_irqrestore(&port->lock, flags);
1335 /* Must be called with interrupts disabled */
1336 static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
1338 struct tty_struct *tty;
1340 unsigned long flags;
1344 if (!(port->flags & ASYNC_INITIALIZED)) {
1349 if (sx_debug & SX_DEBUG_FIFO) {
1350 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
1351 board_No(bp), port_No(port), port->overrun);
1352 for (i = 0; i < 10; i++) {
1353 dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
1355 dprintk(SX_DEBUG_FIFO, "].\n");
1358 if (port->xmit_buf) {
1359 free_page((unsigned long) port->xmit_buf);
1360 port->xmit_buf = NULL;
1364 spin_lock_irqsave(&bp->lock, flags);
1365 sx_out(bp, CD186x_CAR, port_No(port));
1367 if (!(tty = port->tty) || C_HUPCL(tty)) {
1369 sx_out(bp, CD186x_MSVDTR, 0);
1371 spin_unlock_irqrestore(&bp->lock, flags);
1374 spin_lock_irqsave(&bp->lock, flags);
1375 sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
1376 /* Disable all interrupts from this port */
1378 sx_out(bp, CD186x_IER, port->IER);
1379 spin_unlock_irqrestore(&bp->lock, flags);
1381 set_bit(TTY_IO_ERROR, &tty->flags);
1382 port->flags &= ~ASYNC_INITIALIZED;
1385 sx_shutdown_board(bp);
1390 static int block_til_ready(struct tty_struct *tty, struct file * filp,
1391 struct specialix_port *port)
1393 DECLARE_WAITQUEUE(wait, current);
1394 struct specialix_board *bp = port_Board(port);
1398 unsigned long flags;
1403 * If the device is in the middle of being closed, then block
1404 * until it's done, and then try again.
1406 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
1407 interruptible_sleep_on(&port->close_wait);
1408 if (port->flags & ASYNC_HUP_NOTIFY) {
1413 return -ERESTARTSYS;
1418 * If non-blocking mode is set, or the port is not enabled,
1419 * then make the check up front and then exit.
1421 if ((filp->f_flags & O_NONBLOCK) ||
1422 (tty->flags & (1 << TTY_IO_ERROR))) {
1423 port->flags |= ASYNC_NORMAL_ACTIVE;
1432 * Block waiting for the carrier detect and the line to become
1433 * free (i.e., not in use by the callout). While we are in
1434 * this loop, info->count is dropped by one, so that
1435 * rs_close() knows when to free things. We restore it upon
1436 * exit, either normal or abnormal.
1439 add_wait_queue(&port->open_wait, &wait);
1440 spin_lock_irqsave(&port->lock, flags);
1441 if (!tty_hung_up_p(filp)) {
1444 spin_unlock_irqrestore(&port->lock, flags);
1445 port->blocked_open++;
1447 spin_lock_irqsave(&bp->lock, flags);
1448 sx_out(bp, CD186x_CAR, port_No(port));
1449 CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
1450 if (SX_CRTSCTS (tty)) {
1452 port->MSVR |= MSVR_DTR; /* WTF? */
1453 sx_out (bp, CD186x_MSVR, port->MSVR);
1456 port->MSVR |= MSVR_DTR;
1457 sx_out (bp, CD186x_MSVR, port->MSVR);
1459 spin_unlock_irqrestore(&bp->lock, flags);
1460 set_current_state(TASK_INTERRUPTIBLE);
1461 if (tty_hung_up_p(filp) ||
1462 !(port->flags & ASYNC_INITIALIZED)) {
1463 if (port->flags & ASYNC_HUP_NOTIFY)
1466 retval = -ERESTARTSYS;
1469 if (!(port->flags & ASYNC_CLOSING) &&
1472 if (signal_pending(current)) {
1473 retval = -ERESTARTSYS;
1479 set_current_state(TASK_RUNNING);
1480 remove_wait_queue(&port->open_wait, &wait);
1481 spin_lock_irqsave(&port->lock, flags);
1482 if (!tty_hung_up_p(filp)) {
1485 port->blocked_open--;
1486 spin_unlock_irqrestore(&port->lock, flags);
1492 port->flags |= ASYNC_NORMAL_ACTIVE;
1498 static int sx_open(struct tty_struct * tty, struct file * filp)
1502 struct specialix_port * port;
1503 struct specialix_board * bp;
1505 unsigned long flags;
1509 board = SX_BOARD(tty->index);
1511 if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
1516 bp = &sx_board[board];
1517 port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
1519 for (i = 0; i < 10; i++)
1522 dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
1523 board, bp, port, SX_PORT(tty->index));
1525 if (sx_paranoia_check(port, tty->name, "sx_open")) {
1530 if ((error = sx_setup_board(bp))) {
1535 spin_lock_irqsave(&bp->lock, flags);
1538 tty->driver_data = port;
1540 spin_unlock_irqrestore(&bp->lock, flags);
1542 if ((error = sx_setup_port(bp, port))) {
1547 if ((error = block_til_ready(tty, filp, port))) {
1557 static void sx_close(struct tty_struct * tty, struct file * filp)
1559 struct specialix_port *port = (struct specialix_port *) tty->driver_data;
1560 struct specialix_board *bp;
1561 unsigned long flags;
1562 unsigned long timeout;
1565 if (!port || sx_paranoia_check(port, tty->name, "close")) {
1569 spin_lock_irqsave(&port->lock, flags);
1571 if (tty_hung_up_p(filp)) {
1572 spin_unlock_irqrestore(&port->lock, flags);
1577 bp = port_Board(port);
1578 if ((tty->count == 1) && (port->count != 1)) {
1579 printk(KERN_ERR "sx%d: sx_close: bad port count;"
1580 " tty->count is 1, port count is %d\n",
1581 board_No(bp), port->count);
1585 if (port->count > 1) {
1589 spin_unlock_irqrestore(&port->lock, flags);
1594 port->flags |= ASYNC_CLOSING;
1596 * Now we wait for the transmit buffer to clear; and we notify
1597 * the line discipline to only process XON/XOFF characters.
1600 spin_unlock_irqrestore(&port->lock, flags);
1601 dprintk (SX_DEBUG_OPEN, "Closing\n");
1602 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
1603 tty_wait_until_sent(tty, port->closing_wait);
1606 * At this point we stop accepting input. To do this, we
1607 * disable the receive line status interrupts, and tell the
1608 * interrupt driver to stop checking the data ready bit in the
1609 * line status register.
1611 dprintk (SX_DEBUG_OPEN, "Closed\n");
1612 port->IER &= ~IER_RXD;
1613 if (port->flags & ASYNC_INITIALIZED) {
1614 port->IER &= ~IER_TXRDY;
1615 port->IER |= IER_TXEMPTY;
1616 spin_lock_irqsave(&bp->lock, flags);
1617 sx_out(bp, CD186x_CAR, port_No(port));
1618 sx_out(bp, CD186x_IER, port->IER);
1619 spin_unlock_irqrestore(&bp->lock, flags);
1621 * Before we drop DTR, make sure the UART transmitter
1622 * has completely drained; this is especially
1623 * important if there is a transmit FIFO!
1625 timeout = jiffies+HZ;
1626 while(port->IER & IER_TXEMPTY) {
1627 set_current_state (TASK_INTERRUPTIBLE);
1628 msleep_interruptible(jiffies_to_msecs(port->timeout));
1629 if (time_after(jiffies, timeout)) {
1630 printk (KERN_INFO "Timeout waiting for close\n");
1637 if (--bp->count < 0) {
1638 printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
1639 board_No(bp), bp->count, tty->index);
1642 if (--port->count < 0) {
1643 printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
1644 board_No(bp), port_No(port), port->count);
1648 sx_shutdown_port(bp, port);
1649 if (tty->driver->flush_buffer)
1650 tty->driver->flush_buffer(tty);
1651 tty_ldisc_flush(tty);
1652 spin_lock_irqsave(&port->lock, flags);
1656 spin_unlock_irqrestore(&port->lock, flags);
1657 if (port->blocked_open) {
1658 if (port->close_delay) {
1659 msleep_interruptible(jiffies_to_msecs(port->close_delay));
1661 wake_up_interruptible(&port->open_wait);
1663 port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1664 wake_up_interruptible(&port->close_wait);
1670 static int sx_write(struct tty_struct * tty,
1671 const unsigned char *buf, int count)
1673 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1674 struct specialix_board *bp;
1676 unsigned long flags;
1679 if (sx_paranoia_check(port, tty->name, "sx_write")) {
1684 bp = port_Board(port);
1686 if (!tty || !port->xmit_buf || !tmp_buf) {
1692 spin_lock_irqsave(&port->lock, flags);
1693 c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1694 SERIAL_XMIT_SIZE - port->xmit_head));
1696 spin_unlock_irqrestore(&port->lock, flags);
1699 memcpy(port->xmit_buf + port->xmit_head, buf, c);
1700 port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1701 port->xmit_cnt += c;
1702 spin_unlock_irqrestore(&port->lock, flags);
1709 spin_lock_irqsave(&bp->lock, flags);
1710 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1711 !(port->IER & IER_TXRDY)) {
1712 port->IER |= IER_TXRDY;
1713 sx_out(bp, CD186x_CAR, port_No(port));
1714 sx_out(bp, CD186x_IER, port->IER);
1716 spin_unlock_irqrestore(&bp->lock, flags);
1723 static void sx_put_char(struct tty_struct * tty, unsigned char ch)
1725 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1726 unsigned long flags;
1727 struct specialix_board * bp;
1731 if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
1735 dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
1736 if (!tty || !port->xmit_buf) {
1740 bp = port_Board(port);
1741 spin_lock_irqsave(&port->lock, flags);
1743 dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf);
1744 if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) {
1745 spin_unlock_irqrestore(&port->lock, flags);
1746 dprintk (SX_DEBUG_TX, "Exit size\n");
1750 dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
1751 port->xmit_buf[port->xmit_head++] = ch;
1752 port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1754 spin_unlock_irqrestore(&port->lock, flags);
1760 static void sx_flush_chars(struct tty_struct * tty)
1762 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1763 unsigned long flags;
1764 struct specialix_board * bp = port_Board(port);
1768 if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
1772 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1777 spin_lock_irqsave(&bp->lock, flags);
1778 port->IER |= IER_TXRDY;
1779 sx_out(port_Board(port), CD186x_CAR, port_No(port));
1780 sx_out(port_Board(port), CD186x_IER, port->IER);
1781 spin_unlock_irqrestore(&bp->lock, flags);
1787 static int sx_write_room(struct tty_struct * tty)
1789 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1794 if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
1799 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1808 static int sx_chars_in_buffer(struct tty_struct *tty)
1810 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1814 if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
1819 return port->xmit_cnt;
1823 static void sx_flush_buffer(struct tty_struct *tty)
1825 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1826 unsigned long flags;
1827 struct specialix_board * bp;
1831 if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
1836 bp = port_Board(port);
1837 spin_lock_irqsave(&port->lock, flags);
1838 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1839 spin_unlock_irqrestore(&port->lock, flags);
1846 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1848 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1849 struct specialix_board * bp;
1850 unsigned char status;
1851 unsigned int result;
1852 unsigned long flags;
1856 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1861 bp = port_Board(port);
1862 spin_lock_irqsave (&bp->lock, flags);
1863 sx_out(bp, CD186x_CAR, port_No(port));
1864 status = sx_in(bp, CD186x_MSVR);
1865 spin_unlock_irqrestore(&bp->lock, flags);
1866 dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
1867 port_No(port), status, sx_in (bp, CD186x_CAR));
1868 dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
1869 if (SX_CRTSCTS(port->tty)) {
1870 result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
1871 | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
1872 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1873 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1874 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1876 result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
1877 | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1878 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1879 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1880 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1889 static int sx_tiocmset(struct tty_struct *tty, struct file *file,
1890 unsigned int set, unsigned int clear)
1892 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1893 unsigned long flags;
1894 struct specialix_board *bp;
1898 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1903 bp = port_Board(port);
1905 spin_lock_irqsave(&port->lock, flags);
1906 /* if (set & TIOCM_RTS)
1907 port->MSVR |= MSVR_RTS; */
1908 /* if (set & TIOCM_DTR)
1909 port->MSVR |= MSVR_DTR; */
1911 if (SX_CRTSCTS(port->tty)) {
1912 if (set & TIOCM_RTS)
1913 port->MSVR |= MSVR_DTR;
1915 if (set & TIOCM_DTR)
1916 port->MSVR |= MSVR_DTR;
1919 /* if (clear & TIOCM_RTS)
1920 port->MSVR &= ~MSVR_RTS; */
1921 /* if (clear & TIOCM_DTR)
1922 port->MSVR &= ~MSVR_DTR; */
1923 if (SX_CRTSCTS(port->tty)) {
1924 if (clear & TIOCM_RTS)
1925 port->MSVR &= ~MSVR_DTR;
1927 if (clear & TIOCM_DTR)
1928 port->MSVR &= ~MSVR_DTR;
1930 spin_lock_irqsave(&bp->lock, flags);
1931 sx_out(bp, CD186x_CAR, port_No(port));
1932 sx_out(bp, CD186x_MSVR, port->MSVR);
1933 spin_unlock_irqrestore(&bp->lock, flags);
1934 spin_unlock_irqrestore(&port->lock, flags);
1940 static inline void sx_send_break(struct specialix_port * port, unsigned long length)
1942 struct specialix_board *bp = port_Board(port);
1943 unsigned long flags;
1947 spin_lock_irqsave (&port->lock, flags);
1948 port->break_length = SPECIALIX_TPS / HZ * length;
1949 port->COR2 |= COR2_ETC;
1950 port->IER |= IER_TXRDY;
1951 spin_lock_irqsave(&bp->lock, flags);
1952 sx_out(bp, CD186x_CAR, port_No(port));
1953 sx_out(bp, CD186x_COR2, port->COR2);
1954 sx_out(bp, CD186x_IER, port->IER);
1955 spin_unlock_irqrestore(&bp->lock, flags);
1956 spin_unlock_irqrestore (&port->lock, flags);
1958 spin_lock_irqsave(&bp->lock, flags);
1959 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
1960 spin_unlock_irqrestore(&bp->lock, flags);
1967 static inline int sx_set_serial_info(struct specialix_port * port,
1968 struct serial_struct __user * newinfo)
1970 struct serial_struct tmp;
1971 struct specialix_board *bp = port_Board(port);
1976 if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) {
1981 if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
1987 if ((tmp.irq != bp->irq) ||
1988 (tmp.port != bp->base) ||
1989 (tmp.type != PORT_CIRRUS) ||
1990 (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
1991 (tmp.custom_divisor != 0) ||
1992 (tmp.xmit_fifo_size != CD186x_NFIFO) ||
1993 (tmp.flags & ~SPECIALIX_LEGAL_FLAGS)) {
1999 change_speed = ((port->flags & ASYNC_SPD_MASK) !=
2000 (tmp.flags & ASYNC_SPD_MASK));
2001 change_speed |= (tmp.custom_divisor != port->custom_divisor);
2003 if (!capable(CAP_SYS_ADMIN)) {
2004 if ((tmp.close_delay != port->close_delay) ||
2005 (tmp.closing_wait != port->closing_wait) ||
2006 ((tmp.flags & ~ASYNC_USR_MASK) !=
2007 (port->flags & ~ASYNC_USR_MASK))) {
2011 port->flags = ((port->flags & ~ASYNC_USR_MASK) |
2012 (tmp.flags & ASYNC_USR_MASK));
2013 port->custom_divisor = tmp.custom_divisor;
2015 port->flags = ((port->flags & ~ASYNC_FLAGS) |
2016 (tmp.flags & ASYNC_FLAGS));
2017 port->close_delay = tmp.close_delay;
2018 port->closing_wait = tmp.closing_wait;
2019 port->custom_divisor = tmp.custom_divisor;
2022 sx_change_speed(bp, port);
2029 static inline int sx_get_serial_info(struct specialix_port * port,
2030 struct serial_struct __user *retinfo)
2032 struct serial_struct tmp;
2033 struct specialix_board *bp = port_Board(port);
2038 if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
2042 memset(&tmp, 0, sizeof(tmp));
2043 tmp.type = PORT_CIRRUS;
2044 tmp.line = port - sx_port;
2045 tmp.port = bp->base;
2047 tmp.flags = port->flags;
2048 tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
2049 tmp.close_delay = port->close_delay * HZ/100;
2050 tmp.closing_wait = port->closing_wait * HZ/100;
2051 tmp.custom_divisor = port->custom_divisor;
2052 tmp.xmit_fifo_size = CD186x_NFIFO;
2053 if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
2063 static int sx_ioctl(struct tty_struct * tty, struct file * filp,
2064 unsigned int cmd, unsigned long arg)
2066 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2068 void __user *argp = (void __user *)arg;
2072 if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
2078 case TCSBRK: /* SVID version: non-zero arg --> no break */
2079 retval = tty_check_change(tty);
2084 tty_wait_until_sent(tty, 0);
2086 sx_send_break(port, HZ/4); /* 1/4 second */
2088 case TCSBRKP: /* support for POSIX tcsendbreak() */
2089 retval = tty_check_change(tty);
2094 tty_wait_until_sent(tty, 0);
2095 sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
2099 if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) {
2106 if (get_user(arg, (unsigned long __user *) argp)) {
2110 tty->termios->c_cflag =
2111 ((tty->termios->c_cflag & ~CLOCAL) |
2112 (arg ? CLOCAL : 0));
2117 return sx_get_serial_info(port, argp);
2120 return sx_set_serial_info(port, argp);
2123 return -ENOIOCTLCMD;
2130 static void sx_throttle(struct tty_struct * tty)
2132 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2133 struct specialix_board *bp;
2134 unsigned long flags;
2138 if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
2143 bp = port_Board(port);
2145 /* Use DTR instead of RTS ! */
2146 if (SX_CRTSCTS (tty))
2147 port->MSVR &= ~MSVR_DTR;
2149 /* Auch!!! I think the system shouldn't call this then. */
2150 /* Or maybe we're supposed (allowed?) to do our side of hw
2151 handshake anyway, even when hardware handshake is off.
2152 When you see this in your logs, please report.... */
2153 printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
2156 spin_lock_irqsave(&bp->lock, flags);
2157 sx_out(bp, CD186x_CAR, port_No(port));
2158 spin_unlock_irqrestore(&bp->lock, flags);
2160 spin_unlock_irqrestore(&bp->lock, flags);
2162 spin_lock_irqsave(&bp->lock, flags);
2163 sx_out(bp, CD186x_CCR, CCR_SSCH2);
2164 spin_unlock_irqrestore(&bp->lock, flags);
2167 spin_lock_irqsave(&bp->lock, flags);
2168 sx_out(bp, CD186x_MSVR, port->MSVR);
2169 spin_unlock_irqrestore(&bp->lock, flags);
2175 static void sx_unthrottle(struct tty_struct * tty)
2177 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2178 struct specialix_board *bp;
2179 unsigned long flags;
2183 if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
2188 bp = port_Board(port);
2190 spin_lock_irqsave(&port->lock, flags);
2191 /* XXXX Use DTR INSTEAD???? */
2192 if (SX_CRTSCTS(tty)) {
2193 port->MSVR |= MSVR_DTR;
2194 } /* Else clause: see remark in "sx_throttle"... */
2195 spin_lock_irqsave(&bp->lock, flags);
2196 sx_out(bp, CD186x_CAR, port_No(port));
2197 spin_unlock_irqrestore(&bp->lock, flags);
2199 spin_unlock_irqrestore(&port->lock, flags);
2201 spin_lock_irqsave(&bp->lock, flags);
2202 sx_out(bp, CD186x_CCR, CCR_SSCH1);
2203 spin_unlock_irqrestore(&bp->lock, flags);
2205 spin_lock_irqsave(&port->lock, flags);
2207 spin_lock_irqsave(&bp->lock, flags);
2208 sx_out(bp, CD186x_MSVR, port->MSVR);
2209 spin_unlock_irqrestore(&bp->lock, flags);
2210 spin_unlock_irqrestore(&port->lock, flags);
2216 static void sx_stop(struct tty_struct * tty)
2218 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2219 struct specialix_board *bp;
2220 unsigned long flags;
2224 if (sx_paranoia_check(port, tty->name, "sx_stop")) {
2229 bp = port_Board(port);
2231 spin_lock_irqsave(&port->lock, flags);
2232 port->IER &= ~IER_TXRDY;
2233 spin_lock_irqsave(&bp->lock, flags);
2234 sx_out(bp, CD186x_CAR, port_No(port));
2235 sx_out(bp, CD186x_IER, port->IER);
2236 spin_unlock_irqrestore(&bp->lock, flags);
2237 spin_unlock_irqrestore(&port->lock, flags);
2243 static void sx_start(struct tty_struct * tty)
2245 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2246 struct specialix_board *bp;
2247 unsigned long flags;
2251 if (sx_paranoia_check(port, tty->name, "sx_start")) {
2256 bp = port_Board(port);
2258 spin_lock_irqsave(&port->lock, flags);
2259 if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
2260 port->IER |= IER_TXRDY;
2261 spin_lock_irqsave(&bp->lock, flags);
2262 sx_out(bp, CD186x_CAR, port_No(port));
2263 sx_out(bp, CD186x_IER, port->IER);
2264 spin_unlock_irqrestore(&bp->lock, flags);
2266 spin_unlock_irqrestore(&port->lock, flags);
2273 * This routine is called from the work-queue when the interrupt
2274 * routine has signalled that a hangup has occurred. The path of
2275 * hangup processing is:
2277 * serial interrupt routine -> (workqueue) ->
2278 * do_sx_hangup() -> tty->hangup() -> sx_hangup()
2281 static void do_sx_hangup(void *private_)
2283 struct specialix_port *port = (struct specialix_port *) private_;
2284 struct tty_struct *tty;
2290 tty_hangup(tty); /* FIXME: module removal race here */
2296 static void sx_hangup(struct tty_struct * tty)
2298 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2299 struct specialix_board *bp;
2300 unsigned long flags;
2304 if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
2309 bp = port_Board(port);
2311 sx_shutdown_port(bp, port);
2312 spin_lock_irqsave(&port->lock, flags);
2314 bp->count -= port->count;
2315 if (bp->count < 0) {
2316 printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n",
2317 board_No(bp), bp->count, tty->index);
2321 port->flags &= ~ASYNC_NORMAL_ACTIVE;
2323 spin_unlock_irqrestore(&port->lock, flags);
2324 wake_up_interruptible(&port->open_wait);
2330 static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios)
2332 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2333 unsigned long flags;
2334 struct specialix_board * bp;
2336 if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
2339 if (tty->termios->c_cflag == old_termios->c_cflag &&
2340 tty->termios->c_iflag == old_termios->c_iflag)
2343 bp = port_Board(port);
2344 spin_lock_irqsave(&port->lock, flags);
2345 sx_change_speed(port_Board(port), port);
2346 spin_unlock_irqrestore(&port->lock, flags);
2348 if ((old_termios->c_cflag & CRTSCTS) &&
2349 !(tty->termios->c_cflag & CRTSCTS)) {
2350 tty->hw_stopped = 0;
2356 static void do_softint(void *private_)
2358 struct specialix_port *port = (struct specialix_port *) private_;
2359 struct tty_struct *tty;
2363 if(!(tty = port->tty)) {
2368 if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
2370 //wake_up_interruptible(&tty->write_wait);
2376 static struct tty_operations sx_ops = {
2380 .put_char = sx_put_char,
2381 .flush_chars = sx_flush_chars,
2382 .write_room = sx_write_room,
2383 .chars_in_buffer = sx_chars_in_buffer,
2384 .flush_buffer = sx_flush_buffer,
2386 .throttle = sx_throttle,
2387 .unthrottle = sx_unthrottle,
2388 .set_termios = sx_set_termios,
2391 .hangup = sx_hangup,
2392 .tiocmget = sx_tiocmget,
2393 .tiocmset = sx_tiocmset,
2396 static int sx_init_drivers(void)
2403 specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
2404 if (!specialix_driver) {
2405 printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
2410 if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
2411 printk(KERN_ERR "sx: Couldn't get free page.\n");
2412 put_tty_driver(specialix_driver);
2416 specialix_driver->owner = THIS_MODULE;
2417 specialix_driver->name = "ttyW";
2418 specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
2419 specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
2420 specialix_driver->subtype = SERIAL_TYPE_NORMAL;
2421 specialix_driver->init_termios = tty_std_termios;
2422 specialix_driver->init_termios.c_cflag =
2423 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2424 specialix_driver->flags = TTY_DRIVER_REAL_RAW;
2425 tty_set_operations(specialix_driver, &sx_ops);
2427 if ((error = tty_register_driver(specialix_driver))) {
2428 put_tty_driver(specialix_driver);
2429 free_page((unsigned long)tmp_buf);
2430 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2435 memset(sx_port, 0, sizeof(sx_port));
2436 for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
2437 sx_port[i].magic = SPECIALIX_MAGIC;
2438 INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]);
2439 INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]);
2440 sx_port[i].close_delay = 50 * HZ/100;
2441 sx_port[i].closing_wait = 3000 * HZ/100;
2442 init_waitqueue_head(&sx_port[i].open_wait);
2443 init_waitqueue_head(&sx_port[i].close_wait);
2444 spin_lock_init(&sx_port[i].lock);
2451 static void sx_release_drivers(void)
2455 free_page((unsigned long)tmp_buf);
2456 tty_unregister_driver(specialix_driver);
2457 put_tty_driver(specialix_driver);
2462 * This routine must be called by kernel at boot time
2464 static int __init specialix_init(void)
2471 printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
2472 printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2473 #ifdef CONFIG_SPECIALIX_RTSCTS
2474 printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
2476 printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2479 for (i = 0; i < SX_NBOARD; i++)
2480 sx_board[i].lock = SPIN_LOCK_UNLOCKED;
2482 if (sx_init_drivers()) {
2487 for (i = 0; i < SX_NBOARD; i++)
2488 if (sx_board[i].base && !sx_probe(&sx_board[i]))
2493 struct pci_dev *pdev = NULL;
2496 while (i < SX_NBOARD) {
2497 if (sx_board[i].flags & SX_BOARD_PRESENT) {
2501 pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
2502 PCI_DEVICE_ID_SPECIALIX_IO8,
2506 if (pci_enable_device(pdev))
2509 sx_board[i].irq = pdev->irq;
2511 sx_board[i].base = pci_resource_start (pdev, 2);
2513 sx_board[i].flags |= SX_BOARD_IS_PCI;
2514 if (!sx_probe(&sx_board[i]))
2521 sx_release_drivers();
2522 printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
2531 static int iobase[SX_NBOARD] = {0,};
2533 static int irq [SX_NBOARD] = {0,};
2535 module_param_array(iobase, int, NULL, 0);
2536 module_param_array(irq, int, NULL, 0);
2537 module_param(sx_debug, int, 0);
2538 module_param(sx_rxfifo, int, 0);
2539 #ifdef SPECIALIX_TIMER
2540 module_param(sx_poll, int, 0);
2544 * You can setup up to 4 boards.
2545 * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
2546 * You should specify the IRQs too in that case "irq=....,...".
2548 * More than 4 boards in one computer is not possible, as the card can
2549 * only use 4 different interrupts.
2552 static int __init specialix_init_module(void)
2558 if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
2559 for(i = 0; i < SX_NBOARD; i++) {
2560 sx_board[i].base = iobase[i];
2561 sx_board[i].irq = irq[i];
2562 sx_board[i].count= 0;
2568 return specialix_init();
2571 static void __exit specialix_exit_module(void)
2577 sx_release_drivers();
2578 for (i = 0; i < SX_NBOARD; i++)
2579 if (sx_board[i].flags & SX_BOARD_PRESENT)
2580 sx_release_io_range(&sx_board[i]);
2581 #ifdef SPECIALIX_TIMER
2582 del_timer (&missed_irq_timer);
2588 module_init(specialix_init_module);
2589 module_exit(specialix_exit_module);
2591 MODULE_LICENSE("GPL");