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)
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,
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)
69 #define VERSION "1.10"
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
78 #include <linux/config.h>
79 #include <linux/module.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>
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>
98 /* ************************************************************** */
99 /* * This section can be removed when 2.0 becomes outdated.... * */
100 /* ************************************************************** */
102 #if LINUX_VERSION_CODE < 131328 /* Less than 2.1.0 */
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."
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
119 #define Get_user(a,b) get_user(a,b)
122 /* ************************************************************** */
123 /* * End of compatibility section.. * */
124 /* ************************************************************** */
128 #include <asm/uaccess.h>
131 #include "specialix_io8.h"
136 /* Configurable options: */
138 /* Am I paranoid or not ? ;-) */
139 #define SPECIALIX_PARANOIA_CHECK
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
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.
150 #undef SX_REPORT_FIFO
151 #undef SX_REPORT_OVERRUN
155 #ifdef CONFIG_SPECIALIX_RTSCTS
156 #define SX_CRTSCTS(bla) 1
158 #define SX_CRTSCTS(tty) C_CRTSCTS(tty)
162 /* Used to be outb (0xff, 0x80); */
163 #define short_pause() udelay (1)
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)
172 #define MIN(a,b) ((a) < (b) ? (a) : (b))
175 DECLARE_TASK_QUEUE(tq_specialix
);
177 #undef RS_EVENT_WRITE_WAKEUP
178 #define RS_EVENT_WRITE_WAKEUP 0
180 #define SPECIALIX_TYPE_NORMAL 1
181 #define SPECIALIX_TYPE_CALLOUT 2
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
);
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,
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, },
203 static struct specialix_port sx_port
[SX_NBOARD
* SX_NPORT
];
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
);
213 static inline int sx_paranoia_check(struct specialix_port
const * port
,
214 kdev_t device
, const char *routine
)
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";
223 printk(badinfo
, kdevname(device
), routine
);
226 if (port
->magic
!= SPECIALIX_MAGIC
) {
227 printk(badmagic
, kdevname(device
), routine
);
237 * Service functions for specialix IO8+ driver.
241 /* Get board number from pointer */
242 extern inline int board_No (struct specialix_board
* bp
)
244 return bp
- sx_board
;
248 /* Get port number from pointer */
249 extern inline int port_No (struct specialix_port
const * port
)
251 return SX_PORT(port
- sx_port
);
255 /* Get pointer to board from pointer to port */
256 extern inline struct specialix_board
* port_Board(struct specialix_port
const * port
)
258 return &sx_board
[SX_BOARD(port
- sx_port
)];
262 /* Input Byte from CL CD186x register */
263 extern inline unsigned char sx_in(struct specialix_board
* bp
, unsigned short reg
)
265 bp
->reg
= reg
| 0x80;
266 outb (reg
| 0x80, bp
->base
+ SX_ADDR_REG
);
267 return inb (bp
->base
+ SX_DATA_REG
);
271 /* Output Byte to CL CD186x register */
272 extern inline void sx_out(struct specialix_board
* bp
, unsigned short reg
,
275 bp
->reg
= reg
| 0x80;
276 outb (reg
| 0x80, bp
->base
+ SX_ADDR_REG
);
277 outb (val
, bp
->base
+ SX_DATA_REG
);
281 /* Input Byte from CL CD186x register */
282 extern inline unsigned char sx_in_off(struct specialix_board
* bp
, unsigned short reg
)
285 outb (reg
, bp
->base
+ SX_ADDR_REG
);
286 return inb (bp
->base
+ SX_DATA_REG
);
290 /* Output Byte to CL CD186x register */
291 extern inline void sx_out_off(struct specialix_board
* bp
, unsigned short reg
,
295 outb (reg
, bp
->base
+ SX_ADDR_REG
);
296 outb (val
, bp
->base
+ SX_DATA_REG
);
300 /* Wait for Channel Command Register ready */
301 extern inline void sx_wait_CCR(struct specialix_board
* bp
)
305 for (delay
= SX_CCR_TIMEOUT
; delay
; delay
--)
306 if (!sx_in(bp
, CD186x_CCR
))
309 printk(KERN_ERR
"sx%d: Timeout waiting for CCR.\n", board_No(bp
));
313 /* Wait for Channel Command Register ready */
314 extern inline void sx_wait_CCR_off(struct specialix_board
* bp
)
318 for (delay
= SX_CCR_TIMEOUT
; delay
; delay
--)
319 if (!sx_in_off(bp
, CD186x_CCR
))
322 printk(KERN_ERR
"sx%d: Timeout waiting for CCR.\n", board_No(bp
));
327 * specialix IO8+ IO range functions.
330 extern inline int sx_check_io_range(struct specialix_board
* bp
)
332 return check_region (bp
->base
, SX_IO_SPACE
);
336 extern inline void sx_request_io_range(struct specialix_board
* bp
)
338 request_region(bp
->base
,
339 bp
->flags
&SX_BOARD_IS_PCI
?SX_PCI_IO_SPACE
:SX_IO_SPACE
,
344 extern inline void sx_release_io_range(struct specialix_board
* bp
)
346 release_region(bp
->base
,
347 bp
->flags
&SX_BOARD_IS_PCI
?SX_PCI_IO_SPACE
:SX_IO_SPACE
);
351 /* Must be called with enabled interrupts */
352 /* Ugly. Very ugly. Don't use this for anything else than initialization
354 extern inline void sx_long_delay(unsigned long delay
)
358 for (i
= jiffies
+ delay
; time_after(i
, jiffies
); ) ;
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
)
369 if (bp
->flags
& SX_BOARD_IS_PCI
)
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
);
382 sx_out(bp
, CD186x_CAR
, i
);
383 sx_out(bp
, CD186x_MSVRTS
, ((virq
>> i
) & 0x1)? MSVR_RTS
:0);
389 /* Reset and setup CD186x chip */
390 static int sx_init_CD186x(struct specialix_board
* bp
)
396 save_flags(flags
); cli();
398 sx_wait_CCR_off(bp
); /* Wait for CCR ready */
399 sx_out_off(bp
, CD186x_CCR
, CCR_HARDRESET
); /* Reset CD186x chip */
401 sx_long_delay(HZ
/20); /* Delay 0.05 sec */
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 */
409 sx_out_off(bp
, CD186x_SRCR
, sx_in (bp
, CD186x_SRCR
) | SRCR_REGACKEN
);
411 /* Setting up prescaler. We need 4 ticks per 1 ms */
412 scaler
= SX_OSCFREQ
/SPECIALIX_TPS
;
414 sx_out_off(bp
, CD186x_PPRH
, scaler
>> 8);
415 sx_out_off(bp
, CD186x_PPRL
, scaler
& 0xff);
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
);
423 restore_flags(flags
);
428 int read_cross_byte (struct specialix_board
*bp
, int reg
, int bit
)
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
)
442 #ifdef SPECIALIX_TIMER
443 void missed_irq (unsigned long data
)
445 if (sx_in ((struct specialix_board
*)data
, CD186x_SRSR
) &
449 printk (KERN_INFO
"Missed interrupt... Calling int from timer. \n");
450 sx_interrupt (((struct specialix_board
*)data
)->irq
,
453 missed_irq_timer
.expires
= jiffies
+ HZ
;
454 add_timer (&missed_irq_timer
);
460 /* Main probing routine, also sets irq. */
461 static int sx_probe(struct specialix_board
*bp
)
463 unsigned char val1
, val2
;
471 if (sx_check_io_range(bp
))
474 /* Are the I/O ports here ? */
475 sx_out_off(bp
, CD186x_PPRL
, 0x5a);
477 val1
= sx_in_off(bp
, CD186x_PPRL
);
479 sx_out_off(bp
, CD186x_PPRL
, 0xa5);
481 val2
= sx_in_off(bp
, CD186x_PPRL
);
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
);
490 /* Check the DSR lines that Specialix uses as board
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
);
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
502 val2
= (bp
->flags
& SX_BOARD_IS_PCI
)?0x4d : 0xb2;
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
);
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 */
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
);
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
));
529 /* Reset CD186x again */
530 if (!sx_init_CD186x(bp
)) {
531 /* Hmmm. This is dead code anyway. */
533 #if SPECIALIX_DEBUG > 2
534 printk (KERN_DEBUG
"val1 = %02x, val2 = %02x, val3 = %02x.\n",
542 printk(KERN_ERR
"sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
543 board_No(bp
), bp
->base
);
547 printk (KERN_INFO
"Started with irq=%d, but now have irq=%d.\n", bp
->irq
, irqs
);
551 /* Reset CD186x again */
552 if (!sx_init_CD186x(bp
)) {
556 sx_request_io_range(bp
);
557 bp
->flags
|= SX_BOARD_PRESENT
;
559 /* Chip revcode pkgtype
564 CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
566 -- Thanks to Gwen Wang, Cirrus Logic.
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';
577 #if SPECIALIX_DEBUG > 2
578 printk (KERN_DEBUG
" GFCR = 0x%02x\n", sx_in_off(bp
, CD186x_GFRCR
) );
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
);
589 printk(KERN_INFO
"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
599 * Interrupt processing routines.
602 extern inline void sx_mark_event(struct specialix_port
* port
, int event
)
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.
613 set_bit(event
, &port
->event
);
614 queue_task(&port
->tqueue
, &tq_specialix
);
615 mark_bh(SPECIALIX_BH
);
619 extern inline struct specialix_port
* sx_get_port(struct specialix_board
* bp
,
620 unsigned char const * what
)
622 unsigned char channel
;
623 struct specialix_port
* port
;
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
) {
632 printk(KERN_INFO
"sx%d: %s interrupt from invalid port %d\n",
633 board_No(bp
), what
, channel
);
638 extern inline void sx_receive_exc(struct specialix_board
* bp
)
640 struct specialix_port
*port
;
641 struct tty_struct
*tty
;
642 unsigned char status
;
645 if (!(port
= sx_get_port(bp
, "Receive")))
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
));
655 #ifdef SX_REPORT_OVERRUN
656 status
= sx_in(bp
, CD186x_RCSR
);
657 if (status
& RCSR_OE
) {
660 printk(KERN_DEBUG
"sx%d: port %d: Overrun. Total %ld overruns.\n",
661 board_No(bp
), port_No(port
), port
->overrun
);
664 status
&= port
->mark_mask
;
666 status
= sx_in(bp
, CD186x_RCSR
) & port
->mark_mask
;
668 ch
= sx_in(bp
, CD186x_RDR
);
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
));
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
));
682 *tty
->flip
.flag_buf_ptr
++ = TTY_BREAK
;
683 if (port
->flags
& ASYNC_SAK
)
686 } else if (status
& RCSR_PE
)
687 *tty
->flip
.flag_buf_ptr
++ = TTY_PARITY
;
689 else if (status
& RCSR_FE
)
690 *tty
->flip
.flag_buf_ptr
++ = TTY_FRAME
;
692 else if (status
& RCSR_OE
)
693 *tty
->flip
.flag_buf_ptr
++ = TTY_OVERRUN
;
696 *tty
->flip
.flag_buf_ptr
++ = 0;
698 *tty
->flip
.char_buf_ptr
++ = ch
;
700 queue_task(&tty
->flip
.tqueue
, &tq_timer
);
704 extern inline void sx_receive(struct specialix_board
* bp
)
706 struct specialix_port
*port
;
707 struct tty_struct
*tty
;
710 if (!(port
= sx_get_port(bp
, "Receive")))
715 count
= sx_in(bp
, CD186x_RDCR
);
717 #ifdef SX_REPORT_FIFO
718 port
->hits
[count
> 8 ? 9 : 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
));
727 *tty
->flip
.char_buf_ptr
++ = sx_in(bp
, CD186x_RDR
);
728 *tty
->flip
.flag_buf_ptr
++ = 0;
731 queue_task(&tty
->flip
.tqueue
, &tq_timer
);
735 extern inline void sx_transmit(struct specialix_board
* bp
)
737 struct specialix_port
*port
;
738 struct tty_struct
*tty
;
742 if (!(port
= sx_get_port(bp
, "Transmit")))
747 if (port
->IER
& IER_TXEMPTY
) {
749 sx_out(bp
, CD186x_CAR
, port_No(port
));
750 port
->IER
&= ~IER_TXEMPTY
;
751 sx_out(bp
, CD186x_IER
, port
->IER
);
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
);
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
;
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
--;
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
);
781 sx_out(bp
, CD186x_CCR
, CCR_CORCHG2
);
782 port
->break_length
= 0;
787 count
= CD186x_NFIFO
;
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)
793 } while (--count
> 0);
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
);
800 if (port
->xmit_cnt
<= port
->wakeup_chars
)
801 sx_mark_event(port
, RS_EVENT_WRITE_WAKEUP
);
805 extern inline void sx_check_modem(struct specialix_board
* bp
)
807 struct specialix_port
*port
;
808 struct tty_struct
*tty
;
811 #ifdef SPECIALIX_DEBUG
812 printk (KERN_DEBUG
"Modem intr. ");
814 if (!(port
= sx_get_port(bp
, "Modem")))
819 mcr
= sx_in(bp
, CD186x_MCR
);
820 printk ("mcr = %02x.\n", mcr
);
822 if ((mcr
& MCR_CDCHG
)) {
823 #ifdef SPECIALIX_DEBUG
824 printk (KERN_DEBUG
"CD just changed... ");
826 if (sx_in(bp
, CD186x_MSVR
) & MSVR_CD
) {
827 #ifdef SPECIALIX_DEBUG
828 printk ( "Waking up guys in open.\n");
830 wake_up_interruptible(&port
->open_wait
);
832 else if (!((port
->flags
& ASYNC_CALLOUT_ACTIVE
) &&
833 (port
->flags
& ASYNC_CALLOUT_NOHUP
))) {
834 #ifdef SPECIALIX_DEBUG
835 printk ( "Sending HUP.\n");
838 if (schedule_task(&port
->tqueue_hangup
) == 0)
841 #ifdef SPECIALIX_DEBUG
842 printk ( "Don't need to send HUP.\n");
847 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
848 if (mcr
& MCR_CTSCHG
) {
849 if (sx_in(bp
, CD186x_MSVR
) & MSVR_CTS
) {
851 port
->IER
|= IER_TXRDY
;
852 if (port
->xmit_cnt
<= port
->wakeup_chars
)
853 sx_mark_event(port
, RS_EVENT_WRITE_WAKEUP
);
856 port
->IER
&= ~IER_TXRDY
;
858 sx_out(bp
, CD186x_IER
, port
->IER
);
860 if (mcr
& MCR_DSSXHG
) {
861 if (sx_in(bp
, CD186x_MSVR
) & MSVR_DSR
) {
863 port
->IER
|= IER_TXRDY
;
864 if (port
->xmit_cnt
<= port
->wakeup_chars
)
865 sx_mark_event(port
, RS_EVENT_WRITE_WAKEUP
);
868 port
->IER
&= ~IER_TXRDY
;
870 sx_out(bp
, CD186x_IER
, port
->IER
);
872 #endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
874 /* Clear change bits */
875 sx_out(bp
, CD186x_MCR
, 0);
879 /* The main interrupt processing routine */
880 static void sx_interrupt(int irq
, void * dev_id
, struct pt_regs
* regs
)
882 unsigned char status
;
884 struct specialix_board
*bp
;
885 unsigned long loop
= 0;
890 if (!bp
|| !(bp
->flags
& SX_BOARD_ACTIVE
)) {
891 #ifdef SPECIALIX_DEBUG
892 printk (KERN_DEBUG
"sx: False interrupt. irq %d.\n", irq
);
899 while ((++loop
< 16) && (status
= (sx_in(bp
, CD186x_SRSR
) &
903 if (status
& SRSR_RREQint
) {
904 ack
= sx_in(bp
, CD186x_RRAR
);
906 if (ack
== (SX_ID
| GIVR_IT_RCV
))
908 else if (ack
== (SX_ID
| GIVR_IT_REXC
))
911 printk(KERN_ERR
"sx%d: Bad receive ack 0x%02x.\n",
914 } else if (status
& SRSR_TREQint
) {
915 ack
= sx_in(bp
, CD186x_TRAR
);
917 if (ack
== (SX_ID
| GIVR_IT_TX
))
920 printk(KERN_ERR
"sx%d: Bad transmit ack 0x%02x.\n",
922 } else if (status
& SRSR_MREQint
) {
923 ack
= sx_in(bp
, CD186x_MRAR
);
925 if (ack
== (SX_ID
| GIVR_IT_MODEM
))
928 printk(KERN_ERR
"sx%d: Bad modem ack 0x%02x.\n",
933 sx_out(bp
, CD186x_EOIR
, 0); /* Mark end of interrupt */
936 outb (bp
->reg
, bp
->base
+ SX_ADDR_REG
);
941 * Routines for open & close processing.
944 void turn_ints_off (struct specialix_board
*bp
)
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. */
952 (void) sx_in_off (bp
, 0); /* Turn off interrupts. */
955 void turn_ints_on (struct specialix_board
*bp
)
957 if (bp
->flags
& SX_BOARD_IS_PCI
) {
958 /* play with the PCI chip. See comment above. */
960 (void) sx_in (bp
, 0); /* Turn ON interrupts. */
964 /* Called with disabled interrupts */
965 extern inline int sx_setup_board(struct specialix_board
* bp
)
969 if (bp
->flags
& SX_BOARD_ACTIVE
)
972 error
= request_irq(bp
->irq
, sx_interrupt
, SA_INTERRUPT
, "specialix IO8+", bp
);
978 bp
->flags
|= SX_BOARD_ACTIVE
;
985 /* Called with disabled interrupts */
986 extern inline void sx_shutdown_board(struct specialix_board
*bp
)
988 if (!(bp
->flags
& SX_BOARD_ACTIVE
))
991 bp
->flags
&= ~SX_BOARD_ACTIVE
;
993 #if SPECIALIX_DEBUG > 2
994 printk ("Freeing IRQ%d for board %d.\n", bp
->irq
, board_No (bp
));
996 free_irq(bp
->irq
, bp
);
1005 * Setting up port characteristics.
1006 * Must be called with disabled interrupts
1008 static void sx_change_speed(struct specialix_board
*bp
, struct specialix_port
*port
)
1010 struct tty_struct
*tty
;
1013 unsigned char cor1
= 0, cor3
= 0;
1014 unsigned char mcor1
= 0, mcor2
= 0;
1017 if (!(tty
= port
->tty
) || !tty
->termios
)
1022 /* Select port on the board */
1023 sx_out(bp
, CD186x_CAR
, port_No(port
));
1025 /* The Specialix board doens't implement the RTS lines.
1026 They are used to set the IRQ level. Don't touch them. */
1027 if (SX_CRTSCTS(tty
))
1028 port
->MSVR
= MSVR_DTR
| (sx_in(bp
, CD186x_MSVR
) & MSVR_RTS
);
1030 port
->MSVR
= (sx_in(bp
, CD186x_MSVR
) & MSVR_RTS
);
1031 #ifdef DEBUG_SPECIALIX
1032 printk (KERN_DEBUG
"sx: got MSVR=%02x.\n", port
->MSVR
);
1036 if (baud
& CBAUDEX
) {
1038 if (baud
< 1 || baud
> 2)
1039 port
->tty
->termios
->c_cflag
&= ~CBAUDEX
;
1044 if ((port
->flags
& ASYNC_SPD_MASK
) == ASYNC_SPD_HI
)
1046 if ((port
->flags
& ASYNC_SPD_MASK
) == ASYNC_SPD_VHI
)
1051 if (!baud_table
[baud
]) {
1052 /* Drop DTR & exit */
1053 #ifdef SPECIALIX_DEBUG
1054 printk (KERN_DEBUG
"Dropping DTR... Hmm....\n");
1056 if (!SX_CRTSCTS (tty
)) {
1057 port
-> MSVR
&= ~ MSVR_DTR
;
1058 sx_out(bp
, CD186x_MSVR
, port
->MSVR
);
1060 #ifdef DEBUG_SPECIALIX
1062 printk (KERN_DEBUG
"Can't drop DTR: no DTR.\n");
1067 if (!SX_CRTSCTS (tty
)) {
1068 port
->MSVR
|= MSVR_DTR
;
1073 * Now we must calculate some speed depended things
1076 /* Set baud rate for port */
1077 tmp
= port
->custom_divisor
;
1079 printk (KERN_INFO
"sx%d: Using custom baud rate divisor %ld. \n"
1080 "This is an untested option, please be carefull.\n",
1081 port_No (port
), tmp
);
1083 tmp
= (((SX_OSCFREQ
+ baud_table
[baud
]/2) / baud_table
[baud
] +
1084 CD186x_TPC
/2) / CD186x_TPC
);
1086 if ((tmp
< 0x10) && time_before(again
, jiffies
)) {
1087 again
= jiffies
+ HZ
* 60;
1088 /* Page 48 of version 2.0 of the CL-CD1865 databook */
1090 printk (KERN_INFO
"sx%d: Baud rate divisor is %ld. \n"
1091 "Performance degradation is possible.\n"
1092 "Read specialix.txt for more info.\n",
1093 port_No (port
), tmp
);
1095 printk (KERN_INFO
"sx%d: Baud rate divisor is %ld. \n"
1096 "Warning: overstressing Cirrus chip. "
1097 "This might not work.\n"
1098 "Read specialix.txt for more info.\n",
1099 port_No (port
), tmp
);
1103 sx_out(bp
, CD186x_RBPRH
, (tmp
>> 8) & 0xff);
1104 sx_out(bp
, CD186x_TBPRH
, (tmp
>> 8) & 0xff);
1105 sx_out(bp
, CD186x_RBPRL
, tmp
& 0xff);
1106 sx_out(bp
, CD186x_TBPRL
, tmp
& 0xff);
1108 if (port
->custom_divisor
) {
1109 baud
= (SX_OSCFREQ
+ port
->custom_divisor
/2) / port
->custom_divisor
;
1110 baud
= ( baud
+ 5 ) / 10;
1112 baud
= (baud_table
[baud
] + 5) / 10; /* Estimated CPS */
1114 /* Two timer ticks seems enough to wakeup something like SLIP driver */
1115 tmp
= ((baud
+ HZ
/2) / HZ
) * 2 - CD186x_NFIFO
;
1116 port
->wakeup_chars
= (tmp
< 0) ? 0 : ((tmp
>= SERIAL_XMIT_SIZE
) ?
1117 SERIAL_XMIT_SIZE
- 1 : tmp
);
1119 /* Receiver timeout will be transmission time for 1.5 chars */
1120 tmp
= (SPECIALIX_TPS
+ SPECIALIX_TPS
/2 + baud
/2) / baud
;
1121 tmp
= (tmp
> 0xff) ? 0xff : tmp
;
1122 sx_out(bp
, CD186x_RTPR
, tmp
);
1124 switch (C_CSIZE(tty
)) {
1142 cor1
|= COR1_IGNORE
;
1143 if (C_PARENB(tty
)) {
1144 cor1
|= COR1_NORMPAR
;
1148 cor1
&= ~COR1_IGNORE
;
1150 /* Set marking of some errors */
1151 port
->mark_mask
= RCSR_OE
| RCSR_TOUT
;
1153 port
->mark_mask
|= RCSR_FE
| RCSR_PE
;
1154 if (I_BRKINT(tty
) || I_PARMRK(tty
))
1155 port
->mark_mask
|= RCSR_BREAK
;
1157 port
->mark_mask
&= ~(RCSR_FE
| RCSR_PE
);
1158 if (I_IGNBRK(tty
)) {
1159 port
->mark_mask
&= ~RCSR_BREAK
;
1161 /* Real raw mode. Ignore all */
1162 port
->mark_mask
&= ~RCSR_OE
;
1164 /* Enable Hardware Flow Control */
1165 if (C_CRTSCTS(tty
)) {
1166 #ifdef SPECIALIX_BRAIN_DAMAGED_CTS
1167 port
->IER
|= IER_DSR
| IER_CTS
;
1168 mcor1
|= MCOR1_DSRZD
| MCOR1_CTSZD
;
1169 mcor2
|= MCOR2_DSROD
| MCOR2_CTSOD
;
1170 tty
->hw_stopped
= !(sx_in(bp
, CD186x_MSVR
) & (MSVR_CTS
|MSVR_DSR
));
1172 port
->COR2
|= COR2_CTSAE
;
1175 /* Enable Software Flow Control. FIXME: I'm not sure about this */
1176 /* Some people reported that it works, but I still doubt it */
1178 port
->COR2
|= COR2_TXIBE
;
1179 cor3
|= (COR3_FCT
| COR3_SCDE
);
1181 port
->COR2
|= COR2_IXM
;
1182 sx_out(bp
, CD186x_SCHR1
, START_CHAR(tty
));
1183 sx_out(bp
, CD186x_SCHR2
, STOP_CHAR(tty
));
1184 sx_out(bp
, CD186x_SCHR3
, START_CHAR(tty
));
1185 sx_out(bp
, CD186x_SCHR4
, STOP_CHAR(tty
));
1187 if (!C_CLOCAL(tty
)) {
1188 /* Enable CD check */
1189 port
->IER
|= IER_CD
;
1190 mcor1
|= MCOR1_CDZD
;
1191 mcor2
|= MCOR2_CDOD
;
1195 /* Enable receiver */
1196 port
->IER
|= IER_RXD
;
1198 /* Set input FIFO size (1-8 bytes) */
1199 cor3
|= SPECIALIX_RXFIFO
;
1200 /* Setting up CD186x channel registers */
1201 sx_out(bp
, CD186x_COR1
, cor1
);
1202 sx_out(bp
, CD186x_COR2
, port
->COR2
);
1203 sx_out(bp
, CD186x_COR3
, cor3
);
1204 /* Make CD186x know about registers change */
1206 sx_out(bp
, CD186x_CCR
, CCR_CORCHG1
| CCR_CORCHG2
| CCR_CORCHG3
);
1207 /* Setting up modem option registers */
1208 #ifdef DEBUG_SPECIALIX
1209 printk ("Mcor1 = %02x, mcor2 = %02x.\n", mcor1
, mcor2
);
1211 sx_out(bp
, CD186x_MCOR1
, mcor1
);
1212 sx_out(bp
, CD186x_MCOR2
, mcor2
);
1213 /* Enable CD186x transmitter & receiver */
1215 sx_out(bp
, CD186x_CCR
, CCR_TXEN
| CCR_RXEN
);
1216 /* Enable interrupts */
1217 sx_out(bp
, CD186x_IER
, port
->IER
);
1218 /* And finally set the modem lines... */
1219 sx_out(bp
, CD186x_MSVR
, port
->MSVR
);
1223 /* Must be called with interrupts enabled */
1224 static int sx_setup_port(struct specialix_board
*bp
, struct specialix_port
*port
)
1226 unsigned long flags
;
1228 if (port
->flags
& ASYNC_INITIALIZED
)
1231 if (!port
->xmit_buf
) {
1232 /* We may sleep in get_free_page() */
1235 if (!(tmp
= get_free_page(GFP_KERNEL
)))
1238 if (port
->xmit_buf
) {
1240 return -ERESTARTSYS
;
1242 port
->xmit_buf
= (unsigned char *) tmp
;
1245 save_flags(flags
); cli();
1248 clear_bit(TTY_IO_ERROR
, &port
->tty
->flags
);
1250 if (port
->count
== 1)
1253 port
->xmit_cnt
= port
->xmit_head
= port
->xmit_tail
= 0;
1254 sx_change_speed(bp
, port
);
1255 port
->flags
|= ASYNC_INITIALIZED
;
1257 restore_flags(flags
);
1262 /* Must be called with interrupts disabled */
1263 static void sx_shutdown_port(struct specialix_board
*bp
, struct specialix_port
*port
)
1265 struct tty_struct
*tty
;
1267 if (!(port
->flags
& ASYNC_INITIALIZED
))
1270 #ifdef SX_REPORT_OVERRUN
1271 printk(KERN_INFO
"sx%d: port %d: Total %ld overruns were detected.\n",
1272 board_No(bp
), port_No(port
), port
->overrun
);
1274 #ifdef SX_REPORT_FIFO
1278 printk(KERN_INFO
"sx%d: port %d: FIFO hits [ ",
1279 board_No(bp
), port_No(port
));
1280 for (i
= 0; i
< 10; i
++) {
1281 printk("%ld ", port
->hits
[i
]);
1286 if (port
->xmit_buf
) {
1287 free_page((unsigned long) port
->xmit_buf
);
1288 port
->xmit_buf
= NULL
;
1292 sx_out(bp
, CD186x_CAR
, port_No(port
));
1294 if (!(tty
= port
->tty
) || C_HUPCL(tty
)) {
1296 sx_out(bp
, CD186x_MSVDTR
, 0);
1301 sx_out(bp
, CD186x_CCR
, CCR_SOFTRESET
);
1302 /* Disable all interrupts from this port */
1304 sx_out(bp
, CD186x_IER
, port
->IER
);
1307 set_bit(TTY_IO_ERROR
, &tty
->flags
);
1308 port
->flags
&= ~ASYNC_INITIALIZED
;
1310 if (--bp
->count
< 0) {
1311 printk(KERN_ERR
"sx%d: sx_shutdown_port: bad board count: %d\n",
1312 board_No(bp
), bp
->count
);
1317 * If this is the last opened port on the board
1318 * shutdown whole board
1321 sx_shutdown_board(bp
);
1325 static int block_til_ready(struct tty_struct
*tty
, struct file
* filp
,
1326 struct specialix_port
*port
)
1328 DECLARE_WAITQUEUE(wait
, current
);
1329 struct specialix_board
*bp
= port_Board(port
);
1335 * If the device is in the middle of being closed, then block
1336 * until it's done, and then try again.
1338 if (tty_hung_up_p(filp
) || port
->flags
& ASYNC_CLOSING
) {
1339 interruptible_sleep_on(&port
->close_wait
);
1340 if (port
->flags
& ASYNC_HUP_NOTIFY
)
1343 return -ERESTARTSYS
;
1347 * If this is a callout device, then just make sure the normal
1348 * device isn't being used.
1350 if (tty
->driver
.subtype
== SPECIALIX_TYPE_CALLOUT
) {
1351 if (port
->flags
& ASYNC_NORMAL_ACTIVE
)
1353 if ((port
->flags
& ASYNC_CALLOUT_ACTIVE
) &&
1354 (port
->flags
& ASYNC_SESSION_LOCKOUT
) &&
1355 (port
->session
!= current
->session
))
1357 if ((port
->flags
& ASYNC_CALLOUT_ACTIVE
) &&
1358 (port
->flags
& ASYNC_PGRP_LOCKOUT
) &&
1359 (port
->pgrp
!= current
->pgrp
))
1361 port
->flags
|= ASYNC_CALLOUT_ACTIVE
;
1366 * If non-blocking mode is set, or the port is not enabled,
1367 * then make the check up front and then exit.
1369 if ((filp
->f_flags
& O_NONBLOCK
) ||
1370 (tty
->flags
& (1 << TTY_IO_ERROR
))) {
1371 if (port
->flags
& ASYNC_CALLOUT_ACTIVE
)
1373 port
->flags
|= ASYNC_NORMAL_ACTIVE
;
1377 if (port
->flags
& ASYNC_CALLOUT_ACTIVE
) {
1378 if (port
->normal_termios
.c_cflag
& CLOCAL
)
1386 * Block waiting for the carrier detect and the line to become
1387 * free (i.e., not in use by the callout). While we are in
1388 * this loop, info->count is dropped by one, so that
1389 * rs_close() knows when to free things. We restore it upon
1390 * exit, either normal or abnormal.
1393 add_wait_queue(&port
->open_wait
, &wait
);
1395 if (!tty_hung_up_p(filp
))
1398 port
->blocked_open
++;
1401 sx_out(bp
, CD186x_CAR
, port_No(port
));
1402 CD
= sx_in(bp
, CD186x_MSVR
) & MSVR_CD
;
1403 if (!(port
->flags
& ASYNC_CALLOUT_ACTIVE
)) {
1404 if (SX_CRTSCTS (tty
)) {
1406 port
->MSVR
|= MSVR_DTR
;
1407 sx_out (bp
, CD186x_MSVR
, port
->MSVR
);
1410 port
->MSVR
|= MSVR_DTR
;
1411 sx_out (bp
, CD186x_MSVR
, port
->MSVR
);
1415 set_current_state(TASK_INTERRUPTIBLE
);
1416 if (tty_hung_up_p(filp
) ||
1417 !(port
->flags
& ASYNC_INITIALIZED
)) {
1418 if (port
->flags
& ASYNC_HUP_NOTIFY
)
1421 retval
= -ERESTARTSYS
;
1424 if (!(port
->flags
& ASYNC_CALLOUT_ACTIVE
) &&
1425 !(port
->flags
& ASYNC_CLOSING
) &&
1428 if (signal_pending(current
)) {
1429 retval
= -ERESTARTSYS
;
1434 current
->state
= TASK_RUNNING
;
1435 remove_wait_queue(&port
->open_wait
, &wait
);
1436 if (!tty_hung_up_p(filp
))
1438 port
->blocked_open
--;
1442 port
->flags
|= ASYNC_NORMAL_ACTIVE
;
1447 static int sx_open(struct tty_struct
* tty
, struct file
* filp
)
1451 struct specialix_port
* port
;
1452 struct specialix_board
* bp
;
1453 unsigned long flags
;
1455 board
= SX_BOARD(MINOR(tty
->device
));
1457 if (board
> SX_NBOARD
|| !(sx_board
[board
].flags
& SX_BOARD_PRESENT
))
1460 bp
= &sx_board
[board
];
1461 port
= sx_port
+ board
* SX_NPORT
+ SX_PORT(MINOR(tty
->device
));
1463 #ifdef DEBUG_SPECIALIX
1464 printk (KERN_DEBUG
"Board = %d, bp = %p, port = %p, portno = %d.\n",
1465 board
, bp
, port
, SX_PORT(MINOR(tty
->device
)));
1468 if (sx_paranoia_check(port
, tty
->device
, "sx_open"))
1471 if ((error
= sx_setup_board(bp
)))
1475 tty
->driver_data
= port
;
1478 if ((error
= sx_setup_port(bp
, port
)))
1481 if ((error
= block_til_ready(tty
, filp
, port
)))
1484 if ((port
->count
== 1) && (port
->flags
& ASYNC_SPLIT_TERMIOS
)) {
1485 if (tty
->driver
.subtype
== SPECIALIX_TYPE_NORMAL
)
1486 *tty
->termios
= port
->normal_termios
;
1488 *tty
->termios
= port
->callout_termios
;
1489 save_flags(flags
); cli();
1490 sx_change_speed(bp
, port
);
1491 restore_flags(flags
);
1494 port
->session
= current
->session
;
1495 port
->pgrp
= current
->pgrp
;
1500 static void sx_close(struct tty_struct
* tty
, struct file
* filp
)
1502 struct specialix_port
*port
= (struct specialix_port
*) tty
->driver_data
;
1503 struct specialix_board
*bp
;
1504 unsigned long flags
;
1505 unsigned long timeout
;
1507 if (!port
|| sx_paranoia_check(port
, tty
->device
, "close"))
1510 save_flags(flags
); cli();
1511 if (tty_hung_up_p(filp
)) {
1512 restore_flags(flags
);
1516 bp
= port_Board(port
);
1517 if ((tty
->count
== 1) && (port
->count
!= 1)) {
1518 printk(KERN_ERR
"sx%d: sx_close: bad port count;"
1519 " tty->count is 1, port count is %d\n",
1520 board_No(bp
), port
->count
);
1523 if (--port
->count
< 0) {
1524 printk(KERN_ERR
"sx%d: sx_close: bad port count for tty%d: %d\n",
1525 board_No(bp
), port_No(port
), port
->count
);
1529 restore_flags(flags
);
1532 port
->flags
|= ASYNC_CLOSING
;
1534 * Save the termios structure, since this port may have
1535 * separate termios for callout and dialin.
1537 if (port
->flags
& ASYNC_NORMAL_ACTIVE
)
1538 port
->normal_termios
= *tty
->termios
;
1539 if (port
->flags
& ASYNC_CALLOUT_ACTIVE
)
1540 port
->callout_termios
= *tty
->termios
;
1542 * Now we wait for the transmit buffer to clear; and we notify
1543 * the line discipline to only process XON/XOFF characters.
1546 if (port
->closing_wait
!= ASYNC_CLOSING_WAIT_NONE
)
1547 tty_wait_until_sent(tty
, port
->closing_wait
);
1549 * At this point we stop accepting input. To do this, we
1550 * disable the receive line status interrupts, and tell the
1551 * interrupt driver to stop checking the data ready bit in the
1552 * line status register.
1554 port
->IER
&= ~IER_RXD
;
1555 if (port
->flags
& ASYNC_INITIALIZED
) {
1556 port
->IER
&= ~IER_TXRDY
;
1557 port
->IER
|= IER_TXEMPTY
;
1558 sx_out(bp
, CD186x_CAR
, port_No(port
));
1559 sx_out(bp
, CD186x_IER
, port
->IER
);
1561 * Before we drop DTR, make sure the UART transmitter
1562 * has completely drained; this is especially
1563 * important if there is a transmit FIFO!
1565 timeout
= jiffies
+HZ
;
1566 while(port
->IER
& IER_TXEMPTY
) {
1567 current
->state
= TASK_INTERRUPTIBLE
;
1568 schedule_timeout(port
->timeout
);
1569 if (time_after(jiffies
, timeout
)) {
1570 printk (KERN_INFO
"Timeout waiting for close\n");
1576 sx_shutdown_port(bp
, port
);
1577 if (tty
->driver
.flush_buffer
)
1578 tty
->driver
.flush_buffer(tty
);
1579 if (tty
->ldisc
.flush_buffer
)
1580 tty
->ldisc
.flush_buffer(tty
);
1584 if (port
->blocked_open
) {
1585 if (port
->close_delay
) {
1586 current
->state
= TASK_INTERRUPTIBLE
;
1587 schedule_timeout(port
->close_delay
);
1589 wake_up_interruptible(&port
->open_wait
);
1591 port
->flags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
|
1593 wake_up_interruptible(&port
->close_wait
);
1594 restore_flags(flags
);
1598 static int sx_write(struct tty_struct
* tty
, int from_user
,
1599 const unsigned char *buf
, int count
)
1601 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
1602 struct specialix_board
*bp
;
1604 unsigned long flags
;
1606 if (sx_paranoia_check(port
, tty
->device
, "sx_write"))
1609 bp
= port_Board(port
);
1611 if (!tty
|| !port
->xmit_buf
|| !tmp_buf
)
1620 c
= MIN(count
, MIN(SERIAL_XMIT_SIZE
- port
->xmit_cnt
- 1,
1621 SERIAL_XMIT_SIZE
- port
->xmit_head
));
1626 copy_from_user(tmp_buf
, buf
, c
);
1627 c
= MIN(c
, MIN(SERIAL_XMIT_SIZE
- port
->xmit_cnt
- 1,
1628 SERIAL_XMIT_SIZE
- port
->xmit_head
));
1629 memcpy(port
->xmit_buf
+ port
->xmit_head
, tmp_buf
, c
);
1631 memcpy(port
->xmit_buf
+ port
->xmit_head
, buf
, c
);
1632 port
->xmit_head
= (port
->xmit_head
+ c
) & (SERIAL_XMIT_SIZE
-1);
1633 port
->xmit_cnt
+= c
;
1634 restore_flags(flags
);
1641 if (port
->xmit_cnt
&& !tty
->stopped
&& !tty
->hw_stopped
&&
1642 !(port
->IER
& IER_TXRDY
)) {
1643 port
->IER
|= IER_TXRDY
;
1644 sx_out(bp
, CD186x_CAR
, port_No(port
));
1645 sx_out(bp
, CD186x_IER
, port
->IER
);
1647 restore_flags(flags
);
1652 static void sx_put_char(struct tty_struct
* tty
, unsigned char ch
)
1654 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
1655 unsigned long flags
;
1657 if (sx_paranoia_check(port
, tty
->device
, "sx_put_char"))
1660 if (!tty
|| !port
->xmit_buf
)
1663 save_flags(flags
); cli();
1665 if (port
->xmit_cnt
>= SERIAL_XMIT_SIZE
- 1) {
1666 restore_flags(flags
);
1670 port
->xmit_buf
[port
->xmit_head
++] = ch
;
1671 port
->xmit_head
&= SERIAL_XMIT_SIZE
- 1;
1673 restore_flags(flags
);
1677 static void sx_flush_chars(struct tty_struct
* tty
)
1679 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
1680 unsigned long flags
;
1682 if (sx_paranoia_check(port
, tty
->device
, "sx_flush_chars"))
1685 if (port
->xmit_cnt
<= 0 || tty
->stopped
|| tty
->hw_stopped
||
1689 save_flags(flags
); cli();
1690 port
->IER
|= IER_TXRDY
;
1691 sx_out(port_Board(port
), CD186x_CAR
, port_No(port
));
1692 sx_out(port_Board(port
), CD186x_IER
, port
->IER
);
1693 restore_flags(flags
);
1697 static int sx_write_room(struct tty_struct
* tty
)
1699 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
1702 if (sx_paranoia_check(port
, tty
->device
, "sx_write_room"))
1705 ret
= SERIAL_XMIT_SIZE
- port
->xmit_cnt
- 1;
1712 static int sx_chars_in_buffer(struct tty_struct
*tty
)
1714 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
1716 if (sx_paranoia_check(port
, tty
->device
, "sx_chars_in_buffer"))
1719 return port
->xmit_cnt
;
1723 static void sx_flush_buffer(struct tty_struct
*tty
)
1725 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
1726 unsigned long flags
;
1728 if (sx_paranoia_check(port
, tty
->device
, "sx_flush_buffer"))
1731 save_flags(flags
); cli();
1732 port
->xmit_cnt
= port
->xmit_head
= port
->xmit_tail
= 0;
1733 restore_flags(flags
);
1735 wake_up_interruptible(&tty
->write_wait
);
1736 if ((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) &&
1737 tty
->ldisc
.write_wakeup
)
1738 (tty
->ldisc
.write_wakeup
)(tty
);
1742 static int sx_get_modem_info(struct specialix_port
* port
, unsigned int *value
)
1744 struct specialix_board
* bp
;
1745 unsigned char status
;
1746 unsigned int result
;
1747 unsigned long flags
;
1749 bp
= port_Board(port
);
1750 save_flags(flags
); cli();
1751 sx_out(bp
, CD186x_CAR
, port_No(port
));
1752 status
= sx_in(bp
, CD186x_MSVR
);
1753 restore_flags(flags
);
1754 #ifdef DEBUG_SPECIALIX
1755 printk (KERN_DEBUG
"Got msvr[%d] = %02x, car = %d.\n",
1756 port_No(port
), status
, sx_in (bp
, CD186x_CAR
));
1757 printk (KERN_DEBUG
"sx_port = %p, port = %p\n", sx_port
, port
);
1759 if (SX_CRTSCTS(port
->tty
)) {
1760 result
= /* (status & MSVR_RTS) ? */ TIOCM_DTR
/* : 0) */
1761 | ((status
& MSVR_DTR
) ? TIOCM_RTS
: 0)
1762 | ((status
& MSVR_CD
) ? TIOCM_CAR
: 0)
1763 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR
/* : 0) */
1764 | ((status
& MSVR_CTS
) ? TIOCM_CTS
: 0);
1766 result
= /* (status & MSVR_RTS) ? */ TIOCM_RTS
/* : 0) */
1767 | ((status
& MSVR_DTR
) ? TIOCM_DTR
: 0)
1768 | ((status
& MSVR_CD
) ? TIOCM_CAR
: 0)
1769 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR
/* : 0) */
1770 | ((status
& MSVR_CTS
) ? TIOCM_CTS
: 0);
1772 put_user(result
,(unsigned int *) value
);
1777 static int sx_set_modem_info(struct specialix_port
* port
, unsigned int cmd
,
1778 unsigned int *value
)
1782 unsigned long flags
;
1783 struct specialix_board
*bp
= port_Board(port
);
1785 error
= verify_area(VERIFY_READ
, value
, sizeof(int));
1789 Get_user(arg
, (unsigned long *) value
);
1792 /* if (arg & TIOCM_RTS)
1793 port->MSVR |= MSVR_RTS; */
1794 /* if (arg & TIOCM_DTR)
1795 port->MSVR |= MSVR_DTR; */
1797 if (SX_CRTSCTS(port
->tty
)) {
1798 if (arg
& TIOCM_RTS
)
1799 port
->MSVR
|= MSVR_DTR
;
1801 if (arg
& TIOCM_DTR
)
1802 port
->MSVR
|= MSVR_DTR
;
1806 /* if (arg & TIOCM_RTS)
1807 port->MSVR &= ~MSVR_RTS; */
1808 /* if (arg & TIOCM_DTR)
1809 port->MSVR &= ~MSVR_DTR; */
1810 if (SX_CRTSCTS(port
->tty
)) {
1811 if (arg
& TIOCM_RTS
)
1812 port
->MSVR
&= ~MSVR_DTR
;
1814 if (arg
& TIOCM_DTR
)
1815 port
->MSVR
&= ~MSVR_DTR
;
1819 /* port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | MSVR_RTS) :
1820 (port->MSVR & ~MSVR_RTS); */
1821 /* port->MSVR = (arg & TIOCM_DTR) ? (port->MSVR | MSVR_DTR) :
1822 (port->MSVR & ~MSVR_DTR); */
1823 if (SX_CRTSCTS(port
->tty
)) {
1824 port
->MSVR
= (arg
& TIOCM_RTS
) ?
1825 (port
->MSVR
| MSVR_DTR
) :
1826 (port
->MSVR
& ~MSVR_DTR
);
1828 port
->MSVR
= (arg
& TIOCM_DTR
) ?
1829 (port
->MSVR
| MSVR_DTR
):
1830 (port
->MSVR
& ~MSVR_DTR
);
1836 save_flags(flags
); cli();
1837 sx_out(bp
, CD186x_CAR
, port_No(port
));
1838 sx_out(bp
, CD186x_MSVR
, port
->MSVR
);
1839 restore_flags(flags
);
1844 extern inline void sx_send_break(struct specialix_port
* port
, unsigned long length
)
1846 struct specialix_board
*bp
= port_Board(port
);
1847 unsigned long flags
;
1849 save_flags(flags
); cli();
1850 port
->break_length
= SPECIALIX_TPS
/ HZ
* length
;
1851 port
->COR2
|= COR2_ETC
;
1852 port
->IER
|= IER_TXRDY
;
1853 sx_out(bp
, CD186x_CAR
, port_No(port
));
1854 sx_out(bp
, CD186x_COR2
, port
->COR2
);
1855 sx_out(bp
, CD186x_IER
, port
->IER
);
1857 sx_out(bp
, CD186x_CCR
, CCR_CORCHG2
);
1859 restore_flags(flags
);
1863 extern inline int sx_set_serial_info(struct specialix_port
* port
,
1864 struct serial_struct
* newinfo
)
1866 struct serial_struct tmp
;
1867 struct specialix_board
*bp
= port_Board(port
);
1869 unsigned long flags
;
1872 error
= verify_area(VERIFY_READ
, (void *) newinfo
, sizeof(tmp
));
1876 if (copy_from_user(&tmp
, newinfo
, sizeof(tmp
)))
1880 if ((tmp
.irq
!= bp
->irq
) ||
1881 (tmp
.port
!= bp
->base
) ||
1882 (tmp
.type
!= PORT_CIRRUS
) ||
1883 (tmp
.baud_base
!= (SX_OSCFREQ
+ CD186x_TPC
/2) / CD186x_TPC
) ||
1884 (tmp
.custom_divisor
!= 0) ||
1885 (tmp
.xmit_fifo_size
!= CD186x_NFIFO
) ||
1886 (tmp
.flags
& ~SPECIALIX_LEGAL_FLAGS
))
1890 change_speed
= ((port
->flags
& ASYNC_SPD_MASK
) !=
1891 (tmp
.flags
& ASYNC_SPD_MASK
));
1892 change_speed
|= (tmp
.custom_divisor
!= port
->custom_divisor
);
1894 if (!capable(CAP_SYS_ADMIN
)) {
1895 if ((tmp
.close_delay
!= port
->close_delay
) ||
1896 (tmp
.closing_wait
!= port
->closing_wait
) ||
1897 ((tmp
.flags
& ~ASYNC_USR_MASK
) !=
1898 (port
->flags
& ~ASYNC_USR_MASK
)))
1900 port
->flags
= ((port
->flags
& ~ASYNC_USR_MASK
) |
1901 (tmp
.flags
& ASYNC_USR_MASK
));
1902 port
->custom_divisor
= tmp
.custom_divisor
;
1904 port
->flags
= ((port
->flags
& ~ASYNC_FLAGS
) |
1905 (tmp
.flags
& ASYNC_FLAGS
));
1906 port
->close_delay
= tmp
.close_delay
;
1907 port
->closing_wait
= tmp
.closing_wait
;
1908 port
->custom_divisor
= tmp
.custom_divisor
;
1911 save_flags(flags
); cli();
1912 sx_change_speed(bp
, port
);
1913 restore_flags(flags
);
1919 extern inline int sx_get_serial_info(struct specialix_port
* port
,
1920 struct serial_struct
* retinfo
)
1922 struct serial_struct tmp
;
1923 struct specialix_board
*bp
= port_Board(port
);
1926 error
= verify_area(VERIFY_WRITE
, (void *) retinfo
, sizeof(tmp
));
1930 memset(&tmp
, 0, sizeof(tmp
));
1931 tmp
.type
= PORT_CIRRUS
;
1932 tmp
.line
= port
- sx_port
;
1933 tmp
.port
= bp
->base
;
1935 tmp
.flags
= port
->flags
;
1936 tmp
.baud_base
= (SX_OSCFREQ
+ CD186x_TPC
/2) / CD186x_TPC
;
1937 tmp
.close_delay
= port
->close_delay
* HZ
/100;
1938 tmp
.closing_wait
= port
->closing_wait
* HZ
/100;
1939 tmp
.custom_divisor
= port
->custom_divisor
;
1940 tmp
.xmit_fifo_size
= CD186x_NFIFO
;
1941 if (copy_to_user(retinfo
, &tmp
, sizeof(tmp
)))
1947 static int sx_ioctl(struct tty_struct
* tty
, struct file
* filp
,
1948 unsigned int cmd
, unsigned long arg
)
1950 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
1954 if (sx_paranoia_check(port
, tty
->device
, "sx_ioctl"))
1958 case TCSBRK
: /* SVID version: non-zero arg --> no break */
1959 retval
= tty_check_change(tty
);
1962 tty_wait_until_sent(tty
, 0);
1964 sx_send_break(port
, HZ
/4); /* 1/4 second */
1966 case TCSBRKP
: /* support for POSIX tcsendbreak() */
1967 retval
= tty_check_change(tty
);
1970 tty_wait_until_sent(tty
, 0);
1971 sx_send_break(port
, arg
? arg
*(HZ
/10) : HZ
/4);
1974 error
= verify_area(VERIFY_WRITE
, (void *) arg
, sizeof(long));
1977 put_user(C_CLOCAL(tty
) ? 1 : 0,
1978 (unsigned long *) arg
);
1981 Get_user(arg
, (unsigned long *) arg
);
1982 tty
->termios
->c_cflag
=
1983 ((tty
->termios
->c_cflag
& ~CLOCAL
) |
1984 (arg
? CLOCAL
: 0));
1987 error
= verify_area(VERIFY_WRITE
, (void *) arg
,
1988 sizeof(unsigned int));
1991 return sx_get_modem_info(port
, (unsigned int *) arg
);
1995 return sx_set_modem_info(port
, cmd
, (unsigned int *) arg
);
1997 return sx_get_serial_info(port
, (struct serial_struct
*) arg
);
1999 return sx_set_serial_info(port
, (struct serial_struct
*) arg
);
2001 return -ENOIOCTLCMD
;
2007 static void sx_throttle(struct tty_struct
* tty
)
2009 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
2010 struct specialix_board
*bp
;
2011 unsigned long flags
;
2013 if (sx_paranoia_check(port
, tty
->device
, "sx_throttle"))
2016 bp
= port_Board(port
);
2018 save_flags(flags
); cli();
2020 /* Use DTR instead of RTS ! */
2021 if (SX_CRTSCTS (tty
))
2022 port
->MSVR
&= ~MSVR_DTR
;
2024 /* Auch!!! I think the system shouldn't call this then. */
2025 /* Or maybe we're supposed (allowed?) to do our side of hw
2026 handshake anyway, even when hardware handshake is off.
2027 When you see this in your logs, please report.... */
2028 printk (KERN_ERR
"sx%d: Need to throttle, but can't (hardware hs is off)\n",
2031 sx_out(bp
, CD186x_CAR
, port_No(port
));
2034 sx_out(bp
, CD186x_CCR
, CCR_SSCH2
);
2037 sx_out(bp
, CD186x_MSVR
, port
->MSVR
);
2038 restore_flags(flags
);
2042 static void sx_unthrottle(struct tty_struct
* tty
)
2044 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
2045 struct specialix_board
*bp
;
2046 unsigned long flags
;
2048 if (sx_paranoia_check(port
, tty
->device
, "sx_unthrottle"))
2051 bp
= port_Board(port
);
2053 save_flags(flags
); cli();
2054 /* XXXX Use DTR INSTEAD???? */
2055 if (SX_CRTSCTS(tty
)) {
2056 port
->MSVR
|= MSVR_DTR
;
2057 } /* Else clause: see remark in "sx_throttle"... */
2059 sx_out(bp
, CD186x_CAR
, port_No(port
));
2062 sx_out(bp
, CD186x_CCR
, CCR_SSCH1
);
2065 sx_out(bp
, CD186x_MSVR
, port
->MSVR
);
2066 restore_flags(flags
);
2070 static void sx_stop(struct tty_struct
* tty
)
2072 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
2073 struct specialix_board
*bp
;
2074 unsigned long flags
;
2076 if (sx_paranoia_check(port
, tty
->device
, "sx_stop"))
2079 bp
= port_Board(port
);
2081 save_flags(flags
); cli();
2082 port
->IER
&= ~IER_TXRDY
;
2083 sx_out(bp
, CD186x_CAR
, port_No(port
));
2084 sx_out(bp
, CD186x_IER
, port
->IER
);
2085 restore_flags(flags
);
2089 static void sx_start(struct tty_struct
* tty
)
2091 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
2092 struct specialix_board
*bp
;
2093 unsigned long flags
;
2095 if (sx_paranoia_check(port
, tty
->device
, "sx_start"))
2098 bp
= port_Board(port
);
2100 save_flags(flags
); cli();
2101 if (port
->xmit_cnt
&& port
->xmit_buf
&& !(port
->IER
& IER_TXRDY
)) {
2102 port
->IER
|= IER_TXRDY
;
2103 sx_out(bp
, CD186x_CAR
, port_No(port
));
2104 sx_out(bp
, CD186x_IER
, port
->IER
);
2106 restore_flags(flags
);
2111 * This routine is called from the scheduler tqueue when the interrupt
2112 * routine has signalled that a hangup has occurred. The path of
2113 * hangup processing is:
2115 * serial interrupt routine -> (scheduler tqueue) ->
2116 * do_sx_hangup() -> tty->hangup() -> sx_hangup()
2119 static void do_sx_hangup(void *private_
)
2121 struct specialix_port
*port
= (struct specialix_port
*) private_
;
2122 struct tty_struct
*tty
;
2126 tty_hangup(tty
); /* FIXME: module removal race here */
2131 static void sx_hangup(struct tty_struct
* tty
)
2133 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
2134 struct specialix_board
*bp
;
2136 if (sx_paranoia_check(port
, tty
->device
, "sx_hangup"))
2139 bp
= port_Board(port
);
2141 sx_shutdown_port(bp
, port
);
2144 port
->flags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
2146 wake_up_interruptible(&port
->open_wait
);
2150 static void sx_set_termios(struct tty_struct
* tty
, struct termios
* old_termios
)
2152 struct specialix_port
*port
= (struct specialix_port
*)tty
->driver_data
;
2153 unsigned long flags
;
2155 if (sx_paranoia_check(port
, tty
->device
, "sx_set_termios"))
2158 if (tty
->termios
->c_cflag
== old_termios
->c_cflag
&&
2159 tty
->termios
->c_iflag
== old_termios
->c_iflag
)
2162 save_flags(flags
); cli();
2163 sx_change_speed(port_Board(port
), port
);
2164 restore_flags(flags
);
2166 if ((old_termios
->c_cflag
& CRTSCTS
) &&
2167 !(tty
->termios
->c_cflag
& CRTSCTS
)) {
2168 tty
->hw_stopped
= 0;
2174 static void do_specialix_bh(void)
2176 run_task_queue(&tq_specialix
);
2180 static void do_softint(void *private_
)
2182 struct specialix_port
*port
= (struct specialix_port
*) private_
;
2183 struct tty_struct
*tty
;
2185 if(!(tty
= port
->tty
))
2188 if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP
, &port
->event
)) {
2189 if ((tty
->flags
& (1 << TTY_DO_WRITE_WAKEUP
)) &&
2190 tty
->ldisc
.write_wakeup
)
2191 (tty
->ldisc
.write_wakeup
)(tty
);
2192 wake_up_interruptible(&tty
->write_wait
);
2197 static int sx_init_drivers(void)
2203 if (!(tmp_buf
= (unsigned char *) get_free_page(GFP_KERNEL
))) {
2204 printk(KERN_ERR
"sx: Couldn't get free page.\n");
2207 init_bh(SPECIALIX_BH
, do_specialix_bh
);
2208 memset(&specialix_driver
, 0, sizeof(specialix_driver
));
2209 specialix_driver
.magic
= TTY_DRIVER_MAGIC
;
2210 specialix_driver
.name
= "ttyW";
2211 specialix_driver
.major
= SPECIALIX_NORMAL_MAJOR
;
2212 specialix_driver
.num
= SX_NBOARD
* SX_NPORT
;
2213 specialix_driver
.type
= TTY_DRIVER_TYPE_SERIAL
;
2214 specialix_driver
.subtype
= SPECIALIX_TYPE_NORMAL
;
2215 specialix_driver
.init_termios
= tty_std_termios
;
2216 specialix_driver
.init_termios
.c_cflag
=
2217 B9600
| CS8
| CREAD
| HUPCL
| CLOCAL
;
2218 specialix_driver
.flags
= TTY_DRIVER_REAL_RAW
;
2219 specialix_driver
.refcount
= &specialix_refcount
;
2220 specialix_driver
.table
= specialix_table
;
2221 specialix_driver
.termios
= specialix_termios
;
2222 specialix_driver
.termios_locked
= specialix_termios_locked
;
2224 specialix_driver
.open
= sx_open
;
2225 specialix_driver
.close
= sx_close
;
2226 specialix_driver
.write
= sx_write
;
2227 specialix_driver
.put_char
= sx_put_char
;
2228 specialix_driver
.flush_chars
= sx_flush_chars
;
2229 specialix_driver
.write_room
= sx_write_room
;
2230 specialix_driver
.chars_in_buffer
= sx_chars_in_buffer
;
2231 specialix_driver
.flush_buffer
= sx_flush_buffer
;
2232 specialix_driver
.ioctl
= sx_ioctl
;
2233 specialix_driver
.throttle
= sx_throttle
;
2234 specialix_driver
.unthrottle
= sx_unthrottle
;
2235 specialix_driver
.set_termios
= sx_set_termios
;
2236 specialix_driver
.stop
= sx_stop
;
2237 specialix_driver
.start
= sx_start
;
2238 specialix_driver
.hangup
= sx_hangup
;
2240 specialix_callout_driver
= specialix_driver
;
2241 specialix_callout_driver
.name
= "cuw";
2242 specialix_callout_driver
.major
= SPECIALIX_CALLOUT_MAJOR
;
2243 specialix_callout_driver
.subtype
= SPECIALIX_TYPE_CALLOUT
;
2245 if ((error
= tty_register_driver(&specialix_driver
))) {
2246 free_page((unsigned long)tmp_buf
);
2247 printk(KERN_ERR
"sx: Couldn't register specialix IO8+ driver, error = %d\n",
2251 if ((error
= tty_register_driver(&specialix_callout_driver
))) {
2252 free_page((unsigned long)tmp_buf
);
2253 tty_unregister_driver(&specialix_driver
);
2254 printk(KERN_ERR
"sx: Couldn't register specialix IO8+ callout driver, error = %d\n",
2259 memset(sx_port
, 0, sizeof(sx_port
));
2260 for (i
= 0; i
< SX_NPORT
* SX_NBOARD
; i
++) {
2261 sx_port
[i
].callout_termios
= specialix_callout_driver
.init_termios
;
2262 sx_port
[i
].normal_termios
= specialix_driver
.init_termios
;
2263 sx_port
[i
].magic
= SPECIALIX_MAGIC
;
2264 sx_port
[i
].tqueue
.routine
= do_softint
;
2265 sx_port
[i
].tqueue
.data
= &sx_port
[i
];
2266 sx_port
[i
].tqueue_hangup
.routine
= do_sx_hangup
;
2267 sx_port
[i
].tqueue_hangup
.data
= &sx_port
[i
];
2268 sx_port
[i
].close_delay
= 50 * HZ
/100;
2269 sx_port
[i
].closing_wait
= 3000 * HZ
/100;
2270 init_waitqueue_head(&sx_port
[i
].open_wait
);
2271 init_waitqueue_head(&sx_port
[i
].close_wait
);
2278 static void sx_release_drivers(void)
2280 free_page((unsigned long)tmp_buf
);
2281 tty_unregister_driver(&specialix_driver
);
2282 tty_unregister_driver(&specialix_callout_driver
);
2288 * Called at boot time.
2290 * You can specify IO base for up to SX_NBOARD cards,
2291 * using line "specialix=0xiobase1,0xiobase2,.." at LILO prompt.
2292 * Note that there will be no probing at default
2293 * addresses in this case.
2296 void specialix_setup(char *str
, int * ints
)
2300 for (i
=0;i
<SX_NBOARD
;i
++) {
2301 sx_board
[i
].base
= 0;
2304 for (i
= 1; i
<= ints
[0]; i
++) {
2306 sx_board
[i
/2].base
= ints
[i
];
2308 sx_board
[i
/2 -1].irq
= ints
[i
];
2314 * This routine must be called by kernel at boot time
2316 int specialix_init(void)
2321 printk(KERN_INFO
"sx: Specialix IO8+ driver v" VERSION
", (c) R.E.Wolff 1997/1998.\n");
2322 printk(KERN_INFO
"sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2323 #ifdef CONFIG_SPECIALIX_RTSCTS
2324 printk (KERN_INFO
"sx: DTR/RTS pin is always RTS.\n");
2326 printk (KERN_INFO
"sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2329 if (sx_init_drivers())
2332 for (i
= 0; i
< SX_NBOARD
; i
++)
2333 if (sx_board
[i
].base
&& !sx_probe(&sx_board
[i
]))
2337 if (pci_present()) {
2338 struct pci_dev
*pdev
= NULL
;
2341 while (i
<= SX_NBOARD
) {
2342 if (sx_board
[i
].flags
& SX_BOARD_PRESENT
) {
2346 pdev
= pci_find_device (PCI_VENDOR_ID_SPECIALIX
,
2347 PCI_DEVICE_ID_SPECIALIX_IO8
,
2351 if (pci_enable_device(pdev
))
2354 sx_board
[i
].irq
= pdev
->irq
;
2356 sx_board
[i
].base
= pci_resource_start (pdev
, 2);
2358 sx_board
[i
].flags
|= SX_BOARD_IS_PCI
;
2359 if (!sx_probe(&sx_board
[i
]))
2366 sx_release_drivers();
2367 printk(KERN_INFO
"sx: No specialix IO8+ boards detected.\n");
2375 int iobase
[SX_NBOARD
] = {0,};
2377 int irq
[SX_NBOARD
] = {0,};
2379 MODULE_PARM(iobase
,"1-" __MODULE_STRING(SX_NBOARD
) "i");
2380 MODULE_PARM(irq
,"1-" __MODULE_STRING(SX_NBOARD
) "i");
2383 * You can setup up to 4 boards.
2384 * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
2385 * You should specify the IRQs too in that case "irq=....,...".
2387 * More than 4 boards in one computer is not possible, as the card can
2388 * only use 4 different interrupts.
2391 int init_module(void)
2395 if (iobase
[0] || iobase
[1] || iobase
[2] || iobase
[3]) {
2396 for(i
= 0; i
< SX_NBOARD
; i
++) {
2397 sx_board
[i
].base
= iobase
[i
];
2398 sx_board
[i
].irq
= irq
[i
];
2402 return specialix_init();
2406 void cleanup_module(void)
2410 sx_release_drivers();
2411 for (i
= 0; i
< SX_NBOARD
; i
++)
2412 if (sx_board
[i
].flags
& SX_BOARD_PRESENT
)
2413 sx_release_io_range(&sx_board
[i
]);
2414 #ifdef SPECIALIX_TIMER
2415 del_timer (&missed_irq_timer
);