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