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