vserver 1.9.3
[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                         current->state = TASK_INTERRUPTIBLE;
1456                         schedule_timeout(port->timeout);
1457                         if (time_after(jiffies, timeout)) {
1458                                 printk (KERN_INFO "Timeout waiting for close\n");
1459                                 break;
1460                         }
1461                 }
1462
1463         }
1464         sx_shutdown_port(bp, port);
1465         if (tty->driver->flush_buffer)
1466                 tty->driver->flush_buffer(tty);
1467         tty_ldisc_flush(tty);
1468         tty->closing = 0;
1469         port->event = 0;
1470         port->tty = NULL;
1471         if (port->blocked_open) {
1472                 if (port->close_delay) {
1473                         current->state = TASK_INTERRUPTIBLE;
1474                         schedule_timeout(port->close_delay);
1475                 }
1476                 wake_up_interruptible(&port->open_wait);
1477         }
1478         port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1479         wake_up_interruptible(&port->close_wait);
1480         restore_flags(flags);
1481 }
1482
1483
1484 static int sx_write(struct tty_struct * tty, int from_user, 
1485                     const unsigned char *buf, int count)
1486 {
1487         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1488         struct specialix_board *bp;
1489         int c, total = 0;
1490         unsigned long flags;
1491                                 
1492         if (sx_paranoia_check(port, tty->name, "sx_write"))
1493                 return 0;
1494         
1495         bp = port_Board(port);
1496
1497         if (!tty || !port->xmit_buf || !tmp_buf)
1498                 return 0;
1499
1500         save_flags(flags);
1501         if (from_user) {
1502                 down(&tmp_buf_sem);
1503                 while (1) {
1504                         c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1505                                            SERIAL_XMIT_SIZE - port->xmit_head));
1506                         if (c <= 0)
1507                                 break;
1508
1509                         c -= copy_from_user(tmp_buf, buf, c);
1510                         if (!c) {
1511                                 if (!total)
1512                                         total = -EFAULT;
1513                                 break;
1514                         }
1515
1516                         cli();
1517                         c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1518                                        SERIAL_XMIT_SIZE - port->xmit_head));
1519                         memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
1520                         port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1521                         port->xmit_cnt += c;
1522                         restore_flags(flags);
1523
1524                         buf += c;
1525                         count -= c;
1526                         total += c;
1527                 }
1528                 up(&tmp_buf_sem);
1529         } else {
1530                 while (1) {
1531                         cli();
1532                         c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1533                                            SERIAL_XMIT_SIZE - port->xmit_head));
1534                         if (c <= 0) {
1535                                 restore_flags(flags);
1536                                 break;
1537                         }
1538                         memcpy(port->xmit_buf + port->xmit_head, buf, c);
1539                         port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1540                         port->xmit_cnt += c;
1541                         restore_flags(flags);
1542
1543                         buf += c;
1544                         count -= c;
1545                         total += c;
1546                 }
1547         }
1548
1549         cli();
1550         if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1551             !(port->IER & IER_TXRDY)) {
1552                 port->IER |= IER_TXRDY;
1553                 sx_out(bp, CD186x_CAR, port_No(port));
1554                 sx_out(bp, CD186x_IER, port->IER);
1555         }
1556         restore_flags(flags);
1557         return total;
1558 }
1559
1560
1561 static void sx_put_char(struct tty_struct * tty, unsigned char ch)
1562 {
1563         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1564         unsigned long flags;
1565
1566         if (sx_paranoia_check(port, tty->name, "sx_put_char"))
1567                 return;
1568
1569         if (!tty || !port->xmit_buf)
1570                 return;
1571
1572         save_flags(flags); cli();
1573         
1574         if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
1575                 restore_flags(flags);
1576                 return;
1577         }
1578
1579         port->xmit_buf[port->xmit_head++] = ch;
1580         port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1581         port->xmit_cnt++;
1582         restore_flags(flags);
1583 }
1584
1585
1586 static void sx_flush_chars(struct tty_struct * tty)
1587 {
1588         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1589         unsigned long flags;
1590                                 
1591         if (sx_paranoia_check(port, tty->name, "sx_flush_chars"))
1592                 return;
1593         
1594         if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1595             !port->xmit_buf)
1596                 return;
1597
1598         save_flags(flags); cli();
1599         port->IER |= IER_TXRDY;
1600         sx_out(port_Board(port), CD186x_CAR, port_No(port));
1601         sx_out(port_Board(port), CD186x_IER, port->IER);
1602         restore_flags(flags);
1603 }
1604
1605
1606 static int sx_write_room(struct tty_struct * tty)
1607 {
1608         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1609         int     ret;
1610                                 
1611         if (sx_paranoia_check(port, tty->name, "sx_write_room"))
1612                 return 0;
1613
1614         ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1615         if (ret < 0)
1616                 ret = 0;
1617         return ret;
1618 }
1619
1620
1621 static int sx_chars_in_buffer(struct tty_struct *tty)
1622 {
1623         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1624                                 
1625         if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer"))
1626                 return 0;
1627         
1628         return port->xmit_cnt;
1629 }
1630
1631
1632 static void sx_flush_buffer(struct tty_struct *tty)
1633 {
1634         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1635         unsigned long flags;
1636                                 
1637         if (sx_paranoia_check(port, tty->name, "sx_flush_buffer"))
1638                 return;
1639
1640         save_flags(flags); cli();
1641         port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1642         restore_flags(flags);
1643         
1644         tty_wakeup(tty);
1645         wake_up_interruptible(&tty->write_wait);
1646 }
1647
1648
1649 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1650 {
1651         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1652         struct specialix_board * bp;
1653         unsigned char status;
1654         unsigned int result;
1655         unsigned long flags;
1656
1657         if (sx_paranoia_check(port, tty->name, __FUNCTION__))
1658                 return -ENODEV;
1659
1660         bp = port_Board(port);
1661         save_flags(flags); cli();
1662         sx_out(bp, CD186x_CAR, port_No(port));
1663         status = sx_in(bp, CD186x_MSVR);
1664         restore_flags(flags);
1665 #ifdef DEBUG_SPECIALIX
1666         printk (KERN_DEBUG "Got msvr[%d] = %02x, car = %d.\n", 
1667                 port_No(port), status, sx_in (bp, CD186x_CAR));
1668         printk (KERN_DEBUG "sx_port = %p, port = %p\n", sx_port, port);
1669 #endif
1670         if (SX_CRTSCTS(port->tty)) {
1671                 result  = /*   (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ 
1672                           |   ((status & MSVR_DTR) ? TIOCM_RTS : 0)
1673                           |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
1674                           |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1675                           |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1676         } else {
1677                 result  = /*   (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ 
1678                           |   ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1679                           |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
1680                           |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1681                           |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1682         }
1683
1684         return result;
1685 }
1686
1687
1688 static int sx_tiocmset(struct tty_struct *tty, struct file *file,
1689                        unsigned int set, unsigned int clear)
1690 {
1691         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1692         unsigned long flags;
1693         struct specialix_board *bp;
1694
1695         if (sx_paranoia_check(port, tty->name, __FUNCTION__))
1696                 return -ENODEV;
1697
1698         bp = port_Board(port);
1699
1700         save_flags(flags); cli();
1701    /*   if (set & TIOCM_RTS)
1702                 port->MSVR |= MSVR_RTS; */
1703    /*   if (set & TIOCM_DTR)
1704                 port->MSVR |= MSVR_DTR; */
1705
1706         if (SX_CRTSCTS(port->tty)) {
1707                 if (set & TIOCM_RTS)
1708                         port->MSVR |= MSVR_DTR;
1709         } else {
1710                 if (set & TIOCM_DTR)
1711                         port->MSVR |= MSVR_DTR;
1712         }
1713
1714   /*    if (clear & TIOCM_RTS)
1715                 port->MSVR &= ~MSVR_RTS; */
1716   /*    if (clear & TIOCM_DTR)
1717                 port->MSVR &= ~MSVR_DTR; */
1718         if (SX_CRTSCTS(port->tty)) {
1719                 if (clear & TIOCM_RTS)
1720                         port->MSVR &= ~MSVR_DTR;
1721         } else {
1722                 if (clear & TIOCM_DTR)
1723                         port->MSVR &= ~MSVR_DTR;
1724         }
1725
1726         sx_out(bp, CD186x_CAR, port_No(port));
1727         sx_out(bp, CD186x_MSVR, port->MSVR);
1728         restore_flags(flags);
1729         return 0;
1730 }
1731
1732
1733 static inline void sx_send_break(struct specialix_port * port, unsigned long length)
1734 {
1735         struct specialix_board *bp = port_Board(port);
1736         unsigned long flags;
1737         
1738         save_flags(flags); cli();
1739         port->break_length = SPECIALIX_TPS / HZ * length;
1740         port->COR2 |= COR2_ETC;
1741         port->IER  |= IER_TXRDY;
1742         sx_out(bp, CD186x_CAR, port_No(port));
1743         sx_out(bp, CD186x_COR2, port->COR2);
1744         sx_out(bp, CD186x_IER, port->IER);
1745         sx_wait_CCR(bp);
1746         sx_out(bp, CD186x_CCR, CCR_CORCHG2);
1747         sx_wait_CCR(bp);
1748         restore_flags(flags);
1749 }
1750
1751
1752 static inline int sx_set_serial_info(struct specialix_port * port,
1753                                      struct serial_struct __user * newinfo)
1754 {
1755         struct serial_struct tmp;
1756         struct specialix_board *bp = port_Board(port);
1757         int change_speed;
1758         unsigned long flags;
1759         
1760         if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
1761                 return -EFAULT;
1762         
1763 #if 0   
1764         if ((tmp.irq != bp->irq) ||
1765             (tmp.port != bp->base) ||
1766             (tmp.type != PORT_CIRRUS) ||
1767             (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
1768             (tmp.custom_divisor != 0) ||
1769             (tmp.xmit_fifo_size != CD186x_NFIFO) ||
1770             (tmp.flags & ~SPECIALIX_LEGAL_FLAGS))
1771                 return -EINVAL;
1772 #endif  
1773
1774         change_speed = ((port->flags & ASYNC_SPD_MASK) !=
1775                         (tmp.flags & ASYNC_SPD_MASK));
1776         change_speed |= (tmp.custom_divisor != port->custom_divisor);
1777         
1778         if (!capable(CAP_SYS_ADMIN)) {
1779                 if ((tmp.close_delay != port->close_delay) ||
1780                     (tmp.closing_wait != port->closing_wait) ||
1781                     ((tmp.flags & ~ASYNC_USR_MASK) !=
1782                      (port->flags & ~ASYNC_USR_MASK)))
1783                         return -EPERM;
1784                 port->flags = ((port->flags & ~ASYNC_USR_MASK) |
1785                                   (tmp.flags & ASYNC_USR_MASK));
1786                 port->custom_divisor = tmp.custom_divisor;
1787         } else {
1788                 port->flags = ((port->flags & ~ASYNC_FLAGS) |
1789                                   (tmp.flags & ASYNC_FLAGS));
1790                 port->close_delay = tmp.close_delay;
1791                 port->closing_wait = tmp.closing_wait;
1792                 port->custom_divisor = tmp.custom_divisor;
1793         }
1794         if (change_speed) {
1795                 save_flags(flags); cli();
1796                 sx_change_speed(bp, port);
1797                 restore_flags(flags);
1798         }
1799         return 0;
1800 }
1801
1802
1803 static inline int sx_get_serial_info(struct specialix_port * port,
1804                                      struct serial_struct __user *retinfo)
1805 {
1806         struct serial_struct tmp;
1807         struct specialix_board *bp = port_Board(port);
1808         
1809         memset(&tmp, 0, sizeof(tmp));
1810         tmp.type = PORT_CIRRUS;
1811         tmp.line = port - sx_port;
1812         tmp.port = bp->base;
1813         tmp.irq  = bp->irq;
1814         tmp.flags = port->flags;
1815         tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
1816         tmp.close_delay = port->close_delay * HZ/100;
1817         tmp.closing_wait = port->closing_wait * HZ/100;
1818         tmp.custom_divisor =  port->custom_divisor;
1819         tmp.xmit_fifo_size = CD186x_NFIFO;
1820         if (copy_to_user(retinfo, &tmp, sizeof(tmp)))
1821                 return -EFAULT;
1822         return 0;
1823 }
1824
1825
1826 static int sx_ioctl(struct tty_struct * tty, struct file * filp, 
1827                     unsigned int cmd, unsigned long arg)
1828 {
1829         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1830         int retval;
1831         void __user *argp = (void __user *)arg;
1832                                 
1833         if (sx_paranoia_check(port, tty->name, "sx_ioctl"))
1834                 return -ENODEV;
1835         
1836         switch (cmd) {
1837          case TCSBRK:   /* SVID version: non-zero arg --> no break */
1838                 retval = tty_check_change(tty);
1839                 if (retval)
1840                         return retval;
1841                 tty_wait_until_sent(tty, 0);
1842                 if (!arg)
1843                         sx_send_break(port, HZ/4);      /* 1/4 second */
1844                 return 0;
1845          case TCSBRKP:  /* support for POSIX tcsendbreak() */
1846                 retval = tty_check_change(tty);
1847                 if (retval)
1848                         return retval;
1849                 tty_wait_until_sent(tty, 0);
1850                 sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
1851                 return 0;
1852          case TIOCGSOFTCAR:
1853                 if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp))
1854                         return -EFAULT;
1855                 return 0;
1856          case TIOCSSOFTCAR:
1857                 if (get_user(arg, (unsigned long __user *) argp))
1858                         return -EFAULT;
1859                 tty->termios->c_cflag =
1860                         ((tty->termios->c_cflag & ~CLOCAL) |
1861                         (arg ? CLOCAL : 0));
1862                 return 0;
1863          case TIOCGSERIAL:      
1864                 return sx_get_serial_info(port, argp);
1865          case TIOCSSERIAL:      
1866                 return sx_set_serial_info(port, argp);
1867          default:
1868                 return -ENOIOCTLCMD;
1869         }
1870         return 0;
1871 }
1872
1873
1874 static void sx_throttle(struct tty_struct * tty)
1875 {
1876         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1877         struct specialix_board *bp;
1878         unsigned long flags;
1879                                 
1880         if (sx_paranoia_check(port, tty->name, "sx_throttle"))
1881                 return;
1882         
1883         bp = port_Board(port);
1884         
1885         save_flags(flags); cli();
1886
1887         /* Use DTR instead of RTS ! */
1888         if (SX_CRTSCTS (tty)) 
1889                 port->MSVR &= ~MSVR_DTR;
1890         else {
1891                 /* Auch!!! I think the system shouldn't call this then. */
1892                 /* Or maybe we're supposed (allowed?) to do our side of hw
1893                    handshake anyway, even when hardware handshake is off. 
1894                    When you see this in your logs, please report.... */
1895                 printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
1896                          port_No (port));
1897         }
1898         sx_out(bp, CD186x_CAR, port_No(port));
1899         if (I_IXOFF(tty)) {
1900                 sx_wait_CCR(bp);
1901                 sx_out(bp, CD186x_CCR, CCR_SSCH2);
1902                 sx_wait_CCR(bp);
1903         }
1904         sx_out(bp, CD186x_MSVR, port->MSVR);
1905         restore_flags(flags);
1906 }
1907
1908
1909 static void sx_unthrottle(struct tty_struct * tty)
1910 {
1911         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1912         struct specialix_board *bp;
1913         unsigned long flags;
1914                                 
1915         if (sx_paranoia_check(port, tty->name, "sx_unthrottle"))
1916                 return;
1917         
1918         bp = port_Board(port);
1919         
1920         save_flags(flags); cli();
1921         /* XXXX Use DTR INSTEAD???? */
1922         if (SX_CRTSCTS(tty)) {
1923                 port->MSVR |= MSVR_DTR;
1924         } /* Else clause: see remark in "sx_throttle"... */
1925
1926         sx_out(bp, CD186x_CAR, port_No(port));
1927         if (I_IXOFF(tty)) {
1928                 sx_wait_CCR(bp);
1929                 sx_out(bp, CD186x_CCR, CCR_SSCH1);
1930                 sx_wait_CCR(bp);
1931         }
1932         sx_out(bp, CD186x_MSVR, port->MSVR);
1933         restore_flags(flags);
1934 }
1935
1936
1937 static void sx_stop(struct tty_struct * tty)
1938 {
1939         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1940         struct specialix_board *bp;
1941         unsigned long flags;
1942                                 
1943         if (sx_paranoia_check(port, tty->name, "sx_stop"))
1944                 return;
1945         
1946         bp = port_Board(port);
1947         
1948         save_flags(flags); cli();
1949         port->IER &= ~IER_TXRDY;
1950         sx_out(bp, CD186x_CAR, port_No(port));
1951         sx_out(bp, CD186x_IER, port->IER);
1952         restore_flags(flags);
1953 }
1954
1955
1956 static void sx_start(struct tty_struct * tty)
1957 {
1958         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1959         struct specialix_board *bp;
1960         unsigned long flags;
1961                                 
1962         if (sx_paranoia_check(port, tty->name, "sx_start"))
1963                 return;
1964         
1965         bp = port_Board(port);
1966         
1967         save_flags(flags); cli();
1968         if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
1969                 port->IER |= IER_TXRDY;
1970                 sx_out(bp, CD186x_CAR, port_No(port));
1971                 sx_out(bp, CD186x_IER, port->IER);
1972         }
1973         restore_flags(flags);
1974 }
1975
1976
1977 /*
1978  * This routine is called from the work-queue when the interrupt
1979  * routine has signalled that a hangup has occurred.  The path of
1980  * hangup processing is:
1981  *
1982  *      serial interrupt routine -> (workqueue) ->
1983  *      do_sx_hangup() -> tty->hangup() -> sx_hangup()
1984  * 
1985  */
1986 static void do_sx_hangup(void *private_)
1987 {
1988         struct specialix_port   *port = (struct specialix_port *) private_;
1989         struct tty_struct       *tty;
1990         
1991         tty = port->tty;
1992         if (tty)
1993                 tty_hangup(tty);        /* FIXME: module removal race here */
1994 }
1995
1996
1997 static void sx_hangup(struct tty_struct * tty)
1998 {
1999         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2000         struct specialix_board *bp;
2001                                 
2002         if (sx_paranoia_check(port, tty->name, "sx_hangup"))
2003                 return;
2004         
2005         bp = port_Board(port);
2006         
2007         sx_shutdown_port(bp, port);
2008         port->event = 0;
2009         port->count = 0;
2010         port->flags &= ~ASYNC_NORMAL_ACTIVE;
2011         port->tty = NULL;
2012         wake_up_interruptible(&port->open_wait);
2013 }
2014
2015
2016 static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios)
2017 {
2018         struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2019         unsigned long flags;
2020                                 
2021         if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
2022                 return;
2023         
2024         if (tty->termios->c_cflag == old_termios->c_cflag &&
2025             tty->termios->c_iflag == old_termios->c_iflag)
2026                 return;
2027
2028         save_flags(flags); cli();
2029         sx_change_speed(port_Board(port), port);
2030         restore_flags(flags);
2031
2032         if ((old_termios->c_cflag & CRTSCTS) &&
2033             !(tty->termios->c_cflag & CRTSCTS)) {
2034                 tty->hw_stopped = 0;
2035                 sx_start(tty);
2036         }
2037 }
2038
2039
2040 static void do_softint(void *private_)
2041 {
2042         struct specialix_port   *port = (struct specialix_port *) private_;
2043         struct tty_struct       *tty;
2044         
2045         if(!(tty = port->tty)) 
2046                 return;
2047
2048         if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
2049                 tty_wakeup(tty);
2050 }
2051
2052 static struct tty_operations sx_ops = {
2053         .open  = sx_open,
2054         .close = sx_close,
2055         .write = sx_write,
2056         .put_char = sx_put_char,
2057         .flush_chars = sx_flush_chars,
2058         .write_room = sx_write_room,
2059         .chars_in_buffer = sx_chars_in_buffer,
2060         .flush_buffer = sx_flush_buffer,
2061         .ioctl = sx_ioctl,
2062         .throttle = sx_throttle,
2063         .unthrottle = sx_unthrottle,
2064         .set_termios = sx_set_termios,
2065         .stop = sx_stop,
2066         .start = sx_start,
2067         .hangup = sx_hangup,
2068         .tiocmget = sx_tiocmget,
2069         .tiocmset = sx_tiocmset,
2070 };
2071
2072 static int sx_init_drivers(void)
2073 {
2074         int error;
2075         int i;
2076
2077         specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
2078         if (!specialix_driver) {
2079                 printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
2080                 return 1;
2081         }
2082         
2083         if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
2084                 printk(KERN_ERR "sx: Couldn't get free page.\n");
2085                 put_tty_driver(specialix_driver);
2086                 return 1;
2087         }
2088         specialix_driver->owner = THIS_MODULE;
2089         specialix_driver->name = "ttyW";
2090         specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
2091         specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
2092         specialix_driver->subtype = SERIAL_TYPE_NORMAL;
2093         specialix_driver->init_termios = tty_std_termios;
2094         specialix_driver->init_termios.c_cflag =
2095                 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2096         specialix_driver->flags = TTY_DRIVER_REAL_RAW;
2097         tty_set_operations(specialix_driver, &sx_ops);
2098
2099         if ((error = tty_register_driver(specialix_driver))) {
2100                 put_tty_driver(specialix_driver);
2101                 free_page((unsigned long)tmp_buf);
2102                 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2103                        error);
2104                 return 1;
2105         }
2106         memset(sx_port, 0, sizeof(sx_port));
2107         for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
2108                 sx_port[i].magic = SPECIALIX_MAGIC;
2109                 INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]);
2110                 INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]);
2111                 sx_port[i].close_delay = 50 * HZ/100;
2112                 sx_port[i].closing_wait = 3000 * HZ/100;
2113                 init_waitqueue_head(&sx_port[i].open_wait);
2114                 init_waitqueue_head(&sx_port[i].close_wait);
2115         }
2116         
2117         return 0;
2118 }
2119
2120
2121 static void sx_release_drivers(void)
2122 {
2123         free_page((unsigned long)tmp_buf);
2124         tty_unregister_driver(specialix_driver);
2125         put_tty_driver(specialix_driver);
2126 }
2127
2128
2129 #ifndef MODULE
2130 /*
2131  * Called at boot time.
2132  * 
2133  * You can specify IO base for up to SX_NBOARD cards,
2134  * using line "specialix=0xiobase1,0xiobase2,.." at LILO prompt.
2135  * Note that there will be no probing at default
2136  * addresses in this case.
2137  *
2138  */ 
2139 void specialix_setup(char *str, int * ints)
2140 {
2141         int i;
2142         
2143         for (i=0;i<SX_NBOARD;i++) {
2144                 sx_board[i].base = 0;
2145         }
2146
2147         for (i = 1; i <= ints[0]; i++) {
2148                 if (i&1)
2149                         sx_board[i/2].base = ints[i];
2150                 else
2151                         sx_board[i/2 -1].irq = ints[i];
2152         }
2153 }
2154 #endif
2155
2156 /* 
2157  * This routine must be called by kernel at boot time 
2158  */
2159 static int __init specialix_init(void)
2160 {
2161         int i;
2162         int found = 0;
2163
2164         printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
2165         printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2166 #ifdef CONFIG_SPECIALIX_RTSCTS
2167         printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
2168 #else
2169         printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2170 #endif
2171         
2172         if (sx_init_drivers()) 
2173                 return -EIO;
2174
2175         for (i = 0; i < SX_NBOARD; i++) 
2176                 if (sx_board[i].base && !sx_probe(&sx_board[i]))
2177                         found++;
2178
2179 #ifdef CONFIG_PCI
2180         {
2181                 struct pci_dev *pdev = NULL;
2182
2183                 i=0;
2184                 while (i < SX_NBOARD) {
2185                         if (sx_board[i].flags & SX_BOARD_PRESENT) {
2186                                 i++;
2187                                 continue;
2188                         }
2189                         pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
2190                                                 PCI_DEVICE_ID_SPECIALIX_IO8, 
2191                                                 pdev);
2192                         if (!pdev) break;
2193
2194                         if (pci_enable_device(pdev))
2195                                 continue;
2196
2197                         sx_board[i].irq = pdev->irq;
2198
2199                         sx_board[i].base = pci_resource_start (pdev, 2);
2200
2201                         sx_board[i].flags |= SX_BOARD_IS_PCI;
2202                         if (!sx_probe(&sx_board[i]))
2203                                 found ++;
2204                 }
2205         }
2206 #endif
2207
2208         if (!found) {
2209                 sx_release_drivers();
2210                 printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
2211                 return -EIO;
2212         }
2213
2214         return 0;
2215 }
2216
2217 int iobase[SX_NBOARD]  = {0,};
2218
2219 int irq [SX_NBOARD] = {0,};
2220
2221 MODULE_PARM(iobase,"1-" __MODULE_STRING(SX_NBOARD) "i");
2222 MODULE_PARM(irq,"1-" __MODULE_STRING(SX_NBOARD) "i");
2223
2224 /*
2225  * You can setup up to 4 boards.
2226  * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
2227  * You should specify the IRQs too in that case "irq=....,...". 
2228  * 
2229  * More than 4 boards in one computer is not possible, as the card can
2230  * only use 4 different interrupts. 
2231  *
2232  */
2233 static int __init specialix_init_module(void)
2234 {
2235         int i;
2236
2237         if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
2238                 for(i = 0; i < SX_NBOARD; i++) {
2239                         sx_board[i].base = iobase[i];
2240                         sx_board[i].irq = irq[i];
2241                 }
2242         }
2243
2244         return specialix_init();
2245 }
2246         
2247 static void __exit specialix_exit_module(void)
2248 {
2249         int i;
2250         
2251         sx_release_drivers();
2252         for (i = 0; i < SX_NBOARD; i++)
2253                 if (sx_board[i].flags & SX_BOARD_PRESENT) 
2254                         sx_release_io_range(&sx_board[i]);
2255 #ifdef SPECIALIX_TIMER
2256         del_timer (&missed_irq_timer);
2257 #endif
2258         
2259 }
2260
2261 module_init(specialix_init_module);
2262 module_exit(specialix_exit_module);
2263
2264 MODULE_LICENSE("GPL");