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