MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / char / mxser.c
blobe6a23bad3b2718b77c2ed26c97ee104838a0ff45
1 /*
2 * mxser.c -- MOXA Smartio/Industio family multiport serial driver.
4 * Copyright (C) 1999-2001 Moxa Technologies (support@moxa.com.tw).
6 * This code is loosely based on the Linux serial driver, written by
7 * Linus Torvalds, Theodore T'so and others.
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.
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.
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.
23 * Original release 10/26/00
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.
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>
65 #if 1 // add by Victor Yu. 02-21-2006
66 #include <linux/proc_fs.h>
67 #endif
69 #include <asm/system.h>
70 #include <asm/io.h>
71 #include <asm/irq.h>
72 #include <asm/segment.h>
73 #include <asm/bitops.h>
75 #define VERSION_CODE(ver,rel,seq) ((ver << 16) | (rel << 8) | seq)
77 #define MXSER_VERSION "2.0"
78 #define MXSERMAJOR 30
79 #define MXSERCUMAJOR 35
81 #ifdef CONFIG_PCI
82 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
83 #include <linux/bios32.h>
84 #endif
85 #include <linux/pci.h>
86 #endif /* ENABLE_PCI */
88 #include <asm/uaccess.h>
89 #define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)
90 #define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)
92 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128) && !(defined CONFIG_ARCH_IA241_16128)
93 #undef UART_RX
94 #undef UART_TX
95 #undef UART_DLL
96 #undef UART_TRG
97 #undef UART_DLM
98 #undef UART_IER
99 #undef UART_FCTR
100 #undef UART_IIR
101 #undef UART_FCR
102 #undef UART_EFR
103 #undef UART_LCR
104 #undef UART_MCR
105 #undef UART_LSR
106 #undef UART_MSR
107 #undef UART_SCR
108 #undef UART_EMSR
109 #define UART_RX 0
110 #define UART_TX 0
111 #define UART_DLL 0
112 #define UART_TRG 0
113 #define UART_DLM 4
114 #define UART_IER 4
115 #define UART_FCTR 4
116 #define UART_IIR 8
117 #define UART_FCR 8
118 #define UART_EFR 8
119 #define UART_LCR 12
120 #define UART_MCR 16
121 #define UART_LSR 20
122 #define UART_MSR 24
123 #define UART_SCR 28
124 #define UART_EMSR 28
125 #endif // !CONFIG_ARCH_IA241
127 #define MXSER_EVENT_TXLOW 1
128 #define MXSER_EVENT_HANGUP 2
130 #define SERIAL_DO_RESTART
132 #define MXSER_BOARDS 4 /* Max. boards */
133 #define MXSER_PORTS 32 /* Max. ports */
134 #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board*/
135 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
136 #define MXSER_ISR_PASS_LIMIT 8192 // add by Victor Yu. 02-04-2005
137 #else
138 #define MXSER_ISR_PASS_LIMIT 256 // mask by Victor Yu. 02-04-2005
139 #endif
141 #define MXSER_ERR_IOADDR -1
142 #define MXSER_ERR_IRQ -2
143 #define MXSER_ERR_IRQ_CONFLIT -3
144 #define MXSER_ERR_VECTOR -4
146 #define SERIAL_TYPE_NORMAL 1
147 #define SERIAL_TYPE_CALLOUT 2
149 #define WAKEUP_CHARS 256
151 #define UART_MCR_AFE 0x20
152 #define UART_LSR_SPECIAL 0x1E
154 #if 0
155 #define PORTNO(x) (MINOR((x)->device) - (x)->driver.minor_start)
156 #else
157 #define PORTNO(x) ((x)->index)
158 #endif
160 #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
162 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
164 #ifndef MIN
165 #define MIN(a,b) ((a) < (b) ? (a) : (b))
166 #endif
168 enum {
169 IA240_BOARD=1,
172 static char *mxser_brdname[] = {
173 "MU860 UART",
176 static int mxser_numports[] = {
177 #if defined(CONFIG_ARCH_UC_7112_LX_PLUS) || defined(CONFIG_ARCH_UC_7112_LX_PLUS_LITON) || defined(CONFIG_ARCH_W321) || defined(CONFIG_ARCH_W325)
179 #elif defined(CONFIG_ARCH_W311) || defined(CONFIG_ARCH_W315)
181 #else
182 #ifdef CONFIG_MOXA_SMARTIO_PCIE
184 #else
186 #endif
187 #endif
190 typedef struct {
191 unsigned short vendor_id;
192 unsigned short device_id;
193 unsigned short board_type;
194 } mxser_pciinfo;
196 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128)// add by Victor Yu. 05-22-2007
197 static mxser_pciinfo mxser_pcibrds[] = {
198 {0x1393,0x0001,IA240_BOARD},
199 #ifdef CONFIG_MOXA_SMARTIO_PCIE
200 {0x1393,0x1181,IA240_BOARD},
201 #endif
203 #endif
206 * MOXA ioctls
208 #define MOXA 0x400
209 #define MOXA_GETDATACOUNT (MOXA + 23)
210 #define MOXA_GET_CONF (MOXA + 35)
211 #define MOXA_DIAGNOSE (MOXA + 50)
212 #define MOXA_CHKPORTENABLE (MOXA + 60)
213 #define MOXA_HighSpeedOn (MOXA + 61)
214 #define MOXA_GET_MAJOR (MOXA + 63)
215 #define MOXA_GET_CUMAJOR (MOXA + 64)
216 #define MOXA_GETMSTATUS (MOXA + 65)
218 // following add by Victor Yu. 01-05-2004
219 #define MOXA_SET_OP_MODE (MOXA + 66)
220 #define MOXA_GET_OP_MODE (MOXA + 67)
222 #if 1 // add by Victor Yu. 05-08-2007, to support IDMX special
223 #define MOXA_BREAK_TIMER (MOXA + 70)
224 #endif
226 #if 1 // add by Victor Yu. 01-26-2005
227 #define MOXA_UNWAIT (MOXA+200)
228 #define MXSER_PROC_NODE "driver/mxser" // add by Victor Yu. 07-27-2004
229 #endif
231 #define RS232_MODE 0
232 #define RS485_2WIRE_MODE 1
233 #define RS422_MODE 2
234 #define RS485_4WIRE_MODE 3
235 #define OP_MODE_MASK 3
236 // above add by Victor Yu. 01-05-2004
238 #define CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE
239 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
240 #define UC_SET_SPECIAL_BAUD_RATE (MOXA+68)
241 #define UC_GET_SPECIAL_BAUD_RATE (MOXA+69)
242 #define MOXA_SET_SPECIAL_BAUD_RATE (MOXA+100)
243 #define MOXA_GET_SPECIAL_BAUD_RATE (MOXA+101)
244 #endif
246 static int ttymajor=MXSERMAJOR;
247 static int calloutmajor=MXSERCUMAJOR;
248 static int verbose=0;
250 /* Variables for insmod */
251 MODULE_AUTHOR("Victor Yu.");
252 MODULE_DESCRIPTION("MOXA MU860 UART Device Driver");
254 typedef struct _moxa_pci_info {
255 unsigned short busNum;
256 unsigned short devNum;
257 struct pci_dev *pdev; // add by Victor Yu. 06-23-2003
258 } moxa_pci_info;
260 struct mxser_hwconf {
261 int board_type;
262 int ports;
263 int irq;
264 int vector;
265 int vector_mask;
266 int uart_type;
267 int ioaddr[MXSER_PORTS_PER_BOARD];
268 int baud_base[MXSER_PORTS_PER_BOARD];
269 moxa_pci_info pciInfo;
270 int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 09-04-2002
271 int opmode_ioaddr[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 01-05-2004
274 struct mxser_struct {
275 int port;
276 int base; /* port base address */
277 int irq; /* port using irq no. */
278 int vector; /* port irq vector */
279 int vectormask; /* port vector mask */
280 int rx_trigger; /* Rx fifo trigger level */
281 int baud_base; /* max. speed */
282 int flags; /* defined in tty.h */
283 int type; /* UART type */
284 struct tty_struct * tty;
285 int read_status_mask;
286 int ignore_status_mask;
287 int xmit_fifo_size;
288 int custom_divisor;
289 int x_char; /* xon/xoff character */
290 int close_delay;
291 unsigned short closing_wait;
292 int IER; /* Interrupt Enable Register */
293 int MCR; /* Modem control register */
294 unsigned long event;
295 int count; /* # of fd on device */
296 int blocked_open; /* # of blocked opens */
297 #if 0
298 long session; /* Session of opening process */
299 long pgrp; /* pgrp of opening process */
300 #endif
301 unsigned char *xmit_buf;
302 int xmit_head;
303 int xmit_tail;
304 int xmit_cnt;
305 struct work_struct tqueue;
306 struct termios normal_termios;
307 wait_queue_head_t open_wait;
308 wait_queue_head_t close_wait;
309 wait_queue_head_t delta_msr_wait;
310 struct async_icount icount; /* kernel counters for the 4 input interrupts */
311 int timeout;
312 int MaxCanSetBaudRate; // add by Victor Yu. 09-04-2002
313 int opmode_ioaddr; // add by Victor Yu. 01-05-2004
314 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
315 int speed;
316 #endif
319 struct mxser_log {
320 int tick;
321 int rxcnt[MXSER_PORTS];
322 int txcnt[MXSER_PORTS];
325 struct mxser_mstatus{
326 tcflag_t cflag;
327 int cts;
328 int dsr;
329 int ri;
330 int dcd;
333 static struct mxser_mstatus GMStatus[MXSER_PORTS];
335 static struct tty_driver mxvar_sdriver;
336 static struct mxser_struct mxvar_table[MXSER_PORTS];
337 static struct termios * mxvar_termios[MXSER_PORTS+1];
338 static struct termios * mxvar_termios_locked[MXSER_PORTS+1];
339 static struct mxser_log mxvar_log;
340 static int mxvar_diagflag;
342 * mxvar_tmp_buf is used as a temporary buffer by serial_write. We need
343 * to lock it in case the memcpy_fromfs blocks while swapping in a page,
344 * and some other program tries to do a serial write at the same time.
345 * Since the lock will only come under contention when the system is
346 * swapping and available memory is low, it makes sense to share one
347 * buffer across all the serial ports, since it significantly saves
348 * memory if large numbers of serial ports are open.
350 static unsigned char * mxvar_tmp_buf;
351 static struct semaphore mxvar_tmp_buf_sem;
354 * This is used to figure out the divisor speeds and the timeouts
356 #define B50_INDEX 1 // add by Victor Yu. 08-12-2004
357 static int mxvar_baud_table[] = {
358 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
359 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 0 };
360 #define BAUD_TABLE_NO (sizeof(mxvar_baud_table)/sizeof(int))
362 struct mxser_hwconf mxsercfg[MXSER_BOARDS];
365 * static functions:
367 #if 1 // add by Victor Yu. 02-21-2006
368 static int mxser_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); // add by Victor Yu. 07-27-2004
369 #endif
370 static void mxser_getcfg(int board,struct mxser_hwconf *hwconf);
371 int mxser_init(void);
372 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128) // add by Victor Yu. 05-22-2007
373 static int mxser_get_PCI_conf(int ,struct mxser_hwconf *);
374 #endif
375 static void mxser_do_softint(void *);
376 static int mxser_open(struct tty_struct *, struct file *);
377 static void mxser_close(struct tty_struct *, struct file *);
378 static int mxser_write(struct tty_struct *, int, const unsigned char *, int);
379 static int mxser_write_room(struct tty_struct *);
380 static void mxser_flush_buffer(struct tty_struct *);
381 static int mxser_chars_in_buffer(struct tty_struct *);
382 static void mxser_flush_chars(struct tty_struct *);
383 static void mxser_put_char(struct tty_struct *, unsigned char);
384 static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);
385 static int mxser_ioctl_special(unsigned int, unsigned long);
386 static void mxser_throttle(struct tty_struct *);
387 static void mxser_unthrottle(struct tty_struct *);
388 static void mxser_set_termios(struct tty_struct *, struct termios *);
389 static void mxser_stop(struct tty_struct *);
390 static void mxser_start(struct tty_struct *);
391 static void mxser_hangup(struct tty_struct *);
392 static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *);
393 static inline void mxser_receive_chars(struct mxser_struct *, int *);
394 static inline void mxser_transmit_chars(struct mxser_struct *);
395 static inline void mxser_check_modem_status(struct mxser_struct *, int);
396 static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
397 static int mxser_startup(struct mxser_struct *);
398 static void mxser_shutdown(struct mxser_struct *);
399 static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios);
400 static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct *);
401 static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);
402 static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *);
403 static void mxser_send_break(struct mxser_struct *, int);
404 #if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0)) // add by Victor Yu. 04-28-2006, for 2.6.x
405 static int mxser_get_modem_info(struct mxser_struct *, unsigned int *);
406 static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);
407 #endif
408 static void mxser_wait_until_sent(struct tty_struct *tty, int timeout);
410 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0)) // add by Victor Yu. 04-28-2006, for 2.6.x
411 static int mxser_tiocmget(struct tty_struct *tty, struct file *file);
412 static int mxser_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
413 #endif
415 // follwoing is modified by Victor Yu. 08-15-2002
417 // follow just for Moxa Must chip define.
419 // when LCR register (offset 0x03) write following value,
420 // the Must chip will enter enchance mode. And write value
421 // on EFR (offset 0x02) bit 6,7 to change bank.
422 #define MOXA_MUST_ENTER_ENCHANCE 0xBF
424 // when enhance mode enable, access on general bank register
425 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128) && !(defined CONFIG_ARCH_IA241_16128)
426 #define MOXA_MUST_GDL_REGISTER 28
427 #else
428 #define MOXA_MUST_GDL_REGISTER 7
429 #endif
431 #define MOXA_MUST_GDL_MASK 0x7F
432 #define MOXA_MUST_GDL_HAS_BAD_DATA 0x80
434 #define MOXA_MUST_LSR_RERR 0x80 // error in receive FIFO
435 // enchance register bank select and enchance mode setting register
436 // when LCR register equal to 0xBF
437 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128) && !(defined CONFIG_ARCH_IA241_16128)
438 #define MOXA_MUST_EFR_REGISTER 8
439 #else
440 #define MOXA_MUST_EFR_REGISTER 2
441 #endif
443 // enchance mode enable
444 #define MOXA_MUST_EFR_EFRB_ENABLE 0x10
445 // enchance reister bank set 0, 1, 2
446 #define MOXA_MUST_EFR_BANK0 0x00
447 #define MOXA_MUST_EFR_BANK1 0x40
448 #define MOXA_MUST_EFR_BANK2 0x80
449 #define MOXA_MUST_EFR_BANK3 0xC0
450 #define MOXA_MUST_EFR_BANK_MASK 0xC0
452 // set XON1 value register, when LCR=0xBF and change to bank0
453 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128) && !(defined CONFIG_ARCH_IA241_16128)
454 #define MOXA_MUST_XON1_REGISTER 16
455 #else
456 #define MOXA_MUST_XON1_REGISTER 4
457 #endif
459 // set XON2 value register, when LCR=0xBF and change to bank0
460 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128) && !(defined CONFIG_ARCH_IA241_16128)
461 #define MOXA_MUST_XON2_REGISTER 20
462 #else
463 #define MOXA_MUST_XON2_REGISTER 5
464 #endif
466 // set XOFF1 value register, when LCR=0xBF and change to bank0
467 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128) && !(defined CONFIG_ARCH_IA241_16128)
468 #define MOXA_MUST_XOFF1_REGISTER 24
469 #else
470 #define MOXA_MUST_XOFF1_REGISTER 6
471 #endif
473 // set XOFF2 value register, when LCR=0xBF and change to bank0
474 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128) && !(defined CONFIG_ARCH_IA241_16128)
475 #define MOXA_MUST_XOFF2_REGISTER 28
476 #define MOXA_MUST_RBRTL_REGISTER 16
477 #define MOXA_MUST_RBRTH_REGISTER 20
478 #define MOXA_MUST_RBRTI_REGISTER 24
479 #define MOXA_MUST_THRTL_REGISTER 28
480 #define MOXA_MUST_ENUM_REGISTER 16
481 #define MOXA_MUST_HWID_REGISTER 20
482 #define MOXA_MUST_ECR_REGISTER 24
483 #define MOXA_MUST_CSR_REGISTER 28
484 #else
485 #define MOXA_MUST_XOFF2_REGISTER 7
486 #define MOXA_MUST_RBRTL_REGISTER 4
487 #define MOXA_MUST_RBRTH_REGISTER 5
488 #define MOXA_MUST_RBRTI_REGISTER 6
489 #define MOXA_MUST_THRTL_REGISTER 7
490 #define MOXA_MUST_ENUM_REGISTER 4
491 #define MOXA_MUST_HWID_REGISTER 5
492 #define MOXA_MUST_ECR_REGISTER 6
493 #define MOXA_MUST_CSR_REGISTER 7
494 #endif
496 // good data mode enable
497 #define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20
498 // only good data put into RxFIFO
499 #define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10
501 // enable CTS interrupt
502 #define MOXA_MUST_IER_ECTSI 0x80
503 // eanble RTS interrupt
504 #define MOXA_MUST_IER_ERTSI 0x40
505 // enable Xon/Xoff interrupt
506 #define MOXA_MUST_IER_XINT 0x20
507 // enable GDA interrupt
508 #define MOXA_MUST_IER_EGDAI 0x10
510 #define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI)
512 // GDA interrupt pending
513 #define MOXA_MUST_IIR_GDA 0x1C
514 #define MOXA_MUST_IIR_RDA 0x04
515 #define MOXA_MUST_IIR_RTO 0x0C
516 #define MOXA_MUST_IIR_LSR 0x06
518 // recieved Xon/Xoff or specical interrupt pending
519 #define MOXA_MUST_IIR_XSC 0x10
521 // RTS/CTS change state interrupt pending
522 #define MOXA_MUST_IIR_RTSCTS 0x20
523 #define MOXA_MUST_IIR_MASK 0x3E
525 #define MOXA_MUST_MCR_XON_FLAG 0x40
526 #define MOXA_MUST_MCR_XON_ANY 0x80
527 #define MOXA_MUST_HARDWARE_ID 0x01
528 #define MOXA_MUST_HARDWARE_ID1 0x02
530 // software flow control on chip mask value
531 #define MOXA_MUST_EFR_SF_MASK 0x0F
532 // send Xon1/Xoff1
533 #define MOXA_MUST_EFR_SF_TX1 0x08
534 // send Xon2/Xoff2
535 #define MOXA_MUST_EFR_SF_TX2 0x04
536 // send Xon1,Xon2/Xoff1,Xoff2
537 #define MOXA_MUST_EFR_SF_TX12 0x0C
538 // don't send Xon/Xoff
539 #define MOXA_MUST_EFR_SF_TX_NO 0x00
540 // Tx software flow control mask
541 #define MOXA_MUST_EFR_SF_TX_MASK 0x0C
542 // don't receive Xon/Xoff
543 #define MOXA_MUST_EFR_SF_RX_NO 0x00
544 // receive Xon1/Xoff1
545 #define MOXA_MUST_EFR_SF_RX1 0x02
546 // receive Xon2/Xoff2
547 #define MOXA_MUST_EFR_SF_RX2 0x01
548 // receive Xon1,Xon2/Xoff1,Xoff2
549 #define MOXA_MUST_EFR_SF_RX12 0x03
550 // Rx software flow control mask
551 #define MOXA_MUST_EFR_SF_RX_MASK 0x03
553 #define MOXA_MUST_MIN_XOFFLIMIT 66
554 #define MOXA_MUST_MIN_XONLIMIT 20
556 #ifndef UCHAR
557 typedef unsigned char UCHAR;
558 #endif
560 #define CHECK_MOXA_MUST_XOFFLIMIT(info) { \
561 if ( (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) { \
562 (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT; \
563 (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT; \
567 #define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
568 UCHAR __oldlcr, __efr; \
569 __oldlcr = inb((baseio)+UART_LCR); \
570 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
571 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
572 __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \
573 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
574 outb(__oldlcr, (baseio)+UART_LCR); \
577 #define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
578 UCHAR __oldlcr, __efr; \
579 __oldlcr = inb((baseio)+UART_LCR); \
580 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
581 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
582 __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \
583 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
584 outb(__oldlcr, (baseio)+UART_LCR); \
587 #define SET_MOXA_MUST_XON1_VALUE(baseio, Value) { \
588 UCHAR __oldlcr, __efr; \
589 __oldlcr = inb((baseio)+UART_LCR); \
590 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
591 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
592 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
593 __efr |= MOXA_MUST_EFR_BANK0; \
594 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
595 outb((UCHAR)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \
596 outb(__oldlcr, (baseio)+UART_LCR); \
599 #define SET_MOXA_MUST_XON2_VALUE(baseio, Value) { \
600 UCHAR __oldlcr, __efr; \
601 __oldlcr = inb((baseio)+UART_LCR); \
602 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
603 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
604 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
605 __efr |= MOXA_MUST_EFR_BANK0; \
606 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
607 outb((UCHAR)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \
608 outb(__oldlcr, (baseio)+UART_LCR); \
611 #define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) { \
612 UCHAR __oldlcr, __efr; \
613 __oldlcr = inb((baseio)+UART_LCR); \
614 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
615 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
616 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
617 __efr |= MOXA_MUST_EFR_BANK0; \
618 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
619 outb((UCHAR)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \
620 outb(__oldlcr, (baseio)+UART_LCR); \
623 #define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) { \
624 UCHAR __oldlcr, __efr; \
625 __oldlcr = inb((baseio)+UART_LCR); \
626 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
627 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
628 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
629 __efr |= MOXA_MUST_EFR_BANK0; \
630 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
631 outb((UCHAR)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER); \
632 outb(__oldlcr, (baseio)+UART_LCR); \
635 #define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) { \
636 UCHAR __oldlcr, __efr; \
637 __oldlcr = inb((baseio)+UART_LCR); \
638 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
639 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
640 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
641 __efr |= MOXA_MUST_EFR_BANK1; \
642 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
643 outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER); \
644 outb(__oldlcr, (baseio)+UART_LCR); \
647 #define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) { \
648 UCHAR __oldlcr, __efr; \
649 __oldlcr = inb((baseio)+UART_LCR); \
650 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
651 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
652 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
653 __efr |= MOXA_MUST_EFR_BANK1; \
654 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
655 outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER); \
656 outb(__oldlcr, (baseio)+UART_LCR); \
659 #define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) { \
660 UCHAR __oldlcr, __efr; \
661 __oldlcr = inb((baseio)+UART_LCR); \
662 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
663 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
664 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
665 __efr |= MOXA_MUST_EFR_BANK1; \
666 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
667 outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER); \
668 outb(__oldlcr, (baseio)+UART_LCR); \
671 #define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) { \
672 UCHAR __oldlcr, __efr; \
673 __oldlcr = inb((baseio)+UART_LCR); \
674 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
675 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
676 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
677 __efr |= MOXA_MUST_EFR_BANK1; \
678 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
679 outb((UCHAR)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER); \
680 outb(__oldlcr, (baseio)+UART_LCR); \
683 #define MOXA_MUST_RBRL_VALUE 4
684 #define SET_MOXA_MUST_FIFO_VALUE(info) { \
685 UCHAR __oldlcr, __efr; \
686 __oldlcr = inb((info)->base+UART_LCR); \
687 outb(MOXA_MUST_ENTER_ENCHANCE, (info)->base+UART_LCR); \
688 __efr = inb((info)->base+MOXA_MUST_EFR_REGISTER); \
689 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
690 __efr |= MOXA_MUST_EFR_BANK1; \
691 outb(__efr, (info)->base+MOXA_MUST_EFR_REGISTER); \
692 outb((UCHAR)0, (info)->base+MOXA_MUST_THRTL_REGISTER); \
693 outb((UCHAR)((info)->rx_trigger), (info)->base+MOXA_MUST_RBRTH_REGISTER); \
694 if ( (info)->rx_trigger <= MOXA_MUST_RBRL_VALUE ) { \
695 outb((UCHAR)0, (info)->base+MOXA_MUST_RBRTI_REGISTER); \
696 outb((UCHAR)0, (info)->base+MOXA_MUST_RBRTL_REGISTER); \
697 } else { \
698 outb((UCHAR)((info)->rx_trigger-MOXA_MUST_RBRL_VALUE), \
699 (info)->base+MOXA_MUST_RBRTI_REGISTER); \
700 outb((UCHAR)((info)->rx_trigger-MOXA_MUST_RBRL_VALUE), \
701 (info)->base+MOXA_MUST_RBRTL_REGISTER); \
703 outb(__oldlcr, (info)->base+UART_LCR); \
706 #define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) { \
707 UCHAR __oldlcr, __efr; \
708 __oldlcr = inb((baseio)+UART_LCR); \
709 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
710 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
711 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
712 __efr |= MOXA_MUST_EFR_BANK2; \
713 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
714 outb((UCHAR)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \
715 outb(__oldlcr, (baseio)+UART_LCR); \
718 #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) { \
719 UCHAR __oldlcr, __efr; \
720 __oldlcr = inb((baseio)+UART_LCR); \
721 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
722 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
723 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
724 __efr |= MOXA_MUST_EFR_BANK2; \
725 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
726 *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \
727 outb(__oldlcr, (baseio)+UART_LCR); \
730 #define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) { \
731 UCHAR __oldlcr, __efr; \
732 __oldlcr = inb((baseio)+UART_LCR); \
733 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
734 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
735 __efr &= ~MOXA_MUST_EFR_SF_MASK; \
736 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
737 outb(__oldlcr, (baseio)+UART_LCR); \
740 #define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
741 UCHAR __oldlcr, __efr; \
742 __oldlcr = inb((baseio)+UART_LCR); \
743 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
744 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
745 __efr &= ~MOXA_MUST_EFR_SF_MASK; \
746 __efr |= MOXA_MUST_EFR_SF_TX1; \
747 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
748 outb(__oldlcr, (baseio)+UART_LCR); \
751 #define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
752 UCHAR __oldlcr, __efr; \
753 __oldlcr = inb((baseio)+UART_LCR); \
754 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
755 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
756 __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \
757 __efr |= MOXA_MUST_EFR_SF_TX1; \
758 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
759 outb(__oldlcr, (baseio)+UART_LCR); \
762 #define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
763 UCHAR __oldlcr, __efr; \
764 __oldlcr = inb((baseio)+UART_LCR); \
765 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
766 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
767 __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \
768 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
769 outb(__oldlcr, (baseio)+UART_LCR); \
772 #define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
773 UCHAR __oldlcr, __efr; \
774 __oldlcr = inb((baseio)+UART_LCR); \
775 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
776 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
777 __efr &= ~MOXA_MUST_EFR_SF_MASK; \
778 __efr |= MOXA_MUST_EFR_SF_RX1; \
779 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
780 outb(__oldlcr, (baseio)+UART_LCR); \
783 #define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
784 UCHAR __oldlcr, __efr; \
785 __oldlcr = inb((baseio)+UART_LCR); \
786 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
787 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
788 __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \
789 __efr |= MOXA_MUST_EFR_SF_RX1; \
790 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
791 outb(__oldlcr, (baseio)+UART_LCR); \
794 #define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
795 UCHAR __oldlcr, __efr; \
796 __oldlcr = inb((baseio)+UART_LCR); \
797 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
798 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
799 __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \
800 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
801 outb(__oldlcr, (baseio)+UART_LCR); \
804 #define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
805 UCHAR __oldlcr, __efr; \
806 __oldlcr = inb((baseio)+UART_LCR); \
807 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
808 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
809 __efr &= ~MOXA_MUST_EFR_SF_MASK; \
810 __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1); \
811 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
812 outb(__oldlcr, (baseio)+UART_LCR); \
815 #define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \
816 UCHAR __oldmcr; \
817 __oldmcr = inb((baseio)+UART_MCR); \
818 __oldmcr |= MOXA_MUST_MCR_XON_ANY; \
819 outb(__oldmcr, (baseio)+UART_MCR); \
822 #define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \
823 UCHAR __oldmcr; \
824 __oldmcr = inb((baseio)+UART_MCR); \
825 __oldmcr &= ~MOXA_MUST_MCR_XON_ANY; \
826 outb(__oldmcr, (baseio)+UART_MCR); \
829 #define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER)
831 #if 1 // add by Victor Yu. 02-21-2006
832 static int mxser_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
834 int len=0, board, port, p, i, j;
835 struct mxser_struct *info;
837 for ( board=0, port=0; board<MXSER_BOARDS; board++ ) {
838 if ( mxsercfg[board].board_type == -1 )
839 continue;
840 port += mxsercfg[board].ports;
842 #if 0
843 len = sprintf(page, "Ports: %d\n", port);
844 #else
845 len = sprintf(page, "%d\n", port);
846 #endif
847 if ( !port )
848 goto end_mxser_read_proc;
849 #if 0
850 len += sprintf(page+len, "PortNo InBytes OutBytes Speed Opened Interface DataBits Parity CTS DSR DCD RTS DTR\n");
851 #endif
852 for ( board=0, p=0; board<MXSER_BOARDS; board++ ) {
853 if ( mxsercfg[board].board_type == -1 )
854 continue;
855 for ( port=0, i=(board*MXSER_PORTS_PER_BOARD); port<mxsercfg[board].ports; port++, p++, i++ ) {
856 info = &mxvar_table[i];
858 // output PortNo InBytes OutBytes
859 #if 0
860 len += sprintf(page+len, "Port%d: %lu %lu", p, mxvar_log.rxcnt[i], mxvar_log.txcnt[i]);
861 #else
862 len += sprintf(page+len, "%lu %lu", mxvar_log.rxcnt[i], mxvar_log.txcnt[i]);
863 #endif
865 // output Speed Opened (1 - opened, 2 - not opened)
866 if ( info->count ) { // has opened
867 #if 0 // mask by Victor Yu. 02-21-2006
868 #ifndef B921600
869 #define B921600 (B460800 +1)
870 #endif
871 switch( info->tty->termios->c_cflag & (CBAUD | CBAUDEX) ){
872 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE
873 case B40000000 :
874 len += sprintf(page+len, " %d 1", info->speed);
875 goto read_proc_l1;
876 break;
877 #endif
878 case B921600 : j = 20; break;
879 case B460800 : j = 19; break;
880 case B230400 : j = 18; break;
881 case B115200 : j = 17; break;
882 case B57600 : j = 16; break;
883 case B38400 : j = 15; break;
884 case B19200 : j = 14; break;
885 case B9600 : j = 13; break;
886 case B4800 : j = 12; break;
887 case B2400 : j = 11; break;
888 case B1800 : j = 10; break;
889 case B1200 : j = 9; break;
890 case B600 : j = 8; break;
891 case B300 : j = 7; break;
892 case B200 : j = 6; break;
893 case B150 : j = 5; break;
894 case B134 : j = 4; break;
895 case B110 : j = 3; break;
896 case B75 : j = 2; break;
897 case B50 : j = 1; break;
898 default: j = 0; break;
901 if ( j == 15 ) {
902 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI )
903 j = 16; /* 57600 bps */
904 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI )
905 j = 17; /* 115200 bps */
906 #ifdef ASYNC_SPD_SHI
907 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
908 j = 18;
909 #endif
910 #ifdef ASYNC_SPD_WARP
911 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
912 j = 19;
913 #endif
915 len += sprintf(page+len, " %d 1", mxvar_baud_table[j]);
916 #else
917 len += sprintf(page+len, " %d 1", info->speed);
918 #endif
919 } else { // not opened
920 #if 0 // mask by Victor Yu. 02-21-2006
921 len += sprintf(page+len, " 9600 2");
922 #else
923 len += sprintf(page+len, " %d 2", info->speed);
924 #endif
927 // output interface (1-other, 2-rs232, 3-rs422, 4-rs423, 5-v35)
928 #if 0 // mask by Victor Yu. 02-21-2006
929 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE
930 read_proc_l1:
931 #endif
932 switch ( info->interface ) {
933 case RS232_MODE :
934 len += sprintf(page+len, " 2");
935 break;
936 case RS422_MODE :
937 len += sprintf(page+len, " 3");
938 break;
939 default :
940 len += sprintf(page+len, " 1");
941 break;
943 #else
945 int opmode;
946 int shiftbit;
947 //#if (defined CONFIG_ARCH_W311)
948 // shiftbit = ((info->port%4)+1) * 2;
949 // opmode = inl(info->opmode_ioaddr) >> shiftbit;
950 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128)
951 shiftbit = (info->port%4) * 2;
952 opmode = inb(info->opmode_ioaddr) >> shiftbit;
953 #else
954 shiftbit = ((info->port%4)+2) * 2;
955 opmode = inl(info->opmode_ioaddr) >> shiftbit;
956 #endif
957 opmode &= OP_MODE_MASK;
958 switch ( opmode ) {
959 case RS232_MODE :
960 len += sprintf(page+len, " 2");
961 break;
962 case RS422_MODE :
963 len += sprintf(page+len, " 3");
964 break;
965 default :
966 len += sprintf(page+len, " 1");
967 break;
970 #endif
972 // output data bits
973 if ( info->count ) { // has opened
974 switch ( info->tty->termios->c_cflag & CSIZE ) {
975 case CS5 :
976 len += sprintf(page+len, " 5");
977 break;
978 case CS6 :
979 len += sprintf(page+len, " 6");
980 break;
981 case CS7 :
982 len += sprintf(page+len, " 7");
983 break;
984 case CS8 :
985 default :
986 len += sprintf(page+len, " 8");
987 break;
989 } else { // not opened
990 len += sprintf(page+len, " 8");
993 // output stop bits (1-one, 2-two, 3-one-and-half, 4-dynamic)
994 if ( info->count ) { // has opened
995 if ( info->tty->termios->c_cflag & CSTOPB ) {
996 len += sprintf(page+len, " 2");
997 } else {
998 len += sprintf(page+len, " 1");
1000 } else {
1001 len += sprintf(page+len, " 1");
1004 // output parity (1-none, 2-odd, 3-even, 4-mark, 5-space)
1005 if ( info->count ) { // has opened
1006 if ( info->tty->termios->c_cflag & PARENB ) {
1007 if ( info->tty->termios->c_cflag & PARODD ) {
1008 len += sprintf(page+len, " 2");
1009 } else {
1010 len += sprintf(page+len, " 3");
1012 } else {
1013 len += sprintf(page+len, " 1");
1015 } else { // not opened
1016 len += sprintf(page+len, " 1");
1019 // output CTS DSR DCD status (1-none, 2-on, 3-off)
1020 j = inb(info->base+UART_MSR);
1021 if ( j & UART_MSR_CTS )
1022 len += sprintf(page+len, " 2");
1023 else
1024 len += sprintf(page+len, " 3");
1025 if ( j & UART_MSR_DSR )
1026 len += sprintf(page+len, " 2");
1027 else
1028 len += sprintf(page+len, " 3");
1029 if ( j & UART_MSR_DCD )
1030 len += sprintf(page+len, " 2");
1031 else
1032 len += sprintf(page+len, " 3");
1034 // output RTS DTR status (1-none, 2-on, 3-off)
1035 j = inb(info->base+UART_MCR);
1036 if ( j & UART_MCR_RTS )
1037 len += sprintf(page+len, " 2");
1038 else
1039 len += sprintf(page+len, " 3");
1040 if ( j & UART_MCR_DTR )
1041 len += sprintf(page+len, " 2");
1042 else
1043 len += sprintf(page+len, " 3");
1045 // end output
1046 len += sprintf(page+len, "\n");
1050 end_mxser_read_proc:
1051 if ( len <= (off + count) )
1052 *eof = 1;
1053 *start = page + off;
1054 len -= off;
1055 if ( len > count )
1056 len = count;
1057 if ( len < 0 )
1058 len = 0;
1060 return len;
1062 #endif
1065 * The MOXA Smartio/Industio serial driver boot-time initialization code!
1067 static int __init mxser_init_module(void)
1069 int ret;
1071 if (verbose)
1072 printk("Loading module mxser ...\n");
1073 ret = mxser_init();
1074 if (verbose)
1075 printk("Done.\n");
1076 return (ret);
1079 static void __exit mxser_exit_module(void)
1081 int i,err = 0;
1084 if (verbose)
1085 printk("Unloading module mxser ...\n");
1086 #if 1 // mask by Victor Yu. 11-22-2005
1087 if ((err |= tty_unregister_driver(&mxvar_sdriver)))
1088 printk("Couldn't unregister MOXA Smartio/Industio family serial driver\n");
1089 #else // add by Victor Yu. 11-22-2005
1090 put_tty_driver(&mxvar_sdriver);
1091 #endif // 11-22-2005
1093 for(i=0; i<MXSER_BOARDS; i++){
1094 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128) // add by Victor Yu. 05-22-2007
1095 struct pci_dev *pdev;
1096 #endif
1097 if(mxsercfg[i].board_type == -1)
1098 continue;
1099 else{
1100 free_irq(mxsercfg[i].irq, &mxvar_table[i*MXSER_PORTS_PER_BOARD]);
1101 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128) // add by Victor Yu. 05-22-2007
1102 pdev = mxsercfg[i].pciInfo.pdev;
1103 release_region(pci_resource_start(pdev, 2),
1104 pci_resource_len(pdev, 2));
1105 release_region(pci_resource_start(pdev, 3),
1106 pci_resource_len(pdev, 3));
1107 #endif // 11-22-2005
1111 #if 1 // add by Victor Yu. 02-21-2006
1112 remove_proc_entry(MXSER_PROC_NODE, NULL); // add by Victor Yu. 07-27-2004
1113 #endif
1115 if (verbose)
1116 printk("Done.\n");
1119 module_init(mxser_init_module);
1120 module_exit(mxser_exit_module);
1122 int mxser_initbrd(int board,struct mxser_hwconf *hwconf)
1124 struct mxser_struct * info;
1125 unsigned long flags;
1126 int retval;
1127 int i,n;
1129 init_MUTEX(&mxvar_tmp_buf_sem);
1130 n = board*MXSER_PORTS_PER_BOARD;
1131 info = &mxvar_table[n];
1132 for ( i=0; i<hwconf->ports; i++, n++, info++ ) {
1133 if (verbose) {
1134 printk(" ttyM%d/cum%d at 0x%04x ", n, n, hwconf->ioaddr[i]);
1135 if ( hwconf->baud_base[i] == 115200 )
1136 printk(" max. baud rate up to 115200 bps.\n");
1137 else
1138 printk(" max. baud rate up to 921600 bps.\n");
1140 info->port = n;
1141 info->base = hwconf->ioaddr[i];
1142 info->irq = hwconf->irq;
1143 info->vector = hwconf->vector;
1144 info->vectormask = hwconf->vector_mask;
1145 info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; // add by Victor Yu. 01-05-2004
1147 // following add by Victor Yu. 08-30-2002
1148 // Moxa Must UART support FIFO is 64bytes for Tx/Rx
1149 // but receive FIFO just can set up to 62 will be OK.
1150 info->rx_trigger = 120;
1151 info->baud_base = hwconf->baud_base[i];
1152 info->flags = ASYNC_SHARE_IRQ;
1153 info->type = hwconf->uart_type;
1155 // following add by Victor Yu. 08-30-2002
1156 info->xmit_fifo_size = 128;
1157 ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base);
1158 info->MaxCanSetBaudRate = hwconf->MaxCanSetBaudRate[i];
1159 // above add by Victor Yu. 08-30-2002
1161 info->custom_divisor = hwconf->baud_base[i] * 16;
1162 info->close_delay = 5*HZ/10;
1163 info->closing_wait = 30*HZ;
1164 INIT_WORK(&info->tqueue, mxser_do_softint, info);
1165 info->normal_termios = mxvar_sdriver.init_termios;
1166 init_waitqueue_head(&info->open_wait);
1167 init_waitqueue_head(&info->close_wait);
1168 init_waitqueue_head(&info->delta_msr_wait);
1169 info->icount.rx = info->icount.tx = 0;
1170 info->icount.cts = info->icount.dsr =
1171 info->icount.dsr = info->icount.dcd = 0;
1172 info->icount.frame = info->icount.overrun =
1173 info->icount.brk = info->icount.parity = 0;
1174 info->icount.buf_overrun = 0;
1175 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add b Victor Yu. 08-12-2004
1176 info->speed = 38400;
1177 #endif
1180 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128) // add by Victor Yu. 05-22-2007
1181 request_region(hwconf->ioaddr[0],8*hwconf->ports,"mxser(io)");
1182 if ((hwconf->pciInfo.busNum == 0)&&(hwconf->pciInfo.devNum == 0))
1183 request_region(hwconf->vector,1,"mxser(vector)");
1184 else
1185 request_region(hwconf->vector,16,"mxser(vector)");
1186 #endif
1189 * Allocate the IRQ if necessary
1191 save_flags(flags);
1193 n = board*MXSER_PORTS_PER_BOARD;
1194 info = &mxvar_table[n];
1196 cli();
1197 retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info),
1198 "mxser", info);
1199 if ( retval ) {
1200 restore_flags(flags);
1201 printk("Board %d: %s", board, mxser_brdname[hwconf->board_type-1]);
1202 printk(" Request irq fail,IRQ (%d) may be conflit with another device.\n",info->irq);
1203 return(retval);
1205 restore_flags(flags);
1207 return 0;
1210 static void mxser_getcfg(int board,struct mxser_hwconf *hwconf)
1212 mxsercfg[board] = *hwconf;
1215 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128) // add by Victor Yu. 05-22-2007
1216 static int mxser_get_PCI_conf(int board_type,struct mxser_hwconf *hwconf)
1218 int i;
1219 unsigned int ioaddress;
1220 struct pci_dev *pdev=hwconf->pciInfo.pdev;
1222 hwconf->board_type = board_type;
1223 hwconf->ports = mxser_numports[board_type-1];
1224 ioaddress = pci_resource_start(pdev, 2);
1225 request_region(pci_resource_start(pdev, 2),
1226 pci_resource_len(pdev, 2),
1227 "mxser(IO)");
1228 for (i = 0; i < hwconf->ports; i++) {
1229 hwconf->ioaddr[i] = ioaddress + 8*i;
1231 // disable the interrupt
1232 outb(0, hwconf->ioaddr[i]+1);
1233 // flush FIFO
1234 outb(0x06, hwconf->ioaddr[i]+2);
1235 // flush interrupt
1236 inb(hwconf->ioaddr[i]+2);
1237 inb(hwconf->ioaddr[i]+6);
1238 inb(hwconf->ioaddr[i]+5);
1239 inb(hwconf->ioaddr[i]);
1240 hwconf->MaxCanSetBaudRate[i] = 921600;
1243 #if 1 // add by Victor Yu. 05-25-2006
1245 unsigned int _addr;
1246 for ( ; i<MXSER_PORTS_PER_BOARD; i++ ) {
1247 _addr = ioaddress + 8 * i;
1248 outb(0, _addr+1);
1249 outb(0x06, _addr+2);
1250 inb(_addr+2);
1251 inb(_addr+6);
1252 inb(_addr+5);
1255 #endif
1256 ioaddress = pci_resource_start(pdev, 3);
1257 request_region(pci_resource_start(pdev, 3),
1258 pci_resource_len(pdev, 3),
1259 "mxser(vector)");
1260 hwconf->vector = ioaddress;
1262 // following add by Victor Yu. 01-05-2004
1263 for (i = 0; i < hwconf->ports; i++) {
1264 if ( i < 4 )
1265 hwconf->opmode_ioaddr[i] = ioaddress + 4;
1266 else
1267 hwconf->opmode_ioaddr[i] = ioaddress + 0x0c;
1269 outb(0, ioaddress+4); // default set to RS232 mode
1270 outb(0, ioaddress+0x0c); //default set to RS232 mode
1271 // above add by Victor Yu. 01-05-2004
1273 hwconf->irq = hwconf->pciInfo.pdev->irq;
1275 hwconf->uart_type = PORT_16550A;
1276 hwconf->vector_mask = 0;
1277 for (i = 0; i < hwconf->ports; i++) {
1278 hwconf->vector_mask |= (1<<i);
1279 hwconf->baud_base[i] = 921600;
1281 return(0);
1283 #endif
1285 #if !defined(CONFIG_ARCH_IA241) && !defined(CONFIG_ARCH_IA241_32128) && !defined(CONFIG_ARCH_IA241_16128)
1286 static void ia240_hw_set(struct mxser_hwconf *hwconf)
1288 int i;
1290 hwconf->board_type = IA240_BOARD;
1291 hwconf->ports = mxser_numports[IA240_BOARD-1];
1292 hwconf->irq = IRQ_UART;
1293 hwconf->vector = CPE_UART_INT_VEC_VA_BASE;
1294 //#if defined(CONFIG_ARCH_W311)
1295 // hwconf->vector_mask = 0x02;
1296 #if defined(CONFIG_ARCH_W315)
1297 hwconf->vector_mask = 0x04;
1298 #elif defined(CONFIG_ARCH_IA240) || defined(CONFIG_ARCH_W341) || defined(CONFIG_ARCH_W345) || defined(CONFIG_ARCH_W345_IMP1)
1299 hwconf->vector_mask = 0x3c;
1300 #else
1301 hwconf->vector_mask = 0x0c;
1302 #endif
1303 hwconf->uart_type = PORT_16550A;
1304 for ( i=0; i<hwconf->ports; i++ ) {
1305 //#if (defined CONFIG_ARCH_W311)
1306 // hwconf->ioaddr[i] = CPE_UART2_VA_BASE + i * 32;
1307 //#else
1308 hwconf->ioaddr[i] = CPE_UART3_VA_BASE + i * 32;
1309 //#endif
1310 hwconf->baud_base[i] = 921600;
1311 hwconf->MaxCanSetBaudRate[i] = 921600;
1312 hwconf->opmode_ioaddr[i] = CPE_UART_MODE_VA_BASE;
1315 #endif
1317 int mxser_init(void)
1319 int i, m;
1320 int ret1, ret2;
1321 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128) // add by Victor Yu. 05-22-2007
1322 struct pci_dev *pdev=NULL;
1323 int n, index, retval, b;
1324 #endif
1325 struct mxser_hwconf hwconf;
1327 printk("MOXA MU860 UART Device Driver version %s\n",MXSER_VERSION);
1329 /* Initialize the tty_driver structure */
1330 memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));
1331 mxvar_sdriver.magic = TTY_DRIVER_MAGIC;
1332 mxvar_sdriver.name = "ttyM";
1333 mxvar_sdriver.major = ttymajor;
1334 mxvar_sdriver.minor_start = 0;
1335 mxvar_sdriver.num = MXSER_PORTS + 1;
1336 mxvar_sdriver.type = TTY_DRIVER_TYPE_SERIAL;
1337 mxvar_sdriver.subtype = SERIAL_TYPE_NORMAL;
1338 mxvar_sdriver.init_termios = tty_std_termios;
1339 mxvar_sdriver.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
1340 mxvar_sdriver.flags = TTY_DRIVER_REAL_RAW;
1341 mxvar_sdriver.refcount = 0;
1342 mxvar_sdriver.termios = mxvar_termios;
1343 mxvar_sdriver.termios_locked = mxvar_termios_locked;
1345 mxvar_sdriver.open = mxser_open;
1346 mxvar_sdriver.close = mxser_close;
1347 mxvar_sdriver.write = mxser_write;
1348 mxvar_sdriver.put_char = mxser_put_char;
1349 mxvar_sdriver.flush_chars = mxser_flush_chars;
1350 mxvar_sdriver.write_room = mxser_write_room;
1351 mxvar_sdriver.chars_in_buffer = mxser_chars_in_buffer;
1352 mxvar_sdriver.flush_buffer = mxser_flush_buffer;
1353 mxvar_sdriver.ioctl = mxser_ioctl;
1354 mxvar_sdriver.throttle = mxser_throttle;
1355 mxvar_sdriver.unthrottle = mxser_unthrottle;
1356 mxvar_sdriver.set_termios = mxser_set_termios;
1357 mxvar_sdriver.stop = mxser_stop;
1358 mxvar_sdriver.start = mxser_start;
1359 mxvar_sdriver.hangup = mxser_hangup;
1360 mxvar_sdriver.wait_until_sent = mxser_wait_until_sent;
1361 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0)) // add by Victor Yu. 04-28-2006, for 2.6.x
1362 mxvar_sdriver.tiocmget = mxser_tiocmget;
1363 mxvar_sdriver.tiocmset = mxser_tiocmset;
1364 #endif
1366 printk("Tty devices major number = %d\n",ttymajor);
1368 mxvar_diagflag = 0;
1369 memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct));
1370 memset(&mxvar_log, 0, sizeof(struct mxser_log));
1372 m = 0;
1373 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128) && !(defined CONFIG_ARCH_IA241_16128)
1374 ia240_hw_set(&hwconf);
1375 if ( mxser_initbrd(m,&hwconf) < 0 )
1376 return -1;
1377 mxser_getcfg(m,&hwconf);
1378 m++;
1379 #else
1381 n = sizeof (mxser_pcibrds)/sizeof (mxser_pciinfo);
1382 index = 0;
1383 b = 0;
1384 while (b < n) {
1385 pdev = pci_find_device(mxser_pcibrds[b].vendor_id,
1386 mxser_pcibrds[b].device_id,
1387 pdev);
1388 if ( pdev == NULL ) {
1389 b++;
1390 continue;
1392 hwconf.pciInfo.busNum = pdev->bus->number;
1393 hwconf.pciInfo.devNum = pdev->devfn;
1394 hwconf.pciInfo.pdev = pdev;
1395 printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",mxser_brdname[mxser_pcibrds[b].board_type-1],pdev->bus->number,pdev->devfn >> 3);
1396 if ( m >= MXSER_BOARDS) {
1397 printk("Too many Smartio/Industio family boards find (maximum %d),board not configured\n",MXSER_BOARDS);
1399 else {
1400 if ( pci_enable_device(pdev) ) {
1401 printk("Moxa SmartI/O PCI enable fail !\n");
1402 continue;
1404 retval = mxser_get_PCI_conf(mxser_pcibrds[b].board_type,&hwconf);
1405 if (retval < 0) {
1406 if (retval == MXSER_ERR_IRQ)
1407 printk("Invalid interrupt number,board not configured\n");
1408 else if (retval == MXSER_ERR_IRQ_CONFLIT)
1409 printk("Invalid interrupt number,board not configured\n");
1410 else if (retval == MXSER_ERR_VECTOR)
1411 printk("Invalid interrupt vector,board not configured\n");
1412 else if (retval == MXSER_ERR_IOADDR)
1413 printk("Invalid I/O address,board not configured\n");
1414 continue;
1418 if(mxser_initbrd(m,&hwconf)<0)
1419 continue;
1420 mxser_getcfg(m,&hwconf);
1421 m++;
1425 #endif
1427 for(i=m; i<MXSER_BOARDS; i++){
1428 mxsercfg[i].board_type = -1;
1432 ret1 = 0;
1433 ret2 = 0;
1434 if ( !(ret1=tty_register_driver(&mxvar_sdriver)) ){
1435 #if 1 // add by Victor Yu. 02-21-2006
1436 create_proc_read_entry(MXSER_PROC_NODE, 0, 0, mxser_read_proc, NULL); // add by Victor Yu. 07-27-2004
1437 #endif
1438 return 0;
1439 }else
1440 printk("Couldn't install MOXA Smartio/Industio family driver !\n");
1443 if(ret1 || ret2){
1444 for(i=0; i<MXSER_BOARDS; i++){
1445 if(mxsercfg[i].board_type == -1)
1446 continue;
1447 else{
1448 free_irq(mxsercfg[i].irq, &mxvar_table[i*MXSER_PORTS_PER_BOARD]);
1451 return -1;
1454 return(0);
1457 static void mxser_do_softint(void *private_)
1459 struct mxser_struct * info = (struct mxser_struct *)private_;
1460 struct tty_struct * tty;
1462 tty = info->tty;
1464 if (tty) {
1465 if ( test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event) ) {
1466 if ( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1467 tty->ldisc.write_wakeup )
1468 (tty->ldisc.write_wakeup)(tty);
1469 wake_up_interruptible(&tty->write_wait);
1471 if ( test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event) ) {
1472 tty_hangup(tty);
1475 MOD_DEC_USE_COUNT;
1478 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,6,0)) // add by Victor Yu. 04-28-2006, for 2.6.x
1479 static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
1481 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
1482 unsigned char control, status;
1483 int result;
1484 unsigned long flags;
1486 save_flags(flags);
1487 cli();
1488 control = info->MCR;
1489 status = inb(info->base + UART_MSR);
1490 restore_flags(flags);
1491 result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
1492 ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
1493 ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
1494 ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
1495 ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
1496 ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
1497 return(result);
1500 static int mxser_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear)
1502 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
1503 unsigned long flags;
1505 save_flags(flags);
1506 cli();
1507 if ( set & TIOCM_RTS )
1508 info->MCR |= UART_MCR_RTS;
1509 if ( set & TIOCM_DTR )
1510 info->MCR |= UART_MCR_DTR;
1511 if ( clear & TIOCM_RTS )
1512 info->MCR &= ~UART_MCR_RTS;
1513 if ( clear & TIOCM_DTR )
1514 info->MCR &= ~UART_MCR_DTR;
1515 outb(info->MCR, info->base + UART_MCR);
1516 restore_flags(flags);
1517 return(0);
1519 #endif
1521 * This routine is called whenever a serial port is opened. It
1522 * enables interrupts for a serial port, linking in its async structure into
1523 * the IRQ chain. It also performs the serial-specific
1524 * initialization for the tty structure.
1526 static int mxser_open(struct tty_struct * tty, struct file * filp)
1528 struct mxser_struct * info;
1529 int retval, line;
1530 unsigned long page;
1531 #if 1 // add by Victor Yu. 12-28-2004
1532 unsigned long flags;
1533 #endif
1535 line = PORTNO(tty);
1536 if ( line == MXSER_PORTS )
1537 return(0);
1538 if ( (line < 0) || (line > MXSER_PORTS) )
1539 return(-ENODEV);
1541 info = mxvar_table + line;
1542 if ( !info->base )
1543 return(-ENODEV);
1545 tty->driver_data = info;
1546 save_flags(flags);
1547 cli();
1548 info->tty = tty;
1549 restore_flags(flags);
1551 if ( !mxvar_tmp_buf ) {
1552 page = get_zeroed_page(GFP_KERNEL);
1553 if ( !page )
1554 return(-ENOMEM);
1555 if ( mxvar_tmp_buf )
1556 free_page(page);
1557 else
1558 mxvar_tmp_buf = (unsigned char *)page;
1562 * Start up serial port
1564 retval = mxser_startup(info);
1565 if ( retval )
1566 return(retval);
1568 retval = mxser_block_til_ready(tty, filp, info);
1569 if ( retval )
1570 return(retval);
1572 #if 0 // mask by Victor Yu. 12-28-2004
1573 info->count++;
1574 #else // add by Victor Yu. 12-28-2004
1575 save_flags(flags);
1576 cli();
1577 info->count++;
1578 restore_flags(flags);
1579 #endif
1580 MOD_INC_USE_COUNT;
1582 if ( (info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS) ) {
1583 *tty->termios = info->normal_termios;
1584 mxser_change_speed(info, 0);
1587 save_flags(flags);
1588 cli();
1589 clear_bit(TTY_DONT_FLIP, &tty->flags);
1590 restore_flags(flags);
1592 /* unmark here for very high baud rate (ex. 921600 bps) used
1594 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
1595 tty->low_latency = 1;
1596 #endif
1597 return(0);
1601 * This routine is called when the serial port gets closed. First, we
1602 * wait for the last remaining data to be sent. Then, we unlink its
1603 * async structure from the interrupt chain if necessary, and we free
1604 * that IRQ if nothing is left in the chain.
1606 static void mxser_close(struct tty_struct * tty, struct file * filp)
1608 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
1609 unsigned long flags;
1610 unsigned long timeout;
1612 if ( PORTNO(tty) == MXSER_PORTS )
1613 return;
1614 if ( !info )
1615 return;
1617 if ( tty_hung_up_p(filp) ) {
1618 MOD_DEC_USE_COUNT;
1619 return;
1622 #if 1 // add by Victor Yu. 12-28-2004
1623 save_flags(flags);
1624 cli();
1625 #endif
1626 if ( (tty->count == 1) && (info->count != 1) ) {
1628 * Uh, oh. tty->count is 1, which means that the tty
1629 * structure will be freed. Info->count should always
1630 * be one in these conditions. If it's greater than
1631 * one, we've got real problems, since it means the
1632 * serial port won't be shutdown.
1634 printk("mxser_close: bad serial port count; tty->count is 1, "
1635 "info->count is %d\n", info->count);
1636 info->count = 1;
1638 if ( --info->count < 0 ) {
1639 printk("mxser_close: bad serial port count for ttys%d: %d\n",
1640 info->port, info->count);
1641 info->count = 0;
1643 if ( info->count ) {
1644 restore_flags(flags);
1645 MOD_DEC_USE_COUNT;
1646 return;
1648 info->flags |= ASYNC_CLOSING;
1649 restore_flags(flags); // add by Victor Yu. 09-26-2002
1652 * Save the termios structure, since this port may have
1653 * separate termios for callout and dialin.
1655 if ( info->flags & ASYNC_NORMAL_ACTIVE )
1656 info->normal_termios = *tty->termios;
1658 * Now we wait for the transmit buffer to clear; and we notify
1659 * the line discipline to only process XON/XOFF characters.
1661 tty->closing = 1;
1662 if ( info->closing_wait != ASYNC_CLOSING_WAIT_NONE ) {
1663 tty_wait_until_sent(tty, info->closing_wait);
1666 * At this point we stop accepting input. To do this, we
1667 * disable the receive line status interrupts, and tell the
1668 * interrupt driver to stop checking the data ready bit in the
1669 * line status register.
1671 info->IER &= ~(UART_IER_RLSI|MOXA_MUST_RECV_ISR);
1672 if ( info->flags & ASYNC_INITIALIZED ) {
1673 outb(info->IER, info->base + UART_IER);
1675 * Before we drop DTR, make sure the UART transmitter
1676 * has completely drained; this is especially
1677 * important if there is a transmit FIFO!
1679 timeout = jiffies + HZ;
1680 while ( !(inb(info->base + UART_LSR) & UART_LSR_TEMT) ) {
1681 current->state = TASK_INTERRUPTIBLE;
1682 schedule_timeout(5);
1683 if ( time_after(jiffies, timeout) )
1684 break;
1687 mxser_shutdown(info);
1689 if ( tty->driver->flush_buffer )
1690 tty->driver->flush_buffer(tty);
1691 if ( tty->ldisc.flush_buffer )
1692 tty->ldisc.flush_buffer(tty);
1693 tty->closing = 0;
1694 info->event = 0;
1695 info->tty = 0;
1696 if ( info->blocked_open ) {
1697 if ( info->close_delay ) {
1698 current->state = TASK_INTERRUPTIBLE;
1699 schedule_timeout(info->close_delay);
1701 wake_up_interruptible(&info->open_wait);
1704 info->flags &= ~(ASYNC_NORMAL_ACTIVE |
1705 ASYNC_CLOSING);
1706 wake_up_interruptible(&info->close_wait);
1708 MOD_DEC_USE_COUNT;
1711 static int mxser_write(struct tty_struct * tty, int from_user,
1712 const unsigned char * buf, int count)
1714 int c, total = 0;
1715 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1716 unsigned long flags;
1718 if ( !tty || !info->xmit_buf || !mxvar_tmp_buf )
1719 return(0);
1721 #if 0 // mask by Victor Yu. 10-13-2004
1722 if ( from_user )
1723 down(&mxvar_tmp_buf_sem);
1724 #endif
1725 save_flags(flags);
1726 cli();
1727 while ( 1 ) {
1728 // cli();
1729 c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1730 SERIAL_XMIT_SIZE - info->xmit_head));
1731 if ( c <= 0 )
1732 break;
1734 if ( from_user ) {
1736 copy_from_user(mxvar_tmp_buf, buf, c);
1737 c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1738 SERIAL_XMIT_SIZE - info->xmit_head));
1739 memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
1741 copy_from_user(info->xmit_buf+info->xmit_head, buf, c);
1742 } else
1743 memcpy(info->xmit_buf + info->xmit_head, buf, c);
1744 info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
1745 info->xmit_cnt += c;
1746 // restore_flags(flags);
1747 buf += c;
1748 count -= c;
1749 total += c;
1751 #if 0 // mask by Victor Yu. 10-13-2004
1752 if ( from_user )
1753 up(&mxvar_tmp_buf_sem);
1754 #endif
1755 if ( info->xmit_cnt && !tty->stopped &&
1756 !(info->IER & UART_IER_THRI) ) {
1757 if (!tty->hw_stopped||(info->type == PORT_16550A)) {
1758 info->IER |= UART_IER_THRI;
1759 outb(info->IER, info->base + UART_IER);
1762 restore_flags(flags);
1763 return(total);
1766 static void mxser_put_char(struct tty_struct * tty, unsigned char ch)
1768 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1769 unsigned long flags;
1771 if ( !tty || !info->xmit_buf )
1772 return;
1774 save_flags(flags);
1775 cli();
1776 if ( info->xmit_cnt >= SERIAL_XMIT_SIZE - 1 ) {
1777 restore_flags(flags);
1778 return;
1781 info->xmit_buf[info->xmit_head++] = ch;
1782 info->xmit_head &= SERIAL_XMIT_SIZE - 1;
1783 info->xmit_cnt++;
1784 if ( !tty->stopped && !(info->IER & UART_IER_THRI) ) {
1785 if (!tty->hw_stopped||(info->type == PORT_16550A)) {
1786 info->IER |= UART_IER_THRI;
1787 outb(info->IER, info->base + UART_IER);
1790 restore_flags(flags);
1793 static void mxser_flush_chars(struct tty_struct * tty)
1795 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1796 unsigned long flags;
1798 if ( info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf ||
1799 (tty->hw_stopped && info->type!=PORT_16550A))
1800 return;
1802 save_flags(flags);
1803 cli();
1804 info->IER |= UART_IER_THRI;
1805 outb(info->IER, info->base + UART_IER);
1806 restore_flags(flags);
1809 static int mxser_write_room(struct tty_struct * tty)
1811 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1812 int ret;
1814 ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
1815 if ( ret < 0 )
1816 ret = 0;
1817 return(ret);
1820 static int mxser_chars_in_buffer(struct tty_struct * tty)
1822 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1824 return(info->xmit_cnt);
1827 static void mxser_flush_buffer(struct tty_struct * tty)
1829 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1830 unsigned long flags;
1832 save_flags(flags);
1833 cli();
1834 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1835 restore_flags(flags);
1836 wake_up_interruptible(&tty->write_wait);
1837 if ( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1838 tty->ldisc.write_wakeup )
1839 (tty->ldisc.write_wakeup)(tty);
1842 static int mxser_ioctl(struct tty_struct * tty, struct file * file,
1843 unsigned int cmd, unsigned long arg)
1845 int error;
1846 unsigned long flags;
1847 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
1848 int retval;
1849 struct async_icount cprev, cnow; /* kernel counter temps */
1850 struct serial_icounter_struct *p_cuser; /* user space */
1851 unsigned long templ;
1852 if ( PORTNO(tty) == MXSER_PORTS )
1853 return(mxser_ioctl_special(cmd, arg));
1855 // following add by Victor Yu. 01-05-2004
1856 if ( cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE ) {
1857 int opmode, p;
1858 int shiftbit;
1859 unsigned int val;
1861 p = info->port % 4;
1862 if ( cmd == MOXA_SET_OP_MODE ) {
1863 error = verify_area(VERIFY_READ, (void *)arg, sizeof(int));
1864 if ( error )
1865 return(error);
1866 get_from_user(opmode,(int *)arg);
1867 if ( opmode != RS232_MODE && opmode != RS485_2WIRE_MODE && opmode != RS422_MODE && opmode != RS485_4WIRE_MODE )
1868 return -EFAULT;
1869 //#if (defined CONFIG_ARCH_W311)
1870 // shiftbit = (p+1) * 2;
1871 // val = inl(info->opmode_ioaddr);
1872 #if (defined CONFIG_ARCH_IA241) || (defined CONFIG_ARCH_IA241_32128)|| (defined CONFIG_ARCH_IA241_16128)
1873 shiftbit = p * 2;
1874 val = inb(info->opmode_ioaddr);
1875 #else
1876 shiftbit = (p+2) * 2;
1877 val = inl(info->opmode_ioaddr);
1878 #endif
1879 val &= (~(3 << shiftbit));
1880 val |= (opmode << shiftbit);
1881 #if !(defined CONFIG_ARCH_IA241) && !(defined CONFIG_ARCH_IA241_32128)&& !(defined CONFIG_ARCH_IA241_16128)
1882 outl(val, info->opmode_ioaddr);
1883 #else
1884 outb(val, info->opmode_ioaddr);
1885 #endif
1886 } else {
1887 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1888 if ( error )
1889 return(error);
1890 //#if (defined CONFIG_ARCH_W311)
1891 // shiftbit = (p+1) * 2;
1892 // opmode = inl(info->opmode_ioaddr) >> shiftbit;
1893 #if (defined CONFIG_ARCH_IA241) || (defined CONFIG_ARCH_IA241_32128)|| (defined CONFIG_ARCH_IA241_16128)
1894 shiftbit = p * 2;
1895 opmode = inb(info->opmode_ioaddr) >> shiftbit;
1896 #else
1897 shiftbit = (p+2) * 2;
1898 opmode = inl(info->opmode_ioaddr) >> shiftbit;
1899 #endif
1900 opmode &= OP_MODE_MASK;
1901 copy_to_user((int*)arg, &opmode, sizeof(int));
1903 return 0;
1905 // above add by Victor Yu. 01-05-2004
1907 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
1908 if ( cmd == MOXA_SET_SPECIAL_BAUD_RATE || cmd == MOXA_GET_SPECIAL_BAUD_RATE ||
1909 cmd == UC_SET_SPECIAL_BAUD_RATE || cmd == UC_GET_SPECIAL_BAUD_RATE ) {
1910 int speed, i;
1911 if ( cmd == MOXA_SET_SPECIAL_BAUD_RATE ||
1912 cmd == UC_SET_SPECIAL_BAUD_RATE ) {
1913 error = verify_area(VERIFY_READ, (void *)arg, sizeof(int));
1914 if ( error )
1915 return(error);
1916 get_from_user(speed,(int *)arg);
1917 if ( speed <= 0 || speed > info->MaxCanSetBaudRate )
1918 return -EFAULT;
1919 if ( !info->tty || !info->tty->termios || !info->base )
1920 return 0;
1921 info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX);
1922 for ( i=0; i<BAUD_TABLE_NO && speed != mxvar_baud_table[i]; i++ );
1923 if ( i == BAUD_TABLE_NO ) {
1924 info->tty->termios->c_cflag |= B4000000;
1925 } else {
1926 switch ( mxvar_baud_table[i] ) {
1927 case 921600 : info->tty->termios->c_cflag |= B921600; break;
1928 case 460800 : info->tty->termios->c_cflag |= B460800; break;
1929 case 230400 : info->tty->termios->c_cflag |= B230400; break;
1930 case 115200 : info->tty->termios->c_cflag |= B115200; break;
1931 case 57600 : info->tty->termios->c_cflag |= B57600; break;
1932 case 38400 : info->tty->termios->c_cflag |= B38400; break;
1933 case 19200 : info->tty->termios->c_cflag |= B19200; break;
1934 case 9600 : info->tty->termios->c_cflag |= B9600; break;
1935 case 4800 : info->tty->termios->c_cflag |= B4800; break;
1936 case 2400 : info->tty->termios->c_cflag |= B2400; break;
1937 case 1800 : info->tty->termios->c_cflag |= B1800; break;
1938 case 1200 : info->tty->termios->c_cflag |= B1200; break;
1939 case 600 : info->tty->termios->c_cflag |= B600; break;
1940 case 300 : info->tty->termios->c_cflag |= B300; break;
1941 case 200 : info->tty->termios->c_cflag |= B200; break;
1942 case 150 : info->tty->termios->c_cflag |= B150; break;
1943 case 134 : info->tty->termios->c_cflag |= B134; break;
1944 case 110 : info->tty->termios->c_cflag |= B110; break;
1945 case 75 : info->tty->termios->c_cflag |= B75; break;
1946 case 50 : info->tty->termios->c_cflag |= B50; break;
1949 info->speed = speed;
1950 mxser_change_speed(info, 0);
1951 } else {
1952 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1953 if ( error )
1954 return(error);
1955 copy_to_user((int*)arg, &info->speed, sizeof(int));
1957 return 0;
1959 #endif
1961 if ( (cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) &&
1962 (cmd != TIOCGICOUNT) ) {
1963 if ( tty->flags & (1 << TTY_IO_ERROR) )
1964 return(-EIO);
1966 switch ( cmd ) {
1967 #if 1 // add by Victor Yu. 05-08-2007, for GL ODM, I let it to be Moxa standard feature
1968 case MOXA_BREAK_TIMER :
1969 retval = tty_check_change(tty);
1970 if ( retval )
1971 return(retval);
1972 tty_wait_until_sent(tty, 0);
1973 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
1974 local_irq_save(flags);
1975 #else
1976 save_flags(flags);
1977 cli();
1978 #endif // LINUX_VERSION_CODE
1979 outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
1980 udelay(arg);
1981 outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
1982 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
1983 local_irq_restore(flags);
1984 #else
1985 restore_flags(flags);
1986 #endif // LINUX_VERSION_CODE
1987 break;
1988 #endif
1989 #if 1 // add by Victor Yu. 12-28-2004
1990 case TIOCSBRK : // start to send break
1991 retval = tty_check_change(tty);
1992 if ( retval )
1993 return(retval);
1994 tty_wait_until_sent(tty, 0);
1995 save_flags(flags);
1996 cli();
1997 outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
1998 restore_flags(flags);
1999 return 0;
2000 case TIOCCBRK : // stop to send break
2001 save_flags(flags);
2002 cli();
2003 outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
2004 restore_flags(flags);
2005 return 0;
2006 #endif
2007 case TCSBRK: /* SVID version: non-zero arg --> no break */
2008 retval = tty_check_change(tty);
2009 if ( retval )
2010 return(retval);
2011 tty_wait_until_sent(tty, 0);
2012 if ( !arg )
2013 mxser_send_break(info, HZ/4); /* 1/4 second */
2014 return(0);
2015 case TCSBRKP: /* support for POSIX tcsendbreak() */
2016 retval = tty_check_change(tty);
2017 if ( retval )
2018 return(retval);
2019 tty_wait_until_sent(tty, 0);
2020 mxser_send_break(info, arg ? arg*(HZ/10) : HZ/4);
2021 return(0);
2022 case TIOCGSOFTCAR:
2023 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));
2024 if ( error )
2025 return(error);
2026 put_to_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
2027 return 0;
2028 case TIOCSSOFTCAR:
2029 error = verify_area(VERIFY_READ, (void *)arg, sizeof(long));
2030 if ( error )
2031 return(error);
2032 get_from_user(templ,(unsigned long *)arg);
2033 arg = templ;
2034 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
2035 (arg ? CLOCAL : 0));
2036 return(0);
2037 #if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0)) // add by Victor Yu. 04-28-2006, for 2.6.x
2038 case TIOCMGET:
2039 error = verify_area(VERIFY_WRITE, (void *)arg,
2040 sizeof(unsigned int));
2041 if ( error )
2042 return(error);
2043 return(mxser_get_modem_info(info, (unsigned int *)arg));
2044 case TIOCMBIS:
2045 case TIOCMBIC:
2046 case TIOCMSET:
2047 return(mxser_set_modem_info(info, cmd, (unsigned int *)arg));
2048 #endif
2049 case TIOCGSERIAL:
2050 error = verify_area(VERIFY_WRITE, (void *)arg,
2051 sizeof(struct serial_struct));
2052 if ( error )
2053 return(error);
2054 return(mxser_get_serial_info(info, (struct serial_struct *)arg));
2055 case TIOCSSERIAL:
2056 error = verify_area(VERIFY_READ, (void *)arg,
2057 sizeof(struct serial_struct));
2058 if ( error )
2059 return(error);
2060 return(mxser_set_serial_info(info, (struct serial_struct *)arg));
2061 case TIOCSERGETLSR: /* Get line status register */
2062 error = verify_area(VERIFY_WRITE, (void *)arg,
2063 sizeof(unsigned int));
2064 if ( error )
2065 return(error);
2066 else
2067 return(mxser_get_lsr_info(info, (unsigned int *)arg));
2069 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
2070 * - mask passed in arg for lines of interest
2071 * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
2072 * Caller should use TIOCGICOUNT to see which one it was
2074 case TIOCMIWAIT:
2075 save_flags(flags);
2076 cli();
2077 cprev = info->icount; /* note the counters on entry */
2078 restore_flags(flags);
2079 while ( 1 ) {
2080 interruptible_sleep_on(&info->delta_msr_wait);
2081 /* see if a signal did it */
2082 if ( signal_pending(current) ) {
2083 return(-ERESTARTSYS);
2085 save_flags(flags);
2086 cli();
2087 cnow = info->icount; /* atomic copy */
2088 restore_flags(flags);
2089 #if 0 // mask by Victor Yu. 12-31-2004
2090 if ( cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2091 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts )
2092 return(-EIO); /* no change => error */
2093 if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2094 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2095 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
2096 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
2097 return(0);
2099 #else // add by Victor Yu. 12-31-2004
2100 #define TIOCM_BRK 0x10000
2101 #define TIOCM_PARITY 0x20000
2102 #define TIOCM_FRAME 0x40000
2103 #define TIOCM_XOFFHOLD 0x80000
2104 if ( cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2105 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts &&
2106 cnow.brk == cprev.brk && cnow.parity == cprev.parity &&
2107 cnow.frame == cprev.frame && cnow.buf_overrun == cprev.buf_overrun )
2108 return(-EIO); /* no change => error */
2109 if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2110 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2111 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
2112 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ||
2113 ((arg & TIOCM_BRK) && (cnow.brk != cprev.brk)) ||
2114 ((arg & TIOCM_PARITY) && (cnow.parity != cprev.parity)) ||
2115 ((arg & TIOCM_FRAME) && (cnow.frame != cprev.frame)) ||
2116 ((arg & TIOCM_XOFFHOLD) && (cnow.buf_overrun != cprev.buf_overrun)) ) {
2117 return(0);
2119 #endif
2120 cprev = cnow;
2122 /* NOTREACHED */
2124 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2125 * Return: write counters to the user passed counter struct
2126 * NB: both 1->0 and 0->1 transitions are counted except for
2127 * RI where only 0->1 is counted.
2130 #if 1 // add by Victor Yu. 01-26-2005
2131 case MOXA_UNWAIT :
2132 wake_up_interruptible(&info->delta_msr_wait);
2133 break;
2134 #endif
2136 case TIOCGICOUNT:
2137 error = verify_area(VERIFY_WRITE, (void *)arg,
2138 sizeof(struct serial_icounter_struct));
2139 if ( error )
2140 return(error);
2141 save_flags(flags);
2142 cli();
2143 cnow = info->icount;
2144 restore_flags(flags);
2145 p_cuser = (struct serial_icounter_struct *)arg;
2146 /* modified by casper 1/11/2000 */
2147 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2148 if (put_user(cnow.frame, &p_cuser->frame))
2149 return -EFAULT;
2150 if (put_user(cnow.brk, &p_cuser->brk))
2151 return -EFAULT;
2152 if (put_user(cnow.overrun, &p_cuser->overrun))
2153 return -EFAULT;
2154 if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
2155 return -EFAULT;
2156 if (put_user(cnow.parity, &p_cuser->parity))
2157 return -EFAULT;
2158 if (put_user(cnow.rx, &p_cuser->rx))
2159 return -EFAULT;
2160 if (put_user(cnow.tx, &p_cuser->tx))
2161 return -EFAULT;
2162 #endif
2164 put_to_user(cnow.cts, &p_cuser->cts);
2165 put_to_user(cnow.dsr, &p_cuser->dsr);
2166 put_to_user(cnow.rng, &p_cuser->rng);
2167 put_to_user(cnow.dcd, &p_cuser->dcd);
2169 /* */
2170 return(0);
2171 case MOXA_HighSpeedOn:
2172 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
2173 if ( error )
2174 return(error);
2175 put_to_user(info->baud_base != 115200 ? 1 : 0, (int *)arg);
2176 return(0);
2177 default:
2178 return(-ENOIOCTLCMD);
2180 return(0);
2183 static int mxser_ioctl_special(unsigned int cmd, unsigned long arg)
2185 int error, i, result, status;
2187 switch ( cmd ) {
2188 case MOXA_GET_CONF:
2189 error = verify_area(VERIFY_WRITE, (void *)arg,
2190 sizeof(struct mxser_hwconf)*4);
2191 if ( error )
2192 return(error);
2193 copy_to_user((struct mxser_hwconf *)arg, mxsercfg,
2194 sizeof(struct mxser_hwconf)*4);
2195 return 0;
2196 case MOXA_GET_MAJOR:
2197 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
2198 if ( error )
2199 return(error);
2200 copy_to_user((int*)arg, &ttymajor, sizeof(int));
2201 return 0;
2203 case MOXA_GET_CUMAJOR:
2204 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
2205 if ( error )
2206 return(error);
2207 copy_to_user((int*)arg, &calloutmajor, sizeof(int));
2208 return 0;
2210 case MOXA_CHKPORTENABLE:
2211 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));
2212 if ( error )
2213 return(error);
2214 result = 0;
2215 for ( i=0; i<MXSER_PORTS; i++ ) {
2216 if ( mxvar_table[i].base )
2217 result |= (1 << i);
2219 put_to_user(result, (unsigned long *)arg);
2220 return(0);
2221 case MOXA_GETDATACOUNT:
2222 error = verify_area(VERIFY_WRITE, (void *)arg,
2223 sizeof(struct mxser_log));
2224 if ( error )
2225 return(error);
2226 copy_to_user((struct mxser_log *)arg, &mxvar_log, sizeof(mxvar_log));
2227 return(0);
2228 case MOXA_GETMSTATUS:
2229 error = verify_area(VERIFY_WRITE, (void *)arg,
2230 sizeof(struct mxser_mstatus) * MXSER_PORTS);
2231 if ( error )
2232 return(error);
2234 for(i=0; i<MXSER_PORTS; i++){
2235 GMStatus[i].ri = 0;
2236 if ( !mxvar_table[i].base ){
2237 GMStatus[i].dcd = 0;
2238 GMStatus[i].dsr = 0;
2239 GMStatus[i].cts = 0;
2240 continue;
2243 if ( !mxvar_table[i].tty || !mxvar_table[i].tty->termios )
2244 GMStatus[i].cflag=mxvar_table[i].normal_termios.c_cflag;
2245 else
2246 GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag;
2248 status = inb(mxvar_table[i].base + UART_MSR);
2249 if(status & 0x80/*UART_MSR_DCD*/)
2250 GMStatus[i].dcd = 1;
2251 else
2252 GMStatus[i].dcd = 0;
2254 if(status & 0x20/*UART_MSR_DSR*/)
2255 GMStatus[i].dsr = 1;
2256 else
2257 GMStatus[i].dsr = 0;
2260 if(status & 0x10/*UART_MSR_CTS*/)
2261 GMStatus[i].cts = 1;
2262 else
2263 GMStatus[i].cts = 0;
2265 copy_to_user((struct mxser_mstatus *)arg, GMStatus,
2266 sizeof(struct mxser_mstatus) * MXSER_PORTS);
2267 return 0;
2268 default:
2269 return(-ENOIOCTLCMD);
2271 return(0);
2275 * This routine is called by the upper-layer tty layer to signal that
2276 * incoming characters should be throttled.
2278 static void mxser_throttle(struct tty_struct * tty)
2280 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2281 unsigned long flags;
2283 if ( I_IXOFF(tty) || (info->tty->termios->c_cflag & CRTSCTS) ) {
2284 save_flags(flags);
2285 cli();
2286 info->IER &= ~MOXA_MUST_RECV_ISR;
2287 outb(info->IER, info->base+UART_IER);
2288 restore_flags(flags);
2292 static void mxser_unthrottle(struct tty_struct * tty)
2294 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2295 unsigned long flags;
2297 if ( I_IXOFF(tty) ) {
2298 if ( info->x_char )
2299 info->x_char = 0;
2300 else {
2301 save_flags(flags);
2302 cli();
2303 info->IER |= MOXA_MUST_RECV_ISR;
2304 outb(info->IER, info->base+UART_IER);
2305 restore_flags(flags);
2309 if ( info->tty->termios->c_cflag & CRTSCTS ) {
2310 save_flags(flags);
2311 cli();
2312 info->IER |= MOXA_MUST_RECV_ISR;
2313 outb(info->IER, info->base+UART_IER);
2314 restore_flags(flags);
2318 static void mxser_set_termios(struct tty_struct * tty,
2319 struct termios * old_termios)
2321 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2323 #if 0 // mask by Victor Yu. 01-04-2005
2324 if ( (tty->termios->c_cflag != old_termios->c_cflag) ||
2325 (RELEVANT_IFLAG(tty->termios->c_iflag) !=
2326 RELEVANT_IFLAG(old_termios->c_iflag)) ) {
2327 #else // add by Victor Yu. 01-04-2005
2328 if ( (tty->termios->c_cflag != old_termios->c_cflag) ||
2329 (tty->termios->c_iflag != old_termios->c_iflag) ) {
2330 #endif
2332 mxser_change_speed(info, old_termios);
2334 if ( (old_termios->c_cflag & CRTSCTS) &&
2335 !(tty->termios->c_cflag & CRTSCTS) ) {
2336 tty->hw_stopped = 0;
2337 mxser_start(tty);
2341 /* Handle sw stopped */
2342 if ( (old_termios->c_iflag & IXON) &&
2343 !(tty->termios->c_iflag & IXON) ) {
2344 tty->stopped = 0;
2345 mxser_start(tty);
2350 * mxser_stop() and mxser_start()
2352 * This routines are called before setting or resetting tty->stopped.
2353 * They enable or disable transmitter interrupts, as necessary.
2355 static void mxser_stop(struct tty_struct * tty)
2357 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2358 unsigned long flags;
2360 save_flags(flags);
2361 cli();
2362 if ( info->IER & UART_IER_THRI ) {
2363 info->IER &= ~UART_IER_THRI;
2364 outb(info->IER, info->base + UART_IER);
2366 restore_flags(flags);
2369 static void mxser_start(struct tty_struct * tty)
2371 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2372 unsigned long flags;
2374 save_flags(flags);
2375 cli();
2376 if ( info->xmit_cnt && info->xmit_buf &&
2377 !(info->IER & UART_IER_THRI) ) {
2378 info->IER |= UART_IER_THRI;
2379 outb(info->IER, info->base + UART_IER);
2381 restore_flags(flags);
2384 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2386 * mxser_wait_until_sent() --- wait until the transmitter is empty
2388 static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
2390 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
2391 unsigned long orig_jiffies, char_time;
2392 int lsr;
2394 if (info->type == PORT_UNKNOWN)
2395 return;
2397 if (info->xmit_fifo_size == 0)
2398 return; /* Just in case.... */
2401 * Set the check interval to be 1/5 of the estimated time to
2402 * send a single character, and make it at least 1. The check
2403 * interval should also be less than the timeout.
2405 * Note: we have to use pretty tight timings here to satisfy
2406 * the NIST-PCTS.
2408 char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
2409 char_time = char_time / 5;
2410 if (char_time == 0)
2411 char_time = 1;
2412 if (timeout && timeout < char_time)
2413 char_time = timeout;
2415 * If the transmitter hasn't cleared in twice the approximate
2416 * amount of time to send the entire FIFO, it probably won't
2417 * ever clear. This assumes the UART isn't doing flow
2418 * control, which is currently the case. Hence, if it ever
2419 * takes longer than info->timeout, this is probably due to a
2420 * UART bug of some kind. So, we clamp the timeout parameter at
2421 * 2*info->timeout.
2423 if (!timeout || timeout > 2*info->timeout)
2424 timeout = 2*info->timeout;
2425 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2426 printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
2427 printk("jiff=%lu...", jiffies);
2428 #endif
2429 orig_jiffies = jiffies + timeout;
2430 while (!((lsr = inb(info->base+ UART_LSR)) & UART_LSR_TEMT)) {
2431 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2432 printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
2433 #endif
2434 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))
2435 set_current_state(TASK_INTERRUPTIBLE);
2436 #else
2437 current->state = TASK_INTERRUPTIBLE;
2438 #endif
2439 schedule_timeout(char_time);
2440 if (signal_pending(current))
2441 break;
2442 if (timeout && time_after(jiffies, orig_jiffies))
2443 break;
2445 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))
2446 set_current_state(TASK_RUNNING);
2447 #else
2448 current->state = TASK_RUNNING;
2449 #endif
2451 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2452 printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
2453 #endif
2455 #endif
2459 * This routine is called by tty_hangup() when a hangup is signaled.
2461 void mxser_hangup(struct tty_struct * tty)
2463 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
2464 #if 1 // add by Victor Yu. 12-28-2004
2465 unsigned long flags;
2466 #endif
2468 mxser_flush_buffer(tty);
2469 mxser_shutdown(info);
2470 #if 0 // mask by Victor Yu. 12-28-2004
2471 info->event = 0;
2472 info->count = 0;
2473 info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2474 info->tty = 0;
2475 #else
2476 save_flags(flags);
2477 cli();
2478 info->event = 0;
2479 info->count = 0;
2480 #if 0
2481 info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2482 #else
2483 info->flags &= ~(ASYNC_NORMAL_ACTIVE);
2484 #endif
2485 info->tty = 0;
2486 restore_flags(flags);
2487 #endif
2488 wake_up_interruptible(&info->open_wait);
2492 * This is the serial driver's generic interrupt routine
2494 static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs * regs)
2496 int status, iir, i;
2497 struct mxser_struct * info;
2498 struct mxser_struct * port=NULL;
2499 int max, irqbits, msr;
2500 int pass_counter=0, bits;
2502 for ( i=0; i<MXSER_BOARDS; i++ ) {
2503 if ( dev_id == &(mxvar_table[i*MXSER_PORTS_PER_BOARD]) ) {
2504 port = dev_id;
2505 break;
2508 if ( port == NULL ) {
2509 return IRQ_NONE;
2511 max = mxser_numports[mxsercfg[i].board_type-1];
2513 while ( 1 ) {
2514 irqbits = inb(port->vector) & port->vectormask;
2515 if ( irqbits == port->vectormask )
2516 break;
2517 #if defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_IA241_32128) || defined(CONFIG_ARCH_IA241_16128) // add by Victor Yu. 05-22-2007, by PCI interface
2518 for ( i=0, bits=1; i<max; i++, irqbits |= bits, bits <<= 1 ) {
2519 //#elif (defined CONFIG_ARCH_W311)
2520 // for ( i=0, bits=2; i<max; i++, irqbits |= bits, bits <<= 1 ) {
2521 #else
2522 for ( i=0, bits=4; i<max; i++, irqbits |= bits, bits <<= 1 ) {
2523 #endif
2524 if ( irqbits == port->vectormask )
2525 break;
2526 if ( bits & irqbits )
2527 continue;
2528 info = port + i;
2530 // following add by Victor Yu. 09-13-2002
2531 iir = inb(info->base+UART_IIR);
2532 if ( iir & UART_IIR_NO_INT )
2533 continue;
2534 iir &= MOXA_MUST_IIR_MASK;
2535 if ( !info->tty ) { // because the UART chip has bug. so need to do this
2536 status = inb(info->base+UART_LSR);
2537 outb(0x27, info->base+UART_FCR);
2538 inb(info->base+UART_MSR);
2539 continue;
2541 // above add by Victor Yu. 09-13-2002
2543 #if 1 // add by Victor Yu. 01-04-2005
2544 if ( iir == MOXA_MUST_IIR_XSC ) {
2545 if ( !(inb(info->base+UART_MCR) & MOXA_MUST_MCR_XON_FLAG) ) {
2546 info->icount.buf_overrun++;
2547 wake_up_interruptible(&info->delta_msr_wait);
2549 continue;
2551 #endif
2553 if ( iir == MOXA_MUST_IIR_GDA ||
2554 iir == MOXA_MUST_IIR_RDA ||
2555 iir == MOXA_MUST_IIR_RTO ||
2556 iir == MOXA_MUST_IIR_LSR ) {
2557 status = inb(info->base+UART_LSR);
2558 mxser_receive_chars(info, &status);
2560 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2561 if ( iir == UART_IIR_MSI ) {
2562 msr = inb(info->base + UART_MSR);
2563 if ( msr & UART_MSR_ANY_DELTA ) {
2564 mxser_check_modem_status(info, msr);
2567 #else
2568 msr = inb(info->base + UART_MSR);
2569 if ( msr & UART_MSR_ANY_DELTA ) {
2570 mxser_check_modem_status(info, msr);
2572 #endif
2574 if ( iir == 0x02 )
2575 mxser_transmit_chars(info);
2577 if ( pass_counter++ > MXSER_ISR_PASS_LIMIT ) {
2578 break; /* Prevent infinite loops */
2581 return IRQ_HANDLED;
2584 #define BYPASS_FLIP // add by Victor Yu. 09-17-2004
2585 #define N_TTY_BUF_SIZE_MASK (N_TTY_BUF_SIZE-1) // add by Victor Yu. 02-04-2005
2586 static inline void mxser_receive_chars(struct mxser_struct *info,
2587 int *status)
2589 struct tty_struct * tty = info->tty;
2590 unsigned char ch, gdl;
2591 int cnt = 0;
2592 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2593 unsigned char *cp=tty->read_buf;
2594 int wptr=tty->read_head;
2595 #else
2596 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2597 unsigned char *cp=tty->flip.char_buf;
2598 char *fp=tty->flip.flag_buf;
2599 #endif // BYPASS_FLIP
2600 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2602 // following add by Victor Yu. 09-02-2002
2603 if ( *status & (UART_LSR_SPECIAL|MOXA_MUST_LSR_RERR) )
2604 goto intr_old;
2606 gdl = inb(info->base+MOXA_MUST_GDL_REGISTER);
2608 // following add by Victor Yu. 10-13-2004
2609 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2610 cnt = gdl = MIN(gdl, N_TTY_BUF_SIZE_MASK);
2611 #else
2612 #ifdef BYPASS_FLIP
2613 //cnt = gdl = MIN(gdl, TTY_FLIPBUF_SIZE);
2614 cnt = gdl;
2615 #else
2616 cnt = gdl = MIN(gdl, TTY_FLIPBUF_SIZE-tty->flip.count);
2617 #endif // BYPASS_FLIP
2618 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2619 // above add by Victor Yu. 10-13-2004
2621 while ( gdl-- ) {
2622 #if 0 // mask by Victor Yu. 10-13-2004
2623 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2624 if ( cnt >= TTY_FLIPBUF_SIZE )
2625 break;
2626 #else
2627 if ( tty->flip.count >= TTY_FLIPBUF_SIZE )
2628 break;
2629 #endif
2630 #endif
2631 ch = inb(info->base + UART_RX);
2632 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2633 cp[wptr++] = ch;
2634 wptr &= N_TTY_BUF_SIZE_MASK;
2635 #else
2636 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2637 *cp++ = ch;
2638 *fp++ = 0;
2639 #else
2640 tty->flip.count++;
2641 *tty->flip.char_buf_ptr++ = ch;
2642 *tty->flip.flag_buf_ptr++ = 0;
2643 #endif // BYPASS_FLIP
2644 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2645 //cnt++; // mask by Victor Yu. 10-13-2004
2647 goto end_intr;
2649 intr_old:
2650 // above add by Victor Yu. 09-02-2002
2652 ch = inb(info->base + UART_RX);
2654 // following add by Victor Yu. 09-02-2002
2655 if ( (*status&UART_LSR_OE) && !(*status&UART_LSR_DR) )
2656 outb(0x23, info->base+UART_FCR);
2658 #if 1 // add by Victor Yu. 01-06-2005
2660 int __flag=0;
2661 if ( *status & UART_LSR_BI ) {
2662 info->icount.brk++;
2663 __flag = 1;
2665 if ( *status & UART_LSR_PE ) {
2666 info->icount.parity++;
2667 __flag = 1;
2669 if ( *status & UART_LSR_FE ) {
2670 info->icount.frame++;
2671 __flag = 1;
2673 if ( *status & UART_LSR_OE ) {
2674 info->icount.overrun++;
2675 __flag = 1;
2677 if ( __flag )
2678 wake_up_interruptible(&info->delta_msr_wait);
2680 #endif
2682 *status &= info->read_status_mask;
2683 // above add by Victor Yu. 09-02-2002
2685 if ( !(*status & info->ignore_status_mask) ) {
2686 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2687 if ( (cnt+tty->read_cnt) >= N_TTY_BUF_SIZE_MASK )
2688 goto end_intr;
2689 #else
2690 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2691 if ( cnt >= TTY_FLIPBUF_SIZE )
2692 goto end_intr;
2693 #else
2694 if ( tty->flip.count >= TTY_FLIPBUF_SIZE )
2695 goto end_intr;
2696 tty->flip.count++;
2697 #endif // BYPASS_FLIP
2698 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2699 if ( *status & UART_LSR_SPECIAL ) {
2700 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2701 goto end_intr;
2702 #else
2703 if ( *status & UART_LSR_BI ) {
2704 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2705 *fp++ = TTY_BREAK;
2706 #else
2707 *tty->flip.flag_buf_ptr++ = TTY_BREAK;
2708 #endif
2710 if ( info->flags & ASYNC_SAK )
2711 do_SAK(tty);
2712 } else if ( *status & UART_LSR_PE ) {
2713 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2714 *fp++ = TTY_PARITY;
2715 #else
2716 *tty->flip.flag_buf_ptr++ = TTY_PARITY;
2717 #endif
2718 } else if ( *status & UART_LSR_FE ) {
2719 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2720 *fp++ = TTY_FRAME;
2721 #else
2722 *tty->flip.flag_buf_ptr++ = TTY_FRAME;
2723 #endif
2724 } else if ( *status & UART_LSR_OE ) {
2725 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2726 *fp++ = TTY_OVERRUN;
2727 #else
2728 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
2729 #endif
2730 } else {
2731 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2732 *fp++ = 0;
2733 #else
2734 *tty->flip.flag_buf_ptr++ = 0;
2735 #endif
2737 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2738 } else {
2739 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2740 // do nothing
2741 #else
2742 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2743 *fp++ = 0;
2744 #else
2745 *tty->flip.flag_buf_ptr++ = 0;
2746 #endif // BYPASS_FLIP
2747 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2749 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2750 cp[wptr++] = ch;
2751 wptr &= N_TTY_BUF_SIZE_MASK;
2752 #else
2753 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2754 *cp++ = ch;
2755 #else
2756 *tty->flip.char_buf_ptr++ = ch;
2757 #endif // BYPASS_FLIP
2758 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2759 cnt++;
2762 end_intr: // add by Victor Yu. 09-02-2002
2764 mxvar_log.rxcnt[info->port] += cnt;
2766 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)) // add by Victor Yu. 02-04-2005
2767 info->icount.rx += cnt;
2768 #endif
2770 /* added by casper 1/11/2000 */
2771 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2772 tty->read_head = wptr;
2773 tty->read_cnt += cnt;
2774 #else
2775 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2776 tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, cnt);
2777 #else
2778 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2779 tty_flip_buffer_push(tty);
2780 #else
2781 queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
2782 #endif // LINUX_VERSION_CODE
2783 #endif // BYPASS_FLIP
2784 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2785 /* */
2788 static inline void mxser_transmit_chars(struct mxser_struct *info)
2790 int count, cnt;
2792 if ( info->x_char ) {
2793 outb(info->x_char, info->base + UART_TX);
2794 info->x_char = 0;
2795 mxvar_log.txcnt[info->port]++;
2796 /* added by casper 1/11/2000 */
2797 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2798 info->icount.tx++;
2799 #endif
2800 /* */
2801 return;
2804 if ( info->xmit_buf == 0 )
2805 return;
2807 if ((info->xmit_cnt <= 0) || info->tty->stopped ||
2808 (info->tty->hw_stopped && (info->type != PORT_16550A))) {
2809 info->IER &= ~UART_IER_THRI;
2810 outb(info->IER, info->base + UART_IER);
2811 return;
2814 #if 0 // mask by Victor Yu. 10-12-2004
2815 cnt = info->xmit_cnt;
2816 count = info->xmit_fifo_size;
2817 do {
2818 outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
2819 info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
2820 if ( --info->xmit_cnt <= 0 )
2821 break;
2822 } while ( --count > 0 );
2823 mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
2824 #else // add by Victor Yu. 10-12-2004
2826 int tail=info->xmit_tail;
2827 unsigned char *ptr=info->xmit_buf;
2828 #define XMIT_SIZE_MASK (SERIAL_XMIT_SIZE - 1)
2829 cnt = count = MIN(info->xmit_fifo_size, info->xmit_cnt);
2830 while ( count-- > 0 ) {
2831 outb(ptr[tail++], info->base);
2832 tail &= XMIT_SIZE_MASK;
2834 info->xmit_tail = tail;
2835 info->xmit_cnt -= cnt;
2836 mxvar_log.txcnt[info->port] += cnt;
2838 #endif
2840 /* added by casper 1/11/2000 */
2841 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2842 #if 0 // mask by Victor Yu. 10-12-2004
2843 info->icount.tx += (cnt - info->xmit_cnt);
2844 #else // add by Victor Yu. 10-12-2004
2845 info->icount.tx += cnt;
2846 #endif
2847 #endif
2848 /* */
2850 if ( info->xmit_cnt < WAKEUP_CHARS ) {
2851 set_bit(MXSER_EVENT_TXLOW,&info->event);
2852 #if 0
2853 MOD_INC_USE_COUNT;
2854 if (schedule_task(&info->tqueue) == 0)
2855 MOD_DEC_USE_COUNT;
2856 queue_task(&info->tqueue,&tq_scheduler);
2857 #else
2858 schedule_work(&info->tqueue);
2859 #endif
2861 if (info->xmit_cnt <= 0) {
2862 info->IER &= ~UART_IER_THRI;
2863 outb(info->IER, info->base + UART_IER);
2867 static inline void mxser_check_modem_status(struct mxser_struct *info,
2868 int status)
2870 /* update input line counters */
2871 if ( status & UART_MSR_TERI )
2872 info->icount.rng++;
2873 if ( status & UART_MSR_DDSR )
2874 info->icount.dsr++;
2875 if ( status & UART_MSR_DDCD )
2876 info->icount.dcd++;
2877 if ( status & UART_MSR_DCTS )
2878 info->icount.cts++;
2879 wake_up_interruptible(&info->delta_msr_wait);
2881 if ( (info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD) ) {
2882 if ( status & UART_MSR_DCD )
2883 wake_up_interruptible(&info->open_wait);
2884 #if 0
2885 else if ( !((info->flags & ASYNC_CALLOUT_ACTIVE) &&
2886 (info->flags & ASYNC_CALLOUT_NOHUP)) )
2887 #else
2888 else
2889 #endif
2890 set_bit(MXSER_EVENT_HANGUP,&info->event);
2891 #if 0
2892 MOD_INC_USE_COUNT;
2893 if (schedule_task(&info->tqueue) == 0)
2894 MOD_DEC_USE_COUNT;
2895 #else
2896 schedule_work(&info->tqueue);
2897 #endif
2899 if ( info->flags & ASYNC_CTS_FLOW ) {
2900 if ( info->tty->hw_stopped ) {
2901 if (status & UART_MSR_CTS ){
2902 info->tty->hw_stopped = 0;
2904 if (info->type != PORT_16550A) {
2905 info->IER |= UART_IER_THRI;
2906 outb(info->IER, info->base + UART_IER);
2908 set_bit(MXSER_EVENT_TXLOW,&info->event);
2909 #if 0
2910 MOD_INC_USE_COUNT;
2911 if (schedule_task(&info->tqueue) == 0)
2912 MOD_DEC_USE_COUNT;
2913 #else
2914 schedule_work(&info->tqueue);
2915 #endif
2917 } else {
2918 if ( !(status & UART_MSR_CTS) ){
2919 info->tty->hw_stopped = 1;
2920 if (info->type != PORT_16550A) {
2921 info->IER &= ~UART_IER_THRI;
2922 outb(info->IER, info->base + UART_IER);
2929 static int mxser_block_til_ready(struct tty_struct *tty, struct file * filp,
2930 struct mxser_struct *info)
2932 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))
2933 DECLARE_WAITQUEUE(wait, current);
2934 #else
2935 struct wait_queue wait = { current, NULL };
2936 #endif
2937 unsigned long flags;
2938 int retval;
2939 int do_clocal = 0;
2942 * If the device is in the middle of being closed, then block
2943 * until it's done, and then try again.
2945 if ( tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING) ) {
2946 if ( info->flags & ASYNC_CLOSING )
2947 interruptible_sleep_on(&info->close_wait);
2948 #ifdef SERIAL_DO_RESTART
2949 if ( info->flags & ASYNC_HUP_NOTIFY )
2950 return(-EAGAIN);
2951 else
2952 return(-ERESTARTSYS);
2953 #else
2954 return(-EAGAIN);
2955 #endif
2959 * If this is a callout device, then just make sure the normal
2960 * device isn't being used.
2962 #if 0
2963 if ( tty->driver->subtype == SERIAL_TYPE_CALLOUT ) {
2964 if ( info->flags & ASYNC_NORMAL_ACTIVE )
2965 return(-EBUSY);
2966 if ( (info->flags & ASYNC_CALLOUT_ACTIVE) &&
2967 (info->flags & ASYNC_SESSION_LOCKOUT) &&
2968 (info->session != current->session) )
2969 return(-EBUSY);
2970 if ( (info->flags & ASYNC_CALLOUT_ACTIVE) &&
2971 (info->flags & ASYNC_PGRP_LOCKOUT) &&
2972 (info->pgrp != current->pgrp) )
2973 return(-EBUSY);
2974 info->flags |= ASYNC_CALLOUT_ACTIVE;
2975 return(0);
2977 #endif
2980 * If non-blocking mode is set, or the port is not enabled,
2981 * then make the check up front and then exit.
2983 if ( (filp->f_flags & O_NONBLOCK) ||
2984 (tty->flags & (1 << TTY_IO_ERROR)) ) {
2985 #if 0
2986 if ( info->flags & ASYNC_CALLOUT_ACTIVE )
2987 return(-EBUSY);
2988 #endif
2989 info->flags |= ASYNC_NORMAL_ACTIVE;
2990 return(0);
2993 #if 0
2994 if ( info->flags & ASYNC_CALLOUT_ACTIVE ) {
2995 if ( info->normal_termios.c_cflag & CLOCAL )
2996 do_clocal = 1;
2997 } else {
2998 #endif
2999 if ( tty->termios->c_cflag & CLOCAL )
3000 do_clocal = 1;
3001 #if 0
3003 #endif
3006 * Block waiting for the carrier detect and the line to become
3007 * free (i.e., not in use by the callout). While we are in
3008 * this loop, info->count is dropped by one, so that
3009 * mxser_close() knows when to free things. We restore it upon
3010 * exit, either normal or abnormal.
3012 retval = 0;
3013 add_wait_queue(&info->open_wait, &wait);
3014 #if 0 // mask by Victor Yu. 12-28-2004
3015 save_flags(flags);
3016 cli();
3017 if ( !tty_hung_up_p(filp) )
3018 info->count--;
3019 restore_flags(flags);
3020 #else // add by Victor Yu. 12-28-2004
3021 if ( !tty_hung_up_p(filp) ) {
3022 save_flags(flags);
3023 cli();
3024 info->count--;
3025 restore_flags(flags);
3027 #endif
3028 info->blocked_open++;
3029 while ( 1 ) {
3030 save_flags(flags);
3031 cli();
3032 #if 0
3033 if ( !(info->flags & ASYNC_CALLOUT_ACTIVE) )
3034 #endif
3035 outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS,
3036 info->base + UART_MCR);
3037 restore_flags(flags);
3038 current->state = TASK_INTERRUPTIBLE;
3039 if ( tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED) ) {
3040 #ifdef SERIAL_DO_RESTART
3041 if ( info->flags & ASYNC_HUP_NOTIFY )
3042 retval = -EAGAIN;
3043 else
3044 retval = -ERESTARTSYS;
3045 #else
3046 retval = -EAGAIN;
3047 #endif
3048 break;
3050 #if 0
3051 if ( !(info->flags & ASYNC_CALLOUT_ACTIVE) &&
3052 !(info->flags & ASYNC_CLOSING) &&
3053 (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)) )
3054 #else
3055 if ( !(info->flags & ASYNC_CLOSING) &&
3056 (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)) )
3057 #endif
3058 break;
3059 if ( signal_pending(current) ) {
3060 retval = -ERESTARTSYS;
3061 break;
3063 schedule();
3065 current->state = TASK_RUNNING;
3066 remove_wait_queue(&info->open_wait, &wait);
3067 if ( !tty_hung_up_p(filp) ) {
3068 #if 0 // mask by Victor 12-28-2004
3069 info->count++;
3070 #else // add by Victor Yu. 12-28-2004
3071 save_flags(flags);
3072 cli();
3073 info->count++;
3074 restore_flags(flags);
3075 #endif
3077 info->blocked_open--;
3078 if ( retval )
3079 return(retval);
3080 info->flags |= ASYNC_NORMAL_ACTIVE;
3081 return(0);
3084 static int mxser_startup(struct mxser_struct * info)
3086 unsigned long flags;
3087 unsigned long page;
3089 page = get_zeroed_page(GFP_KERNEL);
3090 if ( !page )
3091 return(-ENOMEM);
3093 save_flags(flags);
3094 cli();
3096 if ( info->flags & ASYNC_INITIALIZED ) {
3097 free_page(page);
3098 restore_flags(flags);
3099 return(0);
3102 if ( !info->base || !info->type ) {
3103 if ( info->tty )
3104 set_bit(TTY_IO_ERROR, &info->tty->flags);
3105 free_page(page);
3106 restore_flags(flags);
3107 return(0);
3109 if ( info->xmit_buf )
3110 free_page(page);
3111 else
3112 info->xmit_buf = (unsigned char *)page;
3115 * Clear the FIFO buffers and disable them
3116 * (they will be reenabled in mxser_change_speed())
3118 if ( info->xmit_fifo_size == 16 )
3119 outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
3120 info->base + UART_FCR);
3121 // following add by Victor Yu. 08-30-2002
3122 else if ( info->xmit_fifo_size == 64 || info->xmit_fifo_size == 128 )
3123 outb((UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT|MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base+UART_FCR);
3124 // above add by Victor Yu. 08-30-2002
3127 * At this point there's no way the LSR could still be 0xFF;
3128 * if it is, then bail out, because there's likely no UART
3129 * here.
3131 if ( inb(info->base + UART_LSR) == 0xff ) {
3132 restore_flags(flags);
3133 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3134 if ( suser() ) {
3135 #else
3136 if (capable(CAP_SYS_ADMIN)) {
3137 #endif
3138 if ( info->tty )
3139 set_bit(TTY_IO_ERROR, &info->tty->flags);
3140 return(0);
3141 } else
3142 return(-ENODEV);
3146 * Clear the interrupt registers.
3148 (void)inb(info->base + UART_LSR);
3149 (void)inb(info->base + UART_RX);
3150 (void)inb(info->base + UART_IIR);
3151 (void)inb(info->base + UART_MSR);
3154 * Now, initialize the UART
3156 outb(UART_LCR_WLEN8, info->base + UART_LCR); /* reset DLAB */
3157 info->MCR = UART_MCR_DTR | UART_MCR_RTS;
3158 outb(info->MCR, info->base + UART_MCR);
3161 * Finally, enable interrupts
3163 info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI | MOXA_MUST_IER_EGDAI;
3164 outb(info->IER, info->base + UART_IER); /* enable interrupts */
3167 * And clear the interrupt registers again for luck.
3169 (void)inb(info->base + UART_LSR);
3170 (void)inb(info->base + UART_RX);
3171 (void)inb(info->base + UART_IIR);
3172 (void)inb(info->base + UART_MSR);
3174 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3175 if ( info->tty )
3176 clear_bit(TTY_IO_ERROR, &info->tty->flags);
3177 #else
3178 if ( info->tty )
3179 test_and_clear_bit(TTY_IO_ERROR, &info->tty->flags);
3180 #endif
3181 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
3184 * and set the speed of the serial port
3186 #if 1 // add by Victor Yu. 12-27-2004
3187 restore_flags(flags);
3188 #endif
3189 mxser_change_speed(info, 0);
3191 #if 1 // add by Victor Yu. 12-27-2004
3192 save_flags(flags);
3193 cli();
3194 #endif
3195 info->flags |= ASYNC_INITIALIZED;
3196 restore_flags(flags);
3197 return(0);
3201 * This routine will shutdown a serial port; interrupts maybe disabled, and
3202 * DTR is dropped if the hangup on close termio flag is on.
3204 static void mxser_shutdown(struct mxser_struct * info)
3206 unsigned long flags;
3208 if ( !(info->flags & ASYNC_INITIALIZED) )
3209 return;
3211 save_flags(flags);
3212 cli(); /* Disable interrupts */
3215 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
3216 * here so the queue might never be waken up
3218 wake_up_interruptible(&info->delta_msr_wait);
3221 * Free the IRQ, if necessary
3223 if ( info->xmit_buf ) {
3224 free_page((unsigned long)info->xmit_buf);
3225 info->xmit_buf = 0;
3228 info->IER = 0;
3229 outb(0x00, info->base + UART_IER);
3231 if ( !info->tty || (info->tty->termios->c_cflag & HUPCL) )
3232 info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
3233 outb(info->MCR, info->base + UART_MCR);
3235 /* clear Rx/Tx FIFO's */
3236 outb((UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT|MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
3238 /* read data port to reset things */
3239 (void)inb(info->base + UART_RX);
3241 if ( info->tty )
3242 set_bit(TTY_IO_ERROR, &info->tty->flags);
3244 info->flags &= ~ASYNC_INITIALIZED;
3245 SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base);
3246 restore_flags(flags);
3250 * This routine is called to set the UART divisor registers to match
3251 * the specified baud rate for a serial port.
3253 static int mxser_change_speed(struct mxser_struct *info,
3254 struct termios *old_termios)
3256 int quot = 0;
3257 unsigned cflag, cval, fcr;
3258 int bindex;
3259 int ret = 0;
3260 unsigned long flags;
3262 if ( !info->tty || !info->tty->termios )
3263 return ret;
3264 cflag = info->tty->termios->c_cflag;
3265 if ( !(info->base) )
3266 return ret;
3268 #ifndef B921600
3269 #define B921600 (B460800 +1)
3270 #endif
3271 switch( cflag & (CBAUD | CBAUDEX) ){
3272 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-13-2004
3273 case B4000000 : bindex = BAUD_TABLE_NO; break;
3274 #endif
3275 case B921600 : bindex = 20; break;
3276 case B460800 : bindex = 19; break;
3277 case B230400 : bindex = 18; break;
3278 case B115200 : bindex = 17; break;
3279 case B57600 : bindex = 16; break;
3280 case B38400 : bindex = 15; break;
3281 case B19200 : bindex = 14; break;
3282 case B9600 : bindex = 13; break;
3283 case B4800 : bindex = 12; break;
3284 case B2400 : bindex = 11; break;
3285 case B1800 : bindex = 10; break;
3286 case B1200 : bindex = 9; break;
3287 case B600 : bindex = 8; break;
3288 case B300 : bindex = 7; break;
3289 case B200 : bindex = 6; break;
3290 case B150 : bindex = 5; break;
3291 case B134 : bindex = 4; break;
3292 case B110 : bindex = 3; break;
3293 case B75 : bindex = 2; break;
3294 case B50 : bindex = 1; break;
3295 default: bindex = 0; break;
3298 if ( bindex == 15 ) {
3299 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI )
3300 bindex = 16; /* 57600 bps */
3301 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI )
3302 bindex = 17; /* 115200 bps */
3304 #ifdef ASYNC_SPD_SHI
3305 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3306 bindex = 18;
3307 #endif
3309 #ifdef ASYNC_SPD_WARP
3310 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3311 bindex = 19;
3312 #endif
3314 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-13-2004
3315 if ( bindex == BAUD_TABLE_NO ) {
3316 quot = info->baud_base / info->speed;
3317 if ( info->speed <= 0 || info->speed > info->MaxCanSetBaudRate )
3318 quot = 0;
3320 else
3321 #endif
3322 if ( mxvar_baud_table[bindex] == 134 ) {
3323 quot = (2 * info->baud_base / 269);
3324 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3325 info->speed = 134;
3326 #endif
3327 } else if ( mxvar_baud_table[bindex] ) {
3328 quot = info->baud_base / mxvar_baud_table[bindex];
3329 // following add by Victor Yu. 09-04-2002
3330 if ( mxvar_baud_table[bindex] > info->MaxCanSetBaudRate )
3331 quot = 0;
3332 // add by Victor Yu. 09-04-2002
3333 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3334 info->speed = mxvar_baud_table[bindex];
3335 #endif
3336 if (!quot && old_termios) {
3337 /* re-calculate */
3338 info->tty->termios->c_cflag &= ~CBAUD;
3339 info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
3340 switch( info->tty->termios->c_cflag & (CBAUD | CBAUDEX) ){
3341 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-13-2004
3342 case B4000000 : bindex = BAUD_TABLE_NO; break;
3343 #endif
3344 case B921600 : bindex = 20; break;
3345 case B460800 : bindex = 19; break;
3346 case B230400 : bindex = 18; break;
3347 case B115200 : bindex = 17; break;
3348 case B57600 : bindex = 16; break;
3349 case B38400 : bindex = 15; break;
3350 case B19200 : bindex = 14; break;
3351 case B9600 : bindex = 13; break;
3352 case B4800 : bindex = 12; break;
3353 case B2400 : bindex = 11; break;
3354 case B1800 : bindex = 10; break;
3355 case B1200 : bindex = 9; break;
3356 case B600 : bindex = 8; break;
3357 case B300 : bindex = 7; break;
3358 case B200 : bindex = 6; break;
3359 case B150 : bindex = 5; break;
3360 case B134 : bindex = 4; break;
3361 case B110 : bindex = 3; break;
3362 case B75 : bindex = 2; break;
3363 case B50 : bindex = 1; break;
3364 default: bindex = 0; break;
3366 if ( bindex == 15 ) {
3367 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI )
3368 bindex = 16; /* 57600 bps */
3369 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI )
3370 bindex = 17; /* 115200 bps */
3371 #ifdef ASYNC_SPD_SHI
3372 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3373 bindex = 18;
3374 #endif
3375 #ifdef ASYNC_SPD_WARP
3376 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3377 bindex = 19;
3378 #endif
3380 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-13-2004
3381 if ( bindex == BAUD_TABLE_NO ) {
3382 quot = info->baud_base / info->speed;
3383 if ( info->speed <= 0 || info->speed > info->MaxCanSetBaudRate )
3384 quot = 0;
3386 else
3387 #endif
3388 if ( mxvar_baud_table[bindex] == 134 ) {
3389 quot = (2 * info->baud_base / 269);
3390 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3391 info->speed = 134;
3392 #endif
3393 } else if ( mxvar_baud_table[bindex] ) {
3394 quot = info->baud_base / mxvar_baud_table[bindex];
3395 // following add by Victor Yu. 09-04-2002
3396 if ( mxvar_baud_table[bindex] > info->MaxCanSetBaudRate )
3397 quot = 0;
3398 // above add by Victor Yu. 09-04-2002
3399 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3400 info->speed = mxvar_baud_table[bindex];
3401 #endif
3402 if(quot==0)
3403 quot = 1;
3404 } else {
3405 quot = 0;
3407 }else if(quot==0)
3408 quot = 1;
3409 } else {
3410 quot = 0;
3413 info->timeout = ((info->xmit_fifo_size*HZ*10*quot) / info->baud_base);
3414 info->timeout += HZ/50; /* Add .02 seconds of slop */
3416 if ( quot ) {
3417 save_flags(flags);
3418 cli();
3419 info->MCR |= UART_MCR_DTR;
3420 outb(info->MCR, info->base + UART_MCR);
3421 restore_flags(flags);
3422 } else {
3423 save_flags(flags);
3424 cli();
3425 info->MCR &= ~UART_MCR_DTR;
3426 outb(info->MCR, info->base + UART_MCR);
3427 restore_flags(flags);
3428 return ret;
3430 /* byte size and parity */
3431 switch ( cflag & CSIZE ) {
3432 case CS5: cval = 0x00; break;
3433 case CS6: cval = 0x01; break;
3434 case CS7: cval = 0x02; break;
3435 case CS8: cval = 0x03; break;
3436 default: cval = 0x00; break; /* too keep GCC shut... */
3438 if ( cflag & CSTOPB )
3439 cval |= 0x04;
3440 if ( cflag & PARENB )
3441 cval |= UART_LCR_PARITY;
3442 #ifndef CMSPAR
3443 #define CMSPAR 010000000000
3444 #endif
3445 if ( !(cflag & PARODD) ){
3446 cval |= UART_LCR_EPAR;
3448 if ( cflag & CMSPAR )
3449 cval |= UART_LCR_SPAR;
3451 if ( (info->type == PORT_8250) || (info->type == PORT_16450) ) {
3452 fcr = 0;
3453 } else {
3454 fcr = UART_FCR_ENABLE_FIFO;
3455 // following add by Victor Yu. 08-30-2002
3456 fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
3457 #if 1 // add by Victor Yu. 05-04-2005
3458 save_flags(flags);
3459 cli();
3460 #endif
3461 SET_MOXA_MUST_FIFO_VALUE(info);
3462 #if 1 // add by Victor Yu. 05-04-2005
3463 restore_flags(flags);
3464 #endif
3467 /* CTS flow control flag and modem status interrupts */
3468 #if 1 // add by Victor Yu. 12-30-2004
3469 save_flags(flags);
3470 cli();
3471 #if 1 // add by Victor Yu. 05-04-2005
3472 outb(cval | UART_LCR_DLAB, info->base + UART_LCR); /* set DLAB */
3473 outb(quot & 0xff, info->base + UART_DLL); /* LS of divisor */
3474 outb(quot >> 8, info->base + UART_DLM); /* MS of divisor */
3475 outb(cval, info->base + UART_LCR); /* reset DLAB */
3476 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3477 if ( info->speed ) {
3478 quot = info->baud_base % info->speed;
3479 quot *= 8;
3480 if ( (quot % info->speed) > (info->speed / 2) ) {
3481 quot /= info->speed;
3482 quot++;
3483 } else {
3484 quot /= info->speed;
3486 SET_MOXA_MUST_ENUM_VALUE(info->base, quot);
3487 } else {
3488 SET_MOXA_MUST_ENUM_VALUE(info->base, 0);
3490 #endif
3491 outb(fcr, info->base + UART_FCR); /* set fcr */
3492 #endif // 05-04-2005
3493 #endif // 12-30-2004
3494 #if 0 // mask by Victor Yu. 12-31-2004
3495 info->IER &= ~UART_IER_MSI;
3496 #endif
3497 info->MCR &= ~UART_MCR_AFE;
3498 if ( cflag & CRTSCTS ) {
3499 info->flags |= ASYNC_CTS_FLOW;
3500 info->IER |= UART_IER_MSI;
3501 if ( info->type == PORT_16550A ) {
3502 info->MCR |= UART_MCR_AFE;
3503 } else {
3504 unsigned char status;
3505 #if 0 // mask by Victor Yu. 12-30-2004
3506 save_flags(flags);
3507 cli();
3508 #endif
3509 status = inb(info->base + UART_MSR);
3510 #if 0 // mask by Victor Yu. 12-30-2004
3511 restore_flags(flags);
3512 #endif
3513 if (info->tty->hw_stopped) {
3514 if (status & UART_MSR_CTS) {
3515 info->tty->hw_stopped = 0;
3516 if (info->type != PORT_16550A) {
3517 info->IER |= UART_IER_THRI;
3518 outb(info->IER, info->base + UART_IER);
3520 set_bit(MXSER_EVENT_TXLOW, &info->event);
3521 #if 0
3522 MOD_INC_USE_COUNT;
3523 if (schedule_task(&info->tqueue) == 0)
3524 MOD_DEC_USE_COUNT;
3525 #else
3526 schedule_work(&info->tqueue);
3527 #endif
3529 } else {
3530 if (!(status & UART_MSR_CTS)) {
3531 info->tty->hw_stopped = 1;
3532 if (info->type != PORT_16550A) {
3533 info->IER &= ~UART_IER_THRI;
3534 outb(info->IER, info->base + UART_IER);
3539 } else {
3540 info->flags &= ~ASYNC_CTS_FLOW;
3542 #if 0 // add by Victor Yu. 12-27-2004
3543 save_flags(flags);
3544 cli();
3545 #endif
3546 outb(info->MCR, info->base + UART_MCR);
3547 if ( cflag & CLOCAL ){
3548 info->flags &= ~ASYNC_CHECK_CD;
3549 }else {
3550 info->flags |= ASYNC_CHECK_CD;
3551 info->IER |= UART_IER_MSI;
3553 outb(info->IER, info->base + UART_IER);
3554 #if 1 // add by Victor Yu. 12-27-2004
3555 restore_flags(flags);
3556 #endif
3559 * Set up parity check flag
3561 info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
3562 if ( I_INPCK(info->tty) )
3563 info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
3564 if ( I_BRKINT(info->tty) || I_PARMRK(info->tty) )
3565 info->read_status_mask |= UART_LSR_BI;
3567 info->ignore_status_mask = 0;
3568 #if 0
3569 /* This should be safe, but for some broken bits of hardware... */
3570 if ( I_IGNPAR(info->tty) ) {
3571 info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
3572 info->read_status_mask |= UART_LSR_PE | UART_LSR_FE;
3574 #endif
3575 if ( I_IGNBRK(info->tty) ) {
3576 info->ignore_status_mask |= UART_LSR_BI;
3577 info->read_status_mask |= UART_LSR_BI;
3579 * If we're ignore parity and break indicators, ignore
3580 * overruns too. (For real raw support).
3582 if ( I_IGNPAR(info->tty) ) {
3583 info->ignore_status_mask |= UART_LSR_OE|UART_LSR_PE|UART_LSR_FE;
3584 info->read_status_mask |= UART_LSR_OE|UART_LSR_PE|UART_LSR_FE;
3588 // following add by Victor Yu. 09-02-2002
3589 save_flags(flags);
3590 cli();
3591 SET_MOXA_MUST_XON1_VALUE(info->base, START_CHAR(info->tty));
3592 SET_MOXA_MUST_XOFF1_VALUE(info->base, STOP_CHAR(info->tty));
3593 if ( I_IXON(info->tty) ) {
3594 #if 1 // add by Victor Yu. 01-04-2005
3595 info->IER |= MOXA_MUST_IER_XINT;
3596 #endif
3597 ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
3598 } else {
3599 #if 1 // add by Victor Yu. 01-04-2005
3600 info->IER &= ~MOXA_MUST_IER_XINT;
3601 #endif
3602 DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
3604 #if 1 // add by Victor Yu. 01-04-2005
3605 outb(info->IER, info->base+UART_IER);
3606 #endif
3607 if ( I_IXOFF(info->tty) ) {
3608 ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base);
3609 } else {
3610 DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base);
3612 if ( I_IXANY(info->tty) ) {
3613 info->MCR |= MOXA_MUST_MCR_XON_ANY;
3614 ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base);
3615 } else {
3616 info->MCR &= ~MOXA_MUST_MCR_XON_ANY;
3617 DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base);
3619 restore_flags(flags);
3620 // above add by Victor Yu. 09-02-2002
3622 return ret;
3626 * ------------------------------------------------------------
3627 * friends of mxser_ioctl()
3628 * ------------------------------------------------------------
3630 static int mxser_get_serial_info(struct mxser_struct * info,
3631 struct serial_struct * retinfo)
3633 struct serial_struct tmp;
3635 if ( !retinfo )
3636 return(-EFAULT);
3637 memset(&tmp, 0, sizeof(tmp));
3638 tmp.type = info->type;
3639 tmp.line = info->port;
3640 tmp.port = info->base;
3641 tmp.irq = info->irq;
3642 tmp.flags = info->flags;
3643 tmp.baud_base = info->baud_base;
3644 tmp.close_delay = info->close_delay;
3645 tmp.closing_wait = info->closing_wait;
3646 tmp.custom_divisor = info->custom_divisor;
3647 tmp.hub6 = 0;
3648 copy_to_user(retinfo, &tmp, sizeof(*retinfo));
3649 return(0);
3652 static int mxser_set_serial_info(struct mxser_struct * info,
3653 struct serial_struct * new_info)
3655 struct serial_struct new_serial;
3656 unsigned int flags;
3657 int retval = 0;
3659 if ( !new_info || !info->base )
3660 return(-EFAULT);
3661 copy_from_user(&new_serial, new_info, sizeof(new_serial));
3663 if ( (new_serial.irq != info->irq) ||
3664 (new_serial.port != info->base) ||
3665 (new_serial.custom_divisor != info->custom_divisor) ||
3666 (new_serial.baud_base != info->baud_base) )
3667 return(-EPERM);
3669 flags = info->flags & ASYNC_SPD_MASK;
3671 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3672 if ( !suser() ) {
3673 #else
3674 if ( !capable(CAP_SYS_ADMIN)) {
3675 #endif
3676 if ( (new_serial.baud_base != info->baud_base) ||
3677 (new_serial.close_delay != info->close_delay) ||
3678 ((new_serial.flags & ~ASYNC_USR_MASK) !=
3679 (info->flags & ~ASYNC_USR_MASK)) )
3680 return(-EPERM);
3681 info->flags = ((info->flags & ~ASYNC_USR_MASK) |
3682 (new_serial.flags & ASYNC_USR_MASK));
3683 } else {
3685 * OK, past this point, all the error checking has been done.
3686 * At this point, we start making changes.....
3688 info->flags = ((info->flags & ~ASYNC_FLAGS) |
3689 (new_serial.flags & ASYNC_FLAGS));
3690 info->close_delay = new_serial.close_delay * HZ/100;
3691 info->closing_wait = new_serial.closing_wait * HZ/100;
3692 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
3693 info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
3694 #endif
3697 /* added by casper, 3/17/2000, for mouse */
3698 info->type = new_serial.type;
3700 info->xmit_fifo_size = 128;
3701 if ( info->flags & ASYNC_INITIALIZED ) {
3702 if ( flags != (info->flags & ASYNC_SPD_MASK) ){
3703 mxser_change_speed(info,0);
3705 } else{
3706 retval = mxser_startup(info);
3708 return(retval);
3712 * mxser_get_lsr_info - get line status register info
3714 * Purpose: Let user call ioctl() to get info when the UART physically
3715 * is emptied. On bus types like RS485, the transmitter must
3716 * release the bus after transmitting. This must be done when
3717 * the transmit shift register is empty, not be done when the
3718 * transmit holding register is empty. This functionality
3719 * allows an RS485 driver to be written in user space.
3721 static int mxser_get_lsr_info(struct mxser_struct * info, unsigned int *value)
3723 unsigned char status;
3724 unsigned int result;
3725 unsigned long flags;
3727 save_flags(flags);
3728 cli();
3729 status = inb(info->base + UART_LSR);
3730 restore_flags(flags);
3731 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
3732 put_to_user(result, value);
3733 return(0);
3737 * This routine sends a break character out the serial port.
3739 static void mxser_send_break(struct mxser_struct * info, int duration)
3741 unsigned long flags;
3742 #if 1 // add by Victor Yu. 12-27-2004
3743 unsigned long timeout;
3744 #endif
3746 if ( !info->base )
3747 return;
3748 #if 0 // mask by Victor Yu. 12-27-2004
3749 current->state = TASK_INTERRUPTIBLE;
3750 #endif
3751 save_flags(flags);
3752 cli();
3753 outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
3754 #if 0 // mask by Victor Yu. 12-27-2004
3755 schedule_timeout(duration);
3756 #else // add by Victor Yu. 12-27-2004
3757 restore_flags(flags);
3758 timeout = jiffies + (unsigned long)duration;
3759 while ( 1 ) {
3760 current->state = TASK_INTERRUPTIBLE;
3761 schedule_timeout(5);
3762 if ( time_after(jiffies, timeout) )
3763 break;
3765 save_flags(flags);
3766 cli();
3767 #endif
3768 outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
3769 restore_flags(flags);
3772 #if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0)) // add by Victor Yu. 04-28-2006, for 2.6.x
3773 static int mxser_get_modem_info(struct mxser_struct * info,
3774 unsigned int *value)
3776 unsigned char control, status;
3777 unsigned int result;
3778 unsigned long flags;
3780 save_flags(flags);
3781 cli();
3782 control = info->MCR;
3783 status = inb(info->base + UART_MSR);
3784 #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.
3785 if ( status & UART_MSR_ANY_DELTA )
3786 mxser_check_modem_status(info, status);
3787 #endif
3788 restore_flags(flags);
3789 result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
3790 ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
3791 ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
3792 ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
3793 ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
3794 ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
3795 put_to_user(result, value);
3796 return(0);
3799 static int mxser_set_modem_info(struct mxser_struct * info, unsigned int cmd,
3800 unsigned int *value)
3802 int error;
3803 unsigned int arg;
3804 unsigned long flags;
3806 error = verify_area(VERIFY_READ, value, sizeof(int));
3807 if ( error )
3808 return(error);
3809 get_from_user(arg,value);
3810 #if 1 // add by Victor Yu. 12-30-2004
3811 save_flags(flags);
3812 cli();
3813 #endif
3814 switch ( cmd ) {
3815 case TIOCMBIS:
3816 if ( arg & TIOCM_RTS )
3817 info->MCR |= UART_MCR_RTS;
3818 if ( arg & TIOCM_DTR )
3819 info->MCR |= UART_MCR_DTR;
3820 break;
3821 case TIOCMBIC:
3822 if ( arg & TIOCM_RTS )
3823 info->MCR &= ~UART_MCR_RTS;
3824 if ( arg & TIOCM_DTR )
3825 info->MCR &= ~UART_MCR_DTR;
3826 break;
3827 case TIOCMSET:
3828 info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) |
3829 ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) |
3830 ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
3831 break;
3832 default:
3833 #if 1 // add by Victor Yu. 12-30-2004
3834 restore_flags(flags);
3835 #endif
3836 return(-EINVAL);
3838 #if 0 // mask by Victor Yu. 12-30-2004
3839 save_flags(flags);
3840 cli();
3841 #endif
3842 outb(info->MCR, info->base + UART_MCR);
3843 restore_flags(flags);
3844 return(0);
3846 #endif