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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [isicom.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *      This program is free software; you can redistribute it and/or
3
 *      modify it under the terms of the GNU General Public License
4
 *      as published by the Free Software Foundation; either version
5
 *      2 of the License, or (at your option) any later version.
6
 *
7
 *      Original driver code supplied by Multi-Tech
8
 *
9
 *      Changes
10
 *      1/9/98  alan@redhat.com         Merge to 2.0.x kernel tree
11
 *                                      Obtain and use official major/minors
12
 *                                      Loader switched to a misc device
13
 *                                      (fixed range check bug as a side effect)
14
 *                                      Printk clean up
15
 *      9/12/98 alan@redhat.com         Rough port to 2.1.x
16
 *
17
 *      10/6/99 sameer                  Merged the ISA and PCI drivers to
18
 *                                      a new unified driver.
19
 *
20
 *      3/9/99  sameer                  Added support for ISI4616 cards.
21
 *
22
 *      16/9/99 sameer                  We do not force RTS low anymore.
23
 *                                      This is to prevent the firmware
24
 *                                      from getting confused.
25
 *
26
 *      26/10/99 sameer                 Cosmetic changes:The driver now
27
 *                                      dumps the Port Count information
28
 *                                      along with I/O address and IRQ.
29
 *
30
 *      13/12/99 sameer                 Fixed the problem with IRQ sharing.
31
 *
32
 *      10/5/00  sameer                 Fixed isicom_shutdown_board()
33
 *                                      to not lower DTR on all the ports
34
 *                                      when the last port on the card is
35
 *                                      closed.
36
 *
37
 *      10/5/00  sameer                 Signal mask setup command added
38
 *                                      to  isicom_setup_port and
39
 *                                      isicom_shutdown_port.
40
 *
41
 *      24/5/00  sameer                 The driver is now SMP aware.
42
 *
43
 *
44
 *      27/11/00 Vinayak P Risbud       Fixed the Driver Crash Problem
45
 *
46
 *
47
 *      03/01/01  anil .s               Added support for resetting the
48
 *                                      internal modems on ISI cards.
49
 *
50
 *      08/02/01  anil .s               Upgraded the driver for kernel
51
 *                                      2.4.x
52
 *
53
 *      11/04/01  Kevin                 Fixed firmware load problem with
54
 *                                      ISIHP-4X card
55
 *
56
 *      30/04/01  anil .s               Fixed the remote login through
57
 *                                      ISI port problem. Now the link
58
 *                                      does not go down before password
59
 *                                      prompt.
60
 *
61
 *      03/05/01  anil .s               Fixed the problem with IRQ sharing
62
 *                                      among ISI-PCI cards.
63
 *
64
 *      03/05/01  anil .s               Added support to display the version
65
 *                                      info during insmod as well as module
66
 *                                      listing by lsmod.
67
 *
68
 *      10/05/01  anil .s               Done the modifications to the source
69
 *                                      file and Install script so that the
70
 *                                      same installation can be used for
71
 *                                      2.2.x and 2.4.x kernel.
72
 *
73
 *      06/06/01  anil .s               Now we drop both dtr and rts during
74
 *                                      shutdown_port as well as raise them
75
 *                                      during isicom_config_port.
76
 *
77
 *      09/06/01 acme@conectiva.com.br  use capable, not suser, do
78
 *                                      restore_flags on failure in
79
 *                                      isicom_send_break, verify put_user
80
 *                                      result
81
 *
82
 *      11/02/03  ranjeeth              Added support for 230 Kbps and 460 Kbps
83
 *                                      Baud index extended to 21
84
 *
85
 *      20/03/03  ranjeeth              Made to work for Linux Advanced server.
86
 *                                      Taken care of license warning.
87
 *
88
 *      10/12/03  Ravindra              Made to work for Fedora Core 1 of
89
 *                                      Red Hat Distribution
90
 *
91
 *      06/01/05  Alan Cox              Merged the ISI and base kernel strands
92
 *                                      into a single 2.6 driver
93
 *
94
 *      ***********************************************************
95
 *
96
 *      To use this driver you also need the support package. You
97
 *      can find this in RPM format on
98
 *              ftp://ftp.linux.org.uk/pub/linux/alan
99
 *
100
 *      You can find the original tools for this direct from Multitech
101
 *              ftp://ftp.multitech.com/ISI-Cards/
102
 *
103
 *      Having installed the cards the module options (/etc/modprobe.conf)
104
 *
105
 *      options isicom   io=card1,card2,card3,card4 irq=card1,card2,card3,card4
106
 *
107
 *      Omit those entries for boards you don't have installed.
108
 *
109
 *      TODO
110
 *              Merge testing
111
 *              64-bit verification
112
 */
113
 
114
#include <linux/module.h>
115
#include <linux/firmware.h>
116
#include <linux/kernel.h>
117
#include <linux/tty.h>
118
#include <linux/tty_flip.h>
119
#include <linux/termios.h>
120
#include <linux/fs.h>
121
#include <linux/sched.h>
122
#include <linux/serial.h>
123
#include <linux/mm.h>
124
#include <linux/interrupt.h>
125
#include <linux/timer.h>
126
#include <linux/delay.h>
127
#include <linux/ioport.h>
128
 
129
#include <asm/uaccess.h>
130
#include <asm/io.h>
131
#include <asm/system.h>
132
 
133
#include <linux/pci.h>
134
 
135
#include <linux/isicom.h>
136
 
137
#define InterruptTheCard(base) outw(0, (base) + 0xc)
138
#define ClearInterrupt(base) inw((base) + 0x0a)
139
 
140
#define pr_dbg(str...) pr_debug("ISICOM: " str)
141
#ifdef DEBUG
142
#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
143
#else
144
#define isicom_paranoia_check(a, b, c) 0
145
#endif
146
 
147
static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
148
static void __devexit isicom_remove(struct pci_dev *);
149
 
150
static struct pci_device_id isicom_pci_tbl[] = {
151
        { PCI_DEVICE(VENDOR_ID, 0x2028) },
152
        { PCI_DEVICE(VENDOR_ID, 0x2051) },
153
        { PCI_DEVICE(VENDOR_ID, 0x2052) },
154
        { PCI_DEVICE(VENDOR_ID, 0x2053) },
155
        { PCI_DEVICE(VENDOR_ID, 0x2054) },
156
        { PCI_DEVICE(VENDOR_ID, 0x2055) },
157
        { PCI_DEVICE(VENDOR_ID, 0x2056) },
158
        { PCI_DEVICE(VENDOR_ID, 0x2057) },
159
        { PCI_DEVICE(VENDOR_ID, 0x2058) },
160
        { 0 }
161
};
162
MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
163
 
164
static struct pci_driver isicom_driver = {
165
        .name           = "isicom",
166
        .id_table       = isicom_pci_tbl,
167
        .probe          = isicom_probe,
168
        .remove         = __devexit_p(isicom_remove)
169
};
170
 
171
static int prev_card = 3;       /*      start servicing isi_card[0]     */
172
static struct tty_driver *isicom_normal;
173
 
174
static void isicom_tx(unsigned long _data);
175
static void isicom_start(struct tty_struct *tty);
176
 
177
static DEFINE_TIMER(tx, isicom_tx, 0, 0);
178
 
179
/*   baud index mappings from linux defns to isi */
180
 
181
static signed char linuxb_to_isib[] = {
182
        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
183
};
184
 
185
struct  isi_board {
186
        unsigned long           base;
187
        int                     irq;
188
        unsigned char           port_count;
189
        unsigned short          status;
190
        unsigned short          port_status; /* each bit for each port */
191
        unsigned short          shift_count;
192
        struct isi_port         * ports;
193
        signed char             count;
194
        spinlock_t              card_lock; /* Card wide lock 11/5/00 -sameer */
195
        unsigned long           flags;
196
        unsigned int            index;
197
};
198
 
199
struct  isi_port {
200
        unsigned short          magic;
201
        unsigned int            flags;
202
        int                     count;
203
        int                     blocked_open;
204
        int                     close_delay;
205
        u16                     channel;
206
        u16                     status;
207
        u16                     closing_wait;
208
        struct isi_board        * card;
209
        struct tty_struct       * tty;
210
        wait_queue_head_t       close_wait;
211
        wait_queue_head_t       open_wait;
212
        unsigned char           * xmit_buf;
213
        int                     xmit_head;
214
        int                     xmit_tail;
215
        int                     xmit_cnt;
216
};
217
 
218
static struct isi_board isi_card[BOARD_COUNT];
219
static struct isi_port  isi_ports[PORT_COUNT];
220
 
221
/*
222
 *      Locking functions for card level locking. We need to own both
223
 *      the kernel lock for the card and have the card in a position that
224
 *      it wants to talk.
225
 */
226
 
227
static inline int WaitTillCardIsFree(unsigned long base)
228
{
229
        unsigned int count = 0;
230
        unsigned int a = in_atomic(); /* do we run under spinlock? */
231
 
232
        while (!(inw(base + 0xe) & 0x1) && count++ < 100)
233
                if (a)
234
                        mdelay(1);
235
                else
236
                        msleep(1);
237
 
238
        return !(inw(base + 0xe) & 0x1);
239
}
240
 
241
static int lock_card(struct isi_board *card)
242
{
243
        unsigned long base = card->base;
244
        unsigned int retries, a;
245
 
246
        for (retries = 0; retries < 10; retries++) {
247
                spin_lock_irqsave(&card->card_lock, card->flags);
248
                for (a = 0; a < 10; a++) {
249
                        if (inw(base + 0xe) & 0x1)
250
                                return 1;
251
                        udelay(10);
252
                }
253
                spin_unlock_irqrestore(&card->card_lock, card->flags);
254
                msleep(10);
255
        }
256
        printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
257
                card->base);
258
 
259
        return 0;        /* Failed to acquire the card! */
260
}
261
 
262
static void unlock_card(struct isi_board *card)
263
{
264
        spin_unlock_irqrestore(&card->card_lock, card->flags);
265
}
266
 
267
/*
268
 *  ISI Card specific ops ...
269
 */
270
 
271
/* card->lock HAS to be held */
272
static void raise_dtr(struct isi_port *port)
273
{
274
        struct isi_board *card = port->card;
275
        unsigned long base = card->base;
276
        u16 channel = port->channel;
277
 
278
        if (WaitTillCardIsFree(base))
279
                return;
280
 
281
        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
282
        outw(0x0504, base);
283
        InterruptTheCard(base);
284
        port->status |= ISI_DTR;
285
}
286
 
287
/* card->lock HAS to be held */
288
static inline void drop_dtr(struct isi_port *port)
289
{
290
        struct isi_board *card = port->card;
291
        unsigned long base = card->base;
292
        u16 channel = port->channel;
293
 
294
        if (WaitTillCardIsFree(base))
295
                return;
296
 
297
        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
298
        outw(0x0404, base);
299
        InterruptTheCard(base);
300
        port->status &= ~ISI_DTR;
301
}
302
 
303
/* card->lock HAS to be held */
304
static inline void raise_rts(struct isi_port *port)
305
{
306
        struct isi_board *card = port->card;
307
        unsigned long base = card->base;
308
        u16 channel = port->channel;
309
 
310
        if (WaitTillCardIsFree(base))
311
                return;
312
 
313
        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
314
        outw(0x0a04, base);
315
        InterruptTheCard(base);
316
        port->status |= ISI_RTS;
317
}
318
 
319
/* card->lock HAS to be held */
320
static inline void drop_rts(struct isi_port *port)
321
{
322
        struct isi_board *card = port->card;
323
        unsigned long base = card->base;
324
        u16 channel = port->channel;
325
 
326
        if (WaitTillCardIsFree(base))
327
                return;
328
 
329
        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
330
        outw(0x0804, base);
331
        InterruptTheCard(base);
332
        port->status &= ~ISI_RTS;
333
}
334
 
335
/* card->lock MUST NOT be held */
336
static inline void raise_dtr_rts(struct isi_port *port)
337
{
338
        struct isi_board *card = port->card;
339
        unsigned long base = card->base;
340
        u16 channel = port->channel;
341
 
342
        if (!lock_card(card))
343
                return;
344
 
345
        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
346
        outw(0x0f04, base);
347
        InterruptTheCard(base);
348
        port->status |= (ISI_DTR | ISI_RTS);
349
        unlock_card(card);
350
}
351
 
352
/* card->lock HAS to be held */
353
static void drop_dtr_rts(struct isi_port *port)
354
{
355
        struct isi_board *card = port->card;
356
        unsigned long base = card->base;
357
        u16 channel = port->channel;
358
 
359
        if (WaitTillCardIsFree(base))
360
                return;
361
 
362
        outw(0x8000 | (channel << card->shift_count) | 0x02, base);
363
        outw(0x0c04, base);
364
        InterruptTheCard(base);
365
        port->status &= ~(ISI_RTS | ISI_DTR);
366
}
367
 
368
/*
369
 *      ISICOM Driver specific routines ...
370
 *
371
 */
372
 
373
static inline int __isicom_paranoia_check(struct isi_port const *port,
374
        char *name, const char *routine)
375
{
376
        if (!port) {
377
                printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
378
                        "dev %s in %s.\n", name, routine);
379
                return 1;
380
        }
381
        if (port->magic != ISICOM_MAGIC) {
382
                printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
383
                        "dev %s in %s.\n", name, routine);
384
                return 1;
385
        }
386
 
387
        return 0;
388
}
389
 
390
/*
391
 *      Transmitter.
392
 *
393
 *      We shovel data into the card buffers on a regular basis. The card
394
 *      will do the rest of the work for us.
395
 */
396
 
397
static void isicom_tx(unsigned long _data)
398
{
399
        unsigned long flags, base;
400
        unsigned int retries;
401
        short count = (BOARD_COUNT-1), card;
402
        short txcount, wrd, residue, word_count, cnt;
403
        struct isi_port *port;
404
        struct tty_struct *tty;
405
 
406
        /*      find next active board  */
407
        card = (prev_card + 1) & 0x0003;
408
        while(count-- > 0) {
409
                if (isi_card[card].status & BOARD_ACTIVE)
410
                        break;
411
                card = (card + 1) & 0x0003;
412
        }
413
        if (!(isi_card[card].status & BOARD_ACTIVE))
414
                goto sched_again;
415
 
416
        prev_card = card;
417
 
418
        count = isi_card[card].port_count;
419
        port = isi_card[card].ports;
420
        base = isi_card[card].base;
421
 
422
        spin_lock_irqsave(&isi_card[card].card_lock, flags);
423
        for (retries = 0; retries < 100; retries++) {
424
                if (inw(base + 0xe) & 0x1)
425
                        break;
426
                udelay(2);
427
        }
428
        if (retries >= 100)
429
                goto unlock;
430
 
431
        for (;count > 0;count--, port++) {
432
                /* port not active or tx disabled to force flow control */
433
                if (!(port->flags & ASYNC_INITIALIZED) ||
434
                                !(port->status & ISI_TXOK))
435
                        continue;
436
 
437
                tty = port->tty;
438
 
439
                if (tty == NULL)
440
                        continue;
441
 
442
                txcount = min_t(short, TX_SIZE, port->xmit_cnt);
443
                if (txcount <= 0 || tty->stopped || tty->hw_stopped)
444
                        continue;
445
 
446
                if (!(inw(base + 0x02) & (1 << port->channel)))
447
                        continue;
448
 
449
                pr_dbg("txing %d bytes, port%d.\n", txcount,
450
                        port->channel + 1);
451
                outw((port->channel << isi_card[card].shift_count) | txcount,
452
                        base);
453
                residue = NO;
454
                wrd = 0;
455
                while (1) {
456
                        cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
457
                                        - port->xmit_tail));
458
                        if (residue == YES) {
459
                                residue = NO;
460
                                if (cnt > 0) {
461
                                        wrd |= (port->xmit_buf[port->xmit_tail]
462
                                                                        << 8);
463
                                        port->xmit_tail = (port->xmit_tail + 1)
464
                                                & (SERIAL_XMIT_SIZE - 1);
465
                                        port->xmit_cnt--;
466
                                        txcount--;
467
                                        cnt--;
468
                                        outw(wrd, base);
469
                                } else {
470
                                        outw(wrd, base);
471
                                        break;
472
                                }
473
                        }
474
                        if (cnt <= 0) break;
475
                        word_count = cnt >> 1;
476
                        outsw(base, port->xmit_buf+port->xmit_tail,word_count);
477
                        port->xmit_tail = (port->xmit_tail
478
                                + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
479
                        txcount -= (word_count << 1);
480
                        port->xmit_cnt -= (word_count << 1);
481
                        if (cnt & 0x0001) {
482
                                residue = YES;
483
                                wrd = port->xmit_buf[port->xmit_tail];
484
                                port->xmit_tail = (port->xmit_tail + 1)
485
                                        & (SERIAL_XMIT_SIZE - 1);
486
                                port->xmit_cnt--;
487
                                txcount--;
488
                        }
489
                }
490
 
491
                InterruptTheCard(base);
492
                if (port->xmit_cnt <= 0)
493
                        port->status &= ~ISI_TXOK;
494
                if (port->xmit_cnt <= WAKEUP_CHARS)
495
                        tty_wakeup(tty);
496
        }
497
 
498
unlock:
499
        spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
500
        /*      schedule another tx for hopefully in about 10ms */
501
sched_again:
502
        mod_timer(&tx, jiffies + msecs_to_jiffies(10));
503
}
504
 
505
/*
506
 *      Main interrupt handler routine
507
 */
508
 
509
static irqreturn_t isicom_interrupt(int irq, void *dev_id)
510
{
511
        struct isi_board *card = dev_id;
512
        struct isi_port *port;
513
        struct tty_struct *tty;
514
        unsigned long base;
515
        u16 header, word_count, count, channel;
516
        short byte_count;
517
        unsigned char *rp;
518
 
519
        if (!card || !(card->status & FIRMWARE_LOADED))
520
                return IRQ_NONE;
521
 
522
        base = card->base;
523
 
524
        /* did the card interrupt us? */
525
        if (!(inw(base + 0x0e) & 0x02))
526
                return IRQ_NONE;
527
 
528
        spin_lock(&card->card_lock);
529
 
530
        /*
531
         * disable any interrupts from the PCI card and lower the
532
         * interrupt line
533
         */
534
        outw(0x8000, base+0x04);
535
        ClearInterrupt(base);
536
 
537
        inw(base);              /* get the dummy word out */
538
        header = inw(base);
539
        channel = (header & 0x7800) >> card->shift_count;
540
        byte_count = header & 0xff;
541
 
542
        if (channel + 1 > card->port_count) {
543
                printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
544
                        "%d(channel) > port_count.\n", base, channel+1);
545
                outw(0x0000, base+0x04); /* enable interrupts */
546
                spin_unlock(&card->card_lock);
547
                return IRQ_HANDLED;
548
        }
549
        port = card->ports + channel;
550
        if (!(port->flags & ASYNC_INITIALIZED)) {
551
                outw(0x0000, base+0x04); /* enable interrupts */
552
                spin_unlock(&card->card_lock);
553
                return IRQ_HANDLED;
554
        }
555
 
556
        tty = port->tty;
557
        if (tty == NULL) {
558
                word_count = byte_count >> 1;
559
                while(byte_count > 1) {
560
                        inw(base);
561
                        byte_count -= 2;
562
                }
563
                if (byte_count & 0x01)
564
                        inw(base);
565
                outw(0x0000, base+0x04); /* enable interrupts */
566
                spin_unlock(&card->card_lock);
567
                return IRQ_HANDLED;
568
        }
569
 
570
        if (header & 0x8000) {          /* Status Packet */
571
                header = inw(base);
572
                switch(header & 0xff) {
573
                case 0:  /* Change in EIA signals */
574
                        if (port->flags & ASYNC_CHECK_CD) {
575
                                if (port->status & ISI_DCD) {
576
                                        if (!(header & ISI_DCD)) {
577
                                        /* Carrier has been lost  */
578
                                                pr_dbg("interrupt: DCD->low.\n"
579
                                                        );
580
                                                port->status &= ~ISI_DCD;
581
                                                tty_hangup(tty);
582
                                        }
583
                                } else if (header & ISI_DCD) {
584
                                /* Carrier has been detected */
585
                                        pr_dbg("interrupt: DCD->high.\n");
586
                                        port->status |= ISI_DCD;
587
                                        wake_up_interruptible(&port->open_wait);
588
                                }
589
                        } else {
590
                                if (header & ISI_DCD)
591
                                        port->status |= ISI_DCD;
592
                                else
593
                                        port->status &= ~ISI_DCD;
594
                        }
595
 
596
                        if (port->flags & ASYNC_CTS_FLOW) {
597
                                if (port->tty->hw_stopped) {
598
                                        if (header & ISI_CTS) {
599
                                                port->tty->hw_stopped = 0;
600
                                                /* start tx ing */
601
                                                port->status |= (ISI_TXOK
602
                                                        | ISI_CTS);
603
                                                tty_wakeup(tty);
604
                                        }
605
                                } else if (!(header & ISI_CTS)) {
606
                                        port->tty->hw_stopped = 1;
607
                                        /* stop tx ing */
608
                                        port->status &= ~(ISI_TXOK | ISI_CTS);
609
                                }
610
                        } else {
611
                                if (header & ISI_CTS)
612
                                        port->status |= ISI_CTS;
613
                                else
614
                                        port->status &= ~ISI_CTS;
615
                        }
616
 
617
                        if (header & ISI_DSR)
618
                                port->status |= ISI_DSR;
619
                        else
620
                                port->status &= ~ISI_DSR;
621
 
622
                        if (header & ISI_RI)
623
                                port->status |= ISI_RI;
624
                        else
625
                                port->status &= ~ISI_RI;
626
 
627
                        break;
628
 
629
                case 1: /* Received Break !!! */
630
                        tty_insert_flip_char(tty, 0, TTY_BREAK);
631
                        if (port->flags & ASYNC_SAK)
632
                                do_SAK(tty);
633
                        tty_flip_buffer_push(tty);
634
                        break;
635
 
636
                case 2: /* Statistics            */
637
                        pr_dbg("isicom_interrupt: stats!!!.\n");
638
                        break;
639
 
640
                default:
641
                        pr_dbg("Intr: Unknown code in status packet.\n");
642
                        break;
643
                }
644
        } else {                                /* Data   Packet */
645
 
646
                count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
647
                pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
648
                word_count = count >> 1;
649
                insw(base, rp, word_count);
650
                byte_count -= (word_count << 1);
651
                if (count & 0x0001) {
652
                        tty_insert_flip_char(tty,  inw(base) & 0xff,
653
                                TTY_NORMAL);
654
                        byte_count -= 2;
655
                }
656
                if (byte_count > 0) {
657
                        pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
658
                                "bytes...\n", base, channel + 1);
659
                        while(byte_count > 0) { /* drain out unread xtra data */
660
                                inw(base);
661
                                byte_count -= 2;
662
                        }
663
                }
664
                tty_flip_buffer_push(tty);
665
        }
666
        outw(0x0000, base+0x04); /* enable interrupts */
667
        spin_unlock(&card->card_lock);
668
 
669
        return IRQ_HANDLED;
670
}
671
 
672
static void isicom_config_port(struct isi_port *port)
673
{
674
        struct isi_board *card = port->card;
675
        struct tty_struct *tty;
676
        unsigned long baud;
677
        unsigned long base = card->base;
678
        u16 channel_setup, channel = port->channel,
679
                shift_count = card->shift_count;
680
        unsigned char flow_ctrl;
681
 
682
        if (!(tty = port->tty) || !tty->termios)
683
                return;
684
        baud = C_BAUD(tty);
685
        if (baud & CBAUDEX) {
686
                baud &= ~CBAUDEX;
687
 
688
                /*  if CBAUDEX bit is on and the baud is set to either 50 or 75
689
                 *  then the card is programmed for 57.6Kbps or 115Kbps
690
                 *  respectively.
691
                 */
692
 
693
                /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
694
                if (baud < 1 || baud > 4)
695
                        port->tty->termios->c_cflag &= ~CBAUDEX;
696
                else
697
                        baud += 15;
698
        }
699
        if (baud == 15) {
700
 
701
                /*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
702
                 *  by the set_serial_info ioctl ... this is done by
703
                 *  the 'setserial' utility.
704
                 */
705
 
706
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
707
                        baud++; /*  57.6 Kbps */
708
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
709
                        baud +=2; /*  115  Kbps */
710
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
711
                        baud += 3; /* 230 kbps*/
712
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
713
                        baud += 4; /* 460 kbps*/
714
        }
715
        if (linuxb_to_isib[baud] == -1) {
716
                /* hang up */
717
                drop_dtr(port);
718
                return;
719
        }
720
        else
721
                raise_dtr(port);
722
 
723
        if (WaitTillCardIsFree(base) == 0) {
724
                outw(0x8000 | (channel << shift_count) |0x03, base);
725
                outw(linuxb_to_isib[baud] << 8 | 0x03, base);
726
                channel_setup = 0;
727
                switch(C_CSIZE(tty)) {
728
                case CS5:
729
                        channel_setup |= ISICOM_CS5;
730
                        break;
731
                case CS6:
732
                        channel_setup |= ISICOM_CS6;
733
                        break;
734
                case CS7:
735
                        channel_setup |= ISICOM_CS7;
736
                        break;
737
                case CS8:
738
                        channel_setup |= ISICOM_CS8;
739
                        break;
740
                }
741
 
742
                if (C_CSTOPB(tty))
743
                        channel_setup |= ISICOM_2SB;
744
                if (C_PARENB(tty)) {
745
                        channel_setup |= ISICOM_EVPAR;
746
                        if (C_PARODD(tty))
747
                                channel_setup |= ISICOM_ODPAR;
748
                }
749
                outw(channel_setup, base);
750
                InterruptTheCard(base);
751
        }
752
        if (C_CLOCAL(tty))
753
                port->flags &= ~ASYNC_CHECK_CD;
754
        else
755
                port->flags |= ASYNC_CHECK_CD;
756
 
757
        /* flow control settings ...*/
758
        flow_ctrl = 0;
759
        port->flags &= ~ASYNC_CTS_FLOW;
760
        if (C_CRTSCTS(tty)) {
761
                port->flags |= ASYNC_CTS_FLOW;
762
                flow_ctrl |= ISICOM_CTSRTS;
763
        }
764
        if (I_IXON(tty))
765
                flow_ctrl |= ISICOM_RESPOND_XONXOFF;
766
        if (I_IXOFF(tty))
767
                flow_ctrl |= ISICOM_INITIATE_XONXOFF;
768
 
769
        if (WaitTillCardIsFree(base) == 0) {
770
                outw(0x8000 | (channel << shift_count) |0x04, base);
771
                outw(flow_ctrl << 8 | 0x05, base);
772
                outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
773
                InterruptTheCard(base);
774
        }
775
 
776
        /*      rx enabled -> enable port for rx on the card    */
777
        if (C_CREAD(tty)) {
778
                card->port_status |= (1 << channel);
779
                outw(card->port_status, base + 0x02);
780
        }
781
}
782
 
783
/* open et all */
784
 
785
static inline void isicom_setup_board(struct isi_board *bp)
786
{
787
        int channel;
788
        struct isi_port *port;
789
        unsigned long flags;
790
 
791
        spin_lock_irqsave(&bp->card_lock, flags);
792
        if (bp->status & BOARD_ACTIVE) {
793
                spin_unlock_irqrestore(&bp->card_lock, flags);
794
                return;
795
        }
796
        port = bp->ports;
797
        bp->status |= BOARD_ACTIVE;
798
        for (channel = 0; channel < bp->port_count; channel++, port++)
799
                drop_dtr_rts(port);
800
        spin_unlock_irqrestore(&bp->card_lock, flags);
801
}
802
 
803
static int isicom_setup_port(struct isi_port *port)
804
{
805
        struct isi_board *card = port->card;
806
        unsigned long flags;
807
 
808
        if (port->flags & ASYNC_INITIALIZED) {
809
                return 0;
810
        }
811
        if (!port->xmit_buf) {
812
                unsigned long page;
813
 
814
                if (!(page = get_zeroed_page(GFP_KERNEL)))
815
                        return -ENOMEM;
816
 
817
                if (port->xmit_buf) {
818
                        free_page(page);
819
                        return -ERESTARTSYS;
820
                }
821
                port->xmit_buf = (unsigned char *) page;
822
        }
823
 
824
        spin_lock_irqsave(&card->card_lock, flags);
825
        if (port->tty)
826
                clear_bit(TTY_IO_ERROR, &port->tty->flags);
827
        if (port->count == 1)
828
                card->count++;
829
 
830
        port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
831
 
832
        /*      discard any residual data       */
833
        if (WaitTillCardIsFree(card->base) == 0) {
834
                outw(0x8000 | (port->channel << card->shift_count) | 0x02,
835
                                card->base);
836
                outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
837
                InterruptTheCard(card->base);
838
        }
839
 
840
        isicom_config_port(port);
841
        port->flags |= ASYNC_INITIALIZED;
842
        spin_unlock_irqrestore(&card->card_lock, flags);
843
 
844
        return 0;
845
}
846
 
847
static int block_til_ready(struct tty_struct *tty, struct file *filp,
848
        struct isi_port *port)
849
{
850
        struct isi_board *card = port->card;
851
        int do_clocal = 0, retval;
852
        unsigned long flags;
853
        DECLARE_WAITQUEUE(wait, current);
854
 
855
        /* block if port is in the process of being closed */
856
 
857
        if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
858
                pr_dbg("block_til_ready: close in progress.\n");
859
                interruptible_sleep_on(&port->close_wait);
860
                if (port->flags & ASYNC_HUP_NOTIFY)
861
                        return -EAGAIN;
862
                else
863
                        return -ERESTARTSYS;
864
        }
865
 
866
        /* if non-blocking mode is set ... */
867
 
868
        if ((filp->f_flags & O_NONBLOCK) ||
869
                        (tty->flags & (1 << TTY_IO_ERROR))) {
870
                pr_dbg("block_til_ready: non-block mode.\n");
871
                port->flags |= ASYNC_NORMAL_ACTIVE;
872
                return 0;
873
        }
874
 
875
        if (C_CLOCAL(tty))
876
                do_clocal = 1;
877
 
878
        /* block waiting for DCD to be asserted, and while
879
                                                callout dev is busy */
880
        retval = 0;
881
        add_wait_queue(&port->open_wait, &wait);
882
 
883
        spin_lock_irqsave(&card->card_lock, flags);
884
        if (!tty_hung_up_p(filp))
885
                port->count--;
886
        port->blocked_open++;
887
        spin_unlock_irqrestore(&card->card_lock, flags);
888
 
889
        while (1) {
890
                raise_dtr_rts(port);
891
 
892
                set_current_state(TASK_INTERRUPTIBLE);
893
                if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
894
                        if (port->flags & ASYNC_HUP_NOTIFY)
895
                                retval = -EAGAIN;
896
                        else
897
                                retval = -ERESTARTSYS;
898
                        break;
899
                }
900
                if (!(port->flags & ASYNC_CLOSING) &&
901
                                (do_clocal || (port->status & ISI_DCD))) {
902
                        break;
903
                }
904
                if (signal_pending(current)) {
905
                        retval = -ERESTARTSYS;
906
                        break;
907
                }
908
                schedule();
909
        }
910
        set_current_state(TASK_RUNNING);
911
        remove_wait_queue(&port->open_wait, &wait);
912
        spin_lock_irqsave(&card->card_lock, flags);
913
        if (!tty_hung_up_p(filp))
914
                port->count++;
915
        port->blocked_open--;
916
        spin_unlock_irqrestore(&card->card_lock, flags);
917
        if (retval)
918
                return retval;
919
        port->flags |= ASYNC_NORMAL_ACTIVE;
920
        return 0;
921
}
922
 
923
static int isicom_open(struct tty_struct *tty, struct file *filp)
924
{
925
        struct isi_port *port;
926
        struct isi_board *card;
927
        unsigned int board;
928
        int error, line;
929
 
930
        line = tty->index;
931
        if (line < 0 || line > PORT_COUNT-1)
932
                return -ENODEV;
933
        board = BOARD(line);
934
        card = &isi_card[board];
935
 
936
        if (!(card->status & FIRMWARE_LOADED))
937
                return -ENODEV;
938
 
939
        /*  open on a port greater than the port count for the card !!! */
940
        if (line > ((board * 16) + card->port_count - 1))
941
                return -ENODEV;
942
 
943
        port = &isi_ports[line];
944
        if (isicom_paranoia_check(port, tty->name, "isicom_open"))
945
                return -ENODEV;
946
 
947
        isicom_setup_board(card);
948
 
949
        port->count++;
950
        tty->driver_data = port;
951
        port->tty = tty;
952
        if ((error = isicom_setup_port(port))!=0)
953
                return error;
954
        if ((error = block_til_ready(tty, filp, port))!=0)
955
                return error;
956
 
957
        return 0;
958
}
959
 
960
/* close et all */
961
 
962
static inline void isicom_shutdown_board(struct isi_board *bp)
963
{
964
        if (bp->status & BOARD_ACTIVE) {
965
                bp->status &= ~BOARD_ACTIVE;
966
        }
967
}
968
 
969
/* card->lock HAS to be held */
970
static void isicom_shutdown_port(struct isi_port *port)
971
{
972
        struct isi_board *card = port->card;
973
        struct tty_struct *tty;
974
 
975
        tty = port->tty;
976
 
977
        if (!(port->flags & ASYNC_INITIALIZED))
978
                return;
979
 
980
        if (port->xmit_buf) {
981
                free_page((unsigned long) port->xmit_buf);
982
                port->xmit_buf = NULL;
983
        }
984
        port->flags &= ~ASYNC_INITIALIZED;
985
        /* 3rd October 2000 : Vinayak P Risbud */
986
        port->tty = NULL;
987
 
988
        /*Fix done by Anil .S on 30-04-2001
989
        remote login through isi port has dtr toggle problem
990
        due to which the carrier drops before the password prompt
991
        appears on the remote end. Now we drop the dtr only if the
992
        HUPCL(Hangup on close) flag is set for the tty*/
993
 
994
        if (C_HUPCL(tty))
995
                /* drop dtr on this port */
996
                drop_dtr(port);
997
 
998
        /* any other port uninits  */
999
        if (tty)
1000
                set_bit(TTY_IO_ERROR, &tty->flags);
1001
 
1002
        if (--card->count < 0) {
1003
                pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
1004
                        card->base, card->count);
1005
                card->count = 0;
1006
        }
1007
 
1008
        /* last port was closed, shutdown that boad too */
1009
        if (C_HUPCL(tty)) {
1010
                if (!card->count)
1011
                        isicom_shutdown_board(card);
1012
        }
1013
}
1014
 
1015
static void isicom_close(struct tty_struct *tty, struct file *filp)
1016
{
1017
        struct isi_port *port = tty->driver_data;
1018
        struct isi_board *card;
1019
        unsigned long flags;
1020
 
1021
        if (!port)
1022
                return;
1023
        card = port->card;
1024
        if (isicom_paranoia_check(port, tty->name, "isicom_close"))
1025
                return;
1026
 
1027
        pr_dbg("Close start!!!.\n");
1028
 
1029
        spin_lock_irqsave(&card->card_lock, flags);
1030
        if (tty_hung_up_p(filp)) {
1031
                spin_unlock_irqrestore(&card->card_lock, flags);
1032
                return;
1033
        }
1034
 
1035
        if (tty->count == 1 && port->count != 1) {
1036
                printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
1037
                        "count tty->count = 1 port count = %d.\n",
1038
                        card->base, port->count);
1039
                port->count = 1;
1040
        }
1041
        if (--port->count < 0) {
1042
                printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
1043
                        "count for channel%d = %d", card->base, port->channel,
1044
                        port->count);
1045
                port->count = 0;
1046
        }
1047
 
1048
        if (port->count) {
1049
                spin_unlock_irqrestore(&card->card_lock, flags);
1050
                return;
1051
        }
1052
        port->flags |= ASYNC_CLOSING;
1053
        tty->closing = 1;
1054
        spin_unlock_irqrestore(&card->card_lock, flags);
1055
 
1056
        if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1057
                tty_wait_until_sent(tty, port->closing_wait);
1058
        /* indicate to the card that no more data can be received
1059
           on this port */
1060
        spin_lock_irqsave(&card->card_lock, flags);
1061
        if (port->flags & ASYNC_INITIALIZED) {
1062
                card->port_status &= ~(1 << port->channel);
1063
                outw(card->port_status, card->base + 0x02);
1064
        }
1065
        isicom_shutdown_port(port);
1066
        spin_unlock_irqrestore(&card->card_lock, flags);
1067
 
1068
        if (tty->driver->flush_buffer)
1069
                tty->driver->flush_buffer(tty);
1070
        tty_ldisc_flush(tty);
1071
 
1072
        spin_lock_irqsave(&card->card_lock, flags);
1073
        tty->closing = 0;
1074
 
1075
        if (port->blocked_open) {
1076
                spin_unlock_irqrestore(&card->card_lock, flags);
1077
                if (port->close_delay) {
1078
                        pr_dbg("scheduling until time out.\n");
1079
                        msleep_interruptible(
1080
                                jiffies_to_msecs(port->close_delay));
1081
                }
1082
                spin_lock_irqsave(&card->card_lock, flags);
1083
                wake_up_interruptible(&port->open_wait);
1084
        }
1085
        port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
1086
        wake_up_interruptible(&port->close_wait);
1087
        spin_unlock_irqrestore(&card->card_lock, flags);
1088
}
1089
 
1090
/* write et all */
1091
static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
1092
        int count)
1093
{
1094
        struct isi_port *port = tty->driver_data;
1095
        struct isi_board *card = port->card;
1096
        unsigned long flags;
1097
        int cnt, total = 0;
1098
 
1099
        if (isicom_paranoia_check(port, tty->name, "isicom_write"))
1100
                return 0;
1101
 
1102
        if (!port->xmit_buf)
1103
                return 0;
1104
 
1105
        spin_lock_irqsave(&card->card_lock, flags);
1106
 
1107
        while(1) {
1108
                cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
1109
                                - 1, SERIAL_XMIT_SIZE - port->xmit_head));
1110
                if (cnt <= 0)
1111
                        break;
1112
 
1113
                memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
1114
                port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
1115
                        - 1);
1116
                port->xmit_cnt += cnt;
1117
                buf += cnt;
1118
                count -= cnt;
1119
                total += cnt;
1120
        }
1121
        if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
1122
                port->status |= ISI_TXOK;
1123
        spin_unlock_irqrestore(&card->card_lock, flags);
1124
        return total;
1125
}
1126
 
1127
/* put_char et all */
1128
static void isicom_put_char(struct tty_struct *tty, unsigned char ch)
1129
{
1130
        struct isi_port *port = tty->driver_data;
1131
        struct isi_board *card = port->card;
1132
        unsigned long flags;
1133
 
1134
        if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
1135
                return;
1136
 
1137
        if (!port->xmit_buf)
1138
                return;
1139
 
1140
        spin_lock_irqsave(&card->card_lock, flags);
1141
        if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
1142
                spin_unlock_irqrestore(&card->card_lock, flags);
1143
                return;
1144
        }
1145
 
1146
        port->xmit_buf[port->xmit_head++] = ch;
1147
        port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
1148
        port->xmit_cnt++;
1149
        spin_unlock_irqrestore(&card->card_lock, flags);
1150
}
1151
 
1152
/* flush_chars et all */
1153
static void isicom_flush_chars(struct tty_struct *tty)
1154
{
1155
        struct isi_port *port = tty->driver_data;
1156
 
1157
        if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
1158
                return;
1159
 
1160
        if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1161
                        !port->xmit_buf)
1162
                return;
1163
 
1164
        /* this tells the transmitter to consider this port for
1165
           data output to the card ... that's the best we can do. */
1166
        port->status |= ISI_TXOK;
1167
}
1168
 
1169
/* write_room et all */
1170
static int isicom_write_room(struct tty_struct *tty)
1171
{
1172
        struct isi_port *port = tty->driver_data;
1173
        int free;
1174
 
1175
        if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
1176
                return 0;
1177
 
1178
        free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1179
        if (free < 0)
1180
                free = 0;
1181
        return free;
1182
}
1183
 
1184
/* chars_in_buffer et all */
1185
static int isicom_chars_in_buffer(struct tty_struct *tty)
1186
{
1187
        struct isi_port *port = tty->driver_data;
1188
        if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
1189
                return 0;
1190
        return port->xmit_cnt;
1191
}
1192
 
1193
/* ioctl et all */
1194
static inline void isicom_send_break(struct isi_port *port,
1195
        unsigned long length)
1196
{
1197
        struct isi_board *card = port->card;
1198
        unsigned long base = card->base;
1199
 
1200
        if (!lock_card(card))
1201
                return;
1202
 
1203
        outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
1204
        outw((length & 0xff) << 8 | 0x00, base);
1205
        outw((length & 0xff00), base);
1206
        InterruptTheCard(base);
1207
 
1208
        unlock_card(card);
1209
}
1210
 
1211
static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
1212
{
1213
        struct isi_port *port = tty->driver_data;
1214
        /* just send the port status */
1215
        u16 status = port->status;
1216
 
1217
        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1218
                return -ENODEV;
1219
 
1220
        return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
1221
                ((status & ISI_DTR) ? TIOCM_DTR : 0) |
1222
                ((status & ISI_DCD) ? TIOCM_CAR : 0) |
1223
                ((status & ISI_DSR) ? TIOCM_DSR : 0) |
1224
                ((status & ISI_CTS) ? TIOCM_CTS : 0) |
1225
                ((status & ISI_RI ) ? TIOCM_RI  : 0);
1226
}
1227
 
1228
static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
1229
        unsigned int set, unsigned int clear)
1230
{
1231
        struct isi_port *port = tty->driver_data;
1232
        unsigned long flags;
1233
 
1234
        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1235
                return -ENODEV;
1236
 
1237
        spin_lock_irqsave(&port->card->card_lock, flags);
1238
        if (set & TIOCM_RTS)
1239
                raise_rts(port);
1240
        if (set & TIOCM_DTR)
1241
                raise_dtr(port);
1242
 
1243
        if (clear & TIOCM_RTS)
1244
                drop_rts(port);
1245
        if (clear & TIOCM_DTR)
1246
                drop_dtr(port);
1247
        spin_unlock_irqrestore(&port->card->card_lock, flags);
1248
 
1249
        return 0;
1250
}
1251
 
1252
static int isicom_set_serial_info(struct isi_port *port,
1253
        struct serial_struct __user *info)
1254
{
1255
        struct serial_struct newinfo;
1256
        int reconfig_port;
1257
 
1258
        if (copy_from_user(&newinfo, info, sizeof(newinfo)))
1259
                return -EFAULT;
1260
 
1261
        reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
1262
                (newinfo.flags & ASYNC_SPD_MASK));
1263
 
1264
        if (!capable(CAP_SYS_ADMIN)) {
1265
                if ((newinfo.close_delay != port->close_delay) ||
1266
                                (newinfo.closing_wait != port->closing_wait) ||
1267
                                ((newinfo.flags & ~ASYNC_USR_MASK) !=
1268
                                (port->flags & ~ASYNC_USR_MASK)))
1269
                        return -EPERM;
1270
                port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
1271
                                (newinfo.flags & ASYNC_USR_MASK));
1272
        }
1273
        else {
1274
                port->close_delay = newinfo.close_delay;
1275
                port->closing_wait = newinfo.closing_wait;
1276
                port->flags = ((port->flags & ~ASYNC_FLAGS) |
1277
                                (newinfo.flags & ASYNC_FLAGS));
1278
        }
1279
        if (reconfig_port) {
1280
                unsigned long flags;
1281
                spin_lock_irqsave(&port->card->card_lock, flags);
1282
                isicom_config_port(port);
1283
                spin_unlock_irqrestore(&port->card->card_lock, flags);
1284
        }
1285
        return 0;
1286
}
1287
 
1288
static int isicom_get_serial_info(struct isi_port *port,
1289
        struct serial_struct __user *info)
1290
{
1291
        struct serial_struct out_info;
1292
 
1293
        memset(&out_info, 0, sizeof(out_info));
1294
/*      out_info.type = ? */
1295
        out_info.line = port - isi_ports;
1296
        out_info.port = port->card->base;
1297
        out_info.irq = port->card->irq;
1298
        out_info.flags = port->flags;
1299
/*      out_info.baud_base = ? */
1300
        out_info.close_delay = port->close_delay;
1301
        out_info.closing_wait = port->closing_wait;
1302
        if (copy_to_user(info, &out_info, sizeof(out_info)))
1303
                return -EFAULT;
1304
        return 0;
1305
}
1306
 
1307
static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
1308
        unsigned int cmd, unsigned long arg)
1309
{
1310
        struct isi_port *port = tty->driver_data;
1311
        void __user *argp = (void __user *)arg;
1312
        int retval;
1313
 
1314
        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1315
                return -ENODEV;
1316
 
1317
        switch(cmd) {
1318
        case TCSBRK:
1319
                retval = tty_check_change(tty);
1320
                if (retval)
1321
                        return retval;
1322
                tty_wait_until_sent(tty, 0);
1323
                if (!arg)
1324
                        isicom_send_break(port, HZ/4);
1325
                return 0;
1326
 
1327
        case TCSBRKP:
1328
                retval = tty_check_change(tty);
1329
                if (retval)
1330
                        return retval;
1331
                tty_wait_until_sent(tty, 0);
1332
                isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
1333
                return 0;
1334
 
1335
        case TIOCGSOFTCAR:
1336
                return put_user(C_CLOCAL(tty) ? 1 : 0,
1337
                                (unsigned long __user *)argp);
1338
 
1339
        case TIOCSSOFTCAR:
1340
                if (get_user(arg, (unsigned long __user *) argp))
1341
                        return -EFAULT;
1342
                tty->termios->c_cflag =
1343
                        ((tty->termios->c_cflag & ~CLOCAL) |
1344
                        (arg ? CLOCAL : 0));
1345
                return 0;
1346
 
1347
        case TIOCGSERIAL:
1348
                return isicom_get_serial_info(port, argp);
1349
 
1350
        case TIOCSSERIAL:
1351
                return isicom_set_serial_info(port, argp);
1352
 
1353
        default:
1354
                return -ENOIOCTLCMD;
1355
        }
1356
        return 0;
1357
}
1358
 
1359
/* set_termios et all */
1360
static void isicom_set_termios(struct tty_struct *tty,
1361
        struct ktermios *old_termios)
1362
{
1363
        struct isi_port *port = tty->driver_data;
1364
        unsigned long flags;
1365
 
1366
        if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
1367
                return;
1368
 
1369
        if (tty->termios->c_cflag == old_termios->c_cflag &&
1370
                        tty->termios->c_iflag == old_termios->c_iflag)
1371
                return;
1372
 
1373
        spin_lock_irqsave(&port->card->card_lock, flags);
1374
        isicom_config_port(port);
1375
        spin_unlock_irqrestore(&port->card->card_lock, flags);
1376
 
1377
        if ((old_termios->c_cflag & CRTSCTS) &&
1378
                        !(tty->termios->c_cflag & CRTSCTS)) {
1379
                tty->hw_stopped = 0;
1380
                isicom_start(tty);
1381
        }
1382
}
1383
 
1384
/* throttle et all */
1385
static void isicom_throttle(struct tty_struct *tty)
1386
{
1387
        struct isi_port *port = tty->driver_data;
1388
        struct isi_board *card = port->card;
1389
 
1390
        if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
1391
                return;
1392
 
1393
        /* tell the card that this port cannot handle any more data for now */
1394
        card->port_status &= ~(1 << port->channel);
1395
        outw(card->port_status, card->base + 0x02);
1396
}
1397
 
1398
/* unthrottle et all */
1399
static void isicom_unthrottle(struct tty_struct *tty)
1400
{
1401
        struct isi_port *port = tty->driver_data;
1402
        struct isi_board *card = port->card;
1403
 
1404
        if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
1405
                return;
1406
 
1407
        /* tell the card that this port is ready to accept more data */
1408
        card->port_status |= (1 << port->channel);
1409
        outw(card->port_status, card->base + 0x02);
1410
}
1411
 
1412
/* stop et all */
1413
static void isicom_stop(struct tty_struct *tty)
1414
{
1415
        struct isi_port *port = tty->driver_data;
1416
 
1417
        if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
1418
                return;
1419
 
1420
        /* this tells the transmitter not to consider this port for
1421
           data output to the card. */
1422
        port->status &= ~ISI_TXOK;
1423
}
1424
 
1425
/* start et all */
1426
static void isicom_start(struct tty_struct *tty)
1427
{
1428
        struct isi_port *port = tty->driver_data;
1429
 
1430
        if (isicom_paranoia_check(port, tty->name, "isicom_start"))
1431
                return;
1432
 
1433
        /* this tells the transmitter to consider this port for
1434
           data output to the card. */
1435
        port->status |= ISI_TXOK;
1436
}
1437
 
1438
static void isicom_hangup(struct tty_struct *tty)
1439
{
1440
        struct isi_port *port = tty->driver_data;
1441
        unsigned long flags;
1442
 
1443
        if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
1444
                return;
1445
 
1446
        spin_lock_irqsave(&port->card->card_lock, flags);
1447
        isicom_shutdown_port(port);
1448
        spin_unlock_irqrestore(&port->card->card_lock, flags);
1449
 
1450
        port->count = 0;
1451
        port->flags &= ~ASYNC_NORMAL_ACTIVE;
1452
        port->tty = NULL;
1453
        wake_up_interruptible(&port->open_wait);
1454
}
1455
 
1456
/* flush_buffer et all */
1457
static void isicom_flush_buffer(struct tty_struct *tty)
1458
{
1459
        struct isi_port *port = tty->driver_data;
1460
        struct isi_board *card = port->card;
1461
        unsigned long flags;
1462
 
1463
        if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
1464
                return;
1465
 
1466
        spin_lock_irqsave(&card->card_lock, flags);
1467
        port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1468
        spin_unlock_irqrestore(&card->card_lock, flags);
1469
 
1470
        tty_wakeup(tty);
1471
}
1472
 
1473
/*
1474
 * Driver init and deinit functions
1475
 */
1476
 
1477
static const struct tty_operations isicom_ops = {
1478
        .open                   = isicom_open,
1479
        .close                  = isicom_close,
1480
        .write                  = isicom_write,
1481
        .put_char               = isicom_put_char,
1482
        .flush_chars            = isicom_flush_chars,
1483
        .write_room             = isicom_write_room,
1484
        .chars_in_buffer        = isicom_chars_in_buffer,
1485
        .ioctl                  = isicom_ioctl,
1486
        .set_termios            = isicom_set_termios,
1487
        .throttle               = isicom_throttle,
1488
        .unthrottle             = isicom_unthrottle,
1489
        .stop                   = isicom_stop,
1490
        .start                  = isicom_start,
1491
        .hangup                 = isicom_hangup,
1492
        .flush_buffer           = isicom_flush_buffer,
1493
        .tiocmget               = isicom_tiocmget,
1494
        .tiocmset               = isicom_tiocmset,
1495
};
1496
 
1497
static int __devinit reset_card(struct pci_dev *pdev,
1498
        const unsigned int card, unsigned int *signature)
1499
{
1500
        struct isi_board *board = pci_get_drvdata(pdev);
1501
        unsigned long base = board->base;
1502
        unsigned int sig, portcount = 0;
1503
        int retval = 0;
1504
 
1505
        dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
1506
                base);
1507
 
1508
        inw(base + 0x8);
1509
 
1510
        msleep(10);
1511
 
1512
        outw(0, base + 0x8); /* Reset */
1513
 
1514
        msleep(1000);
1515
 
1516
        sig = inw(base + 0x4) & 0xff;
1517
 
1518
        if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
1519
                        sig != 0xee) {
1520
                dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
1521
                        "bad I/O Port Address 0x%lx).\n", card + 1, base);
1522
                dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
1523
                retval = -EIO;
1524
                goto end;
1525
        }
1526
 
1527
        msleep(10);
1528
 
1529
        portcount = inw(base + 0x2);
1530
        if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 &&
1531
                                portcount != 8 && portcount != 16)) {
1532
                dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
1533
                        card + 1);
1534
                retval = -EIO;
1535
                goto end;
1536
        }
1537
 
1538
        switch (sig) {
1539
        case 0xa5:
1540
        case 0xbb:
1541
        case 0xdd:
1542
                board->port_count = (portcount == 4) ? 4 : 8;
1543
                board->shift_count = 12;
1544
                break;
1545
        case 0xcc:
1546
        case 0xee:
1547
                board->port_count = 16;
1548
                board->shift_count = 11;
1549
                break;
1550
        }
1551
        dev_info(&pdev->dev, "-Done\n");
1552
        *signature = sig;
1553
 
1554
end:
1555
        return retval;
1556
}
1557
 
1558
static int __devinit load_firmware(struct pci_dev *pdev,
1559
        const unsigned int index, const unsigned int signature)
1560
{
1561
        struct isi_board *board = pci_get_drvdata(pdev);
1562
        const struct firmware *fw;
1563
        unsigned long base = board->base;
1564
        unsigned int a;
1565
        u16 word_count, status;
1566
        int retval = -EIO;
1567
        char *name;
1568
        u8 *data;
1569
 
1570
        struct stframe {
1571
                u16     addr;
1572
                u16     count;
1573
                u8      data[0];
1574
        } *frame;
1575
 
1576
        switch (signature) {
1577
        case 0xa5:
1578
                name = "isi608.bin";
1579
                break;
1580
        case 0xbb:
1581
                name = "isi608em.bin";
1582
                break;
1583
        case 0xcc:
1584
                name = "isi616em.bin";
1585
                break;
1586
        case 0xdd:
1587
                name = "isi4608.bin";
1588
                break;
1589
        case 0xee:
1590
                name = "isi4616.bin";
1591
                break;
1592
        default:
1593
                dev_err(&pdev->dev, "Unknown signature.\n");
1594
                goto end;
1595
        }
1596
 
1597
        retval = request_firmware(&fw, name, &pdev->dev);
1598
        if (retval)
1599
                goto end;
1600
 
1601
        retval = -EIO;
1602
 
1603
        for (frame = (struct stframe *)fw->data;
1604
                        frame < (struct stframe *)(fw->data + fw->size);
1605
                        frame = (struct stframe *)((u8 *)(frame + 1) +
1606
                                frame->count)) {
1607
                if (WaitTillCardIsFree(base))
1608
                        goto errrelfw;
1609
 
1610
                outw(0xf0, base);       /* start upload sequence */
1611
                outw(0x00, base);
1612
                outw(frame->addr, base); /* lsb of address */
1613
 
1614
                word_count = frame->count / 2 + frame->count % 2;
1615
                outw(word_count, base);
1616
                InterruptTheCard(base);
1617
 
1618
                udelay(100); /* 0x2f */
1619
 
1620
                if (WaitTillCardIsFree(base))
1621
                        goto errrelfw;
1622
 
1623
                if ((status = inw(base + 0x4)) != 0) {
1624
                        dev_warn(&pdev->dev, "Card%d rejected load header:\n"
1625
                                KERN_WARNING "Address:0x%x\n"
1626
                                KERN_WARNING "Count:0x%x\n"
1627
                                KERN_WARNING "Status:0x%x\n",
1628
                                index + 1, frame->addr, frame->count, status);
1629
                        goto errrelfw;
1630
                }
1631
                outsw(base, frame->data, word_count);
1632
 
1633
                InterruptTheCard(base);
1634
 
1635
                udelay(50); /* 0x0f */
1636
 
1637
                if (WaitTillCardIsFree(base))
1638
                        goto errrelfw;
1639
 
1640
                if ((status = inw(base + 0x4)) != 0) {
1641
                        dev_err(&pdev->dev, "Card%d got out of sync.Card "
1642
                                "Status:0x%x\n", index + 1, status);
1643
                        goto errrelfw;
1644
                }
1645
        }
1646
 
1647
/* XXX: should we test it by reading it back and comparing with original like
1648
 * in load firmware package? */
1649
        for (frame = (struct stframe *)fw->data;
1650
                        frame < (struct stframe *)(fw->data + fw->size);
1651
                        frame = (struct stframe *)((u8 *)(frame + 1) +
1652
                                frame->count)) {
1653
                if (WaitTillCardIsFree(base))
1654
                        goto errrelfw;
1655
 
1656
                outw(0xf1, base); /* start download sequence */
1657
                outw(0x00, base);
1658
                outw(frame->addr, base); /* lsb of address */
1659
 
1660
                word_count = (frame->count >> 1) + frame->count % 2;
1661
                outw(word_count + 1, base);
1662
                InterruptTheCard(base);
1663
 
1664
                udelay(50); /* 0xf */
1665
 
1666
                if (WaitTillCardIsFree(base))
1667
                        goto errrelfw;
1668
 
1669
                if ((status = inw(base + 0x4)) != 0) {
1670
                        dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
1671
                                KERN_WARNING "Address:0x%x\n"
1672
                                KERN_WARNING "Count:0x%x\n"
1673
                                KERN_WARNING "Status: 0x%x\n",
1674
                                index + 1, frame->addr, frame->count, status);
1675
                        goto errrelfw;
1676
                }
1677
 
1678
                data = kmalloc(word_count * 2, GFP_KERNEL);
1679
                if (data == NULL) {
1680
                        dev_err(&pdev->dev, "Card%d, firmware upload "
1681
                                "failed, not enough memory\n", index + 1);
1682
                        goto errrelfw;
1683
                }
1684
                inw(base);
1685
                insw(base, data, word_count);
1686
                InterruptTheCard(base);
1687
 
1688
                for (a = 0; a < frame->count; a++)
1689
                        if (data[a] != frame->data[a]) {
1690
                                kfree(data);
1691
                                dev_err(&pdev->dev, "Card%d, firmware upload "
1692
                                        "failed\n", index + 1);
1693
                                goto errrelfw;
1694
                        }
1695
                kfree(data);
1696
 
1697
                udelay(50); /* 0xf */
1698
 
1699
                if (WaitTillCardIsFree(base))
1700
                        goto errrelfw;
1701
 
1702
                if ((status = inw(base + 0x4)) != 0) {
1703
                        dev_err(&pdev->dev, "Card%d verify got out of sync. "
1704
                                "Card Status:0x%x\n", index + 1, status);
1705
                        goto errrelfw;
1706
                }
1707
        }
1708
 
1709
        /* xfer ctrl */
1710
        if (WaitTillCardIsFree(base))
1711
                goto errrelfw;
1712
 
1713
        outw(0xf2, base);
1714
        outw(0x800, base);
1715
        outw(0x0, base);
1716
        outw(0x0, base);
1717
        InterruptTheCard(base);
1718
        outw(0x0, base + 0x4); /* for ISI4608 cards */
1719
 
1720
        board->status |= FIRMWARE_LOADED;
1721
        retval = 0;
1722
 
1723
errrelfw:
1724
        release_firmware(fw);
1725
end:
1726
        return retval;
1727
}
1728
 
1729
/*
1730
 *      Insmod can set static symbols so keep these static
1731
 */
1732
static unsigned int card_count;
1733
 
1734
static int __devinit isicom_probe(struct pci_dev *pdev,
1735
        const struct pci_device_id *ent)
1736
{
1737
        unsigned int signature, index;
1738
        int retval = -EPERM;
1739
        struct isi_board *board = NULL;
1740
 
1741
        if (card_count >= BOARD_COUNT)
1742
                goto err;
1743
 
1744
        dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
1745
 
1746
        /* allot the first empty slot in the array */
1747
        for (index = 0; index < BOARD_COUNT; index++)
1748
                if (isi_card[index].base == 0) {
1749
                        board = &isi_card[index];
1750
                        break;
1751
                }
1752
 
1753
        board->index = index;
1754
        board->base = pci_resource_start(pdev, 3);
1755
        board->irq = pdev->irq;
1756
        card_count++;
1757
 
1758
        pci_set_drvdata(pdev, board);
1759
 
1760
        retval = pci_request_region(pdev, 3, ISICOM_NAME);
1761
        if (retval) {
1762
                dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
1763
                        "will be disabled.\n", board->base, board->base + 15,
1764
                        index + 1);
1765
                retval = -EBUSY;
1766
                goto errdec;
1767
        }
1768
 
1769
        retval = request_irq(board->irq, isicom_interrupt,
1770
                        IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
1771
        if (retval < 0) {
1772
                dev_err(&pdev->dev, "Could not install handler at Irq %d. "
1773
                        "Card%d will be disabled.\n", board->irq, index + 1);
1774
                goto errunrr;
1775
        }
1776
 
1777
        retval = reset_card(pdev, index, &signature);
1778
        if (retval < 0)
1779
                goto errunri;
1780
 
1781
        retval = load_firmware(pdev, index, signature);
1782
        if (retval < 0)
1783
                goto errunri;
1784
 
1785
        for (index = 0; index < board->port_count; index++)
1786
                tty_register_device(isicom_normal, board->index * 16 + index,
1787
                                &pdev->dev);
1788
 
1789
        return 0;
1790
 
1791
errunri:
1792
        free_irq(board->irq, board);
1793
errunrr:
1794
        pci_release_region(pdev, 3);
1795
errdec:
1796
        board->base = 0;
1797
        card_count--;
1798
err:
1799
        return retval;
1800
}
1801
 
1802
static void __devexit isicom_remove(struct pci_dev *pdev)
1803
{
1804
        struct isi_board *board = pci_get_drvdata(pdev);
1805
        unsigned int i;
1806
 
1807
        for (i = 0; i < board->port_count; i++)
1808
                tty_unregister_device(isicom_normal, board->index * 16 + i);
1809
 
1810
        free_irq(board->irq, board);
1811
        pci_release_region(pdev, 3);
1812
        board->base = 0;
1813
        card_count--;
1814
}
1815
 
1816
static int __init isicom_init(void)
1817
{
1818
        int retval, idx, channel;
1819
        struct isi_port *port;
1820
 
1821
        for(idx = 0; idx < BOARD_COUNT; idx++) {
1822
                port = &isi_ports[idx * 16];
1823
                isi_card[idx].ports = port;
1824
                spin_lock_init(&isi_card[idx].card_lock);
1825
                for (channel = 0; channel < 16; channel++, port++) {
1826
                        port->magic = ISICOM_MAGIC;
1827
                        port->card = &isi_card[idx];
1828
                        port->channel = channel;
1829
                        port->close_delay = 50 * HZ/100;
1830
                        port->closing_wait = 3000 * HZ/100;
1831
                        port->status = 0;
1832
                        init_waitqueue_head(&port->open_wait);
1833
                        init_waitqueue_head(&port->close_wait);
1834
                        /*  . . .  */
1835
                }
1836
                isi_card[idx].base = 0;
1837
                isi_card[idx].irq = 0;
1838
        }
1839
 
1840
        /* tty driver structure initialization */
1841
        isicom_normal = alloc_tty_driver(PORT_COUNT);
1842
        if (!isicom_normal) {
1843
                retval = -ENOMEM;
1844
                goto error;
1845
        }
1846
 
1847
        isicom_normal->owner                    = THIS_MODULE;
1848
        isicom_normal->name                     = "ttyM";
1849
        isicom_normal->major                    = ISICOM_NMAJOR;
1850
        isicom_normal->minor_start              = 0;
1851
        isicom_normal->type                     = TTY_DRIVER_TYPE_SERIAL;
1852
        isicom_normal->subtype                  = SERIAL_TYPE_NORMAL;
1853
        isicom_normal->init_termios             = tty_std_termios;
1854
        isicom_normal->init_termios.c_cflag     = B9600 | CS8 | CREAD | HUPCL |
1855
                CLOCAL;
1856
        isicom_normal->flags                    = TTY_DRIVER_REAL_RAW |
1857
                TTY_DRIVER_DYNAMIC_DEV;
1858
        tty_set_operations(isicom_normal, &isicom_ops);
1859
 
1860
        retval = tty_register_driver(isicom_normal);
1861
        if (retval) {
1862
                pr_dbg("Couldn't register the dialin driver\n");
1863
                goto err_puttty;
1864
        }
1865
 
1866
        retval = pci_register_driver(&isicom_driver);
1867
        if (retval < 0) {
1868
                printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
1869
                goto err_unrtty;
1870
        }
1871
 
1872
        mod_timer(&tx, jiffies + 1);
1873
 
1874
        return 0;
1875
err_unrtty:
1876
        tty_unregister_driver(isicom_normal);
1877
err_puttty:
1878
        put_tty_driver(isicom_normal);
1879
error:
1880
        return retval;
1881
}
1882
 
1883
static void __exit isicom_exit(void)
1884
{
1885
        del_timer_sync(&tx);
1886
 
1887
        pci_unregister_driver(&isicom_driver);
1888
        tty_unregister_driver(isicom_normal);
1889
        put_tty_driver(isicom_normal);
1890
}
1891
 
1892
module_init(isicom_init);
1893
module_exit(isicom_exit);
1894
 
1895
MODULE_AUTHOR("MultiTech");
1896
MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
1897
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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