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