]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/char/specialix.c
[PPC] minor irq handler cleanups
[mirror_ubuntu-artful-kernel.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");
d61780c0 446 sx_interrupt (((struct specialix_board *)data)->irq,
d096f3e9 447 (void*)data);
1da177e4 448 }
40565f19 449 mod_timer(&missed_irq_timer, jiffies + sx_poll);
1da177e4
LT
450}
451#endif
452
453
454
455/* Main probing routine, also sets irq. */
456static int sx_probe(struct specialix_board *bp)
457{
458 unsigned char val1, val2;
459#if 0
460 int irqs = 0;
461 int retries;
462#endif
463 int rev;
464 int chip;
465
466 func_enter();
467
d61780c0 468 if (sx_request_io_range(bp)) {
1da177e4
LT
469 func_exit();
470 return 1;
471 }
472
473 /* Are the I/O ports here ? */
474 sx_out_off(bp, CD186x_PPRL, 0x5a);
475 short_pause ();
476 val1 = sx_in_off(bp, CD186x_PPRL);
477
478 sx_out_off(bp, CD186x_PPRL, 0xa5);
479 short_pause ();
480 val2 = sx_in_off(bp, CD186x_PPRL);
481
d61780c0 482
1da177e4
LT
483 if ((val1 != 0x5a) || (val2 != 0xa5)) {
484 printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
485 board_No(bp), bp->base);
d61780c0 486 sx_release_io_range(bp);
1da177e4
LT
487 func_exit();
488 return 1;
489 }
490
d61780c0 491 /* Check the DSR lines that Specialix uses as board
1da177e4
LT
492 identification */
493 val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
494 val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
495 dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
496 board_No(bp), val1, val2);
497
498 /* They managed to switch the bit order between the docs and
499 the IO8+ card. The new PCI card now conforms to old docs.
500 They changed the PCI docs to reflect the situation on the
501 old card. */
502 val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
503 if (val1 != val2) {
504 printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
505 board_No(bp), val2, bp->base, val1);
d61780c0 506 sx_release_io_range(bp);
1da177e4
LT
507 func_exit();
508 return 1;
509 }
510
511
512#if 0
513 /* It's time to find IRQ for this board */
514 for (retries = 0; retries < 5 && irqs <= 0; retries++) {
515 irqs = probe_irq_on();
516 sx_init_CD186x(bp); /* Reset CD186x chip */
517 sx_out(bp, CD186x_CAR, 2); /* Select port 2 */
518 sx_wait_CCR(bp);
519 sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */
520 sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */
3e98cee7 521 msleep(50);
1da177e4
LT
522 irqs = probe_irq_off(irqs);
523
524 dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
525 dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
526 dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
527 dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR));
528 dprintk (SX_DEBUG_INIT, "\n");
529
530 /* Reset CD186x again */
531 if (!sx_init_CD186x(bp)) {
532 /* Hmmm. This is dead code anyway. */
533 }
534
535 dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
d61780c0
JG
536 val1, val2, val3);
537
1da177e4 538 }
d61780c0 539
1da177e4
LT
540#if 0
541 if (irqs <= 0) {
542 printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
543 board_No(bp), bp->base);
d61780c0 544 sx_release_io_range(bp);
1da177e4
LT
545 func_exit();
546 return 1;
547 }
548#endif
549 printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
550 if (irqs > 0)
551 bp->irq = irqs;
552#endif
553 /* Reset CD186x again */
554 if (!sx_init_CD186x(bp)) {
d61780c0 555 sx_release_io_range(bp);
1da177e4 556 func_exit();
d61780c0 557 return 1;
1da177e4
LT
558 }
559
560 sx_request_io_range(bp);
561 bp->flags |= SX_BOARD_PRESENT;
d61780c0 562
1da177e4
LT
563 /* Chip revcode pkgtype
564 GFRCR SRCR bit 7
565 CD180 rev B 0x81 0
566 CD180 rev C 0x82 0
567 CD1864 rev A 0x82 1
d61780c0 568 CD1865 rev A 0x83 1 -- Do not use!!! Does not work.
1da177e4
LT
569 CD1865 rev B 0x84 1
570 -- Thanks to Gwen Wang, Cirrus Logic.
571 */
572
573 switch (sx_in_off(bp, CD186x_GFRCR)) {
574 case 0x82:chip = 1864;rev='A';break;
575 case 0x83:chip = 1865;rev='A';break;
576 case 0x84:chip = 1865;rev='B';break;
577 case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */
578 default:chip=-1;rev='x';
579 }
580
581 dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
582
583#ifdef SPECIALIX_TIMER
40565f19
JS
584 setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp);
585 mod_timer(&missed_irq_timer, jiffies + sx_poll);
1da177e4
LT
586#endif
587
588 printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
589 board_No(bp),
590 bp->base, bp->irq,
591 chip, rev);
592
593 func_exit();
594 return 0;
595}
596
d61780c0
JG
597/*
598 *
1da177e4
LT
599 * Interrupt processing routines.
600 * */
601
1da177e4
LT
602static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
603 unsigned char const * what)
604{
605 unsigned char channel;
606 struct specialix_port * port = NULL;
607
608 channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
609 dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel);
610 if (channel < CD186x_NCH) {
611 port = &sx_port[board_No(bp) * SX_NPORT + channel];
612 dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%x\n",board_No(bp) * SX_NPORT + channel, port, port->flags & ASYNC_INITIALIZED);
613
614 if (port->flags & ASYNC_INITIALIZED) {
615 dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
616 func_exit();
617 return port;
618 }
619 }
d61780c0 620 printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
1da177e4
LT
621 board_No(bp), what, channel);
622 return NULL;
623}
624
625
626static inline void sx_receive_exc(struct specialix_board * bp)
627{
628 struct specialix_port *port;
629 struct tty_struct *tty;
630 unsigned char status;
33f0f88f 631 unsigned char ch, flag;
1da177e4
LT
632
633 func_enter();
634
635 port = sx_get_port(bp, "Receive");
636 if (!port) {
637 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
638 func_exit();
639 return;
640 }
641 tty = port->tty;
d61780c0 642
1da177e4
LT
643 status = sx_in(bp, CD186x_RCSR);
644
645 dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
646 if (status & RCSR_OE) {
647 port->overrun++;
648 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
649 board_No(bp), port_No(port), port->overrun);
650 }
651 status &= port->mark_mask;
652
653 /* This flip buffer check needs to be below the reading of the
654 status register to reset the chip's IRQ.... */
33f0f88f 655 if (tty_buffer_request_room(tty, 1) == 0) {
1da177e4
LT
656 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
657 board_No(bp), port_No(port));
658 func_exit();
659 return;
660 }
661
662 ch = sx_in(bp, CD186x_RDR);
663 if (!status) {
664 func_exit();
665 return;
666 }
667 if (status & RCSR_TOUT) {
d61780c0 668 printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
1da177e4
LT
669 board_No(bp), port_No(port));
670 func_exit();
671 return;
d61780c0 672
1da177e4
LT
673 } else if (status & RCSR_BREAK) {
674 dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
675 board_No(bp), port_No(port));
33f0f88f 676 flag = TTY_BREAK;
1da177e4
LT
677 if (port->flags & ASYNC_SAK)
678 do_SAK(tty);
d61780c0
JG
679
680 } else if (status & RCSR_PE)
33f0f88f 681 flag = TTY_PARITY;
d61780c0
JG
682
683 else if (status & RCSR_FE)
33f0f88f 684 flag = TTY_FRAME;
d61780c0 685
1da177e4 686 else if (status & RCSR_OE)
33f0f88f 687 flag = TTY_OVERRUN;
d61780c0 688
1da177e4 689 else
33f0f88f 690 flag = TTY_NORMAL;
1da177e4 691
33f0f88f
AC
692 if(tty_insert_flip_char(tty, ch, flag))
693 tty_flip_buffer_push(tty);
1da177e4
LT
694 func_exit();
695}
696
697
698static inline void sx_receive(struct specialix_board * bp)
699{
700 struct specialix_port *port;
701 struct tty_struct *tty;
702 unsigned char count;
703
704 func_enter();
d61780c0 705
1da177e4
LT
706 if (!(port = sx_get_port(bp, "Receive"))) {
707 dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
708 func_exit();
709 return;
710 }
711 tty = port->tty;
d61780c0 712
1da177e4
LT
713 count = sx_in(bp, CD186x_RDCR);
714 dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
715 port->hits[count > 8 ? 9 : count]++;
d61780c0 716
33f0f88f 717 tty_buffer_request_room(tty, count);
1da177e4 718
33f0f88f
AC
719 while (count--)
720 tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
721 tty_flip_buffer_push(tty);
1da177e4
LT
722 func_exit();
723}
724
725
726static inline void sx_transmit(struct specialix_board * bp)
727{
728 struct specialix_port *port;
729 struct tty_struct *tty;
730 unsigned char count;
731
732 func_enter();
733 if (!(port = sx_get_port(bp, "Transmit"))) {
734 func_exit();
735 return;
736 }
737 dprintk (SX_DEBUG_TX, "port: %p\n", port);
738 tty = port->tty;
d61780c0 739
1da177e4
LT
740 if (port->IER & IER_TXEMPTY) {
741 /* FIFO drained */
742 sx_out(bp, CD186x_CAR, port_No(port));
743 port->IER &= ~IER_TXEMPTY;
744 sx_out(bp, CD186x_IER, port->IER);
745 func_exit();
746 return;
747 }
d61780c0 748
1da177e4
LT
749 if ((port->xmit_cnt <= 0 && !port->break_length)
750 || tty->stopped || tty->hw_stopped) {
751 sx_out(bp, CD186x_CAR, port_No(port));
752 port->IER &= ~IER_TXRDY;
753 sx_out(bp, CD186x_IER, port->IER);
754 func_exit();
755 return;
756 }
d61780c0 757
1da177e4
LT
758 if (port->break_length) {
759 if (port->break_length > 0) {
760 if (port->COR2 & COR2_ETC) {
761 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
762 sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
763 port->COR2 &= ~COR2_ETC;
764 }
765 count = min_t(int, port->break_length, 0xff);
766 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
767 sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
768 sx_out(bp, CD186x_TDR, count);
769 if (!(port->break_length -= count))
770 port->break_length--;
771 } else {
772 sx_out(bp, CD186x_TDR, CD186x_C_ESC);
773 sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
774 sx_out(bp, CD186x_COR2, port->COR2);
775 sx_wait_CCR(bp);
776 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
777 port->break_length = 0;
778 }
779
780 func_exit();
781 return;
782 }
d61780c0 783
1da177e4
LT
784 count = CD186x_NFIFO;
785 do {
786 sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
787 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
788 if (--port->xmit_cnt <= 0)
789 break;
790 } while (--count > 0);
d61780c0 791
1da177e4
LT
792 if (port->xmit_cnt <= 0) {
793 sx_out(bp, CD186x_CAR, port_No(port));
794 port->IER &= ~IER_TXRDY;
795 sx_out(bp, CD186x_IER, port->IER);
796 }
797 if (port->xmit_cnt <= port->wakeup_chars)
d0d4e1c0 798 tty_wakeup(tty);
1da177e4
LT
799
800 func_exit();
801}
802
803
804static inline void sx_check_modem(struct specialix_board * bp)
805{
806 struct specialix_port *port;
807 struct tty_struct *tty;
808 unsigned char mcr;
809 int msvr_cd;
810
811 dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
812 if (!(port = sx_get_port(bp, "Modem")))
813 return;
d61780c0 814
1da177e4 815 tty = port->tty;
d61780c0 816
1da177e4
LT
817 mcr = sx_in(bp, CD186x_MCR);
818 printk ("mcr = %02x.\n", mcr);
819
820 if ((mcr & MCR_CDCHG)) {
821 dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
822 msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
823 if (msvr_cd) {
824 dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
825 wake_up_interruptible(&port->open_wait);
826 } else {
827 dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
d0d4e1c0 828 tty_hangup(tty);
1da177e4
LT
829 }
830 }
d61780c0 831
1da177e4
LT
832#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
833 if (mcr & MCR_CTSCHG) {
834 if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
835 tty->hw_stopped = 0;
836 port->IER |= IER_TXRDY;
837 if (port->xmit_cnt <= port->wakeup_chars)
d0d4e1c0 838 tty_wakeup(tty);
1da177e4
LT
839 } else {
840 tty->hw_stopped = 1;
841 port->IER &= ~IER_TXRDY;
842 }
843 sx_out(bp, CD186x_IER, port->IER);
844 }
845 if (mcr & MCR_DSSXHG) {
846 if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
847 tty->hw_stopped = 0;
848 port->IER |= IER_TXRDY;
849 if (port->xmit_cnt <= port->wakeup_chars)
d0d4e1c0 850 tty_wakeup(tty);
1da177e4
LT
851 } else {
852 tty->hw_stopped = 1;
853 port->IER &= ~IER_TXRDY;
854 }
855 sx_out(bp, CD186x_IER, port->IER);
856 }
857#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
d61780c0 858
1da177e4
LT
859 /* Clear change bits */
860 sx_out(bp, CD186x_MCR, 0);
861}
862
863
864/* The main interrupt processing routine */
7d12e780 865static irqreturn_t sx_interrupt(int irq, void *dev_id)
1da177e4
LT
866{
867 unsigned char status;
868 unsigned char ack;
869 struct specialix_board *bp;
870 unsigned long loop = 0;
871 int saved_reg;
872 unsigned long flags;
873
874 func_enter();
875
876 bp = dev_id;
877 spin_lock_irqsave(&bp->lock, flags);
878
879 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 880 if (!(bp->flags & SX_BOARD_ACTIVE)) {
1da177e4
LT
881 dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
882 spin_unlock_irqrestore(&bp->lock, flags);
883 func_exit();
884 return IRQ_NONE;
885 }
886
887 saved_reg = bp->reg;
888
889 while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
890 (SRSR_RREQint |
891 SRSR_TREQint |
d61780c0 892 SRSR_MREQint)))) {
1da177e4
LT
893 if (status & SRSR_RREQint) {
894 ack = sx_in(bp, CD186x_RRAR);
895
896 if (ack == (SX_ID | GIVR_IT_RCV))
897 sx_receive(bp);
898 else if (ack == (SX_ID | GIVR_IT_REXC))
899 sx_receive_exc(bp);
900 else
901 printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
902 board_No(bp), status, ack);
d61780c0 903
1da177e4
LT
904 } else if (status & SRSR_TREQint) {
905 ack = sx_in(bp, CD186x_TRAR);
906
907 if (ack == (SX_ID | GIVR_IT_TX))
908 sx_transmit(bp);
909 else
910 printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
911 board_No(bp), status, ack, port_No (sx_get_port (bp, "Int")));
912 } else if (status & SRSR_MREQint) {
913 ack = sx_in(bp, CD186x_MRAR);
914
d61780c0 915 if (ack == (SX_ID | GIVR_IT_MODEM))
1da177e4
LT
916 sx_check_modem(bp);
917 else
918 printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
919 board_No(bp), status, ack);
d61780c0
JG
920
921 }
1da177e4
LT
922
923 sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */
924 }
925 bp->reg = saved_reg;
926 outb (bp->reg, bp->base + SX_ADDR_REG);
927 spin_unlock_irqrestore(&bp->lock, flags);
928 func_exit();
929 return IRQ_HANDLED;
930}
931
932
933/*
934 * Routines for open & close processing.
935 */
936
937static void turn_ints_off (struct specialix_board *bp)
938{
939 unsigned long flags;
940
941 func_enter();
942 if (bp->flags & SX_BOARD_IS_PCI) {
943 /* This was intended for enabeling the interrupt on the
944 * PCI card. However it seems that it's already enabled
945 * and as PCI interrupts can be shared, there is no real
946 * reason to have to turn it off. */
947 }
948
949 spin_lock_irqsave(&bp->lock, flags);
950 (void) sx_in_off (bp, 0); /* Turn off interrupts. */
951 spin_unlock_irqrestore(&bp->lock, flags);
952
953 func_exit();
954}
955
956static void turn_ints_on (struct specialix_board *bp)
957{
958 unsigned long flags;
959
960 func_enter();
961
962 if (bp->flags & SX_BOARD_IS_PCI) {
963 /* play with the PCI chip. See comment above. */
964 }
965 spin_lock_irqsave(&bp->lock, flags);
966 (void) sx_in (bp, 0); /* Turn ON interrupts. */
967 spin_unlock_irqrestore(&bp->lock, flags);
968
969 func_exit();
970}
971
972
973/* Called with disabled interrupts */
974static inline int sx_setup_board(struct specialix_board * bp)
975{
976 int error;
977
d61780c0 978 if (bp->flags & SX_BOARD_ACTIVE)
1da177e4
LT
979 return 0;
980
981 if (bp->flags & SX_BOARD_IS_PCI)
0f2ed4c6 982 error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
1da177e4 983 else
0f2ed4c6 984 error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp);
1da177e4 985
d61780c0 986 if (error)
1da177e4
LT
987 return error;
988
989 turn_ints_on (bp);
990 bp->flags |= SX_BOARD_ACTIVE;
991
992 return 0;
993}
994
995
996/* Called with disabled interrupts */
997static inline void sx_shutdown_board(struct specialix_board *bp)
998{
999 func_enter();
1000
1001 if (!(bp->flags & SX_BOARD_ACTIVE)) {
1002 func_exit();
1003 return;
1004 }
1005
1006 bp->flags &= ~SX_BOARD_ACTIVE;
d61780c0 1007
1da177e4
LT
1008 dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
1009 bp->irq, board_No (bp));
1010 free_irq(bp->irq, bp);
1011
1012 turn_ints_off (bp);
1013
1014
1015 func_exit();
1016}
1017
1018
1019/*
d61780c0 1020 * Setting up port characteristics.
1da177e4
LT
1021 * Must be called with disabled interrupts
1022 */
1023static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
1024{
1025 struct tty_struct *tty;
1026 unsigned long baud;
1027 long tmp;
1028 unsigned char cor1 = 0, cor3 = 0;
1029 unsigned char mcor1 = 0, mcor2 = 0;
1030 static unsigned long again;
1031 unsigned long flags;
1032
1033 func_enter();
1034
1035 if (!(tty = port->tty) || !tty->termios) {
1036 func_exit();
1037 return;
1038 }
1039
1040 port->IER = 0;
1041 port->COR2 = 0;
1042 /* Select port on the board */
1043 spin_lock_irqsave(&bp->lock, flags);
1044 sx_out(bp, CD186x_CAR, port_No(port));
1045
1046 /* The Specialix board doens't implement the RTS lines.
1047 They are used to set the IRQ level. Don't touch them. */
1048 if (SX_CRTSCTS(tty))
1049 port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1050 else
1051 port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
1052 spin_unlock_irqrestore(&bp->lock, flags);
1053 dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
67cc0161 1054 baud = tty_get_baud_rate(tty);
d61780c0 1055
67cc0161 1056 if (baud == 38400) {
1da177e4 1057 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
a4bb2cf1 1058 baud = 57600;
1da177e4 1059 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
a4bb2cf1 1060 baud = 115200;
1da177e4 1061 }
d61780c0 1062
67cc0161 1063 if (!baud) {
1da177e4
LT
1064 /* Drop DTR & exit */
1065 dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
1066 if (!SX_CRTSCTS (tty)) {
1067 port -> MSVR &= ~ MSVR_DTR;
1068 spin_lock_irqsave(&bp->lock, flags);
1069 sx_out(bp, CD186x_MSVR, port->MSVR );
1070 spin_unlock_irqrestore(&bp->lock, flags);
d61780c0 1071 }
1da177e4
LT
1072 else
1073 dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
1074 return;
1075 } else {
1076 /* Set DTR on */
1077 if (!SX_CRTSCTS (tty)) {
1078 port ->MSVR |= MSVR_DTR;
1079 }
1080 }
d61780c0 1081
1da177e4 1082 /*
d61780c0 1083 * Now we must calculate some speed depended things
1da177e4
LT
1084 */
1085
1086 /* Set baud rate for port */
1087 tmp = port->custom_divisor ;
1088 if ( tmp )
1089 printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"
1090 "This is an untested option, please be carefull.\n",
1091 port_No (port), tmp);
1092 else
67cc0161 1093 tmp = (((SX_OSCFREQ + baud/2) / baud +
1da177e4
LT
1094 CD186x_TPC/2) / CD186x_TPC);
1095
d61780c0 1096 if ((tmp < 0x10) && time_before(again, jiffies)) {
1da177e4
LT
1097 again = jiffies + HZ * 60;
1098 /* Page 48 of version 2.0 of the CL-CD1865 databook */
1099 if (tmp >= 12) {
1100 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1101 "Performance degradation is possible.\n"
1102 "Read specialix.txt for more info.\n",
1103 port_No (port), tmp);
1104 } else {
1105 printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
1106 "Warning: overstressing Cirrus chip. "
1107 "This might not work.\n"
d61780c0 1108 "Read specialix.txt for more info.\n",
1da177e4
LT
1109 port_No (port), tmp);
1110 }
1111 }
1112 spin_lock_irqsave(&bp->lock, flags);
d61780c0
JG
1113 sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
1114 sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
1115 sx_out(bp, CD186x_RBPRL, tmp & 0xff);
1da177e4
LT
1116 sx_out(bp, CD186x_TBPRL, tmp & 0xff);
1117 spin_unlock_irqrestore(&bp->lock, flags);
a4bb2cf1 1118 if (port->custom_divisor)
1da177e4 1119 baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
a4bb2cf1 1120 baud = (baud + 5) / 10; /* Estimated CPS */
1da177e4
LT
1121
1122 /* Two timer ticks seems enough to wakeup something like SLIP driver */
d61780c0 1123 tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
1da177e4
LT
1124 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
1125 SERIAL_XMIT_SIZE - 1 : tmp);
d61780c0 1126
1da177e4
LT
1127 /* Receiver timeout will be transmission time for 1.5 chars */
1128 tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
1129 tmp = (tmp > 0xff) ? 0xff : tmp;
1130 spin_lock_irqsave(&bp->lock, flags);
1131 sx_out(bp, CD186x_RTPR, tmp);
1132 spin_unlock_irqrestore(&bp->lock, flags);
1133 switch (C_CSIZE(tty)) {
1134 case CS5:
1135 cor1 |= COR1_5BITS;
1136 break;
1137 case CS6:
1138 cor1 |= COR1_6BITS;
1139 break;
1140 case CS7:
1141 cor1 |= COR1_7BITS;
1142 break;
1143 case CS8:
1144 cor1 |= COR1_8BITS;
1145 break;
1146 }
d61780c0
JG
1147
1148 if (C_CSTOPB(tty))
1da177e4 1149 cor1 |= COR1_2SB;
d61780c0 1150
1da177e4
LT
1151 cor1 |= COR1_IGNORE;
1152 if (C_PARENB(tty)) {
1153 cor1 |= COR1_NORMPAR;
d61780c0 1154 if (C_PARODD(tty))
1da177e4 1155 cor1 |= COR1_ODDP;
d61780c0 1156 if (I_INPCK(tty))
1da177e4
LT
1157 cor1 &= ~COR1_IGNORE;
1158 }
1159 /* Set marking of some errors */
1160 port->mark_mask = RCSR_OE | RCSR_TOUT;
d61780c0 1161 if (I_INPCK(tty))
1da177e4 1162 port->mark_mask |= RCSR_FE | RCSR_PE;
d61780c0 1163 if (I_BRKINT(tty) || I_PARMRK(tty))
1da177e4 1164 port->mark_mask |= RCSR_BREAK;
d61780c0 1165 if (I_IGNPAR(tty))
1da177e4
LT
1166 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
1167 if (I_IGNBRK(tty)) {
1168 port->mark_mask &= ~RCSR_BREAK;
d61780c0 1169 if (I_IGNPAR(tty))
1da177e4
LT
1170 /* Real raw mode. Ignore all */
1171 port->mark_mask &= ~RCSR_OE;
1172 }
1173 /* Enable Hardware Flow Control */
1174 if (C_CRTSCTS(tty)) {
1175#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
1176 port->IER |= IER_DSR | IER_CTS;
1177 mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
1178 mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
1179 spin_lock_irqsave(&bp->lock, flags);
1180 tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
1181 spin_unlock_irqrestore(&bp->lock, flags);
1182#else
d61780c0 1183 port->COR2 |= COR2_CTSAE;
1da177e4
LT
1184#endif
1185 }
1186 /* Enable Software Flow Control. FIXME: I'm not sure about this */
1187 /* Some people reported that it works, but I still doubt it */
1188 if (I_IXON(tty)) {
1189 port->COR2 |= COR2_TXIBE;
1190 cor3 |= (COR3_FCT | COR3_SCDE);
1191 if (I_IXANY(tty))
1192 port->COR2 |= COR2_IXM;
1193 spin_lock_irqsave(&bp->lock, flags);
1194 sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
1195 sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
1196 sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
1197 sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
1198 spin_unlock_irqrestore(&bp->lock, flags);
1199 }
1200 if (!C_CLOCAL(tty)) {
1201 /* Enable CD check */
1202 port->IER |= IER_CD;
1203 mcor1 |= MCOR1_CDZD;
1204 mcor2 |= MCOR2_CDOD;
1205 }
d61780c0
JG
1206
1207 if (C_CREAD(tty))
1da177e4
LT
1208 /* Enable receiver */
1209 port->IER |= IER_RXD;
d61780c0 1210
1da177e4
LT
1211 /* Set input FIFO size (1-8 bytes) */
1212 cor3 |= sx_rxfifo;
1213 /* Setting up CD186x channel registers */
1214 spin_lock_irqsave(&bp->lock, flags);
1215 sx_out(bp, CD186x_COR1, cor1);
1216 sx_out(bp, CD186x_COR2, port->COR2);
1217 sx_out(bp, CD186x_COR3, cor3);
1218 spin_unlock_irqrestore(&bp->lock, flags);
1219 /* Make CD186x know about registers change */
1220 sx_wait_CCR(bp);
1221 spin_lock_irqsave(&bp->lock, flags);
1222 sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
1223 /* Setting up modem option registers */
1224 dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
1225 sx_out(bp, CD186x_MCOR1, mcor1);
1226 sx_out(bp, CD186x_MCOR2, mcor2);
1227 spin_unlock_irqrestore(&bp->lock, flags);
1228 /* Enable CD186x transmitter & receiver */
1229 sx_wait_CCR(bp);
1230 spin_lock_irqsave(&bp->lock, flags);
1231 sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
1232 /* Enable interrupts */
1233 sx_out(bp, CD186x_IER, port->IER);
1234 /* And finally set the modem lines... */
1235 sx_out(bp, CD186x_MSVR, port->MSVR);
1236 spin_unlock_irqrestore(&bp->lock, flags);
1237
1238 func_exit();
1239}
1240
1241
1242/* Must be called with interrupts enabled */
1243static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
1244{
1245 unsigned long flags;
1246
1247 func_enter();
1248
1249 if (port->flags & ASYNC_INITIALIZED) {
1250 func_exit();
1251 return 0;
1252 }
d61780c0 1253
1da177e4
LT
1254 if (!port->xmit_buf) {
1255 /* We may sleep in get_zeroed_page() */
1256 unsigned long tmp;
d61780c0 1257
1da177e4
LT
1258 if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
1259 func_exit();
1260 return -ENOMEM;
1261 }
1262
1263 if (port->xmit_buf) {
1264 free_page(tmp);
1265 func_exit();
1266 return -ERESTARTSYS;
1267 }
1268 port->xmit_buf = (unsigned char *) tmp;
1269 }
d61780c0 1270
1da177e4
LT
1271 spin_lock_irqsave(&port->lock, flags);
1272
d61780c0 1273 if (port->tty)
1da177e4
LT
1274 clear_bit(TTY_IO_ERROR, &port->tty->flags);
1275
1276 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1277 sx_change_speed(bp, port);
1278 port->flags |= ASYNC_INITIALIZED;
1279
1280 spin_unlock_irqrestore(&port->lock, flags);
1281
d61780c0 1282
1da177e4
LT
1283 func_exit();
1284 return 0;
1285}
1286
1287
1288/* Must be called with interrupts disabled */
1289static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
1290{
1291 struct tty_struct *tty;
1292 int i;
1293 unsigned long flags;
d61780c0 1294
1da177e4
LT
1295 func_enter();
1296
1297 if (!(port->flags & ASYNC_INITIALIZED)) {
1298 func_exit();
1299 return;
1300 }
d61780c0 1301
1da177e4
LT
1302 if (sx_debug & SX_DEBUG_FIFO) {
1303 dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
1304 board_No(bp), port_No(port), port->overrun);
1305 for (i = 0; i < 10; i++) {
1306 dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
1307 }
1308 dprintk(SX_DEBUG_FIFO, "].\n");
1309 }
1310
1311 if (port->xmit_buf) {
1312 free_page((unsigned long) port->xmit_buf);
1313 port->xmit_buf = NULL;
1314 }
1315
1316 /* Select port */
1317 spin_lock_irqsave(&bp->lock, flags);
1318 sx_out(bp, CD186x_CAR, port_No(port));
1319
1320 if (!(tty = port->tty) || C_HUPCL(tty)) {
1321 /* Drop DTR */
1322 sx_out(bp, CD186x_MSVDTR, 0);
1323 }
1324 spin_unlock_irqrestore(&bp->lock, flags);
1325 /* Reset port */
1326 sx_wait_CCR(bp);
1327 spin_lock_irqsave(&bp->lock, flags);
1328 sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
1329 /* Disable all interrupts from this port */
1330 port->IER = 0;
1331 sx_out(bp, CD186x_IER, port->IER);
1332 spin_unlock_irqrestore(&bp->lock, flags);
1333 if (tty)
1334 set_bit(TTY_IO_ERROR, &tty->flags);
1335 port->flags &= ~ASYNC_INITIALIZED;
d61780c0
JG
1336
1337 if (!bp->count)
1da177e4
LT
1338 sx_shutdown_board(bp);
1339 func_exit();
1340}
1341
d61780c0 1342
1da177e4
LT
1343static int block_til_ready(struct tty_struct *tty, struct file * filp,
1344 struct specialix_port *port)
1345{
1346 DECLARE_WAITQUEUE(wait, current);
1347 struct specialix_board *bp = port_Board(port);
1348 int retval;
1349 int do_clocal = 0;
1350 int CD;
1351 unsigned long flags;
1352
1353 func_enter();
1354
1355 /*
1356 * If the device is in the middle of being closed, then block
1357 * until it's done, and then try again.
1358 */
1359 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
1360 interruptible_sleep_on(&port->close_wait);
1361 if (port->flags & ASYNC_HUP_NOTIFY) {
1362 func_exit();
1363 return -EAGAIN;
1364 } else {
1365 func_exit();
1366 return -ERESTARTSYS;
1367 }
1368 }
d61780c0 1369
1da177e4
LT
1370 /*
1371 * If non-blocking mode is set, or the port is not enabled,
1372 * then make the check up front and then exit.
1373 */
1374 if ((filp->f_flags & O_NONBLOCK) ||
1375 (tty->flags & (1 << TTY_IO_ERROR))) {
1376 port->flags |= ASYNC_NORMAL_ACTIVE;
1377 func_exit();
1378 return 0;
1379 }
1380
1381 if (C_CLOCAL(tty))
1382 do_clocal = 1;
1383
1384 /*
1385 * Block waiting for the carrier detect and the line to become
1386 * free (i.e., not in use by the callout). While we are in
1387 * this loop, info->count is dropped by one, so that
1388 * rs_close() knows when to free things. We restore it upon
1389 * exit, either normal or abnormal.
1390 */
1391 retval = 0;
1392 add_wait_queue(&port->open_wait, &wait);
1393 spin_lock_irqsave(&port->lock, flags);
1394 if (!tty_hung_up_p(filp)) {
1395 port->count--;
1396 }
1397 spin_unlock_irqrestore(&port->lock, flags);
1398 port->blocked_open++;
1399 while (1) {
1400 spin_lock_irqsave(&bp->lock, flags);
1401 sx_out(bp, CD186x_CAR, port_No(port));
1402 CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
1403 if (SX_CRTSCTS (tty)) {
1404 /* Activate RTS */
1405 port->MSVR |= MSVR_DTR; /* WTF? */
1406 sx_out (bp, CD186x_MSVR, port->MSVR);
1407 } else {
1408 /* Activate DTR */
1409 port->MSVR |= MSVR_DTR;
1410 sx_out (bp, CD186x_MSVR, port->MSVR);
1411 }
1412 spin_unlock_irqrestore(&bp->lock, flags);
1413 set_current_state(TASK_INTERRUPTIBLE);
1414 if (tty_hung_up_p(filp) ||
1415 !(port->flags & ASYNC_INITIALIZED)) {
1416 if (port->flags & ASYNC_HUP_NOTIFY)
1417 retval = -EAGAIN;
1418 else
d61780c0 1419 retval = -ERESTARTSYS;
1da177e4
LT
1420 break;
1421 }
1422 if (!(port->flags & ASYNC_CLOSING) &&
1423 (do_clocal || CD))
1424 break;
1425 if (signal_pending(current)) {
1426 retval = -ERESTARTSYS;
1427 break;
1428 }
1429 schedule();
1430 }
1431
1432 set_current_state(TASK_RUNNING);
1433 remove_wait_queue(&port->open_wait, &wait);
1434 spin_lock_irqsave(&port->lock, flags);
1435 if (!tty_hung_up_p(filp)) {
1436 port->count++;
1437 }
1438 port->blocked_open--;
1439 spin_unlock_irqrestore(&port->lock, flags);
1440 if (retval) {
1441 func_exit();
1442 return retval;
1443 }
1444
1445 port->flags |= ASYNC_NORMAL_ACTIVE;
1446 func_exit();
1447 return 0;
d61780c0 1448}
1da177e4
LT
1449
1450
1451static int sx_open(struct tty_struct * tty, struct file * filp)
1452{
1453 int board;
1454 int error;
1455 struct specialix_port * port;
1456 struct specialix_board * bp;
1457 int i;
1458 unsigned long flags;
1459
1460 func_enter();
1461
1462 board = SX_BOARD(tty->index);
1463
1464 if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
1465 func_exit();
1466 return -ENODEV;
1467 }
d61780c0 1468
1da177e4
LT
1469 bp = &sx_board[board];
1470 port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
1471 port->overrun = 0;
1472 for (i = 0; i < 10; i++)
1473 port->hits[i]=0;
1474
1475 dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
1476 board, bp, port, SX_PORT(tty->index));
1477
1478 if (sx_paranoia_check(port, tty->name, "sx_open")) {
1479 func_enter();
1480 return -ENODEV;
1481 }
1482
1483 if ((error = sx_setup_board(bp))) {
1484 func_exit();
1485 return error;
1486 }
1487
1488 spin_lock_irqsave(&bp->lock, flags);
1489 port->count++;
1490 bp->count++;
1491 tty->driver_data = port;
1492 port->tty = tty;
1493 spin_unlock_irqrestore(&bp->lock, flags);
1494
1495 if ((error = sx_setup_port(bp, port))) {
1496 func_enter();
1497 return error;
1498 }
d61780c0 1499
1da177e4
LT
1500 if ((error = block_til_ready(tty, filp, port))) {
1501 func_enter();
1502 return error;
1503 }
1504
1505 func_exit();
1506 return 0;
1507}
1508
1509
1510static void sx_close(struct tty_struct * tty, struct file * filp)
1511{
1512 struct specialix_port *port = (struct specialix_port *) tty->driver_data;
1513 struct specialix_board *bp;
1514 unsigned long flags;
1515 unsigned long timeout;
d61780c0 1516
1da177e4
LT
1517 func_enter();
1518 if (!port || sx_paranoia_check(port, tty->name, "close")) {
1519 func_exit();
1520 return;
1521 }
1522 spin_lock_irqsave(&port->lock, flags);
1523
1524 if (tty_hung_up_p(filp)) {
1525 spin_unlock_irqrestore(&port->lock, flags);
1526 func_exit();
1527 return;
1528 }
d61780c0 1529
1da177e4
LT
1530 bp = port_Board(port);
1531 if ((tty->count == 1) && (port->count != 1)) {
1532 printk(KERN_ERR "sx%d: sx_close: bad port count;"
1533 " tty->count is 1, port count is %d\n",
1534 board_No(bp), port->count);
1535 port->count = 1;
1536 }
1537
1538 if (port->count > 1) {
1539 port->count--;
1540 bp->count--;
1541
1542 spin_unlock_irqrestore(&port->lock, flags);
1543
1544 func_exit();
1545 return;
1546 }
1547 port->flags |= ASYNC_CLOSING;
1548 /*
d61780c0 1549 * Now we wait for the transmit buffer to clear; and we notify
1da177e4
LT
1550 * the line discipline to only process XON/XOFF characters.
1551 */
1552 tty->closing = 1;
1553 spin_unlock_irqrestore(&port->lock, flags);
1554 dprintk (SX_DEBUG_OPEN, "Closing\n");
1555 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
1556 tty_wait_until_sent(tty, port->closing_wait);
1557 }
1558 /*
1559 * At this point we stop accepting input. To do this, we
1560 * disable the receive line status interrupts, and tell the
1561 * interrupt driver to stop checking the data ready bit in the
1562 * line status register.
1563 */
1564 dprintk (SX_DEBUG_OPEN, "Closed\n");
1565 port->IER &= ~IER_RXD;
1566 if (port->flags & ASYNC_INITIALIZED) {
1567 port->IER &= ~IER_TXRDY;
1568 port->IER |= IER_TXEMPTY;
1569 spin_lock_irqsave(&bp->lock, flags);
1570 sx_out(bp, CD186x_CAR, port_No(port));
1571 sx_out(bp, CD186x_IER, port->IER);
1572 spin_unlock_irqrestore(&bp->lock, flags);
1573 /*
1574 * Before we drop DTR, make sure the UART transmitter
1575 * has completely drained; this is especially
1576 * important if there is a transmit FIFO!
1577 */
1578 timeout = jiffies+HZ;
1579 while(port->IER & IER_TXEMPTY) {
1580 set_current_state (TASK_INTERRUPTIBLE);
1581 msleep_interruptible(jiffies_to_msecs(port->timeout));
1582 if (time_after(jiffies, timeout)) {
1583 printk (KERN_INFO "Timeout waiting for close\n");
1584 break;
1585 }
1586 }
1587
1588 }
1589
1590 if (--bp->count < 0) {
1591 printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
1592 board_No(bp), bp->count, tty->index);
1593 bp->count = 0;
1594 }
1595 if (--port->count < 0) {
1596 printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
1597 board_No(bp), port_No(port), port->count);
1598 port->count = 0;
1599 }
1600
1601 sx_shutdown_port(bp, port);
1602 if (tty->driver->flush_buffer)
1603 tty->driver->flush_buffer(tty);
1604 tty_ldisc_flush(tty);
1605 spin_lock_irqsave(&port->lock, flags);
1606 tty->closing = 0;
1da177e4
LT
1607 port->tty = NULL;
1608 spin_unlock_irqrestore(&port->lock, flags);
1609 if (port->blocked_open) {
1610 if (port->close_delay) {
1611 msleep_interruptible(jiffies_to_msecs(port->close_delay));
1612 }
1613 wake_up_interruptible(&port->open_wait);
1614 }
1615 port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1616 wake_up_interruptible(&port->close_wait);
1617
1618 func_exit();
1619}
1620
1621
d61780c0 1622static int sx_write(struct tty_struct * tty,
1da177e4
LT
1623 const unsigned char *buf, int count)
1624{
1625 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1626 struct specialix_board *bp;
1627 int c, total = 0;
1628 unsigned long flags;
1629
1630 func_enter();
1631 if (sx_paranoia_check(port, tty->name, "sx_write")) {
1632 func_exit();
1633 return 0;
1634 }
d61780c0 1635
1da177e4
LT
1636 bp = port_Board(port);
1637
365e0223 1638 if (!port->xmit_buf) {
1da177e4
LT
1639 func_exit();
1640 return 0;
1641 }
1642
1643 while (1) {
1644 spin_lock_irqsave(&port->lock, flags);
1645 c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1646 SERIAL_XMIT_SIZE - port->xmit_head));
1647 if (c <= 0) {
1648 spin_unlock_irqrestore(&port->lock, flags);
1649 break;
1650 }
1651 memcpy(port->xmit_buf + port->xmit_head, buf, c);
1652 port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1653 port->xmit_cnt += c;
1654 spin_unlock_irqrestore(&port->lock, flags);
1655
1656 buf += c;
1657 count -= c;
1658 total += c;
1659 }
1660
1661 spin_lock_irqsave(&bp->lock, flags);
1662 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1663 !(port->IER & IER_TXRDY)) {
1664 port->IER |= IER_TXRDY;
1665 sx_out(bp, CD186x_CAR, port_No(port));
1666 sx_out(bp, CD186x_IER, port->IER);
1667 }
1668 spin_unlock_irqrestore(&bp->lock, flags);
1669 func_exit();
1670
1671 return total;
1672}
1673
1674
1675static void sx_put_char(struct tty_struct * tty, unsigned char ch)
1676{
1677 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1678 unsigned long flags;
1679 struct specialix_board * bp;
1680
1681 func_enter();
1682
1683 if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
1684 func_exit();
1685 return;
1686 }
1687 dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
326f28e9 1688 if (!port->xmit_buf) {
1da177e4
LT
1689 func_exit();
1690 return;
1691 }
1692 bp = port_Board(port);
1693 spin_lock_irqsave(&port->lock, flags);
1694
1695 dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf);
1696 if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) {
1697 spin_unlock_irqrestore(&port->lock, flags);
1698 dprintk (SX_DEBUG_TX, "Exit size\n");
1699 func_exit();
1700 return;
1701 }
1702 dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
1703 port->xmit_buf[port->xmit_head++] = ch;
1704 port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1705 port->xmit_cnt++;
1706 spin_unlock_irqrestore(&port->lock, flags);
1707
1708 func_exit();
1709}
1710
1711
1712static void sx_flush_chars(struct tty_struct * tty)
1713{
1714 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1715 unsigned long flags;
1716 struct specialix_board * bp = port_Board(port);
1717
1718 func_enter();
1719
1720 if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
1721 func_exit();
1722 return;
1723 }
1724 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1725 !port->xmit_buf) {
1726 func_exit();
1727 return;
1728 }
1729 spin_lock_irqsave(&bp->lock, flags);
1730 port->IER |= IER_TXRDY;
1731 sx_out(port_Board(port), CD186x_CAR, port_No(port));
1732 sx_out(port_Board(port), CD186x_IER, port->IER);
1733 spin_unlock_irqrestore(&bp->lock, flags);
1734
1735 func_exit();
1736}
1737
1738
1739static int sx_write_room(struct tty_struct * tty)
1740{
1741 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1742 int ret;
1743
1744 func_enter();
1745
1746 if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
1747 func_exit();
1748 return 0;
1749 }
1750
1751 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1752 if (ret < 0)
1753 ret = 0;
1754
1755 func_exit();
1756 return ret;
1757}
1758
1759
1760static int sx_chars_in_buffer(struct tty_struct *tty)
1761{
1762 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1763
1764 func_enter();
d61780c0 1765
1da177e4
LT
1766 if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
1767 func_exit();
1768 return 0;
1769 }
1770 func_exit();
1771 return port->xmit_cnt;
1772}
1773
1774
1775static void sx_flush_buffer(struct tty_struct *tty)
1776{
1777 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1778 unsigned long flags;
1779 struct specialix_board * bp;
1780
1781 func_enter();
1782
1783 if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
1784 func_exit();
1785 return;
1786 }
1787
1788 bp = port_Board(port);
1789 spin_lock_irqsave(&port->lock, flags);
1790 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1791 spin_unlock_irqrestore(&port->lock, flags);
1792 tty_wakeup(tty);
1793
1794 func_exit();
1795}
1796
1797
1798static int sx_tiocmget(struct tty_struct *tty, struct file *file)
1799{
1800 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1801 struct specialix_board * bp;
1802 unsigned char status;
1803 unsigned int result;
1804 unsigned long flags;
1805
1806 func_enter();
1807
1808 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1809 func_exit();
1810 return -ENODEV;
1811 }
1812
1813 bp = port_Board(port);
1814 spin_lock_irqsave (&bp->lock, flags);
1815 sx_out(bp, CD186x_CAR, port_No(port));
1816 status = sx_in(bp, CD186x_MSVR);
1817 spin_unlock_irqrestore(&bp->lock, flags);
1818 dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
1819 port_No(port), status, sx_in (bp, CD186x_CAR));
1820 dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
1821 if (SX_CRTSCTS(port->tty)) {
d61780c0 1822 result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
1da177e4
LT
1823 | ((status & MSVR_DTR) ? TIOCM_RTS : 0)
1824 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1825 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1826 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1827 } else {
d61780c0 1828 result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
1da177e4
LT
1829 | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1830 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1831 |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
1832 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1833 }
1834
1835 func_exit();
1836
1837 return result;
1838}
1839
1840
1841static int sx_tiocmset(struct tty_struct *tty, struct file *file,
1842 unsigned int set, unsigned int clear)
1843{
1844 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
1845 unsigned long flags;
1846 struct specialix_board *bp;
1847
1848 func_enter();
1849
1850 if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
1851 func_exit();
1852 return -ENODEV;
1853 }
1854
1855 bp = port_Board(port);
1856
1857 spin_lock_irqsave(&port->lock, flags);
1858 /* if (set & TIOCM_RTS)
1859 port->MSVR |= MSVR_RTS; */
1860 /* if (set & TIOCM_DTR)
1861 port->MSVR |= MSVR_DTR; */
1862
1863 if (SX_CRTSCTS(port->tty)) {
1864 if (set & TIOCM_RTS)
1865 port->MSVR |= MSVR_DTR;
1866 } else {
1867 if (set & TIOCM_DTR)
1868 port->MSVR |= MSVR_DTR;
1869 }
1870
1871 /* if (clear & TIOCM_RTS)
1872 port->MSVR &= ~MSVR_RTS; */
1873 /* if (clear & TIOCM_DTR)
1874 port->MSVR &= ~MSVR_DTR; */
1875 if (SX_CRTSCTS(port->tty)) {
1876 if (clear & TIOCM_RTS)
1877 port->MSVR &= ~MSVR_DTR;
1878 } else {
1879 if (clear & TIOCM_DTR)
1880 port->MSVR &= ~MSVR_DTR;
1881 }
1882 spin_lock_irqsave(&bp->lock, flags);
1883 sx_out(bp, CD186x_CAR, port_No(port));
1884 sx_out(bp, CD186x_MSVR, port->MSVR);
1885 spin_unlock_irqrestore(&bp->lock, flags);
1886 spin_unlock_irqrestore(&port->lock, flags);
1887 func_exit();
1888 return 0;
1889}
1890
1891
1892static inline void sx_send_break(struct specialix_port * port, unsigned long length)
1893{
1894 struct specialix_board *bp = port_Board(port);
1895 unsigned long flags;
d61780c0 1896
1da177e4
LT
1897 func_enter();
1898
1899 spin_lock_irqsave (&port->lock, flags);
1900 port->break_length = SPECIALIX_TPS / HZ * length;
1901 port->COR2 |= COR2_ETC;
1902 port->IER |= IER_TXRDY;
1903 spin_lock_irqsave(&bp->lock, flags);
1904 sx_out(bp, CD186x_CAR, port_No(port));
1905 sx_out(bp, CD186x_COR2, port->COR2);
1906 sx_out(bp, CD186x_IER, port->IER);
1907 spin_unlock_irqrestore(&bp->lock, flags);
1908 spin_unlock_irqrestore (&port->lock, flags);
1909 sx_wait_CCR(bp);
1910 spin_lock_irqsave(&bp->lock, flags);
1911 sx_out(bp, CD186x_CCR, CCR_CORCHG2);
1912 spin_unlock_irqrestore(&bp->lock, flags);
1913 sx_wait_CCR(bp);
1914
1915 func_exit();
1916}
1917
1918
1919static inline int sx_set_serial_info(struct specialix_port * port,
1920 struct serial_struct __user * newinfo)
1921{
1922 struct serial_struct tmp;
1923 struct specialix_board *bp = port_Board(port);
1924 int change_speed;
1925
1926 func_enter();
1927 /*
e49332bd 1928 if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) {
1da177e4 1929 func_exit();
e49332bd 1930 return -EFAULT;
1da177e4
LT
1931 }
1932 */
1933 if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
1934 func_enter();
1935 return -EFAULT;
1936 }
d61780c0
JG
1937
1938#if 0
1da177e4
LT
1939 if ((tmp.irq != bp->irq) ||
1940 (tmp.port != bp->base) ||
1941 (tmp.type != PORT_CIRRUS) ||
1942 (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
1943 (tmp.custom_divisor != 0) ||
1944 (tmp.xmit_fifo_size != CD186x_NFIFO) ||
1945 (tmp.flags & ~SPECIALIX_LEGAL_FLAGS)) {
1946 func_exit();
1947 return -EINVAL;
1948 }
d61780c0 1949#endif
1da177e4
LT
1950
1951 change_speed = ((port->flags & ASYNC_SPD_MASK) !=
1952 (tmp.flags & ASYNC_SPD_MASK));
1953 change_speed |= (tmp.custom_divisor != port->custom_divisor);
d61780c0 1954
1da177e4
LT
1955 if (!capable(CAP_SYS_ADMIN)) {
1956 if ((tmp.close_delay != port->close_delay) ||
1957 (tmp.closing_wait != port->closing_wait) ||
1958 ((tmp.flags & ~ASYNC_USR_MASK) !=
1959 (port->flags & ~ASYNC_USR_MASK))) {
1960 func_exit();
1961 return -EPERM;
1962 }
1963 port->flags = ((port->flags & ~ASYNC_USR_MASK) |
1964 (tmp.flags & ASYNC_USR_MASK));
1965 port->custom_divisor = tmp.custom_divisor;
1966 } else {
1967 port->flags = ((port->flags & ~ASYNC_FLAGS) |
1968 (tmp.flags & ASYNC_FLAGS));
1969 port->close_delay = tmp.close_delay;
1970 port->closing_wait = tmp.closing_wait;
1971 port->custom_divisor = tmp.custom_divisor;
1972 }
1973 if (change_speed) {
1974 sx_change_speed(bp, port);
1975 }
1976 func_exit();
1977 return 0;
1978}
1979
1980
1981static inline int sx_get_serial_info(struct specialix_port * port,
1982 struct serial_struct __user *retinfo)
1983{
1984 struct serial_struct tmp;
1985 struct specialix_board *bp = port_Board(port);
d61780c0 1986
1da177e4
LT
1987 func_enter();
1988
1989 /*
e49332bd
JJ
1990 if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
1991 return -EFAULT;
1da177e4
LT
1992 */
1993
1994 memset(&tmp, 0, sizeof(tmp));
1995 tmp.type = PORT_CIRRUS;
1996 tmp.line = port - sx_port;
1997 tmp.port = bp->base;
1998 tmp.irq = bp->irq;
1999 tmp.flags = port->flags;
2000 tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
2001 tmp.close_delay = port->close_delay * HZ/100;
2002 tmp.closing_wait = port->closing_wait * HZ/100;
2003 tmp.custom_divisor = port->custom_divisor;
2004 tmp.xmit_fifo_size = CD186x_NFIFO;
2005 if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
2006 func_exit();
2007 return -EFAULT;
2008 }
2009
2010 func_exit();
2011 return 0;
2012}
2013
2014
d61780c0 2015static int sx_ioctl(struct tty_struct * tty, struct file * filp,
1da177e4
LT
2016 unsigned int cmd, unsigned long arg)
2017{
2018 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2019 int retval;
2020 void __user *argp = (void __user *)arg;
2021
2022 func_enter();
2023
2024 if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
2025 func_exit();
2026 return -ENODEV;
2027 }
d61780c0 2028
1da177e4
LT
2029 switch (cmd) {
2030 case TCSBRK: /* SVID version: non-zero arg --> no break */
2031 retval = tty_check_change(tty);
2032 if (retval) {
2033 func_exit();
2034 return retval;
2035 }
2036 tty_wait_until_sent(tty, 0);
2037 if (!arg)
2038 sx_send_break(port, HZ/4); /* 1/4 second */
2039 return 0;
2040 case TCSBRKP: /* support for POSIX tcsendbreak() */
2041 retval = tty_check_change(tty);
2042 if (retval) {
2043 func_exit();
2044 return retval;
2045 }
2046 tty_wait_until_sent(tty, 0);
2047 sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
2048 func_exit();
2049 return 0;
2050 case TIOCGSOFTCAR:
2051 if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) {
2052 func_exit();
2053 return -EFAULT;
2054 }
2055 func_exit();
2056 return 0;
2057 case TIOCSSOFTCAR:
2058 if (get_user(arg, (unsigned long __user *) argp)) {
2059 func_exit();
2060 return -EFAULT;
2061 }
2062 tty->termios->c_cflag =
2063 ((tty->termios->c_cflag & ~CLOCAL) |
2064 (arg ? CLOCAL : 0));
2065 func_exit();
2066 return 0;
2067 case TIOCGSERIAL:
2068 func_exit();
2069 return sx_get_serial_info(port, argp);
d61780c0 2070 case TIOCSSERIAL:
1da177e4
LT
2071 func_exit();
2072 return sx_set_serial_info(port, argp);
2073 default:
2074 func_exit();
2075 return -ENOIOCTLCMD;
2076 }
2077 func_exit();
2078 return 0;
2079}
2080
2081
2082static void sx_throttle(struct tty_struct * tty)
2083{
2084 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2085 struct specialix_board *bp;
2086 unsigned long flags;
2087
2088 func_enter();
2089
2090 if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
2091 func_exit();
2092 return;
2093 }
d61780c0 2094
1da177e4 2095 bp = port_Board(port);
d61780c0 2096
1da177e4 2097 /* Use DTR instead of RTS ! */
d61780c0 2098 if (SX_CRTSCTS (tty))
1da177e4
LT
2099 port->MSVR &= ~MSVR_DTR;
2100 else {
2101 /* Auch!!! I think the system shouldn't call this then. */
2102 /* Or maybe we're supposed (allowed?) to do our side of hw
d61780c0 2103 handshake anyway, even when hardware handshake is off.
1da177e4
LT
2104 When you see this in your logs, please report.... */
2105 printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
2106 port_No (port));
2107 }
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)) {
1da177e4
LT
2112 sx_wait_CCR(bp);
2113 spin_lock_irqsave(&bp->lock, flags);
2114 sx_out(bp, CD186x_CCR, CCR_SSCH2);
2115 spin_unlock_irqrestore(&bp->lock, flags);
2116 sx_wait_CCR(bp);
2117 }
2118 spin_lock_irqsave(&bp->lock, flags);
2119 sx_out(bp, CD186x_MSVR, port->MSVR);
2120 spin_unlock_irqrestore(&bp->lock, flags);
2121
2122 func_exit();
2123}
2124
2125
2126static void sx_unthrottle(struct tty_struct * tty)
2127{
2128 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2129 struct specialix_board *bp;
2130 unsigned long flags;
2131
2132 func_enter();
d61780c0 2133
1da177e4
LT
2134 if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
2135 func_exit();
2136 return;
2137 }
d61780c0 2138
1da177e4 2139 bp = port_Board(port);
d61780c0 2140
1da177e4
LT
2141 spin_lock_irqsave(&port->lock, flags);
2142 /* XXXX Use DTR INSTEAD???? */
2143 if (SX_CRTSCTS(tty)) {
2144 port->MSVR |= MSVR_DTR;
2145 } /* Else clause: see remark in "sx_throttle"... */
2146 spin_lock_irqsave(&bp->lock, flags);
2147 sx_out(bp, CD186x_CAR, port_No(port));
2148 spin_unlock_irqrestore(&bp->lock, flags);
2149 if (I_IXOFF(tty)) {
2150 spin_unlock_irqrestore(&port->lock, flags);
2151 sx_wait_CCR(bp);
2152 spin_lock_irqsave(&bp->lock, flags);
2153 sx_out(bp, CD186x_CCR, CCR_SSCH1);
2154 spin_unlock_irqrestore(&bp->lock, flags);
2155 sx_wait_CCR(bp);
2156 spin_lock_irqsave(&port->lock, flags);
2157 }
2158 spin_lock_irqsave(&bp->lock, flags);
2159 sx_out(bp, CD186x_MSVR, port->MSVR);
2160 spin_unlock_irqrestore(&bp->lock, flags);
2161 spin_unlock_irqrestore(&port->lock, flags);
2162
2163 func_exit();
2164}
2165
2166
2167static void sx_stop(struct tty_struct * tty)
2168{
2169 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2170 struct specialix_board *bp;
2171 unsigned long flags;
2172
2173 func_enter();
d61780c0 2174
1da177e4
LT
2175 if (sx_paranoia_check(port, tty->name, "sx_stop")) {
2176 func_exit();
2177 return;
2178 }
2179
2180 bp = port_Board(port);
d61780c0 2181
1da177e4
LT
2182 spin_lock_irqsave(&port->lock, flags);
2183 port->IER &= ~IER_TXRDY;
2184 spin_lock_irqsave(&bp->lock, flags);
2185 sx_out(bp, CD186x_CAR, port_No(port));
2186 sx_out(bp, CD186x_IER, port->IER);
2187 spin_unlock_irqrestore(&bp->lock, flags);
2188 spin_unlock_irqrestore(&port->lock, flags);
2189
2190 func_exit();
2191}
2192
2193
2194static void sx_start(struct tty_struct * tty)
2195{
2196 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2197 struct specialix_board *bp;
2198 unsigned long flags;
2199
2200 func_enter();
d61780c0 2201
1da177e4
LT
2202 if (sx_paranoia_check(port, tty->name, "sx_start")) {
2203 func_exit();
2204 return;
2205 }
d61780c0 2206
1da177e4 2207 bp = port_Board(port);
d61780c0 2208
1da177e4
LT
2209 spin_lock_irqsave(&port->lock, flags);
2210 if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
2211 port->IER |= IER_TXRDY;
2212 spin_lock_irqsave(&bp->lock, flags);
2213 sx_out(bp, CD186x_CAR, port_No(port));
2214 sx_out(bp, CD186x_IER, port->IER);
2215 spin_unlock_irqrestore(&bp->lock, flags);
2216 }
2217 spin_unlock_irqrestore(&port->lock, flags);
2218
2219 func_exit();
2220}
2221
1da177e4
LT
2222static void sx_hangup(struct tty_struct * tty)
2223{
2224 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2225 struct specialix_board *bp;
2226 unsigned long flags;
2227
2228 func_enter();
2229
2230 if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
2231 func_exit();
2232 return;
2233 }
d61780c0 2234
1da177e4 2235 bp = port_Board(port);
d61780c0 2236
1da177e4
LT
2237 sx_shutdown_port(bp, port);
2238 spin_lock_irqsave(&port->lock, flags);
1da177e4
LT
2239 bp->count -= port->count;
2240 if (bp->count < 0) {
2241 printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n",
2242 board_No(bp), bp->count, tty->index);
2243 bp->count = 0;
2244 }
2245 port->count = 0;
2246 port->flags &= ~ASYNC_NORMAL_ACTIVE;
2247 port->tty = NULL;
2248 spin_unlock_irqrestore(&port->lock, flags);
2249 wake_up_interruptible(&port->open_wait);
2250
2251 func_exit();
2252}
2253
2254
606d099c 2255static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
1da177e4
LT
2256{
2257 struct specialix_port *port = (struct specialix_port *)tty->driver_data;
2258 unsigned long flags;
2259 struct specialix_board * bp;
d61780c0 2260
1da177e4
LT
2261 if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
2262 return;
d61780c0 2263
1da177e4
LT
2264 if (tty->termios->c_cflag == old_termios->c_cflag &&
2265 tty->termios->c_iflag == old_termios->c_iflag)
2266 return;
2267
2268 bp = port_Board(port);
2269 spin_lock_irqsave(&port->lock, flags);
2270 sx_change_speed(port_Board(port), port);
2271 spin_unlock_irqrestore(&port->lock, flags);
2272
2273 if ((old_termios->c_cflag & CRTSCTS) &&
2274 !(tty->termios->c_cflag & CRTSCTS)) {
2275 tty->hw_stopped = 0;
2276 sx_start(tty);
2277 }
2278}
2279
b68e31d0 2280static const struct tty_operations sx_ops = {
1da177e4
LT
2281 .open = sx_open,
2282 .close = sx_close,
2283 .write = sx_write,
2284 .put_char = sx_put_char,
2285 .flush_chars = sx_flush_chars,
2286 .write_room = sx_write_room,
2287 .chars_in_buffer = sx_chars_in_buffer,
2288 .flush_buffer = sx_flush_buffer,
2289 .ioctl = sx_ioctl,
2290 .throttle = sx_throttle,
2291 .unthrottle = sx_unthrottle,
2292 .set_termios = sx_set_termios,
2293 .stop = sx_stop,
2294 .start = sx_start,
2295 .hangup = sx_hangup,
2296 .tiocmget = sx_tiocmget,
2297 .tiocmset = sx_tiocmset,
2298};
2299
2300static int sx_init_drivers(void)
2301{
2302 int error;
2303 int i;
2304
2305 func_enter();
2306
2307 specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
2308 if (!specialix_driver) {
2309 printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
2310 func_exit();
2311 return 1;
2312 }
d61780c0 2313
1da177e4
LT
2314 specialix_driver->owner = THIS_MODULE;
2315 specialix_driver->name = "ttyW";
2316 specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
2317 specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
2318 specialix_driver->subtype = SERIAL_TYPE_NORMAL;
2319 specialix_driver->init_termios = tty_std_termios;
2320 specialix_driver->init_termios.c_cflag =
2321 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
606d099c
AC
2322 specialix_driver->init_termios.c_ispeed = 9600;
2323 specialix_driver->init_termios.c_ospeed = 9600;
1da177e4
LT
2324 specialix_driver->flags = TTY_DRIVER_REAL_RAW;
2325 tty_set_operations(specialix_driver, &sx_ops);
2326
2327 if ((error = tty_register_driver(specialix_driver))) {
2328 put_tty_driver(specialix_driver);
1da177e4
LT
2329 printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
2330 error);
2331 func_exit();
2332 return 1;
2333 }
2334 memset(sx_port, 0, sizeof(sx_port));
2335 for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
2336 sx_port[i].magic = SPECIALIX_MAGIC;
1da177e4
LT
2337 sx_port[i].close_delay = 50 * HZ/100;
2338 sx_port[i].closing_wait = 3000 * HZ/100;
2339 init_waitqueue_head(&sx_port[i].open_wait);
2340 init_waitqueue_head(&sx_port[i].close_wait);
2341 spin_lock_init(&sx_port[i].lock);
2342 }
d61780c0 2343
1da177e4
LT
2344 func_exit();
2345 return 0;
2346}
2347
2348static void sx_release_drivers(void)
2349{
2350 func_enter();
2351
1da177e4
LT
2352 tty_unregister_driver(specialix_driver);
2353 put_tty_driver(specialix_driver);
2354 func_exit();
2355}
2356
d61780c0
JG
2357/*
2358 * This routine must be called by kernel at boot time
1da177e4
LT
2359 */
2360static int __init specialix_init(void)
2361{
2362 int i;
2363 int found = 0;
2364
2365 func_enter();
2366
2367 printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
2368 printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
2369#ifdef CONFIG_SPECIALIX_RTSCTS
2370 printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
2371#else
2372 printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
2373#endif
d61780c0 2374
1da177e4 2375 for (i = 0; i < SX_NBOARD; i++)
34af946a 2376 spin_lock_init(&sx_board[i].lock);
1da177e4
LT
2377
2378 if (sx_init_drivers()) {
2379 func_exit();
2380 return -EIO;
2381 }
2382
d61780c0 2383 for (i = 0; i < SX_NBOARD; i++)
1da177e4
LT
2384 if (sx_board[i].base && !sx_probe(&sx_board[i]))
2385 found++;
2386
2387#ifdef CONFIG_PCI
2388 {
2389 struct pci_dev *pdev = NULL;
2390
2391 i=0;
2392 while (i < SX_NBOARD) {
2393 if (sx_board[i].flags & SX_BOARD_PRESENT) {
2394 i++;
2395 continue;
2396 }
606d099c 2397 pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
d61780c0 2398 PCI_DEVICE_ID_SPECIALIX_IO8,
1da177e4
LT
2399 pdev);
2400 if (!pdev) break;
2401
2402 if (pci_enable_device(pdev))
2403 continue;
2404
2405 sx_board[i].irq = pdev->irq;
2406
2407 sx_board[i].base = pci_resource_start (pdev, 2);
2408
2409 sx_board[i].flags |= SX_BOARD_IS_PCI;
2410 if (!sx_probe(&sx_board[i]))
2411 found ++;
2412 }
606d099c
AC
2413 /* May exit pci_get sequence early with lots of boards */
2414 if (pdev != NULL)
2415 pci_dev_put(pdev);
1da177e4
LT
2416 }
2417#endif
2418
2419 if (!found) {
2420 sx_release_drivers();
2421 printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
2422 func_exit();
2423 return -EIO;
2424 }
2425
2426 func_exit();
2427 return 0;
2428}
2429
2430static int iobase[SX_NBOARD] = {0,};
2431
2432static int irq [SX_NBOARD] = {0,};
2433
2434module_param_array(iobase, int, NULL, 0);
2435module_param_array(irq, int, NULL, 0);
2436module_param(sx_debug, int, 0);
2437module_param(sx_rxfifo, int, 0);
2438#ifdef SPECIALIX_TIMER
2439module_param(sx_poll, int, 0);
2440#endif
2441
2442/*
2443 * You can setup up to 4 boards.
2444 * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
d61780c0
JG
2445 * You should specify the IRQs too in that case "irq=....,...".
2446 *
1da177e4 2447 * More than 4 boards in one computer is not possible, as the card can
d61780c0 2448 * only use 4 different interrupts.
1da177e4
LT
2449 *
2450 */
2451static int __init specialix_init_module(void)
2452{
2453 int i;
2454
2455 func_enter();
2456
1da177e4
LT
2457 if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
2458 for(i = 0; i < SX_NBOARD; i++) {
2459 sx_board[i].base = iobase[i];
2460 sx_board[i].irq = irq[i];
2461 sx_board[i].count= 0;
2462 }
2463 }
2464
2465 func_exit();
2466
2467 return specialix_init();
2468}
d61780c0 2469
1da177e4
LT
2470static void __exit specialix_exit_module(void)
2471{
2472 int i;
d61780c0 2473
1da177e4
LT
2474 func_enter();
2475
2476 sx_release_drivers();
2477 for (i = 0; i < SX_NBOARD; i++)
d61780c0 2478 if (sx_board[i].flags & SX_BOARD_PRESENT)
1da177e4
LT
2479 sx_release_io_range(&sx_board[i]);
2480#ifdef SPECIALIX_TIMER
40565f19 2481 del_timer_sync(&missed_irq_timer);
1da177e4
LT
2482#endif
2483
2484 func_exit();
2485}
2486
7691030b
CS
2487static struct pci_device_id specialx_pci_tbl[] __devinitdata = {
2488 { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
2489 { }
2490};
2491MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
2492
1da177e4
LT
2493module_init(specialix_init_module);
2494module_exit(specialix_exit_module);
2495
2496MODULE_LICENSE("GPL");