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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [mxser.c] - Blame information for rev 1774

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

Line No. Rev Author Line
1 1275 phoenix
/*****************************************************************************/
2
/*
3
 *          mxser.c  -- MOXA Smartio family multiport serial driver.
4
 *
5
 *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com.tw).
6
 *
7
 *      This code is loosely based on the Linux serial driver, written by
8
 *      Linus Torvalds, Theodore T'so and others.
9
 *
10
 *      This program is free software; you can redistribute it and/or modify
11
 *      it under the terms of the GNU General Public License as published by
12
 *      the Free Software Foundation; either version 2 of the License, or
13
 *      (at your option) any later version.
14
 *
15
 *      This program is distributed in the hope that it will be useful,
16
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *      GNU General Public License for more details.
19
 *
20
 *      You should have received a copy of the GNU General Public License
21
 *      along with this program; if not, write to the Free Software
22
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
 */
24
 
25
/*
26
 *    MOXA Smartio Family Serial Driver
27
 *
28
 *      Copyright (C) 1999,2000  Moxa Technologies Co., LTD.
29
 *
30
 *      for             : LINUX 2.0.X, 2.2.X, 2.4.X
31
 *      date            : 2001/05/01
32
 *      version         : 1.2
33
 *
34
 *    Fixes for C104H/PCI by Tim Hockin <thockin@sun.com>
35
 *    Added support for: C102, CI-132, CI-134, CP-132, CP-114, CT-114 cards
36
 *                        by Damian Wrobel <dwrobel@ertel.com.pl>
37
 *
38
 */
39
 
40
#include <linux/config.h>
41
#include <linux/module.h>
42
#include <linux/version.h>
43
#include <linux/errno.h>
44
#include <linux/signal.h>
45
#include <linux/sched.h>
46
#include <linux/timer.h>
47
#include <linux/interrupt.h>
48
#include <linux/tty.h>
49
#include <linux/tty_flip.h>
50
#include <linux/serial.h>
51
#include <linux/serial_reg.h>
52
#include <linux/major.h>
53
#include <linux/string.h>
54
#include <linux/fcntl.h>
55
#include <linux/ptrace.h>
56
#include <linux/ioport.h>
57
#include <linux/mm.h>
58
#include <linux/smp_lock.h>
59
#include <linux/pci.h>
60
 
61
#include <asm/system.h>
62
#include <asm/io.h>
63
#include <asm/irq.h>
64
#include <asm/segment.h>
65
#include <asm/bitops.h>
66
#include <asm/uaccess.h>
67
 
68
#define         MXSER_VERSION                   "1.2.1"
69
 
70
#define         MXSERMAJOR              174
71
#define         MXSERCUMAJOR            175
72
 
73
 
74
#define MXSER_EVENT_TXLOW        1
75
#define MXSER_EVENT_HANGUP       2
76
 
77
 
78
#define         SERIAL_DO_RESTART
79
 
80
#define         MXSER_BOARDS            4       /* Max. boards */
81
#define         MXSER_PORTS             32      /* Max. ports */
82
#define         MXSER_PORTS_PER_BOARD   8       /* Max. ports per board */
83
#define         MXSER_ISR_PASS_LIMIT    256
84
 
85
#define         MXSER_ERR_IOADDR        -1
86
#define         MXSER_ERR_IRQ           -2
87
#define         MXSER_ERR_IRQ_CONFLIT   -3
88
#define         MXSER_ERR_VECTOR        -4
89
 
90
#define         SERIAL_TYPE_NORMAL      1
91
#define         SERIAL_TYPE_CALLOUT     2
92
 
93
#define         WAKEUP_CHARS            256
94
 
95
#define         UART_MCR_AFE            0x20
96
#define         UART_LSR_SPECIAL        0x1E
97
 
98
#define PORTNO(x)               (MINOR((x)->device) - (x)->driver.minor_start)
99
 
100
#define RELEVANT_IFLAG(iflag)   (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
101
 
102
#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
103
 
104
#ifndef MIN
105
#define MIN(a,b)        ((a) < (b) ? (a) : (b))
106
#endif
107
 
108
/*
109
 *    Define the Moxa PCI vendor and device IDs.
110
 */
111
 
112
#ifndef PCI_VENDOR_ID_MOXA
113
#define PCI_VENDOR_ID_MOXA      0x1393
114
#endif
115
#ifndef PCI_DEVICE_ID_C168
116
#define PCI_DEVICE_ID_C168      0x1680
117
#endif
118
#ifndef PCI_DEVICE_ID_C104
119
#define PCI_DEVICE_ID_C104      0x1040
120
#endif
121
#ifndef PCI_DEVICE_ID_CP132
122
#define PCI_DEVICE_ID_CP132     0x1320
123
#endif
124
#ifndef PCI_DEVICE_ID_CP114
125
#define PCI_DEVICE_ID_CP114     0x1141
126
#endif
127
#ifndef PCI_DEVICE_ID_CT114
128
#define PCI_DEVICE_ID_CT114     0x1140
129
#endif
130
 
131
#define C168_ASIC_ID    1
132
#define C104_ASIC_ID    2
133
#define CI134_ASIC_ID   3
134
#define CI132_ASIC_ID   4
135
#define CI104J_ASIC_ID  5
136
#define C102_ASIC_ID    0xB
137
 
138
enum {
139
        MXSER_BOARD_C168_ISA = 0,
140
        MXSER_BOARD_C104_ISA,
141
        MXSER_BOARD_CI104J,
142
        MXSER_BOARD_C168_PCI,
143
        MXSER_BOARD_C104_PCI,
144
        MXSER_BOARD_C102_ISA,
145
        MXSER_BOARD_CI132,
146
        MXSER_BOARD_CI134,
147
        MXSER_BOARD_CP132_PCI,
148
        MXSER_BOARD_CP114_PCI,
149
        MXSER_BOARD_CT114_PCI
150
};
151
 
152
static char *mxser_brdname[] =
153
{
154
        "C168 series",
155
        "C104 series",
156
        "CI-104J series",
157
        "C168H/PCI series",
158
        "C104H/PCI series",
159
        "C102 series",
160
        "CI-132 series",
161
        "CI-134 series",
162
        "CP-132 series",
163
        "CP-114 series",
164
        "CT-114 series"
165
};
166
 
167
static int mxser_numports[] =
168
{
169
        8,
170
        4,
171
        4,
172
        8,
173
        4,
174
        2,
175
        2,
176
        4,
177
        2,
178
        4,
179
        4
180
};
181
 
182
/*
183
 *    MOXA ioctls
184
 */
185
#define         MOXA            0x400
186
#define         MOXA_GETDATACOUNT     (MOXA + 23)
187
#define         MOXA_GET_CONF         (MOXA + 35)
188
#define         MOXA_DIAGNOSE         (MOXA + 50)
189
#define         MOXA_CHKPORTENABLE    (MOXA + 60)
190
#define         MOXA_HighSpeedOn      (MOXA + 61)
191
#define         MOXA_GET_MAJOR        (MOXA + 63)
192
#define         MOXA_GET_CUMAJOR      (MOXA + 64)
193
#define         MOXA_GETMSTATUS       (MOXA + 65)
194
 
195
static struct pci_device_id mxser_pcibrds[] = {
196
        { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C168, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
197
          MXSER_BOARD_C168_PCI },
198
        { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C104, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
199
          MXSER_BOARD_C104_PCI },
200
        { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP132, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
201
          MXSER_BOARD_CP132_PCI },
202
        { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP114, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
203
          MXSER_BOARD_CP114_PCI },
204
        { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CT114, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
205
          MXSER_BOARD_CT114_PCI },
206
        { 0 }
207
};
208
MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
209
 
210
static int ioaddr[MXSER_BOARDS];
211
static int ttymajor = MXSERMAJOR;
212
static int calloutmajor = MXSERCUMAJOR;
213
static int verbose;
214
 
215
/* Variables for insmod */
216
 
217
MODULE_AUTHOR("William Chen");
218
MODULE_DESCRIPTION("MOXA Smartio Family Multiport Board Device Driver");
219
MODULE_LICENSE("GPL");
220
MODULE_PARM(ioaddr, "1-4i");
221
MODULE_PARM(ttymajor, "i");
222
MODULE_PARM(calloutmajor, "i");
223
MODULE_PARM(verbose, "i");
224
 
225
EXPORT_NO_SYMBOLS;
226
 
227
struct mxser_hwconf {
228
        int board_type;
229
        int ports;
230
        int irq;
231
        int vector;
232
        int vector_mask;
233
        int uart_type;
234
        int ioaddr[MXSER_PORTS_PER_BOARD];
235
        int baud_base[MXSER_PORTS_PER_BOARD];
236
        struct pci_dev *pdev;
237
};
238
 
239
struct mxser_struct {
240
        int port;
241
        int base;               /* port base address */
242
        int irq;                /* port using irq no. */
243
        int vector;             /* port irq vector */
244
        int vectormask;         /* port vector mask */
245
        int rx_trigger;         /* Rx fifo trigger level */
246
        int baud_base;          /* max. speed */
247
        int flags;              /* defined in tty.h */
248
        int type;               /* UART type */
249
        struct tty_struct *tty;
250
        int read_status_mask;
251
        int ignore_status_mask;
252
        int xmit_fifo_size;
253
        int custom_divisor;
254
        int x_char;             /* xon/xoff character */
255
        int close_delay;
256
        unsigned short closing_wait;
257
        int IER;                /* Interrupt Enable Register */
258
        int MCR;                /* Modem control register */
259
        unsigned long event;
260
        int count;              /* # of fd on device */
261
        int blocked_open;       /* # of blocked opens */
262
        long session;           /* Session of opening process */
263
        long pgrp;              /* pgrp of opening process */
264
        unsigned char *xmit_buf;
265
        int xmit_head;
266
        int xmit_tail;
267
        int xmit_cnt;
268
        struct tq_struct tqueue;
269
        struct termios normal_termios;
270
        struct termios callout_termios;
271
        wait_queue_head_t open_wait;
272
        wait_queue_head_t close_wait;
273
        wait_queue_head_t delta_msr_wait;
274
        struct async_icount icount;     /* kernel counters for the 4 input interrupts */
275
};
276
 
277
struct mxser_log {
278
        int tick;
279
        int rxcnt[MXSER_PORTS];
280
        int txcnt[MXSER_PORTS];
281
};
282
 
283
struct mxser_mstatus {
284
        tcflag_t cflag;
285
        int cts;
286
        int dsr;
287
        int ri;
288
        int dcd;
289
};
290
 
291
static struct mxser_mstatus GMStatus[MXSER_PORTS];
292
 
293
static int mxserBoardCAP[MXSER_BOARDS] =
294
{
295
        0, 0, 0, 0
296
       /*  0x180, 0x280, 0x200, 0x320   */
297
};
298
 
299
 
300
static struct tty_driver mxvar_sdriver, mxvar_cdriver;
301
static int mxvar_refcount;
302
static struct mxser_struct mxvar_table[MXSER_PORTS];
303
static struct tty_struct *mxvar_tty[MXSER_PORTS + 1];
304
static struct termios *mxvar_termios[MXSER_PORTS + 1];
305
static struct termios *mxvar_termios_locked[MXSER_PORTS + 1];
306
static struct mxser_log mxvar_log;
307
static int mxvar_diagflag;
308
/*
309
 * mxvar_tmp_buf is used as a temporary buffer by serial_write. We need
310
 * to lock it in case the memcpy_fromfs blocks while swapping in a page,
311
 * and some other program tries to do a serial write at the same time.
312
 * Since the lock will only come under contention when the system is
313
 * swapping and available memory is low, it makes sense to share one
314
 * buffer across all the serial ports, since it significantly saves
315
 * memory if large numbers of serial ports are open.
316
 */
317
static unsigned char *mxvar_tmp_buf;
318
static struct semaphore mxvar_tmp_buf_sem;
319
 
320
/*
321
 * This is used to figure out the divisor speeds and the timeouts
322
 */
323
static int mxvar_baud_table[] =
324
{
325
        0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
326
        9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 0};
327
 
328
struct mxser_hwconf mxsercfg[MXSER_BOARDS];
329
 
330
/*
331
 * static functions:
332
 */
333
 
334
#ifdef MODULE
335
int init_module(void);
336
void cleanup_module(void);
337
#endif
338
 
339
static void mxser_getcfg(int board, struct mxser_hwconf *hwconf);
340
int mxser_init(void);
341
static int mxser_get_ISA_conf(int, struct mxser_hwconf *);
342
static int mxser_get_PCI_conf(struct pci_dev *, int, struct mxser_hwconf *);
343
static void mxser_do_softint(void *);
344
static int mxser_open(struct tty_struct *, struct file *);
345
static void mxser_close(struct tty_struct *, struct file *);
346
static int mxser_write(struct tty_struct *, int, const unsigned char *, int);
347
static int mxser_write_room(struct tty_struct *);
348
static void mxser_flush_buffer(struct tty_struct *);
349
static int mxser_chars_in_buffer(struct tty_struct *);
350
static void mxser_flush_chars(struct tty_struct *);
351
static void mxser_put_char(struct tty_struct *, unsigned char);
352
static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);
353
static int mxser_ioctl_special(unsigned int, unsigned long);
354
static void mxser_throttle(struct tty_struct *);
355
static void mxser_unthrottle(struct tty_struct *);
356
static void mxser_set_termios(struct tty_struct *, struct termios *);
357
static void mxser_stop(struct tty_struct *);
358
static void mxser_start(struct tty_struct *);
359
static void mxser_hangup(struct tty_struct *);
360
static void mxser_interrupt(int, void *, struct pt_regs *);
361
static inline void mxser_receive_chars(struct mxser_struct *, int *);
362
static inline void mxser_transmit_chars(struct mxser_struct *);
363
static inline void mxser_check_modem_status(struct mxser_struct *, int);
364
static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
365
static int mxser_startup(struct mxser_struct *);
366
static void mxser_shutdown(struct mxser_struct *);
367
static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios);
368
static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct *);
369
static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);
370
static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *);
371
static void mxser_send_break(struct mxser_struct *, int);
372
static int mxser_get_modem_info(struct mxser_struct *, unsigned int *);
373
static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);
374
 
375
/*
376
 * The MOXA C168/C104 serial driver boot-time initialization code!
377
 */
378
 
379
 
380
#ifdef MODULE
381
int init_module(void)
382
{
383
        int ret;
384
 
385
        if (verbose)
386
                printk("Loading module mxser ...\n");
387
        ret = mxser_init();
388
        if (verbose)
389
                printk("Done.\n");
390
        return (ret);
391
}
392
 
393
void cleanup_module(void)
394
{
395
        int i, err = 0;
396
 
397
 
398
        if (verbose)
399
                printk("Unloading module mxser ...\n");
400
        if ((err |= tty_unregister_driver(&mxvar_cdriver)))
401
                printk("Couldn't unregister MOXA Smartio family callout driver\n");
402
        if ((err |= tty_unregister_driver(&mxvar_sdriver)))
403
                printk("Couldn't unregister MOXA Smartio family serial driver\n");
404
 
405
        for (i = 0; i < MXSER_BOARDS; i++) {
406
                if (mxsercfg[i].board_type == -1)
407
                        continue;
408
                else {
409
                        free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);
410
                }
411
        }
412
 
413
        if (verbose)
414
                printk("Done.\n");
415
 
416
}
417
#endif
418
 
419
 
420
int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
421
{
422
        struct mxser_struct *info;
423
        unsigned long flags;
424
        int retval;
425
        int i, n;
426
 
427
        init_MUTEX(&mxvar_tmp_buf_sem);
428
 
429
        n = board * MXSER_PORTS_PER_BOARD;
430
        info = &mxvar_table[n];
431
        for (i = 0; i < hwconf->ports; i++, n++, info++) {
432
                if (verbose) {
433
                        printk("        ttyM%d/cum%d at 0x%04x ", n, n, hwconf->ioaddr[i]);
434
                        if (hwconf->baud_base[i] == 115200)
435
                                printk(" max. baud rate up to 115200 bps.\n");
436
                        else
437
                                printk(" max. baud rate up to 921600 bps.\n");
438
                }
439
                info->port = n;
440
                info->base = hwconf->ioaddr[i];
441
                info->irq = hwconf->irq;
442
                info->vector = hwconf->vector;
443
                info->vectormask = hwconf->vector_mask;
444
                info->rx_trigger = 14;
445
                info->baud_base = hwconf->baud_base[i];
446
                info->flags = ASYNC_SHARE_IRQ;
447
                info->type = hwconf->uart_type;
448
                if ((info->type == PORT_16450) || (info->type == PORT_8250))
449
                        info->xmit_fifo_size = 1;
450
                else
451
                        info->xmit_fifo_size = 16;
452
                info->custom_divisor = hwconf->baud_base[i] * 16;
453
                info->close_delay = 5 * HZ / 10;
454
                info->closing_wait = 30 * HZ;
455
                info->tqueue.routine = mxser_do_softint;
456
                info->tqueue.data = info;
457
                info->callout_termios = mxvar_cdriver.init_termios;
458
                info->normal_termios = mxvar_sdriver.init_termios;
459
                init_waitqueue_head(&info->open_wait);
460
                init_waitqueue_head(&info->close_wait);
461
                init_waitqueue_head(&info->delta_msr_wait);
462
        }
463
 
464
        /*
465
         * Allocate the IRQ if necessary
466
         */
467
        save_flags(flags);
468
 
469
        n = board * MXSER_PORTS_PER_BOARD;
470
        info = &mxvar_table[n];
471
 
472
        cli();
473
        retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info),
474
                             "mxser", info);
475
        if (retval) {
476
                restore_flags(flags);
477
                printk("Board %d: %s", board, mxser_brdname[hwconf->board_type]);
478
                printk("  Request irq fail,IRQ (%d) may be conflit with another device.\n", info->irq);
479
                return (retval);
480
        }
481
        restore_flags(flags);
482
 
483
        return 0;
484
}
485
 
486
 
487
static void mxser_getcfg(int board, struct mxser_hwconf *hwconf)
488
{
489
        mxsercfg[board] = *hwconf;
490
}
491
 
492
static int mxser_get_PCI_conf(struct pci_dev *pdev, int board_type, struct mxser_hwconf *hwconf)
493
{
494
        int i;
495
        unsigned int ioaddress;
496
 
497
        hwconf->board_type = board_type;
498
        hwconf->ports = mxser_numports[board_type];
499
        ioaddress = pci_resource_start (pdev, 2);
500
        for (i = 0; i < hwconf->ports; i++)
501
                hwconf->ioaddr[i] = ioaddress + 8 * i;
502
 
503
        ioaddress = pci_resource_start (pdev, 3);
504
        hwconf->vector = ioaddress;
505
 
506
        hwconf->irq = pdev->irq;
507
 
508
        hwconf->uart_type = PORT_16550A;
509
        hwconf->vector_mask = 0;
510
        for (i = 0; i < hwconf->ports; i++) {
511
                hwconf->vector_mask |= (1 << i);
512
                hwconf->baud_base[i] = 921600;
513
        }
514
        return (0);
515
}
516
 
517
int mxser_init(void)
518
{
519
        int i, m, retval, b;
520
        int n, index;
521
        int ret1, ret2;
522
        struct mxser_hwconf hwconf;
523
 
524
        printk("MOXA Smartio family driver version %s\n", MXSER_VERSION);
525
 
526
        /* Initialize the tty_driver structure */
527
 
528
        memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));
529
        mxvar_sdriver.magic = TTY_DRIVER_MAGIC;
530
        mxvar_sdriver.name = "ttyM";
531
        mxvar_sdriver.major = ttymajor;
532
        mxvar_sdriver.minor_start = 0;
533
        mxvar_sdriver.num = MXSER_PORTS + 1;
534
        mxvar_sdriver.type = TTY_DRIVER_TYPE_SERIAL;
535
        mxvar_sdriver.subtype = SERIAL_TYPE_NORMAL;
536
        mxvar_sdriver.init_termios = tty_std_termios;
537
        mxvar_sdriver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
538
        mxvar_sdriver.flags = TTY_DRIVER_REAL_RAW;
539
        mxvar_sdriver.refcount = &mxvar_refcount;
540
        mxvar_sdriver.table = mxvar_tty;
541
        mxvar_sdriver.termios = mxvar_termios;
542
        mxvar_sdriver.termios_locked = mxvar_termios_locked;
543
 
544
        mxvar_sdriver.open = mxser_open;
545
        mxvar_sdriver.close = mxser_close;
546
        mxvar_sdriver.write = mxser_write;
547
        mxvar_sdriver.put_char = mxser_put_char;
548
        mxvar_sdriver.flush_chars = mxser_flush_chars;
549
        mxvar_sdriver.write_room = mxser_write_room;
550
        mxvar_sdriver.chars_in_buffer = mxser_chars_in_buffer;
551
        mxvar_sdriver.flush_buffer = mxser_flush_buffer;
552
        mxvar_sdriver.ioctl = mxser_ioctl;
553
        mxvar_sdriver.throttle = mxser_throttle;
554
        mxvar_sdriver.unthrottle = mxser_unthrottle;
555
        mxvar_sdriver.set_termios = mxser_set_termios;
556
        mxvar_sdriver.stop = mxser_stop;
557
        mxvar_sdriver.start = mxser_start;
558
        mxvar_sdriver.hangup = mxser_hangup;
559
 
560
        /*
561
         * The callout device is just like normal device except for
562
         * major number and the subtype code.
563
         */
564
        mxvar_cdriver = mxvar_sdriver;
565
        mxvar_cdriver.name = "cum";
566
        mxvar_cdriver.major = calloutmajor;
567
        mxvar_cdriver.subtype = SERIAL_TYPE_CALLOUT;
568
 
569
        printk("Tty devices major number = %d, callout devices major number = %d\n", ttymajor, calloutmajor);
570
 
571
        mxvar_diagflag = 0;
572
        memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct));
573
        memset(&mxvar_log, 0, sizeof(struct mxser_log));
574
 
575
 
576
        m = 0;
577
        /* Start finding ISA boards here */
578
        for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
579
                int cap;
580
                if (!(cap = mxserBoardCAP[b]))
581
                        continue;
582
 
583
                retval = mxser_get_ISA_conf(cap, &hwconf);
584
 
585
                if (retval != 0)
586
                        printk("Found MOXA %s board (CAP=0x%x)\n",
587
                               mxser_brdname[hwconf.board_type],
588
                               ioaddr[b]);
589
 
590
                if (retval <= 0) {
591
                        if (retval == MXSER_ERR_IRQ)
592
                                printk("Invalid interrupt number,board not configured\n");
593
                        else if (retval == MXSER_ERR_IRQ_CONFLIT)
594
                                printk("Invalid interrupt number,board not configured\n");
595
                        else if (retval == MXSER_ERR_VECTOR)
596
                                printk("Invalid interrupt vector,board not configured\n");
597
                        else if (retval == MXSER_ERR_IOADDR)
598
                                printk("Invalid I/O address,board not configured\n");
599
 
600
                        continue;
601
                }
602
                hwconf.pdev = NULL;
603
 
604
                if (mxser_initbrd(m, &hwconf) < 0)
605
                        continue;
606
 
607
                mxser_getcfg(m, &hwconf);
608
 
609
                m++;
610
        }
611
 
612
        /* Start finding ISA boards from module arg */
613
        for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
614
                int cap;
615
                if (!(cap = ioaddr[b]))
616
                        continue;
617
 
618
                retval = mxser_get_ISA_conf(cap, &hwconf);
619
 
620
                if (retval != 0)
621
                        printk("Found MOXA %s board (CAP=0x%x)\n",
622
                               mxser_brdname[hwconf.board_type],
623
                               ioaddr[b]);
624
 
625
                if (retval <= 0) {
626
                        if (retval == MXSER_ERR_IRQ)
627
                                printk("Invalid interrupt number,board not configured\n");
628
                        else if (retval == MXSER_ERR_IRQ_CONFLIT)
629
                                printk("Invalid interrupt number,board not configured\n");
630
                        else if (retval == MXSER_ERR_VECTOR)
631
                                printk("Invalid interrupt vector,board not configured\n");
632
                        else if (retval == MXSER_ERR_IOADDR)
633
                                printk("Invalid I/O address,board not configured\n");
634
 
635
                        continue;
636
                }
637
                hwconf.pdev = NULL;
638
 
639
                if (mxser_initbrd(m, &hwconf) < 0)
640
                        continue;
641
 
642
                mxser_getcfg(m, &hwconf);
643
 
644
                m++;
645
        }
646
 
647
        /* start finding PCI board here */
648
 
649
#ifdef CONFIG_PCI
650
        {
651
                struct pci_dev *pdev = NULL;
652
 
653
                n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1;
654
                index = 0;
655
                for (b = 0; b < n; b++) {
656
                        while ((pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev)) != NULL)
657
                        {
658
                                if (pci_enable_device(pdev))
659
                                        continue;
660
                                hwconf.pdev = pdev;
661
                                printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
662
                                        mxser_brdname[mxser_pcibrds[b].driver_data],
663
                                pdev->bus->number, PCI_SLOT(pdev->devfn));
664
                                if (m >= MXSER_BOARDS) {
665
                                        printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS);
666
                                } else {
667
                                        retval = mxser_get_PCI_conf(pdev, mxser_pcibrds[b].driver_data, &hwconf);
668
                                        if (retval < 0) {
669
                                                if (retval == MXSER_ERR_IRQ)
670
                                                        printk("Invalid interrupt number,board not configured\n");
671
                                                else if (retval == MXSER_ERR_IRQ_CONFLIT)
672
                                                        printk("Invalid interrupt number,board not configured\n");
673
                                                else if (retval == MXSER_ERR_VECTOR)
674
                                                        printk("Invalid interrupt vector,board not configured\n");
675
                                                else if (retval == MXSER_ERR_IOADDR)
676
                                                        printk("Invalid I/O address,board not configured\n");
677
                                                continue;
678
                                        }
679
                                        if (mxser_initbrd(m, &hwconf) < 0)
680
                                                continue;
681
                                        mxser_getcfg(m, &hwconf);
682
                                        m++;
683
                                }
684
                        }
685
                }
686
        }
687
#endif
688
 
689
        for (i = m; i < MXSER_BOARDS; i++) {
690
                mxsercfg[i].board_type = -1;
691
        }
692
 
693
 
694
        ret1 = 0;
695
        ret2 = 0;
696
        if (!(ret1 = tty_register_driver(&mxvar_sdriver))) {
697
                if (!(ret2 = tty_register_driver(&mxvar_cdriver))) {
698
                        return 0;
699
                } else {
700
                        tty_unregister_driver(&mxvar_sdriver);
701
                        printk("Couldn't install MOXA Smartio family callout driver !\n");
702
                }
703
        } else
704
                printk("Couldn't install MOXA Smartio family driver !\n");
705
 
706
 
707
        if (ret1 || ret2) {
708
                for (i = 0; i < MXSER_BOARDS; i++) {
709
                        if (mxsercfg[i].board_type == -1)
710
                                continue;
711
                        else {
712
                                free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);
713
                        }
714
                }
715
                return -1;
716
        }
717
        return (0);
718
}
719
 
720
static void mxser_do_softint(void *private_)
721
{
722
        struct mxser_struct *info = (struct mxser_struct *) private_;
723
        struct tty_struct *tty;
724
 
725
        tty = info->tty;
726
        if (tty) {
727
                if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
728
                        if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
729
                            tty->ldisc.write_wakeup)
730
                                (tty->ldisc.write_wakeup) (tty);
731
                        wake_up_interruptible(&tty->write_wait);
732
                }
733
                if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {
734
                        tty_hangup(tty);        /* FIXME: module removal race here - AKPM */
735
                }
736
        }
737
        MOD_DEC_USE_COUNT;
738
}
739
 
740
/*
741
 * This routine is called whenever a serial port is opened.  It
742
 * enables interrupts for a serial port, linking in its async structure into
743
 * the IRQ chain.   It also performs the serial-specific
744
 * initialization for the tty structure.
745
 */
746
 
747
static int mxser_open(struct tty_struct *tty, struct file *filp)
748
{
749
        struct mxser_struct *info;
750
        int retval, line;
751
        unsigned long page;
752
 
753
        line = PORTNO(tty);
754
        if (line == MXSER_PORTS)
755
                return (0);
756
        if ((line < 0) || (line > MXSER_PORTS))
757
                return (-ENODEV);
758
        info = mxvar_table + line;
759
        if (!info->base)
760
                return (-ENODEV);
761
 
762
        info->count++;
763
        tty->driver_data = info;
764
        info->tty = tty;
765
 
766
        if (!mxvar_tmp_buf) {
767
                page = get_free_page(GFP_KERNEL);
768
                if (!page)
769
                        return (-ENOMEM);
770
                if (mxvar_tmp_buf)
771
                        free_page(page);
772
                else
773
                        mxvar_tmp_buf = (unsigned char *) page;
774
        }
775
        /*
776
         * Start up serial port
777
         */
778
        retval = mxser_startup(info);
779
        if (retval)
780
                return (retval);
781
 
782
        retval = mxser_block_til_ready(tty, filp, info);
783
        if (retval)
784
                return (retval);
785
 
786
        if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
787
                if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
788
                        *tty->termios = info->normal_termios;
789
                else
790
                        *tty->termios = info->callout_termios;
791
                mxser_change_speed(info, 0);
792
        }
793
        info->session = current->session;
794
        info->pgrp = current->pgrp;
795
 
796
        MOD_INC_USE_COUNT;
797
 
798
        return (0);
799
}
800
 
801
/*
802
 * This routine is called when the serial port gets closed.  First, we
803
 * wait for the last remaining data to be sent.  Then, we unlink its
804
 * async structure from the interrupt chain if necessary, and we free
805
 * that IRQ if nothing is left in the chain.
806
 */
807
 
808
static void mxser_close(struct tty_struct *tty, struct file *filp)
809
{
810
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
811
        unsigned long flags;
812
        unsigned long timeout;
813
 
814
        if (PORTNO(tty) == MXSER_PORTS)
815
                return;
816
        if (!info)
817
                return;
818
 
819
        save_flags(flags);
820
        cli();
821
 
822
        if (tty_hung_up_p(filp)) {
823
                restore_flags(flags);
824
                MOD_DEC_USE_COUNT;
825
                return;
826
        }
827
        if ((tty->count == 1) && (info->count != 1)) {
828
                /*
829
                 * Uh, oh.        tty->count is 1, which means that the tty
830
                 * structure will be freed.  Info->count should always
831
                 * be one in these conditions.  If it's greater than
832
                 * one, we've got real problems, since it means the
833
                 * serial port won't be shutdown.
834
                 */
835
                printk("mxser_close: bad serial port count; tty->count is 1, "
836
                       "info->count is %d\n", info->count);
837
                info->count = 1;
838
        }
839
        if (--info->count < 0) {
840
                printk("mxser_close: bad serial port count for ttys%d: %d\n",
841
                       info->port, info->count);
842
                info->count = 0;
843
        }
844
        if (info->count) {
845
                restore_flags(flags);
846
                MOD_DEC_USE_COUNT;
847
                return;
848
        }
849
        info->flags |= ASYNC_CLOSING;
850
        /*
851
         * Save the termios structure, since this port may have
852
         * separate termios for callout and dialin.
853
         */
854
        if (info->flags & ASYNC_NORMAL_ACTIVE)
855
                info->normal_termios = *tty->termios;
856
        if (info->flags & ASYNC_CALLOUT_ACTIVE)
857
                info->callout_termios = *tty->termios;
858
        /*
859
         * Now we wait for the transmit buffer to clear; and we notify
860
         * the line discipline to only process XON/XOFF characters.
861
         */
862
        tty->closing = 1;
863
        if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
864
                tty_wait_until_sent(tty, info->closing_wait);
865
        /*
866
         * At this point we stop accepting input.  To do this, we
867
         * disable the receive line status interrupts, and tell the
868
         * interrupt driver to stop checking the data ready bit in the
869
         * line status register.
870
         */
871
        info->IER &= ~UART_IER_RLSI;
872
        /* by William
873
           info->read_status_mask &= ~UART_LSR_DR;
874
         */
875
        if (info->flags & ASYNC_INITIALIZED) {
876
                outb(info->IER, info->base + UART_IER);
877
                /*
878
                 * Before we drop DTR, make sure the UART transmitter
879
                 * has completely drained; this is especially
880
                 * important if there is a transmit FIFO!
881
                 */
882
                timeout = jiffies + HZ;
883
                while (!(inb(info->base + UART_LSR) & UART_LSR_TEMT)) {
884
                        set_current_state(TASK_INTERRUPTIBLE);
885
                        schedule_timeout(5);
886
                        if (jiffies > timeout)
887
                                break;
888
                }
889
        }
890
        mxser_shutdown(info);
891
        if (tty->driver.flush_buffer)
892
                tty->driver.flush_buffer(tty);
893
        if (tty->ldisc.flush_buffer)
894
                tty->ldisc.flush_buffer(tty);
895
        tty->closing = 0;
896
        info->event = 0;
897
        info->tty = 0;
898
        if (info->blocked_open) {
899
                if (info->close_delay) {
900
                        set_current_state(TASK_INTERRUPTIBLE);
901
                        schedule_timeout(info->close_delay);
902
                }
903
                wake_up_interruptible(&info->open_wait);
904
        }
905
        info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
906
                         ASYNC_CLOSING);
907
        wake_up_interruptible(&info->close_wait);
908
        restore_flags(flags);
909
 
910
        MOD_DEC_USE_COUNT;
911
}
912
 
913
static int mxser_write(struct tty_struct *tty, int from_user,
914
                       const unsigned char *buf, int count)
915
{
916
        int c, total = 0;
917
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
918
        unsigned long flags;
919
 
920
        if (!tty || !info->xmit_buf || !mxvar_tmp_buf)
921
                return (0);
922
 
923
        save_flags(flags);
924
        if (from_user) {
925
                down(&mxvar_tmp_buf_sem);
926
                while (1) {
927
                        c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
928
                                           SERIAL_XMIT_SIZE - info->xmit_head));
929
                        if (c <= 0)
930
                                break;
931
 
932
                        c -= copy_from_user(mxvar_tmp_buf, buf, c);
933
                        if (!c) {
934
                                if (!total)
935
                                        total = -EFAULT;
936
                                break;
937
                        }
938
 
939
                        cli();
940
                        c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
941
                                       SERIAL_XMIT_SIZE - info->xmit_head));
942
                        memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
943
                        info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
944
                        info->xmit_cnt += c;
945
                        restore_flags(flags);
946
 
947
                        buf += c;
948
                        count -= c;
949
                        total += c;
950
                }
951
                up(&mxvar_tmp_buf_sem);
952
        } else {
953
                while (1) {
954
                        cli();
955
                        c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
956
                                           SERIAL_XMIT_SIZE - info->xmit_head));
957
                        if (c <= 0) {
958
                                restore_flags(flags);
959
                                break;
960
                        }
961
 
962
                        memcpy(info->xmit_buf + info->xmit_head, buf, c);
963
                        info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
964
                        info->xmit_cnt += c;
965
                        restore_flags(flags);
966
 
967
                        buf += c;
968
                        count -= c;
969
                        total += c;
970
                }
971
        }
972
 
973
        cli();
974
        if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
975
            !(info->IER & UART_IER_THRI)) {
976
                info->IER |= UART_IER_THRI;
977
                outb(info->IER, info->base + UART_IER);
978
        }
979
        restore_flags(flags);
980
        return (total);
981
}
982
 
983
static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
984
{
985
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
986
        unsigned long flags;
987
 
988
        if (!tty || !info->xmit_buf)
989
                return;
990
 
991
        save_flags(flags);
992
        cli();
993
        if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
994
                restore_flags(flags);
995
                return;
996
        }
997
        info->xmit_buf[info->xmit_head++] = ch;
998
        info->xmit_head &= SERIAL_XMIT_SIZE - 1;
999
        info->xmit_cnt++;
1000
        /********************************************** why ??? ***********
1001
        if ( !tty->stopped && !tty->hw_stopped &&
1002
             !(info->IER & UART_IER_THRI) ) {
1003
            info->IER |= UART_IER_THRI;
1004
            outb(info->IER, info->base + UART_IER);
1005
        }
1006
        *****************************************************************/
1007
        restore_flags(flags);
1008
}
1009
 
1010
static void mxser_flush_chars(struct tty_struct *tty)
1011
{
1012
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1013
        unsigned long flags;
1014
 
1015
        if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1016
            !info->xmit_buf)
1017
                return;
1018
 
1019
        save_flags(flags);
1020
        cli();
1021
        info->IER |= UART_IER_THRI;
1022
        outb(info->IER, info->base + UART_IER);
1023
        restore_flags(flags);
1024
}
1025
 
1026
static int mxser_write_room(struct tty_struct *tty)
1027
{
1028
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1029
        int ret;
1030
 
1031
        ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
1032
        if (ret < 0)
1033
                ret = 0;
1034
        return (ret);
1035
}
1036
 
1037
static int mxser_chars_in_buffer(struct tty_struct *tty)
1038
{
1039
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1040
 
1041
        return (info->xmit_cnt);
1042
}
1043
 
1044
static void mxser_flush_buffer(struct tty_struct *tty)
1045
{
1046
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1047
        unsigned long flags;
1048
 
1049
        save_flags(flags);
1050
        cli();
1051
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1052
        restore_flags(flags);
1053
        wake_up_interruptible(&tty->write_wait);
1054
        if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1055
            tty->ldisc.write_wakeup)
1056
                (tty->ldisc.write_wakeup) (tty);
1057
}
1058
 
1059
static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1060
                       unsigned int cmd, unsigned long arg)
1061
{
1062
        unsigned long flags;
1063
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1064
        int retval;
1065
        struct async_icount cprev, cnow;        /* kernel counter temps */
1066
        struct serial_icounter_struct *p_cuser;         /* user space */
1067
        unsigned long templ;
1068
 
1069
        if (PORTNO(tty) == MXSER_PORTS)
1070
                return (mxser_ioctl_special(cmd, arg));
1071
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) &&
1072
            (cmd != TIOCGICOUNT)) {
1073
                if (tty->flags & (1 << TTY_IO_ERROR))
1074
                        return (-EIO);
1075
        }
1076
        switch (cmd) {
1077
        case TCSBRK:            /* SVID version: non-zero arg --> no break */
1078
                retval = tty_check_change(tty);
1079
                if (retval)
1080
                        return (retval);
1081
                tty_wait_until_sent(tty, 0);
1082
                if (!arg)
1083
                        mxser_send_break(info, HZ / 4);         /* 1/4 second */
1084
                return (0);
1085
        case TCSBRKP:           /* support for POSIX tcsendbreak() */
1086
                retval = tty_check_change(tty);
1087
                if (retval)
1088
                        return (retval);
1089
                tty_wait_until_sent(tty, 0);
1090
                mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
1091
                return (0);
1092
        case TIOCGSOFTCAR:
1093
                return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
1094
        case TIOCSSOFTCAR:
1095
                if(get_user(templ, (unsigned long *) arg))
1096
                        return -EFAULT;
1097
                arg = templ;
1098
                tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
1099
                                         (arg ? CLOCAL : 0));
1100
                return (0);
1101
        case TIOCMGET:
1102
                return (mxser_get_modem_info(info, (unsigned int *) arg));
1103
        case TIOCMBIS:
1104
        case TIOCMBIC:
1105
        case TIOCMSET:
1106
                return (mxser_set_modem_info(info, cmd, (unsigned int *) arg));
1107
        case TIOCGSERIAL:
1108
                return (mxser_get_serial_info(info, (struct serial_struct *) arg));
1109
        case TIOCSSERIAL:
1110
                return (mxser_set_serial_info(info, (struct serial_struct *) arg));
1111
        case TIOCSERGETLSR:     /* Get line status register */
1112
                return (mxser_get_lsr_info(info, (unsigned int *) arg));
1113
                /*
1114
                 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
1115
                 * - mask passed in arg for lines of interest
1116
                 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
1117
                 * Caller should use TIOCGICOUNT to see which one it was
1118
                 */
1119
        case TIOCMIWAIT:
1120
                save_flags(flags);
1121
                cli();
1122
                cprev = info->icount;   /* note the counters on entry */
1123
                restore_flags(flags);
1124
                while (1) {
1125
                        interruptible_sleep_on(&info->delta_msr_wait);
1126
                        /* see if a signal did it */
1127
                        if (signal_pending(current))
1128
                                return (-ERESTARTSYS);
1129
                        save_flags(flags);
1130
                        cli();
1131
                        cnow = info->icount;    /* atomic copy */
1132
                        restore_flags(flags);
1133
                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
1134
                          cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
1135
                                return (-EIO);  /* no change => error */
1136
                        if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
1137
                        ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
1138
                         ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
1139
                        ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
1140
                                return (0);
1141
                        }
1142
                        cprev = cnow;
1143
                }
1144
                /* NOTREACHED */
1145
                /*
1146
                 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1147
                 * Return: write counters to the user passed counter struct
1148
                 * NB: both 1->0 and 0->1 transitions are counted except for
1149
                 *     RI where only 0->1 is counted.
1150
                 */
1151
        case TIOCGICOUNT:
1152
                save_flags(flags);
1153
                cli();
1154
                cnow = info->icount;
1155
                restore_flags(flags);
1156
                p_cuser = (struct serial_icounter_struct *) arg;
1157
                if(put_user(cnow.cts, &p_cuser->cts))
1158
                        return -EFAULT;
1159
                if(put_user(cnow.dsr, &p_cuser->dsr))
1160
                        return -EFAULT;
1161
                if(put_user(cnow.rng, &p_cuser->rng))
1162
                        return -EFAULT;
1163
                return put_user(cnow.dcd, &p_cuser->dcd);
1164
        case MOXA_HighSpeedOn:
1165
                return put_user(info->baud_base != 115200 ? 1 : 0, (int *) arg);
1166
        default:
1167
                return (-ENOIOCTLCMD);
1168
        }
1169
        return (0);
1170
}
1171
 
1172
static int mxser_ioctl_special(unsigned int cmd, unsigned long arg)
1173
{
1174
        int i, result, status;
1175
 
1176
        switch (cmd) {
1177
        case MOXA_GET_CONF:
1178
                if(copy_to_user((struct mxser_hwconf *) arg, mxsercfg,
1179
                             sizeof(struct mxser_hwconf) * 4))
1180
                                return -EFAULT;
1181
                return 0;
1182
        case MOXA_GET_MAJOR:
1183
                if(copy_to_user((int *) arg, &ttymajor, sizeof(int)))
1184
                        return -EFAULT;
1185
                return 0;
1186
 
1187
        case MOXA_GET_CUMAJOR:
1188
                if(copy_to_user((int *) arg, &calloutmajor, sizeof(int)))
1189
                        return -EFAULT;
1190
                return 0;
1191
 
1192
        case MOXA_CHKPORTENABLE:
1193
                result = 0;
1194
                for (i = 0; i < MXSER_PORTS; i++) {
1195
                        if (mxvar_table[i].base)
1196
                                result |= (1 << i);
1197
                }
1198
                return put_user(result, (unsigned long *) arg);
1199
        case MOXA_GETDATACOUNT:
1200
                if(copy_to_user((struct mxser_log *) arg, &mxvar_log, sizeof(mxvar_log)))
1201
                        return -EFAULT;
1202
                return (0);
1203
        case MOXA_GETMSTATUS:
1204
                for (i = 0; i < MXSER_PORTS; i++) {
1205
                        GMStatus[i].ri = 0;
1206
                        if (!mxvar_table[i].base) {
1207
                                GMStatus[i].dcd = 0;
1208
                                GMStatus[i].dsr = 0;
1209
                                GMStatus[i].cts = 0;
1210
                                continue;
1211
                        }
1212
                        if (!mxvar_table[i].tty || !mxvar_table[i].tty->termios)
1213
                                GMStatus[i].cflag = mxvar_table[i].normal_termios.c_cflag;
1214
                        else
1215
                                GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag;
1216
 
1217
                        status = inb(mxvar_table[i].base + UART_MSR);
1218
                        if (status & 0x80 /*UART_MSR_DCD */ )
1219
                                GMStatus[i].dcd = 1;
1220
                        else
1221
                                GMStatus[i].dcd = 0;
1222
 
1223
                        if (status & 0x20 /*UART_MSR_DSR */ )
1224
                                GMStatus[i].dsr = 1;
1225
                        else
1226
                                GMStatus[i].dsr = 0;
1227
 
1228
 
1229
                        if (status & 0x10 /*UART_MSR_CTS */ )
1230
                                GMStatus[i].cts = 1;
1231
                        else
1232
                                GMStatus[i].cts = 0;
1233
                }
1234
                if(copy_to_user((struct mxser_mstatus *) arg, GMStatus,
1235
                             sizeof(struct mxser_mstatus) * MXSER_PORTS))
1236
                        return -EFAULT;
1237
                return 0;
1238
        default:
1239
                return (-ENOIOCTLCMD);
1240
        }
1241
        return (0);
1242
}
1243
 
1244
/*
1245
 * This routine is called by the upper-layer tty layer to signal that
1246
 * incoming characters should be throttled.
1247
 */
1248
static void mxser_throttle(struct tty_struct *tty)
1249
{
1250
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1251
        unsigned long flags;
1252
 
1253
        if (I_IXOFF(tty)) {
1254
                info->x_char = STOP_CHAR(tty);
1255
                save_flags(flags);
1256
                cli();
1257
                outb(info->IER, 0);
1258
                info->IER |= UART_IER_THRI;
1259
                outb(info->IER, info->base + UART_IER);         /* force Tx interrupt */
1260
                restore_flags(flags);
1261
        }
1262
        if (info->tty->termios->c_cflag & CRTSCTS) {
1263
                info->MCR &= ~UART_MCR_RTS;
1264
                save_flags(flags);
1265
                cli();
1266
                outb(info->MCR, info->base + UART_MCR);
1267
                restore_flags(flags);
1268
        }
1269
}
1270
 
1271
static void mxser_unthrottle(struct tty_struct *tty)
1272
{
1273
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1274
        unsigned long flags;
1275
 
1276
        if (I_IXOFF(tty)) {
1277
                if (info->x_char)
1278
                        info->x_char = 0;
1279
                else {
1280
                        info->x_char = START_CHAR(tty);
1281
                        save_flags(flags);
1282
                        cli();
1283
                        outb(info->IER, 0);
1284
                        info->IER |= UART_IER_THRI;     /* force Tx interrupt */
1285
                        outb(info->IER, info->base + UART_IER);
1286
                        restore_flags(flags);
1287
                }
1288
        }
1289
        if (info->tty->termios->c_cflag & CRTSCTS) {
1290
                info->MCR |= UART_MCR_RTS;
1291
                save_flags(flags);
1292
                cli();
1293
                outb(info->MCR, info->base + UART_MCR);
1294
                restore_flags(flags);
1295
        }
1296
}
1297
 
1298
static void mxser_set_termios(struct tty_struct *tty,
1299
                              struct termios *old_termios)
1300
{
1301
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1302
 
1303
/* 8-2-99 by William
1304
   if ( (tty->termios->c_cflag == old_termios->c_cflag) &&
1305
   (RELEVANT_IFLAG(tty->termios->c_iflag) ==
1306
   RELEVANT_IFLAG(old_termios->c_iflag)) )
1307
   return;
1308
 
1309
   mxser_change_speed(info, old_termios);
1310
 
1311
   if ( (old_termios->c_cflag & CRTSCTS) &&
1312
   !(tty->termios->c_cflag & CRTSCTS) ) {
1313
   tty->hw_stopped = 0;
1314
   mxser_start(tty);
1315
   }
1316
 */
1317
        if ((tty->termios->c_cflag != old_termios->c_cflag) ||
1318
            (RELEVANT_IFLAG(tty->termios->c_iflag) !=
1319
             RELEVANT_IFLAG(old_termios->c_iflag))) {
1320
 
1321
                mxser_change_speed(info, old_termios);
1322
 
1323
                if ((old_termios->c_cflag & CRTSCTS) &&
1324
                    !(tty->termios->c_cflag & CRTSCTS)) {
1325
                        tty->hw_stopped = 0;
1326
                        mxser_start(tty);
1327
                }
1328
        }
1329
/* Handle sw stopped */
1330
        if ((old_termios->c_iflag & IXON) &&
1331
            !(tty->termios->c_iflag & IXON)) {
1332
                tty->stopped = 0;
1333
                mxser_start(tty);
1334
        }
1335
}
1336
 
1337
/*
1338
 * mxser_stop() and mxser_start()
1339
 *
1340
 * This routines are called before setting or resetting tty->stopped.
1341
 * They enable or disable transmitter interrupts, as necessary.
1342
 */
1343
static void mxser_stop(struct tty_struct *tty)
1344
{
1345
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1346
        unsigned long flags;
1347
 
1348
        save_flags(flags);
1349
        cli();
1350
        if (info->IER & UART_IER_THRI) {
1351
                info->IER &= ~UART_IER_THRI;
1352
                outb(info->IER, info->base + UART_IER);
1353
        }
1354
        restore_flags(flags);
1355
}
1356
 
1357
static void mxser_start(struct tty_struct *tty)
1358
{
1359
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1360
        unsigned long flags;
1361
 
1362
        save_flags(flags);
1363
        cli();
1364
        if (info->xmit_cnt && info->xmit_buf &&
1365
            !(info->IER & UART_IER_THRI)) {
1366
                info->IER |= UART_IER_THRI;
1367
                outb(info->IER, info->base + UART_IER);
1368
        }
1369
        restore_flags(flags);
1370
}
1371
 
1372
/*
1373
 * This routine is called by tty_hangup() when a hangup is signaled.
1374
 */
1375
void mxser_hangup(struct tty_struct *tty)
1376
{
1377
        struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
1378
 
1379
        mxser_flush_buffer(tty);
1380
        mxser_shutdown(info);
1381
        info->event = 0;
1382
        info->count = 0;
1383
        info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
1384
        info->tty = 0;
1385
        wake_up_interruptible(&info->open_wait);
1386
}
1387
 
1388
/*
1389
 * This is the serial driver's generic interrupt routine
1390
 */
1391
static void mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1392
{
1393
        int status, i;
1394
        struct mxser_struct *info;
1395
        struct mxser_struct *port;
1396
        int max, irqbits, bits, msr;
1397
        int pass_counter = 0;
1398
 
1399
        port = 0;
1400
        for (i = 0; i < MXSER_BOARDS; i++) {
1401
                if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
1402
                        port = dev_id;
1403
                        break;
1404
                }
1405
        }
1406
 
1407
        if (i == MXSER_BOARDS)
1408
                return;
1409
        if (port == 0)
1410
                return;
1411
        max = mxser_numports[mxsercfg[i].board_type];
1412
 
1413
        while (1) {
1414
                irqbits = inb(port->vector) & port->vectormask;
1415
                if (irqbits == port->vectormask)
1416
                        break;
1417
                for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
1418
                        if (irqbits == port->vectormask)
1419
                                break;
1420
                        if (bits & irqbits)
1421
                                continue;
1422
                        info = port + i;
1423
                        if (!info->tty ||
1424
                          (inb(info->base + UART_IIR) & UART_IIR_NO_INT))
1425
                                continue;
1426
                        status = inb(info->base + UART_LSR) & info->read_status_mask;
1427
                        if (status & UART_LSR_DR)
1428
                                mxser_receive_chars(info, &status);
1429
                        msr = inb(info->base + UART_MSR);
1430
                        if (msr & UART_MSR_ANY_DELTA)
1431
                                mxser_check_modem_status(info, msr);
1432
                        if (status & UART_LSR_THRE) {
1433
/* 8-2-99 by William
1434
   if ( info->x_char || (info->xmit_cnt > 0) )
1435
 */
1436
                                mxser_transmit_chars(info);
1437
                        }
1438
                }
1439
                if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
1440
#if 0
1441
                        printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n");
1442
#endif
1443
                        break;  /* Prevent infinite loops */
1444
                }
1445
        }
1446
}
1447
 
1448
static inline void mxser_receive_chars(struct mxser_struct *info,
1449
                                         int *status)
1450
{
1451
        struct tty_struct *tty = info->tty;
1452
        unsigned char ch;
1453
        int ignored = 0;
1454
        int cnt = 0;
1455
 
1456
        do {
1457
                ch = inb(info->base + UART_RX);
1458
                if (*status & info->ignore_status_mask) {
1459
                        if (++ignored > 100)
1460
                                break;
1461
                } else {
1462
                        if (tty->flip.count >= TTY_FLIPBUF_SIZE)
1463
                                break;
1464
                        tty->flip.count++;
1465
                        if (*status & UART_LSR_SPECIAL) {
1466
                                if (*status & UART_LSR_BI) {
1467
                                        *tty->flip.flag_buf_ptr++ = TTY_BREAK;
1468
                                        if (info->flags & ASYNC_SAK)
1469
                                                do_SAK(tty);
1470
                                } else if (*status & UART_LSR_PE) {
1471
                                        *tty->flip.flag_buf_ptr++ = TTY_PARITY;
1472
                                } else if (*status & UART_LSR_FE) {
1473
                                        *tty->flip.flag_buf_ptr++ = TTY_FRAME;
1474
                                } else if (*status & UART_LSR_OE) {
1475
                                        *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
1476
                                } else
1477
                                        *tty->flip.flag_buf_ptr++ = 0;
1478
                        } else
1479
                                *tty->flip.flag_buf_ptr++ = 0;
1480
                        *tty->flip.char_buf_ptr++ = ch;
1481
                        cnt++;
1482
                }
1483
                *status = inb(info->base + UART_LSR) & info->read_status_mask;
1484
        } while (*status & UART_LSR_DR);
1485
        mxvar_log.rxcnt[info->port] += cnt;
1486
        queue_task(&tty->flip.tqueue, &tq_timer);
1487
 
1488
}
1489
 
1490
static inline void mxser_transmit_chars(struct mxser_struct *info)
1491
{
1492
        int count, cnt;
1493
 
1494
        if (info->x_char) {
1495
                outb(info->x_char, info->base + UART_TX);
1496
                info->x_char = 0;
1497
                mxvar_log.txcnt[info->port]++;
1498
                return;
1499
        }
1500
        if ((info->xmit_cnt <= 0) || info->tty->stopped ||
1501
            info->tty->hw_stopped) {
1502
                info->IER &= ~UART_IER_THRI;
1503
                outb(info->IER, info->base + UART_IER);
1504
                return;
1505
        }
1506
        cnt = info->xmit_cnt;
1507
        count = info->xmit_fifo_size;
1508
        do {
1509
                outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
1510
                info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
1511
                if (--info->xmit_cnt <= 0)
1512
                        break;
1513
        } while (--count > 0);
1514
        mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
1515
 
1516
        if (info->xmit_cnt < WAKEUP_CHARS) {
1517
                set_bit(MXSER_EVENT_TXLOW, &info->event);
1518
                MOD_INC_USE_COUNT;
1519
                if (schedule_task(&info->tqueue) == 0)
1520
                    MOD_DEC_USE_COUNT;
1521
        }
1522
        if (info->xmit_cnt <= 0) {
1523
                info->IER &= ~UART_IER_THRI;
1524
                outb(info->IER, info->base + UART_IER);
1525
        }
1526
}
1527
 
1528
static inline void mxser_check_modem_status(struct mxser_struct *info,
1529
                                              int status)
1530
{
1531
 
1532
        /* update input line counters */
1533
        if (status & UART_MSR_TERI)
1534
                info->icount.rng++;
1535
        if (status & UART_MSR_DDSR)
1536
                info->icount.dsr++;
1537
        if (status & UART_MSR_DDCD)
1538
                info->icount.dcd++;
1539
        if (status & UART_MSR_DCTS)
1540
                info->icount.cts++;
1541
        wake_up_interruptible(&info->delta_msr_wait);
1542
 
1543
        if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
1544
                if (status & UART_MSR_DCD)
1545
                        wake_up_interruptible(&info->open_wait);
1546
                else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
1547
                           (info->flags & ASYNC_CALLOUT_NOHUP)))
1548
                        set_bit(MXSER_EVENT_HANGUP, &info->event);
1549
                MOD_INC_USE_COUNT;
1550
                if (schedule_task(&info->tqueue) == 0)
1551
                    MOD_DEC_USE_COUNT;
1552
        }
1553
        if (info->flags & ASYNC_CTS_FLOW) {
1554
                if (info->tty->hw_stopped) {
1555
                        if (status & UART_MSR_CTS) {
1556
                                info->tty->hw_stopped = 0;
1557
                                info->IER |= UART_IER_THRI;
1558
                                outb(info->IER, info->base + UART_IER);
1559
 
1560
                                set_bit(MXSER_EVENT_TXLOW, &info->event);
1561
                                MOD_INC_USE_COUNT;
1562
                                if (schedule_task(&info->tqueue) == 0)
1563
                                        MOD_DEC_USE_COUNT;
1564
                        }
1565
                } else {
1566
                        if (!(status & UART_MSR_CTS)) {
1567
                                info->tty->hw_stopped = 1;
1568
                                info->IER &= ~UART_IER_THRI;
1569
                                outb(info->IER, info->base + UART_IER);
1570
                        }
1571
                }
1572
        }
1573
}
1574
 
1575
static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
1576
                                 struct mxser_struct *info)
1577
{
1578
        DECLARE_WAITQUEUE(wait, current);
1579
        unsigned long flags;
1580
        int retval;
1581
        int do_clocal = 0;
1582
 
1583
        /*
1584
         * If the device is in the middle of being closed, then block
1585
         * until it's done, and then try again.
1586
         */
1587
        if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
1588
                if (info->flags & ASYNC_CLOSING)
1589
                        interruptible_sleep_on(&info->close_wait);
1590
#ifdef SERIAL_DO_RESTART
1591
                if (info->flags & ASYNC_HUP_NOTIFY)
1592
                        return (-EAGAIN);
1593
                else
1594
                        return (-ERESTARTSYS);
1595
#else
1596
                return (-EAGAIN);
1597
#endif
1598
        }
1599
        /*
1600
         * If this is a callout device, then just make sure the normal
1601
         * device isn't being used.
1602
         */
1603
        if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
1604
                if (info->flags & ASYNC_NORMAL_ACTIVE)
1605
                        return (-EBUSY);
1606
                if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
1607
                    (info->flags & ASYNC_SESSION_LOCKOUT) &&
1608
                    (info->session != current->session))
1609
                        return (-EBUSY);
1610
                if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
1611
                    (info->flags & ASYNC_PGRP_LOCKOUT) &&
1612
                    (info->pgrp != current->pgrp))
1613
                        return (-EBUSY);
1614
                info->flags |= ASYNC_CALLOUT_ACTIVE;
1615
                return (0);
1616
        }
1617
        /*
1618
         * If non-blocking mode is set, or the port is not enabled,
1619
         * then make the check up front and then exit.
1620
         */
1621
        if ((filp->f_flags & O_NONBLOCK) ||
1622
            (tty->flags & (1 << TTY_IO_ERROR))) {
1623
                if (info->flags & ASYNC_CALLOUT_ACTIVE)
1624
                        return (-EBUSY);
1625
                info->flags |= ASYNC_NORMAL_ACTIVE;
1626
                return (0);
1627
        }
1628
        if (info->flags & ASYNC_CALLOUT_ACTIVE) {
1629
                if (info->normal_termios.c_cflag & CLOCAL)
1630
                        do_clocal = 1;
1631
        } else {
1632
                if (tty->termios->c_cflag & CLOCAL)
1633
                        do_clocal = 1;
1634
        }
1635
 
1636
        /*
1637
         * Block waiting for the carrier detect and the line to become
1638
         * free (i.e., not in use by the callout).  While we are in
1639
         * this loop, info->count is dropped by one, so that
1640
         * mxser_close() knows when to free things.  We restore it upon
1641
         * exit, either normal or abnormal.
1642
         */
1643
        retval = 0;
1644
        add_wait_queue(&info->open_wait, &wait);
1645
        save_flags(flags);
1646
        cli();
1647
        if (!tty_hung_up_p(filp))
1648
                info->count--;
1649
        restore_flags(flags);
1650
        info->blocked_open++;
1651
        while (1) {
1652
                save_flags(flags);
1653
                cli();
1654
                if (!(info->flags & ASYNC_CALLOUT_ACTIVE))
1655
                        outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS,
1656
                             info->base + UART_MCR);
1657
                restore_flags(flags);
1658
                set_current_state(TASK_INTERRUPTIBLE);
1659
                if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) {
1660
#ifdef SERIAL_DO_RESTART
1661
                        if (info->flags & ASYNC_HUP_NOTIFY)
1662
                                retval = -EAGAIN;
1663
                        else
1664
                                retval = -ERESTARTSYS;
1665
#else
1666
                        retval = -EAGAIN;
1667
#endif
1668
                        break;
1669
                }
1670
                if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
1671
                    !(info->flags & ASYNC_CLOSING) &&
1672
                    (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)))
1673
                        break;
1674
                if (signal_pending(current)) {
1675
                        retval = -ERESTARTSYS;
1676
                        break;
1677
                }
1678
                schedule();
1679
        }
1680
        set_current_state(TASK_RUNNING);
1681
        remove_wait_queue(&info->open_wait, &wait);
1682
        if (!tty_hung_up_p(filp))
1683
                info->count++;
1684
        info->blocked_open--;
1685
        if (retval)
1686
                return (retval);
1687
        info->flags |= ASYNC_NORMAL_ACTIVE;
1688
        return (0);
1689
}
1690
 
1691
static int mxser_startup(struct mxser_struct *info)
1692
{
1693
        unsigned long flags;
1694
        unsigned long page;
1695
 
1696
        page = get_free_page(GFP_KERNEL);
1697
        if (!page)
1698
                return (-ENOMEM);
1699
 
1700
        save_flags(flags);
1701
        cli();
1702
 
1703
        if (info->flags & ASYNC_INITIALIZED) {
1704
                free_page(page);
1705
                restore_flags(flags);
1706
                return (0);
1707
        }
1708
        if (!info->base || !info->type) {
1709
                if (info->tty)
1710
                        set_bit(TTY_IO_ERROR, &info->tty->flags);
1711
                free_page(page);
1712
                restore_flags(flags);
1713
                return (0);
1714
        }
1715
        if (info->xmit_buf)
1716
                free_page(page);
1717
        else
1718
                info->xmit_buf = (unsigned char *) page;
1719
 
1720
        /*
1721
         * Clear the FIFO buffers and disable them
1722
         * (they will be reenabled in mxser_change_speed())
1723
         */
1724
        if (info->xmit_fifo_size == 16)
1725
                outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
1726
                     info->base + UART_FCR);
1727
 
1728
        /*
1729
         * At this point there's no way the LSR could still be 0xFF;
1730
         * if it is, then bail out, because there's likely no UART
1731
         * here.
1732
         */
1733
        if (inb(info->base + UART_LSR) == 0xff) {
1734
                restore_flags(flags);
1735
                if (capable(CAP_SYS_ADMIN)) {
1736
                        if (info->tty)
1737
                                set_bit(TTY_IO_ERROR, &info->tty->flags);
1738
                        return (0);
1739
                } else
1740
                        return (-ENODEV);
1741
        }
1742
        /*
1743
         * Clear the interrupt registers.
1744
         */
1745
        (void) inb(info->base + UART_LSR);
1746
        (void) inb(info->base + UART_RX);
1747
        (void) inb(info->base + UART_IIR);
1748
        (void) inb(info->base + UART_MSR);
1749
 
1750
        /*
1751
         * Now, initialize the UART
1752
         */
1753
        outb(UART_LCR_WLEN8, info->base + UART_LCR);    /* reset DLAB */
1754
        info->MCR = UART_MCR_DTR | UART_MCR_RTS;
1755
        outb(info->MCR, info->base + UART_MCR);
1756
 
1757
        /*
1758
         * Finally, enable interrupts
1759
         */
1760
        info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
1761
        outb(info->IER, info->base + UART_IER);         /* enable interrupts */
1762
 
1763
        /*
1764
         * And clear the interrupt registers again for luck.
1765
         */
1766
        (void) inb(info->base + UART_LSR);
1767
        (void) inb(info->base + UART_RX);
1768
        (void) inb(info->base + UART_IIR);
1769
        (void) inb(info->base + UART_MSR);
1770
 
1771
        if (info->tty)
1772
                test_and_clear_bit(TTY_IO_ERROR, &info->tty->flags);
1773
 
1774
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1775
 
1776
        /*
1777
         * and set the speed of the serial port
1778
         */
1779
        mxser_change_speed(info, 0);
1780
 
1781
        info->flags |= ASYNC_INITIALIZED;
1782
        restore_flags(flags);
1783
        return (0);
1784
}
1785
 
1786
/*
1787
 * This routine will shutdown a serial port; interrupts maybe disabled, and
1788
 * DTR is dropped if the hangup on close termio flag is on.
1789
 */
1790
static void mxser_shutdown(struct mxser_struct *info)
1791
{
1792
        unsigned long flags;
1793
 
1794
        if (!(info->flags & ASYNC_INITIALIZED))
1795
                return;
1796
 
1797
        save_flags(flags);
1798
        cli();                  /* Disable interrupts */
1799
 
1800
        /*
1801
         * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
1802
         * here so the queue might never be waken up
1803
         */
1804
        wake_up_interruptible(&info->delta_msr_wait);
1805
 
1806
        /*
1807
         * Free the IRQ, if necessary
1808
         */
1809
        if (info->xmit_buf) {
1810
                free_page((unsigned long) info->xmit_buf);
1811
                info->xmit_buf = 0;
1812
        }
1813
        info->IER = 0;
1814
        outb(0x00, info->base + UART_IER);      /* disable all intrs */
1815
 
1816
        if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
1817
                info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
1818
        outb(info->MCR, info->base + UART_MCR);
1819
 
1820
        /* clear Rx/Tx FIFO's */
1821
        outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
1822
        /* read data port to reset things */
1823
        (void) inb(info->base + UART_RX);
1824
 
1825
        if (info->tty)
1826
                set_bit(TTY_IO_ERROR, &info->tty->flags);
1827
 
1828
        info->flags &= ~ASYNC_INITIALIZED;
1829
        restore_flags(flags);
1830
}
1831
 
1832
/*
1833
 * This routine is called to set the UART divisor registers to match
1834
 * the specified baud rate for a serial port.
1835
 */
1836
static int mxser_change_speed(struct mxser_struct *info,
1837
                              struct termios *old_termios)
1838
{
1839
        int quot = 0;
1840
        unsigned cflag, cval, fcr;
1841
        int i;
1842
        int ret = 0;
1843
        unsigned long flags;
1844
 
1845
        if (!info->tty || !info->tty->termios)
1846
                return ret;
1847
        cflag = info->tty->termios->c_cflag;
1848
        if (!(info->base))
1849
                return ret;
1850
 
1851
#ifndef B921600
1852
#define B921600 (B460800 +1)
1853
#endif
1854
        switch (cflag & (CBAUD | CBAUDEX)) {
1855
        case B921600:
1856
                i = 20;
1857
                break;
1858
        case B460800:
1859
                i = 19;
1860
                break;
1861
        case B230400:
1862
                i = 18;
1863
                break;
1864
        case B115200:
1865
                i = 17;
1866
                break;
1867
        case B57600:
1868
                i = 16;
1869
                break;
1870
        case B38400:
1871
                i = 15;
1872
                break;
1873
        case B19200:
1874
                i = 14;
1875
                break;
1876
        case B9600:
1877
                i = 13;
1878
                break;
1879
        case B4800:
1880
                i = 12;
1881
                break;
1882
        case B2400:
1883
                i = 11;
1884
                break;
1885
        case B1800:
1886
                i = 10;
1887
                break;
1888
        case B1200:
1889
                i = 9;
1890
                break;
1891
        case B600:
1892
                i = 8;
1893
                break;
1894
        case B300:
1895
                i = 7;
1896
                break;
1897
        case B200:
1898
                i = 6;
1899
                break;
1900
        case B150:
1901
                i = 5;
1902
                break;
1903
        case B134:
1904
                i = 4;
1905
                break;
1906
        case B110:
1907
                i = 3;
1908
                break;
1909
        case B75:
1910
                i = 2;
1911
                break;
1912
        case B50:
1913
                i = 1;
1914
                break;
1915
        default:
1916
                i = 0;
1917
                break;
1918
        }
1919
 
1920
        if (i == 15) {
1921
                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1922
                        i = 16; /* 57600 bps */
1923
                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
1924
                        i = 17; /* 115200 bps */
1925
 
1926
#ifdef ASYNC_SPD_SHI
1927
                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
1928
                        i = 18;
1929
#endif
1930
 
1931
#ifdef ASYNC_SPD_WARP
1932
                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
1933
                        i = 19;
1934
#endif
1935
        }
1936
        if (mxvar_baud_table[i] == 134) {
1937
                quot = (2 * info->baud_base / 269);
1938
        } else if (mxvar_baud_table[i]) {
1939
                quot = info->baud_base / mxvar_baud_table[i];
1940
                if (!quot && old_termios) {
1941
                        /* re-calculate */
1942
                        info->tty->termios->c_cflag &= ~CBAUD;
1943
                        info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
1944
                        switch (info->tty->termios->c_cflag & (CBAUD | CBAUDEX)) {
1945
                        case B921600:
1946
                                i = 20;
1947
                                break;
1948
                        case B460800:
1949
                                i = 19;
1950
                                break;
1951
                        case B230400:
1952
                                i = 18;
1953
                                break;
1954
                        case B115200:
1955
                                i = 17;
1956
                                break;
1957
                        case B57600:
1958
                                i = 16;
1959
                                break;
1960
                        case B38400:
1961
                                i = 15;
1962
                                break;
1963
                        case B19200:
1964
                                i = 14;
1965
                                break;
1966
                        case B9600:
1967
                                i = 13;
1968
                                break;
1969
                        case B4800:
1970
                                i = 12;
1971
                                break;
1972
                        case B2400:
1973
                                i = 11;
1974
                                break;
1975
                        case B1800:
1976
                                i = 10;
1977
                                break;
1978
                        case B1200:
1979
                                i = 9;
1980
                                break;
1981
                        case B600:
1982
                                i = 8;
1983
                                break;
1984
                        case B300:
1985
                                i = 7;
1986
                                break;
1987
                        case B200:
1988
                                i = 6;
1989
                                break;
1990
                        case B150:
1991
                                i = 5;
1992
                                break;
1993
                        case B134:
1994
                                i = 4;
1995
                                break;
1996
                        case B110:
1997
                                i = 3;
1998
                                break;
1999
                        case B75:
2000
                                i = 2;
2001
                                break;
2002
                        case B50:
2003
                                i = 1;
2004
                                break;
2005
                        default:
2006
                                i = 0;
2007
                                break;
2008
                        }
2009
                        if (i == 15) {
2010
                                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2011
                                        i = 16;         /* 57600 bps */
2012
                                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2013
                                        i = 17;         /* 115200 bps */
2014
#ifdef ASYNC_SPD_SHI
2015
                                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2016
                                        i = 18;
2017
#endif
2018
#ifdef ASYNC_SPD_WARP
2019
                                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2020
                                        i = 19;
2021
#endif
2022
                        }
2023
                        if (mxvar_baud_table[i] == 134) {
2024
                                quot = (2 * info->baud_base / 269);
2025
                        } else if (mxvar_baud_table[i]) {
2026
                                quot = info->baud_base / mxvar_baud_table[i];
2027
                                if (quot == 0)
2028
                                        quot = 1;
2029
                        } else {
2030
                                quot = 0;
2031
                        }
2032
                } else if (quot == 0)
2033
                        quot = 1;
2034
        } else {
2035
                quot = 0;
2036
        }
2037
 
2038
        if (quot) {
2039
                info->MCR |= UART_MCR_DTR;
2040
                save_flags(flags);
2041
                cli();
2042
                outb(info->MCR, info->base + UART_MCR);
2043
                restore_flags(flags);
2044
        } else {
2045
                info->MCR &= ~UART_MCR_DTR;
2046
                save_flags(flags);
2047
                cli();
2048
                outb(info->MCR, info->base + UART_MCR);
2049
                restore_flags(flags);
2050
                return ret;
2051
        }
2052
        /* byte size and parity */
2053
        switch (cflag & CSIZE) {
2054
        case CS5:
2055
                cval = 0x00;
2056
                break;
2057
        case CS6:
2058
                cval = 0x01;
2059
                break;
2060
        case CS7:
2061
                cval = 0x02;
2062
                break;
2063
        case CS8:
2064
                cval = 0x03;
2065
                break;
2066
        default:
2067
                cval = 0x00;
2068
                break;          /* too keep GCC shut... */
2069
        }
2070
        if (cflag & CSTOPB)
2071
                cval |= 0x04;
2072
        if (cflag & PARENB)
2073
                cval |= UART_LCR_PARITY;
2074
        if (!(cflag & PARODD))
2075
                cval |= UART_LCR_EPAR;
2076
        if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
2077
                fcr = 0;
2078
        } else {
2079
                fcr = UART_FCR_ENABLE_FIFO;
2080
                switch (info->rx_trigger) {
2081
                case 1:
2082
                        fcr |= UART_FCR_TRIGGER_1;
2083
                        break;
2084
                case 4:
2085
                        fcr |= UART_FCR_TRIGGER_4;
2086
                        break;
2087
                case 8:
2088
                        fcr |= UART_FCR_TRIGGER_8;
2089
                        break;
2090
                default:
2091
                        fcr |= UART_FCR_TRIGGER_14;
2092
                }
2093
        }
2094
 
2095
        /* CTS flow control flag and modem status interrupts */
2096
        info->IER &= ~UART_IER_MSI;
2097
        info->MCR &= ~UART_MCR_AFE;
2098
        if (cflag & CRTSCTS) {
2099
                info->flags |= ASYNC_CTS_FLOW;
2100
                info->IER |= UART_IER_MSI;
2101
                if (info->type == PORT_16550A)
2102
                        info->MCR |= UART_MCR_AFE;
2103
        } else {
2104
                info->flags &= ~ASYNC_CTS_FLOW;
2105
        }
2106
        outb(info->MCR, info->base + UART_MCR);
2107
        if (cflag & CLOCAL)
2108
                info->flags &= ~ASYNC_CHECK_CD;
2109
        else {
2110
                info->flags |= ASYNC_CHECK_CD;
2111
                info->IER |= UART_IER_MSI;
2112
        }
2113
        outb(info->IER, info->base + UART_IER);
2114
 
2115
        /*
2116
         * Set up parity check flag
2117
         */
2118
        info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
2119
        if (I_INPCK(info->tty))
2120
                info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
2121
        if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
2122
                info->read_status_mask |= UART_LSR_BI;
2123
 
2124
        info->ignore_status_mask = 0;
2125
#if 0
2126
        /* This should be safe, but for some broken bits of hardware... */
2127
        if (I_IGNPAR(info->tty)) {
2128
                info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
2129
                info->read_status_mask |= UART_LSR_PE | UART_LSR_FE;
2130
        }
2131
#endif
2132
        if (I_IGNBRK(info->tty)) {
2133
                info->ignore_status_mask |= UART_LSR_BI;
2134
                info->read_status_mask |= UART_LSR_BI;
2135
                /*
2136
                 * If we're ignore parity and break indicators, ignore
2137
                 * overruns too.  (For real raw support).
2138
                 */
2139
                if (I_IGNPAR(info->tty)) {
2140
                        info->ignore_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;
2141
                        info->read_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;
2142
                }
2143
        }
2144
        save_flags(flags);
2145
        cli();
2146
        outb(cval | UART_LCR_DLAB, info->base + UART_LCR);      /* set DLAB */
2147
        outb(quot & 0xff, info->base + UART_DLL);       /* LS of divisor */
2148
        outb(quot >> 8, info->base + UART_DLM);         /* MS of divisor */
2149
        outb(cval, info->base + UART_LCR);      /* reset DLAB */
2150
        outb(fcr, info->base + UART_FCR);       /* set fcr */
2151
        restore_flags(flags);
2152
 
2153
        return ret;
2154
}
2155
 
2156
/*
2157
 * ------------------------------------------------------------
2158
 * friends of mxser_ioctl()
2159
 * ------------------------------------------------------------
2160
 */
2161
static int mxser_get_serial_info(struct mxser_struct *info,
2162
                                 struct serial_struct *retinfo)
2163
{
2164
        struct serial_struct tmp;
2165
 
2166
        if (!retinfo)
2167
                return (-EFAULT);
2168
        memset(&tmp, 0, sizeof(tmp));
2169
        tmp.type = info->type;
2170
        tmp.line = info->port;
2171
        tmp.port = info->base;
2172
        tmp.irq = info->irq;
2173
        tmp.flags = info->flags;
2174
        tmp.baud_base = info->baud_base;
2175
        tmp.close_delay = info->close_delay;
2176
        tmp.closing_wait = info->closing_wait;
2177
        tmp.custom_divisor = info->custom_divisor;
2178
        tmp.hub6 = 0;
2179
        return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
2180
}
2181
 
2182
static int mxser_set_serial_info(struct mxser_struct *info,
2183
                                 struct serial_struct *new_info)
2184
{
2185
        struct serial_struct new_serial;
2186
        unsigned int flags;
2187
        int retval = 0;
2188
 
2189
        if (!new_info || !info->base)
2190
                return (-EFAULT);
2191
        if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
2192
                return -EFAULT;
2193
 
2194
        if ((new_serial.irq != info->irq) ||
2195
            (new_serial.port != info->base) ||
2196
            (new_serial.type != info->type) ||
2197
            (new_serial.custom_divisor != info->custom_divisor) ||
2198
            (new_serial.baud_base != info->baud_base))
2199
                return (-EPERM);
2200
 
2201
        flags = info->flags & ASYNC_SPD_MASK;
2202
 
2203
        if (!suser()) {
2204
                if ((new_serial.baud_base != info->baud_base) ||
2205
                    (new_serial.close_delay != info->close_delay) ||
2206
                    ((new_serial.flags & ~ASYNC_USR_MASK) !=
2207
                     (info->flags & ~ASYNC_USR_MASK)))
2208
                        return (-EPERM);
2209
                info->flags = ((info->flags & ~ASYNC_USR_MASK) |
2210
                               (new_serial.flags & ASYNC_USR_MASK));
2211
        } else {
2212
                /*
2213
                 * OK, past this point, all the error checking has been done.
2214
                 * At this point, we start making changes.....
2215
                 */
2216
                info->flags = ((info->flags & ~ASYNC_FLAGS) |
2217
                               (new_serial.flags & ASYNC_FLAGS));
2218
                info->close_delay = new_serial.close_delay * HZ / 100;
2219
                info->closing_wait = new_serial.closing_wait * HZ / 100;
2220
        }
2221
 
2222
        if (info->flags & ASYNC_INITIALIZED) {
2223
                if (flags != (info->flags & ASYNC_SPD_MASK)) {
2224
                        mxser_change_speed(info, 0);
2225
                }
2226
        } else
2227
                retval = mxser_startup(info);
2228
        return (retval);
2229
}
2230
 
2231
/*
2232
 * mxser_get_lsr_info - get line status register info
2233
 *
2234
 * Purpose: Let user call ioctl() to get info when the UART physically
2235
 *          is emptied.  On bus types like RS485, the transmitter must
2236
 *          release the bus after transmitting. This must be done when
2237
 *          the transmit shift register is empty, not be done when the
2238
 *          transmit holding register is empty.  This functionality
2239
 *          allows an RS485 driver to be written in user space.
2240
 */
2241
static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int *value)
2242
{
2243
        unsigned char status;
2244
        unsigned int result;
2245
        unsigned long flags;
2246
 
2247
        save_flags(flags);
2248
        cli();
2249
        status = inb(info->base + UART_LSR);
2250
        restore_flags(flags);
2251
        result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
2252
        return put_user(result, value);
2253
}
2254
 
2255
/*
2256
 * This routine sends a break character out the serial port.
2257
 */
2258
static void mxser_send_break(struct mxser_struct *info, int duration)
2259
{
2260
        unsigned long flags;
2261
        if (!info->base)
2262
                return;
2263
        set_current_state(TASK_INTERRUPTIBLE);
2264
        save_flags(flags);
2265
        cli();
2266
        outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
2267
        schedule_timeout(duration);
2268
        outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
2269
        restore_flags(flags);
2270
}
2271
 
2272
static int mxser_get_modem_info(struct mxser_struct *info,
2273
                                unsigned int *value)
2274
{
2275
        unsigned char control, status;
2276
        unsigned int result;
2277
        unsigned long flags;
2278
 
2279
        control = info->MCR;
2280
        save_flags(flags);
2281
        cli();
2282
        status = inb(info->base + UART_MSR);
2283
        if (status & UART_MSR_ANY_DELTA)
2284
                mxser_check_modem_status(info, status);
2285
        restore_flags(flags);
2286
        result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
2287
            ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
2288
            ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
2289
            ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
2290
            ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
2291
            ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
2292
        return put_user(result, value);
2293
}
2294
 
2295
static int mxser_set_modem_info(struct mxser_struct *info, unsigned int cmd,
2296
                                unsigned int *value)
2297
{
2298
        unsigned int arg;
2299
        unsigned long flags;
2300
 
2301
        if(get_user(arg, value))
2302
                return -EFAULT;
2303
        switch (cmd) {
2304
        case TIOCMBIS:
2305
                if (arg & TIOCM_RTS)
2306
                        info->MCR |= UART_MCR_RTS;
2307
                if (arg & TIOCM_DTR)
2308
                        info->MCR |= UART_MCR_DTR;
2309
                break;
2310
        case TIOCMBIC:
2311
                if (arg & TIOCM_RTS)
2312
                        info->MCR &= ~UART_MCR_RTS;
2313
                if (arg & TIOCM_DTR)
2314
                        info->MCR &= ~UART_MCR_DTR;
2315
                break;
2316
        case TIOCMSET:
2317
                info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) |
2318
                             ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) |
2319
                             ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
2320
                break;
2321
        default:
2322
                return (-EINVAL);
2323
        }
2324
        save_flags(flags);
2325
        cli();
2326
        outb(info->MCR, info->base + UART_MCR);
2327
        restore_flags(flags);
2328
        return (0);
2329
}
2330
 
2331
static int mxser_read_register(int, unsigned short *);
2332
static int mxser_program_mode(int);
2333
static void mxser_normal_mode(int);
2334
 
2335
static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf)
2336
{
2337
        int id, i, bits;
2338
        unsigned short regs[16], irq;
2339
        unsigned char scratch, scratch2;
2340
 
2341
        id = mxser_read_register(cap, regs);
2342
        if (id == C168_ASIC_ID)
2343
                hwconf->board_type = MXSER_BOARD_C168_ISA;
2344
        else if (id == C104_ASIC_ID)
2345
                hwconf->board_type = MXSER_BOARD_C104_ISA;
2346
        else if (id == C102_ASIC_ID)
2347
                hwconf->board_type = MXSER_BOARD_C102_ISA;
2348
        else if (id == CI132_ASIC_ID)
2349
                hwconf->board_type = MXSER_BOARD_CI132;
2350
        else if (id == CI134_ASIC_ID)
2351
                hwconf->board_type = MXSER_BOARD_CI134;
2352
        else if (id == CI104J_ASIC_ID)
2353
                hwconf->board_type = MXSER_BOARD_CI104J;
2354
        else
2355
                return (0);
2356
        irq = regs[9] & 0x0F;
2357
        irq = irq | (irq << 4);
2358
        irq = irq | (irq << 8);
2359
        if ((irq != regs[9]) || ((id == 1) && (irq != regs[10]))) {
2360
                return (MXSER_ERR_IRQ_CONFLIT);
2361
        }
2362
        if (!irq) {
2363
                return (MXSER_ERR_IRQ);
2364
        }
2365
        for (i = 0; i < 8; i++)
2366
                hwconf->ioaddr[i] = (int) regs[i + 1] & 0xFFF8;
2367
        hwconf->irq = (int) (irq & 0x0F);
2368
        if ((regs[12] & 0x80) == 0) {
2369
                return (MXSER_ERR_VECTOR);
2370
        }
2371
        hwconf->vector = (int) regs[11];        /* interrupt vector */
2372
        if (id == 1)
2373
                hwconf->vector_mask = 0x00FF;
2374
        else
2375
                hwconf->vector_mask = 0x000F;
2376
        for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
2377
                if (regs[12] & bits)
2378
                        hwconf->baud_base[i] = 921600;
2379
                else
2380
                        hwconf->baud_base[i] = 115200;
2381
        }
2382
        scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
2383
        outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);
2384
        outb(0, cap + UART_EFR); /* EFR is the same as FCR */
2385
        outb(scratch2, cap + UART_LCR);
2386
        outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);
2387
        scratch = inb(cap + UART_IIR);
2388
        if (scratch & 0xC0)
2389
                hwconf->uart_type = PORT_16550A;
2390
        else
2391
                hwconf->uart_type = PORT_16450;
2392
        if (id == 1)
2393
                hwconf->ports = 8;
2394
        else
2395
                hwconf->ports = 4;
2396
        return (hwconf->ports);
2397
}
2398
 
2399
#define CHIP_SK         0x01    /* Serial Data Clock  in Eprom */
2400
#define CHIP_DO         0x02    /* Serial Data Output in Eprom */
2401
#define CHIP_CS         0x04    /* Serial Chip Select in Eprom */
2402
#define CHIP_DI         0x08    /* Serial Data Input  in Eprom */
2403
#define EN_CCMD         0x000   /* Chip's command register     */
2404
#define EN0_RSARLO      0x008   /* Remote start address reg 0  */
2405
#define EN0_RSARHI      0x009   /* Remote start address reg 1  */
2406
#define EN0_RCNTLO      0x00A   /* Remote byte count reg WR    */
2407
#define EN0_RCNTHI      0x00B   /* Remote byte count reg WR    */
2408
#define EN0_DCFG        0x00E   /* Data configuration reg WR   */
2409
#define EN0_PORT        0x010   /* Rcv missed frame error counter RD */
2410
#define ENC_PAGE0       0x000   /* Select page 0 of chip registers   */
2411
#define ENC_PAGE3       0x0C0   /* Select page 3 of chip registers   */
2412
static int mxser_read_register(int port, unsigned short *regs)
2413
{
2414
        int i, k, value, id;
2415
        unsigned int j;
2416
 
2417
        id = mxser_program_mode(port);
2418
        if (id < 0)
2419
                return (id);
2420
        for (i = 0; i < 14; i++) {
2421
                k = (i & 0x3F) | 0x180;
2422
                for (j = 0x100; j > 0; j >>= 1) {
2423
                        outb(CHIP_CS, port);
2424
                        if (k & j) {
2425
                                outb(CHIP_CS | CHIP_DO, port);
2426
                                outb(CHIP_CS | CHIP_DO | CHIP_SK, port);        /* A? bit of read */
2427
                        } else {
2428
                                outb(CHIP_CS, port);
2429
                                outb(CHIP_CS | CHIP_SK, port);  /* A? bit of read */
2430
                        }
2431
                }
2432
                (void) inb(port);
2433
                value = 0;
2434
                for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
2435
                        outb(CHIP_CS, port);
2436
                        outb(CHIP_CS | CHIP_SK, port);
2437
                        if (inb(port) & CHIP_DI)
2438
                                value |= j;
2439
                }
2440
                regs[i] = value;
2441
                outb(0, port);
2442
        }
2443
        mxser_normal_mode(port);
2444
        return (id);
2445
}
2446
 
2447
static int mxser_program_mode(int port)
2448
{
2449
        int id, i, j, n;
2450
        unsigned long flags;
2451
 
2452
        save_flags(flags);
2453
        cli();
2454
        outb(0, port);
2455
        outb(0, port);
2456
        outb(0, port);
2457
        (void) inb(port);
2458
        (void) inb(port);
2459
        outb(0, port);
2460
        (void) inb(port);
2461
        restore_flags(flags);
2462
        id = inb(port + 1) & 0x1F;
2463
        if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != CI104J_ASIC_ID) &&
2464
                (id != C102_ASIC_ID) && (id != CI132_ASIC_ID) && (id != CI134_ASIC_ID))
2465
                return (-1);
2466
        for (i = 0, j = 0; i < 4; i++) {
2467
                n = inb(port + 2);
2468
                if (n == 'M') {
2469
                        j = 1;
2470
                } else if ((j == 1) && (n == 1)) {
2471
                        j = 2;
2472
                        break;
2473
                } else
2474
                        j = 0;
2475
        }
2476
        if (j != 2)
2477
                id = -2;
2478
        return (id);
2479
}
2480
 
2481
static void mxser_normal_mode(int port)
2482
{
2483
        int i, n;
2484
 
2485
        outb(0xA5, port + 1);
2486
        outb(0x80, port + 3);
2487
        outb(12, port + 0);      /* 9600 bps */
2488
        outb(0, port + 1);
2489
        outb(0x03, port + 3);   /* 8 data bits */
2490
        outb(0x13, port + 4);   /* loop back mode */
2491
        for (i = 0; i < 16; i++) {
2492
                n = inb(port + 5);
2493
                if ((n & 0x61) == 0x60)
2494
                        break;
2495
                if ((n & 1) == 1)
2496
                        (void) inb(port);
2497
        }
2498
        outb(0x00, port + 4);
2499
}

powered by: WebSVN 2.1.0

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