MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / char / mxser.c-bak-02152006
blob881b677164a701eb70ee11c79b18ea1da6a68944
1 /*
2  *          mxser.c  -- MOXA Smartio/Industio family multiport serial driver.
3  *
4  *      Copyright (C) 1999-2001  Moxa Technologies (support@moxa.com.tw).
5  *
6  *      This code is loosely based on the Linux serial driver, written by
7  *      Linus Torvalds, Theodore T'so and others.
8  *
9  *      This program is free software; you can redistribute it and/or modify
10  *      it under the terms of the GNU General Public License as published by
11  *      the Free Software Foundation; either version 2 of the License, or
12  *      (at your option) any later version.
13  *
14  *      This program is distributed in the hope that it will be useful,
15  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *      GNU General Public License for more details.
18  *
19  *      You should have received a copy of the GNU General Public License
20  *      along with this program; if not, write to the Free Software
21  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *      
23  *      Original release        10/26/00
24  *
25  *      02/06/01        Support MOXA Industio family boards.
26  *      02/06/01        Support TIOCGICOUNT.
27  *      02/06/01        Fix the problem for connecting to serial mouse.
28  *      02/06/01        Fix the problem for H/W flow control.
29  *      02/06/01        Fix the compling warning when CONFIG_PCI        
30  *                      don't be defined.
31  *      08/12/04        Add to supprt special baud rate
32  *      09/17/04        To support by pass flip, and directly send to ldisc
33  *      12/28/04        Add to support TIOCSBRK, TIOCCBRK ioctl.
34  *      12/31/04        Add TICOM_BRK, TICOM_PARITY & TIOCM_FRAME on TIOCMIWAIT input argument for Moxa
35  *                      private RealCOM used.
36  *      01/04/05        Add TICOM_XOFFHOLD and use buf_overrun to note xoff hold to support RealCOM.
37  *      02/04/05        Add to support for Q-Free specical used.
38  *      11/22/05        Porting to Moxa Embedded system.
39  */
40 #include <linux/config.h>
41 #include <asm/arch/cpe/cpe.h>
42 #include <linux/module.h>
43 #include <asm/arch/cpe_int.h>
44 #include <linux/version.h>
45 #include <linux/autoconf.h>
46 #include <linux/errno.h>
47 #include <linux/signal.h>
48 #include <linux/sched.h>
49 #include <linux/timer.h>
50 #include <linux/interrupt.h>
51 #include <linux/tty.h>
52 #include <linux/tty_flip.h>
53 #include <linux/serial.h>
54 #include <linux/serial_reg.h>
56 #include <linux/major.h>
57 #include <linux/string.h>
58 #include <linux/fcntl.h>
59 #include <linux/ptrace.h>
60 #include <linux/ioport.h>
61 #include <linux/mm.h>
62 #include <linux/smp_lock.h>
63 #include <linux/delay.h>
64 #include <linux/init.h>
66 #include <asm/system.h>
67 #include <asm/io.h>
68 #include <asm/irq.h>
69 #include <asm/segment.h>
70 #include <asm/bitops.h>
72 #define VERSION_CODE(ver,rel,seq)       ((ver << 16) | (rel << 8) | seq)
74 #define MXSER_VERSION   "2.0"
75 #define MXSERMAJOR       30     
76 #define MXSERCUMAJOR     35     
78 #ifdef CONFIG_PCI
79 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
80 #include <linux/bios32.h>
81 #endif
82 #include <linux/pci.h>
83 #endif /* ENABLE_PCI */
85 #include <asm/uaccess.h>
86 #define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)
87 #define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)
89 #ifdef CONFIG_ARCH_IA240        // add by Victor Yu. 02-15-2006, to use embedded UART
90 #undef UART_RX
91 #undef UART_TX
92 #undef UART_DLL
93 #undef UART_TRG
94 #undef UART_DLM
95 #undef UART_IER
96 #undef UART_FCTR
97 #undef UART_IIR
98 #undef UART_FCR
99 #undef UART_EFR
100 #undef UART_LCR
101 #undef UART_MCR
102 #undef UART_LSR
103 #undef UART_MSR
104 #undef UART_SCR
105 #undef UART_EMSR
106 #define UART_RX         0
107 #define UART_TX         0
108 #define UART_DLL        0
109 #define UART_TRG        0
110 #define UART_DLM        4
111 #define UART_IER        4
112 #define UART_FCTR       4
113 #define UART_IIR        8
114 #define UART_FCR        8
115 #define UART_EFR        8
116 #define UART_LCR        12
117 #define UART_MCR        16
118 #define UART_LSR        20
119 #define UART_MSR        24
120 #define UART_SCR        28
121 #define UART_EMSR       28
122 #endif
124 #define MXSER_EVENT_TXLOW        1
125 #define MXSER_EVENT_HANGUP       2
127 #define SERIAL_DO_RESTART
129 #define MXSER_BOARDS            4       /* Max. boards */
130 #define MXSER_PORTS             32      /* Max. ports */
131 #define MXSER_PORTS_PER_BOARD   8       /* Max. ports per board*/
132 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
133 #define MXSER_ISR_PASS_LIMIT    8192    // add by Victor Yu. 02-04-2005
134 #else
135 #define MXSER_ISR_PASS_LIMIT    256     // mask by Victor Yu. 02-04-2005
136 #endif
138 #define MXSER_ERR_IOADDR        -1
139 #define MXSER_ERR_IRQ           -2
140 #define MXSER_ERR_IRQ_CONFLIT   -3
141 #define MXSER_ERR_VECTOR        -4
143 #define SERIAL_TYPE_NORMAL      1
144 #define SERIAL_TYPE_CALLOUT     2
146 #define WAKEUP_CHARS            256
148 #define UART_MCR_AFE            0x20
149 #define UART_LSR_SPECIAL        0x1E
151 #if 0
152 #define PORTNO(x)       (MINOR((x)->device) - (x)->driver.minor_start)
153 #else
154 #define PORTNO(x)       ((x)->index)
155 #endif
157 #define RELEVANT_IFLAG(iflag)   (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
159 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
161 #ifndef MIN
162 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
163 #endif
165 enum    {
166         IA240_BOARD=1,
169 static char *mxser_brdname[] = {
170         "MU860 UART",
173 static int mxser_numports[] = {
174         4,
177 typedef struct {
178         unsigned short  vendor_id;
179         unsigned short  device_id;
180         unsigned short  board_type;
181 }       mxser_pciinfo;
183 static mxser_pciinfo    mxser_pcibrds[] = {
184         {0x1393,0x0001,IA240_BOARD},
188  *      MOXA ioctls
189  */
190 #define MOXA                    0x400
191 #define MOXA_GETDATACOUNT     (MOXA + 23)
192 #define MOXA_GET_CONF         (MOXA + 35)
193 #define MOXA_DIAGNOSE         (MOXA + 50)
194 #define MOXA_CHKPORTENABLE    (MOXA + 60)
195 #define MOXA_HighSpeedOn      (MOXA + 61)
196 #define MOXA_GET_MAJOR        (MOXA + 63)
197 #define MOXA_GET_CUMAJOR      (MOXA + 64)
198 #define MOXA_GETMSTATUS       (MOXA + 65)
200 // following add by Victor Yu. 01-05-2004
201 #define MOXA_SET_OP_MODE      (MOXA + 66)
202 #define MOXA_GET_OP_MODE      (MOXA + 67)
204 #if 1   // add by Victor Yu. 01-26-2005
205 #define MOXA_UNWAIT             (MOXA+200)
206 #endif
208 #define RS232_MODE              0
209 #define RS485_2WIRE_MODE        1
210 #define RS422_MODE              2
211 #define RS485_4WIRE_MODE        3
212 #define OP_MODE_MASK            3
213 // above add by Victor Yu. 01-05-2004
215 #define CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE
216 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
217 #define MOXA_SET_SPECIAL_BAUD_RATE      (MOXA+68)
218 #define MOXA_GET_SPECIAL_BAUD_RATE      (MOXA+69)
219 #endif
221 static int ttymajor=MXSERMAJOR;
222 static int calloutmajor=MXSERCUMAJOR;
223 static int verbose=0;
225 /* Variables for insmod */
226 MODULE_AUTHOR("Victor Yu.");
227 MODULE_DESCRIPTION("MOXA MU860 UART Device Driver");
229 typedef struct _moxa_pci_info {
230         unsigned short busNum;
231         unsigned short devNum;
232         struct pci_dev  *pdev;  // add by Victor Yu. 06-23-2003
233 } moxa_pci_info;
235 struct mxser_hwconf {
236         int             board_type;
237         int             ports;
238         int             irq;
239         int             vector;
240         int             vector_mask;
241         int             uart_type;
242         int             ioaddr[MXSER_PORTS_PER_BOARD];
243         int             baud_base[MXSER_PORTS_PER_BOARD];
244         moxa_pci_info   pciInfo;
245         int             IsMoxaMustChipFlag;     // add by Victor Yu. 08-30-2002
246         int             MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD];       // add by Victor Yu. 09-04-2002
247         int             opmode_ioaddr[MXSER_PORTS_PER_BOARD];   // add by Victor Yu. 01-05-2004
250 struct mxser_struct {
251         int                     port;
252         int                     base;           /* port base address */
253         int                     irq;            /* port using irq no. */
254         int                     vector;         /* port irq vector */
255         int                     vectormask;     /* port vector mask */
256         int                     rx_trigger;     /* Rx fifo trigger level */
257         int                     baud_base;      /* max. speed */
258         int                     flags;          /* defined in tty.h */
259         int                     type;           /* UART type */
260         struct tty_struct *     tty;
261         int                     read_status_mask;
262         int                     ignore_status_mask;
263         int                     xmit_fifo_size;
264         int                     custom_divisor;
265         int                     x_char;         /* xon/xoff character */
266         int                     close_delay;
267         unsigned short          closing_wait;
268         int                     IER;            /* Interrupt Enable Register */
269         int                     MCR;            /* Modem control register */
270         unsigned long           event;
271         int                     count;          /* # of fd on device */
272         int                     blocked_open;   /* # of blocked opens */
273 #if 0
274         long                    session;        /* Session of opening process */
275         long                    pgrp;           /* pgrp of opening process */
276 #endif
277         unsigned char           *xmit_buf;
278         int                     xmit_head;
279         int                     xmit_tail;
280         int                     xmit_cnt;
281         struct work_struct      tqueue;
282         struct termios          normal_termios;
283         wait_queue_head_t       open_wait;
284         wait_queue_head_t       close_wait;
285         wait_queue_head_t       delta_msr_wait;
286         struct async_icount     icount; /* kernel counters for the 4 input interrupts */
287         int                     timeout;
288         int                     IsMoxaMustChipFlag;     // add by Victor Yu. 08-30-2002
289         int                     MaxCanSetBaudRate;      // add by Victor Yu. 09-04-2002
290         int                     opmode_ioaddr;  // add by Victor Yu. 01-05-2004
291 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
292         int                     speed;
293 #endif
296 struct mxser_log {
297         int     tick;
298         int     rxcnt[MXSER_PORTS];
299         int     txcnt[MXSER_PORTS];
302 struct mxser_mstatus{
303        tcflag_t cflag;
304        int      cts;
305        int      dsr;
306        int      ri;
307        int      dcd;
310 static  struct mxser_mstatus GMStatus[MXSER_PORTS];
312 static struct tty_driver        mxvar_sdriver;
313 static struct mxser_struct      mxvar_table[MXSER_PORTS];
314 static struct termios *         mxvar_termios[MXSER_PORTS+1];
315 static struct termios *         mxvar_termios_locked[MXSER_PORTS+1];
316 static struct mxser_log         mxvar_log;
317 static int                      mxvar_diagflag;
319  * mxvar_tmp_buf is used as a temporary buffer by serial_write. We need
320  * to lock it in case the memcpy_fromfs blocks while swapping in a page,
321  * and some other program tries to do a serial write at the same time.
322  * Since the lock will only come under contention when the system is
323  * swapping and available memory is low, it makes sense to share one
324  * buffer across all the serial ports, since it significantly saves
325  * memory if large numbers of serial ports are open.
326  */
327 static unsigned char *          mxvar_tmp_buf;
328 static struct semaphore         mxvar_tmp_buf_sem;
331  * This is used to figure out the divisor speeds and the timeouts
332  */
333 #define B50_INDEX       1       // add by Victor Yu. 08-12-2004
334 static int mxvar_baud_table[] = {
335         0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
336         9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 0 };
337 #define BAUD_TABLE_NO   (sizeof(mxvar_baud_table)/sizeof(int))
338         
339 struct mxser_hwconf mxsercfg[MXSER_BOARDS];
342  * static functions:
343  */
344 static void     mxser_getcfg(int board,struct mxser_hwconf *hwconf);
345 int             mxser_init(void);
346 static int      mxser_get_PCI_conf(int ,int ,int ,struct mxser_hwconf *);
347 static void     mxser_do_softint(void *);
348 static int      mxser_open(struct tty_struct *, struct file *);
349 static void     mxser_close(struct tty_struct *, struct file *);
350 static int      mxser_write(struct tty_struct *, int, const unsigned char *, int);
351 static int      mxser_write_room(struct tty_struct *);
352 static void     mxser_flush_buffer(struct tty_struct *);
353 static int      mxser_chars_in_buffer(struct tty_struct *);
354 static void     mxser_flush_chars(struct tty_struct *);
355 static void     mxser_put_char(struct tty_struct *, unsigned char);
356 static int      mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);
357 static int      mxser_ioctl_special(unsigned int, unsigned long);
358 static void     mxser_throttle(struct tty_struct *);
359 static void     mxser_unthrottle(struct tty_struct *);
360 static void     mxser_set_termios(struct tty_struct *, struct termios *);
361 static void     mxser_stop(struct tty_struct *);
362 static void     mxser_start(struct tty_struct *);
363 static void     mxser_hangup(struct tty_struct *);
364 static irqreturn_t      mxser_interrupt(int, void *, struct pt_regs *);
365 static inline void mxser_receive_chars(struct mxser_struct *, int *);
366 static inline void mxser_transmit_chars(struct mxser_struct *);
367 static inline void mxser_check_modem_status(struct mxser_struct *, int);
368 static int      mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
369 static int      mxser_startup(struct mxser_struct *);
370 static void     mxser_shutdown(struct mxser_struct *);
371 static int      mxser_change_speed(struct mxser_struct *, struct termios *old_termios);
372 static int      mxser_get_serial_info(struct mxser_struct *, struct serial_struct *);
373 static int      mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);
374 static int      mxser_get_lsr_info(struct mxser_struct *, unsigned int *);
375 static void     mxser_send_break(struct mxser_struct *, int);
376 static int      mxser_get_modem_info(struct mxser_struct *, unsigned int *);
377 static int      mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);
378 static void     mxser_wait_until_sent(struct tty_struct *tty, int timeout);
381 // follwoing is modified by Victor Yu. 08-15-2002
383 // follow just for Moxa Must chip define.
385 // when LCR register (offset 0x03) write following value,
386 // the Must chip will enter enchance mode. And write value
387 // on EFR (offset 0x02) bit 6,7 to change bank.
388 #define MOXA_MUST_ENTER_ENCHANCE        0xBF
390 // when enhance mode enable, access on general bank register
391 #define MOXA_MUST_GDL_REGISTER          7
392 #define MOXA_MUST_GDL_MASK              0x7F
393 #define MOXA_MUST_GDL_HAS_BAD_DATA      0x80
395 #define MOXA_MUST_LSR_RERR              0x80    // error in receive FIFO
396 // enchance register bank select and enchance mode setting register
397 // when LCR register equal to 0xBF
398 #define MOXA_MUST_EFR_REGISTER          2
399 // enchance mode enable
400 #define MOXA_MUST_EFR_EFRB_ENABLE       0x10
401 // enchance reister bank set 0, 1, 2
402 #define MOXA_MUST_EFR_BANK0             0x00
403 #define MOXA_MUST_EFR_BANK1             0x40
404 #define MOXA_MUST_EFR_BANK2             0x80
405 #define MOXA_MUST_EFR_BANK3             0xC0
406 #define MOXA_MUST_EFR_BANK_MASK         0xC0
408 // set XON1 value register, when LCR=0xBF and change to bank0
409 #define MOXA_MUST_XON1_REGISTER         4
411 // set XON2 value register, when LCR=0xBF and change to bank0
412 #define MOXA_MUST_XON2_REGISTER         5
414 // set XOFF1 value register, when LCR=0xBF and change to bank0
415 #define MOXA_MUST_XOFF1_REGISTER        6
417 // set XOFF2 value register, when LCR=0xBF and change to bank0
418 #define MOXA_MUST_XOFF2_REGISTER        7
420 #define MOXA_MUST_RBRTL_REGISTER        4
421 #define MOXA_MUST_RBRTH_REGISTER        5
422 #define MOXA_MUST_RBRTI_REGISTER        6
423 #define MOXA_MUST_THRTL_REGISTER        7
424 #define MOXA_MUST_ENUM_REGISTER         4
425 #define MOXA_MUST_HWID_REGISTER         5
426 #define MOXA_MUST_ECR_REGISTER          6
427 #define MOXA_MUST_CSR_REGISTER          7
429 // good data mode enable
430 #define MOXA_MUST_FCR_GDA_MODE_ENABLE   0x20
431 // only good data put into RxFIFO
432 #define MOXA_MUST_FCR_GDA_ONLY_ENABLE   0x10
434 // enable CTS interrupt
435 #define MOXA_MUST_IER_ECTSI             0x80
436 // eanble RTS interrupt
437 #define MOXA_MUST_IER_ERTSI             0x40
438 // enable Xon/Xoff interrupt
439 #define MOXA_MUST_IER_XINT              0x20
440 // enable GDA interrupt
441 #define MOXA_MUST_IER_EGDAI             0x10
443 #define MOXA_MUST_RECV_ISR              (UART_IER_RDI | MOXA_MUST_IER_EGDAI)
445 // GDA interrupt pending
446 #define MOXA_MUST_IIR_GDA               0x1C
447 #define MOXA_MUST_IIR_RDA               0x04
448 #define MOXA_MUST_IIR_RTO               0x0C
449 #define MOXA_MUST_IIR_LSR               0x06
451 // recieved Xon/Xoff or specical interrupt pending
452 #define MOXA_MUST_IIR_XSC               0x10
454 // RTS/CTS change state interrupt pending
455 #define MOXA_MUST_IIR_RTSCTS            0x20
456 #define MOXA_MUST_IIR_MASK              0x3E
458 #define MOXA_MUST_MCR_XON_FLAG          0x40
459 #define MOXA_MUST_MCR_XON_ANY           0x80
460 #define MOXA_MUST_HARDWARE_ID           0x01
461 #define MOXA_MUST_HARDWARE_ID1          0x02
463 // software flow control on chip mask value
464 #define MOXA_MUST_EFR_SF_MASK           0x0F
465 // send Xon1/Xoff1
466 #define MOXA_MUST_EFR_SF_TX1            0x08
467 // send Xon2/Xoff2
468 #define MOXA_MUST_EFR_SF_TX2            0x04
469 // send Xon1,Xon2/Xoff1,Xoff2
470 #define MOXA_MUST_EFR_SF_TX12           0x0C
471 // don't send Xon/Xoff
472 #define MOXA_MUST_EFR_SF_TX_NO          0x00
473 // Tx software flow control mask
474 #define MOXA_MUST_EFR_SF_TX_MASK        0x0C
475 // don't receive Xon/Xoff
476 #define MOXA_MUST_EFR_SF_RX_NO          0x00
477 // receive Xon1/Xoff1
478 #define MOXA_MUST_EFR_SF_RX1            0x02
479 // receive Xon2/Xoff2
480 #define MOXA_MUST_EFR_SF_RX2            0x01
481 // receive Xon1,Xon2/Xoff1,Xoff2
482 #define MOXA_MUST_EFR_SF_RX12           0x03
483 // Rx software flow control mask
484 #define MOXA_MUST_EFR_SF_RX_MASK        0x03
486 #define MOXA_MUST_MIN_XOFFLIMIT         66
487 #define MOXA_MUST_MIN_XONLIMIT          20
489 #ifndef UCHAR
490 typedef unsigned char   UCHAR;
491 #endif
493 #define CHECK_MOXA_MUST_XOFFLIMIT(info) {       \
494         if ( (info)->IsMoxaMustChipFlag &&      \
495          (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) {       \
496                 (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT;   \
497                 (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT;     \
498         }       \
501 #define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
502         UCHAR   __oldlcr, __efr;        \
503         __oldlcr = inb((baseio)+UART_LCR);      \
504         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
505         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
506         __efr |= MOXA_MUST_EFR_EFRB_ENABLE;     \
507         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
508         outb(__oldlcr, (baseio)+UART_LCR);      \
511 #define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) {       \
512         UCHAR   __oldlcr, __efr;        \
513         __oldlcr = inb((baseio)+UART_LCR);      \
514         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
515         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
516         __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;    \
517         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
518         outb(__oldlcr, (baseio)+UART_LCR);      \
521 #define SET_MOXA_MUST_XON1_VALUE(baseio, Value) {       \
522         UCHAR   __oldlcr, __efr;        \
523         __oldlcr = inb((baseio)+UART_LCR);      \
524         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
525         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
526         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
527         __efr |= MOXA_MUST_EFR_BANK0;   \
528         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
529         outb((UCHAR)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \
530         outb(__oldlcr, (baseio)+UART_LCR);      \
533 #define SET_MOXA_MUST_XON2_VALUE(baseio, Value) {       \
534         UCHAR   __oldlcr, __efr;        \
535         __oldlcr = inb((baseio)+UART_LCR);      \
536         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
537         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
538         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
539         __efr |= MOXA_MUST_EFR_BANK0;   \
540         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
541         outb((UCHAR)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \
542         outb(__oldlcr, (baseio)+UART_LCR);      \
545 #define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) {      \
546         UCHAR   __oldlcr, __efr;        \
547         __oldlcr = inb((baseio)+UART_LCR);      \
548         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
549         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
550         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
551         __efr |= MOXA_MUST_EFR_BANK0;   \
552         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
553         outb((UCHAR)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER);        \
554         outb(__oldlcr, (baseio)+UART_LCR);      \
557 #define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) {      \
558         UCHAR   __oldlcr, __efr;        \
559         __oldlcr = inb((baseio)+UART_LCR);      \
560         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
561         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
562         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
563         __efr |= MOXA_MUST_EFR_BANK0;   \
564         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
565         outb((UCHAR)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER);        \
566         outb(__oldlcr, (baseio)+UART_LCR);      \
569 #define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) {      \
570         UCHAR   __oldlcr, __efr;        \
571         __oldlcr = inb((baseio)+UART_LCR);      \
572         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
573         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
574         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
575         __efr |= MOXA_MUST_EFR_BANK1;   \
576         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
577         outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER);        \
578         outb(__oldlcr, (baseio)+UART_LCR);      \
581 #define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) {      \
582         UCHAR   __oldlcr, __efr;        \
583         __oldlcr = inb((baseio)+UART_LCR);      \
584         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
585         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
586         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
587         __efr |= MOXA_MUST_EFR_BANK1;   \
588         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
589         outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER);        \
590         outb(__oldlcr, (baseio)+UART_LCR);      \
593 #define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) {      \
594         UCHAR   __oldlcr, __efr;        \
595         __oldlcr = inb((baseio)+UART_LCR);      \
596         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
597         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
598         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
599         __efr |= MOXA_MUST_EFR_BANK1;   \
600         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
601         outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER);        \
602         outb(__oldlcr, (baseio)+UART_LCR);      \
605 #define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) {      \
606         UCHAR   __oldlcr, __efr;        \
607         __oldlcr = inb((baseio)+UART_LCR);      \
608         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
609         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
610         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
611         __efr |= MOXA_MUST_EFR_BANK1;   \
612         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
613         outb((UCHAR)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER);        \
614         outb(__oldlcr, (baseio)+UART_LCR);      \
617 #define MOXA_MUST_RBRL_VALUE    4
618 #define SET_MOXA_MUST_FIFO_VALUE(info) {        \
619         UCHAR   __oldlcr, __efr;        \
620         __oldlcr = inb((info)->base+UART_LCR);  \
621         outb(MOXA_MUST_ENTER_ENCHANCE, (info)->base+UART_LCR);  \
622         __efr = inb((info)->base+MOXA_MUST_EFR_REGISTER);       \
623         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
624         __efr |= MOXA_MUST_EFR_BANK1;   \
625         outb(__efr, (info)->base+MOXA_MUST_EFR_REGISTER);       \
626         outb((UCHAR)0, (info)->base+MOXA_MUST_THRTL_REGISTER);  \
627         outb((UCHAR)((info)->rx_trigger), (info)->base+MOXA_MUST_RBRTH_REGISTER);       \
628         /*      \
629         outb((UCHAR)((info)->rx_trigger/4),     \
630                 (info)->base+MOXA_MUST_RBRTL_REGISTER); \
631         */      \
632         if ( (info)->rx_trigger <= MOXA_MUST_RBRL_VALUE ) {     \
633                 outb((UCHAR)0, (info)->base+MOXA_MUST_RBRTI_REGISTER);  \
634                 outb((UCHAR)0, (info)->base+MOXA_MUST_RBRTL_REGISTER);  \
635         } else {        \
636                 outb((UCHAR)((info)->rx_trigger-MOXA_MUST_RBRL_VALUE),  \
637                         (info)->base+MOXA_MUST_RBRTI_REGISTER); \
638                 outb((UCHAR)((info)->rx_trigger-MOXA_MUST_RBRL_VALUE),  \
639                         (info)->base+MOXA_MUST_RBRTL_REGISTER); \
640         }       \
641         outb(__oldlcr, (info)->base+UART_LCR);  \
642 }               
644 #define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) {       \
645         UCHAR   __oldlcr, __efr;        \
646         __oldlcr = inb((baseio)+UART_LCR);      \
647         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
648         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
649         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
650         __efr |= MOXA_MUST_EFR_BANK2;   \
651         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
652         outb((UCHAR)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \
653         outb(__oldlcr, (baseio)+UART_LCR);      \
656 #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) {        \
657         UCHAR   __oldlcr, __efr;        \
658         __oldlcr = inb((baseio)+UART_LCR);      \
659         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
660         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
661         __efr &= ~MOXA_MUST_EFR_BANK_MASK;      \
662         __efr |= MOXA_MUST_EFR_BANK2;   \
663         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
664         *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER);   \
665         outb(__oldlcr, (baseio)+UART_LCR);      \
668 #define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) {        \
669         UCHAR   __oldlcr, __efr;        \
670         __oldlcr = inb((baseio)+UART_LCR);      \
671         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
672         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
673         __efr &= ~MOXA_MUST_EFR_SF_MASK;        \
674         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
675         outb(__oldlcr, (baseio)+UART_LCR);      \
678 #define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {   \
679         UCHAR   __oldlcr, __efr;        \
680         __oldlcr = inb((baseio)+UART_LCR);      \
681         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
682         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
683         __efr &= ~MOXA_MUST_EFR_SF_MASK;        \
684         __efr |= MOXA_MUST_EFR_SF_TX1;  \
685         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
686         outb(__oldlcr, (baseio)+UART_LCR);      \
689 #define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {     \
690         UCHAR   __oldlcr, __efr;        \
691         __oldlcr = inb((baseio)+UART_LCR);      \
692         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
693         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
694         __efr &= ~MOXA_MUST_EFR_SF_TX_MASK;     \
695         __efr |= MOXA_MUST_EFR_SF_TX1;  \
696         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
697         outb(__oldlcr, (baseio)+UART_LCR);      \
700 #define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) {    \
701         UCHAR   __oldlcr, __efr;        \
702         __oldlcr = inb((baseio)+UART_LCR);      \
703         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
704         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
705         __efr &= ~MOXA_MUST_EFR_SF_TX_MASK;     \
706         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
707         outb(__oldlcr, (baseio)+UART_LCR);      \
710 #define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {   \
711         UCHAR   __oldlcr, __efr;        \
712         __oldlcr = inb((baseio)+UART_LCR);      \
713         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
714         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
715         __efr &= ~MOXA_MUST_EFR_SF_MASK;        \
716         __efr |= MOXA_MUST_EFR_SF_RX1;  \
717         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
718         outb(__oldlcr, (baseio)+UART_LCR);      \
721 #define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {     \
722         UCHAR   __oldlcr, __efr;        \
723         __oldlcr = inb((baseio)+UART_LCR);      \
724         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
725         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
726         __efr &= ~MOXA_MUST_EFR_SF_RX_MASK;     \
727         __efr |= MOXA_MUST_EFR_SF_RX1;  \
728         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
729         outb(__oldlcr, (baseio)+UART_LCR);      \
732 #define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) {    \
733         UCHAR   __oldlcr, __efr;        \
734         __oldlcr = inb((baseio)+UART_LCR);      \
735         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
736         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
737         __efr &= ~MOXA_MUST_EFR_SF_RX_MASK;     \
738         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
739         outb(__oldlcr, (baseio)+UART_LCR);      \
742 #define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) {  \
743         UCHAR   __oldlcr, __efr;        \
744         __oldlcr = inb((baseio)+UART_LCR);      \
745         outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
746         __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);   \
747         __efr &= ~MOXA_MUST_EFR_SF_MASK;        \
748         __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1);   \
749         outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);   \
750         outb(__oldlcr, (baseio)+UART_LCR);      \
753 #define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \
754         UCHAR   __oldmcr;       \
755         __oldmcr = inb((baseio)+UART_MCR);      \
756         __oldmcr |= MOXA_MUST_MCR_XON_ANY;      \
757         outb(__oldmcr, (baseio)+UART_MCR);      \
760 #define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) {        \
761         UCHAR   __oldmcr;       \
762         __oldmcr = inb((baseio)+UART_MCR);      \
763         __oldmcr &= ~MOXA_MUST_MCR_XON_ANY;     \
764         outb(__oldmcr, (baseio)+UART_MCR);      \
767 #define READ_MOXA_MUST_GDL(baseio)      inb((baseio)+MOXA_MUST_GDL_REGISTER)
769 #if 1
770 static int CheckIsMoxaMust(int io)
772         UCHAR   oldmcr, hwid;
774         outb(0, io+UART_LCR);
775         DISABLE_MOXA_MUST_ENCHANCE_MODE(io);
776         oldmcr = inb(io+UART_MCR);
777         outb(0, io+UART_MCR);
778         SET_MOXA_MUST_XON1_VALUE(io, 0x11);
779         if ( (hwid=inb(io+UART_MCR)) != 0 ) {
780                 outb(oldmcr, io+UART_MCR);
781                 return(0);
782         }
783         GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
784         if ( hwid != MOXA_MUST_HARDWARE_ID && hwid != MOXA_MUST_HARDWARE_ID1 )
785                 return(0);
786         //return(1);    // mask by Victor Yu. 02-10-2004
787         return((int)hwid);      // add by Victor Yu. 02-10-2004
789 #endif
790 // above is modified by Victor Yu. 08-15-2002
793  * The MOXA Smartio/Industio serial driver boot-time initialization code!
794  */
795 static int __init mxser_init_module(void)
797         int     ret;
799         if (verbose)
800                 printk("Loading module mxser ...\n");
801         ret = mxser_init();
802         if (verbose)
803                 printk("Done.\n");
804         return (ret);
807 static void __exit mxser_exit_module(void)
809         int i,err = 0;
812         if (verbose)
813                 printk("Unloading module mxser ...\n");
814 #if 1   // mask by Victor Yu. 11-22-2005
815         if ((err |= tty_unregister_driver(&mxvar_sdriver)))
816                 printk("Couldn't unregister MOXA Smartio/Industio family serial driver\n");
817 #else   // add by Victor Yu. 11-22-2005
818         put_tty_driver(&mxvar_sdriver);
819 #endif  // 11-22-2005
821         for(i=0; i<MXSER_BOARDS; i++){
822             struct pci_dev *pdev;
823             if(mxsercfg[i].board_type == -1)
824                 continue;
825             else{
826                 free_irq(mxsercfg[i].irq, &mxvar_table[i*MXSER_PORTS_PER_BOARD]);
827 #if 1   // mask by Victor Yu. 11-22-2005
828                 pdev = mxsercfg[i].pciInfo.pdev;
829                 release_region(pci_resource_start(pdev, 2),
830                         pci_resource_len(pdev, 2));
831                 release_region(pci_resource_start(pdev, 3),
832                         pci_resource_len(pdev, 3));
833 #endif  // 11-22-2005
834             }
835         }
836         
837         if (verbose)
838                 printk("Done.\n");
842 module_init(mxser_init_module);
843 module_exit(mxser_exit_module);
845 int mxser_initbrd(int board,struct mxser_hwconf *hwconf)
847         struct mxser_struct *   info;
848         unsigned long   flags;
849         int     retval;
850         int     i,n;
852         init_MUTEX(&mxvar_tmp_buf_sem); 
853         n = board*MXSER_PORTS_PER_BOARD;
854         info = &mxvar_table[n];
855         for ( i=0; i<hwconf->ports; i++, n++, info++ ) {
856                 if (verbose) {
857                         printk("        ttyM%d/cum%d at 0x%04x ", n, n, hwconf->ioaddr[i]);
858                         if ( hwconf->baud_base[i] == 115200 )
859                                 printk(" max. baud rate up to 115200 bps.\n");
860                         else
861                                 printk(" max. baud rate up to 921600 bps.\n");
862                 }
863                 info->port = n;
864                 info->base = hwconf->ioaddr[i];
865                 info->irq = hwconf->irq;
866                 info->vector = hwconf->vector;
867                 info->vectormask = hwconf->vector_mask;
868                 info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; // add by Victor Yu. 01-05-2004
869                 
870                 // following add by Victor Yu. 08-30-2002
871                 // Moxa Must UART support FIFO is 64bytes for Tx/Rx
872                 // but receive FIFO just can set up to 62 will be OK.
873                 info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag;
874                 //if ( hwconf->IsMoxaMustChipFlag )     // mask by Victor Yu. 02-10-2004
875                 if ( hwconf->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID ) {
876                         info->rx_trigger = 56;
877                 } else if ( hwconf->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID1 ) {
878 #if 1   // add by Victor 02-01-2005
879                         info->rx_trigger = 120;
880 #else
881                         info->rx_trigger = 1;
882 #endif
883                 } else {
884                 // above add by Victor Yu. 08-30-2002
885                         info->rx_trigger = 14;
886                 }
887                 info->baud_base = hwconf->baud_base[i];
888                 info->flags = ASYNC_SHARE_IRQ;
889                 info->type = hwconf->uart_type;
890                 if ( (info->type == PORT_16450) || (info->type == PORT_8250) )
891                     info->xmit_fifo_size = 1;
892                 else
893                     info->xmit_fifo_size = 16;
895                 // following add by Victor Yu. 08-30-2002
896                 // if ( info->IsMoxaMustChipFlag ) { // mask by Victor Yu. 02-10-2004
897                 if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID ) {
898                     info->xmit_fifo_size = 64;
899                     ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base);
900                 } else if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID1 ) {
901                     info->xmit_fifo_size = 128;
902                     ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base);
903                 }
904                 info->MaxCanSetBaudRate = hwconf->MaxCanSetBaudRate[i];
905                 // above add by Victor Yu. 08-30-2002
907                 info->custom_divisor = hwconf->baud_base[i] * 16;
908                 info->close_delay = 5*HZ/10;
909                 info->closing_wait = 30*HZ;
910                 INIT_WORK(&info->tqueue, mxser_do_softint, info);
911                 info->normal_termios = mxvar_sdriver.init_termios;
912                 init_waitqueue_head(&info->open_wait);
913                 init_waitqueue_head(&info->close_wait);
914                 init_waitqueue_head(&info->delta_msr_wait);
915                 info->icount.rx = info->icount.tx = 0;
916                 info->icount.cts = info->icount.dsr = 
917                     info->icount.dsr = info->icount.dcd = 0;
918                 info->icount.frame = info->icount.overrun = 
919                     info->icount.brk = info->icount.parity = 0;
920                 info->icount.buf_overrun = 0;
921 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add b Victor Yu. 08-12-2004
922                 info->speed = 38400;
923 #endif
924         }
926 #if 1   // mask by Victor Yu. 11-22-2005
927         request_region(hwconf->ioaddr[0],8*hwconf->ports,"mxser(io)");
928         if ((hwconf->pciInfo.busNum == 0)&&(hwconf->pciInfo.devNum == 0))
929                 request_region(hwconf->vector,1,"mxser(vector)");
930         else
931                 request_region(hwconf->vector,16,"mxser(vector)");
932 #endif
934         /*
935          * Allocate the IRQ if necessary
936          */
937         save_flags(flags);
939         n = board*MXSER_PORTS_PER_BOARD;
940         info = &mxvar_table[n];
942         cli();
943         retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info),
944                                  "mxser", info);
945         if ( retval ) {
946             restore_flags(flags);
947             printk("Board %d: %s", board, mxser_brdname[hwconf->board_type-1]);
948             printk("  Request irq fail,IRQ (%d) may be conflit with another device.\n",info->irq);
949             return(retval);
950         }
951         restore_flags(flags);
953         return 0;
956 static void mxser_getcfg(int board,struct mxser_hwconf *hwconf)
958         mxsercfg[board] = *hwconf;
961 static int mxser_get_PCI_conf(int busnum,int devnum,int board_type,struct mxser_hwconf *hwconf)
963         int             i;
964         unsigned int    ioaddress;
965         struct pci_dev  *pdev=hwconf->pciInfo.pdev;
967         hwconf->board_type = board_type;
968         hwconf->ports = mxser_numports[board_type-1];
969         ioaddress = pci_resource_start(pdev, 2);
970         request_region(pci_resource_start(pdev, 2),
971                pci_resource_len(pdev, 2),
972                "mxser(IO)");
973         for (i = 0; i < hwconf->ports; i++) {
974                 hwconf->ioaddr[i] = ioaddress + 8*i;
976                 // disable the interrupt
977                 outb(0, hwconf->ioaddr[i]+1);
978                 // flush FIFO
979                 outb(0x06, hwconf->ioaddr[i]+2);
980                 // flush interrupt
981                 inb(hwconf->ioaddr[i]+2);
982                 inb(hwconf->ioaddr[i]+6);
983                 inb(hwconf->ioaddr[i]+5);
984                 inb(hwconf->ioaddr[i]);
985 #if 0   // mask by Victor Yu. 12-28-2005
986                 if ( board_type == MXSER_BOARD_RC7000 )
987                         hwconf->MaxCanSetBaudRate[i] = 921600;
988                 else
989                         hwconf->MaxCanSetBaudRate[i] = 230400;
990 #else   // add by Victor Yu. 12-28-2005
991                 hwconf->MaxCanSetBaudRate[i] = 921600;
992 #endif
993         }
995         ioaddress = pci_resource_start(pdev, 3);
996         request_region(pci_resource_start(pdev, 3),
997                pci_resource_len(pdev, 3),
998                "mxser(vector)");
999         hwconf->vector = ioaddress;
1001         // following add by Victor Yu. 01-05-2004
1002         for (i = 0; i < hwconf->ports; i++) {
1003                 if ( i < 4 )
1004                         hwconf->opmode_ioaddr[i] = ioaddress + 4;
1005                 else
1006                         hwconf->opmode_ioaddr[i] = ioaddress + 0x0c;
1007         }
1008         outb(0, ioaddress+4);   // default set to RS232 mode
1009         outb(0, ioaddress+0x0c); //default set to RS232 mode
1010         // above add by Victor Yu. 01-05-2004
1012         hwconf->irq = hwconf->pciInfo.pdev->irq;
1014         // following add by Victor Yu. 08-30-2002
1015         hwconf->IsMoxaMustChipFlag = CheckIsMoxaMust(hwconf->ioaddr[0]);
1016         // above add by Victor Yu. 08-30-2002
1018         hwconf->uart_type = PORT_16550A;
1019         hwconf->vector_mask = 0;
1020         for (i = 0; i < hwconf->ports; i++) {
1021                 hwconf->vector_mask |= (1<<i);
1022                 hwconf->baud_base[i] = 921600;
1023         }
1024         return(0);
1026 #if 0   // mask by Victor Yu. 12-22-2005
1027 static void uc7110_hw_set(struct mxser_hwconf *hwconf)
1029         int     i;
1031         hwconf->board_type = UC7110_BOARD;
1032         hwconf->ports = 4;
1033         hwconf->irq = IRQ_UART;
1034         hwconf->vector = CPE_UART_INT_VEC_BASE;
1035         hwconf->vector_mask = 0x3c;
1036         hwconf->uart_type = PORT_16550A;
1037         hwconf->IsMoxaMustChipFlag = MOXA_MUST_HARDWARE_ID1;
1038         for ( i=0; i<4; i++ ) {
1039                 hwconf->ioaddr[i] = CPE_UART3_BASE + i * 32;
1040                 hwconf->baud_base[i] = 921600;
1041                 hwconf->MaxCanSetBaudRate[i] = 921600;
1042                 hwconf->opmode_ioaddr[i] = CPE_UART_MODE_BASE;
1043         }
1045 #endif
1047 int mxser_init(void)
1049         int                     i, m, retval, b;
1050         int                     ret1, ret2;
1051         struct pci_dev          *pdev=NULL;
1052         int                     n,index;
1053         unsigned char           busnum,devnum;
1054         struct mxser_hwconf     hwconf;
1056         printk("MOXA MU860 UART Device Driver version %s\n",MXSER_VERSION);
1058         /* Initialize the tty_driver structure */
1059         memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));
1060         mxvar_sdriver.magic = TTY_DRIVER_MAGIC;
1061         mxvar_sdriver.name = "ttyM";
1062         mxvar_sdriver.major = ttymajor;
1063         mxvar_sdriver.minor_start = 0;
1064         mxvar_sdriver.num = MXSER_PORTS + 1;
1065         mxvar_sdriver.type = TTY_DRIVER_TYPE_SERIAL;
1066         mxvar_sdriver.subtype = SERIAL_TYPE_NORMAL;
1067         mxvar_sdriver.init_termios = tty_std_termios;
1068         mxvar_sdriver.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
1069         mxvar_sdriver.flags = TTY_DRIVER_REAL_RAW;
1070         mxvar_sdriver.refcount = 0;
1071         mxvar_sdriver.termios = mxvar_termios;
1072         mxvar_sdriver.termios_locked = mxvar_termios_locked;
1074         mxvar_sdriver.open = mxser_open;
1075         mxvar_sdriver.close = mxser_close;
1076         mxvar_sdriver.write = mxser_write;
1077         mxvar_sdriver.put_char = mxser_put_char;
1078         mxvar_sdriver.flush_chars = mxser_flush_chars;
1079         mxvar_sdriver.write_room = mxser_write_room;
1080         mxvar_sdriver.chars_in_buffer = mxser_chars_in_buffer;
1081         mxvar_sdriver.flush_buffer = mxser_flush_buffer;
1082         mxvar_sdriver.ioctl = mxser_ioctl;
1083         mxvar_sdriver.throttle = mxser_throttle;
1084         mxvar_sdriver.unthrottle = mxser_unthrottle;
1085         mxvar_sdriver.set_termios = mxser_set_termios;
1086         mxvar_sdriver.stop = mxser_stop;
1087         mxvar_sdriver.start = mxser_start;
1088         mxvar_sdriver.hangup = mxser_hangup;
1089         mxvar_sdriver.wait_until_sent = mxser_wait_until_sent;
1091         printk("Tty devices major number = %d\n",ttymajor);
1093         mxvar_diagflag = 0;
1094         memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct));
1095         memset(&mxvar_log, 0, sizeof(struct mxser_log));
1097         m = 0;
1098 #if 0   // mask by Victor Yu. 12-22-2005
1099         uc7110_hw_set(&hwconf);
1100         if ( mxser_initbrd(m,&hwconf) < 0 )
1101                 return -1;
1102         mxser_getcfg(m,&hwconf);
1103         m++;
1104 #endif
1105 #if 0   // mask by Victor Yu. 12-28-2005 For Linux 2.6.x
1106 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
1107         if (pcibios_present()) {
1108 #else
1109         if (pci_present()) {
1110 #endif
1111 #else   // add by Victor Yu. 12-28-2005
1112         {
1113 #endif
1114                 n = sizeof (mxser_pcibrds)/sizeof (mxser_pciinfo);
1115                 index = 0;
1116                 b = 0;
1117                 while (b < n) {
1118                        pdev = pci_find_device(mxser_pcibrds[b].vendor_id,
1119                        mxser_pcibrds[b].device_id,
1120                        pdev);
1121 #if 0   // mask by Victor Yu. 12-28-2005, for Linux 2.6.x
1122                         if (pcibios_find_device(mxser_pcibrds[b].vendor_id,
1123                                                 mxser_pcibrds[b].device_id,
1124                                                 index,
1125                                                 &busnum,
1126                                                 &devnum) != 0) {
1127                                 b++;
1128                                 index = 0;
1129                                 continue;
1130                         }
1131                         hwconf.pciInfo.busNum = busnum;
1132                         hwconf.pciInfo.devNum = devnum;
1133                         hwconf.pciInfo.pdev = pdev;
1134                         printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",mxser_brdname[mxser_pcibrds[b].board_type-1],busnum,devnum >> 3);
1135                         index++;
1136 #else   // add by Victor Yu. 12-28-2005
1137                         if ( pdev == NULL ) {
1138                                 b++;
1139                                 continue;
1140                         }
1141                         hwconf.pciInfo.busNum = pdev->bus->number;
1142                         hwconf.pciInfo.devNum = pdev->devfn;
1143                         hwconf.pciInfo.pdev = pdev;
1144                         printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",mxser_brdname[mxser_pcibrds[b].board_type-1],pdev->bus->number,pdev->devfn >> 3);
1145 #endif
1146                         if ( m >= MXSER_BOARDS) {
1147                                 printk("Too many Smartio/Industio family boards find (maximum %d),board not configured\n",MXSER_BOARDS);
1148                         }
1149                         else {
1150                                 if ( pci_enable_device(pdev) ) {
1151                                         printk("Moxa SmartI/O PCI enable fail !\n");
1152                                         continue;
1153                                 }
1154                                 retval = mxser_get_PCI_conf(busnum,devnum,
1155                                         mxser_pcibrds[b].board_type,&hwconf);
1156                                 if (retval < 0) {
1157                                         if (retval == MXSER_ERR_IRQ)
1158                                                 printk("Invalid interrupt number,board not configured\n");
1159                                         else if (retval == MXSER_ERR_IRQ_CONFLIT)
1160                                                 printk("Invalid interrupt number,board not configured\n");
1161                                         else if (retval == MXSER_ERR_VECTOR)
1162                                                 printk("Invalid interrupt vector,board not configured\n");
1163                                         else if (retval == MXSER_ERR_IOADDR)
1164                                                 printk("Invalid I/O address,board not configured\n");
1165                                         continue;
1167                                 }
1169                                 if(mxser_initbrd(m,&hwconf)<0)
1170                                     continue;
1171                                 mxser_getcfg(m,&hwconf);
1172                                 m++;
1173                         }
1174                 }
1175         }
1177         for(i=m; i<MXSER_BOARDS; i++){
1178                 mxsercfg[i].board_type = -1;
1179         }
1180         
1182         ret1 = 0;
1183         ret2 = 0;
1184         if ( !(ret1=tty_register_driver(&mxvar_sdriver)) ){
1185                 return 0;
1186         }else
1187             printk("Couldn't install MOXA Smartio/Industio family driver !\n");
1190         if(ret1 || ret2){
1191             for(i=0; i<MXSER_BOARDS; i++){
1192                 if(mxsercfg[i].board_type == -1)
1193                     continue;
1194                 else{
1195                     free_irq(mxsercfg[i].irq, &mxvar_table[i*MXSER_PORTS_PER_BOARD]);
1196                 }
1197             }
1198             return -1;
1199         }
1200         
1201         return(0);
1204 static void mxser_do_softint(void *private_)
1206         struct mxser_struct *   info = (struct mxser_struct *)private_;
1207         struct tty_struct *     tty;
1209         tty = info->tty;
1211         if (tty) {
1212             if ( test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event) ) {
1213                 if ( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1214                  tty->ldisc.write_wakeup )
1215                 (tty->ldisc.write_wakeup)(tty);
1216                 wake_up_interruptible(&tty->write_wait);
1217             }
1218             if ( test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event) ) {
1219                 tty_hangup(tty);
1220             }
1221         }
1222         MOD_DEC_USE_COUNT;  
1226  * This routine is called whenever a serial port is opened.  It
1227  * enables interrupts for a serial port, linking in its async structure into
1228  * the IRQ chain.   It also performs the serial-specific
1229  * initialization for the tty structure.
1230  */
1231 static int mxser_open(struct tty_struct * tty, struct file * filp)
1233         struct mxser_struct *   info;
1234         int                     retval, line;
1235         unsigned long           page;
1236 #if 1   // add by Victor Yu. 12-28-2004
1237         unsigned long           flags;
1238 #endif
1240         line = PORTNO(tty);
1241         if ( line == MXSER_PORTS )
1242             return(0);
1243         if ( (line < 0) || (line > MXSER_PORTS) )
1244             return(-ENODEV);
1246         info = mxvar_table + line;
1247         if ( !info->base )
1248             return(-ENODEV);
1250         tty->driver_data = info;
1251 #if 0   // mask by Victor Yu. 12-28-2004
1252         info->tty = tty;
1253 #else   // add by Victor Yu. 12-28-2004
1254         save_flags(flags);
1255         cli();
1256         info->tty = tty;
1257         restore_flags(flags);
1258 #endif
1260         if ( !mxvar_tmp_buf ) {
1261             page = get_zeroed_page(GFP_KERNEL);
1262             if ( !page )
1263                 return(-ENOMEM);
1264             if ( mxvar_tmp_buf )
1265                 free_page(page);
1266             else
1267                 mxvar_tmp_buf = (unsigned char *)page;
1268         }
1270         /*
1271          * Start up serial port
1272          */
1273         retval = mxser_startup(info);
1274         if ( retval )
1275             return(retval);
1277         retval = mxser_block_til_ready(tty, filp, info);
1278         if ( retval )
1279             return(retval);
1281 #if 0   // mask by Victor Yu. 12-28-2004
1282         info->count++;
1283 #else   // add by Victor Yu. 12-28-2004
1284         save_flags(flags);
1285         cli();
1286         info->count++;
1287         restore_flags(flags);
1288 #endif
1289         MOD_INC_USE_COUNT;
1291         if ( (info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS) ) {
1292             *tty->termios = info->normal_termios;
1293             mxser_change_speed(info, 0);
1294         }
1296 #if 0   // mask by Victor Yu. 12-28-2004
1297         info->session = current->session;
1298         info->pgrp = current->pgrp;
1299         clear_bit(TTY_DONT_FLIP, &tty->flags);
1300 #else   // add by Victor Yu. 12-28-2004
1301         save_flags(flags);
1302         cli();
1303 #if 0
1304         info->session = current->session;
1305         info->pgrp = current->pgrp;
1306 #endif 
1307         clear_bit(TTY_DONT_FLIP, &tty->flags);
1308         restore_flags(flags);
1309 #endif
1311 /* unmark here for very high baud rate (ex. 921600 bps) used
1313 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
1314         tty->low_latency = 1;
1315 #endif
1316         return(0);
1320  * This routine is called when the serial port gets closed.  First, we
1321  * wait for the last remaining data to be sent.  Then, we unlink its
1322  * async structure from the interrupt chain if necessary, and we free
1323  * that IRQ if nothing is left in the chain.
1324  */
1325 static void mxser_close(struct tty_struct * tty, struct file * filp)
1327         struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
1328         unsigned long   flags;
1329         unsigned long   timeout;
1331         if ( PORTNO(tty) == MXSER_PORTS )
1332             return;
1333         if ( !info )
1334             return;
1336 #if 0   // mask by Victor Yu. 12-28-2004
1337         save_flags(flags);
1338         cli();
1339 #endif
1341         if ( tty_hung_up_p(filp) ) {
1342 #if 0   // mask by Victor Yu. 12-28-2004
1343             restore_flags(flags);
1344 #endif
1345             MOD_DEC_USE_COUNT;
1346             return;
1347         }
1349 #if 1   // add by Victor Yu. 12-28-2004
1350         save_flags(flags);
1351         cli();
1352 #endif
1353         if ( (tty->count == 1) && (info->count != 1) ) {
1354             /*
1355              * Uh, oh.  tty->count is 1, which means that the tty
1356              * structure will be freed.  Info->count should always
1357              * be one in these conditions.  If it's greater than
1358              * one, we've got real problems, since it means the
1359              * serial port won't be shutdown.
1360              */
1361             printk("mxser_close: bad serial port count; tty->count is 1, "
1362                    "info->count is %d\n", info->count);
1363             info->count = 1;
1364         }
1365         if ( --info->count < 0 ) {
1366             printk("mxser_close: bad serial port count for ttys%d: %d\n",
1367                    info->port, info->count);
1368             info->count = 0;
1369         }
1370         if ( info->count ) {
1371             restore_flags(flags);
1372             MOD_DEC_USE_COUNT;
1373             return;
1374         }
1375         info->flags |= ASYNC_CLOSING;
1376         restore_flags(flags);   // add by Victor Yu. 09-26-2002
1377         /*
1378          * Save the termios structure, since this port may have
1379          * separate termios for callout and dialin.
1380          */
1381         if ( info->flags & ASYNC_NORMAL_ACTIVE )
1382             info->normal_termios = *tty->termios;
1383         /*
1384          * Now we wait for the transmit buffer to clear; and we notify
1385          * the line discipline to only process XON/XOFF characters.
1386          */
1387         tty->closing = 1;
1388         if ( info->closing_wait != ASYNC_CLOSING_WAIT_NONE ) {
1389             tty_wait_until_sent(tty, info->closing_wait);
1390         }
1391         /*
1392          * At this point we stop accepting input.  To do this, we
1393          * disable the receive line status interrupts, and tell the
1394          * interrupt driver to stop checking the data ready bit in the
1395          * line status register.
1396          */
1397         info->IER &= ~UART_IER_RLSI;
1398         if ( info->IsMoxaMustChipFlag )
1399                 info->IER &= ~MOXA_MUST_RECV_ISR;
1400 /* by William
1401         info->read_status_mask &= ~UART_LSR_DR;
1403         if ( info->flags & ASYNC_INITIALIZED ) {
1404             outb(info->IER, info->base + UART_IER);
1405             /*
1406              * Before we drop DTR, make sure the UART transmitter
1407              * has completely drained; this is especially
1408              * important if there is a transmit FIFO!
1409              */
1410             timeout = jiffies + HZ;
1411             while ( !(inb(info->base + UART_LSR) & UART_LSR_TEMT) ) {
1412                 current->state = TASK_INTERRUPTIBLE;
1413                 schedule_timeout(5);
1414                 if ( time_after(jiffies, timeout) )
1415                     break;
1416             }
1417         }
1418         mxser_shutdown(info);
1420         // following add by Victor Yu. 09-23-2002
1421         /*
1422         if ( info->IsMoxaMustChipFlag )
1423                 SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base);
1424         */
1425         // above add by Victor Yu. 09-23-2002
1427         if ( tty->driver->flush_buffer )
1428             tty->driver->flush_buffer(tty);
1429         if ( tty->ldisc.flush_buffer )
1430             tty->ldisc.flush_buffer(tty);
1431         tty->closing = 0;
1432         info->event = 0;
1433         info->tty = 0;
1434         if ( info->blocked_open ) {
1435             if ( info->close_delay ) {
1436                 current->state = TASK_INTERRUPTIBLE;
1437                 schedule_timeout(info->close_delay);
1438             }
1439             wake_up_interruptible(&info->open_wait);
1440         }
1442 #if 0
1443         info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
1444                          ASYNC_CLOSING);
1445 #else
1446         info->flags &= ~(ASYNC_NORMAL_ACTIVE |
1447                          ASYNC_CLOSING);
1448 #endif
1449         wake_up_interruptible(&info->close_wait);
1450 //      restore_flags(flags);   // mask by Vicror Yu. 09-26-2002
1452         MOD_DEC_USE_COUNT;
1455 static int mxser_write(struct tty_struct * tty, int from_user,
1456                        const unsigned char * buf, int count)
1458         int             c, total = 0;
1459         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1460         unsigned long   flags;
1462         if ( !tty || !info->xmit_buf || !mxvar_tmp_buf )
1463             return(0);
1465 #if 0   // mask by Victor Yu. 10-13-2004
1466         if ( from_user )
1467             down(&mxvar_tmp_buf_sem);
1468 #endif
1469         save_flags(flags);
1470         cli();
1471         while ( 1 ) {
1472 //          cli();
1473             c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1474                                SERIAL_XMIT_SIZE - info->xmit_head));
1475             if ( c <= 0 )
1476                 break;
1478             if ( from_user ) {
1479                 /*
1480                 copy_from_user(mxvar_tmp_buf, buf, c);
1481                 c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1482                                SERIAL_XMIT_SIZE - info->xmit_head));
1483                 memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
1484                 */
1485                 copy_from_user(info->xmit_buf+info->xmit_head, buf, c);
1486             } else
1487                 memcpy(info->xmit_buf + info->xmit_head, buf, c);
1488             info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
1489             info->xmit_cnt += c;
1490 //          restore_flags(flags);
1491             buf += c;
1492             count -= c;
1493             total += c;
1494         }
1495 #if 0   // mask by Victor Yu. 10-13-2004
1496         if ( from_user )
1497             up(&mxvar_tmp_buf_sem);
1498 #endif
1499         if ( info->xmit_cnt && !tty->stopped && 
1500                      !(info->IER & UART_IER_THRI) ) {
1501                 if (!tty->hw_stopped||(info->type == PORT_16550A)) {
1502                     info->IER |= UART_IER_THRI;
1503                     outb(info->IER, info->base + UART_IER);
1504                 }
1505         }
1506         restore_flags(flags);
1507         return(total);
1510 static void mxser_put_char(struct tty_struct * tty, unsigned char ch)
1512         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1513         unsigned long   flags;
1515         if ( !tty || !info->xmit_buf )
1516             return;
1518         save_flags(flags);
1519         cli();
1520         if ( info->xmit_cnt >= SERIAL_XMIT_SIZE - 1 ) {
1521             restore_flags(flags);
1522             return;
1523         }
1525         info->xmit_buf[info->xmit_head++] = ch;
1526         info->xmit_head &= SERIAL_XMIT_SIZE - 1;
1527         info->xmit_cnt++;
1528         if ( !tty->stopped && !(info->IER & UART_IER_THRI) ) {
1529                 if (!tty->hw_stopped||(info->type == PORT_16550A)) {
1530                         info->IER |= UART_IER_THRI;
1531                         outb(info->IER, info->base + UART_IER);
1532                 }
1533         }
1534         restore_flags(flags);
1537 static void mxser_flush_chars(struct tty_struct * tty)
1539         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1540         unsigned long   flags;
1542         if ( info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf || 
1543              (tty->hw_stopped && info->type!=PORT_16550A))
1544             return;
1546         save_flags(flags);
1547         cli();
1548         info->IER |= UART_IER_THRI;
1549         outb(info->IER, info->base + UART_IER);
1550         restore_flags(flags);
1553 static int mxser_write_room(struct tty_struct * tty)
1555         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1556         int     ret;
1558         ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
1559         if ( ret < 0 )
1560             ret = 0;
1561         return(ret);
1564 static int mxser_chars_in_buffer(struct tty_struct * tty)
1566         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1568         return(info->xmit_cnt);
1571 static void mxser_flush_buffer(struct tty_struct * tty)
1573         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1574         unsigned long flags;
1576         save_flags(flags);
1577         cli();
1578         info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1579         restore_flags(flags);
1580         wake_up_interruptible(&tty->write_wait);
1581         if ( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1582              tty->ldisc.write_wakeup )
1583             (tty->ldisc.write_wakeup)(tty);
1586 static int mxser_ioctl(struct tty_struct * tty, struct file * file,
1587                        unsigned int cmd, unsigned long arg)
1589         int             error;
1590         unsigned long   flags;
1591         struct mxser_struct *   info = (struct mxser_struct *)tty->driver_data;
1592         int                     retval;
1593         struct async_icount     cprev, cnow;        /* kernel counter temps */
1594         struct serial_icounter_struct *p_cuser;     /* user space */
1595         unsigned long           templ;
1596         if ( PORTNO(tty) == MXSER_PORTS )
1597             return(mxser_ioctl_special(cmd, arg));
1598         
1599         // following add by Victor Yu. 01-05-2004
1600         if ( cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE ) {
1601                 int             opmode, p;
1602                 int             shiftbit;
1603                 unsigned int    val;
1605                 p = info->port % 4;
1606                 if ( cmd == MOXA_SET_OP_MODE ) {
1607                         error = verify_area(VERIFY_READ, (void *)arg, sizeof(int));
1608                         if ( error )
1609                                 return(error);
1610                         get_from_user(opmode,(int *)arg);
1611                         if ( opmode != RS232_MODE && opmode != RS485_2WIRE_MODE && opmode != RS422_MODE && opmode != RS485_4WIRE_MODE )
1612                                 return -EFAULT;
1613 #if 0
1614                         shiftbit = (p+2) * 2;
1615 #else
1616                         shiftbit = p * 2;
1617 #endif
1618                         val = inl(info->opmode_ioaddr);
1619                         val &= (~(3 << shiftbit));
1620                         val |= (opmode << shiftbit);
1621                         outl(val, info->opmode_ioaddr);
1622                 } else {
1623                         error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1624                         if ( error )
1625                                 return(error);
1626 #if 0
1627                         shiftbit = (p+2) * 2;
1628 #else
1629                         shiftbit = p * 2;
1630 #endif
1631                         opmode = inl(info->opmode_ioaddr) >> shiftbit;
1632                         opmode &= OP_MODE_MASK;
1633                         copy_to_user((int*)arg, &opmode, sizeof(int));
1634                 }
1635                 return 0;
1636         }
1637         // above add by Victor Yu. 01-05-2004
1639 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
1640         if ( cmd == MOXA_SET_SPECIAL_BAUD_RATE || cmd == MOXA_GET_SPECIAL_BAUD_RATE ) {
1641                 int     speed, i;
1642                 if ( cmd == MOXA_SET_SPECIAL_BAUD_RATE ) {
1643                         error = verify_area(VERIFY_READ, (void *)arg, sizeof(int));
1644                         if ( error )
1645                                 return(error);
1646                         get_from_user(speed,(int *)arg);
1647                         if ( speed <= 0 || speed > info->MaxCanSetBaudRate )
1648                                 return -EFAULT;
1649                         if ( !info->tty || !info->tty->termios || !info->base )
1650                                 return 0;
1651                         info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX);
1652                         for ( i=0; i<BAUD_TABLE_NO && speed != mxvar_baud_table[i]; i++ );
1653                         if ( i == BAUD_TABLE_NO ) {
1654                                 info->tty->termios->c_cflag |= B4000000;
1655                         } else {
1656                                 switch ( mxvar_baud_table[i] ) {
1657                                 case 921600 : info->tty->termios->c_cflag |= B921600; break;
1658                                 case 460800 : info->tty->termios->c_cflag |= B460800; break;
1659                                 case 230400 : info->tty->termios->c_cflag |= B230400; break;
1660                                 case 115200 : info->tty->termios->c_cflag |= B115200; break;
1661                                 case 57600 : info->tty->termios->c_cflag |= B57600; break;
1662                                 case 38400 : info->tty->termios->c_cflag |= B38400; break;
1663                                 case 19200 : info->tty->termios->c_cflag |= B19200; break;
1664                                 case 9600 : info->tty->termios->c_cflag |= B9600; break;
1665                                 case 4800 : info->tty->termios->c_cflag |= B4800; break;
1666                                 case 2400 : info->tty->termios->c_cflag |= B2400; break;
1667                                 case 1800 : info->tty->termios->c_cflag |= B1800; break;
1668                                 case 1200 : info->tty->termios->c_cflag |= B1200; break;
1669                                 case 600 : info->tty->termios->c_cflag |= B600; break;
1670                                 case 300 : info->tty->termios->c_cflag |= B300; break;
1671                                 case 200 : info->tty->termios->c_cflag |= B200; break;
1672                                 case 150 : info->tty->termios->c_cflag |= B150; break;
1673                                 case 134 : info->tty->termios->c_cflag |= B134; break;
1674                                 case 110 : info->tty->termios->c_cflag |= B110; break;
1675                                 case 75 : info->tty->termios->c_cflag |= B75; break;
1676                                 case 50 : info->tty->termios->c_cflag |= B50; break;
1677                                 }
1678                         }
1679                         info->speed = speed;
1680                         mxser_change_speed(info, 0);
1681                 } else {
1682                         error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1683                         if ( error )
1684                                 return(error);
1685                         copy_to_user((int*)arg, &info->speed, sizeof(int));
1686                 }
1687                 return 0;
1688         }
1689 #endif
1691         if ( (cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) &&
1692              (cmd != TIOCGICOUNT) ) {
1693             if ( tty->flags & (1 << TTY_IO_ERROR) )
1694                 return(-EIO);
1695         }
1696         switch ( cmd ) {
1697 #if 1   // add by Victor Yu. 12-28-2004
1698         case TIOCSBRK : // start to send break
1699             retval = tty_check_change(tty);
1700             if ( retval )
1701                 return(retval);
1702             tty_wait_until_sent(tty, 0);
1703             save_flags(flags);
1704             cli();
1705             outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
1706             restore_flags(flags);
1707             return 0;
1708         case TIOCCBRK : // stop to send break
1709             save_flags(flags);
1710             cli();
1711             outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
1712             restore_flags(flags);
1713             return 0;
1714 #endif
1715         case TCSBRK:    /* SVID version: non-zero arg --> no break */
1716             retval = tty_check_change(tty);
1717             if ( retval )
1718                 return(retval);
1719             tty_wait_until_sent(tty, 0);
1720             if ( !arg )
1721                 mxser_send_break(info, HZ/4);           /* 1/4 second */
1722             return(0);
1723         case TCSBRKP:   /* support for POSIX tcsendbreak() */
1724             retval = tty_check_change(tty);
1725             if ( retval )
1726                 return(retval);
1727             tty_wait_until_sent(tty, 0);
1728             mxser_send_break(info, arg ? arg*(HZ/10) : HZ/4);
1729             return(0);
1730         case TIOCGSOFTCAR:
1731             error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));
1732             if ( error )
1733                 return(error);
1734             put_to_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
1735             return 0;
1736         case TIOCSSOFTCAR:
1737             error = verify_area(VERIFY_READ, (void *)arg, sizeof(long));
1738             if ( error )
1739                 return(error);
1740             get_from_user(templ,(unsigned long *)arg);
1741             arg = templ;
1742             tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
1743                                     (arg ? CLOCAL : 0));
1744             return(0);
1745         case TIOCMGET:
1746             error = verify_area(VERIFY_WRITE, (void *)arg,
1747                                 sizeof(unsigned int));
1748             if ( error )
1749                 return(error);
1750             return(mxser_get_modem_info(info, (unsigned int *)arg));
1751         case TIOCMBIS:
1752         case TIOCMBIC:
1753         case TIOCMSET:
1754             return(mxser_set_modem_info(info, cmd, (unsigned int *)arg));
1755         case TIOCGSERIAL:
1756             error = verify_area(VERIFY_WRITE, (void *)arg,
1757                                 sizeof(struct serial_struct));
1758             if ( error )
1759                 return(error);
1760             return(mxser_get_serial_info(info, (struct serial_struct *)arg));
1761         case TIOCSSERIAL:
1762             error = verify_area(VERIFY_READ, (void *)arg,
1763                                 sizeof(struct serial_struct));
1764             if ( error )
1765                 return(error);
1766             return(mxser_set_serial_info(info, (struct serial_struct *)arg));
1767         case TIOCSERGETLSR: /* Get line status register */
1768             error = verify_area(VERIFY_WRITE, (void *)arg,
1769                                 sizeof(unsigned int));
1770             if ( error )
1771                 return(error);
1772             else
1773                 return(mxser_get_lsr_info(info, (unsigned int *)arg));
1774         /*
1775          * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
1776          * - mask passed in arg for lines of interest
1777          *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
1778          * Caller should use TIOCGICOUNT to see which one it was
1779          */
1780         case TIOCMIWAIT:
1781             save_flags(flags);
1782             cli();
1783             cprev = info->icount;   /* note the counters on entry */
1784             restore_flags(flags);
1785             while ( 1 ) {
1786                 interruptible_sleep_on(&info->delta_msr_wait);
1787                 /* see if a signal did it */
1788                 if ( signal_pending(current) ) {
1789                     return(-ERESTARTSYS);
1790                 }
1791                 save_flags(flags);
1792                 cli();
1793                 cnow = info->icount;    /* atomic copy */
1794                 restore_flags(flags);
1795 #if 0   // mask by Victor Yu. 12-31-2004
1796                 if ( cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
1797                      cnow.dcd == cprev.dcd && cnow.cts == cprev.cts )
1798                     return(-EIO);       /* no change => error */
1799                 if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
1800                      ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
1801                      ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
1802                      ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
1803                     return(0);
1804                 }
1805 #else   // add by Victor Yu. 12-31-2004
1806 #define TIOCM_BRK       0x10000
1807 #define TIOCM_PARITY    0x20000
1808 #define TIOCM_FRAME     0x40000
1809 #define TIOCM_XOFFHOLD  0x80000
1810                 if ( cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
1811                      cnow.dcd == cprev.dcd && cnow.cts == cprev.cts &&
1812                      cnow.brk == cprev.brk && cnow.parity == cprev.parity &&
1813                      cnow.frame == cprev.frame && cnow.buf_overrun == cprev.buf_overrun )
1814                     return(-EIO);       /* no change => error */
1815                 if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
1816                      ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
1817                      ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
1818                      ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ||
1819                      ((arg & TIOCM_BRK) && (cnow.brk != cprev.brk)) ||
1820                      ((arg & TIOCM_PARITY) && (cnow.parity != cprev.parity)) ||
1821                      ((arg & TIOCM_FRAME) && (cnow.frame != cprev.frame)) ||
1822                      ((arg & TIOCM_XOFFHOLD) && (cnow.buf_overrun != cprev.buf_overrun)) ) {
1823                     return(0);
1824                 }
1825 #endif
1826                 cprev = cnow;
1827             }
1828             /* NOTREACHED */
1829         /*
1830          * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1831          * Return: write counters to the user passed counter struct
1832          * NB: both 1->0 and 0->1 transitions are counted except for
1833          *     RI where only 0->1 is counted.
1834          */
1836 #if 1   // add by Victor Yu. 01-26-2005
1837         case MOXA_UNWAIT :
1838             wake_up_interruptible(&info->delta_msr_wait);
1839             break;
1840 #endif
1842         case TIOCGICOUNT:
1843             error = verify_area(VERIFY_WRITE, (void *)arg,
1844                                 sizeof(struct serial_icounter_struct));
1845             if ( error )
1846                 return(error);
1847             save_flags(flags);
1848             cli();
1849             cnow = info->icount;
1850             restore_flags(flags);
1851             p_cuser = (struct serial_icounter_struct *)arg;
1852 /* modified by casper 1/11/2000 */ 
1853 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
1854                 if (put_user(cnow.frame, &p_cuser->frame))
1855                         return -EFAULT;
1856                 if (put_user(cnow.brk, &p_cuser->brk))
1857                         return -EFAULT;
1858                 if (put_user(cnow.overrun, &p_cuser->overrun))
1859                         return -EFAULT;
1860                 if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
1861                         return -EFAULT;
1862                 if (put_user(cnow.parity, &p_cuser->parity))
1863                         return -EFAULT;
1864                 if (put_user(cnow.rx, &p_cuser->rx))
1865                         return -EFAULT;
1866                 if (put_user(cnow.tx, &p_cuser->tx))
1867                         return -EFAULT;
1868 #endif
1870             put_to_user(cnow.cts, &p_cuser->cts);
1871             put_to_user(cnow.dsr, &p_cuser->dsr);
1872             put_to_user(cnow.rng, &p_cuser->rng);
1873             put_to_user(cnow.dcd, &p_cuser->dcd);
1875 /* */
1876             return(0);
1877         case MOXA_HighSpeedOn:
1878             error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1879             if ( error )
1880                 return(error);
1881             put_to_user(info->baud_base != 115200 ? 1 : 0, (int *)arg);
1882             return(0);
1883         default:
1884             return(-ENOIOCTLCMD);
1885         }
1886         return(0);
1889 static int mxser_ioctl_special(unsigned int cmd, unsigned long arg)
1891         int             error, i, result, status;
1893         switch ( cmd ) {
1894         case MOXA_GET_CONF:
1895             error = verify_area(VERIFY_WRITE, (void *)arg, 
1896                             sizeof(struct mxser_hwconf)*4);
1897             if ( error )
1898                 return(error);
1899             copy_to_user((struct mxser_hwconf *)arg, mxsercfg, 
1900                             sizeof(struct mxser_hwconf)*4);
1901             return 0;
1902         case MOXA_GET_MAJOR:
1903             error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1904             if ( error )
1905                 return(error);
1906             copy_to_user((int*)arg, &ttymajor, sizeof(int));
1907             return 0;
1909         case MOXA_GET_CUMAJOR:
1910             error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1911             if ( error )
1912                 return(error);
1913             copy_to_user((int*)arg, &calloutmajor, sizeof(int));
1914             return 0;
1916         case MOXA_CHKPORTENABLE:
1917             error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));
1918             if ( error )
1919                 return(error);
1920             result = 0;
1921             for ( i=0; i<MXSER_PORTS; i++ ) {
1922                 if ( mxvar_table[i].base )
1923                     result |= (1 << i);
1924             }
1925             put_to_user(result, (unsigned long *)arg);
1926             return(0);
1927         case MOXA_GETDATACOUNT:
1928             error = verify_area(VERIFY_WRITE, (void *)arg,
1929                                 sizeof(struct mxser_log));
1930             if ( error )
1931                 return(error);
1932             copy_to_user((struct mxser_log *)arg, &mxvar_log, sizeof(mxvar_log));
1933             return(0);
1934         case MOXA_GETMSTATUS:
1935             error = verify_area(VERIFY_WRITE, (void *)arg,
1936                                 sizeof(struct mxser_mstatus) * MXSER_PORTS);
1937             if ( error )
1938                 return(error);
1940             for(i=0; i<MXSER_PORTS; i++){
1941                 GMStatus[i].ri = 0;
1942                 if ( !mxvar_table[i].base ){
1943                     GMStatus[i].dcd = 0;
1944                     GMStatus[i].dsr = 0;
1945                     GMStatus[i].cts = 0;
1946                     continue;
1947                 }
1949                 if ( !mxvar_table[i].tty || !mxvar_table[i].tty->termios )
1950                     GMStatus[i].cflag=mxvar_table[i].normal_termios.c_cflag;
1951                 else
1952                     GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag;
1953                 
1954                 status = inb(mxvar_table[i].base + UART_MSR);
1955                 if(status  & 0x80/*UART_MSR_DCD*/)
1956                     GMStatus[i].dcd = 1;
1957                 else
1958                     GMStatus[i].dcd = 0;
1960                 if(status  & 0x20/*UART_MSR_DSR*/)
1961                     GMStatus[i].dsr = 1;
1962                 else
1963                     GMStatus[i].dsr = 0;
1964                 
1966                 if(status  & 0x10/*UART_MSR_CTS*/)
1967                     GMStatus[i].cts = 1;
1968                 else
1969                     GMStatus[i].cts = 0;
1970             }
1971             copy_to_user((struct mxser_mstatus *)arg, GMStatus,
1972                                     sizeof(struct mxser_mstatus) * MXSER_PORTS);
1973             return 0;
1974         default:
1975             return(-ENOIOCTLCMD);
1976         }
1977         return(0);
1981  * This routine is called by the upper-layer tty layer to signal that
1982  * incoming characters should be throttled.
1983  */
1984 static void mxser_throttle(struct tty_struct * tty)
1986         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1987         unsigned long   flags;
1989         if ( I_IXOFF(tty) ) {
1990             save_flags(flags);
1991             cli();
1992             
1993             // following add by Victor Yu. 09-02-2002
1994             if ( info->IsMoxaMustChipFlag ) {
1995                 info->IER &= ~MOXA_MUST_RECV_ISR;
1996                 outb(info->IER, info->base+UART_IER);
1997             } else {
1998             // above add by Victor Yu. 09-02-2002
2000                 info->x_char = STOP_CHAR(tty);
2001                 // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002
2002                 outb(0, info->base+UART_IER);
2003                 info->IER |= UART_IER_THRI;
2004                 outb(info->IER, info->base + UART_IER); /* force Tx interrupt */
2005             }   // add by Victor Yu. 09-02-2002
2006             restore_flags(flags);
2007         }
2009         if ( info->tty->termios->c_cflag & CRTSCTS ) {
2010             save_flags(flags);
2011             cli();
2012 #if 1   // add by Victor Yu. 09-17-2004
2013             if ( info->IsMoxaMustChipFlag ) {
2014                 info->IER &= ~MOXA_MUST_RECV_ISR;
2015                 outb(info->IER, info->base+UART_IER);
2016             } else {
2017                 info->MCR &= ~UART_MCR_RTS;
2018                 outb(info->MCR, info->base + UART_MCR);
2019             }
2020 #else
2021             info->MCR &= ~UART_MCR_RTS;
2022             outb(info->MCR, info->base + UART_MCR);
2023 #endif
2024             restore_flags(flags);
2025         }
2028 static void mxser_unthrottle(struct tty_struct * tty)
2030         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2031         unsigned long   flags;
2033         if ( I_IXOFF(tty) ) {
2034             if ( info->x_char )
2035                 info->x_char = 0;
2036             else {
2037                 save_flags(flags);
2038                 cli();
2039                 
2040                 // following add by Victor Yu. 09-02-2002
2041                 if ( info->IsMoxaMustChipFlag ) {
2042                         info->IER |= MOXA_MUST_RECV_ISR;
2043                         outb(info->IER, info->base+UART_IER);
2044                 } else {
2045                 // above add by Victor Yu. 09-02-2002
2047                         info->x_char = START_CHAR(tty);
2048                         // outb(info->IER, 0);  // mask by Victor Yu. 09-02-2002
2049                         outb(0, info->base+UART_IER);   // add by Victor Yu. 09-02-2002
2050                         info->IER |= UART_IER_THRI;             /* force Tx interrupt */
2051                         outb(info->IER, info->base + UART_IER);
2052                 }       // add by Victor Yu. 09-02-2002
2053                 restore_flags(flags);
2054             }
2055         }
2057         if ( info->tty->termios->c_cflag & CRTSCTS ) {
2058             save_flags(flags);
2059             cli();
2060 #if 1   // add by Victor Yu. 09-17-2004
2061             if ( info->IsMoxaMustChipFlag ) {
2062                 info->IER |= MOXA_MUST_RECV_ISR;
2063                 outb(info->IER, info->base+UART_IER);
2064             } else {
2065                 info->MCR |= UART_MCR_RTS;
2066                 outb(info->MCR, info->base + UART_MCR);
2067             }
2068 #else
2069             info->MCR |= UART_MCR_RTS;
2070             outb(info->MCR, info->base + UART_MCR);
2071 #endif
2072             restore_flags(flags);
2073         }
2076 static void mxser_set_termios(struct tty_struct * tty,
2077                               struct termios * old_termios)
2079         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2081 #if 0   // mask by Victor Yu. 01-04-2005
2082         if ( (tty->termios->c_cflag != old_termios->c_cflag) ||
2083              (RELEVANT_IFLAG(tty->termios->c_iflag) !=
2084               RELEVANT_IFLAG(old_termios->c_iflag)) ) {
2085 #else   // add by Victor Yu. 01-04-2005
2086         if ( (tty->termios->c_cflag != old_termios->c_cflag) ||
2087              (tty->termios->c_iflag != old_termios->c_iflag) ) {
2088 #endif
2090                 mxser_change_speed(info, old_termios);
2092                 if ( (old_termios->c_cflag & CRTSCTS) &&
2093                      !(tty->termios->c_cflag & CRTSCTS) ) {
2094                         tty->hw_stopped = 0;
2095                         mxser_start(tty);
2096                 }
2097         }
2098         
2099 /* Handle sw stopped */
2100         if ( (old_termios->c_iflag & IXON) &&
2101              !(tty->termios->c_iflag & IXON) ) {
2102                 tty->stopped = 0;
2103                 
2104 #if 0   // mask by Victor Yu. 01-04-2005
2105                 // following add by Victor Yu. 09-02-2002
2106                 if ( info->IsMoxaMustChipFlag ) {
2107                         unsigned long   flags;
2108                         save_flags(flags);
2109                         cli();
2110                         info->IER &= ~MOXA_MUST_IER_XINT;
2111                         DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
2112                         outb(info->IER, info->base+UART_IER);
2113                         restore_flags(flags);
2114                 }
2115                 // above add by Victor Yu. 09-02-2002
2116 #endif
2118                 mxser_start(tty);
2119         }
2123  * mxser_stop() and mxser_start()
2125  * This routines are called before setting or resetting tty->stopped.
2126  * They enable or disable transmitter interrupts, as necessary.
2127  */
2128 static void mxser_stop(struct tty_struct * tty)
2130         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2131         unsigned long   flags;
2133         save_flags(flags);
2134         cli();
2135         if ( info->IER & UART_IER_THRI ) {
2136             info->IER &= ~UART_IER_THRI;
2137             outb(info->IER, info->base + UART_IER);
2138         }
2139         restore_flags(flags);
2142 static void mxser_start(struct tty_struct * tty)
2144         struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2145         unsigned long   flags;
2147         save_flags(flags);
2148         cli();
2149         if ( info->xmit_cnt && info->xmit_buf &&
2150              !(info->IER & UART_IER_THRI) ) {
2151             info->IER |= UART_IER_THRI;
2152             outb(info->IER, info->base + UART_IER);
2153         }
2154         restore_flags(flags);
2157 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2159  * mxser_wait_until_sent() --- wait until the transmitter is empty
2160  */
2161 static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
2163         struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
2164         unsigned long orig_jiffies, char_time;
2165         int lsr;
2166         
2167         if (info->type == PORT_UNKNOWN)
2168                 return;
2170         if (info->xmit_fifo_size == 0)
2171                 return; /* Just in case.... */
2173         /*
2174          * Set the check interval to be 1/5 of the estimated time to
2175          * send a single character, and make it at least 1.  The check
2176          * interval should also be less than the timeout.
2177          * 
2178          * Note: we have to use pretty tight timings here to satisfy
2179          * the NIST-PCTS.
2180          */
2181         char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
2182         char_time = char_time / 5;
2183         if (char_time == 0)
2184                 char_time = 1;
2185         if (timeout && timeout < char_time)
2186                 char_time = timeout;
2187         /*
2188          * If the transmitter hasn't cleared in twice the approximate
2189          * amount of time to send the entire FIFO, it probably won't
2190          * ever clear.  This assumes the UART isn't doing flow
2191          * control, which is currently the case.  Hence, if it ever
2192          * takes longer than info->timeout, this is probably due to a
2193          * UART bug of some kind.  So, we clamp the timeout parameter at
2194          * 2*info->timeout.
2195          */
2196         if (!timeout || timeout > 2*info->timeout)
2197                 timeout = 2*info->timeout;
2198 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2199         printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
2200         printk("jiff=%lu...", jiffies);
2201 #endif
2202         orig_jiffies = jiffies + timeout;
2203         while (!((lsr = inb(info->base+ UART_LSR)) & UART_LSR_TEMT)) {
2204 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2205                 printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
2206 #endif
2207 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))
2208                 set_current_state(TASK_INTERRUPTIBLE);
2209 #else
2210                 current->state = TASK_INTERRUPTIBLE;
2211 #endif
2212                 schedule_timeout(char_time);
2213                 if (signal_pending(current))
2214                         break;
2215                 if (timeout && time_after(jiffies, orig_jiffies))
2216                         break;
2217         }
2218 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))
2219                 set_current_state(TASK_RUNNING);
2220 #else
2221                 current->state = TASK_RUNNING;
2222 #endif
2224 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2225         printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
2226 #endif
2228 #endif
2232  * This routine is called by tty_hangup() when a hangup is signaled.
2233  */
2234 void mxser_hangup(struct tty_struct * tty)
2236         struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
2237 #if 1   // add by Victor Yu. 12-28-2004
2238         unsigned long   flags;
2239 #endif
2241         mxser_flush_buffer(tty);
2242         mxser_shutdown(info);
2243 #if 0   // mask by Victor Yu. 12-28-2004
2244         info->event = 0;
2245         info->count = 0;
2246         info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2247         info->tty = 0;
2248 #else
2249         save_flags(flags);
2250         cli();
2251         info->event = 0;
2252         info->count = 0;
2253 #if 0
2254         info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2255 #else
2256         info->flags &= ~(ASYNC_NORMAL_ACTIVE);
2257 #endif
2258         info->tty = 0;
2259         restore_flags(flags);
2260 #endif
2261         wake_up_interruptible(&info->open_wait);
2265  * This is the serial driver's generic interrupt routine
2266  */
2267 //#define USE_INT_POLL
2268 #ifdef USE_INT_POLL
2269 static int      poll_int_port=0;
2270 #endif
2271 static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs * regs)
2273         int                     status, iir, i;
2274         struct mxser_struct *   info;
2275         struct mxser_struct *   port;
2276         int                     max, irqbits, msr;
2277 #ifndef USE_INT_POLL
2278         int                     pass_counter=0, bits;
2279 #endif
2281         port = 0;
2282         for(i=0; i<MXSER_BOARDS; i++){
2283             if(dev_id == &(mxvar_table[i*MXSER_PORTS_PER_BOARD])){
2284                 port = dev_id;
2285                 break;
2286             }
2287         }
2289         if(i==MXSER_BOARDS || port==0)
2290             return IRQ_NONE;
2291         max = mxser_numports[mxsercfg[i].board_type-1];
2292         
2293         while ( 1 ) {
2294             irqbits = inb(port->vector) & port->vectormask;
2295 #ifdef USE_INT_POLL
2296             if ( irqbits & (1<<poll_int_port) )
2297                     break;
2298             info = port + poll_int_port;
2299 #else
2300             if ( irqbits == port->vectormask )
2301                 break;
2302 #if 1
2303             for ( i=0, bits=1; i<max; i++, irqbits |= bits, bits <<= 1 ) {
2304 #else
2305             for ( i=0, bits=4; i<max; i++, irqbits |= bits, bits <<= 1 ) {
2306 #endif
2307                 if ( irqbits == port->vectormask )
2308                     break;
2309                 if ( bits & irqbits )
2310                     continue;
2311                 info = port + i;
2312 #endif
2314                 // following add by Victor Yu. 09-13-2002
2315                 iir = inb(info->base+UART_IIR);
2316                 if ( iir & UART_IIR_NO_INT )
2317                         continue;
2318                 iir &= MOXA_MUST_IIR_MASK;
2319                 if ( !info->tty ) {
2320                         status = inb(info->base+UART_LSR);
2321                         outb(0x27, info->base+UART_FCR);
2322                         inb(info->base+UART_MSR);
2323                         continue;
2324                 }
2325                 // above add by Victor Yu. 09-13-2002
2327 #if 1   // add by Victor Yu. 01-04-2005
2328                 if ( iir == MOXA_MUST_IIR_XSC ) {
2329                         if ( !(inb(info->base+UART_MCR) & MOXA_MUST_MCR_XON_FLAG) ) {
2330                                 info->icount.buf_overrun++;
2331                                 wake_up_interruptible(&info->delta_msr_wait);
2332                         }
2333                         continue;
2334                 }
2335 #endif
2337                 /* mask by Victor Yu. 09-13-2002
2338                 if ( !info->tty ||
2339                      (inb(info->base + UART_IIR) & UART_IIR_NO_INT) )
2340                     continue;
2341                 */
2342                 /* mask by Victor Yu. 09-02-2002
2343                 status = inb(info->base + UART_LSR) & info->read_status_mask;
2344                 */
2346 #if 0   // mask by Victor Yu. 01-04-2005, I do just for UC7400 series
2347                 // following add by Victor Yu. 09-02-2002
2348                 status = inb(info->base+UART_LSR);
2349                 if ( info->IsMoxaMustChipFlag ) {
2350                         /*
2351                         if ( (status & 0x02) && !(status & 0x01) ) {
2352                                 outb(info->base+UART_FCR,  0x23);
2353                                 continue;
2354                         }
2355                         */
2356                         if ( iir == MOXA_MUST_IIR_GDA ||
2357                              iir == MOXA_MUST_IIR_RDA ||
2358                              iir == MOXA_MUST_IIR_RTO ||
2359                              iir == MOXA_MUST_IIR_LSR )
2360                                 mxser_receive_chars(info, &status);
2361                 } else {
2362                 // above add by Victor Yu. 09-02-2002
2364                         status &= info->read_status_mask;
2365                         if ( status & UART_LSR_DR )
2366                             mxser_receive_chars(info, &status);
2367                 }
2368 #else   // add by Victor Yu. 01-04-2005
2369                 if ( iir == MOXA_MUST_IIR_GDA ||
2370                      iir == MOXA_MUST_IIR_RDA ||
2371                      iir == MOXA_MUST_IIR_RTO ||
2372                      iir == MOXA_MUST_IIR_LSR ) {
2373                         status = inb(info->base+UART_LSR);
2374                         mxser_receive_chars(info, &status);
2375                 }
2376 #endif
2377 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2378                 if ( iir == UART_IIR_MSI ) {
2379                         msr = inb(info->base + UART_MSR);
2380                         if ( msr & UART_MSR_ANY_DELTA ) {
2381                                 mxser_check_modem_status(info, msr);
2382                         }
2383                 }
2384 #else
2385                 msr = inb(info->base + UART_MSR);
2386                 if ( msr & UART_MSR_ANY_DELTA ) {
2387                     mxser_check_modem_status(info, msr);
2388                 }
2389 #endif
2391 #if 0   // mask by Victor Yu. I do just for UC7400 series
2392                 // following add by Victor Yu. 09-13-2002
2393                 if ( info->IsMoxaMustChipFlag ) {
2394                         if ( iir == 0x02 )
2395                                 mxser_transmit_chars(info);
2396                 } else {
2397                 // above add by Victor Yu. 09-13-2002
2399                         if ( status & UART_LSR_THRE ) {
2400 /* 8-2-99 by William
2401                             if ( info->x_char || (info->xmit_cnt > 0) )
2403                                 mxser_transmit_chars(info);
2404                         }
2405                 }
2406 #else   // add by Victor Yu. 01-04-2005
2407                 if ( iir == 0x02 )
2408                         mxser_transmit_chars(info);
2409 #endif
2410 #ifndef USE_INT_POLL
2411             }
2412             if ( pass_counter++ > MXSER_ISR_PASS_LIMIT ) {
2413 #if 0
2414                 printk("MOXA Smartio/Industio family driver interrupt loop break\n");
2415 #endif
2416                 break;  /* Prevent infinite loops */
2417             }
2418 #endif
2419         }
2420 #ifdef USE_INT_POLL
2421         if ( ++poll_int_port >= max )
2422                 poll_int_port = 0;
2423 #endif
2424         return IRQ_HANDLED;
2427 #define BYPASS_FLIP     // add by Victor Yu. 09-17-2004
2428 #define N_TTY_BUF_SIZE_MASK     (N_TTY_BUF_SIZE-1)      // add by Victor Yu. 02-04-2005
2429 static inline void mxser_receive_chars(struct mxser_struct *info,
2430                                          int *status)
2432         struct tty_struct *     tty = info->tty;
2433         unsigned char           ch, gdl;
2434         int                     ignored = 0;
2435         int                     cnt = 0;
2436 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2437         unsigned char           *cp=tty->read_buf;
2438         int                     wptr=tty->read_head;
2439 #else
2440 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2441         unsigned char           *cp=tty->flip.char_buf;
2442         char                    *fp=tty->flip.flag_buf;
2443 #endif  // BYPASS_FLIP
2444 #endif  // CONFIG_MOXA_SUPPORT_SKIP_LD
2446         // following add by Victor Yu. 09-02-2002
2447         if ( info->IsMoxaMustChipFlag ) {
2448                 if ( *status & UART_LSR_SPECIAL ) {
2449                         goto intr_old;
2450                 }
2452                 // following add by Victor Yu. 02-11-2004
2453                 if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID1 &&
2454                      (*status & MOXA_MUST_LSR_RERR) )
2455                         goto intr_old;
2456                 // above add by Victor Yu. 02-14-2004
2457                 
2458                 gdl = inb(info->base+MOXA_MUST_GDL_REGISTER);
2460                 if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID ) // add by Victor Yu. 02-11-2004
2461                         gdl &= MOXA_MUST_GDL_MASK;
2463                 // following add by Victor Yu. 10-13-2004
2464 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2465                 cnt = gdl = MIN(gdl, N_TTY_BUF_SIZE_MASK);
2466 #else
2467 #ifdef BYPASS_FLIP
2468                 cnt = gdl = MIN(gdl, TTY_FLIPBUF_SIZE); 
2469 #else
2470                 cnt = gdl = MIN(gdl, TTY_FLIPBUF_SIZE-tty->flip.count);
2471 #endif  // BYPASS_FLIP
2472 #endif  // CONFIG_MOXA_SUPPORT_SKIP_LD
2473                 // above add by Victor Yu. 10-13-2004
2475                 while ( gdl-- ) {
2476 #if 0   // mask by Victor Yu. 10-13-2004
2477 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2478                         if ( cnt >= TTY_FLIPBUF_SIZE )
2479                                 break;
2480 #else
2481                         if ( tty->flip.count >= TTY_FLIPBUF_SIZE )
2482                                 break;
2483 #endif
2484 #endif
2485                         ch = inb(info->base + UART_RX);
2486 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2487                         cp[wptr++] = ch;
2488                         wptr &= N_TTY_BUF_SIZE_MASK;
2489 #else
2490 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2491                         *cp++ = ch;
2492                         *fp++ = 0;
2493 #else
2494                         tty->flip.count++;
2495                         *tty->flip.char_buf_ptr++ = ch;
2496                         *tty->flip.flag_buf_ptr++ = 0;
2497 #endif  // BYPASS_FLIP
2498 #endif  // CONFIG_MOXA_SUPPORT_SKIP_LD
2499                         //cnt++; // mask by Victor Yu. 10-13-2004
2500                 }
2501                 goto end_intr;
2502         }
2503 intr_old:
2504         // above add by Victor Yu. 09-02-2002
2506         do {
2507             ch = inb(info->base + UART_RX);
2508             // following add by Victor Yu. 09-02-2002
2509             if ( info->IsMoxaMustChipFlag && (*status&UART_LSR_OE) && !(*status&UART_LSR_DR) )
2510                 outb(0x23, info->base+UART_FCR);
2512 #if 1   // add by Victor Yu. 01-06-2005
2513             {
2514             int         __flag=0;
2515             if ( *status & UART_LSR_BI ) {
2516                 info->icount.brk++;
2517                 __flag = 1;
2518             }
2519             if ( *status & UART_LSR_PE ) {
2520                 info->icount.parity++;
2521                 __flag = 1;
2522             }
2523             if ( *status & UART_LSR_FE ) {
2524                 info->icount.frame++;
2525                 __flag = 1;
2526             }
2527             if ( *status & UART_LSR_OE ) {
2528                 info->icount.overrun++;
2529                 __flag = 1;
2530             }
2531             if ( __flag ) 
2532                 wake_up_interruptible(&info->delta_msr_wait);
2533             }
2534 #endif
2536             *status &= info->read_status_mask;
2537             // above add by Victor Yu. 09-02-2002
2538             if ( *status & info->ignore_status_mask ) {
2539                 if ( ++ignored > 100 )
2540                     break;
2541             } else {
2542 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2543                 if ( (cnt+tty->read_cnt) >= N_TTY_BUF_SIZE_MASK )
2544                     break;
2545 #else
2546 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2547                 if ( cnt >= TTY_FLIPBUF_SIZE )
2548                     break;
2549 #else
2550                 if ( tty->flip.count >= TTY_FLIPBUF_SIZE )
2551                     break;
2552                 tty->flip.count++;
2553 #endif  // BYPASS_FLIP
2554 #endif  // CONFIG_MOXA_SUPPORT_SKIP_LD
2555                 if ( *status & UART_LSR_SPECIAL ) {
2556 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2557                         break;
2558 #else
2559                     if ( *status & UART_LSR_BI ) {
2560 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2561                         *fp++ = TTY_BREAK;
2562 #else
2563                         *tty->flip.flag_buf_ptr++ = TTY_BREAK;
2564 #endif
2566 #if 0   // mask by Victor Yu. 01-06-2005
2567 /* added by casper 1/11/2000 */
2568 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2569                         info->icount.brk++;
2570 #endif
2571 #endif
2573 /* */
2574                         if ( info->flags & ASYNC_SAK )
2575                             do_SAK(tty);
2576                     } else if ( *status & UART_LSR_PE ) {
2577 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2578                         *fp++ = TTY_PARITY;
2579 #else
2580                         *tty->flip.flag_buf_ptr++ = TTY_PARITY;
2581 #endif
2583 #if 0   // mask by Victor Yu. 01-06-2005
2584 /* added by casper 1/11/2000 */
2585 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2586                         info->icount.parity++;
2587 #endif
2588 #endif
2589 /* */
2590                     } else if ( *status & UART_LSR_FE ) {
2591 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2592                         *fp++ = TTY_FRAME;
2593 #else
2594                         *tty->flip.flag_buf_ptr++ = TTY_FRAME;
2595 #endif
2597 #if 0   // mask by Victor Yu. 01-06-2005
2598 /* added by casper 1/11/2000 */
2599 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2600                         info->icount.frame++;
2601 #endif
2602 #endif
2603 /* */
2604                     } else if ( *status & UART_LSR_OE ) {
2605 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2606                         *fp++ = TTY_OVERRUN;
2607 #else
2608                         *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
2609 #endif
2611 #if 0   // mask by Victor Yu. 01-06-2004
2612 /* added by casper 1/11/2000 */
2613 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2614                         info->icount.overrun++;
2615 #endif
2616 #endif
2617 /* */
2618                     } else {
2619 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2620                         *fp++ = 0;
2621 #else
2622                         *tty->flip.flag_buf_ptr++ = 0;
2623 #endif
2624                     }
2625 #endif  // CONFIG_MOXA_SUPPORT_SKIP_LD
2626                 } else {
2627 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2628                         // do nothing
2629 #else
2630 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2631                     *fp++ = 0;
2632 #else
2633                     *tty->flip.flag_buf_ptr++ = 0;
2634 #endif  // BYPASS_FLIP
2635 #endif  // CONFIG_MOXA_SUPPORT_SKIP_LD
2636                 }
2637 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2638                 cp[wptr++] = ch;
2639                 wptr &= N_TTY_BUF_SIZE_MASK;
2640 #else
2641 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2642                 *cp++ = ch;
2643 #else
2644                 *tty->flip.char_buf_ptr++ = ch;
2645 #endif  // BYPASS_FLIP
2646 #endif  // CONFIG_MOXA_SUPPORT_SKIP_LD
2647                 cnt++;
2648             }
2649         
2650             // following add by Victor Yu. 09-02-2002
2651             if ( info->IsMoxaMustChipFlag )
2652                 break;
2653             // above add by Victor Yu. 09-02-2002
2655             /* mask by Victor Yu. 09-02-2002
2656             *status = inb(info->base + UART_LSR) & info->read_status_mask;
2657             */
2658             // following add by Victor Yu. 09-02-2002
2659             *status = inb(info->base+UART_LSR);
2660             // above add by Victor Yu. 09-02-2002
2661         } while ( *status & UART_LSR_DR );
2663 end_intr:       // add by Victor Yu. 09-02-2002
2665         mxvar_log.rxcnt[info->port] += cnt;
2667 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)) // add by Victor Yu. 02-04-2005
2668         info->icount.rx += cnt;
2669 #endif
2671 /* added by casper 1/11/2000 */
2672 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD      // add by Victor Yu. 02-04-2005
2673         tty->read_head = wptr;
2674         tty->read_cnt += cnt;
2675 #else
2676 #ifdef BYPASS_FLIP      // add by Victor Yu. 09-17-2004
2677         tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, cnt);
2678 #else
2679 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2680         //info->icount.rx += cnt;       // mask by Victor Yu. 02-04-2005
2682         /* add by Victor Yu. 05-14-2002 following */
2683         //clear_bit(TTY_DONT_FLIP, &tty->flags); // mask by Victor Yu. 03-12-2004
2684         /* add by Victor Yu. 05-14-2002 above */
2686         tty_flip_buffer_push(tty);
2687 #else
2688         queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
2689 #endif  // LINUX_VERSION_CODE
2690 #endif  // BYPASS_FLIP
2691 #endif  // CONFIG_MOXA_SUPPORT_SKIP_LD
2692 /* */
2695 static inline void mxser_transmit_chars(struct mxser_struct *info)
2697         int     count, cnt;
2699         if ( info->x_char ) {
2700             outb(info->x_char, info->base + UART_TX);
2701             info->x_char = 0;
2702             mxvar_log.txcnt[info->port]++;
2703 /* added by casper 1/11/2000 */
2704 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2705             info->icount.tx++;
2706 #endif
2707 /* */
2708             return;
2709         }
2711         if ( info->xmit_buf == 0 )
2712                 return;
2714         if ((info->xmit_cnt <= 0) || info->tty->stopped ||
2715             (info->tty->hw_stopped && (info->type != PORT_16550A))) {
2716                 info->IER &= ~UART_IER_THRI;
2717                 outb(info->IER, info->base + UART_IER);
2718                 return;
2719         }
2721 #if 0   // mask by Victor Yu. 10-12-2004
2722         cnt = info->xmit_cnt;
2723         count = info->xmit_fifo_size;
2724         do {
2725             outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
2726             info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
2727             if ( --info->xmit_cnt <= 0 )
2728                 break;
2729         } while ( --count > 0 );
2730         mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
2731 #else   // add by Victor Yu. 10-12-2004
2732         {
2733         int             tail=info->xmit_tail;
2734         unsigned char   *ptr=info->xmit_buf;
2735 #define XMIT_SIZE_MASK  (SERIAL_XMIT_SIZE - 1)
2736         cnt = count = MIN(info->xmit_fifo_size, info->xmit_cnt);
2737         while ( count-- > 0 ) {
2738                 outb(ptr[tail++], info->base);
2739                 tail &= XMIT_SIZE_MASK;
2740         }
2741         info->xmit_tail = tail;
2742         info->xmit_cnt -= cnt;
2743         mxvar_log.txcnt[info->port] += cnt;
2744         }
2745 #endif
2747 /* added by casper 1/11/2000 */
2748 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2749 #if 0   // mask by Victor Yu. 10-12-2004
2750         info->icount.tx += (cnt - info->xmit_cnt);
2751 #else   // add by Victor Yu. 10-12-2004
2752         info->icount.tx += cnt;
2753 #endif
2754 #endif
2755 /* */
2757         if ( info->xmit_cnt < WAKEUP_CHARS ) {
2758                 set_bit(MXSER_EVENT_TXLOW,&info->event);
2759 #if 0
2760                 MOD_INC_USE_COUNT;
2761                 if (schedule_task(&info->tqueue) == 0) 
2762                         MOD_DEC_USE_COUNT;
2763                 queue_task(&info->tqueue,&tq_scheduler);
2764 #else
2765                 schedule_work(&info->tqueue);
2766 #endif
2767         }
2768         if (info->xmit_cnt <= 0) {
2769                 info->IER &= ~UART_IER_THRI;
2770                 outb(info->IER, info->base + UART_IER);
2771         }
2774 static inline void mxser_check_modem_status(struct mxser_struct *info,
2775                                               int status)
2777         /* update input line counters */
2778         if ( status & UART_MSR_TERI )
2779             info->icount.rng++;
2780         if ( status & UART_MSR_DDSR )
2781             info->icount.dsr++;
2782         if ( status & UART_MSR_DDCD )
2783             info->icount.dcd++;
2784         if ( status & UART_MSR_DCTS )
2785             info->icount.cts++;
2786         wake_up_interruptible(&info->delta_msr_wait);
2788         if ( (info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD) ) {
2789             if ( status & UART_MSR_DCD )
2790                 wake_up_interruptible(&info->open_wait);
2791 #if 0
2792             else if ( !((info->flags & ASYNC_CALLOUT_ACTIVE) &&
2793                       (info->flags & ASYNC_CALLOUT_NOHUP)) )
2794 #else
2795             else
2796 #endif
2797                 set_bit(MXSER_EVENT_HANGUP,&info->event);
2798 #if 0
2799                 MOD_INC_USE_COUNT; 
2800                 if (schedule_task(&info->tqueue) == 0) 
2801                         MOD_DEC_USE_COUNT; 
2802 #else
2803             schedule_work(&info->tqueue);
2804 #endif
2805         }
2806         if ( info->flags & ASYNC_CTS_FLOW ) {
2807             if ( info->tty->hw_stopped ) {
2808                 if (status & UART_MSR_CTS ){  
2809                     info->tty->hw_stopped = 0;
2811                     if (info->type != PORT_16550A) {
2812                         info->IER |= UART_IER_THRI;
2813                         outb(info->IER, info->base + UART_IER);
2814                     }
2815                     set_bit(MXSER_EVENT_TXLOW,&info->event);
2816 #if 0
2817                 MOD_INC_USE_COUNT; 
2818                 if (schedule_task(&info->tqueue) == 0)
2819                         MOD_DEC_USE_COUNT; 
2820 #else
2821                     schedule_work(&info->tqueue);
2822 #endif
2823                 }   
2824             } else {
2825                 if ( !(status & UART_MSR_CTS) ){
2826                     info->tty->hw_stopped = 1;
2827                     if (info->type != PORT_16550A) {
2828                         info->IER &= ~UART_IER_THRI;
2829                         outb(info->IER, info->base + UART_IER);
2830                     }
2831                 }
2832             }
2833         }
2836 static int mxser_block_til_ready(struct tty_struct *tty, struct file * filp,
2837                                  struct mxser_struct *info)
2839 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))
2840         DECLARE_WAITQUEUE(wait, current); 
2841 #else
2842         struct wait_queue       wait = { current, NULL };
2843 #endif
2844         unsigned long           flags;
2845         int                     retval;
2846         int                     do_clocal = 0;
2848         /*
2849          * If the device is in the middle of being closed, then block
2850          * until it's done, and then try again.
2851          */
2852         if ( tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING) ) {
2853             if ( info->flags & ASYNC_CLOSING )
2854                 interruptible_sleep_on(&info->close_wait);
2855 #ifdef SERIAL_DO_RESTART
2856             if ( info->flags & ASYNC_HUP_NOTIFY )
2857                 return(-EAGAIN);
2858             else
2859                 return(-ERESTARTSYS);
2860 #else
2861             return(-EAGAIN);
2862 #endif
2863         }
2865         /*
2866          * If this is a callout device, then just make sure the normal
2867          * device isn't being used.
2868          */
2869 #if 0
2870         if ( tty->driver->subtype == SERIAL_TYPE_CALLOUT ) {
2871             if ( info->flags & ASYNC_NORMAL_ACTIVE )
2872                 return(-EBUSY);
2873             if ( (info->flags & ASYNC_CALLOUT_ACTIVE) &&
2874                  (info->flags & ASYNC_SESSION_LOCKOUT) &&
2875                  (info->session != current->session) )
2876                 return(-EBUSY);
2877             if ( (info->flags & ASYNC_CALLOUT_ACTIVE) &&
2878                  (info->flags & ASYNC_PGRP_LOCKOUT) &&
2879                  (info->pgrp != current->pgrp) )
2880                 return(-EBUSY);
2881             info->flags |= ASYNC_CALLOUT_ACTIVE;
2882             return(0);
2883         }
2884 #endif
2886         /*
2887          * If non-blocking mode is set, or the port is not enabled,
2888          * then make the check up front and then exit.
2889          */
2890         if ( (filp->f_flags & O_NONBLOCK) ||
2891              (tty->flags & (1 << TTY_IO_ERROR)) ) {
2892 #if 0
2893             if ( info->flags & ASYNC_CALLOUT_ACTIVE )
2894                 return(-EBUSY);
2895 #endif
2896             info->flags |= ASYNC_NORMAL_ACTIVE;
2897             return(0);
2898         }
2900 #if 0
2901         if ( info->flags & ASYNC_CALLOUT_ACTIVE ) {
2902             if ( info->normal_termios.c_cflag & CLOCAL )
2903                 do_clocal = 1;
2904         } else {
2905 #endif
2906             if ( tty->termios->c_cflag & CLOCAL )
2907                 do_clocal = 1;
2908 #if 0
2909         }
2910 #endif
2912         /*
2913          * Block waiting for the carrier detect and the line to become
2914          * free (i.e., not in use by the callout).  While we are in
2915          * this loop, info->count is dropped by one, so that
2916          * mxser_close() knows when to free things.  We restore it upon
2917          * exit, either normal or abnormal.
2918          */
2919         retval = 0;
2920         add_wait_queue(&info->open_wait, &wait);
2921 #if 0   // mask by Victor Yu. 12-28-2004
2922         save_flags(flags);
2923         cli();
2924         if ( !tty_hung_up_p(filp) )
2925             info->count--;
2926         restore_flags(flags);
2927 #else   // add by Victor Yu. 12-28-2004
2928         if ( !tty_hung_up_p(filp) ) {
2929                 save_flags(flags);
2930                 cli();
2931                 info->count--;
2932                 restore_flags(flags);
2933         }
2934 #endif
2935         info->blocked_open++;
2936         while ( 1 ) {
2937             save_flags(flags);
2938             cli();
2939 #if 0
2940             if ( !(info->flags & ASYNC_CALLOUT_ACTIVE) )
2941 #endif
2942                 outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS,
2943                      info->base + UART_MCR);
2944             restore_flags(flags);
2945             current->state = TASK_INTERRUPTIBLE;
2946             if ( tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED) ) {
2947 #ifdef SERIAL_DO_RESTART
2948                 if ( info->flags & ASYNC_HUP_NOTIFY )
2949                     retval = -EAGAIN;
2950                 else
2951                     retval = -ERESTARTSYS;
2952 #else
2953                 retval = -EAGAIN;
2954 #endif
2955                 break;
2956             }
2957 #if 0
2958             if ( !(info->flags & ASYNC_CALLOUT_ACTIVE) &&
2959                  !(info->flags & ASYNC_CLOSING) &&
2960                  (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)) )
2961 #else
2962             if ( !(info->flags & ASYNC_CLOSING) &&
2963                  (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)) )
2964 #endif
2965                 break;
2966             if ( signal_pending(current) ) {
2967                 retval = -ERESTARTSYS;
2968                 break;
2969             }
2970             schedule();
2971         }
2972         current->state = TASK_RUNNING;
2973         remove_wait_queue(&info->open_wait, &wait);
2974         if ( !tty_hung_up_p(filp) ) {
2975 #if 0   // mask by Victor 12-28-2004
2976             info->count++;
2977 #else   // add by Victor Yu. 12-28-2004
2978             save_flags(flags);
2979             cli();
2980             info->count++;
2981             restore_flags(flags);
2982 #endif
2983         }
2984         info->blocked_open--;
2985         if ( retval )
2986             return(retval);
2987         info->flags |= ASYNC_NORMAL_ACTIVE;
2988         return(0);
2991 static int mxser_startup(struct mxser_struct * info)
2993         unsigned long   flags;
2994         unsigned long   page;
2996         page = get_zeroed_page(GFP_KERNEL);
2997         if ( !page )
2998             return(-ENOMEM);
3000         save_flags(flags);
3001         cli();
3003         if ( info->flags & ASYNC_INITIALIZED ) {
3004             free_page(page);
3005             restore_flags(flags);
3006             return(0);
3007         }
3009         if ( !info->base || !info->type ) {
3010             if ( info->tty )
3011                 set_bit(TTY_IO_ERROR, &info->tty->flags);
3012             free_page(page);
3013             restore_flags(flags);
3014             return(0);
3015         }
3016         if ( info->xmit_buf )
3017             free_page(page);
3018         else
3019             info->xmit_buf = (unsigned char *)page;
3021         /*
3022          * Clear the FIFO buffers and disable them
3023          * (they will be reenabled in mxser_change_speed())
3024          */
3025         if ( info->xmit_fifo_size == 16 )
3026             outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
3027                  info->base + UART_FCR);
3028         // following add by Victor Yu. 08-30-2002
3029         else if ( info->xmit_fifo_size == 64 || info->xmit_fifo_size == 128 )
3030             outb((UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT|MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base+UART_FCR);
3031         // above add by Victor Yu. 08-30-2002
3033         /*
3034          * At this point there's no way the LSR could still be 0xFF;
3035          * if it is, then bail out, because there's likely no UART
3036          * here.
3037          */
3038         if ( inb(info->base + UART_LSR) == 0xff ) {
3039             restore_flags(flags);
3040 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3041             if ( suser() ) {
3042 #else
3043             if (capable(CAP_SYS_ADMIN)) {
3044 #endif          
3045                 if ( info->tty )
3046                     set_bit(TTY_IO_ERROR, &info->tty->flags);
3047                 return(0);
3048             } else
3049                 return(-ENODEV);
3050         }
3051          
3052         /*
3053          * Clear the interrupt registers.
3054          */
3055         (void)inb(info->base + UART_LSR);
3056         (void)inb(info->base + UART_RX);
3057         (void)inb(info->base + UART_IIR);
3058         (void)inb(info->base + UART_MSR);
3060         /*
3061          * Now, initialize the UART
3062          */
3063         outb(UART_LCR_WLEN8, info->base + UART_LCR);    /* reset DLAB */
3064         info->MCR = UART_MCR_DTR | UART_MCR_RTS;
3065         outb(info->MCR, info->base + UART_MCR);
3067         /*
3068          * Finally, enable interrupts
3069          */
3070         info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
3072         // following add by Victor Yu. 08-30-2002
3073         if ( info->IsMoxaMustChipFlag )
3074                 info->IER |= MOXA_MUST_IER_EGDAI;
3075         // above add by Victor Yu. 08-30-2002
3077         outb(info->IER, info->base + UART_IER); /* enable interrupts */
3079         /*
3080          * And clear the interrupt registers again for luck.
3081          */
3082         (void)inb(info->base + UART_LSR);
3083         (void)inb(info->base + UART_RX);
3084         (void)inb(info->base + UART_IIR);
3085         (void)inb(info->base + UART_MSR);
3087 #if (LINUX_VERSION_CODE <  VERSION_CODE(2,1,0))
3088         if ( info->tty )
3089             clear_bit(TTY_IO_ERROR, &info->tty->flags);
3090 #else
3091         if ( info->tty )
3092             test_and_clear_bit(TTY_IO_ERROR, &info->tty->flags);
3093 #endif
3094         info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
3096         /*
3097          * and set the speed of the serial port
3098          */
3099 #if 1   // add by Victor Yu. 12-27-2004
3100         restore_flags(flags);
3101 #endif
3102         mxser_change_speed(info, 0);
3104 #if 1   // add by Victor Yu. 12-27-2004
3105         save_flags(flags);
3106         cli();
3107 #endif
3108         info->flags |= ASYNC_INITIALIZED;
3109         restore_flags(flags);
3110         return(0);
3114  * This routine will shutdown a serial port; interrupts maybe disabled, and
3115  * DTR is dropped if the hangup on close termio flag is on.
3116  */
3117 static void mxser_shutdown(struct mxser_struct * info)
3119         unsigned long   flags;
3121         if ( !(info->flags & ASYNC_INITIALIZED) )
3122             return;
3124         save_flags(flags);
3125         cli();                  /* Disable interrupts */
3127         /*
3128          * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
3129          * here so the queue might never be waken up
3130          */
3131         wake_up_interruptible(&info->delta_msr_wait);
3133         /*
3134          * Free the IRQ, if necessary
3135          */
3136         if ( info->xmit_buf ) {
3137             free_page((unsigned long)info->xmit_buf);
3138             info->xmit_buf = 0;
3139         }
3141         info->IER = 0;
3142         outb(0x00, info->base + UART_IER);
3144         if ( !info->tty || (info->tty->termios->c_cflag & HUPCL) )
3145             info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
3146         outb(info->MCR, info->base + UART_MCR);
3148         /* clear Rx/Tx FIFO's */
3149         // following add by Victor Yu. 08-30-2002
3150         if ( info->IsMoxaMustChipFlag )
3151                 outb((UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT|MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
3152         else
3153         // above add by Victor Yu. 08-30-2002
3154                 outb((UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
3156         /* read data port to reset things */
3157         (void)inb(info->base + UART_RX);
3159         if ( info->tty )
3160             set_bit(TTY_IO_ERROR, &info->tty->flags);
3162         info->flags &= ~ASYNC_INITIALIZED;
3164         // following add by Victor Yu. 09-23-2002
3165         if ( info->IsMoxaMustChipFlag ) {
3166                 SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base);
3167         }
3168         // above add by Victor Yu. 09-23-2002
3170         restore_flags(flags);
3174  * This routine is called to set the UART divisor registers to match
3175  * the specified baud rate for a serial port.
3176  */
3177 static int mxser_change_speed(struct mxser_struct *info,
3178                               struct termios *old_termios)
3180         int             quot = 0;
3181         unsigned        cflag, cval, fcr;
3182         int             bindex;
3183         int             ret = 0;
3184         unsigned long   flags;
3186         if ( !info->tty || !info->tty->termios )
3187             return ret;
3188         cflag = info->tty->termios->c_cflag;
3189         if ( !(info->base) )
3190             return ret;
3191            
3192 #ifndef B921600
3193 #define B921600 (B460800 +1)
3194 #endif 
3195         switch( cflag & (CBAUD | CBAUDEX) ){
3196 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-13-2004
3197         case B4000000 : bindex = BAUD_TABLE_NO; break;
3198 #endif
3199         case B921600 : bindex = 20; break;
3200         case B460800 : bindex = 19; break;
3201         case B230400 : bindex = 18; break;
3202         case B115200 : bindex = 17; break;
3203         case B57600 : bindex = 16; break;
3204         case B38400 : bindex = 15; break;
3205         case B19200 : bindex = 14; break;
3206         case B9600 : bindex = 13; break;
3207         case B4800 : bindex = 12; break;
3208         case B2400 : bindex = 11; break;
3209         case B1800 : bindex = 10; break;
3210         case B1200 : bindex = 9; break;
3211         case B600 : bindex = 8; break;
3212         case B300 : bindex = 7; break;
3213         case B200 : bindex = 6; break;
3214         case B150 : bindex = 5; break;
3215         case B134 : bindex = 4; break;
3216         case B110 : bindex = 3; break;
3217         case B75 : bindex = 2; break;
3218         case B50 : bindex = 1; break;
3219         default:   bindex = 0; break;
3220         }
3221         
3222         if ( bindex == 15 ) {
3223             if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI )
3224                 bindex = 16;                                    /* 57600 bps */
3225             if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI )
3226                 bindex = 17;                                    /* 115200 bps */
3227                 
3228 #ifdef ASYNC_SPD_SHI
3229             if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3230                 bindex = 18;
3231 #endif
3233 #ifdef ASYNC_SPD_WARP
3234             if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3235                 bindex = 19;
3236 #endif
3237         }
3238 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-13-2004
3239         if ( bindex == BAUD_TABLE_NO ) {
3240                 quot = info->baud_base / info->speed;
3241                 if ( info->speed <= 0 || info->speed > info->MaxCanSetBaudRate )
3242                         quot = 0;
3243         }
3244         else
3245 #endif
3246         if ( mxvar_baud_table[bindex] == 134 ) {
3247             quot = (2 * info->baud_base / 269);
3248 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
3249             info->speed = 134;
3250 #endif
3251         } else if ( mxvar_baud_table[bindex] ) {
3252             quot = info->baud_base / mxvar_baud_table[bindex];
3253             // following add by Victor Yu. 09-04-2002
3254             if ( mxvar_baud_table[bindex] > info->MaxCanSetBaudRate )
3255                 quot = 0;
3256             // add by Victor Yu. 09-04-2002
3257 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
3258             info->speed = mxvar_baud_table[bindex];
3259 #endif
3260             if (!quot && old_termios) {
3261                 /* re-calculate */
3262                 info->tty->termios->c_cflag &= ~CBAUD;
3263                 info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
3264                 switch( info->tty->termios->c_cflag & (CBAUD | CBAUDEX) ){
3265 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-13-2004
3266                 case B4000000 : bindex = BAUD_TABLE_NO; break;
3267 #endif
3268                 case B921600 : bindex = 20; break;
3269                 case B460800 : bindex = 19; break;
3270                 case B230400 : bindex = 18; break;
3271                 case B115200 : bindex = 17; break;
3272                 case B57600 : bindex = 16; break;
3273                 case B38400 : bindex = 15; break;
3274                 case B19200 : bindex = 14; break;
3275                 case B9600 : bindex = 13; break;
3276                 case B4800 : bindex = 12; break;
3277                 case B2400 : bindex = 11; break;
3278                 case B1800 : bindex = 10; break;
3279                 case B1200 : bindex = 9; break;
3280                 case B600 : bindex = 8; break;
3281                 case B300 : bindex = 7; break;
3282                 case B200 : bindex = 6; break;
3283                 case B150 : bindex = 5; break;
3284                 case B134 : bindex = 4; break;
3285                 case B110 : bindex = 3; break;
3286                 case B75 : bindex = 2; break;
3287                 case B50 : bindex = 1; break;
3288                 default:   bindex = 0; break;
3289                 }
3290                 if ( bindex == 15 ) {
3291                     if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI )
3292                         bindex = 16;                                    /* 57600 bps */
3293                     if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI )
3294                         bindex = 17;                                    /* 115200 bps */
3295 #ifdef ASYNC_SPD_SHI
3296                     if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3297                         bindex = 18;
3298 #endif
3299 #ifdef ASYNC_SPD_WARP
3300                     if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3301                         bindex = 19;
3302 #endif
3303                 }
3304 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-13-2004
3305                 if ( bindex == BAUD_TABLE_NO ) {
3306                         quot = info->baud_base / info->speed;
3307                         if ( info->speed <= 0 || info->speed > info->MaxCanSetBaudRate )
3308                                 quot = 0;
3309                 }
3310                 else
3311 #endif
3312                 if ( mxvar_baud_table[bindex] == 134 ) {
3313                     quot = (2 * info->baud_base / 269);
3314 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
3315                     info->speed = 134;
3316 #endif
3317                 } else if ( mxvar_baud_table[bindex] ) {
3318                     quot = info->baud_base / mxvar_baud_table[bindex];
3319                     // following add by Victor Yu. 09-04-2002
3320                     if ( mxvar_baud_table[bindex] > info->MaxCanSetBaudRate )
3321                         quot = 0;
3322                     // above add by Victor Yu. 09-04-2002
3323 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
3324                     info->speed = mxvar_baud_table[bindex];
3325 #endif
3326                     if(quot==0)
3327                         quot = 1;
3328                 } else {
3329                     quot = 0;
3330                 }
3331             }else if(quot==0)
3332                 quot = 1;
3333         } else {
3334             quot = 0;
3335         }
3337         info->timeout = ((info->xmit_fifo_size*HZ*10*quot) / info->baud_base);
3338         info->timeout += HZ/50;         /* Add .02 seconds of slop */
3340         if ( quot ) {
3341             save_flags(flags);
3342             cli();
3343             info->MCR |= UART_MCR_DTR;
3344             outb(info->MCR, info->base + UART_MCR);
3345             restore_flags(flags);
3346         } else {
3347             save_flags(flags);
3348             cli();
3349             info->MCR &= ~UART_MCR_DTR;
3350             outb(info->MCR, info->base + UART_MCR);
3351             restore_flags(flags);
3352             return ret;
3353         }
3354         /* byte size and parity */
3355         switch ( cflag & CSIZE ) {
3356         case CS5: cval = 0x00; break;
3357         case CS6: cval = 0x01; break;
3358         case CS7: cval = 0x02; break;
3359         case CS8: cval = 0x03; break;
3360         default:  cval = 0x00; break;   /* too keep GCC shut... */
3361         }
3362         if ( cflag & CSTOPB )
3363             cval |= 0x04;
3364         if ( cflag & PARENB )
3365             cval |= UART_LCR_PARITY;
3366 #ifndef CMSPAR
3367 #define CMSPAR 010000000000
3368 #endif
3369         if ( !(cflag & PARODD) ){
3370             cval |= UART_LCR_EPAR;
3371         }
3372         if ( cflag & CMSPAR )
3373             cval |= UART_LCR_SPAR;
3375         if ( (info->type == PORT_8250) || (info->type == PORT_16450) ) {
3376             fcr = 0;
3377         } else {
3378             fcr = UART_FCR_ENABLE_FIFO;
3379             // following add by Victor Yu. 08-30-2002
3380             if ( info->IsMoxaMustChipFlag ) {
3381                 fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
3382 #if 1   // add by Victor Yu. 05-04-2005
3383                 save_flags(flags);
3384                 cli();
3385 #endif
3386                 SET_MOXA_MUST_FIFO_VALUE(info);
3387 #if 1   // add by Victor Yu. 05-04-2005
3388         restore_flags(flags);
3389 #endif
3390             } else {
3391             // above add by Victor Yu. 08-30-2002
3393                 switch ( info->rx_trigger ) {
3394                 case 1:  fcr |= UART_FCR_TRIGGER_1; break;
3395                 case 4:  fcr |= UART_FCR_TRIGGER_4; break;
3396                 case 8:  fcr |= UART_FCR_TRIGGER_8; break;
3397                 default: fcr |= UART_FCR_TRIGGER_14;
3398                 }
3399             }
3400         }
3402         /* CTS flow control flag and modem status interrupts */
3403 #if 1   // add by Victor Yu. 12-30-2004
3404         save_flags(flags);
3405         cli();
3406 #if 1   // add by Victor Yu. 05-04-2005
3407         outb(cval | UART_LCR_DLAB, info->base + UART_LCR);  /* set DLAB */
3408         outb(quot & 0xff, info->base + UART_DLL);           /* LS of divisor */
3409         outb(quot >> 8, info->base + UART_DLM);             /* MS of divisor */
3410         outb(cval, info->base + UART_LCR);                  /* reset DLAB */
3411 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
3412         if ( info->speed ) {
3413                 quot = info->baud_base % info->speed;
3414                 quot *= 8;
3415                 if ( (quot % info->speed) > (info->speed / 2) ) {
3416                         quot /= info->speed;
3417                         quot++;
3418                 } else {
3419                         quot /= info->speed;
3420                 }
3421                 SET_MOXA_MUST_ENUM_VALUE(info->base, quot);
3422         } else {
3423                 SET_MOXA_MUST_ENUM_VALUE(info->base, 0);
3424         }
3425 #endif
3426         outb(fcr, info->base + UART_FCR);                   /* set fcr */
3427 #endif  // 05-04-2005
3428 #endif  // 12-30-2004
3429 #if 0   // mask by Victor Yu. 12-31-2004
3430         info->IER &= ~UART_IER_MSI;
3431 #endif
3432         info->MCR &= ~UART_MCR_AFE;
3433         if ( cflag & CRTSCTS ) {
3434             info->flags |= ASYNC_CTS_FLOW;
3435             info->IER |= UART_IER_MSI;
3436             if ( info->type == PORT_16550A ) {
3437                 info->MCR |= UART_MCR_AFE;
3438             } else {
3439                         unsigned char status;
3440 #if 0   // mask by Victor Yu. 12-30-2004
3441                         save_flags(flags);
3442                         cli();
3443 #endif
3444                         status = inb(info->base + UART_MSR);
3445 #if 0   // mask by Victor Yu. 12-30-2004
3446                         restore_flags(flags);
3447 #endif
3448                         if (info->tty->hw_stopped) {
3449                                 if (status & UART_MSR_CTS) {
3450                                         info->tty->hw_stopped = 0;
3451                                         if (info->type != PORT_16550A) {
3452                                                 info->IER |= UART_IER_THRI;
3453                                                 outb(info->IER, info->base + UART_IER);
3454                                         }
3455                                         set_bit(MXSER_EVENT_TXLOW, &info->event);
3456 #if 0
3457                                         MOD_INC_USE_COUNT; 
3458                                         if (schedule_task(&info->tqueue) == 0) 
3459                                                 MOD_DEC_USE_COUNT; 
3460 #else
3461                                         schedule_work(&info->tqueue);
3462 #endif
3463                                 }
3464                         } else {
3465                                 if (!(status & UART_MSR_CTS)) {
3466                                         info->tty->hw_stopped = 1;
3467                                         if (info->type != PORT_16550A) {
3468                                                 info->IER &= ~UART_IER_THRI;
3469                                                 outb(info->IER, info->base + UART_IER);
3470                                         }
3471                                 }
3472                         }
3473                 }
3474         } else {
3475             info->flags &= ~ASYNC_CTS_FLOW;
3476         }
3477 #if 0   // add by Victor Yu. 12-27-2004
3478         save_flags(flags);
3479         cli();
3480 #endif
3481         outb(info->MCR, info->base + UART_MCR);
3482         if ( cflag & CLOCAL ){
3483             info->flags &= ~ASYNC_CHECK_CD;
3484         }else {
3485             info->flags |= ASYNC_CHECK_CD;
3486             info->IER |= UART_IER_MSI;
3487         }
3488         outb(info->IER, info->base + UART_IER);
3489 #if 1   // add by Victor Yu. 12-27-2004
3490         restore_flags(flags);
3491 #endif
3493         /*
3494          * Set up parity check flag
3495          */
3496         info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
3497         if ( I_INPCK(info->tty) )
3498             info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
3499         if ( I_BRKINT(info->tty) || I_PARMRK(info->tty) )
3500             info->read_status_mask |= UART_LSR_BI;
3502         info->ignore_status_mask = 0;
3503 #if 0
3504         /* This should be safe, but for some broken bits of hardware... */
3505         if ( I_IGNPAR(info->tty) ) {
3506             info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
3507             info->read_status_mask |= UART_LSR_PE | UART_LSR_FE;
3508         }
3509 #endif
3510         if ( I_IGNBRK(info->tty) ) {
3511             info->ignore_status_mask |= UART_LSR_BI;
3512             info->read_status_mask |= UART_LSR_BI;
3513             /*
3514              * If we're ignore parity and break indicators, ignore
3515              * overruns too.  (For real raw support).
3516              */
3517             if ( I_IGNPAR(info->tty) ) {
3518                 info->ignore_status_mask |= UART_LSR_OE|UART_LSR_PE|UART_LSR_FE;
3519                 info->read_status_mask |= UART_LSR_OE|UART_LSR_PE|UART_LSR_FE;
3520             }
3521         }
3522         
3523         // following add by Victor Yu. 09-02-2002
3524         if ( info->IsMoxaMustChipFlag ) {
3525                 save_flags(flags);
3526                 cli();
3527                 SET_MOXA_MUST_XON1_VALUE(info->base, START_CHAR(info->tty));
3528                 SET_MOXA_MUST_XOFF1_VALUE(info->base, STOP_CHAR(info->tty));
3529                 if ( I_IXON(info->tty) ) {
3530 #if 1   // add by Victor Yu. 01-04-2005
3531                         info->IER |= MOXA_MUST_IER_XINT;
3532 #endif
3533                         ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
3534                 } else {
3535 #if 1   // add by Victor Yu. 01-04-2005
3536                         info->IER &= ~MOXA_MUST_IER_XINT;
3537 #endif
3538                         DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
3539                 }
3540 #if 1   // add by Victor Yu. 01-04-2005
3541                 outb(info->IER, info->base+UART_IER);
3542 #endif
3543                 if ( I_IXOFF(info->tty) ) {
3544                         ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base);
3545                 } else {
3546                         DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base);
3547                 }
3548                 if ( I_IXANY(info->tty) ) {
3549                         info->MCR |= MOXA_MUST_MCR_XON_ANY;
3550                         ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base);
3551                 } else {
3552                         info->MCR &= ~MOXA_MUST_MCR_XON_ANY;
3553                         DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base);
3554                 }
3555                 restore_flags(flags);
3556         }
3557         // above add by Victor Yu. 09-02-2002
3559 #if 0   // mask by Victor Yu. 05-04-2005
3560         save_flags(flags);
3561         cli();
3562         outb(cval | UART_LCR_DLAB, info->base + UART_LCR);  /* set DLAB */
3563         outb(quot & 0xff, info->base + UART_DLL);           /* LS of divisor */
3564         outb(quot >> 8, info->base + UART_DLM);             /* MS of divisor */
3565         outb(cval, info->base + UART_LCR);                  /* reset DLAB */
3566 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE    // add by Victor Yu. 08-12-2004
3567         if ( info->speed ) {
3568                 quot = info->baud_base % info->speed;
3569                 quot *= 8;
3570                 if ( (quot % info->speed) > (info->speed / 2) ) {
3571                         quot /= info->speed;
3572                         quot++;
3573                 } else {
3574                         quot /= info->speed;
3575                 }
3576                 SET_MOXA_MUST_ENUM_VALUE(info->base, quot);
3577         } else {
3578                 SET_MOXA_MUST_ENUM_VALUE(info->base, 0);
3579         }
3580 #endif
3581         outb(fcr, info->base + UART_FCR);                   /* set fcr */
3582         restore_flags(flags);
3583 #endif
3585         return ret;
3589  * ------------------------------------------------------------
3590  * friends of mxser_ioctl()
3591  * ------------------------------------------------------------
3592  */
3593 static int mxser_get_serial_info(struct mxser_struct * info,
3594                                  struct serial_struct * retinfo)
3596         struct serial_struct    tmp;
3598         if ( !retinfo )
3599             return(-EFAULT);
3600         memset(&tmp, 0, sizeof(tmp));
3601         tmp.type = info->type;
3602         tmp.line = info->port;
3603         tmp.port = info->base;
3604         tmp.irq = info->irq;
3605         tmp.flags = info->flags;
3606         tmp.baud_base = info->baud_base;
3607         tmp.close_delay = info->close_delay;
3608         tmp.closing_wait = info->closing_wait;
3609         tmp.custom_divisor = info->custom_divisor;
3610         tmp.hub6 = 0;
3611         copy_to_user(retinfo, &tmp, sizeof(*retinfo));
3612         return(0);
3615 static int mxser_set_serial_info(struct mxser_struct * info,
3616                                  struct serial_struct * new_info)
3618         struct serial_struct    new_serial;
3619         unsigned int            flags;
3620         int                     retval = 0;
3622         if ( !new_info || !info->base )
3623             return(-EFAULT);
3624         copy_from_user(&new_serial, new_info, sizeof(new_serial));
3626         if ( (new_serial.irq != info->irq) ||
3627              (new_serial.port != info->base) ||
3628              (new_serial.custom_divisor != info->custom_divisor) ||
3629              (new_serial.baud_base != info->baud_base) )
3630             return(-EPERM);
3632         flags = info->flags & ASYNC_SPD_MASK;
3634 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3635        if ( !suser() ) {
3636 #else
3637        if ( !capable(CAP_SYS_ADMIN)) {
3638 #endif          
3639             if ( (new_serial.baud_base != info->baud_base) ||
3640                  (new_serial.close_delay != info->close_delay) ||
3641                  ((new_serial.flags & ~ASYNC_USR_MASK) !=
3642                  (info->flags & ~ASYNC_USR_MASK)) )
3643                 return(-EPERM);
3644             info->flags = ((info->flags & ~ASYNC_USR_MASK) |
3645                           (new_serial.flags & ASYNC_USR_MASK));
3646         } else {
3647             /*
3648              * OK, past this point, all the error checking has been done.
3649              * At this point, we start making changes.....
3650              */
3651             info->flags = ((info->flags & ~ASYNC_FLAGS) |
3652                           (new_serial.flags & ASYNC_FLAGS));
3653             info->close_delay = new_serial.close_delay * HZ/100;
3654             info->closing_wait = new_serial.closing_wait * HZ/100;
3655 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
3656             info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
3657 #endif
3658         }
3660 /* added by casper, 3/17/2000, for mouse */
3661         info->type = new_serial.type;
3663         // following add by Victor Yu. 09-02-2002
3664         // if ( info->IsMoxaMustChipFlag )      // mask by Victor Yu. 02-10-2004
3665         if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID ) {
3666                 info->xmit_fifo_size = 64;
3667         } else if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID1 ) {
3668                 info->xmit_fifo_size = 128;
3669         }
3670         // above add by Victor Yu. 09-02-2002
3671         if(info->type == PORT_16550A)
3672                 info->xmit_fifo_size = 16;
3673         else
3674                 info->xmit_fifo_size = 1;
3675 /* */
3676         if ( info->flags & ASYNC_INITIALIZED ) {
3677             if ( flags != (info->flags & ASYNC_SPD_MASK) ){
3678                 mxser_change_speed(info,0);
3679             }
3680         } else{
3681             retval = mxser_startup(info);
3682         }
3683         return(retval);
3687  * mxser_get_lsr_info - get line status register info
3689  * Purpose: Let user call ioctl() to get info when the UART physically
3690  *          is emptied.  On bus types like RS485, the transmitter must
3691  *          release the bus after transmitting. This must be done when
3692  *          the transmit shift register is empty, not be done when the
3693  *          transmit holding register is empty.  This functionality
3694  *          allows an RS485 driver to be written in user space.
3695  */
3696 static int mxser_get_lsr_info(struct mxser_struct * info, unsigned int *value)
3698         unsigned char   status;
3699         unsigned int    result;
3700         unsigned long   flags;
3702         save_flags(flags);
3703         cli();
3704         status = inb(info->base + UART_LSR);
3705         restore_flags(flags);
3706         result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
3707         put_to_user(result, value);
3708         return(0);
3712  * This routine sends a break character out the serial port.
3713  */
3714 static void mxser_send_break(struct mxser_struct * info, int duration)
3716         unsigned long   flags;
3717 #if 1   // add by Victor Yu. 12-27-2004
3718         unsigned long   timeout;
3719 #endif
3721         if ( !info->base )
3722             return;
3723 #if 0   // mask by Victor Yu. 12-27-2004
3724         current->state = TASK_INTERRUPTIBLE;
3725 #endif
3726         save_flags(flags);
3727         cli();
3728         outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
3729 #if 0   // mask by Victor Yu. 12-27-2004
3730         schedule_timeout(duration);
3731 #else   // add by Victor Yu. 12-27-2004
3732         restore_flags(flags);
3733         timeout = jiffies + (unsigned long)duration;
3734         while ( 1 ) {
3735                 current->state = TASK_INTERRUPTIBLE;
3736                 schedule_timeout(5);
3737                 if ( time_after(jiffies, timeout) )
3738                         break;
3739         }
3740         save_flags(flags);
3741         cli();
3742 #endif
3743         outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
3744         restore_flags(flags);
3747 static int mxser_get_modem_info(struct mxser_struct * info,
3748                                 unsigned int *value)
3750         unsigned char   control, status;
3751         unsigned int    result;
3752         unsigned long   flags;
3754         save_flags(flags);
3755         cli();
3756         control = info->MCR;
3757         status = inb(info->base + UART_MSR);
3758 #if 0   // mask by Victor Yu. 12-30-2004, I think that we donot need to do it. Because the interrupt service will do it.
3759         if ( status & UART_MSR_ANY_DELTA )
3760             mxser_check_modem_status(info, status);
3761 #endif
3762         restore_flags(flags);
3763         result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
3764                  ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
3765                  ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0) |
3766                  ((status  & UART_MSR_RI)  ? TIOCM_RNG : 0) |
3767                  ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0) |
3768                  ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
3769         put_to_user(result, value);
3770         return(0);
3773 static int mxser_set_modem_info(struct mxser_struct * info, unsigned int cmd,
3774                                 unsigned int *value)
3776         int             error;
3777         unsigned int    arg;
3778         unsigned long   flags;
3780         error = verify_area(VERIFY_READ, value, sizeof(int));
3781         if ( error )
3782             return(error);
3783         get_from_user(arg,value);
3784 #if 1   // add by Victor Yu. 12-30-2004
3785         save_flags(flags);
3786         cli();
3787 #endif
3788         switch ( cmd ) {
3789         case TIOCMBIS:
3790             if ( arg & TIOCM_RTS )
3791                 info->MCR |= UART_MCR_RTS;
3792             if ( arg & TIOCM_DTR )
3793                 info->MCR |= UART_MCR_DTR;
3794             break;
3795         case TIOCMBIC:
3796             if ( arg & TIOCM_RTS )
3797                 info->MCR &= ~UART_MCR_RTS;
3798             if ( arg & TIOCM_DTR )
3799                 info->MCR &= ~UART_MCR_DTR;
3800             break;
3801         case TIOCMSET:
3802             info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) |
3803                         ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) |
3804                         ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
3805             break;
3806         default:
3807 #if 1   // add by Victor Yu. 12-30-2004
3808             restore_flags(flags);
3809 #endif
3810             return(-EINVAL);
3811         }
3812 #if 0   // mask by Victor Yu. 12-30-2004
3813         save_flags(flags);
3814         cli();
3815 #endif
3816         outb(info->MCR, info->base + UART_MCR);
3817         restore_flags(flags);
3818         return(0);