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>
66 #include <asm/system.h>
69 #include <asm/segment.h>
70 #include <asm/bitops.h>
72 #define VERSION_CODE(ver,rel,seq) ((ver << 16) | (rel << 8) | seq)
74 #define MXSER_VERSION "2.0"
76 #define MXSERCUMAJOR 35
79 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
80 #include <linux/bios32.h>
82 #include <linux/pci.h>
83 #endif /* ENABLE_PCI */
85 #include <asm/uaccess.h>
86 #define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)
87 #define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)
89 #ifdef CONFIG_ARCH_IA240 // add by Victor Yu. 02-15-2006, to use embedded UART
124 #define MXSER_EVENT_TXLOW 1
125 #define MXSER_EVENT_HANGUP 2
127 #define SERIAL_DO_RESTART
129 #define MXSER_BOARDS 4 /* Max. boards */
130 #define MXSER_PORTS 32 /* Max. ports */
131 #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board*/
132 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
133 #define MXSER_ISR_PASS_LIMIT 8192 // add by Victor Yu. 02-04-2005
135 #define MXSER_ISR_PASS_LIMIT 256 // mask by Victor Yu. 02-04-2005
138 #define MXSER_ERR_IOADDR -1
139 #define MXSER_ERR_IRQ -2
140 #define MXSER_ERR_IRQ_CONFLIT -3
141 #define MXSER_ERR_VECTOR -4
143 #define SERIAL_TYPE_NORMAL 1
144 #define SERIAL_TYPE_CALLOUT 2
146 #define WAKEUP_CHARS 256
148 #define UART_MCR_AFE 0x20
149 #define UART_LSR_SPECIAL 0x1E
152 #define PORTNO(x) (MINOR((x)->device) - (x)->driver.minor_start)
154 #define PORTNO(x) ((x)->index)
157 #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
159 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
162 #define MIN(a,b) ((a) < (b) ? (a) : (b))
169 static char *mxser_brdname[] = {
173 static int mxser_numports[] = {
178 unsigned short vendor_id;
179 unsigned short device_id;
180 unsigned short board_type;
183 static mxser_pciinfo mxser_pcibrds[] = {
184 {0x1393,0x0001,IA240_BOARD},
191 #define MOXA_GETDATACOUNT (MOXA + 23)
192 #define MOXA_GET_CONF (MOXA + 35)
193 #define MOXA_DIAGNOSE (MOXA + 50)
194 #define MOXA_CHKPORTENABLE (MOXA + 60)
195 #define MOXA_HighSpeedOn (MOXA + 61)
196 #define MOXA_GET_MAJOR (MOXA + 63)
197 #define MOXA_GET_CUMAJOR (MOXA + 64)
198 #define MOXA_GETMSTATUS (MOXA + 65)
200 // following add by Victor Yu. 01-05-2004
201 #define MOXA_SET_OP_MODE (MOXA + 66)
202 #define MOXA_GET_OP_MODE (MOXA + 67)
204 #if 1 // add by Victor Yu. 01-26-2005
205 #define MOXA_UNWAIT (MOXA+200)
209 #define RS485_2WIRE_MODE 1
211 #define RS485_4WIRE_MODE 3
212 #define OP_MODE_MASK 3
213 // above add by Victor Yu. 01-05-2004
215 #define CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE
216 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
217 #define MOXA_SET_SPECIAL_BAUD_RATE (MOXA+68)
218 #define MOXA_GET_SPECIAL_BAUD_RATE (MOXA+69)
221 static int ttymajor=MXSERMAJOR;
222 static int calloutmajor=MXSERCUMAJOR;
223 static int verbose=0;
225 /* Variables for insmod */
226 MODULE_AUTHOR("Victor Yu.");
227 MODULE_DESCRIPTION("MOXA MU860 UART Device Driver");
229 typedef struct _moxa_pci_info {
230 unsigned short busNum;
231 unsigned short devNum;
232 struct pci_dev *pdev; // add by Victor Yu. 06-23-2003
235 struct mxser_hwconf {
242 int ioaddr[MXSER_PORTS_PER_BOARD];
243 int baud_base[MXSER_PORTS_PER_BOARD];
244 moxa_pci_info pciInfo;
245 int IsMoxaMustChipFlag; // add by Victor Yu. 08-30-2002
246 int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 09-04-2002
247 int opmode_ioaddr[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 01-05-2004
250 struct mxser_struct {
252 int base; /* port base address */
253 int irq; /* port using irq no. */
254 int vector; /* port irq vector */
255 int vectormask; /* port vector mask */
256 int rx_trigger; /* Rx fifo trigger level */
257 int baud_base; /* max. speed */
258 int flags; /* defined in tty.h */
259 int type; /* UART type */
260 struct tty_struct * tty;
261 int read_status_mask;
262 int ignore_status_mask;
265 int x_char; /* xon/xoff character */
267 unsigned short closing_wait;
268 int IER; /* Interrupt Enable Register */
269 int MCR; /* Modem control register */
271 int count; /* # of fd on device */
272 int blocked_open; /* # of blocked opens */
274 long session; /* Session of opening process */
275 long pgrp; /* pgrp of opening process */
277 unsigned char *xmit_buf;
281 struct work_struct tqueue;
282 struct termios normal_termios;
283 wait_queue_head_t open_wait;
284 wait_queue_head_t close_wait;
285 wait_queue_head_t delta_msr_wait;
286 struct async_icount icount; /* kernel counters for the 4 input interrupts */
288 int IsMoxaMustChipFlag; // add by Victor Yu. 08-30-2002
289 int MaxCanSetBaudRate; // add by Victor Yu. 09-04-2002
290 int opmode_ioaddr; // add by Victor Yu. 01-05-2004
291 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
298 int rxcnt[MXSER_PORTS];
299 int txcnt[MXSER_PORTS];
302 struct mxser_mstatus{
310 static struct mxser_mstatus GMStatus[MXSER_PORTS];
312 static struct tty_driver mxvar_sdriver;
313 static struct mxser_struct mxvar_table[MXSER_PORTS];
314 static struct termios * mxvar_termios[MXSER_PORTS+1];
315 static struct termios * mxvar_termios_locked[MXSER_PORTS+1];
316 static struct mxser_log mxvar_log;
317 static int mxvar_diagflag;
319 * mxvar_tmp_buf is used as a temporary buffer by serial_write. We need
320 * to lock it in case the memcpy_fromfs blocks while swapping in a page,
321 * and some other program tries to do a serial write at the same time.
322 * Since the lock will only come under contention when the system is
323 * swapping and available memory is low, it makes sense to share one
324 * buffer across all the serial ports, since it significantly saves
325 * memory if large numbers of serial ports are open.
327 static unsigned char * mxvar_tmp_buf;
328 static struct semaphore mxvar_tmp_buf_sem;
331 * This is used to figure out the divisor speeds and the timeouts
333 #define B50_INDEX 1 // add by Victor Yu. 08-12-2004
334 static int mxvar_baud_table[] = {
335 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
336 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 0 };
337 #define BAUD_TABLE_NO (sizeof(mxvar_baud_table)/sizeof(int))
339 struct mxser_hwconf mxsercfg[MXSER_BOARDS];
344 static void mxser_getcfg(int board,struct mxser_hwconf *hwconf);
345 int mxser_init(void);
346 static int mxser_get_PCI_conf(int ,int ,int ,struct mxser_hwconf *);
347 static void mxser_do_softint(void *);
348 static int mxser_open(struct tty_struct *, struct file *);
349 static void mxser_close(struct tty_struct *, struct file *);
350 static int mxser_write(struct tty_struct *, int, const unsigned char *, int);
351 static int mxser_write_room(struct tty_struct *);
352 static void mxser_flush_buffer(struct tty_struct *);
353 static int mxser_chars_in_buffer(struct tty_struct *);
354 static void mxser_flush_chars(struct tty_struct *);
355 static void mxser_put_char(struct tty_struct *, unsigned char);
356 static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);
357 static int mxser_ioctl_special(unsigned int, unsigned long);
358 static void mxser_throttle(struct tty_struct *);
359 static void mxser_unthrottle(struct tty_struct *);
360 static void mxser_set_termios(struct tty_struct *, struct termios *);
361 static void mxser_stop(struct tty_struct *);
362 static void mxser_start(struct tty_struct *);
363 static void mxser_hangup(struct tty_struct *);
364 static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *);
365 static inline void mxser_receive_chars(struct mxser_struct *, int *);
366 static inline void mxser_transmit_chars(struct mxser_struct *);
367 static inline void mxser_check_modem_status(struct mxser_struct *, int);
368 static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
369 static int mxser_startup(struct mxser_struct *);
370 static void mxser_shutdown(struct mxser_struct *);
371 static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios);
372 static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct *);
373 static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);
374 static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *);
375 static void mxser_send_break(struct mxser_struct *, int);
376 static int mxser_get_modem_info(struct mxser_struct *, unsigned int *);
377 static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);
378 static void mxser_wait_until_sent(struct tty_struct *tty, int timeout);
381 // follwoing is modified by Victor Yu. 08-15-2002
383 // follow just for Moxa Must chip define.
385 // when LCR register (offset 0x03) write following value,
386 // the Must chip will enter enchance mode. And write value
387 // on EFR (offset 0x02) bit 6,7 to change bank.
388 #define MOXA_MUST_ENTER_ENCHANCE 0xBF
390 // when enhance mode enable, access on general bank register
391 #define MOXA_MUST_GDL_REGISTER 7
392 #define MOXA_MUST_GDL_MASK 0x7F
393 #define MOXA_MUST_GDL_HAS_BAD_DATA 0x80
395 #define MOXA_MUST_LSR_RERR 0x80 // error in receive FIFO
396 // enchance register bank select and enchance mode setting register
397 // when LCR register equal to 0xBF
398 #define MOXA_MUST_EFR_REGISTER 2
399 // enchance mode enable
400 #define MOXA_MUST_EFR_EFRB_ENABLE 0x10
401 // enchance reister bank set 0, 1, 2
402 #define MOXA_MUST_EFR_BANK0 0x00
403 #define MOXA_MUST_EFR_BANK1 0x40
404 #define MOXA_MUST_EFR_BANK2 0x80
405 #define MOXA_MUST_EFR_BANK3 0xC0
406 #define MOXA_MUST_EFR_BANK_MASK 0xC0
408 // set XON1 value register, when LCR=0xBF and change to bank0
409 #define MOXA_MUST_XON1_REGISTER 4
411 // set XON2 value register, when LCR=0xBF and change to bank0
412 #define MOXA_MUST_XON2_REGISTER 5
414 // set XOFF1 value register, when LCR=0xBF and change to bank0
415 #define MOXA_MUST_XOFF1_REGISTER 6
417 // set XOFF2 value register, when LCR=0xBF and change to bank0
418 #define MOXA_MUST_XOFF2_REGISTER 7
420 #define MOXA_MUST_RBRTL_REGISTER 4
421 #define MOXA_MUST_RBRTH_REGISTER 5
422 #define MOXA_MUST_RBRTI_REGISTER 6
423 #define MOXA_MUST_THRTL_REGISTER 7
424 #define MOXA_MUST_ENUM_REGISTER 4
425 #define MOXA_MUST_HWID_REGISTER 5
426 #define MOXA_MUST_ECR_REGISTER 6
427 #define MOXA_MUST_CSR_REGISTER 7
429 // good data mode enable
430 #define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20
431 // only good data put into RxFIFO
432 #define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10
434 // enable CTS interrupt
435 #define MOXA_MUST_IER_ECTSI 0x80
436 // eanble RTS interrupt
437 #define MOXA_MUST_IER_ERTSI 0x40
438 // enable Xon/Xoff interrupt
439 #define MOXA_MUST_IER_XINT 0x20
440 // enable GDA interrupt
441 #define MOXA_MUST_IER_EGDAI 0x10
443 #define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI)
445 // GDA interrupt pending
446 #define MOXA_MUST_IIR_GDA 0x1C
447 #define MOXA_MUST_IIR_RDA 0x04
448 #define MOXA_MUST_IIR_RTO 0x0C
449 #define MOXA_MUST_IIR_LSR 0x06
451 // recieved Xon/Xoff or specical interrupt pending
452 #define MOXA_MUST_IIR_XSC 0x10
454 // RTS/CTS change state interrupt pending
455 #define MOXA_MUST_IIR_RTSCTS 0x20
456 #define MOXA_MUST_IIR_MASK 0x3E
458 #define MOXA_MUST_MCR_XON_FLAG 0x40
459 #define MOXA_MUST_MCR_XON_ANY 0x80
460 #define MOXA_MUST_HARDWARE_ID 0x01
461 #define MOXA_MUST_HARDWARE_ID1 0x02
463 // software flow control on chip mask value
464 #define MOXA_MUST_EFR_SF_MASK 0x0F
466 #define MOXA_MUST_EFR_SF_TX1 0x08
468 #define MOXA_MUST_EFR_SF_TX2 0x04
469 // send Xon1,Xon2/Xoff1,Xoff2
470 #define MOXA_MUST_EFR_SF_TX12 0x0C
471 // don't send Xon/Xoff
472 #define MOXA_MUST_EFR_SF_TX_NO 0x00
473 // Tx software flow control mask
474 #define MOXA_MUST_EFR_SF_TX_MASK 0x0C
475 // don't receive Xon/Xoff
476 #define MOXA_MUST_EFR_SF_RX_NO 0x00
477 // receive Xon1/Xoff1
478 #define MOXA_MUST_EFR_SF_RX1 0x02
479 // receive Xon2/Xoff2
480 #define MOXA_MUST_EFR_SF_RX2 0x01
481 // receive Xon1,Xon2/Xoff1,Xoff2
482 #define MOXA_MUST_EFR_SF_RX12 0x03
483 // Rx software flow control mask
484 #define MOXA_MUST_EFR_SF_RX_MASK 0x03
486 #define MOXA_MUST_MIN_XOFFLIMIT 66
487 #define MOXA_MUST_MIN_XONLIMIT 20
490 typedef unsigned char UCHAR;
493 #define CHECK_MOXA_MUST_XOFFLIMIT(info) { \
494 if ( (info)->IsMoxaMustChipFlag && \
495 (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) { \
496 (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT; \
497 (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT; \
501 #define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
502 UCHAR __oldlcr, __efr; \
503 __oldlcr = inb((baseio)+UART_LCR); \
504 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
505 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
506 __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \
507 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
508 outb(__oldlcr, (baseio)+UART_LCR); \
511 #define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \
512 UCHAR __oldlcr, __efr; \
513 __oldlcr = inb((baseio)+UART_LCR); \
514 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
515 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
516 __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \
517 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
518 outb(__oldlcr, (baseio)+UART_LCR); \
521 #define SET_MOXA_MUST_XON1_VALUE(baseio, Value) { \
522 UCHAR __oldlcr, __efr; \
523 __oldlcr = inb((baseio)+UART_LCR); \
524 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
525 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
526 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
527 __efr |= MOXA_MUST_EFR_BANK0; \
528 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
529 outb((UCHAR)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \
530 outb(__oldlcr, (baseio)+UART_LCR); \
533 #define SET_MOXA_MUST_XON2_VALUE(baseio, Value) { \
534 UCHAR __oldlcr, __efr; \
535 __oldlcr = inb((baseio)+UART_LCR); \
536 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
537 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
538 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
539 __efr |= MOXA_MUST_EFR_BANK0; \
540 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
541 outb((UCHAR)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \
542 outb(__oldlcr, (baseio)+UART_LCR); \
545 #define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) { \
546 UCHAR __oldlcr, __efr; \
547 __oldlcr = inb((baseio)+UART_LCR); \
548 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
549 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
550 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
551 __efr |= MOXA_MUST_EFR_BANK0; \
552 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
553 outb((UCHAR)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \
554 outb(__oldlcr, (baseio)+UART_LCR); \
557 #define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) { \
558 UCHAR __oldlcr, __efr; \
559 __oldlcr = inb((baseio)+UART_LCR); \
560 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
561 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
562 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
563 __efr |= MOXA_MUST_EFR_BANK0; \
564 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
565 outb((UCHAR)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER); \
566 outb(__oldlcr, (baseio)+UART_LCR); \
569 #define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) { \
570 UCHAR __oldlcr, __efr; \
571 __oldlcr = inb((baseio)+UART_LCR); \
572 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
573 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
574 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
575 __efr |= MOXA_MUST_EFR_BANK1; \
576 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
577 outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER); \
578 outb(__oldlcr, (baseio)+UART_LCR); \
581 #define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) { \
582 UCHAR __oldlcr, __efr; \
583 __oldlcr = inb((baseio)+UART_LCR); \
584 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
585 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
586 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
587 __efr |= MOXA_MUST_EFR_BANK1; \
588 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
589 outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER); \
590 outb(__oldlcr, (baseio)+UART_LCR); \
593 #define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) { \
594 UCHAR __oldlcr, __efr; \
595 __oldlcr = inb((baseio)+UART_LCR); \
596 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
597 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
598 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
599 __efr |= MOXA_MUST_EFR_BANK1; \
600 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
601 outb((UCHAR)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER); \
602 outb(__oldlcr, (baseio)+UART_LCR); \
605 #define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) { \
606 UCHAR __oldlcr, __efr; \
607 __oldlcr = inb((baseio)+UART_LCR); \
608 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
609 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
610 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
611 __efr |= MOXA_MUST_EFR_BANK1; \
612 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
613 outb((UCHAR)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER); \
614 outb(__oldlcr, (baseio)+UART_LCR); \
617 #define MOXA_MUST_RBRL_VALUE 4
618 #define SET_MOXA_MUST_FIFO_VALUE(info) { \
619 UCHAR __oldlcr, __efr; \
620 __oldlcr = inb((info)->base+UART_LCR); \
621 outb(MOXA_MUST_ENTER_ENCHANCE, (info)->base+UART_LCR); \
622 __efr = inb((info)->base+MOXA_MUST_EFR_REGISTER); \
623 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
624 __efr |= MOXA_MUST_EFR_BANK1; \
625 outb(__efr, (info)->base+MOXA_MUST_EFR_REGISTER); \
626 outb((UCHAR)0, (info)->base+MOXA_MUST_THRTL_REGISTER); \
627 outb((UCHAR)((info)->rx_trigger), (info)->base+MOXA_MUST_RBRTH_REGISTER); \
629 outb((UCHAR)((info)->rx_trigger/4), \
630 (info)->base+MOXA_MUST_RBRTL_REGISTER); \
632 if ( (info)->rx_trigger <= MOXA_MUST_RBRL_VALUE ) { \
633 outb((UCHAR)0, (info)->base+MOXA_MUST_RBRTI_REGISTER); \
634 outb((UCHAR)0, (info)->base+MOXA_MUST_RBRTL_REGISTER); \
636 outb((UCHAR)((info)->rx_trigger-MOXA_MUST_RBRL_VALUE), \
637 (info)->base+MOXA_MUST_RBRTI_REGISTER); \
638 outb((UCHAR)((info)->rx_trigger-MOXA_MUST_RBRL_VALUE), \
639 (info)->base+MOXA_MUST_RBRTL_REGISTER); \
641 outb(__oldlcr, (info)->base+UART_LCR); \
644 #define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) { \
645 UCHAR __oldlcr, __efr; \
646 __oldlcr = inb((baseio)+UART_LCR); \
647 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
648 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
649 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
650 __efr |= MOXA_MUST_EFR_BANK2; \
651 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
652 outb((UCHAR)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \
653 outb(__oldlcr, (baseio)+UART_LCR); \
656 #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) { \
657 UCHAR __oldlcr, __efr; \
658 __oldlcr = inb((baseio)+UART_LCR); \
659 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
660 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
661 __efr &= ~MOXA_MUST_EFR_BANK_MASK; \
662 __efr |= MOXA_MUST_EFR_BANK2; \
663 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
664 *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \
665 outb(__oldlcr, (baseio)+UART_LCR); \
668 #define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) { \
669 UCHAR __oldlcr, __efr; \
670 __oldlcr = inb((baseio)+UART_LCR); \
671 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
672 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
673 __efr &= ~MOXA_MUST_EFR_SF_MASK; \
674 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
675 outb(__oldlcr, (baseio)+UART_LCR); \
678 #define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
679 UCHAR __oldlcr, __efr; \
680 __oldlcr = inb((baseio)+UART_LCR); \
681 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
682 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
683 __efr &= ~MOXA_MUST_EFR_SF_MASK; \
684 __efr |= MOXA_MUST_EFR_SF_TX1; \
685 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
686 outb(__oldlcr, (baseio)+UART_LCR); \
689 #define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
690 UCHAR __oldlcr, __efr; \
691 __oldlcr = inb((baseio)+UART_LCR); \
692 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
693 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
694 __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \
695 __efr |= MOXA_MUST_EFR_SF_TX1; \
696 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
697 outb(__oldlcr, (baseio)+UART_LCR); \
700 #define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \
701 UCHAR __oldlcr, __efr; \
702 __oldlcr = inb((baseio)+UART_LCR); \
703 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
704 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
705 __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \
706 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
707 outb(__oldlcr, (baseio)+UART_LCR); \
710 #define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
711 UCHAR __oldlcr, __efr; \
712 __oldlcr = inb((baseio)+UART_LCR); \
713 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
714 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
715 __efr &= ~MOXA_MUST_EFR_SF_MASK; \
716 __efr |= MOXA_MUST_EFR_SF_RX1; \
717 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
718 outb(__oldlcr, (baseio)+UART_LCR); \
721 #define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
722 UCHAR __oldlcr, __efr; \
723 __oldlcr = inb((baseio)+UART_LCR); \
724 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
725 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
726 __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \
727 __efr |= MOXA_MUST_EFR_SF_RX1; \
728 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
729 outb(__oldlcr, (baseio)+UART_LCR); \
732 #define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
733 UCHAR __oldlcr, __efr; \
734 __oldlcr = inb((baseio)+UART_LCR); \
735 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
736 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
737 __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \
738 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
739 outb(__oldlcr, (baseio)+UART_LCR); \
742 #define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \
743 UCHAR __oldlcr, __efr; \
744 __oldlcr = inb((baseio)+UART_LCR); \
745 outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \
746 __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \
747 __efr &= ~MOXA_MUST_EFR_SF_MASK; \
748 __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1); \
749 outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \
750 outb(__oldlcr, (baseio)+UART_LCR); \
753 #define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \
755 __oldmcr = inb((baseio)+UART_MCR); \
756 __oldmcr |= MOXA_MUST_MCR_XON_ANY; \
757 outb(__oldmcr, (baseio)+UART_MCR); \
760 #define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \
762 __oldmcr = inb((baseio)+UART_MCR); \
763 __oldmcr &= ~MOXA_MUST_MCR_XON_ANY; \
764 outb(__oldmcr, (baseio)+UART_MCR); \
767 #define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER)
770 static int CheckIsMoxaMust(int io)
774 outb(0, io+UART_LCR);
775 DISABLE_MOXA_MUST_ENCHANCE_MODE(io);
776 oldmcr = inb(io+UART_MCR);
777 outb(0, io+UART_MCR);
778 SET_MOXA_MUST_XON1_VALUE(io, 0x11);
779 if ( (hwid=inb(io+UART_MCR)) != 0 ) {
780 outb(oldmcr, io+UART_MCR);
783 GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
784 if ( hwid != MOXA_MUST_HARDWARE_ID && hwid != MOXA_MUST_HARDWARE_ID1 )
786 //return(1); // mask by Victor Yu. 02-10-2004
787 return((int)hwid); // add by Victor Yu. 02-10-2004
790 // above is modified by Victor Yu. 08-15-2002
793 * The MOXA Smartio/Industio serial driver boot-time initialization code!
795 static int __init mxser_init_module(void)
800 printk("Loading module mxser ...\n");
807 static void __exit mxser_exit_module(void)
813 printk("Unloading module mxser ...\n");
814 #if 1 // mask by Victor Yu. 11-22-2005
815 if ((err |= tty_unregister_driver(&mxvar_sdriver)))
816 printk("Couldn't unregister MOXA Smartio/Industio family serial driver\n");
817 #else // add by Victor Yu. 11-22-2005
818 put_tty_driver(&mxvar_sdriver);
821 for(i=0; i<MXSER_BOARDS; i++){
822 struct pci_dev *pdev;
823 if(mxsercfg[i].board_type == -1)
826 free_irq(mxsercfg[i].irq, &mxvar_table[i*MXSER_PORTS_PER_BOARD]);
827 #if 1 // mask by Victor Yu. 11-22-2005
828 pdev = mxsercfg[i].pciInfo.pdev;
829 release_region(pci_resource_start(pdev, 2),
830 pci_resource_len(pdev, 2));
831 release_region(pci_resource_start(pdev, 3),
832 pci_resource_len(pdev, 3));
842 module_init(mxser_init_module);
843 module_exit(mxser_exit_module);
845 int mxser_initbrd(int board,struct mxser_hwconf *hwconf)
847 struct mxser_struct * info;
852 init_MUTEX(&mxvar_tmp_buf_sem);
853 n = board*MXSER_PORTS_PER_BOARD;
854 info = &mxvar_table[n];
855 for ( i=0; i<hwconf->ports; i++, n++, info++ ) {
857 printk(" ttyM%d/cum%d at 0x%04x ", n, n, hwconf->ioaddr[i]);
858 if ( hwconf->baud_base[i] == 115200 )
859 printk(" max. baud rate up to 115200 bps.\n");
861 printk(" max. baud rate up to 921600 bps.\n");
864 info->base = hwconf->ioaddr[i];
865 info->irq = hwconf->irq;
866 info->vector = hwconf->vector;
867 info->vectormask = hwconf->vector_mask;
868 info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; // add by Victor Yu. 01-05-2004
870 // following add by Victor Yu. 08-30-2002
871 // Moxa Must UART support FIFO is 64bytes for Tx/Rx
872 // but receive FIFO just can set up to 62 will be OK.
873 info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag;
874 //if ( hwconf->IsMoxaMustChipFlag ) // mask by Victor Yu. 02-10-2004
875 if ( hwconf->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID ) {
876 info->rx_trigger = 56;
877 } else if ( hwconf->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID1 ) {
878 #if 1 // add by Victor 02-01-2005
879 info->rx_trigger = 120;
881 info->rx_trigger = 1;
884 // above add by Victor Yu. 08-30-2002
885 info->rx_trigger = 14;
887 info->baud_base = hwconf->baud_base[i];
888 info->flags = ASYNC_SHARE_IRQ;
889 info->type = hwconf->uart_type;
890 if ( (info->type == PORT_16450) || (info->type == PORT_8250) )
891 info->xmit_fifo_size = 1;
893 info->xmit_fifo_size = 16;
895 // following add by Victor Yu. 08-30-2002
896 // if ( info->IsMoxaMustChipFlag ) { // mask by Victor Yu. 02-10-2004
897 if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID ) {
898 info->xmit_fifo_size = 64;
899 ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base);
900 } else if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID1 ) {
901 info->xmit_fifo_size = 128;
902 ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base);
904 info->MaxCanSetBaudRate = hwconf->MaxCanSetBaudRate[i];
905 // above add by Victor Yu. 08-30-2002
907 info->custom_divisor = hwconf->baud_base[i] * 16;
908 info->close_delay = 5*HZ/10;
909 info->closing_wait = 30*HZ;
910 INIT_WORK(&info->tqueue, mxser_do_softint, info);
911 info->normal_termios = mxvar_sdriver.init_termios;
912 init_waitqueue_head(&info->open_wait);
913 init_waitqueue_head(&info->close_wait);
914 init_waitqueue_head(&info->delta_msr_wait);
915 info->icount.rx = info->icount.tx = 0;
916 info->icount.cts = info->icount.dsr =
917 info->icount.dsr = info->icount.dcd = 0;
918 info->icount.frame = info->icount.overrun =
919 info->icount.brk = info->icount.parity = 0;
920 info->icount.buf_overrun = 0;
921 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add b Victor Yu. 08-12-2004
926 #if 1 // mask by Victor Yu. 11-22-2005
927 request_region(hwconf->ioaddr[0],8*hwconf->ports,"mxser(io)");
928 if ((hwconf->pciInfo.busNum == 0)&&(hwconf->pciInfo.devNum == 0))
929 request_region(hwconf->vector,1,"mxser(vector)");
931 request_region(hwconf->vector,16,"mxser(vector)");
935 * Allocate the IRQ if necessary
939 n = board*MXSER_PORTS_PER_BOARD;
940 info = &mxvar_table[n];
943 retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info),
946 restore_flags(flags);
947 printk("Board %d: %s", board, mxser_brdname[hwconf->board_type-1]);
948 printk(" Request irq fail,IRQ (%d) may be conflit with another device.\n",info->irq);
951 restore_flags(flags);
956 static void mxser_getcfg(int board,struct mxser_hwconf *hwconf)
958 mxsercfg[board] = *hwconf;
961 static int mxser_get_PCI_conf(int busnum,int devnum,int board_type,struct mxser_hwconf *hwconf)
964 unsigned int ioaddress;
965 struct pci_dev *pdev=hwconf->pciInfo.pdev;
967 hwconf->board_type = board_type;
968 hwconf->ports = mxser_numports[board_type-1];
969 ioaddress = pci_resource_start(pdev, 2);
970 request_region(pci_resource_start(pdev, 2),
971 pci_resource_len(pdev, 2),
973 for (i = 0; i < hwconf->ports; i++) {
974 hwconf->ioaddr[i] = ioaddress + 8*i;
976 // disable the interrupt
977 outb(0, hwconf->ioaddr[i]+1);
979 outb(0x06, hwconf->ioaddr[i]+2);
981 inb(hwconf->ioaddr[i]+2);
982 inb(hwconf->ioaddr[i]+6);
983 inb(hwconf->ioaddr[i]+5);
984 inb(hwconf->ioaddr[i]);
985 #if 0 // mask by Victor Yu. 12-28-2005
986 if ( board_type == MXSER_BOARD_RC7000 )
987 hwconf->MaxCanSetBaudRate[i] = 921600;
989 hwconf->MaxCanSetBaudRate[i] = 230400;
990 #else // add by Victor Yu. 12-28-2005
991 hwconf->MaxCanSetBaudRate[i] = 921600;
995 ioaddress = pci_resource_start(pdev, 3);
996 request_region(pci_resource_start(pdev, 3),
997 pci_resource_len(pdev, 3),
999 hwconf->vector = ioaddress;
1001 // following add by Victor Yu. 01-05-2004
1002 for (i = 0; i < hwconf->ports; i++) {
1004 hwconf->opmode_ioaddr[i] = ioaddress + 4;
1006 hwconf->opmode_ioaddr[i] = ioaddress + 0x0c;
1008 outb(0, ioaddress+4); // default set to RS232 mode
1009 outb(0, ioaddress+0x0c); //default set to RS232 mode
1010 // above add by Victor Yu. 01-05-2004
1012 hwconf->irq = hwconf->pciInfo.pdev->irq;
1014 // following add by Victor Yu. 08-30-2002
1015 hwconf->IsMoxaMustChipFlag = CheckIsMoxaMust(hwconf->ioaddr[0]);
1016 // above add by Victor Yu. 08-30-2002
1018 hwconf->uart_type = PORT_16550A;
1019 hwconf->vector_mask = 0;
1020 for (i = 0; i < hwconf->ports; i++) {
1021 hwconf->vector_mask |= (1<<i);
1022 hwconf->baud_base[i] = 921600;
1026 #if 0 // mask by Victor Yu. 12-22-2005
1027 static void uc7110_hw_set(struct mxser_hwconf *hwconf)
1031 hwconf->board_type = UC7110_BOARD;
1033 hwconf->irq = IRQ_UART;
1034 hwconf->vector = CPE_UART_INT_VEC_BASE;
1035 hwconf->vector_mask = 0x3c;
1036 hwconf->uart_type = PORT_16550A;
1037 hwconf->IsMoxaMustChipFlag = MOXA_MUST_HARDWARE_ID1;
1038 for ( i=0; i<4; i++ ) {
1039 hwconf->ioaddr[i] = CPE_UART3_BASE + i * 32;
1040 hwconf->baud_base[i] = 921600;
1041 hwconf->MaxCanSetBaudRate[i] = 921600;
1042 hwconf->opmode_ioaddr[i] = CPE_UART_MODE_BASE;
1047 int mxser_init(void)
1049 int i, m, retval, b;
1051 struct pci_dev *pdev=NULL;
1053 unsigned char busnum,devnum;
1054 struct mxser_hwconf hwconf;
1056 printk("MOXA MU860 UART Device Driver version %s\n",MXSER_VERSION);
1058 /* Initialize the tty_driver structure */
1059 memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));
1060 mxvar_sdriver.magic = TTY_DRIVER_MAGIC;
1061 mxvar_sdriver.name = "ttyM";
1062 mxvar_sdriver.major = ttymajor;
1063 mxvar_sdriver.minor_start = 0;
1064 mxvar_sdriver.num = MXSER_PORTS + 1;
1065 mxvar_sdriver.type = TTY_DRIVER_TYPE_SERIAL;
1066 mxvar_sdriver.subtype = SERIAL_TYPE_NORMAL;
1067 mxvar_sdriver.init_termios = tty_std_termios;
1068 mxvar_sdriver.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
1069 mxvar_sdriver.flags = TTY_DRIVER_REAL_RAW;
1070 mxvar_sdriver.refcount = 0;
1071 mxvar_sdriver.termios = mxvar_termios;
1072 mxvar_sdriver.termios_locked = mxvar_termios_locked;
1074 mxvar_sdriver.open = mxser_open;
1075 mxvar_sdriver.close = mxser_close;
1076 mxvar_sdriver.write = mxser_write;
1077 mxvar_sdriver.put_char = mxser_put_char;
1078 mxvar_sdriver.flush_chars = mxser_flush_chars;
1079 mxvar_sdriver.write_room = mxser_write_room;
1080 mxvar_sdriver.chars_in_buffer = mxser_chars_in_buffer;
1081 mxvar_sdriver.flush_buffer = mxser_flush_buffer;
1082 mxvar_sdriver.ioctl = mxser_ioctl;
1083 mxvar_sdriver.throttle = mxser_throttle;
1084 mxvar_sdriver.unthrottle = mxser_unthrottle;
1085 mxvar_sdriver.set_termios = mxser_set_termios;
1086 mxvar_sdriver.stop = mxser_stop;
1087 mxvar_sdriver.start = mxser_start;
1088 mxvar_sdriver.hangup = mxser_hangup;
1089 mxvar_sdriver.wait_until_sent = mxser_wait_until_sent;
1091 printk("Tty devices major number = %d\n",ttymajor);
1094 memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct));
1095 memset(&mxvar_log, 0, sizeof(struct mxser_log));
1098 #if 0 // mask by Victor Yu. 12-22-2005
1099 uc7110_hw_set(&hwconf);
1100 if ( mxser_initbrd(m,&hwconf) < 0 )
1102 mxser_getcfg(m,&hwconf);
1105 #if 0 // mask by Victor Yu. 12-28-2005 For Linux 2.6.x
1106 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
1107 if (pcibios_present()) {
1109 if (pci_present()) {
1111 #else // add by Victor Yu. 12-28-2005
1114 n = sizeof (mxser_pcibrds)/sizeof (mxser_pciinfo);
1118 pdev = pci_find_device(mxser_pcibrds[b].vendor_id,
1119 mxser_pcibrds[b].device_id,
1121 #if 0 // mask by Victor Yu. 12-28-2005, for Linux 2.6.x
1122 if (pcibios_find_device(mxser_pcibrds[b].vendor_id,
1123 mxser_pcibrds[b].device_id,
1131 hwconf.pciInfo.busNum = busnum;
1132 hwconf.pciInfo.devNum = devnum;
1133 hwconf.pciInfo.pdev = pdev;
1134 printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",mxser_brdname[mxser_pcibrds[b].board_type-1],busnum,devnum >> 3);
1136 #else // add by Victor Yu. 12-28-2005
1137 if ( pdev == NULL ) {
1141 hwconf.pciInfo.busNum = pdev->bus->number;
1142 hwconf.pciInfo.devNum = pdev->devfn;
1143 hwconf.pciInfo.pdev = pdev;
1144 printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",mxser_brdname[mxser_pcibrds[b].board_type-1],pdev->bus->number,pdev->devfn >> 3);
1146 if ( m >= MXSER_BOARDS) {
1147 printk("Too many Smartio/Industio family boards find (maximum %d),board not configured\n",MXSER_BOARDS);
1150 if ( pci_enable_device(pdev) ) {
1151 printk("Moxa SmartI/O PCI enable fail !\n");
1154 retval = mxser_get_PCI_conf(busnum,devnum,
1155 mxser_pcibrds[b].board_type,&hwconf);
1157 if (retval == MXSER_ERR_IRQ)
1158 printk("Invalid interrupt number,board not configured\n");
1159 else if (retval == MXSER_ERR_IRQ_CONFLIT)
1160 printk("Invalid interrupt number,board not configured\n");
1161 else if (retval == MXSER_ERR_VECTOR)
1162 printk("Invalid interrupt vector,board not configured\n");
1163 else if (retval == MXSER_ERR_IOADDR)
1164 printk("Invalid I/O address,board not configured\n");
1169 if(mxser_initbrd(m,&hwconf)<0)
1171 mxser_getcfg(m,&hwconf);
1177 for(i=m; i<MXSER_BOARDS; i++){
1178 mxsercfg[i].board_type = -1;
1184 if ( !(ret1=tty_register_driver(&mxvar_sdriver)) ){
1187 printk("Couldn't install MOXA Smartio/Industio family driver !\n");
1191 for(i=0; i<MXSER_BOARDS; i++){
1192 if(mxsercfg[i].board_type == -1)
1195 free_irq(mxsercfg[i].irq, &mxvar_table[i*MXSER_PORTS_PER_BOARD]);
1204 static void mxser_do_softint(void *private_)
1206 struct mxser_struct * info = (struct mxser_struct *)private_;
1207 struct tty_struct * tty;
1212 if ( test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event) ) {
1213 if ( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1214 tty->ldisc.write_wakeup )
1215 (tty->ldisc.write_wakeup)(tty);
1216 wake_up_interruptible(&tty->write_wait);
1218 if ( test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event) ) {
1226 * This routine is called whenever a serial port is opened. It
1227 * enables interrupts for a serial port, linking in its async structure into
1228 * the IRQ chain. It also performs the serial-specific
1229 * initialization for the tty structure.
1231 static int mxser_open(struct tty_struct * tty, struct file * filp)
1233 struct mxser_struct * info;
1236 #if 1 // add by Victor Yu. 12-28-2004
1237 unsigned long flags;
1241 if ( line == MXSER_PORTS )
1243 if ( (line < 0) || (line > MXSER_PORTS) )
1246 info = mxvar_table + line;
1250 tty->driver_data = info;
1251 #if 0 // mask by Victor Yu. 12-28-2004
1253 #else // add by Victor Yu. 12-28-2004
1257 restore_flags(flags);
1260 if ( !mxvar_tmp_buf ) {
1261 page = get_zeroed_page(GFP_KERNEL);
1264 if ( mxvar_tmp_buf )
1267 mxvar_tmp_buf = (unsigned char *)page;
1271 * Start up serial port
1273 retval = mxser_startup(info);
1277 retval = mxser_block_til_ready(tty, filp, info);
1281 #if 0 // mask by Victor Yu. 12-28-2004
1283 #else // add by Victor Yu. 12-28-2004
1287 restore_flags(flags);
1291 if ( (info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS) ) {
1292 *tty->termios = info->normal_termios;
1293 mxser_change_speed(info, 0);
1296 #if 0 // mask by Victor Yu. 12-28-2004
1297 info->session = current->session;
1298 info->pgrp = current->pgrp;
1299 clear_bit(TTY_DONT_FLIP, &tty->flags);
1300 #else // add by Victor Yu. 12-28-2004
1304 info->session = current->session;
1305 info->pgrp = current->pgrp;
1307 clear_bit(TTY_DONT_FLIP, &tty->flags);
1308 restore_flags(flags);
1311 /* unmark here for very high baud rate (ex. 921600 bps) used
1313 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
1314 tty->low_latency = 1;
1320 * This routine is called when the serial port gets closed. First, we
1321 * wait for the last remaining data to be sent. Then, we unlink its
1322 * async structure from the interrupt chain if necessary, and we free
1323 * that IRQ if nothing is left in the chain.
1325 static void mxser_close(struct tty_struct * tty, struct file * filp)
1327 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
1328 unsigned long flags;
1329 unsigned long timeout;
1331 if ( PORTNO(tty) == MXSER_PORTS )
1336 #if 0 // mask by Victor Yu. 12-28-2004
1341 if ( tty_hung_up_p(filp) ) {
1342 #if 0 // mask by Victor Yu. 12-28-2004
1343 restore_flags(flags);
1349 #if 1 // add by Victor Yu. 12-28-2004
1353 if ( (tty->count == 1) && (info->count != 1) ) {
1355 * Uh, oh. tty->count is 1, which means that the tty
1356 * structure will be freed. Info->count should always
1357 * be one in these conditions. If it's greater than
1358 * one, we've got real problems, since it means the
1359 * serial port won't be shutdown.
1361 printk("mxser_close: bad serial port count; tty->count is 1, "
1362 "info->count is %d\n", info->count);
1365 if ( --info->count < 0 ) {
1366 printk("mxser_close: bad serial port count for ttys%d: %d\n",
1367 info->port, info->count);
1370 if ( info->count ) {
1371 restore_flags(flags);
1375 info->flags |= ASYNC_CLOSING;
1376 restore_flags(flags); // add by Victor Yu. 09-26-2002
1378 * Save the termios structure, since this port may have
1379 * separate termios for callout and dialin.
1381 if ( info->flags & ASYNC_NORMAL_ACTIVE )
1382 info->normal_termios = *tty->termios;
1384 * Now we wait for the transmit buffer to clear; and we notify
1385 * the line discipline to only process XON/XOFF characters.
1388 if ( info->closing_wait != ASYNC_CLOSING_WAIT_NONE ) {
1389 tty_wait_until_sent(tty, info->closing_wait);
1392 * At this point we stop accepting input. To do this, we
1393 * disable the receive line status interrupts, and tell the
1394 * interrupt driver to stop checking the data ready bit in the
1395 * line status register.
1397 info->IER &= ~UART_IER_RLSI;
1398 if ( info->IsMoxaMustChipFlag )
1399 info->IER &= ~MOXA_MUST_RECV_ISR;
1401 info->read_status_mask &= ~UART_LSR_DR;
1403 if ( info->flags & ASYNC_INITIALIZED ) {
1404 outb(info->IER, info->base + UART_IER);
1406 * Before we drop DTR, make sure the UART transmitter
1407 * has completely drained; this is especially
1408 * important if there is a transmit FIFO!
1410 timeout = jiffies + HZ;
1411 while ( !(inb(info->base + UART_LSR) & UART_LSR_TEMT) ) {
1412 current->state = TASK_INTERRUPTIBLE;
1413 schedule_timeout(5);
1414 if ( time_after(jiffies, timeout) )
1418 mxser_shutdown(info);
1420 // following add by Victor Yu. 09-23-2002
1422 if ( info->IsMoxaMustChipFlag )
1423 SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base);
1425 // above add by Victor Yu. 09-23-2002
1427 if ( tty->driver->flush_buffer )
1428 tty->driver->flush_buffer(tty);
1429 if ( tty->ldisc.flush_buffer )
1430 tty->ldisc.flush_buffer(tty);
1434 if ( info->blocked_open ) {
1435 if ( info->close_delay ) {
1436 current->state = TASK_INTERRUPTIBLE;
1437 schedule_timeout(info->close_delay);
1439 wake_up_interruptible(&info->open_wait);
1443 info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
1446 info->flags &= ~(ASYNC_NORMAL_ACTIVE |
1449 wake_up_interruptible(&info->close_wait);
1450 // restore_flags(flags); // mask by Vicror Yu. 09-26-2002
1455 static int mxser_write(struct tty_struct * tty, int from_user,
1456 const unsigned char * buf, int count)
1459 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1460 unsigned long flags;
1462 if ( !tty || !info->xmit_buf || !mxvar_tmp_buf )
1465 #if 0 // mask by Victor Yu. 10-13-2004
1467 down(&mxvar_tmp_buf_sem);
1473 c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1474 SERIAL_XMIT_SIZE - info->xmit_head));
1480 copy_from_user(mxvar_tmp_buf, buf, c);
1481 c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1482 SERIAL_XMIT_SIZE - info->xmit_head));
1483 memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
1485 copy_from_user(info->xmit_buf+info->xmit_head, buf, c);
1487 memcpy(info->xmit_buf + info->xmit_head, buf, c);
1488 info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
1489 info->xmit_cnt += c;
1490 // restore_flags(flags);
1495 #if 0 // mask by Victor Yu. 10-13-2004
1497 up(&mxvar_tmp_buf_sem);
1499 if ( info->xmit_cnt && !tty->stopped &&
1500 !(info->IER & UART_IER_THRI) ) {
1501 if (!tty->hw_stopped||(info->type == PORT_16550A)) {
1502 info->IER |= UART_IER_THRI;
1503 outb(info->IER, info->base + UART_IER);
1506 restore_flags(flags);
1510 static void mxser_put_char(struct tty_struct * tty, unsigned char ch)
1512 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1513 unsigned long flags;
1515 if ( !tty || !info->xmit_buf )
1520 if ( info->xmit_cnt >= SERIAL_XMIT_SIZE - 1 ) {
1521 restore_flags(flags);
1525 info->xmit_buf[info->xmit_head++] = ch;
1526 info->xmit_head &= SERIAL_XMIT_SIZE - 1;
1528 if ( !tty->stopped && !(info->IER & UART_IER_THRI) ) {
1529 if (!tty->hw_stopped||(info->type == PORT_16550A)) {
1530 info->IER |= UART_IER_THRI;
1531 outb(info->IER, info->base + UART_IER);
1534 restore_flags(flags);
1537 static void mxser_flush_chars(struct tty_struct * tty)
1539 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1540 unsigned long flags;
1542 if ( info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf ||
1543 (tty->hw_stopped && info->type!=PORT_16550A))
1548 info->IER |= UART_IER_THRI;
1549 outb(info->IER, info->base + UART_IER);
1550 restore_flags(flags);
1553 static int mxser_write_room(struct tty_struct * tty)
1555 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1558 ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
1564 static int mxser_chars_in_buffer(struct tty_struct * tty)
1566 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1568 return(info->xmit_cnt);
1571 static void mxser_flush_buffer(struct tty_struct * tty)
1573 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1574 unsigned long flags;
1578 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1579 restore_flags(flags);
1580 wake_up_interruptible(&tty->write_wait);
1581 if ( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1582 tty->ldisc.write_wakeup )
1583 (tty->ldisc.write_wakeup)(tty);
1586 static int mxser_ioctl(struct tty_struct * tty, struct file * file,
1587 unsigned int cmd, unsigned long arg)
1590 unsigned long flags;
1591 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
1593 struct async_icount cprev, cnow; /* kernel counter temps */
1594 struct serial_icounter_struct *p_cuser; /* user space */
1595 unsigned long templ;
1596 if ( PORTNO(tty) == MXSER_PORTS )
1597 return(mxser_ioctl_special(cmd, arg));
1599 // following add by Victor Yu. 01-05-2004
1600 if ( cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE ) {
1606 if ( cmd == MOXA_SET_OP_MODE ) {
1607 error = verify_area(VERIFY_READ, (void *)arg, sizeof(int));
1610 get_from_user(opmode,(int *)arg);
1611 if ( opmode != RS232_MODE && opmode != RS485_2WIRE_MODE && opmode != RS422_MODE && opmode != RS485_4WIRE_MODE )
1614 shiftbit = (p+2) * 2;
1618 val = inl(info->opmode_ioaddr);
1619 val &= (~(3 << shiftbit));
1620 val |= (opmode << shiftbit);
1621 outl(val, info->opmode_ioaddr);
1623 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1627 shiftbit = (p+2) * 2;
1631 opmode = inl(info->opmode_ioaddr) >> shiftbit;
1632 opmode &= OP_MODE_MASK;
1633 copy_to_user((int*)arg, &opmode, sizeof(int));
1637 // above add by Victor Yu. 01-05-2004
1639 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
1640 if ( cmd == MOXA_SET_SPECIAL_BAUD_RATE || cmd == MOXA_GET_SPECIAL_BAUD_RATE ) {
1642 if ( cmd == MOXA_SET_SPECIAL_BAUD_RATE ) {
1643 error = verify_area(VERIFY_READ, (void *)arg, sizeof(int));
1646 get_from_user(speed,(int *)arg);
1647 if ( speed <= 0 || speed > info->MaxCanSetBaudRate )
1649 if ( !info->tty || !info->tty->termios || !info->base )
1651 info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX);
1652 for ( i=0; i<BAUD_TABLE_NO && speed != mxvar_baud_table[i]; i++ );
1653 if ( i == BAUD_TABLE_NO ) {
1654 info->tty->termios->c_cflag |= B4000000;
1656 switch ( mxvar_baud_table[i] ) {
1657 case 921600 : info->tty->termios->c_cflag |= B921600; break;
1658 case 460800 : info->tty->termios->c_cflag |= B460800; break;
1659 case 230400 : info->tty->termios->c_cflag |= B230400; break;
1660 case 115200 : info->tty->termios->c_cflag |= B115200; break;
1661 case 57600 : info->tty->termios->c_cflag |= B57600; break;
1662 case 38400 : info->tty->termios->c_cflag |= B38400; break;
1663 case 19200 : info->tty->termios->c_cflag |= B19200; break;
1664 case 9600 : info->tty->termios->c_cflag |= B9600; break;
1665 case 4800 : info->tty->termios->c_cflag |= B4800; break;
1666 case 2400 : info->tty->termios->c_cflag |= B2400; break;
1667 case 1800 : info->tty->termios->c_cflag |= B1800; break;
1668 case 1200 : info->tty->termios->c_cflag |= B1200; break;
1669 case 600 : info->tty->termios->c_cflag |= B600; break;
1670 case 300 : info->tty->termios->c_cflag |= B300; break;
1671 case 200 : info->tty->termios->c_cflag |= B200; break;
1672 case 150 : info->tty->termios->c_cflag |= B150; break;
1673 case 134 : info->tty->termios->c_cflag |= B134; break;
1674 case 110 : info->tty->termios->c_cflag |= B110; break;
1675 case 75 : info->tty->termios->c_cflag |= B75; break;
1676 case 50 : info->tty->termios->c_cflag |= B50; break;
1679 info->speed = speed;
1680 mxser_change_speed(info, 0);
1682 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1685 copy_to_user((int*)arg, &info->speed, sizeof(int));
1691 if ( (cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) &&
1692 (cmd != TIOCGICOUNT) ) {
1693 if ( tty->flags & (1 << TTY_IO_ERROR) )
1697 #if 1 // add by Victor Yu. 12-28-2004
1698 case TIOCSBRK : // start to send break
1699 retval = tty_check_change(tty);
1702 tty_wait_until_sent(tty, 0);
1705 outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
1706 restore_flags(flags);
1708 case TIOCCBRK : // stop to send break
1711 outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
1712 restore_flags(flags);
1715 case TCSBRK: /* SVID version: non-zero arg --> no break */
1716 retval = tty_check_change(tty);
1719 tty_wait_until_sent(tty, 0);
1721 mxser_send_break(info, HZ/4); /* 1/4 second */
1723 case TCSBRKP: /* support for POSIX tcsendbreak() */
1724 retval = tty_check_change(tty);
1727 tty_wait_until_sent(tty, 0);
1728 mxser_send_break(info, arg ? arg*(HZ/10) : HZ/4);
1731 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));
1734 put_to_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
1737 error = verify_area(VERIFY_READ, (void *)arg, sizeof(long));
1740 get_from_user(templ,(unsigned long *)arg);
1742 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
1743 (arg ? CLOCAL : 0));
1746 error = verify_area(VERIFY_WRITE, (void *)arg,
1747 sizeof(unsigned int));
1750 return(mxser_get_modem_info(info, (unsigned int *)arg));
1754 return(mxser_set_modem_info(info, cmd, (unsigned int *)arg));
1756 error = verify_area(VERIFY_WRITE, (void *)arg,
1757 sizeof(struct serial_struct));
1760 return(mxser_get_serial_info(info, (struct serial_struct *)arg));
1762 error = verify_area(VERIFY_READ, (void *)arg,
1763 sizeof(struct serial_struct));
1766 return(mxser_set_serial_info(info, (struct serial_struct *)arg));
1767 case TIOCSERGETLSR: /* Get line status register */
1768 error = verify_area(VERIFY_WRITE, (void *)arg,
1769 sizeof(unsigned int));
1773 return(mxser_get_lsr_info(info, (unsigned int *)arg));
1775 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
1776 * - mask passed in arg for lines of interest
1777 * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
1778 * Caller should use TIOCGICOUNT to see which one it was
1783 cprev = info->icount; /* note the counters on entry */
1784 restore_flags(flags);
1786 interruptible_sleep_on(&info->delta_msr_wait);
1787 /* see if a signal did it */
1788 if ( signal_pending(current) ) {
1789 return(-ERESTARTSYS);
1793 cnow = info->icount; /* atomic copy */
1794 restore_flags(flags);
1795 #if 0 // mask by Victor Yu. 12-31-2004
1796 if ( cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
1797 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts )
1798 return(-EIO); /* no change => error */
1799 if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
1800 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
1801 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
1802 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
1805 #else // add by Victor Yu. 12-31-2004
1806 #define TIOCM_BRK 0x10000
1807 #define TIOCM_PARITY 0x20000
1808 #define TIOCM_FRAME 0x40000
1809 #define TIOCM_XOFFHOLD 0x80000
1810 if ( cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
1811 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts &&
1812 cnow.brk == cprev.brk && cnow.parity == cprev.parity &&
1813 cnow.frame == cprev.frame && cnow.buf_overrun == cprev.buf_overrun )
1814 return(-EIO); /* no change => error */
1815 if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
1816 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
1817 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
1818 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ||
1819 ((arg & TIOCM_BRK) && (cnow.brk != cprev.brk)) ||
1820 ((arg & TIOCM_PARITY) && (cnow.parity != cprev.parity)) ||
1821 ((arg & TIOCM_FRAME) && (cnow.frame != cprev.frame)) ||
1822 ((arg & TIOCM_XOFFHOLD) && (cnow.buf_overrun != cprev.buf_overrun)) ) {
1830 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1831 * Return: write counters to the user passed counter struct
1832 * NB: both 1->0 and 0->1 transitions are counted except for
1833 * RI where only 0->1 is counted.
1836 #if 1 // add by Victor Yu. 01-26-2005
1838 wake_up_interruptible(&info->delta_msr_wait);
1843 error = verify_area(VERIFY_WRITE, (void *)arg,
1844 sizeof(struct serial_icounter_struct));
1849 cnow = info->icount;
1850 restore_flags(flags);
1851 p_cuser = (struct serial_icounter_struct *)arg;
1852 /* modified by casper 1/11/2000 */
1853 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
1854 if (put_user(cnow.frame, &p_cuser->frame))
1856 if (put_user(cnow.brk, &p_cuser->brk))
1858 if (put_user(cnow.overrun, &p_cuser->overrun))
1860 if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
1862 if (put_user(cnow.parity, &p_cuser->parity))
1864 if (put_user(cnow.rx, &p_cuser->rx))
1866 if (put_user(cnow.tx, &p_cuser->tx))
1870 put_to_user(cnow.cts, &p_cuser->cts);
1871 put_to_user(cnow.dsr, &p_cuser->dsr);
1872 put_to_user(cnow.rng, &p_cuser->rng);
1873 put_to_user(cnow.dcd, &p_cuser->dcd);
1877 case MOXA_HighSpeedOn:
1878 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1881 put_to_user(info->baud_base != 115200 ? 1 : 0, (int *)arg);
1884 return(-ENOIOCTLCMD);
1889 static int mxser_ioctl_special(unsigned int cmd, unsigned long arg)
1891 int error, i, result, status;
1895 error = verify_area(VERIFY_WRITE, (void *)arg,
1896 sizeof(struct mxser_hwconf)*4);
1899 copy_to_user((struct mxser_hwconf *)arg, mxsercfg,
1900 sizeof(struct mxser_hwconf)*4);
1902 case MOXA_GET_MAJOR:
1903 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1906 copy_to_user((int*)arg, &ttymajor, sizeof(int));
1909 case MOXA_GET_CUMAJOR:
1910 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
1913 copy_to_user((int*)arg, &calloutmajor, sizeof(int));
1916 case MOXA_CHKPORTENABLE:
1917 error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(long));
1921 for ( i=0; i<MXSER_PORTS; i++ ) {
1922 if ( mxvar_table[i].base )
1925 put_to_user(result, (unsigned long *)arg);
1927 case MOXA_GETDATACOUNT:
1928 error = verify_area(VERIFY_WRITE, (void *)arg,
1929 sizeof(struct mxser_log));
1932 copy_to_user((struct mxser_log *)arg, &mxvar_log, sizeof(mxvar_log));
1934 case MOXA_GETMSTATUS:
1935 error = verify_area(VERIFY_WRITE, (void *)arg,
1936 sizeof(struct mxser_mstatus) * MXSER_PORTS);
1940 for(i=0; i<MXSER_PORTS; i++){
1942 if ( !mxvar_table[i].base ){
1943 GMStatus[i].dcd = 0;
1944 GMStatus[i].dsr = 0;
1945 GMStatus[i].cts = 0;
1949 if ( !mxvar_table[i].tty || !mxvar_table[i].tty->termios )
1950 GMStatus[i].cflag=mxvar_table[i].normal_termios.c_cflag;
1952 GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag;
1954 status = inb(mxvar_table[i].base + UART_MSR);
1955 if(status & 0x80/*UART_MSR_DCD*/)
1956 GMStatus[i].dcd = 1;
1958 GMStatus[i].dcd = 0;
1960 if(status & 0x20/*UART_MSR_DSR*/)
1961 GMStatus[i].dsr = 1;
1963 GMStatus[i].dsr = 0;
1966 if(status & 0x10/*UART_MSR_CTS*/)
1967 GMStatus[i].cts = 1;
1969 GMStatus[i].cts = 0;
1971 copy_to_user((struct mxser_mstatus *)arg, GMStatus,
1972 sizeof(struct mxser_mstatus) * MXSER_PORTS);
1975 return(-ENOIOCTLCMD);
1981 * This routine is called by the upper-layer tty layer to signal that
1982 * incoming characters should be throttled.
1984 static void mxser_throttle(struct tty_struct * tty)
1986 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
1987 unsigned long flags;
1989 if ( I_IXOFF(tty) ) {
1993 // following add by Victor Yu. 09-02-2002
1994 if ( info->IsMoxaMustChipFlag ) {
1995 info->IER &= ~MOXA_MUST_RECV_ISR;
1996 outb(info->IER, info->base+UART_IER);
1998 // above add by Victor Yu. 09-02-2002
2000 info->x_char = STOP_CHAR(tty);
2001 // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002
2002 outb(0, info->base+UART_IER);
2003 info->IER |= UART_IER_THRI;
2004 outb(info->IER, info->base + UART_IER); /* force Tx interrupt */
2005 } // add by Victor Yu. 09-02-2002
2006 restore_flags(flags);
2009 if ( info->tty->termios->c_cflag & CRTSCTS ) {
2012 #if 1 // add by Victor Yu. 09-17-2004
2013 if ( info->IsMoxaMustChipFlag ) {
2014 info->IER &= ~MOXA_MUST_RECV_ISR;
2015 outb(info->IER, info->base+UART_IER);
2017 info->MCR &= ~UART_MCR_RTS;
2018 outb(info->MCR, info->base + UART_MCR);
2021 info->MCR &= ~UART_MCR_RTS;
2022 outb(info->MCR, info->base + UART_MCR);
2024 restore_flags(flags);
2028 static void mxser_unthrottle(struct tty_struct * tty)
2030 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2031 unsigned long flags;
2033 if ( I_IXOFF(tty) ) {
2040 // following add by Victor Yu. 09-02-2002
2041 if ( info->IsMoxaMustChipFlag ) {
2042 info->IER |= MOXA_MUST_RECV_ISR;
2043 outb(info->IER, info->base+UART_IER);
2045 // above add by Victor Yu. 09-02-2002
2047 info->x_char = START_CHAR(tty);
2048 // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002
2049 outb(0, info->base+UART_IER); // add by Victor Yu. 09-02-2002
2050 info->IER |= UART_IER_THRI; /* force Tx interrupt */
2051 outb(info->IER, info->base + UART_IER);
2052 } // add by Victor Yu. 09-02-2002
2053 restore_flags(flags);
2057 if ( info->tty->termios->c_cflag & CRTSCTS ) {
2060 #if 1 // add by Victor Yu. 09-17-2004
2061 if ( info->IsMoxaMustChipFlag ) {
2062 info->IER |= MOXA_MUST_RECV_ISR;
2063 outb(info->IER, info->base+UART_IER);
2065 info->MCR |= UART_MCR_RTS;
2066 outb(info->MCR, info->base + UART_MCR);
2069 info->MCR |= UART_MCR_RTS;
2070 outb(info->MCR, info->base + UART_MCR);
2072 restore_flags(flags);
2076 static void mxser_set_termios(struct tty_struct * tty,
2077 struct termios * old_termios)
2079 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2081 #if 0 // mask by Victor Yu. 01-04-2005
2082 if ( (tty->termios->c_cflag != old_termios->c_cflag) ||
2083 (RELEVANT_IFLAG(tty->termios->c_iflag) !=
2084 RELEVANT_IFLAG(old_termios->c_iflag)) ) {
2085 #else // add by Victor Yu. 01-04-2005
2086 if ( (tty->termios->c_cflag != old_termios->c_cflag) ||
2087 (tty->termios->c_iflag != old_termios->c_iflag) ) {
2090 mxser_change_speed(info, old_termios);
2092 if ( (old_termios->c_cflag & CRTSCTS) &&
2093 !(tty->termios->c_cflag & CRTSCTS) ) {
2094 tty->hw_stopped = 0;
2099 /* Handle sw stopped */
2100 if ( (old_termios->c_iflag & IXON) &&
2101 !(tty->termios->c_iflag & IXON) ) {
2104 #if 0 // mask by Victor Yu. 01-04-2005
2105 // following add by Victor Yu. 09-02-2002
2106 if ( info->IsMoxaMustChipFlag ) {
2107 unsigned long flags;
2110 info->IER &= ~MOXA_MUST_IER_XINT;
2111 DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
2112 outb(info->IER, info->base+UART_IER);
2113 restore_flags(flags);
2115 // above add by Victor Yu. 09-02-2002
2123 * mxser_stop() and mxser_start()
2125 * This routines are called before setting or resetting tty->stopped.
2126 * They enable or disable transmitter interrupts, as necessary.
2128 static void mxser_stop(struct tty_struct * tty)
2130 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2131 unsigned long flags;
2135 if ( info->IER & UART_IER_THRI ) {
2136 info->IER &= ~UART_IER_THRI;
2137 outb(info->IER, info->base + UART_IER);
2139 restore_flags(flags);
2142 static void mxser_start(struct tty_struct * tty)
2144 struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
2145 unsigned long flags;
2149 if ( info->xmit_cnt && info->xmit_buf &&
2150 !(info->IER & UART_IER_THRI) ) {
2151 info->IER |= UART_IER_THRI;
2152 outb(info->IER, info->base + UART_IER);
2154 restore_flags(flags);
2157 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2159 * mxser_wait_until_sent() --- wait until the transmitter is empty
2161 static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
2163 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
2164 unsigned long orig_jiffies, char_time;
2167 if (info->type == PORT_UNKNOWN)
2170 if (info->xmit_fifo_size == 0)
2171 return; /* Just in case.... */
2174 * Set the check interval to be 1/5 of the estimated time to
2175 * send a single character, and make it at least 1. The check
2176 * interval should also be less than the timeout.
2178 * Note: we have to use pretty tight timings here to satisfy
2181 char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
2182 char_time = char_time / 5;
2185 if (timeout && timeout < char_time)
2186 char_time = timeout;
2188 * If the transmitter hasn't cleared in twice the approximate
2189 * amount of time to send the entire FIFO, it probably won't
2190 * ever clear. This assumes the UART isn't doing flow
2191 * control, which is currently the case. Hence, if it ever
2192 * takes longer than info->timeout, this is probably due to a
2193 * UART bug of some kind. So, we clamp the timeout parameter at
2196 if (!timeout || timeout > 2*info->timeout)
2197 timeout = 2*info->timeout;
2198 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2199 printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
2200 printk("jiff=%lu...", jiffies);
2202 orig_jiffies = jiffies + timeout;
2203 while (!((lsr = inb(info->base+ UART_LSR)) & UART_LSR_TEMT)) {
2204 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2205 printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
2207 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))
2208 set_current_state(TASK_INTERRUPTIBLE);
2210 current->state = TASK_INTERRUPTIBLE;
2212 schedule_timeout(char_time);
2213 if (signal_pending(current))
2215 if (timeout && time_after(jiffies, orig_jiffies))
2218 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,3,0))
2219 set_current_state(TASK_RUNNING);
2221 current->state = TASK_RUNNING;
2224 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
2225 printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
2232 * This routine is called by tty_hangup() when a hangup is signaled.
2234 void mxser_hangup(struct tty_struct * tty)
2236 struct mxser_struct * info = (struct mxser_struct *)tty->driver_data;
2237 #if 1 // add by Victor Yu. 12-28-2004
2238 unsigned long flags;
2241 mxser_flush_buffer(tty);
2242 mxser_shutdown(info);
2243 #if 0 // mask by Victor Yu. 12-28-2004
2246 info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2254 info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2256 info->flags &= ~(ASYNC_NORMAL_ACTIVE);
2259 restore_flags(flags);
2261 wake_up_interruptible(&info->open_wait);
2265 * This is the serial driver's generic interrupt routine
2267 //#define USE_INT_POLL
2269 static int poll_int_port=0;
2271 static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs * regs)
2274 struct mxser_struct * info;
2275 struct mxser_struct * port;
2276 int max, irqbits, msr;
2277 #ifndef USE_INT_POLL
2278 int pass_counter=0, bits;
2282 for(i=0; i<MXSER_BOARDS; i++){
2283 if(dev_id == &(mxvar_table[i*MXSER_PORTS_PER_BOARD])){
2289 if(i==MXSER_BOARDS || port==0)
2291 max = mxser_numports[mxsercfg[i].board_type-1];
2294 irqbits = inb(port->vector) & port->vectormask;
2296 if ( irqbits & (1<<poll_int_port) )
2298 info = port + poll_int_port;
2300 if ( irqbits == port->vectormask )
2303 for ( i=0, bits=1; i<max; i++, irqbits |= bits, bits <<= 1 ) {
2305 for ( i=0, bits=4; i<max; i++, irqbits |= bits, bits <<= 1 ) {
2307 if ( irqbits == port->vectormask )
2309 if ( bits & irqbits )
2314 // following add by Victor Yu. 09-13-2002
2315 iir = inb(info->base+UART_IIR);
2316 if ( iir & UART_IIR_NO_INT )
2318 iir &= MOXA_MUST_IIR_MASK;
2320 status = inb(info->base+UART_LSR);
2321 outb(0x27, info->base+UART_FCR);
2322 inb(info->base+UART_MSR);
2325 // above add by Victor Yu. 09-13-2002
2327 #if 1 // add by Victor Yu. 01-04-2005
2328 if ( iir == MOXA_MUST_IIR_XSC ) {
2329 if ( !(inb(info->base+UART_MCR) & MOXA_MUST_MCR_XON_FLAG) ) {
2330 info->icount.buf_overrun++;
2331 wake_up_interruptible(&info->delta_msr_wait);
2337 /* mask by Victor Yu. 09-13-2002
2339 (inb(info->base + UART_IIR) & UART_IIR_NO_INT) )
2342 /* mask by Victor Yu. 09-02-2002
2343 status = inb(info->base + UART_LSR) & info->read_status_mask;
2346 #if 0 // mask by Victor Yu. 01-04-2005, I do just for UC7400 series
2347 // following add by Victor Yu. 09-02-2002
2348 status = inb(info->base+UART_LSR);
2349 if ( info->IsMoxaMustChipFlag ) {
2351 if ( (status & 0x02) && !(status & 0x01) ) {
2352 outb(info->base+UART_FCR, 0x23);
2356 if ( iir == MOXA_MUST_IIR_GDA ||
2357 iir == MOXA_MUST_IIR_RDA ||
2358 iir == MOXA_MUST_IIR_RTO ||
2359 iir == MOXA_MUST_IIR_LSR )
2360 mxser_receive_chars(info, &status);
2362 // above add by Victor Yu. 09-02-2002
2364 status &= info->read_status_mask;
2365 if ( status & UART_LSR_DR )
2366 mxser_receive_chars(info, &status);
2368 #else // add by Victor Yu. 01-04-2005
2369 if ( iir == MOXA_MUST_IIR_GDA ||
2370 iir == MOXA_MUST_IIR_RDA ||
2371 iir == MOXA_MUST_IIR_RTO ||
2372 iir == MOXA_MUST_IIR_LSR ) {
2373 status = inb(info->base+UART_LSR);
2374 mxser_receive_chars(info, &status);
2377 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2378 if ( iir == UART_IIR_MSI ) {
2379 msr = inb(info->base + UART_MSR);
2380 if ( msr & UART_MSR_ANY_DELTA ) {
2381 mxser_check_modem_status(info, msr);
2385 msr = inb(info->base + UART_MSR);
2386 if ( msr & UART_MSR_ANY_DELTA ) {
2387 mxser_check_modem_status(info, msr);
2391 #if 0 // mask by Victor Yu. I do just for UC7400 series
2392 // following add by Victor Yu. 09-13-2002
2393 if ( info->IsMoxaMustChipFlag ) {
2395 mxser_transmit_chars(info);
2397 // above add by Victor Yu. 09-13-2002
2399 if ( status & UART_LSR_THRE ) {
2400 /* 8-2-99 by William
2401 if ( info->x_char || (info->xmit_cnt > 0) )
2403 mxser_transmit_chars(info);
2406 #else // add by Victor Yu. 01-04-2005
2408 mxser_transmit_chars(info);
2410 #ifndef USE_INT_POLL
2412 if ( pass_counter++ > MXSER_ISR_PASS_LIMIT ) {
2414 printk("MOXA Smartio/Industio family driver interrupt loop break\n");
2416 break; /* Prevent infinite loops */
2421 if ( ++poll_int_port >= max )
2427 #define BYPASS_FLIP // add by Victor Yu. 09-17-2004
2428 #define N_TTY_BUF_SIZE_MASK (N_TTY_BUF_SIZE-1) // add by Victor Yu. 02-04-2005
2429 static inline void mxser_receive_chars(struct mxser_struct *info,
2432 struct tty_struct * tty = info->tty;
2433 unsigned char ch, gdl;
2436 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2437 unsigned char *cp=tty->read_buf;
2438 int wptr=tty->read_head;
2440 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2441 unsigned char *cp=tty->flip.char_buf;
2442 char *fp=tty->flip.flag_buf;
2443 #endif // BYPASS_FLIP
2444 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2446 // following add by Victor Yu. 09-02-2002
2447 if ( info->IsMoxaMustChipFlag ) {
2448 if ( *status & UART_LSR_SPECIAL ) {
2452 // following add by Victor Yu. 02-11-2004
2453 if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID1 &&
2454 (*status & MOXA_MUST_LSR_RERR) )
2456 // above add by Victor Yu. 02-14-2004
2458 gdl = inb(info->base+MOXA_MUST_GDL_REGISTER);
2460 if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID ) // add by Victor Yu. 02-11-2004
2461 gdl &= MOXA_MUST_GDL_MASK;
2463 // following add by Victor Yu. 10-13-2004
2464 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2465 cnt = gdl = MIN(gdl, N_TTY_BUF_SIZE_MASK);
2468 cnt = gdl = MIN(gdl, TTY_FLIPBUF_SIZE);
2470 cnt = gdl = MIN(gdl, TTY_FLIPBUF_SIZE-tty->flip.count);
2471 #endif // BYPASS_FLIP
2472 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2473 // above add by Victor Yu. 10-13-2004
2476 #if 0 // mask by Victor Yu. 10-13-2004
2477 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2478 if ( cnt >= TTY_FLIPBUF_SIZE )
2481 if ( tty->flip.count >= TTY_FLIPBUF_SIZE )
2485 ch = inb(info->base + UART_RX);
2486 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2488 wptr &= N_TTY_BUF_SIZE_MASK;
2490 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2495 *tty->flip.char_buf_ptr++ = ch;
2496 *tty->flip.flag_buf_ptr++ = 0;
2497 #endif // BYPASS_FLIP
2498 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2499 //cnt++; // mask by Victor Yu. 10-13-2004
2504 // above add by Victor Yu. 09-02-2002
2507 ch = inb(info->base + UART_RX);
2508 // following add by Victor Yu. 09-02-2002
2509 if ( info->IsMoxaMustChipFlag && (*status&UART_LSR_OE) && !(*status&UART_LSR_DR) )
2510 outb(0x23, info->base+UART_FCR);
2512 #if 1 // add by Victor Yu. 01-06-2005
2515 if ( *status & UART_LSR_BI ) {
2519 if ( *status & UART_LSR_PE ) {
2520 info->icount.parity++;
2523 if ( *status & UART_LSR_FE ) {
2524 info->icount.frame++;
2527 if ( *status & UART_LSR_OE ) {
2528 info->icount.overrun++;
2532 wake_up_interruptible(&info->delta_msr_wait);
2536 *status &= info->read_status_mask;
2537 // above add by Victor Yu. 09-02-2002
2538 if ( *status & info->ignore_status_mask ) {
2539 if ( ++ignored > 100 )
2542 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2543 if ( (cnt+tty->read_cnt) >= N_TTY_BUF_SIZE_MASK )
2546 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2547 if ( cnt >= TTY_FLIPBUF_SIZE )
2550 if ( tty->flip.count >= TTY_FLIPBUF_SIZE )
2553 #endif // BYPASS_FLIP
2554 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2555 if ( *status & UART_LSR_SPECIAL ) {
2556 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2559 if ( *status & UART_LSR_BI ) {
2560 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2563 *tty->flip.flag_buf_ptr++ = TTY_BREAK;
2566 #if 0 // mask by Victor Yu. 01-06-2005
2567 /* added by casper 1/11/2000 */
2568 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2574 if ( info->flags & ASYNC_SAK )
2576 } else if ( *status & UART_LSR_PE ) {
2577 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2580 *tty->flip.flag_buf_ptr++ = TTY_PARITY;
2583 #if 0 // mask by Victor Yu. 01-06-2005
2584 /* added by casper 1/11/2000 */
2585 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2586 info->icount.parity++;
2590 } else if ( *status & UART_LSR_FE ) {
2591 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2594 *tty->flip.flag_buf_ptr++ = TTY_FRAME;
2597 #if 0 // mask by Victor Yu. 01-06-2005
2598 /* added by casper 1/11/2000 */
2599 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2600 info->icount.frame++;
2604 } else if ( *status & UART_LSR_OE ) {
2605 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2606 *fp++ = TTY_OVERRUN;
2608 *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
2611 #if 0 // mask by Victor Yu. 01-06-2004
2612 /* added by casper 1/11/2000 */
2613 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2614 info->icount.overrun++;
2619 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2622 *tty->flip.flag_buf_ptr++ = 0;
2625 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2627 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2630 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2633 *tty->flip.flag_buf_ptr++ = 0;
2634 #endif // BYPASS_FLIP
2635 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2637 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2639 wptr &= N_TTY_BUF_SIZE_MASK;
2641 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2644 *tty->flip.char_buf_ptr++ = ch;
2645 #endif // BYPASS_FLIP
2646 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2650 // following add by Victor Yu. 09-02-2002
2651 if ( info->IsMoxaMustChipFlag )
2653 // above add by Victor Yu. 09-02-2002
2655 /* mask by Victor Yu. 09-02-2002
2656 *status = inb(info->base + UART_LSR) & info->read_status_mask;
2658 // following add by Victor Yu. 09-02-2002
2659 *status = inb(info->base+UART_LSR);
2660 // above add by Victor Yu. 09-02-2002
2661 } while ( *status & UART_LSR_DR );
2663 end_intr: // add by Victor Yu. 09-02-2002
2665 mxvar_log.rxcnt[info->port] += cnt;
2667 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)) // add by Victor Yu. 02-04-2005
2668 info->icount.rx += cnt;
2671 /* added by casper 1/11/2000 */
2672 #ifdef CONFIG_MOXA_SUPPORT_SKIP_LD // add by Victor Yu. 02-04-2005
2673 tty->read_head = wptr;
2674 tty->read_cnt += cnt;
2676 #ifdef BYPASS_FLIP // add by Victor Yu. 09-17-2004
2677 tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, cnt);
2679 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2680 //info->icount.rx += cnt; // mask by Victor Yu. 02-04-2005
2682 /* add by Victor Yu. 05-14-2002 following */
2683 //clear_bit(TTY_DONT_FLIP, &tty->flags); // mask by Victor Yu. 03-12-2004
2684 /* add by Victor Yu. 05-14-2002 above */
2686 tty_flip_buffer_push(tty);
2688 queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
2689 #endif // LINUX_VERSION_CODE
2690 #endif // BYPASS_FLIP
2691 #endif // CONFIG_MOXA_SUPPORT_SKIP_LD
2695 static inline void mxser_transmit_chars(struct mxser_struct *info)
2699 if ( info->x_char ) {
2700 outb(info->x_char, info->base + UART_TX);
2702 mxvar_log.txcnt[info->port]++;
2703 /* added by casper 1/11/2000 */
2704 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2711 if ( info->xmit_buf == 0 )
2714 if ((info->xmit_cnt <= 0) || info->tty->stopped ||
2715 (info->tty->hw_stopped && (info->type != PORT_16550A))) {
2716 info->IER &= ~UART_IER_THRI;
2717 outb(info->IER, info->base + UART_IER);
2721 #if 0 // mask by Victor Yu. 10-12-2004
2722 cnt = info->xmit_cnt;
2723 count = info->xmit_fifo_size;
2725 outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
2726 info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
2727 if ( --info->xmit_cnt <= 0 )
2729 } while ( --count > 0 );
2730 mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
2731 #else // add by Victor Yu. 10-12-2004
2733 int tail=info->xmit_tail;
2734 unsigned char *ptr=info->xmit_buf;
2735 #define XMIT_SIZE_MASK (SERIAL_XMIT_SIZE - 1)
2736 cnt = count = MIN(info->xmit_fifo_size, info->xmit_cnt);
2737 while ( count-- > 0 ) {
2738 outb(ptr[tail++], info->base);
2739 tail &= XMIT_SIZE_MASK;
2741 info->xmit_tail = tail;
2742 info->xmit_cnt -= cnt;
2743 mxvar_log.txcnt[info->port] += cnt;
2747 /* added by casper 1/11/2000 */
2748 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
2749 #if 0 // mask by Victor Yu. 10-12-2004
2750 info->icount.tx += (cnt - info->xmit_cnt);
2751 #else // add by Victor Yu. 10-12-2004
2752 info->icount.tx += cnt;
2757 if ( info->xmit_cnt < WAKEUP_CHARS ) {
2758 set_bit(MXSER_EVENT_TXLOW,&info->event);
2761 if (schedule_task(&info->tqueue) == 0)
2763 queue_task(&info->tqueue,&tq_scheduler);
2765 schedule_work(&info->tqueue);
2768 if (info->xmit_cnt <= 0) {
2769 info->IER &= ~UART_IER_THRI;
2770 outb(info->IER, info->base + UART_IER);
2774 static inline void mxser_check_modem_status(struct mxser_struct *info,
2777 /* update input line counters */
2778 if ( status & UART_MSR_TERI )
2780 if ( status & UART_MSR_DDSR )
2782 if ( status & UART_MSR_DDCD )
2784 if ( status & UART_MSR_DCTS )
2786 wake_up_interruptible(&info->delta_msr_wait);
2788 if ( (info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD) ) {
2789 if ( status & UART_MSR_DCD )
2790 wake_up_interruptible(&info->open_wait);
2792 else if ( !((info->flags & ASYNC_CALLOUT_ACTIVE) &&
2793 (info->flags & ASYNC_CALLOUT_NOHUP)) )
2797 set_bit(MXSER_EVENT_HANGUP,&info->event);
2800 if (schedule_task(&info->tqueue) == 0)
2803 schedule_work(&info->tqueue);
2806 if ( info->flags & ASYNC_CTS_FLOW ) {
2807 if ( info->tty->hw_stopped ) {
2808 if (status & UART_MSR_CTS ){
2809 info->tty->hw_stopped = 0;
2811 if (info->type != PORT_16550A) {
2812 info->IER |= UART_IER_THRI;
2813 outb(info->IER, info->base + UART_IER);
2815 set_bit(MXSER_EVENT_TXLOW,&info->event);
2818 if (schedule_task(&info->tqueue) == 0)
2821 schedule_work(&info->tqueue);
2825 if ( !(status & UART_MSR_CTS) ){
2826 info->tty->hw_stopped = 1;
2827 if (info->type != PORT_16550A) {
2828 info->IER &= ~UART_IER_THRI;
2829 outb(info->IER, info->base + UART_IER);
2836 static int mxser_block_til_ready(struct tty_struct *tty, struct file * filp,
2837 struct mxser_struct *info)
2839 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,4,0))
2840 DECLARE_WAITQUEUE(wait, current);
2842 struct wait_queue wait = { current, NULL };
2844 unsigned long flags;
2849 * If the device is in the middle of being closed, then block
2850 * until it's done, and then try again.
2852 if ( tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING) ) {
2853 if ( info->flags & ASYNC_CLOSING )
2854 interruptible_sleep_on(&info->close_wait);
2855 #ifdef SERIAL_DO_RESTART
2856 if ( info->flags & ASYNC_HUP_NOTIFY )
2859 return(-ERESTARTSYS);
2866 * If this is a callout device, then just make sure the normal
2867 * device isn't being used.
2870 if ( tty->driver->subtype == SERIAL_TYPE_CALLOUT ) {
2871 if ( info->flags & ASYNC_NORMAL_ACTIVE )
2873 if ( (info->flags & ASYNC_CALLOUT_ACTIVE) &&
2874 (info->flags & ASYNC_SESSION_LOCKOUT) &&
2875 (info->session != current->session) )
2877 if ( (info->flags & ASYNC_CALLOUT_ACTIVE) &&
2878 (info->flags & ASYNC_PGRP_LOCKOUT) &&
2879 (info->pgrp != current->pgrp) )
2881 info->flags |= ASYNC_CALLOUT_ACTIVE;
2887 * If non-blocking mode is set, or the port is not enabled,
2888 * then make the check up front and then exit.
2890 if ( (filp->f_flags & O_NONBLOCK) ||
2891 (tty->flags & (1 << TTY_IO_ERROR)) ) {
2893 if ( info->flags & ASYNC_CALLOUT_ACTIVE )
2896 info->flags |= ASYNC_NORMAL_ACTIVE;
2901 if ( info->flags & ASYNC_CALLOUT_ACTIVE ) {
2902 if ( info->normal_termios.c_cflag & CLOCAL )
2906 if ( tty->termios->c_cflag & CLOCAL )
2913 * Block waiting for the carrier detect and the line to become
2914 * free (i.e., not in use by the callout). While we are in
2915 * this loop, info->count is dropped by one, so that
2916 * mxser_close() knows when to free things. We restore it upon
2917 * exit, either normal or abnormal.
2920 add_wait_queue(&info->open_wait, &wait);
2921 #if 0 // mask by Victor Yu. 12-28-2004
2924 if ( !tty_hung_up_p(filp) )
2926 restore_flags(flags);
2927 #else // add by Victor Yu. 12-28-2004
2928 if ( !tty_hung_up_p(filp) ) {
2932 restore_flags(flags);
2935 info->blocked_open++;
2940 if ( !(info->flags & ASYNC_CALLOUT_ACTIVE) )
2942 outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS,
2943 info->base + UART_MCR);
2944 restore_flags(flags);
2945 current->state = TASK_INTERRUPTIBLE;
2946 if ( tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED) ) {
2947 #ifdef SERIAL_DO_RESTART
2948 if ( info->flags & ASYNC_HUP_NOTIFY )
2951 retval = -ERESTARTSYS;
2958 if ( !(info->flags & ASYNC_CALLOUT_ACTIVE) &&
2959 !(info->flags & ASYNC_CLOSING) &&
2960 (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)) )
2962 if ( !(info->flags & ASYNC_CLOSING) &&
2963 (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)) )
2966 if ( signal_pending(current) ) {
2967 retval = -ERESTARTSYS;
2972 current->state = TASK_RUNNING;
2973 remove_wait_queue(&info->open_wait, &wait);
2974 if ( !tty_hung_up_p(filp) ) {
2975 #if 0 // mask by Victor 12-28-2004
2977 #else // add by Victor Yu. 12-28-2004
2981 restore_flags(flags);
2984 info->blocked_open--;
2987 info->flags |= ASYNC_NORMAL_ACTIVE;
2991 static int mxser_startup(struct mxser_struct * info)
2993 unsigned long flags;
2996 page = get_zeroed_page(GFP_KERNEL);
3003 if ( info->flags & ASYNC_INITIALIZED ) {
3005 restore_flags(flags);
3009 if ( !info->base || !info->type ) {
3011 set_bit(TTY_IO_ERROR, &info->tty->flags);
3013 restore_flags(flags);
3016 if ( info->xmit_buf )
3019 info->xmit_buf = (unsigned char *)page;
3022 * Clear the FIFO buffers and disable them
3023 * (they will be reenabled in mxser_change_speed())
3025 if ( info->xmit_fifo_size == 16 )
3026 outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
3027 info->base + UART_FCR);
3028 // following add by Victor Yu. 08-30-2002
3029 else if ( info->xmit_fifo_size == 64 || info->xmit_fifo_size == 128 )
3030 outb((UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT|MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base+UART_FCR);
3031 // above add by Victor Yu. 08-30-2002
3034 * At this point there's no way the LSR could still be 0xFF;
3035 * if it is, then bail out, because there's likely no UART
3038 if ( inb(info->base + UART_LSR) == 0xff ) {
3039 restore_flags(flags);
3040 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3043 if (capable(CAP_SYS_ADMIN)) {
3046 set_bit(TTY_IO_ERROR, &info->tty->flags);
3053 * Clear the interrupt registers.
3055 (void)inb(info->base + UART_LSR);
3056 (void)inb(info->base + UART_RX);
3057 (void)inb(info->base + UART_IIR);
3058 (void)inb(info->base + UART_MSR);
3061 * Now, initialize the UART
3063 outb(UART_LCR_WLEN8, info->base + UART_LCR); /* reset DLAB */
3064 info->MCR = UART_MCR_DTR | UART_MCR_RTS;
3065 outb(info->MCR, info->base + UART_MCR);
3068 * Finally, enable interrupts
3070 info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
3072 // following add by Victor Yu. 08-30-2002
3073 if ( info->IsMoxaMustChipFlag )
3074 info->IER |= MOXA_MUST_IER_EGDAI;
3075 // above add by Victor Yu. 08-30-2002
3077 outb(info->IER, info->base + UART_IER); /* enable interrupts */
3080 * And clear the interrupt registers again for luck.
3082 (void)inb(info->base + UART_LSR);
3083 (void)inb(info->base + UART_RX);
3084 (void)inb(info->base + UART_IIR);
3085 (void)inb(info->base + UART_MSR);
3087 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3089 clear_bit(TTY_IO_ERROR, &info->tty->flags);
3092 test_and_clear_bit(TTY_IO_ERROR, &info->tty->flags);
3094 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
3097 * and set the speed of the serial port
3099 #if 1 // add by Victor Yu. 12-27-2004
3100 restore_flags(flags);
3102 mxser_change_speed(info, 0);
3104 #if 1 // add by Victor Yu. 12-27-2004
3108 info->flags |= ASYNC_INITIALIZED;
3109 restore_flags(flags);
3114 * This routine will shutdown a serial port; interrupts maybe disabled, and
3115 * DTR is dropped if the hangup on close termio flag is on.
3117 static void mxser_shutdown(struct mxser_struct * info)
3119 unsigned long flags;
3121 if ( !(info->flags & ASYNC_INITIALIZED) )
3125 cli(); /* Disable interrupts */
3128 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
3129 * here so the queue might never be waken up
3131 wake_up_interruptible(&info->delta_msr_wait);
3134 * Free the IRQ, if necessary
3136 if ( info->xmit_buf ) {
3137 free_page((unsigned long)info->xmit_buf);
3142 outb(0x00, info->base + UART_IER);
3144 if ( !info->tty || (info->tty->termios->c_cflag & HUPCL) )
3145 info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
3146 outb(info->MCR, info->base + UART_MCR);
3148 /* clear Rx/Tx FIFO's */
3149 // following add by Victor Yu. 08-30-2002
3150 if ( info->IsMoxaMustChipFlag )
3151 outb((UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT|MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
3153 // above add by Victor Yu. 08-30-2002
3154 outb((UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
3156 /* read data port to reset things */
3157 (void)inb(info->base + UART_RX);
3160 set_bit(TTY_IO_ERROR, &info->tty->flags);
3162 info->flags &= ~ASYNC_INITIALIZED;
3164 // following add by Victor Yu. 09-23-2002
3165 if ( info->IsMoxaMustChipFlag ) {
3166 SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base);
3168 // above add by Victor Yu. 09-23-2002
3170 restore_flags(flags);
3174 * This routine is called to set the UART divisor registers to match
3175 * the specified baud rate for a serial port.
3177 static int mxser_change_speed(struct mxser_struct *info,
3178 struct termios *old_termios)
3181 unsigned cflag, cval, fcr;
3184 unsigned long flags;
3186 if ( !info->tty || !info->tty->termios )
3188 cflag = info->tty->termios->c_cflag;
3189 if ( !(info->base) )
3193 #define B921600 (B460800 +1)
3195 switch( cflag & (CBAUD | CBAUDEX) ){
3196 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-13-2004
3197 case B4000000 : bindex = BAUD_TABLE_NO; break;
3199 case B921600 : bindex = 20; break;
3200 case B460800 : bindex = 19; break;
3201 case B230400 : bindex = 18; break;
3202 case B115200 : bindex = 17; break;
3203 case B57600 : bindex = 16; break;
3204 case B38400 : bindex = 15; break;
3205 case B19200 : bindex = 14; break;
3206 case B9600 : bindex = 13; break;
3207 case B4800 : bindex = 12; break;
3208 case B2400 : bindex = 11; break;
3209 case B1800 : bindex = 10; break;
3210 case B1200 : bindex = 9; break;
3211 case B600 : bindex = 8; break;
3212 case B300 : bindex = 7; break;
3213 case B200 : bindex = 6; break;
3214 case B150 : bindex = 5; break;
3215 case B134 : bindex = 4; break;
3216 case B110 : bindex = 3; break;
3217 case B75 : bindex = 2; break;
3218 case B50 : bindex = 1; break;
3219 default: bindex = 0; break;
3222 if ( bindex == 15 ) {
3223 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI )
3224 bindex = 16; /* 57600 bps */
3225 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI )
3226 bindex = 17; /* 115200 bps */
3228 #ifdef ASYNC_SPD_SHI
3229 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3233 #ifdef ASYNC_SPD_WARP
3234 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3238 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-13-2004
3239 if ( bindex == BAUD_TABLE_NO ) {
3240 quot = info->baud_base / info->speed;
3241 if ( info->speed <= 0 || info->speed > info->MaxCanSetBaudRate )
3246 if ( mxvar_baud_table[bindex] == 134 ) {
3247 quot = (2 * info->baud_base / 269);
3248 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3251 } else if ( mxvar_baud_table[bindex] ) {
3252 quot = info->baud_base / mxvar_baud_table[bindex];
3253 // following add by Victor Yu. 09-04-2002
3254 if ( mxvar_baud_table[bindex] > info->MaxCanSetBaudRate )
3256 // add by Victor Yu. 09-04-2002
3257 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3258 info->speed = mxvar_baud_table[bindex];
3260 if (!quot && old_termios) {
3262 info->tty->termios->c_cflag &= ~CBAUD;
3263 info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
3264 switch( info->tty->termios->c_cflag & (CBAUD | CBAUDEX) ){
3265 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-13-2004
3266 case B4000000 : bindex = BAUD_TABLE_NO; break;
3268 case B921600 : bindex = 20; break;
3269 case B460800 : bindex = 19; break;
3270 case B230400 : bindex = 18; break;
3271 case B115200 : bindex = 17; break;
3272 case B57600 : bindex = 16; break;
3273 case B38400 : bindex = 15; break;
3274 case B19200 : bindex = 14; break;
3275 case B9600 : bindex = 13; break;
3276 case B4800 : bindex = 12; break;
3277 case B2400 : bindex = 11; break;
3278 case B1800 : bindex = 10; break;
3279 case B1200 : bindex = 9; break;
3280 case B600 : bindex = 8; break;
3281 case B300 : bindex = 7; break;
3282 case B200 : bindex = 6; break;
3283 case B150 : bindex = 5; break;
3284 case B134 : bindex = 4; break;
3285 case B110 : bindex = 3; break;
3286 case B75 : bindex = 2; break;
3287 case B50 : bindex = 1; break;
3288 default: bindex = 0; break;
3290 if ( bindex == 15 ) {
3291 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI )
3292 bindex = 16; /* 57600 bps */
3293 if ( (info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI )
3294 bindex = 17; /* 115200 bps */
3295 #ifdef ASYNC_SPD_SHI
3296 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3299 #ifdef ASYNC_SPD_WARP
3300 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3304 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-13-2004
3305 if ( bindex == BAUD_TABLE_NO ) {
3306 quot = info->baud_base / info->speed;
3307 if ( info->speed <= 0 || info->speed > info->MaxCanSetBaudRate )
3312 if ( mxvar_baud_table[bindex] == 134 ) {
3313 quot = (2 * info->baud_base / 269);
3314 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3317 } else if ( mxvar_baud_table[bindex] ) {
3318 quot = info->baud_base / mxvar_baud_table[bindex];
3319 // following add by Victor Yu. 09-04-2002
3320 if ( mxvar_baud_table[bindex] > info->MaxCanSetBaudRate )
3322 // above add by Victor Yu. 09-04-2002
3323 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3324 info->speed = mxvar_baud_table[bindex];
3337 info->timeout = ((info->xmit_fifo_size*HZ*10*quot) / info->baud_base);
3338 info->timeout += HZ/50; /* Add .02 seconds of slop */
3343 info->MCR |= UART_MCR_DTR;
3344 outb(info->MCR, info->base + UART_MCR);
3345 restore_flags(flags);
3349 info->MCR &= ~UART_MCR_DTR;
3350 outb(info->MCR, info->base + UART_MCR);
3351 restore_flags(flags);
3354 /* byte size and parity */
3355 switch ( cflag & CSIZE ) {
3356 case CS5: cval = 0x00; break;
3357 case CS6: cval = 0x01; break;
3358 case CS7: cval = 0x02; break;
3359 case CS8: cval = 0x03; break;
3360 default: cval = 0x00; break; /* too keep GCC shut... */
3362 if ( cflag & CSTOPB )
3364 if ( cflag & PARENB )
3365 cval |= UART_LCR_PARITY;
3367 #define CMSPAR 010000000000
3369 if ( !(cflag & PARODD) ){
3370 cval |= UART_LCR_EPAR;
3372 if ( cflag & CMSPAR )
3373 cval |= UART_LCR_SPAR;
3375 if ( (info->type == PORT_8250) || (info->type == PORT_16450) ) {
3378 fcr = UART_FCR_ENABLE_FIFO;
3379 // following add by Victor Yu. 08-30-2002
3380 if ( info->IsMoxaMustChipFlag ) {
3381 fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
3382 #if 1 // add by Victor Yu. 05-04-2005
3386 SET_MOXA_MUST_FIFO_VALUE(info);
3387 #if 1 // add by Victor Yu. 05-04-2005
3388 restore_flags(flags);
3391 // above add by Victor Yu. 08-30-2002
3393 switch ( info->rx_trigger ) {
3394 case 1: fcr |= UART_FCR_TRIGGER_1; break;
3395 case 4: fcr |= UART_FCR_TRIGGER_4; break;
3396 case 8: fcr |= UART_FCR_TRIGGER_8; break;
3397 default: fcr |= UART_FCR_TRIGGER_14;
3402 /* CTS flow control flag and modem status interrupts */
3403 #if 1 // add by Victor Yu. 12-30-2004
3406 #if 1 // add by Victor Yu. 05-04-2005
3407 outb(cval | UART_LCR_DLAB, info->base + UART_LCR); /* set DLAB */
3408 outb(quot & 0xff, info->base + UART_DLL); /* LS of divisor */
3409 outb(quot >> 8, info->base + UART_DLM); /* MS of divisor */
3410 outb(cval, info->base + UART_LCR); /* reset DLAB */
3411 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3412 if ( info->speed ) {
3413 quot = info->baud_base % info->speed;
3415 if ( (quot % info->speed) > (info->speed / 2) ) {
3416 quot /= info->speed;
3419 quot /= info->speed;
3421 SET_MOXA_MUST_ENUM_VALUE(info->base, quot);
3423 SET_MOXA_MUST_ENUM_VALUE(info->base, 0);
3426 outb(fcr, info->base + UART_FCR); /* set fcr */
3427 #endif // 05-04-2005
3428 #endif // 12-30-2004
3429 #if 0 // mask by Victor Yu. 12-31-2004
3430 info->IER &= ~UART_IER_MSI;
3432 info->MCR &= ~UART_MCR_AFE;
3433 if ( cflag & CRTSCTS ) {
3434 info->flags |= ASYNC_CTS_FLOW;
3435 info->IER |= UART_IER_MSI;
3436 if ( info->type == PORT_16550A ) {
3437 info->MCR |= UART_MCR_AFE;
3439 unsigned char status;
3440 #if 0 // mask by Victor Yu. 12-30-2004
3444 status = inb(info->base + UART_MSR);
3445 #if 0 // mask by Victor Yu. 12-30-2004
3446 restore_flags(flags);
3448 if (info->tty->hw_stopped) {
3449 if (status & UART_MSR_CTS) {
3450 info->tty->hw_stopped = 0;
3451 if (info->type != PORT_16550A) {
3452 info->IER |= UART_IER_THRI;
3453 outb(info->IER, info->base + UART_IER);
3455 set_bit(MXSER_EVENT_TXLOW, &info->event);
3458 if (schedule_task(&info->tqueue) == 0)
3461 schedule_work(&info->tqueue);
3465 if (!(status & UART_MSR_CTS)) {
3466 info->tty->hw_stopped = 1;
3467 if (info->type != PORT_16550A) {
3468 info->IER &= ~UART_IER_THRI;
3469 outb(info->IER, info->base + UART_IER);
3475 info->flags &= ~ASYNC_CTS_FLOW;
3477 #if 0 // add by Victor Yu. 12-27-2004
3481 outb(info->MCR, info->base + UART_MCR);
3482 if ( cflag & CLOCAL ){
3483 info->flags &= ~ASYNC_CHECK_CD;
3485 info->flags |= ASYNC_CHECK_CD;
3486 info->IER |= UART_IER_MSI;
3488 outb(info->IER, info->base + UART_IER);
3489 #if 1 // add by Victor Yu. 12-27-2004
3490 restore_flags(flags);
3494 * Set up parity check flag
3496 info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
3497 if ( I_INPCK(info->tty) )
3498 info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
3499 if ( I_BRKINT(info->tty) || I_PARMRK(info->tty) )
3500 info->read_status_mask |= UART_LSR_BI;
3502 info->ignore_status_mask = 0;
3504 /* This should be safe, but for some broken bits of hardware... */
3505 if ( I_IGNPAR(info->tty) ) {
3506 info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
3507 info->read_status_mask |= UART_LSR_PE | UART_LSR_FE;
3510 if ( I_IGNBRK(info->tty) ) {
3511 info->ignore_status_mask |= UART_LSR_BI;
3512 info->read_status_mask |= UART_LSR_BI;
3514 * If we're ignore parity and break indicators, ignore
3515 * overruns too. (For real raw support).
3517 if ( I_IGNPAR(info->tty) ) {
3518 info->ignore_status_mask |= UART_LSR_OE|UART_LSR_PE|UART_LSR_FE;
3519 info->read_status_mask |= UART_LSR_OE|UART_LSR_PE|UART_LSR_FE;
3523 // following add by Victor Yu. 09-02-2002
3524 if ( info->IsMoxaMustChipFlag ) {
3527 SET_MOXA_MUST_XON1_VALUE(info->base, START_CHAR(info->tty));
3528 SET_MOXA_MUST_XOFF1_VALUE(info->base, STOP_CHAR(info->tty));
3529 if ( I_IXON(info->tty) ) {
3530 #if 1 // add by Victor Yu. 01-04-2005
3531 info->IER |= MOXA_MUST_IER_XINT;
3533 ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
3535 #if 1 // add by Victor Yu. 01-04-2005
3536 info->IER &= ~MOXA_MUST_IER_XINT;
3538 DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
3540 #if 1 // add by Victor Yu. 01-04-2005
3541 outb(info->IER, info->base+UART_IER);
3543 if ( I_IXOFF(info->tty) ) {
3544 ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base);
3546 DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base);
3548 if ( I_IXANY(info->tty) ) {
3549 info->MCR |= MOXA_MUST_MCR_XON_ANY;
3550 ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base);
3552 info->MCR &= ~MOXA_MUST_MCR_XON_ANY;
3553 DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base);
3555 restore_flags(flags);
3557 // above add by Victor Yu. 09-02-2002
3559 #if 0 // mask by Victor Yu. 05-04-2005
3562 outb(cval | UART_LCR_DLAB, info->base + UART_LCR); /* set DLAB */
3563 outb(quot & 0xff, info->base + UART_DLL); /* LS of divisor */
3564 outb(quot >> 8, info->base + UART_DLM); /* MS of divisor */
3565 outb(cval, info->base + UART_LCR); /* reset DLAB */
3566 #ifdef CONFIG_MOXA_SUPPORT_SPECIAL_BAUD_RATE // add by Victor Yu. 08-12-2004
3567 if ( info->speed ) {
3568 quot = info->baud_base % info->speed;
3570 if ( (quot % info->speed) > (info->speed / 2) ) {
3571 quot /= info->speed;
3574 quot /= info->speed;
3576 SET_MOXA_MUST_ENUM_VALUE(info->base, quot);
3578 SET_MOXA_MUST_ENUM_VALUE(info->base, 0);
3581 outb(fcr, info->base + UART_FCR); /* set fcr */
3582 restore_flags(flags);
3589 * ------------------------------------------------------------
3590 * friends of mxser_ioctl()
3591 * ------------------------------------------------------------
3593 static int mxser_get_serial_info(struct mxser_struct * info,
3594 struct serial_struct * retinfo)
3596 struct serial_struct tmp;
3600 memset(&tmp, 0, sizeof(tmp));
3601 tmp.type = info->type;
3602 tmp.line = info->port;
3603 tmp.port = info->base;
3604 tmp.irq = info->irq;
3605 tmp.flags = info->flags;
3606 tmp.baud_base = info->baud_base;
3607 tmp.close_delay = info->close_delay;
3608 tmp.closing_wait = info->closing_wait;
3609 tmp.custom_divisor = info->custom_divisor;
3611 copy_to_user(retinfo, &tmp, sizeof(*retinfo));
3615 static int mxser_set_serial_info(struct mxser_struct * info,
3616 struct serial_struct * new_info)
3618 struct serial_struct new_serial;
3622 if ( !new_info || !info->base )
3624 copy_from_user(&new_serial, new_info, sizeof(new_serial));
3626 if ( (new_serial.irq != info->irq) ||
3627 (new_serial.port != info->base) ||
3628 (new_serial.custom_divisor != info->custom_divisor) ||
3629 (new_serial.baud_base != info->baud_base) )
3632 flags = info->flags & ASYNC_SPD_MASK;
3634 #if (LINUX_VERSION_CODE < VERSION_CODE(2,1,0))
3637 if ( !capable(CAP_SYS_ADMIN)) {
3639 if ( (new_serial.baud_base != info->baud_base) ||
3640 (new_serial.close_delay != info->close_delay) ||
3641 ((new_serial.flags & ~ASYNC_USR_MASK) !=
3642 (info->flags & ~ASYNC_USR_MASK)) )
3644 info->flags = ((info->flags & ~ASYNC_USR_MASK) |
3645 (new_serial.flags & ASYNC_USR_MASK));
3648 * OK, past this point, all the error checking has been done.
3649 * At this point, we start making changes.....
3651 info->flags = ((info->flags & ~ASYNC_FLAGS) |
3652 (new_serial.flags & ASYNC_FLAGS));
3653 info->close_delay = new_serial.close_delay * HZ/100;
3654 info->closing_wait = new_serial.closing_wait * HZ/100;
3655 #if (LINUX_VERSION_CODE >= VERSION_CODE(2,1,0))
3656 info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
3660 /* added by casper, 3/17/2000, for mouse */
3661 info->type = new_serial.type;
3663 // following add by Victor Yu. 09-02-2002
3664 // if ( info->IsMoxaMustChipFlag ) // mask by Victor Yu. 02-10-2004
3665 if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID ) {
3666 info->xmit_fifo_size = 64;
3667 } else if ( info->IsMoxaMustChipFlag == MOXA_MUST_HARDWARE_ID1 ) {
3668 info->xmit_fifo_size = 128;
3670 // above add by Victor Yu. 09-02-2002
3671 if(info->type == PORT_16550A)
3672 info->xmit_fifo_size = 16;
3674 info->xmit_fifo_size = 1;
3676 if ( info->flags & ASYNC_INITIALIZED ) {
3677 if ( flags != (info->flags & ASYNC_SPD_MASK) ){
3678 mxser_change_speed(info,0);
3681 retval = mxser_startup(info);
3687 * mxser_get_lsr_info - get line status register info
3689 * Purpose: Let user call ioctl() to get info when the UART physically
3690 * is emptied. On bus types like RS485, the transmitter must
3691 * release the bus after transmitting. This must be done when
3692 * the transmit shift register is empty, not be done when the
3693 * transmit holding register is empty. This functionality
3694 * allows an RS485 driver to be written in user space.
3696 static int mxser_get_lsr_info(struct mxser_struct * info, unsigned int *value)
3698 unsigned char status;
3699 unsigned int result;
3700 unsigned long flags;
3704 status = inb(info->base + UART_LSR);
3705 restore_flags(flags);
3706 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
3707 put_to_user(result, value);
3712 * This routine sends a break character out the serial port.
3714 static void mxser_send_break(struct mxser_struct * info, int duration)
3716 unsigned long flags;
3717 #if 1 // add by Victor Yu. 12-27-2004
3718 unsigned long timeout;
3723 #if 0 // mask by Victor Yu. 12-27-2004
3724 current->state = TASK_INTERRUPTIBLE;
3728 outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
3729 #if 0 // mask by Victor Yu. 12-27-2004
3730 schedule_timeout(duration);
3731 #else // add by Victor Yu. 12-27-2004
3732 restore_flags(flags);
3733 timeout = jiffies + (unsigned long)duration;
3735 current->state = TASK_INTERRUPTIBLE;
3736 schedule_timeout(5);
3737 if ( time_after(jiffies, timeout) )
3743 outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
3744 restore_flags(flags);
3747 static int mxser_get_modem_info(struct mxser_struct * info,
3748 unsigned int *value)
3750 unsigned char control, status;
3751 unsigned int result;
3752 unsigned long flags;
3756 control = info->MCR;
3757 status = inb(info->base + UART_MSR);
3758 #if 0 // mask by Victor Yu. 12-30-2004, I think that we donot need to do it. Because the interrupt service will do it.
3759 if ( status & UART_MSR_ANY_DELTA )
3760 mxser_check_modem_status(info, status);
3762 restore_flags(flags);
3763 result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
3764 ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
3765 ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
3766 ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
3767 ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
3768 ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
3769 put_to_user(result, value);
3773 static int mxser_set_modem_info(struct mxser_struct * info, unsigned int cmd,
3774 unsigned int *value)
3778 unsigned long flags;
3780 error = verify_area(VERIFY_READ, value, sizeof(int));
3783 get_from_user(arg,value);
3784 #if 1 // add by Victor Yu. 12-30-2004
3790 if ( arg & TIOCM_RTS )
3791 info->MCR |= UART_MCR_RTS;
3792 if ( arg & TIOCM_DTR )
3793 info->MCR |= UART_MCR_DTR;
3796 if ( arg & TIOCM_RTS )
3797 info->MCR &= ~UART_MCR_RTS;
3798 if ( arg & TIOCM_DTR )
3799 info->MCR &= ~UART_MCR_DTR;
3802 info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) |
3803 ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) |
3804 ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
3807 #if 1 // add by Victor Yu. 12-30-2004
3808 restore_flags(flags);
3812 #if 0 // mask by Victor Yu. 12-30-2004
3816 outb(info->MCR, info->base + UART_MCR);
3817 restore_flags(flags);