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
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>
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>
69 #include <asm/system.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"
79 #define MXSERCUMAJOR 35
82 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
83 #include <linux/bios32.h>
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)
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
138 #define MXSER_ISR_PASS_LIMIT 256 // mask by Victor Yu. 02-04-2005
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
155 #define PORTNO(x) (MINOR((x)->device) - (x)->driver.minor_start)
157 #define PORTNO(x) ((x)->index)
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)
165 #define MIN(a,b) ((a) < (b) ? (a) : (b))
172 static char *mxser_brdname
[] = {
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)
182 #ifdef CONFIG_MOXA_SMARTIO_PCIE
191 unsigned short vendor_id
;
192 unsigned short device_id
;
193 unsigned short board_type
;
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
},
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)
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
232 #define RS485_2WIRE_MODE 1
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)
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
260 struct mxser_hwconf
{
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
{
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
;
289 int x_char
; /* xon/xoff character */
291 unsigned short closing_wait
;
292 int IER
; /* Interrupt Enable Register */
293 int MCR
; /* Modem control register */
295 int count
; /* # of fd on device */
296 int blocked_open
; /* # of blocked opens */
298 long session
; /* Session of opening process */
299 long pgrp
; /* pgrp of opening process */
301 unsigned char *xmit_buf
;
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 */
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
321 int rxcnt
[MXSER_PORTS
];
322 int txcnt
[MXSER_PORTS
];
325 struct mxser_mstatus
{
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
];
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
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
*);
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 *);
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
);
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
428 #define MOXA_MUST_GDL_REGISTER 7
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
440 #define MOXA_MUST_EFR_REGISTER 2
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
456 #define MOXA_MUST_XON1_REGISTER 4
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
463 #define MOXA_MUST_XON2_REGISTER 5
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
470 #define MOXA_MUST_XOFF1_REGISTER 6
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
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
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
533 #define MOXA_MUST_EFR_SF_TX1 0x08
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
557 typedef unsigned char UCHAR
;
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); \
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) { \
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) { \
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 )
840 port
+= mxsercfg
[board
].ports
;
843 len
= sprintf(page
, "Ports: %d\n", port
);
845 len
= sprintf(page
, "%d\n", port
);
848 goto end_mxser_read_proc
;
850 len
+= sprintf(page
+len
, "PortNo InBytes OutBytes Speed Opened Interface DataBits Parity CTS DSR DCD RTS DTR\n");
852 for ( board
=0, p
=0; board
<MXSER_BOARDS
; board
++ ) {
853 if ( mxsercfg
[board
].board_type
== -1 )
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
860 len
+= sprintf(page
+len
, "Port%d: %lu %lu", p
, mxvar_log
.rxcnt
[i
], mxvar_log
.txcnt
[i
]);
862 len
+= sprintf(page
+len
, "%lu %lu", mxvar_log
.rxcnt
[i
], mxvar_log
.txcnt
[i
]);
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
869 #define B921600 (B460800 +1)
871 switch( info
->tty
->termios
->c_cflag
& (CBAUD
| CBAUDEX
) ){
872 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE
874 len
+= sprintf(page
+len
, " %d 1", info
->speed
);
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;
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 */
907 if ((info
->flags
& ASYNC_SPD_MASK
) == ASYNC_SPD_SHI
)
910 #ifdef ASYNC_SPD_WARP
911 if ((info
->flags
& ASYNC_SPD_MASK
) == ASYNC_SPD_WARP
)
915 len
+= sprintf(page
+len
, " %d 1", mxvar_baud_table
[j
]);
917 len
+= sprintf(page
+len
, " %d 1", info
->speed
);
919 } else { // not opened
920 #if 0 // mask by Victor Yu. 02-21-2006
921 len
+= sprintf(page
+len
, " 9600 2");
923 len
+= sprintf(page
+len
, " %d 2", info
->speed
);
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
932 switch ( info
->interface
) {
934 len
+= sprintf(page
+len
, " 2");
937 len
+= sprintf(page
+len
, " 3");
940 len
+= sprintf(page
+len
, " 1");
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
;
954 shiftbit
= ((info
->port
%4)+2) * 2;
955 opmode
= inl(info
->opmode_ioaddr
) >> shiftbit
;
957 opmode
&= OP_MODE_MASK
;
960 len
+= sprintf(page
+len
, " 2");
963 len
+= sprintf(page
+len
, " 3");
966 len
+= sprintf(page
+len
, " 1");
973 if ( info
->count
) { // has opened
974 switch ( info
->tty
->termios
->c_cflag
& CSIZE
) {
976 len
+= sprintf(page
+len
, " 5");
979 len
+= sprintf(page
+len
, " 6");
982 len
+= sprintf(page
+len
, " 7");
986 len
+= sprintf(page
+len
, " 8");
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");
998 len
+= sprintf(page
+len
, " 1");
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");
1010 len
+= sprintf(page
+len
, " 3");
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");
1024 len
+= sprintf(page
+len
, " 3");
1025 if ( j
& UART_MSR_DSR
)
1026 len
+= sprintf(page
+len
, " 2");
1028 len
+= sprintf(page
+len
, " 3");
1029 if ( j
& UART_MSR_DCD
)
1030 len
+= sprintf(page
+len
, " 2");
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");
1039 len
+= sprintf(page
+len
, " 3");
1040 if ( j
& UART_MCR_DTR
)
1041 len
+= sprintf(page
+len
, " 2");
1043 len
+= sprintf(page
+len
, " 3");
1046 len
+= sprintf(page
+len
, "\n");
1050 end_mxser_read_proc
:
1051 if ( len
<= (off
+ count
) )
1053 *start
= page
+ off
;
1065 * The MOXA Smartio/Industio serial driver boot-time initialization code!
1067 static int __init
mxser_init_module(void)
1072 printk("Loading module mxser ...\n");
1079 static void __exit
mxser_exit_module(void)
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
;
1097 if(mxsercfg
[i
].board_type
== -1)
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
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
;
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
++ ) {
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");
1138 printk(" max. baud rate up to 921600 bps.\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;
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)");
1185 request_region(hwconf
->vector
,16,"mxser(vector)");
1189 * Allocate the IRQ if necessary
1193 n
= board
*MXSER_PORTS_PER_BOARD
;
1194 info
= &mxvar_table
[n
];
1197 retval
= request_irq(hwconf
->irq
, mxser_interrupt
, IRQ_T(info
),
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
);
1205 restore_flags(flags
);
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
)
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),
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);
1234 outb(0x06, hwconf
->ioaddr
[i
]+2);
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
1246 for ( ; i
<MXSER_PORTS_PER_BOARD
; i
++ ) {
1247 _addr
= ioaddress
+ 8 * i
;
1249 outb(0x06, _addr
+2);
1256 ioaddress
= pci_resource_start(pdev
, 3);
1257 request_region(pci_resource_start(pdev
, 3),
1258 pci_resource_len(pdev
, 3),
1260 hwconf
->vector
= ioaddress
;
1262 // following add by Victor Yu. 01-05-2004
1263 for (i
= 0; i
< hwconf
->ports
; i
++) {
1265 hwconf
->opmode_ioaddr
[i
] = ioaddress
+ 4;
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;
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
)
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;
1301 hwconf
->vector_mask
= 0x0c;
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;
1308 hwconf
->ioaddr
[i
] = CPE_UART3_VA_BASE
+ i
* 32;
1310 hwconf
->baud_base
[i
] = 921600;
1311 hwconf
->MaxCanSetBaudRate
[i
] = 921600;
1312 hwconf
->opmode_ioaddr
[i
] = CPE_UART_MODE_VA_BASE
;
1317 int mxser_init(void)
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
;
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
;
1366 printk("Tty devices major number = %d\n",ttymajor
);
1369 memset(mxvar_table
, 0, MXSER_PORTS
* sizeof(struct mxser_struct
));
1370 memset(&mxvar_log
, 0, sizeof(struct mxser_log
));
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 )
1377 mxser_getcfg(m
,&hwconf
);
1381 n
= sizeof (mxser_pcibrds
)/sizeof (mxser_pciinfo
);
1385 pdev
= pci_find_device(mxser_pcibrds
[b
].vendor_id
,
1386 mxser_pcibrds
[b
].device_id
,
1388 if ( pdev
== NULL
) {
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
);
1400 if ( pci_enable_device(pdev
) ) {
1401 printk("Moxa SmartI/O PCI enable fail !\n");
1404 retval
= mxser_get_PCI_conf(mxser_pcibrds
[b
].board_type
,&hwconf
);
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");
1418 if(mxser_initbrd(m
,&hwconf
)<0)
1420 mxser_getcfg(m
,&hwconf
);
1427 for(i
=m
; i
<MXSER_BOARDS
; i
++){
1428 mxsercfg
[i
].board_type
= -1;
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
1440 printk("Couldn't install MOXA Smartio/Industio family driver !\n");
1444 for(i
=0; i
<MXSER_BOARDS
; i
++){
1445 if(mxsercfg
[i
].board_type
== -1)
1448 free_irq(mxsercfg
[i
].irq
, &mxvar_table
[i
*MXSER_PORTS_PER_BOARD
]);
1457 static void mxser_do_softint(void *private_
)
1459 struct mxser_struct
* info
= (struct mxser_struct
*)private_
;
1460 struct tty_struct
* 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
) ) {
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
;
1484 unsigned long flags
;
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);
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
;
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
);
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
;
1531 #if 1 // add by Victor Yu. 12-28-2004
1532 unsigned long flags
;
1536 if ( line
== MXSER_PORTS
)
1538 if ( (line
< 0) || (line
> MXSER_PORTS
) )
1541 info
= mxvar_table
+ line
;
1545 tty
->driver_data
= info
;
1549 restore_flags(flags
);
1551 if ( !mxvar_tmp_buf
) {
1552 page
= get_zeroed_page(GFP_KERNEL
);
1555 if ( mxvar_tmp_buf
)
1558 mxvar_tmp_buf
= (unsigned char *)page
;
1562 * Start up serial port
1564 retval
= mxser_startup(info
);
1568 retval
= mxser_block_til_ready(tty
, filp
, info
);
1572 #if 0 // mask by Victor Yu. 12-28-2004
1574 #else // add by Victor Yu. 12-28-2004
1578 restore_flags(flags
);
1582 if ( (info
->count
== 1) && (info
->flags
& ASYNC_SPLIT_TERMIOS
) ) {
1583 *tty
->termios
= info
->normal_termios
;
1584 mxser_change_speed(info
, 0);
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;
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
)
1617 if ( tty_hung_up_p(filp
) ) {
1622 #if 1 // add by Victor Yu. 12-28-2004
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
);
1638 if ( --info
->count
< 0 ) {
1639 printk("mxser_close: bad serial port count for ttys%d: %d\n",
1640 info
->port
, info
->count
);
1643 if ( info
->count
) {
1644 restore_flags(flags
);
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.
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
) )
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
);
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
|
1706 wake_up_interruptible(&info
->close_wait
);
1711 static int mxser_write(struct tty_struct
* tty
, int from_user
,
1712 const unsigned char * buf
, int count
)
1715 struct mxser_struct
*info
= (struct mxser_struct
*)tty
->driver_data
;
1716 unsigned long flags
;
1718 if ( !tty
|| !info
->xmit_buf
|| !mxvar_tmp_buf
)
1721 #if 0 // mask by Victor Yu. 10-13-2004
1723 down(&mxvar_tmp_buf_sem
);
1729 c
= MIN(count
, MIN(SERIAL_XMIT_SIZE
- info
->xmit_cnt
- 1,
1730 SERIAL_XMIT_SIZE
- info
->xmit_head
));
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
);
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);
1751 #if 0 // mask by Victor Yu. 10-13-2004
1753 up(&mxvar_tmp_buf_sem
);
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
);
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
)
1776 if ( info
->xmit_cnt
>= SERIAL_XMIT_SIZE
- 1 ) {
1777 restore_flags(flags
);
1781 info
->xmit_buf
[info
->xmit_head
++] = ch
;
1782 info
->xmit_head
&= SERIAL_XMIT_SIZE
- 1;
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
))
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
;
1814 ret
= SERIAL_XMIT_SIZE
- info
->xmit_cnt
- 1;
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
;
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
)
1846 unsigned long flags
;
1847 struct mxser_struct
* info
= (struct mxser_struct
*)tty
->driver_data
;
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
) {
1862 if ( cmd
== MOXA_SET_OP_MODE
) {
1863 error
= verify_area(VERIFY_READ
, (void *)arg
, sizeof(int));
1866 get_from_user(opmode
,(int *)arg
);
1867 if ( opmode
!= RS232_MODE
&& opmode
!= RS485_2WIRE_MODE
&& opmode
!= RS422_MODE
&& opmode
!= RS485_4WIRE_MODE
)
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)
1874 val
= inb(info
->opmode_ioaddr
);
1876 shiftbit
= (p
+2) * 2;
1877 val
= inl(info
->opmode_ioaddr
);
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
);
1884 outb(val
, info
->opmode_ioaddr
);
1887 error
= verify_area(VERIFY_WRITE
, (void *)arg
, sizeof(int));
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)
1895 opmode
= inb(info
->opmode_ioaddr
) >> shiftbit
;
1897 shiftbit
= (p
+2) * 2;
1898 opmode
= inl(info
->opmode_ioaddr
) >> shiftbit
;
1900 opmode
&= OP_MODE_MASK
;
1901 copy_to_user((int*)arg
, &opmode
, sizeof(int));
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
) {
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));
1916 get_from_user(speed
,(int *)arg
);
1917 if ( speed
<= 0 || speed
> info
->MaxCanSetBaudRate
)
1919 if ( !info
->tty
|| !info
->tty
->termios
|| !info
->base
)
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
;
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);
1952 error
= verify_area(VERIFY_WRITE
, (void *)arg
, sizeof(int));
1955 copy_to_user((int*)arg
, &info
->speed
, sizeof(int));
1961 if ( (cmd
!= TIOCGSERIAL
) && (cmd
!= TIOCMIWAIT
) &&
1962 (cmd
!= TIOCGICOUNT
) ) {
1963 if ( tty
->flags
& (1 << TTY_IO_ERROR
) )
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
);
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
);
1978 #endif // LINUX_VERSION_CODE
1979 outb(inb(info
->base
+ UART_LCR
) | UART_LCR_SBC
, info
->base
+ UART_LCR
);
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
);
1985 restore_flags(flags
);
1986 #endif // LINUX_VERSION_CODE
1989 #if 1 // add by Victor Yu. 12-28-2004
1990 case TIOCSBRK
: // start to send break
1991 retval
= tty_check_change(tty
);
1994 tty_wait_until_sent(tty
, 0);
1997 outb(inb(info
->base
+ UART_LCR
) | UART_LCR_SBC
, info
->base
+ UART_LCR
);
1998 restore_flags(flags
);
2000 case TIOCCBRK
: // stop to send break
2003 outb(inb(info
->base
+ UART_LCR
) & ~UART_LCR_SBC
, info
->base
+ UART_LCR
);
2004 restore_flags(flags
);
2007 case TCSBRK
: /* SVID version: non-zero arg --> no break */
2008 retval
= tty_check_change(tty
);
2011 tty_wait_until_sent(tty
, 0);
2013 mxser_send_break(info
, HZ
/4); /* 1/4 second */
2015 case TCSBRKP
: /* support for POSIX tcsendbreak() */
2016 retval
= tty_check_change(tty
);
2019 tty_wait_until_sent(tty
, 0);
2020 mxser_send_break(info
, arg
? arg
*(HZ
/10) : HZ
/4);
2023 error
= verify_area(VERIFY_WRITE
, (void *)arg
, sizeof(long));
2026 put_to_user(C_CLOCAL(tty
) ? 1 : 0, (unsigned long *)arg
);
2029 error
= verify_area(VERIFY_READ
, (void *)arg
, sizeof(long));
2032 get_from_user(templ
,(unsigned long *)arg
);
2034 tty
->termios
->c_cflag
= ((tty
->termios
->c_cflag
& ~CLOCAL
) |
2035 (arg
? CLOCAL
: 0));
2037 #if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0)) // add by Victor Yu. 04-28-2006, for 2.6.x
2039 error
= verify_area(VERIFY_WRITE
, (void *)arg
,
2040 sizeof(unsigned int));
2043 return(mxser_get_modem_info(info
, (unsigned int *)arg
));
2047 return(mxser_set_modem_info(info
, cmd
, (unsigned int *)arg
));
2050 error
= verify_area(VERIFY_WRITE
, (void *)arg
,
2051 sizeof(struct serial_struct
));
2054 return(mxser_get_serial_info(info
, (struct serial_struct
*)arg
));
2056 error
= verify_area(VERIFY_READ
, (void *)arg
,
2057 sizeof(struct serial_struct
));
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));
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
2077 cprev
= info
->icount
; /* note the counters on entry */
2078 restore_flags(flags
);
2080 interruptible_sleep_on(&info
->delta_msr_wait
);
2081 /* see if a signal did it */
2082 if ( signal_pending(current
) ) {
2083 return(-ERESTARTSYS
);
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
)) ) {
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
)) ) {
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
2132 wake_up_interruptible(&info
->delta_msr_wait
);
2137 error
= verify_area(VERIFY_WRITE
, (void *)arg
,
2138 sizeof(struct serial_icounter_struct
));
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
))
2150 if (put_user(cnow
.brk
, &p_cuser
->brk
))
2152 if (put_user(cnow
.overrun
, &p_cuser
->overrun
))
2154 if (put_user(cnow
.buf_overrun
, &p_cuser
->buf_overrun
))
2156 if (put_user(cnow
.parity
, &p_cuser
->parity
))
2158 if (put_user(cnow
.rx
, &p_cuser
->rx
))
2160 if (put_user(cnow
.tx
, &p_cuser
->tx
))
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
);
2171 case MOXA_HighSpeedOn
:
2172 error
= verify_area(VERIFY_WRITE
, (void *)arg
, sizeof(int));
2175 put_to_user(info
->baud_base
!= 115200 ? 1 : 0, (int *)arg
);
2178 return(-ENOIOCTLCMD
);
2183 static int mxser_ioctl_special(unsigned int cmd
, unsigned long arg
)
2185 int error
, i
, result
, status
;
2189 error
= verify_area(VERIFY_WRITE
, (void *)arg
,
2190 sizeof(struct mxser_hwconf
)*4);
2193 copy_to_user((struct mxser_hwconf
*)arg
, mxsercfg
,
2194 sizeof(struct mxser_hwconf
)*4);
2196 case MOXA_GET_MAJOR
:
2197 error
= verify_area(VERIFY_WRITE
, (void *)arg
, sizeof(int));
2200 copy_to_user((int*)arg
, &ttymajor
, sizeof(int));
2203 case MOXA_GET_CUMAJOR
:
2204 error
= verify_area(VERIFY_WRITE
, (void *)arg
, sizeof(int));
2207 copy_to_user((int*)arg
, &calloutmajor
, sizeof(int));
2210 case MOXA_CHKPORTENABLE
:
2211 error
= verify_area(VERIFY_WRITE
, (void *)arg
, sizeof(long));
2215 for ( i
=0; i
<MXSER_PORTS
; i
++ ) {
2216 if ( mxvar_table
[i
].base
)
2219 put_to_user(result
, (unsigned long *)arg
);
2221 case MOXA_GETDATACOUNT
:
2222 error
= verify_area(VERIFY_WRITE
, (void *)arg
,
2223 sizeof(struct mxser_log
));
2226 copy_to_user((struct mxser_log
*)arg
, &mxvar_log
, sizeof(mxvar_log
));
2228 case MOXA_GETMSTATUS
:
2229 error
= verify_area(VERIFY_WRITE
, (void *)arg
,
2230 sizeof(struct mxser_mstatus
) * MXSER_PORTS
);
2234 for(i
=0; i
<MXSER_PORTS
; i
++){
2236 if ( !mxvar_table
[i
].base
){
2237 GMStatus
[i
].dcd
= 0;
2238 GMStatus
[i
].dsr
= 0;
2239 GMStatus
[i
].cts
= 0;
2243 if ( !mxvar_table
[i
].tty
|| !mxvar_table
[i
].tty
->termios
)
2244 GMStatus
[i
].cflag
=mxvar_table
[i
].normal_termios
.c_cflag
;
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;
2252 GMStatus
[i
].dcd
= 0;
2254 if(status
& 0x20/*UART_MSR_DSR*/)
2255 GMStatus
[i
].dsr
= 1;
2257 GMStatus
[i
].dsr
= 0;
2260 if(status
& 0x10/*UART_MSR_CTS*/)
2261 GMStatus
[i
].cts
= 1;
2263 GMStatus
[i
].cts
= 0;
2265 copy_to_user((struct mxser_mstatus
*)arg
, GMStatus
,
2266 sizeof(struct mxser_mstatus
) * MXSER_PORTS
);
2269 return(-ENOIOCTLCMD
);
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
) ) {
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
) ) {
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
) {
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
) ) {
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;
2341 /* Handle sw stopped */
2342 if ( (old_termios
->c_iflag
& IXON
) &&
2343 !(tty
->termios
->c_iflag
& IXON
) ) {
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
;
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
;
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
;
2394 if (info
->type
== PORT_UNKNOWN
)
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
2408 char_time
= (info
->timeout
- HZ
/50) / info
->xmit_fifo_size
;
2409 char_time
= char_time
/ 5;
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
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
);
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
);
2434 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))
2435 set_current_state(TASK_INTERRUPTIBLE
);
2437 current
->state
= TASK_INTERRUPTIBLE
;
2439 schedule_timeout(char_time
);
2440 if (signal_pending(current
))
2442 if (timeout
&& time_after(jiffies
, orig_jiffies
))
2445 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))
2446 set_current_state(TASK_RUNNING
);
2448 current
->state
= TASK_RUNNING
;
2451 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2452 printk("lsr = %d (jiff=%lu)...done\n", lsr
, jiffies
);
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
;
2468 mxser_flush_buffer(tty
);
2469 mxser_shutdown(info
);
2470 #if 0 // mask by Victor Yu. 12-28-2004
2473 info
->flags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
2481 info
->flags
&= ~(ASYNC_NORMAL_ACTIVE
|ASYNC_CALLOUT_ACTIVE
);
2483 info
->flags
&= ~(ASYNC_NORMAL_ACTIVE
);
2486 restore_flags(flags
);
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
)
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
]) ) {
2508 if ( port
== NULL
) {
2511 max
= mxser_numports
[mxsercfg
[i
].board_type
-1];
2514 irqbits
= inb(port
->vector
) & port
->vectormask
;
2515 if ( irqbits
== port
->vectormask
)
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 ) {
2522 for ( i
=0, bits
=4; i
<max
; i
++, irqbits
|= bits
, bits
<<= 1 ) {
2524 if ( irqbits
== port
->vectormask
)
2526 if ( bits
& irqbits
)
2530 // following add by Victor Yu. 09-13-2002
2531 iir
= inb(info
->base
+UART_IIR
);
2532 if ( iir
& UART_IIR_NO_INT
)
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
);
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
);
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
);
2568 msr
= inb(info
->base
+ UART_MSR
);
2569 if ( msr
& UART_MSR_ANY_DELTA
) {
2570 mxser_check_modem_status(info
, msr
);
2575 mxser_transmit_chars(info
);
2577 if ( pass_counter
++ > MXSER_ISR_PASS_LIMIT
) {
2578 break; /* Prevent infinite loops */
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
,
2589 struct tty_struct
* tty
= info
->tty
;
2590 unsigned char ch
, gdl
;
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
;
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
) )
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
);
2613 //cnt = gdl = MIN(gdl, TTY_FLIPBUF_SIZE);
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
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
)
2627 if ( tty
->flip
.count
>= TTY_FLIPBUF_SIZE
)
2631 ch
= inb(info
->base
+ UART_RX
);
2632 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2634 wptr
&= N_TTY_BUF_SIZE_MASK
;
2636 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
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
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
2661 if ( *status
& UART_LSR_BI
) {
2665 if ( *status
& UART_LSR_PE
) {
2666 info
->icount
.parity
++;
2669 if ( *status
& UART_LSR_FE
) {
2670 info
->icount
.frame
++;
2673 if ( *status
& UART_LSR_OE
) {
2674 info
->icount
.overrun
++;
2678 wake_up_interruptible(&info
->delta_msr_wait
);
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
)
2690 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2691 if ( cnt
>= TTY_FLIPBUF_SIZE
)
2694 if ( tty
->flip
.count
>= TTY_FLIPBUF_SIZE
)
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
2703 if ( *status
& UART_LSR_BI
) {
2704 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2707 *tty
->flip
.flag_buf_ptr
++ = TTY_BREAK
;
2710 if ( info
->flags
& ASYNC_SAK
)
2712 } else if ( *status
& UART_LSR_PE
) {
2713 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2716 *tty
->flip
.flag_buf_ptr
++ = TTY_PARITY
;
2718 } else if ( *status
& UART_LSR_FE
) {
2719 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2722 *tty
->flip
.flag_buf_ptr
++ = TTY_FRAME
;
2724 } else if ( *status
& UART_LSR_OE
) {
2725 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2726 *fp
++ = TTY_OVERRUN
;
2728 *tty
->flip
.flag_buf_ptr
++ = TTY_OVERRUN
;
2731 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2734 *tty
->flip
.flag_buf_ptr
++ = 0;
2737 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2739 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2742 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
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
2751 wptr
&= N_TTY_BUF_SIZE_MASK
;
2753 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2756 *tty
->flip
.char_buf_ptr
++ = ch
;
2757 #endif // BYPASS_FLIP
2758 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
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
;
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
;
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
);
2778 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2779 tty_flip_buffer_push(tty
);
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
2788 static inline void mxser_transmit_chars(struct mxser_struct
*info
)
2792 if ( info
->x_char
) {
2793 outb(info
->x_char
, info
->base
+ UART_TX
);
2795 mxvar_log
.txcnt
[info
->port
]++;
2796 /* added by casper 1/11/2000 */
2797 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2804 if ( info
->xmit_buf
== 0 )
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
);
2814 #if 0 // mask by Victor Yu. 10-12-2004
2815 cnt
= info
->xmit_cnt
;
2816 count
= info
->xmit_fifo_size
;
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 )
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
;
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
;
2850 if ( info
->xmit_cnt
< WAKEUP_CHARS
) {
2851 set_bit(MXSER_EVENT_TXLOW
,&info
->event
);
2854 if (schedule_task(&info
->tqueue
) == 0)
2856 queue_task(&info
->tqueue
,&tq_scheduler
);
2858 schedule_work(&info
->tqueue
);
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
,
2870 /* update input line counters */
2871 if ( status
& UART_MSR_TERI
)
2873 if ( status
& UART_MSR_DDSR
)
2875 if ( status
& UART_MSR_DDCD
)
2877 if ( status
& UART_MSR_DCTS
)
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
);
2885 else if ( !((info
->flags
& ASYNC_CALLOUT_ACTIVE
) &&
2886 (info
->flags
& ASYNC_CALLOUT_NOHUP
)) )
2890 set_bit(MXSER_EVENT_HANGUP
,&info
->event
);
2893 if (schedule_task(&info
->tqueue
) == 0)
2896 schedule_work(&info
->tqueue
);
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
);
2911 if (schedule_task(&info
->tqueue
) == 0)
2914 schedule_work(&info
->tqueue
);
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
);
2935 struct wait_queue wait
= { current
, NULL
};
2937 unsigned long flags
;
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
)
2952 return(-ERESTARTSYS
);
2959 * If this is a callout device, then just make sure the normal
2960 * device isn't being used.
2963 if ( tty
->driver
->subtype
== SERIAL_TYPE_CALLOUT
) {
2964 if ( info
->flags
& ASYNC_NORMAL_ACTIVE
)
2966 if ( (info
->flags
& ASYNC_CALLOUT_ACTIVE
) &&
2967 (info
->flags
& ASYNC_SESSION_LOCKOUT
) &&
2968 (info
->session
!= current
->session
) )
2970 if ( (info
->flags
& ASYNC_CALLOUT_ACTIVE
) &&
2971 (info
->flags
& ASYNC_PGRP_LOCKOUT
) &&
2972 (info
->pgrp
!= current
->pgrp
) )
2974 info
->flags
|= ASYNC_CALLOUT_ACTIVE
;
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
)) ) {
2986 if ( info
->flags
& ASYNC_CALLOUT_ACTIVE
)
2989 info
->flags
|= ASYNC_NORMAL_ACTIVE
;
2994 if ( info
->flags
& ASYNC_CALLOUT_ACTIVE
) {
2995 if ( info
->normal_termios
.c_cflag
& CLOCAL
)
2999 if ( tty
->termios
->c_cflag
& CLOCAL
)
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.
3013 add_wait_queue(&info
->open_wait
, &wait
);
3014 #if 0 // mask by Victor Yu. 12-28-2004
3017 if ( !tty_hung_up_p(filp
) )
3019 restore_flags(flags
);
3020 #else // add by Victor Yu. 12-28-2004
3021 if ( !tty_hung_up_p(filp
) ) {
3025 restore_flags(flags
);
3028 info
->blocked_open
++;
3033 if ( !(info
->flags
& ASYNC_CALLOUT_ACTIVE
) )
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
)
3044 retval
= -ERESTARTSYS
;
3051 if ( !(info
->flags
& ASYNC_CALLOUT_ACTIVE
) &&
3052 !(info
->flags
& ASYNC_CLOSING
) &&
3053 (do_clocal
|| (inb(info
->base
+ UART_MSR
) & UART_MSR_DCD
)) )
3055 if ( !(info
->flags
& ASYNC_CLOSING
) &&
3056 (do_clocal
|| (inb(info
->base
+ UART_MSR
) & UART_MSR_DCD
)) )
3059 if ( signal_pending(current
) ) {
3060 retval
= -ERESTARTSYS
;
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
3070 #else // add by Victor Yu. 12-28-2004
3074 restore_flags(flags
);
3077 info
->blocked_open
--;
3080 info
->flags
|= ASYNC_NORMAL_ACTIVE
;
3084 static int mxser_startup(struct mxser_struct
* info
)
3086 unsigned long flags
;
3089 page
= get_zeroed_page(GFP_KERNEL
);
3096 if ( info
->flags
& ASYNC_INITIALIZED
) {
3098 restore_flags(flags
);
3102 if ( !info
->base
|| !info
->type
) {
3104 set_bit(TTY_IO_ERROR
, &info
->tty
->flags
);
3106 restore_flags(flags
);
3109 if ( info
->xmit_buf
)
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
3131 if ( inb(info
->base
+ UART_LSR
) == 0xff ) {
3132 restore_flags(flags
);
3133 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3136 if (capable(CAP_SYS_ADMIN
)) {
3139 set_bit(TTY_IO_ERROR
, &info
->tty
->flags
);
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))
3176 clear_bit(TTY_IO_ERROR
, &info
->tty
->flags
);
3179 test_and_clear_bit(TTY_IO_ERROR
, &info
->tty
->flags
);
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
);
3189 mxser_change_speed(info
, 0);
3191 #if 1 // add by Victor Yu. 12-27-2004
3195 info
->flags
|= ASYNC_INITIALIZED
;
3196 restore_flags(flags
);
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
) )
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
);
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
);
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
)
3257 unsigned cflag
, cval
, fcr
;
3260 unsigned long flags
;
3262 if ( !info
->tty
|| !info
->tty
->termios
)
3264 cflag
= info
->tty
->termios
->c_cflag
;
3265 if ( !(info
->base
) )
3269 #define B921600 (B460800 +1)
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;
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
)
3309 #ifdef ASYNC_SPD_WARP
3310 if ((info
->flags
& ASYNC_SPD_MASK
) == ASYNC_SPD_WARP
)
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
)
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
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
)
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
];
3336 if (!quot
&& old_termios
) {
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;
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
)
3375 #ifdef ASYNC_SPD_WARP
3376 if ((info
->flags
& ASYNC_SPD_MASK
) == ASYNC_SPD_WARP
)
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
)
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
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
)
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
];
3413 info
->timeout
= ((info
->xmit_fifo_size
*HZ
*10*quot
) / info
->baud_base
);
3414 info
->timeout
+= HZ
/50; /* Add .02 seconds of slop */
3419 info
->MCR
|= UART_MCR_DTR
;
3420 outb(info
->MCR
, info
->base
+ UART_MCR
);
3421 restore_flags(flags
);
3425 info
->MCR
&= ~UART_MCR_DTR
;
3426 outb(info
->MCR
, info
->base
+ UART_MCR
);
3427 restore_flags(flags
);
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
)
3440 if ( cflag
& PARENB
)
3441 cval
|= UART_LCR_PARITY
;
3443 #define CMSPAR 010000000000
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
) ) {
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
3461 SET_MOXA_MUST_FIFO_VALUE(info
);
3462 #if 1 // add by Victor Yu. 05-04-2005
3463 restore_flags(flags
);
3467 /* CTS flow control flag and modem status interrupts */
3468 #if 1 // add by Victor Yu. 12-30-2004
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
;
3480 if ( (quot
% info
->speed
) > (info
->speed
/ 2) ) {
3481 quot
/= info
->speed
;
3484 quot
/= info
->speed
;
3486 SET_MOXA_MUST_ENUM_VALUE(info
->base
, quot
);
3488 SET_MOXA_MUST_ENUM_VALUE(info
->base
, 0);
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
;
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
;
3504 unsigned char status
;
3505 #if 0 // mask by Victor Yu. 12-30-2004
3509 status
= inb(info
->base
+ UART_MSR
);
3510 #if 0 // mask by Victor Yu. 12-30-2004
3511 restore_flags(flags
);
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
);
3523 if (schedule_task(&info
->tqueue
) == 0)
3526 schedule_work(&info
->tqueue
);
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
);
3540 info
->flags
&= ~ASYNC_CTS_FLOW
;
3542 #if 0 // add by Victor Yu. 12-27-2004
3546 outb(info
->MCR
, info
->base
+ UART_MCR
);
3547 if ( cflag
& CLOCAL
){
3548 info
->flags
&= ~ASYNC_CHECK_CD
;
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
);
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;
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
;
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
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
;
3597 ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info
->base
);
3599 #if 1 // add by Victor Yu. 01-04-2005
3600 info
->IER
&= ~MOXA_MUST_IER_XINT
;
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
);
3607 if ( I_IXOFF(info
->tty
) ) {
3608 ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info
->base
);
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
);
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
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
;
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
;
3648 copy_to_user(retinfo
, &tmp
, sizeof(*retinfo
));
3652 static int mxser_set_serial_info(struct mxser_struct
* info
,
3653 struct serial_struct
* new_info
)
3655 struct serial_struct new_serial
;
3659 if ( !new_info
|| !info
->base
)
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
) )
3669 flags
= info
->flags
& ASYNC_SPD_MASK
;
3671 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3674 if ( !capable(CAP_SYS_ADMIN
)) {
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
)) )
3681 info
->flags
= ((info
->flags
& ~ASYNC_USR_MASK
) |
3682 (new_serial
.flags
& ASYNC_USR_MASK
));
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;
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);
3706 retval
= mxser_startup(info
);
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
;
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
);
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
;
3748 #if 0 // mask by Victor Yu. 12-27-2004
3749 current
->state
= TASK_INTERRUPTIBLE
;
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
;
3760 current
->state
= TASK_INTERRUPTIBLE
;
3761 schedule_timeout(5);
3762 if ( time_after(jiffies
, timeout
) )
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
;
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
);
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
);
3799 static int mxser_set_modem_info(struct mxser_struct
* info
, unsigned int cmd
,
3800 unsigned int *value
)
3804 unsigned long flags
;
3806 error
= verify_area(VERIFY_READ
, value
, sizeof(int));
3809 get_from_user(arg
,value
);
3810 #if 1 // add by Victor Yu. 12-30-2004
3816 if ( arg
& TIOCM_RTS
)
3817 info
->MCR
|= UART_MCR_RTS
;
3818 if ( arg
& TIOCM_DTR
)
3819 info
->MCR
|= UART_MCR_DTR
;
3822 if ( arg
& TIOCM_RTS
)
3823 info
->MCR
&= ~UART_MCR_RTS
;
3824 if ( arg
& TIOCM_DTR
)
3825 info
->MCR
&= ~UART_MCR_DTR
;
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));
3833 #if 1 // add by Victor Yu. 12-30-2004
3834 restore_flags(flags
);
3838 #if 0 // mask by Victor Yu. 12-30-2004
3842 outb(info
->MCR
, info
->base
+ UART_MCR
);
3843 restore_flags(flags
);