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