OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [specialix.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.