* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / char / specialix.c
blob22014dacfe1e7aed0c423d31568e8bcef993e02c
1 /*
2 * specialix.c -- specialix IO8+ multiport serial driver.
4 * Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
5 * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com)
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.
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.
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.
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.
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.
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.
37 * Revision history:
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. .
66 #define VERSION "1.8"
70 * There is a bunch of documentation about the card, jumpers, config
71 * settings, restrictions, cables, device names and numbers in
72 * ../../Documentation/specialix.txt
75 #include <linux/config.h>
76 #include <linux/module.h>
78 #include <asm/io.h>
79 #include <linux/kernel.h>
80 #include <linux/sched.h>
81 #include <linux/ioport.h>
82 #include <linux/interrupt.h>
83 #include <linux/errno.h>
84 #include <linux/tty.h>
85 #include <linux/mm.h>
86 #include <linux/serial.h>
87 #include <linux/fcntl.h>
88 #include <linux/major.h>
89 #include <linux/delay.h>
90 #include <linux/tqueue.h>
91 #include <linux/version.h>
92 #include <linux/pci.h>
95 /* ************************************************************** */
96 /* * This section can be removed when 2.0 becomes outdated.... * */
97 /* ************************************************************** */
99 #if LINUX_VERSION_CODE < 131328 /* Less than 2.1.0 */
100 #define TWO_ZERO
101 #else
102 #if LINUX_VERSION_CODE < 131371 /* less than 2.1.43 */
103 /* This has not been extensively tested yet. Sorry. */
104 #warning "You're on your own between 2.1.0 and 2.1.43.... "
105 #warning "Please use a recent kernel."
106 #endif
107 #endif
110 #ifdef TWO_ZERO
111 #define Get_user(a,b) a = get_user(b)
112 #define copy_from_user(a,b,c) memcpy_fromfs(a,b,c)
113 #define copy_to_user(a,b,c) memcpy_tofs(a,b,c)
114 #define queue_task queue_task_irq_off
115 #else
116 #define Get_user(a,b) get_user(a,b)
117 #endif
119 /* ************************************************************** */
120 /* * End of compatibility section.. * */
121 /* ************************************************************** */
124 #ifndef TWO_ZERO
125 #include <asm/uaccess.h>
126 #endif
128 #include "specialix_io8.h"
129 #include "cd1865.h"
133 /* Configurable options: */
135 /* Am I paranoid or not ? ;-) */
136 #define SPECIALIX_PARANOIA_CHECK
138 /* Do I trust the IRQ from the card? (enabeling it doesn't seem to help)
139 When the IRQ routine leaves the chip in a state that is keeps on
140 requiring attention, the timer doesn't help either. */
141 #undef SPECIALIX_TIMER
144 * The following defines are mostly for testing purposes. But if you need
145 * some nice reporting in your syslog, you can define them also.
147 #undef SX_REPORT_FIFO
148 #undef SX_REPORT_OVERRUN
152 #ifdef CONFIG_SPECIALIX_RTSCTS
153 #define SX_CRTSCTS(bla) 1
154 #else
155 #define SX_CRTSCTS(tty) C_CRTSCTS(tty)
156 #endif
159 /* Used to be outb (0xff, 0x80); */
160 #define short_pause() udelay (1)
163 #define SPECIALIX_LEGAL_FLAGS \
164 (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \
165 ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \
166 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
168 #ifndef MIN
169 #define MIN(a,b) ((a) < (b) ? (a) : (b))
170 #endif
172 DECLARE_TASK_QUEUE(tq_specialix);
176 #define SPECIALIX_TYPE_NORMAL 1
177 #define SPECIALIX_TYPE_CALLOUT 2
179 static struct tty_driver specialix_driver, specialix_callout_driver;
180 static int specialix_refcount = 0;
181 static struct tty_struct * specialix_table[SX_NBOARD * SX_NPORT] = { NULL, };
182 static struct termios * specialix_termios[SX_NBOARD * SX_NPORT] = { NULL, };
183 static struct termios * specialix_termios_locked[SX_NBOARD * SX_NPORT] = { NULL, };
184 static unsigned char * tmp_buf = NULL;
185 static DECLARE_MUTEX(tmp_buf_sem);
187 static unsigned long baud_table[] = {
188 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
189 9600, 19200, 38400, 57600, 115200, 0,
192 static struct specialix_board sx_board[SX_NBOARD] = {
193 { 0, SX_IOBASE1, 9, },
194 { 0, SX_IOBASE2, 11, },
195 { 0, SX_IOBASE3, 12, },
196 { 0, SX_IOBASE4, 15, },
199 static struct specialix_port sx_port[SX_NBOARD * SX_NPORT] = {
200 { 0, },
204 #ifdef SPECIALIX_TIMER
205 static struct timer_list missed_irq_timer;
206 static void sx_interrupt(int irq, void * dev_id, struct pt_regs * regs);
207 #endif
211 static inline int sx_paranoia_check(struct specialix_port const * port,
212 kdev_t device, const char *routine)
214 #ifdef SPECIALIX_PARANOIA_CHECK
215 static const char *badmagic =
216 KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
217 static const char *badinfo =
218 KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
220 if (!port) {
221 printk(badinfo, kdevname(device), routine);
222 return 1;
224 if (port->magic != SPECIALIX_MAGIC) {
225 printk(badmagic, kdevname(device), routine);
226 return 1;
228 #endif
229 return 0;
235 * Service functions for specialix IO8+ driver.
239 /* Get board number from pointer */
240 extern inline int board_No (struct specialix_board * bp)
242 return bp - sx_board;
246 /* Get port number from pointer */
247 extern inline int port_No (struct specialix_port const * port)
249 return SX_PORT(port - sx_port);
253 /* Get pointer to board from pointer to port */
254 extern inline struct specialix_board * port_Board(struct specialix_port const * port)
256 return &sx_board[SX_BOARD(port - sx_port)];
260 /* Input Byte from CL CD186x register */
261 extern inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg)
263 bp->reg = reg | 0x80;
264 outb (reg | 0x80, bp->base + SX_ADDR_REG);
265 return inb (bp->base + SX_DATA_REG);
269 /* Output Byte to CL CD186x register */
270 extern inline void sx_out(struct specialix_board * bp, unsigned short reg,
271 unsigned char val)
273 bp->reg = reg | 0x80;
274 outb (reg | 0x80, bp->base + SX_ADDR_REG);
275 outb (val, bp->base + SX_DATA_REG);
279 /* Input Byte from CL CD186x register */
280 extern inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg)
282 bp->reg = reg;
283 outb (reg, bp->base + SX_ADDR_REG);
284 return inb (bp->base + SX_DATA_REG);
288 /* Output Byte to CL CD186x register */
289 extern inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
290 unsigned char val)
292 bp->reg = reg;
293 outb (reg, bp->base + SX_ADDR_REG);
294 outb (val, bp->base + SX_DATA_REG);
298 /* Wait for Channel Command Register ready */
299 extern inline void sx_wait_CCR(struct specialix_board * bp)
301 unsigned long delay;
303 for (delay = SX_CCR_TIMEOUT; delay; delay--)
304 if (!sx_in(bp, CD186x_CCR))
305 return;
307 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
311 /* Wait for Channel Command Register ready */
312 extern inline void sx_wait_CCR_off(struct specialix_board * bp)
314 unsigned long delay;
316 for (delay = SX_CCR_TIMEOUT; delay; delay--)
317 if (!sx_in_off(bp, CD186x_CCR))
318 return;
320 printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
325 * specialix IO8+ IO range functions.
328 extern inline int sx_check_io_range(struct specialix_board * bp)
330 return check_region (bp->base, SX_IO_SPACE);
334 extern inline void sx_request_io_range(struct specialix_board * bp)
336 request_region(bp->base,
337 bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE,
338 "specialix IO8+" );
342 extern inline void sx_release_io_range(struct specialix_board * bp)
344 release_region(bp->base,
345 bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
349 /* Must be called with enabled interrupts */
350 /* Ugly. Very ugly. Don't use this for anything else than initialization
351 code */
352 extern inline void sx_long_delay(unsigned long delay)
354 unsigned long i;
356 for (i = jiffies + delay; time_after(i, jiffies); ) ;
361 /* Set the IRQ using the RTS lines that run to the PAL on the board.... */
362 int sx_set_irq ( struct specialix_board *bp)
364 int virq;
365 int i;
367 if (bp->flags & SX_BOARD_IS_PCI)
368 return 1;
369 switch (bp->irq) {
370 /* In the same order as in the docs... */
371 case 15: virq = 0;break;
372 case 12: virq = 1;break;
373 case 11: virq = 2;break;
374 case 9: virq = 3;break;
375 default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq);
376 return 0;
379 for (i=0;i<2;i++) {
380 sx_out(bp, CD186x_CAR, i);
381 sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
383 return 1;
387 /* Reset and setup CD186x chip */
388 static int sx_init_CD186x(struct specialix_board * bp)
390 unsigned long flags;
391 int scaler;
392 int rv = 1;
394 save_flags(flags); cli();
396 sx_wait_CCR_off(bp); /* Wait for CCR ready */
397 sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */
398 sti();
399 sx_long_delay(HZ/20); /* Delay 0.05 sec */
400 cli();
401 sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */
402 sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */
403 sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT); /* Prio for modem intr */
404 sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */
405 sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */
406 /* Set RegAckEn */
407 sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
409 /* Setting up prescaler. We need 4 ticks per 1 ms */
410 scaler = SX_OSCFREQ/SPECIALIX_TPS;
412 sx_out_off(bp, CD186x_PPRH, scaler >> 8);
413 sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
415 if (!sx_set_irq (bp)) {
416 /* Figure out how to pass this along... */
417 printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq);
418 rv = 0;
421 restore_flags(flags);
422 return rv;
426 int read_cross_byte (struct specialix_board *bp, int reg, int bit)
428 int i;
429 int t;
431 for (i=0, t=0;i<8;i++) {
432 sx_out_off (bp, CD186x_CAR, i);
433 if (sx_in_off (bp, reg) & bit)
434 t |= 1 << i;
436 return t;
440 #ifdef SPECIALIX_TIMER
441 void missed_irq (unsigned long data)
443 if (sx_in ((struct specialix_board *)data, CD186x_SRSR) &
444 (SRSR_RREQint |
445 SRSR_TREQint |
446 SRSR_MREQint)) {
447 printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
448 sx_interrupt (((struct specialix_board *)data)->irq,
449 NULL, NULL);
451 missed_irq_timer.expires = jiffies + HZ;
452 add_timer (&missed_irq_timer);
454 #endif
458 /* Main probing routine, also sets irq. */
459 static int sx_probe(struct specialix_board *bp)
461 unsigned char val1, val2;
462 #if 0
463 int irqs = 0;
464 int retries;
465 #endif
466 int rev;
467 int chip;
469 if (sx_check_io_range(bp))
470 return 1;
472 /* Are the I/O ports here ? */
473 sx_out_off(bp, CD186x_PPRL, 0x5a);
474 short_pause ();
475 val1 = sx_in_off(bp, CD186x_PPRL);
477 sx_out_off(bp, CD186x_PPRL, 0xa5);
478 short_pause ();
479 val2 = sx_in_off(bp, CD186x_PPRL);
482 if ((val1 != 0x5a) || (val2 != 0xa5)) {
483 printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
484 board_No(bp), bp->base);
485 return 1;
488 /* Check the DSR lines that Specialix uses as board
489 identification */
490 val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
491 val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
492 #ifdef SPECIALIX_DEBUG
493 printk (KERN_DEBUG "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
494 board_No(bp), val1, val2);
495 #endif
496 /* They managed to switch the bit order between the docs and
497 the IO8+ card. The new PCI card now conforms to old docs.
498 They changed the PCI docs to reflect the situation on the
499 old card. */
500 val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
501 if (val1 != val2) {
502 printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
503 board_No(bp), val2, bp->base, val1);
504 return 1;
508 #if 0
509 /* It's time to find IRQ for this board */
510 for (retries = 0; retries < 5 && irqs <= 0; retries++) {
511 irqs = probe_irq_on();
512 sx_init_CD186x(bp); /* Reset CD186x chip */
513 sx_out(bp, CD186x_CAR, 2); /* Select port 2 */
514 sx_wait_CCR(bp);
515 sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
516 sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
517 sx_long_delay(HZ/20);
518 irqs = probe_irq_off(irqs);
520 #if SPECIALIX_DEBUG > 2
521 printk (KERN_DEBUG "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
522 printk ( "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
523 printk ( "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
524 printk ( "GICR = %02x, ", sx_in(bp, CD186x_GICR));
525 printk ( "\n");
526 #endif
527 /* Reset CD186x again */
528 if (!sx_init_CD186x(bp)) {
529 /* Hmmm. This is dead code anyway. */
531 #if SPECIALIX_DEBUG > 2
532 printk (KERN_DEBUG "val1 = %02x, val2 = %02x, val3 = %02x.\n",
533 val1, val2, val3);
534 #endif
538 #if 0
539 if (irqs <= 0) {
540 printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
541 board_No(bp), bp->base);
542 return 1;
544 #endif
545 printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
546 if (irqs > 0)
547 bp->irq = irqs;
548 #endif
549 /* Reset CD186x again */
550 if (!sx_init_CD186x(bp)) {
551 return -EIO;
554 sx_request_io_range(bp);
555 bp->flags |= SX_BOARD_PRESENT;
557 /* Chip revcode pkgtype
558 GFRCR SRCR bit 7
559 CD180 rev B 0x81 0
560 CD180 rev C 0x82 0
561 CD1864 rev A 0x82 1
562 CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
563 CD1865 rev B 0x84 1
564 -- Thanks to Gwen Wang, Cirrus Logic.
567 switch (sx_in_off(bp, CD186x_GFRCR)) {
568 case 0x82:chip = 1864;rev='A';break;
569 case 0x83:chip = 1865;rev='A';break;
570 case 0x84:chip = 1865;rev='B';break;
571 case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */
572 default:chip=-1;rev='x';
575 #if SPECIALIX_DEBUG > 2
576 printk (KERN_DEBUG " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
577 #endif
579 #ifdef SPECIALIX_TIMER
580 init_timer (&missed_irq_timer);
581 missed_irq_timer.function = missed_irq;
582 missed_irq_timer.data = (unsigned long) bp;
583 missed_irq_timer.expires = jiffies + HZ;
584 add_timer (&missed_irq_timer);
585 #endif
587 printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
588 board_No(bp),
589 bp->base, bp->irq,
590 chip, rev);
592 return 0;
597 * Interrupt processing routines.
598 * */
600 extern inline void sx_mark_event(struct specialix_port * port, int event)
603 * I'm not quite happy with current scheme all serial
604 * drivers use their own BH routine.
605 * It seems this easily can be done with one BH routine
606 * serving for all serial drivers.
607 * For now I must introduce another one - SPECIALIX_BH.
608 * Still hope this will be changed in near future.
609 * -- Dmitry.
611 set_bit(event, &port->event);
612 queue_task(&port->tqueue, &tq_specialix);
613 mark_bh(SPECIALIX_BH);
617 extern inline struct specialix_port * sx_get_port(struct specialix_board * bp,
618 unsigned char const * what)
620 unsigned char channel;
621 struct specialix_port * port;
623 channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
624 if (channel < CD186x_NCH) {
625 port = &sx_port[board_No(bp) * SX_NPORT + channel];
626 if (port->flags & ASYNC_INITIALIZED) {
627 return port;
630 printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
631 board_No(bp), what, channel);
632 return NULL;
636 extern inline void sx_receive_exc(struct specialix_board * bp)
638 struct specialix_port *port;
639 struct tty_struct *tty;
640 unsigned char status;
641 unsigned char ch;
643 if (!(port = sx_get_port(bp, "Receive")))
644 return;
646 tty = port->tty;
647 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
648 printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n",
649 board_No(bp), port_No(port));
650 return;
653 #ifdef SX_REPORT_OVERRUN
654 status = sx_in(bp, CD186x_RCSR);
655 if (status & RCSR_OE) {
656 port->overrun++;
657 #if SPECIALIX_DEBUG
658 printk(KERN_DEBUG "sx%d: port %d: Overrun. Total %ld overruns.\n",
659 board_No(bp), port_No(port), port->overrun);
660 #endif
662 status &= port->mark_mask;
663 #else
664 status = sx_in(bp, CD186x_RCSR) & port->mark_mask;
665 #endif
666 ch = sx_in(bp, CD186x_RDR);
667 if (!status) {
668 return;
670 if (status & RCSR_TOUT) {
671 printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
672 board_No(bp), port_No(port));
673 return;
675 } else if (status & RCSR_BREAK) {
676 #ifdef SPECIALIX_DEBUG
677 printk(KERN_DEBUG "sx%d: port %d: Handling break...\n",
678 board_No(bp), port_No(port));
679 #endif
680 *tty->flip.flag_buf_ptr++ = TTY_BREAK;
681 if (port->flags & ASYNC_SAK)
682 do_SAK(tty);
684 } else if (status & RCSR_PE)
685 *tty->flip.flag_buf_ptr++ = TTY_PARITY;
687 else if (status & RCSR_FE)
688 *tty->flip.flag_buf_ptr++ = TTY_FRAME;
690 else if (status & RCSR_OE)
691 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
693 else
694 *tty->flip.flag_buf_ptr++ = 0;
696 *tty->flip.char_buf_ptr++ = ch;
697 tty->flip.count++;
698 queue_task(&tty->flip.tqueue, &tq_timer);
702 extern inline void sx_receive(struct specialix_board * bp)
704 struct specialix_port *port;
705 struct tty_struct *tty;
706 unsigned char count;
708 if (!(port = sx_get_port(bp, "Receive")))
709 return;
711 tty = port->tty;
713 count = sx_in(bp, CD186x_RDCR);
715 #ifdef SX_REPORT_FIFO
716 port->hits[count > 8 ? 9 : count]++;
717 #endif
719 while (count--) {
720 if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
721 printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n",
722 board_No(bp), port_No(port));
723 break;
725 *tty->flip.char_buf_ptr++ = sx_in(bp, CD186x_RDR);
726 *tty->flip.flag_buf_ptr++ = 0;
727 tty->flip.count++;
729 queue_task(&tty->flip.tqueue, &tq_timer);
733 extern inline void sx_transmit(struct specialix_board * bp)
735 struct specialix_port *port;
736 struct tty_struct *tty;
737 unsigned char count;
740 if (!(port = sx_get_port(bp, "Transmit")))
741 return;
743 tty = port->tty;
745 if (port->IER & IER_TXEMPTY) {
746 /* FIFO drained */
747 sx_out(bp, CD186x_CAR, port_No(port));
748 port->IER &= ~IER_TXEMPTY;
749 sx_out(bp, CD186x_IER, port->IER);
750 return;
753 if ((port->xmit_cnt <= 0 && !port->break_length)
754 || tty->stopped || tty->hw_stopped) {
755 sx_out(bp, CD186x_CAR, port_No(port));
756 port->IER &= ~IER_TXRDY;
757 sx_out(bp, CD186x_IER, port->IER);
758 return;
761 if (port->break_length) {
762 if (port->break_length > 0) {
763 if (port->COR2 & COR2_ETC) {
764 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
765 sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
766 port->COR2 &= ~COR2_ETC;
768 count = MIN(port->break_length, 0xff);
769 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
770 sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
771 sx_out(bp, CD186x_TDR, count);
772 if (!(port->break_length -= count))
773 port->break_length--;
774 } else {
775 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
776 sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
777 sx_out(bp, CD186x_COR2, port->COR2);
778 sx_wait_CCR(bp);
779 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
780 port->break_length = 0;
782 return;
785 count = CD186x_NFIFO;
786 do {
787 sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
788 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
789 if (--port->xmit_cnt <= 0)
790 break;
791 } while (--count > 0);
793 if (port->xmit_cnt <= 0) {
794 sx_out(bp, CD186x_CAR, port_No(port));
795 port->IER &= ~IER_TXRDY;
796 sx_out(bp, CD186x_IER, port->IER);
798 if (port->xmit_cnt <= port->wakeup_chars)
799 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
803 extern inline void sx_check_modem(struct specialix_board * bp)
805 struct specialix_port *port;
806 struct tty_struct *tty;
807 unsigned char mcr;
809 #ifdef SPECIALIX_DEBUG
810 printk (KERN_DEBUG "Modem intr. ");
811 #endif
812 if (!(port = sx_get_port(bp, "Modem")))
813 return;
815 tty = port->tty;
817 mcr = sx_in(bp, CD186x_MCR);
818 printk ("mcr = %02x.\n", mcr);
820 if ((mcr & MCR_CDCHG)) {
821 #ifdef SPECIALIX_DEBUG
822 printk (KERN_DEBUG "CD just changed... ");
823 #endif
824 if (sx_in(bp, CD186x_MSVR) & MSVR_CD) {
825 #ifdef SPECIALIX_DEBUG
826 printk ( "Waking up guys in open.\n");
827 #endif
828 wake_up_interruptible(&port->open_wait);
830 else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
831 (port->flags & ASYNC_CALLOUT_NOHUP))) {
832 #ifdef SPECIALIX_DEBUG
833 printk ( "Sending HUP.\n");
834 #endif
835 queue_task(&port->tqueue_hangup,
836 &tq_scheduler);
837 } else {
838 #ifdef SPECIALIX_DEBUG
839 printk ( "Don't need to send HUP.\n");
840 #endif
844 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
845 if (mcr & MCR_CTSCHG) {
846 if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
847 tty->hw_stopped = 0;
848 port->IER |= IER_TXRDY;
849 if (port->xmit_cnt <= port->wakeup_chars)
850 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
851 } else {
852 tty->hw_stopped = 1;
853 port->IER &= ~IER_TXRDY;
855 sx_out(bp, CD186x_IER, port->IER);
857 if (mcr & MCR_DSSXHG) {
858 if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
859 tty->hw_stopped = 0;
860 port->IER |= IER_TXRDY;
861 if (port->xmit_cnt <= port->wakeup_chars)
862 sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
863 } else {
864 tty->hw_stopped = 1;
865 port->IER &= ~IER_TXRDY;
867 sx_out(bp, CD186x_IER, port->IER);
869 #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
871 /* Clear change bits */
872 sx_out(bp, CD186x_MCR, 0);
876 /* The main interrupt processing routine */
877 static void sx_interrupt(int irq, void * dev_id, struct pt_regs * regs)
879 unsigned char status;
880 unsigned char ack;
881 struct specialix_board *bp;
882 unsigned long loop = 0;
883 int saved_reg;
885 bp = dev_id;
887 if (!bp || !(bp->flags & SX_BOARD_ACTIVE)) {
888 #ifdef SPECIALIX_DEBUG
889 printk (KERN_DEBUG "sx: False interrupt. irq %d.\n", irq);
890 #endif
891 return;
894 saved_reg = bp->reg;
896 while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
897 (SRSR_RREQint |
898 SRSR_TREQint |
899 SRSR_MREQint)))) {
900 if (status & SRSR_RREQint) {
901 ack = sx_in(bp, CD186x_RRAR);
903 if (ack == (SX_ID | GIVR_IT_RCV))
904 sx_receive(bp);
905 else if (ack == (SX_ID | GIVR_IT_REXC))
906 sx_receive_exc(bp);
907 else
908 printk(KERN_ERR "sx%d: Bad receive ack 0x%02x.\n",
909 board_No(bp), ack);
911 } else if (status & SRSR_TREQint) {
912 ack = sx_in(bp, CD186x_TRAR);
914 if (ack == (SX_ID | GIVR_IT_TX))
915 sx_transmit(bp);
916 else
917 printk(KERN_ERR "sx%d: Bad transmit ack 0x%02x.\n",
918 board_No(bp), ack);
919 } else if (status & SRSR_MREQint) {
920 ack = sx_in(bp, CD186x_MRAR);
922 if (ack == (SX_ID | GIVR_IT_MODEM))
923 sx_check_modem(bp);
924 else
925 printk(KERN_ERR "sx%d: Bad modem ack 0x%02x.\n",
926 board_No(bp), ack);
930 sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
932 bp->reg = saved_reg;
933 outb (bp->reg, bp->base + SX_ADDR_REG);
938 * Routines for open & close processing.
941 void turn_ints_off (struct specialix_board *bp)
943 if (bp->flags & SX_BOARD_IS_PCI) {
944 /* This was intended for enabeling the interrupt on the
945 * PCI card. However it seems that it's already enabled
946 * and as PCI interrupts can be shared, there is no real
947 * reason to have to turn it off. */
949 (void) sx_in_off (bp, 0); /* Turn off interrupts. */
952 void turn_ints_on (struct specialix_board *bp)
954 if (bp->flags & SX_BOARD_IS_PCI) {
955 /* play with the PCI chip. See comment above. */
957 (void) sx_in (bp, 0); /* Turn ON interrupts. */
961 /* Called with disabled interrupts */
962 extern inline int sx_setup_board(struct specialix_board * bp)
964 int error;
966 if (bp->flags & SX_BOARD_ACTIVE)
967 return 0;
969 error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp);
971 if (error)
972 return error;
974 turn_ints_on (bp);
975 bp->flags |= SX_BOARD_ACTIVE;
977 MOD_INC_USE_COUNT;
978 return 0;
982 /* Called with disabled interrupts */
983 extern inline void sx_shutdown_board(struct specialix_board *bp)
985 if (!(bp->flags & SX_BOARD_ACTIVE))
986 return;
988 bp->flags &= ~SX_BOARD_ACTIVE;
990 #if SPECIALIX_DEBUG > 2
991 printk ("Freeing IRQ%d for board %d.\n", bp->irq, board_No (bp));
992 #endif
993 free_irq(bp->irq, bp);
995 turn_ints_off (bp);
997 MOD_DEC_USE_COUNT;
1002 * Setting up port characteristics.
1003 * Must be called with disabled interrupts
1005 static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
1007 struct tty_struct *tty;
1008 unsigned long baud;
1009 long tmp;
1010 unsigned char cor1 = 0, cor3 = 0;
1011 unsigned char mcor1 = 0, mcor2 = 0;
1012 static int again=0;
1014 if (!(tty = port->tty) || !tty->termios)
1015 return;
1017 port->IER = 0;
1018 port->COR2 = 0;
1019 /* Select port on the board */
1020 sx_out(bp, CD186x_CAR, port_No(port));
1022 /* The Specialix board doens't implement the RTS lines.
1023 They are used to set the IRQ level. Don't touch them. */
1024 if (SX_CRTSCTS(tty))
1025 port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1026 else
1027 port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1028 #ifdef DEBUG_SPECIALIX
1029 printk (KERN_DEBUG "sx: got MSVR=%02x.\n", port->MSVR);
1030 #endif
1031 baud = C_BAUD(tty);
1033 if (baud & CBAUDEX) {
1034 baud &= ~CBAUDEX;
1035 if (baud < 1 || baud > 2)
1036 port->tty->termios->c_cflag &= ~CBAUDEX;
1037 else
1038 baud += 15;
1040 if (baud == 15) {
1041 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1042 baud ++;
1043 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
1044 baud += 2;
1048 if (!baud_table[baud]) {
1049 /* Drop DTR & exit */
1050 #ifdef SPECIALIX_DEBUG
1051 printk (KERN_DEBUG "Dropping DTR... Hmm....\n");
1052 #endif
1053 if (!SX_CRTSCTS (tty)) {
1054 port -> MSVR &= ~ MSVR_DTR;
1055 sx_out(bp, CD186x_MSVR, port->MSVR );
1057 #ifdef DEBUG_SPECIALIX
1058 else
1059 printk (KERN_DEBUG "Can't drop DTR: no DTR.\n");
1060 #endif
1061 return;
1062 } else {
1063 /* Set DTR on */
1064 if (!SX_CRTSCTS (tty)) {
1065 port ->MSVR |= MSVR_DTR;
1070 * Now we must calculate some speed depended things
1073 /* Set baud rate for port */
1074 tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
1075 CD186x_TPC/2) / CD186x_TPC);
1076 if ((tmp < 0x10) && time_before(again, jiffies)) {
1077 again = jiffies + HZ * 60;
1078 /* Page 48 of version 2.0 of the CL-CD1865 databook */
1079 if (tmp >= 12) {
1080 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1081 "Performance degradation is possible.\n"
1082 "Read specialix.txt for more info.\n",
1083 port_No (port), tmp);
1084 } else {
1085 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1086 "Warning: overstressing Cirrus chip. "
1087 "This might not work.\n"
1088 "Read specialix.txt for more info.\n",
1089 port_No (port), tmp);
1093 sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
1094 sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
1095 sx_out(bp, CD186x_RBPRL, tmp & 0xff);
1096 sx_out(bp, CD186x_TBPRL, tmp & 0xff);
1098 baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */
1100 /* Two timer ticks seems enough to wakeup something like SLIP driver */
1101 tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
1102 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
1103 SERIAL_XMIT_SIZE - 1 : tmp);
1105 /* Receiver timeout will be transmission time for 1.5 chars */
1106 tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
1107 tmp = (tmp > 0xff) ? 0xff : tmp;
1108 sx_out(bp, CD186x_RTPR, tmp);
1110 switch (C_CSIZE(tty)) {
1111 case CS5:
1112 cor1 |= COR1_5BITS;
1113 break;
1114 case CS6:
1115 cor1 |= COR1_6BITS;
1116 break;
1117 case CS7:
1118 cor1 |= COR1_7BITS;
1119 break;
1120 case CS8:
1121 cor1 |= COR1_8BITS;
1122 break;
1125 if (C_CSTOPB(tty))
1126 cor1 |= COR1_2SB;
1128 cor1 |= COR1_IGNORE;
1129 if (C_PARENB(tty)) {
1130 cor1 |= COR1_NORMPAR;
1131 if (C_PARODD(tty))
1132 cor1 |= COR1_ODDP;
1133 if (I_INPCK(tty))
1134 cor1 &= ~COR1_IGNORE;
1136 /* Set marking of some errors */
1137 port->mark_mask = RCSR_OE | RCSR_TOUT;
1138 if (I_INPCK(tty))
1139 port->mark_mask |= RCSR_FE | RCSR_PE;
1140 if (I_BRKINT(tty) || I_PARMRK(tty))
1141 port->mark_mask |= RCSR_BREAK;
1142 if (I_IGNPAR(tty))
1143 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
1144 if (I_IGNBRK(tty)) {
1145 port->mark_mask &= ~RCSR_BREAK;
1146 if (I_IGNPAR(tty))
1147 /* Real raw mode. Ignore all */
1148 port->mark_mask &= ~RCSR_OE;
1150 /* Enable Hardware Flow Control */
1151 if (C_CRTSCTS(tty)) {
1152 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
1153 port->IER |= IER_DSR | IER_CTS;
1154 mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
1155 mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
1156 tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
1157 #else
1158 port->COR2 |= COR2_CTSAE;
1159 #endif
1161 /* Enable Software Flow Control. FIXME: I'm not sure about this */
1162 /* Some people reported that it works, but I still doubt it */
1163 if (I_IXON(tty)) {
1164 port->COR2 |= COR2_TXIBE;
1165 cor3 |= (COR3_FCT | COR3_SCDE);
1166 if (I_IXANY(tty))
1167 port->COR2 |= COR2_IXM;
1168 sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
1169 sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
1170 sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
1171 sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
1173 if (!C_CLOCAL(tty)) {
1174 /* Enable CD check */
1175 port->IER |= IER_CD;
1176 mcor1 |= MCOR1_CDZD;
1177 mcor2 |= MCOR2_CDOD;
1180 if (C_CREAD(tty))
1181 /* Enable receiver */
1182 port->IER |= IER_RXD;
1184 /* Set input FIFO size (1-8 bytes) */
1185 cor3 |= SPECIALIX_RXFIFO;
1186 /* Setting up CD186x channel registers */
1187 sx_out(bp, CD186x_COR1, cor1);
1188 sx_out(bp, CD186x_COR2, port->COR2);
1189 sx_out(bp, CD186x_COR3, cor3);
1190 /* Make CD186x know about registers change */
1191 sx_wait_CCR(bp);
1192 sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1193 /* Setting up modem option registers */
1194 #ifdef DEBUG_SPECIALIX
1195 printk ("Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
1196 #endif
1197 sx_out(bp, CD186x_MCOR1, mcor1);
1198 sx_out(bp, CD186x_MCOR2, mcor2);
1199 /* Enable CD186x transmitter & receiver */
1200 sx_wait_CCR(bp);
1201 sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
1202 /* Enable interrupts */
1203 sx_out(bp, CD186x_IER, port->IER);
1204 /* And finally set the modem lines... */
1205 sx_out(bp, CD186x_MSVR, port->MSVR);
1209 /* Must be called with interrupts enabled */
1210 static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
1212 unsigned long flags;
1214 if (port->flags & ASYNC_INITIALIZED)
1215 return 0;
1217 if (!port->xmit_buf) {
1218 /* We may sleep in get_free_page() */
1219 unsigned long tmp;
1221 if (!(tmp = get_free_page(GFP_KERNEL)))
1222 return -ENOMEM;
1224 if (port->xmit_buf) {
1225 free_page(tmp);
1226 return -ERESTARTSYS;
1228 port->xmit_buf = (unsigned char *) tmp;
1231 save_flags(flags); cli();
1233 if (port->tty)
1234 clear_bit(TTY_IO_ERROR, &port->tty->flags);
1236 if (port->count == 1)
1237 bp->count++;
1239 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1240 sx_change_speed(bp, port);
1241 port->flags |= ASYNC_INITIALIZED;
1243 restore_flags(flags);
1244 return 0;
1248 /* Must be called with interrupts disabled */
1249 static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
1251 struct tty_struct *tty;
1253 if (!(port->flags & ASYNC_INITIALIZED))
1254 return;
1256 #ifdef SX_REPORT_OVERRUN
1257 printk(KERN_INFO "sx%d: port %d: Total %ld overruns were detected.\n",
1258 board_No(bp), port_No(port), port->overrun);
1259 #endif
1260 #ifdef SX_REPORT_FIFO
1262 int i;
1264 printk(KERN_INFO "sx%d: port %d: FIFO hits [ ",
1265 board_No(bp), port_No(port));
1266 for (i = 0; i < 10; i++) {
1267 printk("%ld ", port->hits[i]);
1269 printk("].\n");
1271 #endif
1272 if (port->xmit_buf) {
1273 free_page((unsigned long) port->xmit_buf);
1274 port->xmit_buf = NULL;
1277 /* Select port */
1278 sx_out(bp, CD186x_CAR, port_No(port));
1280 if (!(tty = port->tty) || C_HUPCL(tty)) {
1281 /* Drop DTR */
1282 sx_out(bp, CD186x_MSVDTR, 0);
1285 /* Reset port */
1286 sx_wait_CCR(bp);
1287 sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
1288 /* Disable all interrupts from this port */
1289 port->IER = 0;
1290 sx_out(bp, CD186x_IER, port->IER);
1292 if (tty)
1293 set_bit(TTY_IO_ERROR, &tty->flags);
1294 port->flags &= ~ASYNC_INITIALIZED;
1296 if (--bp->count < 0) {
1297 printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d\n",
1298 board_No(bp), bp->count);
1299 bp->count = 0;
1303 * If this is the last opened port on the board
1304 * shutdown whole board
1306 if (!bp->count)
1307 sx_shutdown_board(bp);
1311 static int block_til_ready(struct tty_struct *tty, struct file * filp,
1312 struct specialix_port *port)
1314 DECLARE_WAITQUEUE(wait, current);
1315 struct specialix_board *bp = port_Board(port);
1316 int retval;
1317 int do_clocal = 0;
1318 int CD;
1321 * If the device is in the middle of being closed, then block
1322 * until it's done, and then try again.
1324 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
1325 interruptible_sleep_on(&port->close_wait);
1326 if (port->flags & ASYNC_HUP_NOTIFY)
1327 return -EAGAIN;
1328 else
1329 return -ERESTARTSYS;
1333 * If this is a callout device, then just make sure the normal
1334 * device isn't being used.
1336 if (tty->driver.subtype == SPECIALIX_TYPE_CALLOUT) {
1337 if (port->flags & ASYNC_NORMAL_ACTIVE)
1338 return -EBUSY;
1339 if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
1340 (port->flags & ASYNC_SESSION_LOCKOUT) &&
1341 (port->session != current->session))
1342 return -EBUSY;
1343 if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
1344 (port->flags & ASYNC_PGRP_LOCKOUT) &&
1345 (port->pgrp != current->pgrp))
1346 return -EBUSY;
1347 port->flags |= ASYNC_CALLOUT_ACTIVE;
1348 return 0;
1352 * If non-blocking mode is set, or the port is not enabled,
1353 * then make the check up front and then exit.
1355 if ((filp->f_flags & O_NONBLOCK) ||
1356 (tty->flags & (1 << TTY_IO_ERROR))) {
1357 if (port->flags & ASYNC_CALLOUT_ACTIVE)
1358 return -EBUSY;
1359 port->flags |= ASYNC_NORMAL_ACTIVE;
1360 return 0;
1363 if (port->flags & ASYNC_CALLOUT_ACTIVE) {
1364 if (port->normal_termios.c_cflag & CLOCAL)
1365 do_clocal = 1;
1366 } else {
1367 if (C_CLOCAL(tty))
1368 do_clocal = 1;
1372 * Block waiting for the carrier detect and the line to become
1373 * free (i.e., not in use by the callout). While we are in
1374 * this loop, info->count is dropped by one, so that
1375 * rs_close() knows when to free things. We restore it upon
1376 * exit, either normal or abnormal.
1378 retval = 0;
1379 add_wait_queue(&port->open_wait, &wait);
1380 cli();
1381 if (!tty_hung_up_p(filp))
1382 port->count--;
1383 sti();
1384 port->blocked_open++;
1385 while (1) {
1386 cli();
1387 sx_out(bp, CD186x_CAR, port_No(port));
1388 CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
1389 if (!(port->flags & ASYNC_CALLOUT_ACTIVE)) {
1390 if (SX_CRTSCTS (tty)) {
1391 /* Activate RTS */
1392 port->MSVR |= MSVR_DTR;
1393 sx_out (bp, CD186x_MSVR, port->MSVR);
1394 } else {
1395 /* Activate DTR */
1396 port->MSVR |= MSVR_DTR;
1397 sx_out (bp, CD186x_MSVR, port->MSVR);
1400 sti();
1401 set_current_state(TASK_INTERRUPTIBLE);
1402 if (tty_hung_up_p(filp) ||
1403 !(port->flags & ASYNC_INITIALIZED)) {
1404 if (port->flags & ASYNC_HUP_NOTIFY)
1405 retval = -EAGAIN;
1406 else
1407 retval = -ERESTARTSYS;
1408 break;
1410 if (!(port->flags & ASYNC_CALLOUT_ACTIVE) &&
1411 !(port->flags & ASYNC_CLOSING) &&
1412 (do_clocal || CD))
1413 break;
1414 if (signal_pending(current)) {
1415 retval = -ERESTARTSYS;
1416 break;
1418 schedule();
1420 current->state = TASK_RUNNING;
1421 remove_wait_queue(&port->open_wait, &wait);
1422 if (!tty_hung_up_p(filp))
1423 port->count++;
1424 port->blocked_open--;
1425 if (retval)
1426 return retval;
1428 port->flags |= ASYNC_NORMAL_ACTIVE;
1429 return 0;
1433 static int sx_open(struct tty_struct * tty, struct file * filp)
1435 int board;
1436 int error;
1437 struct specialix_port * port;
1438 struct specialix_board * bp;
1439 unsigned long flags;
1441 board = SX_BOARD(MINOR(tty->device));
1443 if (board > SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT))
1444 return -ENODEV;
1446 bp = &sx_board[board];
1447 port = sx_port + board * SX_NPORT + SX_PORT(MINOR(tty->device));
1449 #ifdef DEBUG_SPECIALIX
1450 printk (KERN_DEBUG "Board = %d, bp = %p, port = %p, portno = %d.\n",
1451 board, bp, port, SX_PORT(MINOR(tty->device)));
1452 #endif
1454 if (sx_paranoia_check(port, tty->device, "sx_open"))
1455 return -ENODEV;
1457 if ((error = sx_setup_board(bp)))
1458 return error;
1460 port->count++;
1461 tty->driver_data = port;
1462 port->tty = tty;
1464 if ((error = sx_setup_port(bp, port)))
1465 return error;
1467 if ((error = block_til_ready(tty, filp, port)))
1468 return error;
1470 if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
1471 if (tty->driver.subtype == SPECIALIX_TYPE_NORMAL)
1472 *tty->termios = port->normal_termios;
1473 else
1474 *tty->termios = port->callout_termios;
1475 save_flags(flags); cli();
1476 sx_change_speed(bp, port);
1477 restore_flags(flags);
1480 port->session = current->session;
1481 port->pgrp = current->pgrp;
1482 return 0;
1486 static void sx_close(struct tty_struct * tty, struct file * filp)
1488 struct specialix_port *port = (struct specialix_port *) tty->driver_data;
1489 struct specialix_board *bp;
1490 unsigned long flags;
1491 unsigned long timeout;
1493 if (!port || sx_paranoia_check(port, tty->device, "close"))
1494 return;
1496 save_flags(flags); cli();
1497 if (tty_hung_up_p(filp)) {
1498 restore_flags(flags);
1499 return;
1502 bp = port_Board(port);
1503 if ((tty->count == 1) && (port->count != 1)) {
1504 printk(KERN_ERR "sx%d: sx_close: bad port count;"
1505 " tty->count is 1, port count is %d\n",
1506 board_No(bp), port->count);
1507 port->count = 1;
1509 if (--port->count < 0) {
1510 printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
1511 board_No(bp), port_No(port), port->count);
1512 port->count = 0;
1514 if (port->count) {
1515 restore_flags(flags);
1516 return;
1518 port->flags |= ASYNC_CLOSING;
1520 * Save the termios structure, since this port may have
1521 * separate termios for callout and dialin.
1523 if (port->flags & ASYNC_NORMAL_ACTIVE)
1524 port->normal_termios = *tty->termios;
1525 if (port->flags & ASYNC_CALLOUT_ACTIVE)
1526 port->callout_termios = *tty->termios;
1528 * Now we wait for the transmit buffer to clear; and we notify
1529 * the line discipline to only process XON/XOFF characters.
1531 tty->closing = 1;
1532 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1533 tty_wait_until_sent(tty, port->closing_wait);
1535 * At this point we stop accepting input. To do this, we
1536 * disable the receive line status interrupts, and tell the
1537 * interrupt driver to stop checking the data ready bit in the
1538 * line status register.
1540 port->IER &= ~IER_RXD;
1541 if (port->flags & ASYNC_INITIALIZED) {
1542 port->IER &= ~IER_TXRDY;
1543 port->IER |= IER_TXEMPTY;
1544 sx_out(bp, CD186x_CAR, port_No(port));
1545 sx_out(bp, CD186x_IER, port->IER);
1547 * Before we drop DTR, make sure the UART transmitter
1548 * has completely drained; this is especially
1549 * important if there is a transmit FIFO!
1551 timeout = jiffies+HZ;
1552 while(port->IER & IER_TXEMPTY) {
1553 current->state = TASK_INTERRUPTIBLE;
1554 schedule_timeout(port->timeout);
1555 if (time_after(jiffies, timeout)) {
1556 printk (KERN_INFO "Timeout waiting for close\n");
1557 break;
1562 sx_shutdown_port(bp, port);
1563 if (tty->driver.flush_buffer)
1564 tty->driver.flush_buffer(tty);
1565 if (tty->ldisc.flush_buffer)
1566 tty->ldisc.flush_buffer(tty);
1567 tty->closing = 0;
1568 port->event = 0;
1569 port->tty = 0;
1570 if (port->blocked_open) {
1571 if (port->close_delay) {
1572 current->state = TASK_INTERRUPTIBLE;
1573 schedule_timeout(port->close_delay);
1575 wake_up_interruptible(&port->open_wait);
1577 port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
1578 ASYNC_CLOSING);
1579 wake_up_interruptible(&port->close_wait);
1580 restore_flags(flags);
1584 static int sx_write(struct tty_struct * tty, int from_user,
1585 const unsigned char *buf, int count)
1587 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1588 struct specialix_board *bp;
1589 int c, total = 0;
1590 unsigned long flags;
1592 if (sx_paranoia_check(port, tty->device, "sx_write"))
1593 return 0;
1595 bp = port_Board(port);
1597 if (!tty || !port->xmit_buf || !tmp_buf)
1598 return 0;
1600 if (from_user)
1601 down(&tmp_buf_sem);
1603 save_flags(flags);
1604 while (1) {
1605 cli();
1606 c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1607 SERIAL_XMIT_SIZE - port->xmit_head));
1608 if (c <= 0)
1609 break;
1611 if (from_user) {
1612 copy_from_user(tmp_buf, buf, c);
1613 c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1614 SERIAL_XMIT_SIZE - port->xmit_head));
1615 memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
1616 } else
1617 memcpy(port->xmit_buf + port->xmit_head, buf, c);
1618 port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1619 port->xmit_cnt += c;
1620 restore_flags(flags);
1621 buf += c;
1622 count -= c;
1623 total += c;
1625 if (from_user)
1626 up(&tmp_buf_sem);
1627 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1628 !(port->IER & IER_TXRDY)) {
1629 port->IER |= IER_TXRDY;
1630 sx_out(bp, CD186x_CAR, port_No(port));
1631 sx_out(bp, CD186x_IER, port->IER);
1633 restore_flags(flags);
1634 return total;
1638 static void sx_put_char(struct tty_struct * tty, unsigned char ch)
1640 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1641 unsigned long flags;
1643 if (sx_paranoia_check(port, tty->device, "sx_put_char"))
1644 return;
1646 if (!tty || !port->xmit_buf)
1647 return;
1649 save_flags(flags); cli();
1651 if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
1652 restore_flags(flags);
1653 return;
1656 port->xmit_buf[port->xmit_head++] = ch;
1657 port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1658 port->xmit_cnt++;
1659 restore_flags(flags);
1663 static void sx_flush_chars(struct tty_struct * tty)
1665 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1666 unsigned long flags;
1668 if (sx_paranoia_check(port, tty->device, "sx_flush_chars"))
1669 return;
1671 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1672 !port->xmit_buf)
1673 return;
1675 save_flags(flags); cli();
1676 port->IER |= IER_TXRDY;
1677 sx_out(port_Board(port), CD186x_CAR, port_No(port));
1678 sx_out(port_Board(port), CD186x_IER, port->IER);
1679 restore_flags(flags);
1683 static int sx_write_room(struct tty_struct * tty)
1685 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1686 int ret;
1688 if (sx_paranoia_check(port, tty->device, "sx_write_room"))
1689 return 0;
1691 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1692 if (ret < 0)
1693 ret = 0;
1694 return ret;
1698 static int sx_chars_in_buffer(struct tty_struct *tty)
1700 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1702 if (sx_paranoia_check(port, tty->device, "sx_chars_in_buffer"))
1703 return 0;
1705 return port->xmit_cnt;
1709 static void sx_flush_buffer(struct tty_struct *tty)
1711 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1712 unsigned long flags;
1714 if (sx_paranoia_check(port, tty->device, "sx_flush_buffer"))
1715 return;
1717 save_flags(flags); cli();
1718 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1719 restore_flags(flags);
1721 wake_up_interruptible(&tty->write_wait);
1722 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1723 tty->ldisc.write_wakeup)
1724 (tty->ldisc.write_wakeup)(tty);
1728 static int sx_get_modem_info(struct specialix_port * port, unsigned int *value)
1730 struct specialix_board * bp;
1731 unsigned char status;
1732 unsigned int result;
1733 unsigned long flags;
1735 bp = port_Board(port);
1736 save_flags(flags); cli();
1737 sx_out(bp, CD186x_CAR, port_No(port));
1738 status = sx_in(bp, CD186x_MSVR);
1739 restore_flags(flags);
1740 #ifdef DEBUG_SPECIALIX
1741 printk (KERN_DEBUG "Got msvr[%d] = %02x, car = %d.\n",
1742 port_No(port), status, sx_in (bp, CD186x_CAR));
1743 printk (KERN_DEBUG "sx_port = %p, port = %p\n", sx_port, port);
1744 #endif
1745 if (SX_CRTSCTS(port->tty)) {
1746 result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
1747 | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
1748 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1749 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1750 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1751 } else {
1752 result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
1753 | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1754 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1755 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1756 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1758 put_user(result,(unsigned int *) value);
1759 return 0;
1763 static int sx_set_modem_info(struct specialix_port * port, unsigned int cmd,
1764 unsigned int *value)
1766 int error;
1767 unsigned int arg;
1768 unsigned long flags;
1769 struct specialix_board *bp = port_Board(port);
1771 error = verify_area(VERIFY_READ, value, sizeof(int));
1772 if (error)
1773 return error;
1775 Get_user(arg, (unsigned long *) value);
1776 switch (cmd) {
1777 case TIOCMBIS:
1778 /* if (arg & TIOCM_RTS)
1779 port->MSVR |= MSVR_RTS; */
1780 /* if (arg & TIOCM_DTR)
1781 port->MSVR |= MSVR_DTR; */
1783 if (SX_CRTSCTS(port->tty)) {
1784 if (arg & TIOCM_RTS)
1785 port->MSVR |= MSVR_DTR;
1786 } else {
1787 if (arg & TIOCM_DTR)
1788 port->MSVR |= MSVR_DTR;
1790 break;
1791 case TIOCMBIC:
1792 /* if (arg & TIOCM_RTS)
1793 port->MSVR &= ~MSVR_RTS; */
1794 /* if (arg & TIOCM_DTR)
1795 port->MSVR &= ~MSVR_DTR; */
1796 if (SX_CRTSCTS(port->tty)) {
1797 if (arg & TIOCM_RTS)
1798 port->MSVR &= ~MSVR_DTR;
1799 } else {
1800 if (arg & TIOCM_DTR)
1801 port->MSVR &= ~MSVR_DTR;
1803 break;
1804 case TIOCMSET:
1805 /* port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | MSVR_RTS) :
1806 (port->MSVR & ~MSVR_RTS); */
1807 /* port->MSVR = (arg & TIOCM_DTR) ? (port->MSVR | MSVR_DTR) :
1808 (port->MSVR & ~MSVR_DTR); */
1809 if (SX_CRTSCTS(port->tty)) {
1810 port->MSVR = (arg & TIOCM_RTS) ?
1811 (port->MSVR | MSVR_DTR) :
1812 (port->MSVR & ~MSVR_DTR);
1813 } else {
1814 port->MSVR = (arg & TIOCM_DTR) ?
1815 (port->MSVR | MSVR_DTR):
1816 (port->MSVR & ~MSVR_DTR);
1818 break;
1819 default:
1820 return -EINVAL;
1822 save_flags(flags); cli();
1823 sx_out(bp, CD186x_CAR, port_No(port));
1824 sx_out(bp, CD186x_MSVR, port->MSVR);
1825 restore_flags(flags);
1826 return 0;
1830 extern inline void sx_send_break(struct specialix_port * port, unsigned long length)
1832 struct specialix_board *bp = port_Board(port);
1833 unsigned long flags;
1835 save_flags(flags); cli();
1836 port->break_length = SPECIALIX_TPS / HZ * length;
1837 port->COR2 |= COR2_ETC;
1838 port->IER |= IER_TXRDY;
1839 sx_out(bp, CD186x_CAR, port_No(port));
1840 sx_out(bp, CD186x_COR2, port->COR2);
1841 sx_out(bp, CD186x_IER, port->IER);
1842 sx_wait_CCR(bp);
1843 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
1844 sx_wait_CCR(bp);
1845 restore_flags(flags);
1849 extern inline int sx_set_serial_info(struct specialix_port * port,
1850 struct serial_struct * newinfo)
1852 struct serial_struct tmp;
1853 struct specialix_board *bp = port_Board(port);
1854 int change_speed;
1855 unsigned long flags;
1856 int error;
1858 error = verify_area(VERIFY_READ, (void *) newinfo, sizeof(tmp));
1859 if (error)
1860 return error;
1862 copy_from_user(&tmp, newinfo, sizeof(tmp));
1864 #if 0
1865 if ((tmp.irq != bp->irq) ||
1866 (tmp.port != bp->base) ||
1867 (tmp.type != PORT_CIRRUS) ||
1868 (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
1869 (tmp.custom_divisor != 0) ||
1870 (tmp.xmit_fifo_size != CD186x_NFIFO) ||
1871 (tmp.flags & ~SPECIALIX_LEGAL_FLAGS))
1872 return -EINVAL;
1873 #endif
1875 change_speed = ((port->flags & ASYNC_SPD_MASK) !=
1876 (tmp.flags & ASYNC_SPD_MASK));
1878 if (!capable(CAP_SYS_ADMIN)) {
1879 if ((tmp.close_delay != port->close_delay) ||
1880 (tmp.closing_wait != port->closing_wait) ||
1881 ((tmp.flags & ~ASYNC_USR_MASK) !=
1882 (port->flags & ~ASYNC_USR_MASK)))
1883 return -EPERM;
1884 port->flags = ((port->flags & ~ASYNC_USR_MASK) |
1885 (tmp.flags & ASYNC_USR_MASK));
1886 } else {
1887 port->flags = ((port->flags & ~ASYNC_FLAGS) |
1888 (tmp.flags & ASYNC_FLAGS));
1889 port->close_delay = tmp.close_delay;
1890 port->closing_wait = tmp.closing_wait;
1892 if (change_speed) {
1893 save_flags(flags); cli();
1894 sx_change_speed(bp, port);
1895 restore_flags(flags);
1897 return 0;
1901 extern inline int sx_get_serial_info(struct specialix_port * port,
1902 struct serial_struct * retinfo)
1904 struct serial_struct tmp;
1905 struct specialix_board *bp = port_Board(port);
1906 int error;
1908 error = verify_area(VERIFY_WRITE, (void *) retinfo, sizeof(tmp));
1909 if (error)
1910 return error;
1912 memset(&tmp, 0, sizeof(tmp));
1913 tmp.type = PORT_CIRRUS;
1914 tmp.line = port - sx_port;
1915 tmp.port = bp->base;
1916 tmp.irq = bp->irq;
1917 tmp.flags = port->flags;
1918 tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
1919 tmp.close_delay = port->close_delay * HZ/100;
1920 tmp.closing_wait = port->closing_wait * HZ/100;
1921 tmp.xmit_fifo_size = CD186x_NFIFO;
1922 copy_to_user(retinfo, &tmp, sizeof(tmp));
1923 return 0;
1927 static int sx_ioctl(struct tty_struct * tty, struct file * filp,
1928 unsigned int cmd, unsigned long arg)
1930 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1931 int error;
1932 int retval;
1934 if (sx_paranoia_check(port, tty->device, "sx_ioctl"))
1935 return -ENODEV;
1937 switch (cmd) {
1938 case TCSBRK: /* SVID version: non-zero arg --> no break */
1939 retval = tty_check_change(tty);
1940 if (retval)
1941 return retval;
1942 tty_wait_until_sent(tty, 0);
1943 if (!arg)
1944 sx_send_break(port, HZ/4); /* 1/4 second */
1945 return 0;
1946 case TCSBRKP: /* support for POSIX tcsendbreak() */
1947 retval = tty_check_change(tty);
1948 if (retval)
1949 return retval;
1950 tty_wait_until_sent(tty, 0);
1951 sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
1952 return 0;
1953 case TIOCGSOFTCAR:
1954 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
1955 if (error)
1956 return error;
1957 put_user(C_CLOCAL(tty) ? 1 : 0,
1958 (unsigned long *) arg);
1959 return 0;
1960 case TIOCSSOFTCAR:
1961 Get_user(arg, (unsigned long *) arg);
1962 tty->termios->c_cflag =
1963 ((tty->termios->c_cflag & ~CLOCAL) |
1964 (arg ? CLOCAL : 0));
1965 return 0;
1966 case TIOCMGET:
1967 error = verify_area(VERIFY_WRITE, (void *) arg,
1968 sizeof(unsigned int));
1969 if (error)
1970 return error;
1971 return sx_get_modem_info(port, (unsigned int *) arg);
1972 case TIOCMBIS:
1973 case TIOCMBIC:
1974 case TIOCMSET:
1975 return sx_set_modem_info(port, cmd, (unsigned int *) arg);
1976 case TIOCGSERIAL:
1977 return sx_get_serial_info(port, (struct serial_struct *) arg);
1978 case TIOCSSERIAL:
1979 return sx_set_serial_info(port, (struct serial_struct *) arg);
1980 default:
1981 return -ENOIOCTLCMD;
1983 return 0;
1987 static void sx_throttle(struct tty_struct * tty)
1989 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1990 struct specialix_board *bp;
1991 unsigned long flags;
1993 if (sx_paranoia_check(port, tty->device, "sx_throttle"))
1994 return;
1996 bp = port_Board(port);
1998 save_flags(flags); cli();
2000 /* Use DTR instead of RTS ! */
2001 if (SX_CRTSCTS (tty))
2002 port->MSVR &= ~MSVR_DTR;
2003 else {
2004 /* Auch!!! I think the system shouldn't call this then. */
2005 /* Or maybe we're supposed (allowed?) to do our side of hw
2006 handshake anyway, even when hardware handshake is off.
2007 When you see this in your logs, please report.... */
2008 printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
2009 port_No (port));
2011 sx_out(bp, CD186x_CAR, port_No(port));
2012 if (I_IXOFF(tty)) {
2013 sx_wait_CCR(bp);
2014 sx_out(bp, CD186x_CCR, CCR_SSCH2);
2015 sx_wait_CCR(bp);
2017 sx_out(bp, CD186x_MSVR, port->MSVR);
2018 restore_flags(flags);
2022 static void sx_unthrottle(struct tty_struct * tty)
2024 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2025 struct specialix_board *bp;
2026 unsigned long flags;
2028 if (sx_paranoia_check(port, tty->device, "sx_unthrottle"))
2029 return;
2031 bp = port_Board(port);
2033 save_flags(flags); cli();
2034 /* XXXX Use DTR INSTEAD???? */
2035 if (SX_CRTSCTS(tty)) {
2036 port->MSVR |= MSVR_DTR;
2037 } /* Else clause: see remark in "sx_throttle"... */
2039 sx_out(bp, CD186x_CAR, port_No(port));
2040 if (I_IXOFF(tty)) {
2041 sx_wait_CCR(bp);
2042 sx_out(bp, CD186x_CCR, CCR_SSCH1);
2043 sx_wait_CCR(bp);
2045 sx_out(bp, CD186x_MSVR, port->MSVR);
2046 restore_flags(flags);
2050 static void sx_stop(struct tty_struct * tty)
2052 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2053 struct specialix_board *bp;
2054 unsigned long flags;
2056 if (sx_paranoia_check(port, tty->device, "sx_stop"))
2057 return;
2059 bp = port_Board(port);
2061 save_flags(flags); cli();
2062 port->IER &= ~IER_TXRDY;
2063 sx_out(bp, CD186x_CAR, port_No(port));
2064 sx_out(bp, CD186x_IER, port->IER);
2065 restore_flags(flags);
2069 static void sx_start(struct tty_struct * tty)
2071 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2072 struct specialix_board *bp;
2073 unsigned long flags;
2075 if (sx_paranoia_check(port, tty->device, "sx_start"))
2076 return;
2078 bp = port_Board(port);
2080 save_flags(flags); cli();
2081 if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
2082 port->IER |= IER_TXRDY;
2083 sx_out(bp, CD186x_CAR, port_No(port));
2084 sx_out(bp, CD186x_IER, port->IER);
2086 restore_flags(flags);
2091 * This routine is called from the scheduler tqueue when the interrupt
2092 * routine has signalled that a hangup has occurred. The path of
2093 * hangup processing is:
2095 * serial interrupt routine -> (scheduler tqueue) ->
2096 * do_sx_hangup() -> tty->hangup() -> sx_hangup()
2099 static void do_sx_hangup(void *private_)
2101 struct specialix_port *port = (struct specialix_port *) private_;
2102 struct tty_struct *tty;
2104 tty = port->tty;
2105 if (!tty)
2106 return;
2108 tty_hangup(tty);
2112 static void sx_hangup(struct tty_struct * tty)
2114 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2115 struct specialix_board *bp;
2117 if (sx_paranoia_check(port, tty->device, "sx_hangup"))
2118 return;
2120 bp = port_Board(port);
2122 sx_shutdown_port(bp, port);
2123 port->event = 0;
2124 port->count = 0;
2125 port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2126 port->tty = 0;
2127 wake_up_interruptible(&port->open_wait);
2131 static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios)
2133 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2134 unsigned long flags;
2136 if (sx_paranoia_check(port, tty->device, "sx_set_termios"))
2137 return;
2139 if (tty->termios->c_cflag == old_termios->c_cflag &&
2140 tty->termios->c_iflag == old_termios->c_iflag)
2141 return;
2143 save_flags(flags); cli();
2144 sx_change_speed(port_Board(port), port);
2145 restore_flags(flags);
2147 if ((old_termios->c_cflag & CRTSCTS) &&
2148 !(tty->termios->c_cflag & CRTSCTS)) {
2149 tty->hw_stopped = 0;
2150 sx_start(tty);
2155 static void do_specialix_bh(void)
2157 run_task_queue(&tq_specialix);
2161 static void do_softint(void *private_)
2163 struct specialix_port *port = (struct specialix_port *) private_;
2164 struct tty_struct *tty;
2166 if(!(tty = port->tty))
2167 return;
2169 if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
2170 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
2171 tty->ldisc.write_wakeup)
2172 (tty->ldisc.write_wakeup)(tty);
2173 wake_up_interruptible(&tty->write_wait);
2178 static int sx_init_drivers(void)
2180 int error;
2181 int i;
2184 if (!(tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL))) {
2185 printk(KERN_ERR "sx: Couldn't get free page.\n");
2186 return 1;
2188 init_bh(SPECIALIX_BH, do_specialix_bh);
2189 memset(&specialix_driver, 0, sizeof(specialix_driver));
2190 specialix_driver.magic = TTY_DRIVER_MAGIC;
2191 specialix_driver.name = "ttyW";
2192 specialix_driver.major = SPECIALIX_NORMAL_MAJOR;
2193 specialix_driver.num = SX_NBOARD * SX_NPORT;
2194 specialix_driver.type = TTY_DRIVER_TYPE_SERIAL;
2195 specialix_driver.subtype = SPECIALIX_TYPE_NORMAL;
2196 specialix_driver.init_termios = tty_std_termios;
2197 specialix_driver.init_termios.c_cflag =
2198 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2199 specialix_driver.flags = TTY_DRIVER_REAL_RAW;
2200 specialix_driver.refcount = &specialix_refcount;
2201 specialix_driver.table = specialix_table;
2202 specialix_driver.termios = specialix_termios;
2203 specialix_driver.termios_locked = specialix_termios_locked;
2205 specialix_driver.open = sx_open;
2206 specialix_driver.close = sx_close;
2207 specialix_driver.write = sx_write;
2208 specialix_driver.put_char = sx_put_char;
2209 specialix_driver.flush_chars = sx_flush_chars;
2210 specialix_driver.write_room = sx_write_room;
2211 specialix_driver.chars_in_buffer = sx_chars_in_buffer;
2212 specialix_driver.flush_buffer = sx_flush_buffer;
2213 specialix_driver.ioctl = sx_ioctl;
2214 specialix_driver.throttle = sx_throttle;
2215 specialix_driver.unthrottle = sx_unthrottle;
2216 specialix_driver.set_termios = sx_set_termios;
2217 specialix_driver.stop = sx_stop;
2218 specialix_driver.start = sx_start;
2219 specialix_driver.hangup = sx_hangup;
2221 specialix_callout_driver = specialix_driver;
2222 specialix_callout_driver.name = "cuw";
2223 specialix_callout_driver.major = SPECIALIX_CALLOUT_MAJOR;
2224 specialix_callout_driver.subtype = SPECIALIX_TYPE_CALLOUT;
2226 if ((error = tty_register_driver(&specialix_driver))) {
2227 free_page((unsigned long)tmp_buf);
2228 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2229 error);
2230 return 1;
2232 if ((error = tty_register_driver(&specialix_callout_driver))) {
2233 free_page((unsigned long)tmp_buf);
2234 tty_unregister_driver(&specialix_driver);
2235 printk(KERN_ERR "sx: Couldn't register specialix IO8+ callout driver, error = %d\n",
2236 error);
2237 return 1;
2240 memset(sx_port, 0, sizeof(sx_port));
2241 for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
2242 sx_port[i].callout_termios = specialix_callout_driver.init_termios;
2243 sx_port[i].normal_termios = specialix_driver.init_termios;
2244 sx_port[i].magic = SPECIALIX_MAGIC;
2245 sx_port[i].tqueue.routine = do_softint;
2246 sx_port[i].tqueue.data = &sx_port[i];
2247 sx_port[i].tqueue_hangup.routine = do_sx_hangup;
2248 sx_port[i].tqueue_hangup.data = &sx_port[i];
2249 sx_port[i].close_delay = 50 * HZ/100;
2250 sx_port[i].closing_wait = 3000 * HZ/100;
2251 init_waitqueue_head(&sx_port[i].open_wait);
2252 init_waitqueue_head(&sx_port[i].close_wait);
2255 return 0;
2259 static void sx_release_drivers(void)
2261 free_page((unsigned long)tmp_buf);
2262 tty_unregister_driver(&specialix_driver);
2263 tty_unregister_driver(&specialix_callout_driver);
2267 #ifndef MODULE
2269 * Called at boot time.
2271 * You can specify IO base for up to SX_NBOARD cards,
2272 * using line "specialix=0xiobase1,0xiobase2,.." at LILO prompt.
2273 * Note that there will be no probing at default
2274 * addresses in this case.
2277 void specialix_setup(char *str, int * ints)
2279 int i;
2281 for (i=0;i<SX_NBOARD;i++) {
2282 sx_board[i].base = 0;
2285 for (i = 1; i <= ints[0]; i++) {
2286 if (i&1)
2287 sx_board[i/2].base = ints[i];
2288 else
2289 sx_board[i/2 -1].irq = ints[i];
2292 #endif
2295 * This routine must be called by kernel at boot time
2297 int specialix_init(void)
2299 int i;
2300 int found = 0;
2302 printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
2303 printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2304 #ifdef CONFIG_SPECIALIX_RTSCTS
2305 printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
2306 #else
2307 printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2308 #endif
2310 if (sx_init_drivers())
2311 return -EIO;
2313 for (i = 0; i < SX_NBOARD; i++)
2314 if (sx_board[i].base && !sx_probe(&sx_board[i]))
2315 found++;
2317 #ifdef CONFIG_PCI
2318 if (pci_present()) {
2319 struct pci_dev *pdev = NULL;
2320 unsigned int tint;
2322 i=0;
2323 while (i <= SX_NBOARD) {
2324 if (sx_board[i].flags & SX_BOARD_PRESENT) {
2325 i++;
2326 continue;
2328 pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
2329 PCI_DEVICE_ID_SPECIALIX_IO8,
2330 pdev);
2331 if (!pdev) break;
2333 sx_board[i].irq = pdev->irq;
2335 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
2336 /* Mask out the fact that it's IO-space */
2337 sx_board[i].base = tint & PCI_BASE_ADDRESS_IO_MASK;
2339 sx_board[i].flags |= SX_BOARD_IS_PCI;
2340 if (!sx_probe(&sx_board[i]))
2341 found ++;
2344 #endif
2346 if (!found) {
2347 sx_release_drivers();
2348 printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
2349 return -EIO;
2352 return 0;
2355 #ifdef MODULE
2356 int iobase[SX_NBOARD] = {0,};
2358 int irq [SX_NBOARD] = {0,};
2360 MODULE_PARM(iobase,"1-" __MODULE_STRING(SX_NBOARD) "i");
2361 MODULE_PARM(irq,"1-" __MODULE_STRING(SX_NBOARD) "i");
2364 * You can setup up to 4 boards.
2365 * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
2366 * You should specify the IRQs too in that case "irq=....,...".
2368 * More than 4 boards in one computer is not possible, as the card can
2369 * only use 4 different interrupts.
2372 int init_module(void)
2374 int i;
2376 if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
2377 for(i = 0; i < SX_NBOARD; i++) {
2378 sx_board[i].base = iobase[i];
2379 sx_board[i].irq = irq[i];
2383 return specialix_init();
2387 void cleanup_module(void)
2389 int i;
2391 sx_release_drivers();
2392 for (i = 0; i < SX_NBOARD; i++)
2393 if (sx_board[i].flags & SX_BOARD_PRESENT)
2394 sx_release_io_range(&sx_board[i]);
2395 #ifdef SPECIALIX_TIMER
2396 del_timer (&missed_irq_timer);
2397 #endif
2400 #endif /* MODULE */