blob: 5a4c80d38c6522cc64058bb93e3f6d8c1059a671 [file] [log] [blame]
Jiri Slaby037ad482006-12-08 02:38:11 -08001/*
2 * mxser.c -- MOXA Smartio/Industio family multiport serial driver.
3 *
Jiri Slaby3306ce32006-12-08 02:38:13 -08004 * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com.tw).
Jiri Slaby037ad482006-12-08 02:38:11 -08005 *
6 * This code is loosely based on the Linux serial driver, written by
7 * Linus Torvalds, Theodore T'so and others.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
Jiri Slaby037ad482006-12-08 02:38:11 -080023 * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
24 * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com.
25 * - Fixed x86_64 cleanness
26 * - Fixed sleep with spinlock held in mxser_send_break
27 */
28
29
30#include <linux/module.h>
31#include <linux/autoconf.h>
32#include <linux/errno.h>
33#include <linux/signal.h>
34#include <linux/sched.h>
35#include <linux/timer.h>
36#include <linux/interrupt.h>
37#include <linux/tty.h>
38#include <linux/tty_flip.h>
39#include <linux/serial.h>
40#include <linux/serial_reg.h>
41#include <linux/major.h>
42#include <linux/string.h>
43#include <linux/fcntl.h>
44#include <linux/ptrace.h>
45#include <linux/gfp.h>
46#include <linux/ioport.h>
47#include <linux/mm.h>
48#include <linux/smp_lock.h>
49#include <linux/delay.h>
50#include <linux/pci.h>
51
52#include <asm/system.h>
53#include <asm/io.h>
54#include <asm/irq.h>
55#include <asm/bitops.h>
56#include <asm/uaccess.h>
57
Jiri Slaby771f2d12006-12-08 02:38:12 -080058#include "mxser_new.h"
Jiri Slaby037ad482006-12-08 02:38:11 -080059
Jiri Slaby55b307d2006-12-08 02:38:14 -080060#define MXSER_VERSION "2.0"
Jiri Slaby037ad482006-12-08 02:38:11 -080061#define MXSERMAJOR 174
62#define MXSERCUMAJOR 175
63
64#define MXSER_EVENT_TXLOW 1
65#define MXSER_EVENT_HANGUP 2
66
67#define MXSER_BOARDS 4 /* Max. boards */
68#define MXSER_PORTS 32 /* Max. ports */
69#define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */
Jiri Slaby3306ce32006-12-08 02:38:13 -080070#define MXSER_ISR_PASS_LIMIT 99999L
Jiri Slaby037ad482006-12-08 02:38:11 -080071
72#define MXSER_ERR_IOADDR -1
73#define MXSER_ERR_IRQ -2
74#define MXSER_ERR_IRQ_CONFLIT -3
75#define MXSER_ERR_VECTOR -4
76
77#define SERIAL_TYPE_NORMAL 1
78#define SERIAL_TYPE_CALLOUT 2
79
80#define WAKEUP_CHARS 256
81
82#define UART_MCR_AFE 0x20
83#define UART_LSR_SPECIAL 0x1E
84
85#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
86 IXON|IXOFF))
87
Jiri Slaby037ad482006-12-08 02:38:11 -080088#define C168_ASIC_ID 1
89#define C104_ASIC_ID 2
90#define C102_ASIC_ID 0xB
91#define CI132_ASIC_ID 4
92#define CI134_ASIC_ID 3
93#define CI104J_ASIC_ID 5
94
95enum {
96 MXSER_BOARD_C168_ISA = 1,
97 MXSER_BOARD_C104_ISA,
98 MXSER_BOARD_CI104J,
99 MXSER_BOARD_C168_PCI,
100 MXSER_BOARD_C104_PCI,
101 MXSER_BOARD_C102_ISA,
102 MXSER_BOARD_CI132,
103 MXSER_BOARD_CI134,
104 MXSER_BOARD_CP132,
105 MXSER_BOARD_CP114,
106 MXSER_BOARD_CT114,
107 MXSER_BOARD_CP102,
108 MXSER_BOARD_CP104U,
109 MXSER_BOARD_CP168U,
110 MXSER_BOARD_CP132U,
111 MXSER_BOARD_CP134U,
112 MXSER_BOARD_CP104JU,
113 MXSER_BOARD_RC7000,
114 MXSER_BOARD_CP118U,
115 MXSER_BOARD_CP102UL,
116 MXSER_BOARD_CP102U,
Jiri Slaby3306ce32006-12-08 02:38:13 -0800117 MXSER_BOARD_CP118EL,
118 MXSER_BOARD_CP168EL,
119 MXSER_BOARD_CP104EL
Jiri Slaby037ad482006-12-08 02:38:11 -0800120};
121
122static char *mxser_brdname[] = {
123 "C168 series",
124 "C104 series",
125 "CI-104J series",
126 "C168H/PCI series",
127 "C104H/PCI series",
128 "C102 series",
129 "CI-132 series",
130 "CI-134 series",
131 "CP-132 series",
132 "CP-114 series",
133 "CT-114 series",
134 "CP-102 series",
135 "CP-104U series",
136 "CP-168U series",
137 "CP-132U series",
138 "CP-134U series",
139 "CP-104JU series",
140 "Moxa UC7000 Serial",
141 "CP-118U series",
142 "CP-102UL series",
143 "CP-102U series",
Jiri Slaby3306ce32006-12-08 02:38:13 -0800144 "CP-118EL series",
145 "CP-168EL series",
146 "CP-104EL series"
Jiri Slaby037ad482006-12-08 02:38:11 -0800147};
148
149static int mxser_numports[] = {
150 8, /* C168-ISA */
151 4, /* C104-ISA */
152 4, /* CI104J */
153 8, /* C168-PCI */
154 4, /* C104-PCI */
155 2, /* C102-ISA */
156 2, /* CI132 */
157 4, /* CI134 */
158 2, /* CP132 */
159 4, /* CP114 */
160 4, /* CT114 */
161 2, /* CP102 */
162 4, /* CP104U */
163 8, /* CP168U */
164 2, /* CP132U */
165 4, /* CP134U */
166 4, /* CP104JU */
167 8, /* RC7000 */
168 8, /* CP118U */
169 2, /* CP102UL */
170 2, /* CP102U */
Jiri Slaby3306ce32006-12-08 02:38:13 -0800171 8, /* CP118EL */
172 8, /* CP168EL */
173 4 /* CP104EL */
Jiri Slaby037ad482006-12-08 02:38:11 -0800174};
175
176#define UART_TYPE_NUM 2
177
178static const unsigned int Gmoxa_uart_id[UART_TYPE_NUM] = {
179 MOXA_MUST_MU150_HWID,
180 MOXA_MUST_MU860_HWID
181};
182
183/* This is only for PCI */
184#define UART_INFO_NUM 3
185struct mxpciuart_info {
186 int type;
187 int tx_fifo;
188 int rx_fifo;
189 int xmit_fifo_size;
190 int rx_high_water;
191 int rx_trigger;
192 int rx_low_water;
193 long max_baud;
194};
195
196static const struct mxpciuart_info Gpci_uart_info[UART_INFO_NUM] = {
197 {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L},
198 {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L},
199 {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L}
200};
201
202
Jiri Slaby037ad482006-12-08 02:38:11 -0800203static struct pci_device_id mxser_pcibrds[] = {
Jiri Slaby3306ce32006-12-08 02:38:13 -0800204 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168),
205 .driver_data = MXSER_BOARD_C168_PCI },
206 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104),
207 .driver_data = MXSER_BOARD_C104_PCI },
208 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132),
209 .driver_data = MXSER_BOARD_CP132 },
210 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114),
211 .driver_data = MXSER_BOARD_CP114 },
212 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114),
213 .driver_data = MXSER_BOARD_CT114 },
214 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102),
215 .driver_data = MXSER_BOARD_CP102 },
216 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U),
217 .driver_data = MXSER_BOARD_CP104U },
218 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U),
219 .driver_data = MXSER_BOARD_CP168U },
220 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U),
221 .driver_data = MXSER_BOARD_CP132U },
222 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U),
223 .driver_data = MXSER_BOARD_CP134U },
224 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU),
225 .driver_data = MXSER_BOARD_CP104JU },
226 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000),
227 .driver_data = MXSER_BOARD_RC7000 },
228 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U),
229 .driver_data = MXSER_BOARD_CP118U },
230 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL),
231 .driver_data = MXSER_BOARD_CP102UL },
232 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U),
233 .driver_data = MXSER_BOARD_CP102U },
234 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL),
235 .driver_data = MXSER_BOARD_CP118EL },
236 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL),
237 .driver_data = MXSER_BOARD_CP168EL },
238 { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL),
239 .driver_data = MXSER_BOARD_CP104EL },
240 { }
Jiri Slaby037ad482006-12-08 02:38:11 -0800241};
Jiri Slaby037ad482006-12-08 02:38:11 -0800242MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
243
Jiri Slaby037ad482006-12-08 02:38:11 -0800244static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
245static int ttymajor = MXSERMAJOR;
246static int calloutmajor = MXSERCUMAJOR;
247static int verbose = 0;
248
249/* Variables for insmod */
250
251MODULE_AUTHOR("Casper Yang");
252MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
253module_param_array(ioaddr, int, NULL, 0);
254module_param(ttymajor, int, 0);
Jiri Slaby037ad482006-12-08 02:38:11 -0800255module_param(verbose, bool, 0);
256MODULE_LICENSE("GPL");
257
258struct mxser_log {
259 int tick;
260 unsigned long rxcnt[MXSER_PORTS];
261 unsigned long txcnt[MXSER_PORTS];
262};
263
264
265struct mxser_mon {
266 unsigned long rxcnt;
267 unsigned long txcnt;
268 unsigned long up_rxcnt;
269 unsigned long up_txcnt;
270 int modem_status;
271 unsigned char hold_reason;
272};
273
274struct mxser_mon_ext {
275 unsigned long rx_cnt[32];
276 unsigned long tx_cnt[32];
277 unsigned long up_rxcnt[32];
278 unsigned long up_txcnt[32];
279 int modem_status[32];
280
281 long baudrate[32];
282 int databits[32];
283 int stopbits[32];
284 int parity[32];
285 int flowctrl[32];
286 int fifo[32];
287 int iftype[32];
288};
289
Jiri Slaby55b307d2006-12-08 02:38:14 -0800290struct mxser_board;
Jiri Slaby037ad482006-12-08 02:38:11 -0800291
Jiri Slaby55b307d2006-12-08 02:38:14 -0800292struct mxser_port {
293 struct mxser_board *board;
294 struct tty_struct *tty;
295
296 unsigned long ioaddr;
297 unsigned long opmode_ioaddr;
298 int max_baud;
299
Jiri Slaby037ad482006-12-08 02:38:11 -0800300 int rx_high_water;
301 int rx_trigger; /* Rx fifo trigger level */
302 int rx_low_water;
303 int baud_base; /* max. speed */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800304 long realbaud;
Jiri Slaby037ad482006-12-08 02:38:11 -0800305 int type; /* UART type */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800306 int flags; /* defined in tty.h */
307 long session; /* Session of opening process */
308 long pgrp; /* pgrp of opening process */
309
310 int x_char; /* xon/xoff character */
311 int IER; /* Interrupt Enable Register */
312 int MCR; /* Modem control register */
313
314 unsigned char stop_rx;
315 unsigned char ldisc_stop_rx;
316
317 int custom_divisor;
318 int close_delay;
319 unsigned short closing_wait;
320 unsigned char err_shadow;
321 unsigned long event;
322
323 int count; /* # of fd on device */
324 int blocked_open; /* # of blocked opens */
325 struct async_icount icount; /* kernel counters for 4 input interrupts */
326 int timeout;
327
Jiri Slaby037ad482006-12-08 02:38:11 -0800328 int read_status_mask;
329 int ignore_status_mask;
330 int xmit_fifo_size;
Jiri Slaby037ad482006-12-08 02:38:11 -0800331 unsigned char *xmit_buf;
332 int xmit_head;
333 int xmit_tail;
334 int xmit_cnt;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800335
Jiri Slaby037ad482006-12-08 02:38:11 -0800336 struct termios normal_termios;
337 struct termios callout_termios;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800338
339 struct mxser_mon mon_data;
340
341 spinlock_t slock;
342 struct work_struct tqueue;
Jiri Slaby037ad482006-12-08 02:38:11 -0800343 wait_queue_head_t open_wait;
344 wait_queue_head_t close_wait;
345 wait_queue_head_t delta_msr_wait;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800346};
347
348struct mxser_board {
349 struct pci_dev *pdev; /* temporary (until pci probing) */
350
351 int irq;
352 int board_type;
353 unsigned int nports;
354 unsigned long vector;
355 unsigned long vector_mask;
356
357 int chip_flag;
358 int uart_type;
359
360 struct mxser_port ports[MXSER_PORTS_PER_BOARD];
Jiri Slaby037ad482006-12-08 02:38:11 -0800361};
362
363struct mxser_mstatus {
364 tcflag_t cflag;
365 int cts;
366 int dsr;
367 int ri;
368 int dcd;
369};
370
371static struct mxser_mstatus GMStatus[MXSER_PORTS];
372
373static int mxserBoardCAP[MXSER_BOARDS] = {
374 0, 0, 0, 0
375 /* 0x180, 0x280, 0x200, 0x320 */
376};
377
Jiri Slaby55b307d2006-12-08 02:38:14 -0800378static struct mxser_board mxser_boards[MXSER_BOARDS];
Jiri Slaby037ad482006-12-08 02:38:11 -0800379static struct tty_driver *mxvar_sdriver;
Jiri Slaby037ad482006-12-08 02:38:11 -0800380static struct tty_struct *mxvar_tty[MXSER_PORTS + 1];
381static struct termios *mxvar_termios[MXSER_PORTS + 1];
382static struct termios *mxvar_termios_locked[MXSER_PORTS + 1];
383static struct mxser_log mxvar_log;
384static int mxvar_diagflag;
385static unsigned char mxser_msr[MXSER_PORTS + 1];
386static struct mxser_mon_ext mon_data_ext;
387static int mxser_set_baud_method[MXSER_PORTS + 1];
388static spinlock_t gm_lock;
389
390/*
Jiri Slaby037ad482006-12-08 02:38:11 -0800391 * static functions:
392 */
393
Jiri Slaby037ad482006-12-08 02:38:11 -0800394static int mxser_init(void);
395
396/* static void mxser_poll(unsigned long); */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800397static int mxser_get_ISA_conf(int, struct mxser_board *);
Jiri Slaby037ad482006-12-08 02:38:11 -0800398static void mxser_do_softint(void *);
399static int mxser_open(struct tty_struct *, struct file *);
400static void mxser_close(struct tty_struct *, struct file *);
401static int mxser_write(struct tty_struct *, const unsigned char *, int);
402static int mxser_write_room(struct tty_struct *);
403static void mxser_flush_buffer(struct tty_struct *);
404static int mxser_chars_in_buffer(struct tty_struct *);
405static void mxser_flush_chars(struct tty_struct *);
406static void mxser_put_char(struct tty_struct *, unsigned char);
407static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);
408static int mxser_ioctl_special(unsigned int, void __user *);
409static void mxser_throttle(struct tty_struct *);
410static void mxser_unthrottle(struct tty_struct *);
411static void mxser_set_termios(struct tty_struct *, struct termios *);
412static void mxser_stop(struct tty_struct *);
413static void mxser_start(struct tty_struct *);
414static void mxser_hangup(struct tty_struct *);
415static void mxser_rs_break(struct tty_struct *, int);
416static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *);
Jiri Slaby55b307d2006-12-08 02:38:14 -0800417static void mxser_receive_chars(struct mxser_port *, int *);
418static void mxser_transmit_chars(struct mxser_port *);
419static void mxser_check_modem_status(struct mxser_port *, int);
420static int mxser_block_til_ready(struct tty_struct *, struct file *,
421 struct mxser_port *);
422static int mxser_startup(struct mxser_port *);
423static void mxser_shutdown(struct mxser_port *);
424static int mxser_change_speed(struct mxser_port *, struct termios *);
425static int mxser_get_serial_info(struct mxser_port *,
426 struct serial_struct __user *);
427static int mxser_set_serial_info(struct mxser_port *,
428 struct serial_struct __user *);
429static int mxser_get_lsr_info(struct mxser_port *, unsigned int __user *);
430static void mxser_send_break(struct mxser_port *, int);
Jiri Slaby037ad482006-12-08 02:38:11 -0800431static int mxser_tiocmget(struct tty_struct *, struct file *);
Jiri Slaby55b307d2006-12-08 02:38:14 -0800432static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int,
433 unsigned int);
434static int mxser_set_baud(struct mxser_port *, long);
435static void mxser_wait_until_sent(struct tty_struct *, int);
Jiri Slaby037ad482006-12-08 02:38:11 -0800436
Jiri Slaby55b307d2006-12-08 02:38:14 -0800437static void mxser_startrx(struct tty_struct *);
438static void mxser_stoprx(struct tty_struct *);
Jiri Slaby037ad482006-12-08 02:38:11 -0800439
440
441static int CheckIsMoxaMust(int io)
442{
443 u8 oldmcr, hwid;
444 int i;
445
446 outb(0, io + UART_LCR);
447 DISABLE_MOXA_MUST_ENCHANCE_MODE(io);
448 oldmcr = inb(io + UART_MCR);
449 outb(0, io + UART_MCR);
450 SET_MOXA_MUST_XON1_VALUE(io, 0x11);
451 if ((hwid = inb(io + UART_MCR)) != 0) {
452 outb(oldmcr, io + UART_MCR);
453 return MOXA_OTHER_UART;
454 }
455
456 GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
457 for (i = 0; i < UART_TYPE_NUM; i++) {
458 if (hwid == Gmoxa_uart_id[i])
459 return (int)hwid;
460 }
461 return MOXA_OTHER_UART;
462}
463
464/* above is modified by Victor Yu. 08-15-2002 */
465
466static const struct tty_operations mxser_ops = {
467 .open = mxser_open,
468 .close = mxser_close,
469 .write = mxser_write,
470 .put_char = mxser_put_char,
471 .flush_chars = mxser_flush_chars,
472 .write_room = mxser_write_room,
473 .chars_in_buffer = mxser_chars_in_buffer,
474 .flush_buffer = mxser_flush_buffer,
475 .ioctl = mxser_ioctl,
476 .throttle = mxser_throttle,
477 .unthrottle = mxser_unthrottle,
478 .set_termios = mxser_set_termios,
479 .stop = mxser_stop,
480 .start = mxser_start,
481 .hangup = mxser_hangup,
482 .break_ctl = mxser_rs_break,
483 .wait_until_sent = mxser_wait_until_sent,
484 .tiocmget = mxser_tiocmget,
485 .tiocmset = mxser_tiocmset,
486};
487
488/*
489 * The MOXA Smartio/Industio serial driver boot-time initialization code!
490 */
491
492static int __init mxser_module_init(void)
493{
494 int ret;
495
496 if (verbose)
497 printk(KERN_DEBUG "Loading module mxser ...\n");
Jiri Slaby3306ce32006-12-08 02:38:13 -0800498 printk(KERN_INFO "This is mxser driver version 1.9.1 and needs TESTING."
499 "If your are willing to test this driver, please report to "
500 "jirislaby@gmail.com. Thanks.\n");
Jiri Slaby037ad482006-12-08 02:38:11 -0800501 ret = mxser_init();
502 if (verbose)
503 printk(KERN_DEBUG "Done.\n");
504 return ret;
505}
506
507static void __exit mxser_module_exit(void)
508{
509 int i, err;
510
511 if (verbose)
512 printk(KERN_DEBUG "Unloading module mxser ...\n");
513
514 err = tty_unregister_driver(mxvar_sdriver);
515 if (!err)
516 put_tty_driver(mxvar_sdriver);
517 else
518 printk(KERN_ERR "Couldn't unregister MOXA Smartio/Industio family serial driver\n");
519
520 for (i = 0; i < MXSER_BOARDS; i++) {
521 struct pci_dev *pdev;
522
Jiri Slaby55b307d2006-12-08 02:38:14 -0800523 if (mxser_boards[i].board_type == -1)
Jiri Slaby037ad482006-12-08 02:38:11 -0800524 continue;
525 else {
Jiri Slaby55b307d2006-12-08 02:38:14 -0800526 pdev = mxser_boards[i].pdev;
527 free_irq(mxser_boards[i].irq, &mxser_boards[i]);
Jiri Slaby037ad482006-12-08 02:38:11 -0800528 if (pdev != NULL) { /* PCI */
Jiri Slaby59628012006-12-08 02:38:16 -0800529 pci_release_region(pdev, 2);
530 pci_release_region(pdev, 3);
Jiri Slaby037ad482006-12-08 02:38:11 -0800531 pci_dev_put(pdev);
532 } else {
Jiri Slaby55b307d2006-12-08 02:38:14 -0800533 release_region(mxser_boards[i].ports[0].ioaddr, 8 * mxser_boards[i].nports);
534 release_region(mxser_boards[i].vector, 1);
Jiri Slaby037ad482006-12-08 02:38:11 -0800535 }
536 }
537 }
538 if (verbose)
539 printk(KERN_DEBUG "Done.\n");
540}
541
Jiri Slaby55b307d2006-12-08 02:38:14 -0800542static void process_txrx_fifo(struct mxser_port *info)
Jiri Slaby037ad482006-12-08 02:38:11 -0800543{
544 int i;
545
546 if ((info->type == PORT_16450) || (info->type == PORT_8250)) {
547 info->rx_trigger = 1;
548 info->rx_high_water = 1;
549 info->rx_low_water = 1;
550 info->xmit_fifo_size = 1;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800551 } else
552 for (i = 0; i < UART_INFO_NUM; i++)
553 if (info->board->chip_flag == Gpci_uart_info[i].type) {
Jiri Slaby037ad482006-12-08 02:38:11 -0800554 info->rx_trigger = Gpci_uart_info[i].rx_trigger;
555 info->rx_low_water = Gpci_uart_info[i].rx_low_water;
556 info->rx_high_water = Gpci_uart_info[i].rx_high_water;
557 info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size;
558 break;
559 }
Jiri Slaby037ad482006-12-08 02:38:11 -0800560}
561
Jiri Slaby943f2952006-12-08 02:38:15 -0800562static int __devinit mxser_initbrd(struct mxser_board *brd)
Jiri Slaby037ad482006-12-08 02:38:11 -0800563{
Jiri Slaby55b307d2006-12-08 02:38:14 -0800564 struct mxser_port *info;
565 unsigned int i;
Jiri Slaby037ad482006-12-08 02:38:11 -0800566 int retval;
Jiri Slaby037ad482006-12-08 02:38:11 -0800567
Jiri Slaby037ad482006-12-08 02:38:11 -0800568 /*if (verbose) */ {
Jiri Slaby037ad482006-12-08 02:38:11 -0800569 printk(" max. baud rate = %d bps.\n",
Jiri Slaby55b307d2006-12-08 02:38:14 -0800570 brd->ports[0].max_baud);
Jiri Slaby037ad482006-12-08 02:38:11 -0800571 }
572
Jiri Slaby55b307d2006-12-08 02:38:14 -0800573 for (i = 0; i < brd->nports; i++) {
574 info = &brd->ports[i];
575 info->board = brd;
Jiri Slaby037ad482006-12-08 02:38:11 -0800576 info->stop_rx = 0;
577 info->ldisc_stop_rx = 0;
578
Jiri Slaby037ad482006-12-08 02:38:11 -0800579 /* Enhance mode enabled here */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800580 if (brd->chip_flag != MOXA_OTHER_UART)
581 ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -0800582
583 info->flags = ASYNC_SHARE_IRQ;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800584 info->type = brd->uart_type;
Jiri Slaby037ad482006-12-08 02:38:11 -0800585
586 process_txrx_fifo(info);
587
Jiri Slaby55b307d2006-12-08 02:38:14 -0800588 info->custom_divisor = info->baud_base * 16;
Jiri Slaby037ad482006-12-08 02:38:11 -0800589 info->close_delay = 5 * HZ / 10;
590 info->closing_wait = 30 * HZ;
591 INIT_WORK(&info->tqueue, mxser_do_softint, info);
592 info->normal_termios = mxvar_sdriver->init_termios;
593 init_waitqueue_head(&info->open_wait);
594 init_waitqueue_head(&info->close_wait);
595 init_waitqueue_head(&info->delta_msr_wait);
596 memset(&info->mon_data, 0, sizeof(struct mxser_mon));
597 info->err_shadow = 0;
598 spin_lock_init(&info->slock);
Jiri Slaby55b307d2006-12-08 02:38:14 -0800599
600 /* before set INT ISR, disable all int */
601 outb(inb(info->ioaddr + UART_IER) & 0xf0,
602 info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -0800603 }
604 /*
605 * Allocate the IRQ if necessary
606 */
607
Jiri Slaby55b307d2006-12-08 02:38:14 -0800608 retval = request_irq(brd->irq, mxser_interrupt,
609 (brd->ports[0].flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED :
610 IRQF_DISABLED, "mxser", brd);
Jiri Slaby037ad482006-12-08 02:38:11 -0800611 if (retval) {
Jiri Slaby55b307d2006-12-08 02:38:14 -0800612 printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
613 "conflict with another device.\n",
614 mxser_brdname[brd->board_type - 1], brd->irq);
Jiri Slaby037ad482006-12-08 02:38:11 -0800615 return retval;
616 }
617 return 0;
618}
619
Jiri Slaby943f2952006-12-08 02:38:15 -0800620static int __init mxser_get_PCI_conf(int board_type, struct mxser_board *brd,
Jiri Slaby55b307d2006-12-08 02:38:14 -0800621 struct pci_dev *pdev)
Jiri Slaby037ad482006-12-08 02:38:11 -0800622{
Jiri Slaby55b307d2006-12-08 02:38:14 -0800623 unsigned int i, j;
Jiri Slaby3306ce32006-12-08 02:38:13 -0800624 unsigned long ioaddress;
Jiri Slaby7a7a5c32006-12-08 02:38:17 -0800625 int retval;
Jiri Slaby037ad482006-12-08 02:38:11 -0800626
627 /* io address */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800628 brd->board_type = board_type;
629 brd->nports = mxser_numports[board_type - 1];
Jiri Slaby037ad482006-12-08 02:38:11 -0800630 ioaddress = pci_resource_start(pdev, 2);
Jiri Slaby7a7a5c32006-12-08 02:38:17 -0800631 retval = pci_request_region(pdev, 2, "mxser(IO)");
632 if (retval)
633 goto err;
Jiri Slaby037ad482006-12-08 02:38:11 -0800634
Jiri Slaby55b307d2006-12-08 02:38:14 -0800635 for (i = 0; i < brd->nports; i++)
636 brd->ports[i].ioaddr = ioaddress + 8 * i;
Jiri Slaby037ad482006-12-08 02:38:11 -0800637
638 /* vector */
639 ioaddress = pci_resource_start(pdev, 3);
Jiri Slaby7a7a5c32006-12-08 02:38:17 -0800640 retval = pci_request_region(pdev, 3, "mxser(vector)");
641 if (retval)
642 goto err_relio;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800643 brd->vector = ioaddress;
Jiri Slaby037ad482006-12-08 02:38:11 -0800644
645 /* irq */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800646 brd->irq = pdev->irq;
Jiri Slaby037ad482006-12-08 02:38:11 -0800647
Jiri Slaby55b307d2006-12-08 02:38:14 -0800648 brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr);
649 brd->uart_type = PORT_16550A;
650 brd->vector_mask = 0;
Jiri Slaby037ad482006-12-08 02:38:11 -0800651
Jiri Slaby55b307d2006-12-08 02:38:14 -0800652 for (i = 0; i < brd->nports; i++) {
Jiri Slaby037ad482006-12-08 02:38:11 -0800653 for (j = 0; j < UART_INFO_NUM; j++) {
Jiri Slaby55b307d2006-12-08 02:38:14 -0800654 if (Gpci_uart_info[j].type == brd->chip_flag) {
655 brd->ports[i].max_baud =
656 Gpci_uart_info[j].max_baud;
Jiri Slaby037ad482006-12-08 02:38:11 -0800657
658 /* exception....CP-102 */
659 if (board_type == MXSER_BOARD_CP102)
Jiri Slaby55b307d2006-12-08 02:38:14 -0800660 brd->ports[i].max_baud = 921600;
Jiri Slaby037ad482006-12-08 02:38:11 -0800661 break;
662 }
663 }
664 }
665
Jiri Slaby55b307d2006-12-08 02:38:14 -0800666 if (brd->chip_flag == MOXA_MUST_MU860_HWID) {
667 for (i = 0; i < brd->nports; i++) {
Jiri Slaby037ad482006-12-08 02:38:11 -0800668 if (i < 4)
Jiri Slaby55b307d2006-12-08 02:38:14 -0800669 brd->ports[i].opmode_ioaddr = ioaddress + 4;
Jiri Slaby037ad482006-12-08 02:38:11 -0800670 else
Jiri Slaby55b307d2006-12-08 02:38:14 -0800671 brd->ports[i].opmode_ioaddr = ioaddress + 0x0c;
Jiri Slaby037ad482006-12-08 02:38:11 -0800672 }
673 outb(0, ioaddress + 4); /* default set to RS232 mode */
674 outb(0, ioaddress + 0x0c); /* default set to RS232 mode */
675 }
676
Jiri Slaby55b307d2006-12-08 02:38:14 -0800677 for (i = 0; i < brd->nports; i++) {
678 brd->vector_mask |= (1 << i);
679 brd->ports[i].baud_base = 921600;
Jiri Slaby037ad482006-12-08 02:38:11 -0800680 }
681 return 0;
Jiri Slaby7a7a5c32006-12-08 02:38:17 -0800682err_relio:
683 pci_release_region(pdev, 2);
684err:
685 return retval;
Jiri Slaby037ad482006-12-08 02:38:11 -0800686}
Jiri Slaby037ad482006-12-08 02:38:11 -0800687
Jiri Slaby943f2952006-12-08 02:38:15 -0800688static int __init mxser_init(void)
Jiri Slaby037ad482006-12-08 02:38:11 -0800689{
Jiri Slaby037ad482006-12-08 02:38:11 -0800690 struct pci_dev *pdev = NULL;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800691 struct mxser_board *brd;
692 unsigned int i, m;
693 int retval, b, n;
Jiri Slaby037ad482006-12-08 02:38:11 -0800694
695 mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
696 if (!mxvar_sdriver)
697 return -ENOMEM;
698 spin_lock_init(&gm_lock);
699
Jiri Slaby55b307d2006-12-08 02:38:14 -0800700 for (i = 0; i < MXSER_BOARDS; i++)
701 mxser_boards[i].board_type = -1;
Jiri Slaby037ad482006-12-08 02:38:11 -0800702
703 printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
704 MXSER_VERSION);
705
706 /* Initialize the tty_driver structure */
707 memset(mxvar_sdriver, 0, sizeof(struct tty_driver));
708 mxvar_sdriver->magic = TTY_DRIVER_MAGIC;
709 mxvar_sdriver->name = "ttyM";
710 mxvar_sdriver->major = ttymajor;
711 mxvar_sdriver->minor_start = 0;
712 mxvar_sdriver->num = MXSER_PORTS + 1;
713 mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
714 mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
715 mxvar_sdriver->init_termios = tty_std_termios;
716 mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
717 mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW;
718 tty_set_operations(mxvar_sdriver, &mxser_ops);
719 mxvar_sdriver->ttys = mxvar_tty;
720 mxvar_sdriver->termios = mxvar_termios;
721 mxvar_sdriver->termios_locked = mxvar_termios_locked;
722
723 mxvar_diagflag = 0;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800724 memset(mxser_boards, 0, sizeof(mxser_boards));
Jiri Slaby037ad482006-12-08 02:38:11 -0800725 memset(&mxvar_log, 0, sizeof(struct mxser_log));
726
727 memset(&mxser_msr, 0, sizeof(unsigned char) * (MXSER_PORTS + 1));
728 memset(&mon_data_ext, 0, sizeof(struct mxser_mon_ext));
729 memset(&mxser_set_baud_method, 0, sizeof(int) * (MXSER_PORTS + 1));
Jiri Slaby037ad482006-12-08 02:38:11 -0800730
731 m = 0;
732 /* Start finding ISA boards here */
733 for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
734 int cap;
735
736 if (!(cap = mxserBoardCAP[b]))
737 continue;
738
Jiri Slaby55b307d2006-12-08 02:38:14 -0800739 brd = &mxser_boards[m];
740 retval = mxser_get_ISA_conf(cap, brd);
Jiri Slaby037ad482006-12-08 02:38:11 -0800741
742 if (retval != 0)
743 printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n",
Jiri Slaby55b307d2006-12-08 02:38:14 -0800744 mxser_brdname[brd->board_type - 1], ioaddr[b]);
Jiri Slaby037ad482006-12-08 02:38:11 -0800745
746 if (retval <= 0) {
747 if (retval == MXSER_ERR_IRQ)
748 printk(KERN_ERR "Invalid interrupt number, "
749 "board not configured\n");
750 else if (retval == MXSER_ERR_IRQ_CONFLIT)
751 printk(KERN_ERR "Invalid interrupt number, "
752 "board not configured\n");
753 else if (retval == MXSER_ERR_VECTOR)
754 printk(KERN_ERR "Invalid interrupt vector, "
755 "board not configured\n");
756 else if (retval == MXSER_ERR_IOADDR)
757 printk(KERN_ERR "Invalid I/O address, "
758 "board not configured\n");
759
760 continue;
761 }
762
Jiri Slaby55b307d2006-12-08 02:38:14 -0800763 brd->pdev = NULL;
Jiri Slaby037ad482006-12-08 02:38:11 -0800764
Jiri Slaby037ad482006-12-08 02:38:11 -0800765 /* mxser_initbrd will hook ISR. */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800766 if (mxser_initbrd(brd) < 0)
Jiri Slaby037ad482006-12-08 02:38:11 -0800767 continue;
768
769 m++;
770 }
771
772 /* Start finding ISA boards from module arg */
773 for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
Jiri Slaby3306ce32006-12-08 02:38:13 -0800774 unsigned long cap;
Jiri Slaby037ad482006-12-08 02:38:11 -0800775
776 if (!(cap = ioaddr[b]))
777 continue;
778
Jiri Slaby55b307d2006-12-08 02:38:14 -0800779 brd = &mxser_boards[m];
780 retval = mxser_get_ISA_conf(cap, &mxser_boards[m]);
Jiri Slaby037ad482006-12-08 02:38:11 -0800781
782 if (retval != 0)
783 printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n",
Jiri Slaby55b307d2006-12-08 02:38:14 -0800784 mxser_brdname[brd->board_type - 1], ioaddr[b]);
Jiri Slaby037ad482006-12-08 02:38:11 -0800785
786 if (retval <= 0) {
787 if (retval == MXSER_ERR_IRQ)
788 printk(KERN_ERR "Invalid interrupt number, "
789 "board not configured\n");
790 else if (retval == MXSER_ERR_IRQ_CONFLIT)
791 printk(KERN_ERR "Invalid interrupt number, "
792 "board not configured\n");
793 else if (retval == MXSER_ERR_VECTOR)
794 printk(KERN_ERR "Invalid interrupt vector, "
795 "board not configured\n");
796 else if (retval == MXSER_ERR_IOADDR)
797 printk(KERN_ERR "Invalid I/O address, "
798 "board not configured\n");
799
800 continue;
801 }
802
Jiri Slaby55b307d2006-12-08 02:38:14 -0800803 brd->pdev = NULL;
Jiri Slaby037ad482006-12-08 02:38:11 -0800804 /* mxser_initbrd will hook ISR. */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800805 if (mxser_initbrd(brd) < 0)
Jiri Slaby037ad482006-12-08 02:38:11 -0800806 continue;
807
808 m++;
809 }
810
811 /* start finding PCI board here */
Jiri Slaby037ad482006-12-08 02:38:11 -0800812 n = ARRAY_SIZE(mxser_pcibrds) - 1;
Jiri Slaby037ad482006-12-08 02:38:11 -0800813 b = 0;
814 while (b < n) {
815 pdev = pci_get_device(mxser_pcibrds[b].vendor,
816 mxser_pcibrds[b].device, pdev);
817 if (pdev == NULL) {
818 b++;
819 continue;
820 }
Jiri Slaby037ad482006-12-08 02:38:11 -0800821 printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
822 mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1],
Jiri Slaby55b307d2006-12-08 02:38:14 -0800823 pdev->bus->number, PCI_SLOT(pdev->devfn));
Jiri Slaby037ad482006-12-08 02:38:11 -0800824 if (m >= MXSER_BOARDS)
825 printk(KERN_ERR
826 "Too many Smartio/Industio family boards find "
827 "(maximum %d), board not configured\n",
828 MXSER_BOARDS);
829 else {
830 if (pci_enable_device(pdev)) {
831 printk(KERN_ERR "Moxa SmartI/O PCI enable "
832 "fail !\n");
833 continue;
834 }
Jiri Slaby55b307d2006-12-08 02:38:14 -0800835 brd = &mxser_boards[m];
836 brd->pdev = pdev;
837 retval = mxser_get_PCI_conf(
Jiri Slaby037ad482006-12-08 02:38:11 -0800838 (int)mxser_pcibrds[b].driver_data,
Jiri Slaby55b307d2006-12-08 02:38:14 -0800839 brd, pdev);
Jiri Slaby037ad482006-12-08 02:38:11 -0800840 if (retval < 0) {
841 if (retval == MXSER_ERR_IRQ)
842 printk(KERN_ERR
843 "Invalid interrupt number, "
844 "board not configured\n");
845 else if (retval == MXSER_ERR_IRQ_CONFLIT)
846 printk(KERN_ERR
847 "Invalid interrupt number, "
848 "board not configured\n");
849 else if (retval == MXSER_ERR_VECTOR)
850 printk(KERN_ERR
851 "Invalid interrupt vector, "
852 "board not configured\n");
853 else if (retval == MXSER_ERR_IOADDR)
854 printk(KERN_ERR
855 "Invalid I/O address, "
856 "board not configured\n");
857 continue;
858 }
Jiri Slaby037ad482006-12-08 02:38:11 -0800859 /* mxser_initbrd will hook ISR. */
Jiri Slaby55b307d2006-12-08 02:38:14 -0800860 if (mxser_initbrd(brd) < 0)
Jiri Slaby037ad482006-12-08 02:38:11 -0800861 continue;
862 m++;
863 /* Keep an extra reference if we succeeded. It will
864 be returned at unload time */
865 pci_dev_get(pdev);
866 }
867 }
Jiri Slaby037ad482006-12-08 02:38:11 -0800868
869 retval = tty_register_driver(mxvar_sdriver);
870 if (retval) {
871 printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family"
872 " driver !\n");
873 put_tty_driver(mxvar_sdriver);
874
875 for (i = 0; i < MXSER_BOARDS; i++) {
Jiri Slaby55b307d2006-12-08 02:38:14 -0800876 if (mxser_boards[i].board_type == -1)
Jiri Slaby037ad482006-12-08 02:38:11 -0800877 continue;
878 else {
Jiri Slaby55b307d2006-12-08 02:38:14 -0800879 free_irq(mxser_boards[i].irq, &mxser_boards[i]);
Jiri Slaby037ad482006-12-08 02:38:11 -0800880 /* todo: release io, vector */
881 }
882 }
883 return retval;
884 }
885
886 return 0;
887}
888
889static void mxser_do_softint(void *private_)
890{
Jiri Slaby55b307d2006-12-08 02:38:14 -0800891 struct mxser_port *info = private_;
Jiri Slaby037ad482006-12-08 02:38:11 -0800892 struct tty_struct *tty;
893
894 tty = info->tty;
895
Jiri Slaby3306ce32006-12-08 02:38:13 -0800896 if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event))
897 tty_wakeup(tty);
898 if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event))
899 tty_hangup(tty);
Jiri Slaby037ad482006-12-08 02:38:11 -0800900}
901
Jiri Slaby55b307d2006-12-08 02:38:14 -0800902static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
Jiri Slaby037ad482006-12-08 02:38:11 -0800903{
904 unsigned char status = 0;
905
906 status = inb(baseaddr + UART_MSR);
907
908 mxser_msr[port] &= 0x0F;
909 mxser_msr[port] |= status;
910 status = mxser_msr[port];
911 if (mode)
912 mxser_msr[port] = 0;
913
914 return status;
915}
916
917/*
918 * This routine is called whenever a serial port is opened. It
919 * enables interrupts for a serial port, linking in its async structure into
920 * the IRQ chain. It also performs the serial-specific
921 * initialization for the tty structure.
922 */
923static int mxser_open(struct tty_struct *tty, struct file *filp)
924{
Jiri Slaby55b307d2006-12-08 02:38:14 -0800925 struct mxser_port *info;
Jiri Slaby037ad482006-12-08 02:38:11 -0800926 int retval, line;
927
928 /* initialize driver_data in case something fails */
929 tty->driver_data = NULL;
930
931 line = tty->index;
932 if (line == MXSER_PORTS)
933 return 0;
934 if (line < 0 || line > MXSER_PORTS)
935 return -ENODEV;
Jiri Slaby55b307d2006-12-08 02:38:14 -0800936 info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD];
937 if (!info->ioaddr)
Jiri Slaby037ad482006-12-08 02:38:11 -0800938 return -ENODEV;
939
940 tty->driver_data = info;
941 info->tty = tty;
942 /*
943 * Start up serial port
944 */
Jiri Slaby3306ce32006-12-08 02:38:13 -0800945 info->count++;
Jiri Slaby037ad482006-12-08 02:38:11 -0800946 retval = mxser_startup(info);
947 if (retval)
948 return retval;
949
950 retval = mxser_block_til_ready(tty, filp, info);
951 if (retval)
952 return retval;
953
Jiri Slaby037ad482006-12-08 02:38:11 -0800954 if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
955 if (tty->driver->subtype == SERIAL_TYPE_NORMAL)
956 *tty->termios = info->normal_termios;
957 else
958 *tty->termios = info->callout_termios;
959 mxser_change_speed(info, NULL);
960 }
961
Andrew Morton08a4ae42006-12-08 02:38:12 -0800962 info->session = process_session(current);
Jiri Slaby037ad482006-12-08 02:38:11 -0800963 info->pgrp = process_group(current);
964
965 /*
966 status = mxser_get_msr(info->base, 0, info->port);
967 mxser_check_modem_status(info, status);
968 */
969
970/* unmark here for very high baud rate (ex. 921600 bps) used */
971 tty->low_latency = 1;
972 return 0;
973}
974
975/*
976 * This routine is called when the serial port gets closed. First, we
977 * wait for the last remaining data to be sent. Then, we unlink its
978 * async structure from the interrupt chain if necessary, and we free
979 * that IRQ if nothing is left in the chain.
980 */
981static void mxser_close(struct tty_struct *tty, struct file *filp)
982{
Jiri Slaby55b307d2006-12-08 02:38:14 -0800983 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -0800984
985 unsigned long timeout;
986 unsigned long flags;
987 struct tty_ldisc *ld;
988
989 if (tty->index == MXSER_PORTS)
990 return;
991 if (!info)
992 return;
993
994 spin_lock_irqsave(&info->slock, flags);
995
996 if (tty_hung_up_p(filp)) {
997 spin_unlock_irqrestore(&info->slock, flags);
998 return;
999 }
1000 if ((tty->count == 1) && (info->count != 1)) {
1001 /*
1002 * Uh, oh. tty->count is 1, which means that the tty
1003 * structure will be freed. Info->count should always
1004 * be one in these conditions. If it's greater than
1005 * one, we've got real problems, since it means the
1006 * serial port won't be shutdown.
1007 */
1008 printk(KERN_ERR "mxser_close: bad serial port count; "
1009 "tty->count is 1, info->count is %d\n", info->count);
1010 info->count = 1;
1011 }
1012 if (--info->count < 0) {
1013 printk(KERN_ERR "mxser_close: bad serial port count for "
Jiri Slaby55b307d2006-12-08 02:38:14 -08001014 "ttys%d: %d\n", tty->index, info->count);
Jiri Slaby037ad482006-12-08 02:38:11 -08001015 info->count = 0;
1016 }
1017 if (info->count) {
1018 spin_unlock_irqrestore(&info->slock, flags);
1019 return;
1020 }
1021 info->flags |= ASYNC_CLOSING;
1022 spin_unlock_irqrestore(&info->slock, flags);
1023 /*
1024 * Save the termios structure, since this port may have
1025 * separate termios for callout and dialin.
1026 */
1027 if (info->flags & ASYNC_NORMAL_ACTIVE)
1028 info->normal_termios = *tty->termios;
1029 /*
1030 * Now we wait for the transmit buffer to clear; and we notify
1031 * the line discipline to only process XON/XOFF characters.
1032 */
1033 tty->closing = 1;
1034 if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1035 tty_wait_until_sent(tty, info->closing_wait);
1036 /*
1037 * At this point we stop accepting input. To do this, we
1038 * disable the receive line status interrupts, and tell the
1039 * interrupt driver to stop checking the data ready bit in the
1040 * line status register.
1041 */
1042 info->IER &= ~UART_IER_RLSI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001043 if (info->board->chip_flag)
Jiri Slaby037ad482006-12-08 02:38:11 -08001044 info->IER &= ~MOXA_MUST_RECV_ISR;
1045/* by William
1046 info->read_status_mask &= ~UART_LSR_DR;
1047*/
1048 if (info->flags & ASYNC_INITIALIZED) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08001049 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001050 /*
1051 * Before we drop DTR, make sure the UART transmitter
1052 * has completely drained; this is especially
1053 * important if there is a transmit FIFO!
1054 */
1055 timeout = jiffies + HZ;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001056 while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001057 schedule_timeout_interruptible(5);
1058 if (time_after(jiffies, timeout))
1059 break;
1060 }
1061 }
1062 mxser_shutdown(info);
1063
1064 if (tty->driver->flush_buffer)
1065 tty->driver->flush_buffer(tty);
1066
1067 ld = tty_ldisc_ref(tty);
1068 if (ld) {
1069 if (ld->flush_buffer)
1070 ld->flush_buffer(tty);
1071 tty_ldisc_deref(ld);
1072 }
1073
1074 tty->closing = 0;
1075 info->event = 0;
1076 info->tty = NULL;
1077 if (info->blocked_open) {
1078 if (info->close_delay)
1079 schedule_timeout_interruptible(info->close_delay);
1080 wake_up_interruptible(&info->open_wait);
1081 }
1082
1083 info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
1084 wake_up_interruptible(&info->close_wait);
1085
1086}
1087
1088static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
1089{
1090 int c, total = 0;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001091 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001092 unsigned long flags;
1093
1094 if (!info->xmit_buf)
1095 return 0;
1096
1097 while (1) {
1098 c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1099 SERIAL_XMIT_SIZE - info->xmit_head));
1100 if (c <= 0)
1101 break;
1102
1103 memcpy(info->xmit_buf + info->xmit_head, buf, c);
1104 spin_lock_irqsave(&info->slock, flags);
1105 info->xmit_head = (info->xmit_head + c) &
1106 (SERIAL_XMIT_SIZE - 1);
1107 info->xmit_cnt += c;
1108 spin_unlock_irqrestore(&info->slock, flags);
1109
1110 buf += c;
1111 count -= c;
1112 total += c;
1113 }
1114
Jiri Slaby3306ce32006-12-08 02:38:13 -08001115 if (info->xmit_cnt && !tty->stopped
1116 /*&& !(info->IER & UART_IER_THRI)*/) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001117 if (!tty->hw_stopped ||
1118 (info->type == PORT_16550A) ||
Jiri Slaby55b307d2006-12-08 02:38:14 -08001119 (info->board->chip_flag)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001120 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby55b307d2006-12-08 02:38:14 -08001121 outb(info->IER & ~UART_IER_THRI, info->ioaddr +
1122 UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001123 info->IER |= UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001124 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001125 spin_unlock_irqrestore(&info->slock, flags);
1126 }
1127 }
1128 return total;
1129}
1130
1131static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
1132{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001133 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001134 unsigned long flags;
1135
1136 if (!info->xmit_buf)
1137 return;
1138
1139 if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
1140 return;
1141
1142 spin_lock_irqsave(&info->slock, flags);
1143 info->xmit_buf[info->xmit_head++] = ch;
1144 info->xmit_head &= SERIAL_XMIT_SIZE - 1;
1145 info->xmit_cnt++;
1146 spin_unlock_irqrestore(&info->slock, flags);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001147 if (!tty->stopped /*&& !(info->IER & UART_IER_THRI)*/) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001148 if (!tty->hw_stopped ||
1149 (info->type == PORT_16550A) ||
Jiri Slaby55b307d2006-12-08 02:38:14 -08001150 info->board->chip_flag) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001151 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby55b307d2006-12-08 02:38:14 -08001152 outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001153 info->IER |= UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001154 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001155 spin_unlock_irqrestore(&info->slock, flags);
1156 }
1157 }
1158}
1159
1160
1161static void mxser_flush_chars(struct tty_struct *tty)
1162{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001163 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001164 unsigned long flags;
1165
1166 if (info->xmit_cnt <= 0 ||
1167 tty->stopped ||
1168 !info->xmit_buf ||
1169 (tty->hw_stopped &&
1170 (info->type != PORT_16550A) &&
Jiri Slaby55b307d2006-12-08 02:38:14 -08001171 (!info->board->chip_flag)
Jiri Slaby037ad482006-12-08 02:38:11 -08001172 ))
1173 return;
1174
1175 spin_lock_irqsave(&info->slock, flags);
1176
Jiri Slaby55b307d2006-12-08 02:38:14 -08001177 outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001178 info->IER |= UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001179 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001180
1181 spin_unlock_irqrestore(&info->slock, flags);
1182}
1183
1184static int mxser_write_room(struct tty_struct *tty)
1185{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001186 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001187 int ret;
1188
1189 ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
1190 if (ret < 0)
1191 ret = 0;
1192 return ret;
1193}
1194
1195static int mxser_chars_in_buffer(struct tty_struct *tty)
1196{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001197 struct mxser_port *info = tty->driver_data;
Jiri Slaby3306ce32006-12-08 02:38:13 -08001198 int len = info->xmit_cnt;
1199
Jiri Slaby55b307d2006-12-08 02:38:14 -08001200 if (!(inb(info->ioaddr + UART_LSR) & UART_LSR_THRE))
Jiri Slaby3306ce32006-12-08 02:38:13 -08001201 len++;
1202
1203 return len;
Jiri Slaby037ad482006-12-08 02:38:11 -08001204}
1205
1206static void mxser_flush_buffer(struct tty_struct *tty)
1207{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001208 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001209 char fcr;
1210 unsigned long flags;
1211
1212
1213 spin_lock_irqsave(&info->slock, flags);
1214 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1215
1216 /* below added by shinhay */
Jiri Slaby55b307d2006-12-08 02:38:14 -08001217 fcr = inb(info->ioaddr + UART_FCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08001218 outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
Jiri Slaby55b307d2006-12-08 02:38:14 -08001219 info->ioaddr + UART_FCR);
1220 outb(fcr, info->ioaddr + UART_FCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08001221
1222 spin_unlock_irqrestore(&info->slock, flags);
1223 /* above added by shinhay */
1224
1225 wake_up_interruptible(&tty->write_wait);
1226 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
1227 (tty->ldisc.write_wakeup) (tty);
1228}
1229
1230static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1231{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001232 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001233 int retval;
1234 struct async_icount cprev, cnow; /* kernel counter temps */
1235 struct serial_icounter_struct __user *p_cuser;
1236 unsigned long templ;
1237 unsigned long flags;
1238 void __user *argp = (void __user *)arg;
1239
1240 if (tty->index == MXSER_PORTS)
1241 return mxser_ioctl_special(cmd, argp);
1242
1243 /* following add by Victor Yu. 01-05-2004 */
1244 if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) {
Jiri Slaby3306ce32006-12-08 02:38:13 -08001245 int p;
1246 unsigned long opmode;
Jiri Slaby037ad482006-12-08 02:38:11 -08001247 static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f };
1248 int shiftbit;
1249 unsigned char val, mask;
1250
Jiri Slaby55b307d2006-12-08 02:38:14 -08001251 p = tty->index % 4;
Jiri Slaby037ad482006-12-08 02:38:11 -08001252 if (cmd == MOXA_SET_OP_MODE) {
1253 if (get_user(opmode, (int __user *) argp))
1254 return -EFAULT;
1255 if (opmode != RS232_MODE &&
1256 opmode != RS485_2WIRE_MODE &&
1257 opmode != RS422_MODE &&
1258 opmode != RS485_4WIRE_MODE)
1259 return -EFAULT;
1260 mask = ModeMask[p];
1261 shiftbit = p * 2;
1262 val = inb(info->opmode_ioaddr);
1263 val &= mask;
1264 val |= (opmode << shiftbit);
1265 outb(val, info->opmode_ioaddr);
1266 } else {
1267 shiftbit = p * 2;
1268 opmode = inb(info->opmode_ioaddr) >> shiftbit;
1269 opmode &= OP_MODE_MASK;
1270 if (copy_to_user(argp, &opmode, sizeof(int)))
1271 return -EFAULT;
1272 }
1273 return 0;
1274 }
1275 /* above add by Victor Yu. 01-05-2004 */
1276
1277 if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
1278 if (tty->flags & (1 << TTY_IO_ERROR))
1279 return -EIO;
1280 }
1281 switch (cmd) {
1282 case TCSBRK: /* SVID version: non-zero arg --> no break */
1283 retval = tty_check_change(tty);
1284 if (retval)
1285 return retval;
1286 tty_wait_until_sent(tty, 0);
1287 if (!arg)
1288 mxser_send_break(info, HZ / 4); /* 1/4 second */
1289 return 0;
1290 case TCSBRKP: /* support for POSIX tcsendbreak() */
1291 retval = tty_check_change(tty);
1292 if (retval)
1293 return retval;
1294 tty_wait_until_sent(tty, 0);
1295 mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
1296 return 0;
1297 case TIOCGSOFTCAR:
1298 return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
1299 case TIOCSSOFTCAR:
1300 if (get_user(templ, (unsigned long __user *) argp))
1301 return -EFAULT;
1302 arg = templ;
1303 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
1304 return 0;
1305 case TIOCGSERIAL:
1306 return mxser_get_serial_info(info, argp);
1307 case TIOCSSERIAL:
1308 return mxser_set_serial_info(info, argp);
1309 case TIOCSERGETLSR: /* Get line status register */
1310 return mxser_get_lsr_info(info, argp);
1311 /*
1312 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
1313 * - mask passed in arg for lines of interest
1314 * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
1315 * Caller should use TIOCGICOUNT to see which one it was
1316 */
1317 case TIOCMIWAIT: {
1318 DECLARE_WAITQUEUE(wait, current);
1319 int ret;
1320 spin_lock_irqsave(&info->slock, flags);
1321 cprev = info->icount; /* note the counters on entry */
1322 spin_unlock_irqrestore(&info->slock, flags);
1323
1324 add_wait_queue(&info->delta_msr_wait, &wait);
1325 while (1) {
1326 spin_lock_irqsave(&info->slock, flags);
1327 cnow = info->icount; /* atomic copy */
1328 spin_unlock_irqrestore(&info->slock, flags);
1329
1330 set_current_state(TASK_INTERRUPTIBLE);
1331 if (((arg & TIOCM_RNG) &&
1332 (cnow.rng != cprev.rng)) ||
1333 ((arg & TIOCM_DSR) &&
1334 (cnow.dsr != cprev.dsr)) ||
1335 ((arg & TIOCM_CD) &&
1336 (cnow.dcd != cprev.dcd)) ||
1337 ((arg & TIOCM_CTS) &&
1338 (cnow.cts != cprev.cts))) {
1339 ret = 0;
1340 break;
1341 }
1342 /* see if a signal did it */
1343 if (signal_pending(current)) {
1344 ret = -ERESTARTSYS;
1345 break;
1346 }
1347 cprev = cnow;
1348 }
1349 current->state = TASK_RUNNING;
1350 remove_wait_queue(&info->delta_msr_wait, &wait);
1351 break;
1352 }
1353 /* NOTREACHED */
1354 /*
1355 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1356 * Return: write counters to the user passed counter struct
1357 * NB: both 1->0 and 0->1 transitions are counted except for
1358 * RI where only 0->1 is counted.
1359 */
1360 case TIOCGICOUNT:
1361 spin_lock_irqsave(&info->slock, flags);
1362 cnow = info->icount;
1363 spin_unlock_irqrestore(&info->slock, flags);
1364 p_cuser = argp;
1365 /* modified by casper 1/11/2000 */
1366 if (put_user(cnow.frame, &p_cuser->frame))
1367 return -EFAULT;
1368 if (put_user(cnow.brk, &p_cuser->brk))
1369 return -EFAULT;
1370 if (put_user(cnow.overrun, &p_cuser->overrun))
1371 return -EFAULT;
1372 if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
1373 return -EFAULT;
1374 if (put_user(cnow.parity, &p_cuser->parity))
1375 return -EFAULT;
1376 if (put_user(cnow.rx, &p_cuser->rx))
1377 return -EFAULT;
1378 if (put_user(cnow.tx, &p_cuser->tx))
1379 return -EFAULT;
1380 put_user(cnow.cts, &p_cuser->cts);
1381 put_user(cnow.dsr, &p_cuser->dsr);
1382 put_user(cnow.rng, &p_cuser->rng);
1383 put_user(cnow.dcd, &p_cuser->dcd);
1384 return 0;
1385 case MOXA_HighSpeedOn:
1386 return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
1387 case MOXA_SDS_RSTICOUNTER: {
1388 info->mon_data.rxcnt = 0;
1389 info->mon_data.txcnt = 0;
1390 return 0;
1391 }
1392/* (above) added by James. */
1393 case MOXA_ASPP_SETBAUD:{
1394 long baud;
1395 if (get_user(baud, (long __user *)argp))
1396 return -EFAULT;
1397 mxser_set_baud(info, baud);
1398 return 0;
1399 }
1400 case MOXA_ASPP_GETBAUD:
1401 if (copy_to_user(argp, &info->realbaud, sizeof(long)))
1402 return -EFAULT;
1403
1404 return 0;
1405
1406 case MOXA_ASPP_OQUEUE:{
1407 int len, lsr;
1408
1409 len = mxser_chars_in_buffer(tty);
1410
Jiri Slaby55b307d2006-12-08 02:38:14 -08001411 lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT;
Jiri Slaby037ad482006-12-08 02:38:11 -08001412
1413 len += (lsr ? 0 : 1);
1414
1415 if (copy_to_user(argp, &len, sizeof(int)))
1416 return -EFAULT;
1417
1418 return 0;
1419 }
1420 case MOXA_ASPP_MON: {
1421 int mcr, status;
1422
1423 /* info->mon_data.ser_param = tty->termios->c_cflag; */
1424
Jiri Slaby55b307d2006-12-08 02:38:14 -08001425 status = mxser_get_msr(info->ioaddr, 1, tty->index);
Jiri Slaby037ad482006-12-08 02:38:11 -08001426 mxser_check_modem_status(info, status);
1427
Jiri Slaby55b307d2006-12-08 02:38:14 -08001428 mcr = inb(info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08001429 if (mcr & MOXA_MUST_MCR_XON_FLAG)
1430 info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD;
1431 else
1432 info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD;
1433
1434 if (mcr & MOXA_MUST_MCR_TX_XON)
1435 info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT;
1436 else
1437 info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
1438
1439 if (info->tty->hw_stopped)
1440 info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
1441 else
1442 info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
1443
1444 if (copy_to_user(argp, &info->mon_data,
1445 sizeof(struct mxser_mon)))
1446 return -EFAULT;
1447
1448 return 0;
1449 }
1450
1451 case MOXA_ASPP_LSTATUS: {
1452 if (copy_to_user(argp, &info->err_shadow,
1453 sizeof(unsigned char)))
1454 return -EFAULT;
1455
1456 info->err_shadow = 0;
1457 return 0;
1458 }
1459 case MOXA_SET_BAUD_METHOD: {
1460 int method;
1461
1462 if (get_user(method, (int __user *)argp))
1463 return -EFAULT;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001464 mxser_set_baud_method[tty->index] = method;
Jiri Slaby037ad482006-12-08 02:38:11 -08001465 if (copy_to_user(argp, &method, sizeof(int)))
1466 return -EFAULT;
1467
1468 return 0;
1469 }
1470 default:
1471 return -ENOIOCTLCMD;
1472 }
1473 return 0;
1474}
1475
1476#ifndef CMSPAR
1477#define CMSPAR 010000000000
1478#endif
1479
1480static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
1481{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001482 struct mxser_port *port;
1483 int result, status;
1484 unsigned int i, j;
Jiri Slaby037ad482006-12-08 02:38:11 -08001485
1486 switch (cmd) {
1487 case MOXA_GET_CONF:
Jiri Slaby55b307d2006-12-08 02:38:14 -08001488/* if (copy_to_user(argp, mxsercfg,
Jiri Slaby037ad482006-12-08 02:38:11 -08001489 sizeof(struct mxser_hwconf) * 4))
1490 return -EFAULT;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001491 return 0;*/
1492 return -ENXIO;
Jiri Slaby037ad482006-12-08 02:38:11 -08001493 case MOXA_GET_MAJOR:
1494 if (copy_to_user(argp, &ttymajor, sizeof(int)))
1495 return -EFAULT;
1496 return 0;
1497
1498 case MOXA_GET_CUMAJOR:
1499 if (copy_to_user(argp, &calloutmajor, sizeof(int)))
1500 return -EFAULT;
1501 return 0;
1502
1503 case MOXA_CHKPORTENABLE:
1504 result = 0;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001505
1506 for (i = 0; i < MXSER_BOARDS; i++)
1507 for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
1508 if (mxser_boards[i].ports[j].ioaddr)
1509 result |= (1 << i);
1510
Jiri Slaby037ad482006-12-08 02:38:11 -08001511 return put_user(result, (unsigned long __user *)argp);
1512 case MOXA_GETDATACOUNT:
1513 if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
1514 return -EFAULT;
1515 return 0;
1516 case MOXA_GETMSTATUS:
Jiri Slaby55b307d2006-12-08 02:38:14 -08001517 for (i = 0; i < MXSER_BOARDS; i++)
1518 for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
1519 port = &mxser_boards[i].ports[j];
1520
1521 GMStatus[i].ri = 0;
1522 if (!port->ioaddr) {
1523 GMStatus[i].dcd = 0;
1524 GMStatus[i].dsr = 0;
1525 GMStatus[i].cts = 0;
1526 continue;
1527 }
1528
1529 if (!port->tty || !port->tty->termios)
1530 GMStatus[i].cflag =
1531 port->normal_termios.c_cflag;
1532 else
1533 GMStatus[i].cflag =
1534 port->tty->termios->c_cflag;
1535
1536 status = inb(port->ioaddr + UART_MSR);
1537 if (status & 0x80 /*UART_MSR_DCD */ )
1538 GMStatus[i].dcd = 1;
1539 else
1540 GMStatus[i].dcd = 0;
1541
1542 if (status & 0x20 /*UART_MSR_DSR */ )
1543 GMStatus[i].dsr = 1;
1544 else
1545 GMStatus[i].dsr = 0;
1546
1547
1548 if (status & 0x10 /*UART_MSR_CTS */ )
1549 GMStatus[i].cts = 1;
1550 else
1551 GMStatus[i].cts = 0;
Jiri Slaby037ad482006-12-08 02:38:11 -08001552 }
Jiri Slaby037ad482006-12-08 02:38:11 -08001553 if (copy_to_user(argp, GMStatus,
1554 sizeof(struct mxser_mstatus) * MXSER_PORTS))
1555 return -EFAULT;
1556 return 0;
1557 case MOXA_ASPP_MON_EXT: {
Jiri Slaby55b307d2006-12-08 02:38:14 -08001558 int status, p, shiftbit;
1559 unsigned long opmode;
1560 unsigned cflag, iflag;
Jiri Slaby037ad482006-12-08 02:38:11 -08001561
Jiri Slaby55b307d2006-12-08 02:38:14 -08001562 for (i = 0; i < MXSER_BOARDS; i++)
1563 for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
1564 port = &mxser_boards[i].ports[j];
1565 if (!port->ioaddr)
Jiri Slaby037ad482006-12-08 02:38:11 -08001566 continue;
1567
Jiri Slaby55b307d2006-12-08 02:38:14 -08001568 status = mxser_get_msr(port->ioaddr, 0, i);
1569/* mxser_check_modem_status(port, status); */
1570
Jiri Slaby037ad482006-12-08 02:38:11 -08001571 if (status & UART_MSR_TERI)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001572 port->icount.rng++;
Jiri Slaby037ad482006-12-08 02:38:11 -08001573 if (status & UART_MSR_DDSR)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001574 port->icount.dsr++;
Jiri Slaby037ad482006-12-08 02:38:11 -08001575 if (status & UART_MSR_DDCD)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001576 port->icount.dcd++;
Jiri Slaby037ad482006-12-08 02:38:11 -08001577 if (status & UART_MSR_DCTS)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001578 port->icount.cts++;
Jiri Slaby037ad482006-12-08 02:38:11 -08001579
Jiri Slaby55b307d2006-12-08 02:38:14 -08001580 port->mon_data.modem_status = status;
1581 mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt;
1582 mon_data_ext.tx_cnt[i] = port->mon_data.txcnt;
1583 mon_data_ext.up_rxcnt[i] =
1584 port->mon_data.up_rxcnt;
1585 mon_data_ext.up_txcnt[i] =
1586 port->mon_data.up_txcnt;
1587 mon_data_ext.modem_status[i] =
1588 port->mon_data.modem_status;
1589 mon_data_ext.baudrate[i] = port->realbaud;
Jiri Slaby037ad482006-12-08 02:38:11 -08001590
Jiri Slaby55b307d2006-12-08 02:38:14 -08001591 if (!port->tty || !port->tty->termios) {
1592 cflag = port->normal_termios.c_cflag;
1593 iflag = port->normal_termios.c_iflag;
Jiri Slaby037ad482006-12-08 02:38:11 -08001594 } else {
Jiri Slaby55b307d2006-12-08 02:38:14 -08001595 cflag = port->tty->termios->c_cflag;
1596 iflag = port->tty->termios->c_iflag;
Jiri Slaby037ad482006-12-08 02:38:11 -08001597 }
1598
1599 mon_data_ext.databits[i] = cflag & CSIZE;
1600
1601 mon_data_ext.stopbits[i] = cflag & CSTOPB;
1602
Jiri Slaby55b307d2006-12-08 02:38:14 -08001603 mon_data_ext.parity[i] =
1604 cflag & (PARENB | PARODD | CMSPAR);
Jiri Slaby037ad482006-12-08 02:38:11 -08001605
1606 mon_data_ext.flowctrl[i] = 0x00;
1607
1608 if (cflag & CRTSCTS)
1609 mon_data_ext.flowctrl[i] |= 0x03;
1610
1611 if (iflag & (IXON | IXOFF))
1612 mon_data_ext.flowctrl[i] |= 0x0C;
1613
Jiri Slaby55b307d2006-12-08 02:38:14 -08001614 if (port->type == PORT_16550A)
Jiri Slaby037ad482006-12-08 02:38:11 -08001615 mon_data_ext.fifo[i] = 1;
1616 else
1617 mon_data_ext.fifo[i] = 0;
1618
1619 p = i % 4;
1620 shiftbit = p * 2;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001621 opmode = inb(port->opmode_ioaddr) >> shiftbit;
Jiri Slaby037ad482006-12-08 02:38:11 -08001622 opmode &= OP_MODE_MASK;
1623
1624 mon_data_ext.iftype[i] = opmode;
1625
1626 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08001627 if (copy_to_user(argp, &mon_data_ext,
1628 sizeof(mon_data_ext)))
Jiri Slaby037ad482006-12-08 02:38:11 -08001629 return -EFAULT;
1630
1631 return 0;
1632
Jiri Slaby55b307d2006-12-08 02:38:14 -08001633 } default:
Jiri Slaby037ad482006-12-08 02:38:11 -08001634 return -ENOIOCTLCMD;
1635 }
1636 return 0;
1637}
1638
1639static void mxser_stoprx(struct tty_struct *tty)
1640{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001641 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001642
1643 info->ldisc_stop_rx = 1;
1644 if (I_IXOFF(tty)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001645 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08001646 if (info->board->chip_flag) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001647 info->IER &= ~MOXA_MUST_RECV_ISR;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001648 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001649 } else if (!(info->flags & ASYNC_CLOSING)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001650 info->x_char = STOP_CHAR(tty);
Jiri Slaby55b307d2006-12-08 02:38:14 -08001651 outb(0, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001652 info->IER |= UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001653 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001654 }
Jiri Slaby037ad482006-12-08 02:38:11 -08001655 }
1656
1657 if (info->tty->termios->c_cflag & CRTSCTS) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001658 info->MCR &= ~UART_MCR_RTS;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001659 outb(info->MCR, info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08001660 }
1661}
1662
1663static void mxser_startrx(struct tty_struct *tty)
1664{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001665 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001666
1667 info->ldisc_stop_rx = 0;
1668 if (I_IXOFF(tty)) {
1669 if (info->x_char)
1670 info->x_char = 0;
1671 else {
Jiri Slaby037ad482006-12-08 02:38:11 -08001672 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08001673 if (info->board->chip_flag) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001674 info->IER |= MOXA_MUST_RECV_ISR;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001675 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001676 } else if (!(info->flags & ASYNC_CLOSING)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001677 info->x_char = START_CHAR(tty);
Jiri Slaby55b307d2006-12-08 02:38:14 -08001678 outb(0, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001679 info->IER |= UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001680 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001681 }
Jiri Slaby037ad482006-12-08 02:38:11 -08001682 }
1683 }
1684
1685 if (info->tty->termios->c_cflag & CRTSCTS) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001686 info->MCR |= UART_MCR_RTS;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001687 outb(info->MCR, info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08001688 }
1689}
1690
1691/*
1692 * This routine is called by the upper-layer tty layer to signal that
1693 * incoming characters should be throttled.
1694 */
1695static void mxser_throttle(struct tty_struct *tty)
1696{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001697 struct mxser_port *info = tty->driver_data;
Jiri Slaby3306ce32006-12-08 02:38:13 -08001698 unsigned long flags;
Jiri Slaby037ad482006-12-08 02:38:11 -08001699
Jiri Slaby3306ce32006-12-08 02:38:13 -08001700 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08001701 mxser_stoprx(tty);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001702 spin_unlock_irqrestore(&info->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08001703}
1704
1705static void mxser_unthrottle(struct tty_struct *tty)
1706{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001707 struct mxser_port *info = tty->driver_data;
Jiri Slaby3306ce32006-12-08 02:38:13 -08001708 unsigned long flags;
Jiri Slaby037ad482006-12-08 02:38:11 -08001709
Jiri Slaby3306ce32006-12-08 02:38:13 -08001710 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08001711 mxser_startrx(tty);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001712 spin_unlock_irqrestore(&info->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08001713}
1714
1715static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios)
1716{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001717 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001718 unsigned long flags;
1719
1720 if ((tty->termios->c_cflag != old_termios->c_cflag) ||
1721 (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
1722
1723 mxser_change_speed(info, old_termios);
1724
1725 if ((old_termios->c_cflag & CRTSCTS) &&
1726 !(tty->termios->c_cflag & CRTSCTS)) {
1727 tty->hw_stopped = 0;
1728 mxser_start(tty);
1729 }
1730 }
1731
1732/* Handle sw stopped */
1733 if ((old_termios->c_iflag & IXON) &&
1734 !(tty->termios->c_iflag & IXON)) {
1735 tty->stopped = 0;
1736
1737 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08001738 if (info->board->chip_flag) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001739 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby55b307d2006-12-08 02:38:14 -08001740 DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -08001741 spin_unlock_irqrestore(&info->slock, flags);
1742 }
1743 /* above add by Victor Yu. 09-02-2002 */
1744
1745 mxser_start(tty);
1746 }
1747}
1748
1749/*
1750 * mxser_stop() and mxser_start()
1751 *
1752 * This routines are called before setting or resetting tty->stopped.
1753 * They enable or disable transmitter interrupts, as necessary.
1754 */
1755static void mxser_stop(struct tty_struct *tty)
1756{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001757 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001758 unsigned long flags;
1759
1760 spin_lock_irqsave(&info->slock, flags);
1761 if (info->IER & UART_IER_THRI) {
1762 info->IER &= ~UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001763 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001764 }
1765 spin_unlock_irqrestore(&info->slock, flags);
1766}
1767
1768static void mxser_start(struct tty_struct *tty)
1769{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001770 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001771 unsigned long flags;
1772
1773 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001774 if (info->xmit_cnt && info->xmit_buf
1775 /* && !(info->IER & UART_IER_THRI) */) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08001776 outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001777 info->IER |= UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001778 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08001779 }
1780 spin_unlock_irqrestore(&info->slock, flags);
1781}
1782
1783/*
1784 * mxser_wait_until_sent() --- wait until the transmitter is empty
1785 */
1786static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
1787{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001788 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001789 unsigned long orig_jiffies, char_time;
1790 int lsr;
1791
1792 if (info->type == PORT_UNKNOWN)
1793 return;
1794
1795 if (info->xmit_fifo_size == 0)
1796 return; /* Just in case.... */
1797
1798 orig_jiffies = jiffies;
1799 /*
1800 * Set the check interval to be 1/5 of the estimated time to
1801 * send a single character, and make it at least 1. The check
1802 * interval should also be less than the timeout.
1803 *
1804 * Note: we have to use pretty tight timings here to satisfy
1805 * the NIST-PCTS.
1806 */
1807 char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
1808 char_time = char_time / 5;
1809 if (char_time == 0)
1810 char_time = 1;
1811 if (timeout && timeout < char_time)
1812 char_time = timeout;
1813 /*
1814 * If the transmitter hasn't cleared in twice the approximate
1815 * amount of time to send the entire FIFO, it probably won't
1816 * ever clear. This assumes the UART isn't doing flow
1817 * control, which is currently the case. Hence, if it ever
1818 * takes longer than info->timeout, this is probably due to a
1819 * UART bug of some kind. So, we clamp the timeout parameter at
1820 * 2*info->timeout.
1821 */
1822 if (!timeout || timeout > 2 * info->timeout)
1823 timeout = 2 * info->timeout;
1824#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
1825 printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...",
1826 timeout, char_time);
1827 printk("jiff=%lu...", jiffies);
1828#endif
Jiri Slaby55b307d2006-12-08 02:38:14 -08001829 while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08001830#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
1831 printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
1832#endif
1833 schedule_timeout_interruptible(char_time);
1834 if (signal_pending(current))
1835 break;
1836 if (timeout && time_after(jiffies, orig_jiffies + timeout))
1837 break;
1838 }
1839 set_current_state(TASK_RUNNING);
1840
1841#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
1842 printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
1843#endif
1844}
1845
1846
1847/*
1848 * This routine is called by tty_hangup() when a hangup is signaled.
1849 */
1850void mxser_hangup(struct tty_struct *tty)
1851{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001852 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001853
1854 mxser_flush_buffer(tty);
1855 mxser_shutdown(info);
1856 info->event = 0;
1857 info->count = 0;
1858 info->flags &= ~ASYNC_NORMAL_ACTIVE;
1859 info->tty = NULL;
1860 wake_up_interruptible(&info->open_wait);
1861}
1862
1863
1864/* added by James 03-12-2004. */
1865/*
1866 * mxser_rs_break() --- routine which turns the break handling on or off
1867 */
1868static void mxser_rs_break(struct tty_struct *tty, int break_state)
1869{
Jiri Slaby55b307d2006-12-08 02:38:14 -08001870 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08001871 unsigned long flags;
1872
1873 spin_lock_irqsave(&info->slock, flags);
1874 if (break_state == -1)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001875 outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
1876 info->ioaddr + UART_LCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08001877 else
Jiri Slaby55b307d2006-12-08 02:38:14 -08001878 outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
1879 info->ioaddr + UART_LCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08001880 spin_unlock_irqrestore(&info->slock, flags);
1881}
1882
1883/* (above) added by James. */
1884
1885
1886/*
1887 * This is the serial driver's generic interrupt routine
1888 */
1889static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1890{
1891 int status, iir, i;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001892 struct mxser_board *brd = NULL;
1893 struct mxser_port *port;
Jiri Slaby037ad482006-12-08 02:38:11 -08001894 int max, irqbits, bits, msr;
1895 int pass_counter = 0;
Jiri Slaby3306ce32006-12-08 02:38:13 -08001896 unsigned int int_cnt;
Jiri Slaby037ad482006-12-08 02:38:11 -08001897 int handled = IRQ_NONE;
1898
Jiri Slaby037ad482006-12-08 02:38:11 -08001899 /* spin_lock(&gm_lock); */
1900
Jiri Slaby55b307d2006-12-08 02:38:14 -08001901 for (i = 0; i < MXSER_BOARDS; i++)
1902 if (dev_id == &mxser_boards[i]) {
1903 brd = dev_id;
Jiri Slaby037ad482006-12-08 02:38:11 -08001904 break;
1905 }
Jiri Slaby037ad482006-12-08 02:38:11 -08001906
1907 if (i == MXSER_BOARDS)
1908 goto irq_stop;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001909 if (brd == NULL)
Jiri Slaby037ad482006-12-08 02:38:11 -08001910 goto irq_stop;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001911 max = mxser_numports[brd->board_type - 1];
Jiri Slaby037ad482006-12-08 02:38:11 -08001912 while (1) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08001913 irqbits = inb(brd->vector) & brd->vector_mask;
1914 if (irqbits == brd->vector_mask)
Jiri Slaby037ad482006-12-08 02:38:11 -08001915 break;
1916
1917 handled = IRQ_HANDLED;
1918 for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08001919 if (irqbits == brd->vector_mask)
Jiri Slaby037ad482006-12-08 02:38:11 -08001920 break;
1921 if (bits & irqbits)
1922 continue;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001923 port = &brd->ports[i];
Jiri Slaby037ad482006-12-08 02:38:11 -08001924
Jiri Slaby3306ce32006-12-08 02:38:13 -08001925 int_cnt = 0;
1926 do {
1927 /* following add by Victor Yu. 09-13-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08001928 iir = inb(port->ioaddr + UART_IIR);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001929 if (iir & UART_IIR_NO_INT)
1930 break;
1931 iir &= MOXA_MUST_IIR_MASK;
Jiri Slaby55b307d2006-12-08 02:38:14 -08001932 if (!port->tty) {
1933 status = inb(port->ioaddr + UART_LSR);
1934 outb(0x27, port->ioaddr + UART_FCR);
1935 inb(port->ioaddr + UART_MSR);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001936 break;
Jiri Slaby037ad482006-12-08 02:38:11 -08001937 }
Jiri Slaby037ad482006-12-08 02:38:11 -08001938 /* above add by Victor Yu. 09-13-2002 */
1939
Jiri Slaby55b307d2006-12-08 02:38:14 -08001940 spin_lock(&port->slock);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001941 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08001942 status = inb(port->ioaddr + UART_LSR);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001943
1944 if (status & UART_LSR_PE)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001945 port->err_shadow |= NPPI_NOTIFY_PARITY;
Jiri Slaby3306ce32006-12-08 02:38:13 -08001946 if (status & UART_LSR_FE)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001947 port->err_shadow |= NPPI_NOTIFY_FRAMING;
Jiri Slaby3306ce32006-12-08 02:38:13 -08001948 if (status & UART_LSR_OE)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001949 port->err_shadow |=
Jiri Slaby3306ce32006-12-08 02:38:13 -08001950 NPPI_NOTIFY_HW_OVERRUN;
1951 if (status & UART_LSR_BI)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001952 port->err_shadow |= NPPI_NOTIFY_BREAK;
Jiri Slaby3306ce32006-12-08 02:38:13 -08001953
Jiri Slaby55b307d2006-12-08 02:38:14 -08001954 if (port->board->chip_flag) {
Jiri Slaby3306ce32006-12-08 02:38:13 -08001955 /*
1956 if ( (status & 0x02) && !(status & 0x01) ) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08001957 outb(port->ioaddr+UART_FCR, 0x23);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001958 continue;
1959 }
1960 */
1961 if (iir == MOXA_MUST_IIR_GDA ||
1962 iir == MOXA_MUST_IIR_RDA ||
1963 iir == MOXA_MUST_IIR_RTO ||
1964 iir == MOXA_MUST_IIR_LSR)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001965 mxser_receive_chars(port,
Jiri Slaby3306ce32006-12-08 02:38:13 -08001966 &status);
1967
1968 } else {
1969 /* above add by Victor Yu. 09-02-2002 */
1970
Jiri Slaby55b307d2006-12-08 02:38:14 -08001971 status &= port->read_status_mask;
Jiri Slaby3306ce32006-12-08 02:38:13 -08001972 if (status & UART_LSR_DR)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001973 mxser_receive_chars(port,
Jiri Slaby3306ce32006-12-08 02:38:13 -08001974 &status);
Jiri Slaby037ad482006-12-08 02:38:11 -08001975 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08001976 msr = inb(port->ioaddr + UART_MSR);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001977 if (msr & UART_MSR_ANY_DELTA)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001978 mxser_check_modem_status(port, msr);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001979
1980 /* following add by Victor Yu. 09-13-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08001981 if (port->board->chip_flag) {
Jiri Slaby3306ce32006-12-08 02:38:13 -08001982 if (iir == 0x02 && (status &
1983 UART_LSR_THRE))
Jiri Slaby55b307d2006-12-08 02:38:14 -08001984 mxser_transmit_chars(port);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001985 } else {
1986 /* above add by Victor Yu. 09-13-2002 */
1987
1988 if (status & UART_LSR_THRE)
Jiri Slaby55b307d2006-12-08 02:38:14 -08001989 mxser_transmit_chars(port);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001990 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08001991 spin_unlock(&port->slock);
Jiri Slaby3306ce32006-12-08 02:38:13 -08001992 } while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
Jiri Slaby037ad482006-12-08 02:38:11 -08001993 }
Jiri Slaby3306ce32006-12-08 02:38:13 -08001994 if (pass_counter++ > MXSER_ISR_PASS_LIMIT)
Jiri Slaby037ad482006-12-08 02:38:11 -08001995 break; /* Prevent infinite loops */
Jiri Slaby037ad482006-12-08 02:38:11 -08001996 }
1997
1998 irq_stop:
1999 /* spin_unlock(&gm_lock); */
2000 return handled;
2001}
2002
Jiri Slaby55b307d2006-12-08 02:38:14 -08002003static void mxser_receive_chars(struct mxser_port *port, int *status)
Jiri Slaby037ad482006-12-08 02:38:11 -08002004{
Jiri Slaby55b307d2006-12-08 02:38:14 -08002005 struct tty_struct *tty = port->tty;
Jiri Slaby037ad482006-12-08 02:38:11 -08002006 unsigned char ch, gdl;
2007 int ignored = 0;
2008 int cnt = 0;
2009 int recv_room;
2010 int max = 256;
2011 unsigned long flags;
2012
Jiri Slaby55b307d2006-12-08 02:38:14 -08002013 spin_lock_irqsave(&port->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08002014
2015 recv_room = tty->receive_room;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002016 if ((recv_room == 0) && (!port->ldisc_stop_rx)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002017 /* mxser_throttle(tty); */
2018 mxser_stoprx(tty);
2019 /* return; */
2020 }
2021
2022 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002023 if (port->board->chip_flag != MOXA_OTHER_UART) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002024
Jiri Slaby3306ce32006-12-08 02:38:13 -08002025 if (*status & UART_LSR_SPECIAL)
Jiri Slaby037ad482006-12-08 02:38:11 -08002026 goto intr_old;
Jiri Slaby037ad482006-12-08 02:38:11 -08002027 /* following add by Victor Yu. 02-11-2004 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002028 if (port->board->chip_flag == MOXA_MUST_MU860_HWID &&
Jiri Slaby037ad482006-12-08 02:38:11 -08002029 (*status & MOXA_MUST_LSR_RERR))
2030 goto intr_old;
2031 /* above add by Victor Yu. 02-14-2004 */
2032 if (*status & MOXA_MUST_LSR_RERR)
2033 goto intr_old;
2034
Jiri Slaby55b307d2006-12-08 02:38:14 -08002035 gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002036
2037 /* add by Victor Yu. 02-11-2004 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002038 if (port->board->chip_flag == MOXA_MUST_MU150_HWID)
Jiri Slaby037ad482006-12-08 02:38:11 -08002039 gdl &= MOXA_MUST_GDL_MASK;
2040 if (gdl >= recv_room) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002041 if (!port->ldisc_stop_rx) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002042 /* mxser_throttle(tty); */
2043 mxser_stoprx(tty);
2044 }
2045 /* return; */
2046 }
2047 while (gdl--) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002048 ch = inb(port->ioaddr + UART_RX);
Jiri Slaby037ad482006-12-08 02:38:11 -08002049 tty_insert_flip_char(tty, ch, 0);
2050 cnt++;
Jiri Slaby037ad482006-12-08 02:38:11 -08002051 }
2052 goto end_intr;
2053 }
2054 intr_old:
2055 /* above add by Victor Yu. 09-02-2002 */
2056
2057 do {
2058 if (max-- < 0)
2059 break;
Jiri Slaby037ad482006-12-08 02:38:11 -08002060
Jiri Slaby55b307d2006-12-08 02:38:14 -08002061 ch = inb(port->ioaddr + UART_RX);
Jiri Slaby037ad482006-12-08 02:38:11 -08002062 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002063 if (port->board->chip_flag && (*status & UART_LSR_OE)
Jiri Slaby3306ce32006-12-08 02:38:13 -08002064 /*&& !(*status&UART_LSR_DR) */)
Jiri Slaby55b307d2006-12-08 02:38:14 -08002065 outb(0x23, port->ioaddr + UART_FCR);
2066 *status &= port->read_status_mask;
Jiri Slaby037ad482006-12-08 02:38:11 -08002067 /* above add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002068 if (*status & port->ignore_status_mask) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002069 if (++ignored > 100)
2070 break;
2071 } else {
2072 char flag = 0;
2073 if (*status & UART_LSR_SPECIAL) {
2074 if (*status & UART_LSR_BI) {
2075 flag = TTY_BREAK;
2076/* added by casper 1/11/2000 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002077 port->icount.brk++;
Jiri Slaby3306ce32006-12-08 02:38:13 -08002078
Jiri Slaby55b307d2006-12-08 02:38:14 -08002079 if (port->flags & ASYNC_SAK)
Jiri Slaby037ad482006-12-08 02:38:11 -08002080 do_SAK(tty);
2081 } else if (*status & UART_LSR_PE) {
2082 flag = TTY_PARITY;
2083/* added by casper 1/11/2000 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002084 port->icount.parity++;
Jiri Slaby037ad482006-12-08 02:38:11 -08002085 } else if (*status & UART_LSR_FE) {
2086 flag = TTY_FRAME;
2087/* added by casper 1/11/2000 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002088 port->icount.frame++;
Jiri Slaby037ad482006-12-08 02:38:11 -08002089 } else if (*status & UART_LSR_OE) {
2090 flag = TTY_OVERRUN;
2091/* added by casper 1/11/2000 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002092 port->icount.overrun++;
Jiri Slaby3306ce32006-12-08 02:38:13 -08002093 } else
2094 flags = TTY_BREAK;
2095 } else
2096 flags = 0;
Jiri Slaby037ad482006-12-08 02:38:11 -08002097 tty_insert_flip_char(tty, ch, flag);
2098 cnt++;
2099 if (cnt >= recv_room) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002100 if (!port->ldisc_stop_rx) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002101 /* mxser_throttle(tty); */
2102 mxser_stoprx(tty);
2103 }
2104 break;
2105 }
2106
2107 }
2108
2109 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002110 if (port->board->chip_flag)
Jiri Slaby037ad482006-12-08 02:38:11 -08002111 break;
Jiri Slaby037ad482006-12-08 02:38:11 -08002112
2113 /* mask by Victor Yu. 09-02-2002
Jiri Slaby55b307d2006-12-08 02:38:14 -08002114 *status = inb(port->ioaddr + UART_LSR) & port->read_status_mask;
Jiri Slaby037ad482006-12-08 02:38:11 -08002115 */
2116 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002117 *status = inb(port->ioaddr + UART_LSR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002118 /* above add by Victor Yu. 09-02-2002 */
2119 } while (*status & UART_LSR_DR);
2120
2121end_intr: /* add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002122 mxvar_log.rxcnt[port->tty->index] += cnt;
2123 port->mon_data.rxcnt += cnt;
2124 port->mon_data.up_rxcnt += cnt;
2125 spin_unlock_irqrestore(&port->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08002126
2127 tty_flip_buffer_push(tty);
2128}
2129
Jiri Slaby55b307d2006-12-08 02:38:14 -08002130static void mxser_transmit_chars(struct mxser_port *port)
Jiri Slaby037ad482006-12-08 02:38:11 -08002131{
2132 int count, cnt;
2133 unsigned long flags;
2134
Jiri Slaby55b307d2006-12-08 02:38:14 -08002135 spin_lock_irqsave(&port->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08002136
Jiri Slaby55b307d2006-12-08 02:38:14 -08002137 if (port->x_char) {
2138 outb(port->x_char, port->ioaddr + UART_TX);
2139 port->x_char = 0;
2140 mxvar_log.txcnt[port->tty->index]++;
2141 port->mon_data.txcnt++;
2142 port->mon_data.up_txcnt++;
Jiri Slaby037ad482006-12-08 02:38:11 -08002143
2144/* added by casper 1/11/2000 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002145 port->icount.tx++;
Jiri Slaby3306ce32006-12-08 02:38:13 -08002146 goto unlock;
Jiri Slaby037ad482006-12-08 02:38:11 -08002147 }
2148
Jiri Slaby55b307d2006-12-08 02:38:14 -08002149 if (port->xmit_buf == 0)
Jiri Slaby3306ce32006-12-08 02:38:13 -08002150 goto unlock;
Jiri Slaby037ad482006-12-08 02:38:11 -08002151
Jiri Slaby55b307d2006-12-08 02:38:14 -08002152 if (port->xmit_cnt == 0) {
2153 if (port->xmit_cnt < WAKEUP_CHARS) { /* XXX what's this for?? */
2154 set_bit(MXSER_EVENT_TXLOW, &port->event);
2155 schedule_work(&port->tqueue);
Jiri Slaby3306ce32006-12-08 02:38:13 -08002156 }
2157 goto unlock;
2158 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08002159 if (port->tty->stopped || (port->tty->hw_stopped &&
2160 (port->type != PORT_16550A) &&
2161 (!port->board->chip_flag))) {
2162 port->IER &= ~UART_IER_THRI;
2163 outb(port->IER, port->ioaddr + UART_IER);
Jiri Slaby3306ce32006-12-08 02:38:13 -08002164 goto unlock;
Jiri Slaby037ad482006-12-08 02:38:11 -08002165 }
2166
Jiri Slaby55b307d2006-12-08 02:38:14 -08002167 cnt = port->xmit_cnt;
2168 count = port->xmit_fifo_size;
Jiri Slaby037ad482006-12-08 02:38:11 -08002169 do {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002170 outb(port->xmit_buf[port->xmit_tail++],
2171 port->ioaddr + UART_TX);
2172 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
2173 if (--port->xmit_cnt <= 0)
Jiri Slaby037ad482006-12-08 02:38:11 -08002174 break;
2175 } while (--count > 0);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002176 mxvar_log.txcnt[port->tty->index] += (cnt - port->xmit_cnt);
Jiri Slaby037ad482006-12-08 02:38:11 -08002177
2178/* added by James 03-12-2004. */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002179 port->mon_data.txcnt += (cnt - port->xmit_cnt);
2180 port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
Jiri Slaby037ad482006-12-08 02:38:11 -08002181
2182/* added by casper 1/11/2000 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002183 port->icount.tx += (cnt - port->xmit_cnt);
Jiri Slaby037ad482006-12-08 02:38:11 -08002184
Jiri Slaby55b307d2006-12-08 02:38:14 -08002185 if (port->xmit_cnt < WAKEUP_CHARS) {
2186 set_bit(MXSER_EVENT_TXLOW, &port->event);
2187 schedule_work(&port->tqueue);
Jiri Slaby037ad482006-12-08 02:38:11 -08002188 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08002189 if (port->xmit_cnt <= 0) {
2190 port->IER &= ~UART_IER_THRI;
2191 outb(port->IER, port->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002192 }
Jiri Slaby3306ce32006-12-08 02:38:13 -08002193unlock:
Jiri Slaby55b307d2006-12-08 02:38:14 -08002194 spin_unlock_irqrestore(&port->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08002195}
2196
Jiri Slaby55b307d2006-12-08 02:38:14 -08002197static void mxser_check_modem_status(struct mxser_port *port, int status)
Jiri Slaby037ad482006-12-08 02:38:11 -08002198{
2199 /* update input line counters */
2200 if (status & UART_MSR_TERI)
Jiri Slaby55b307d2006-12-08 02:38:14 -08002201 port->icount.rng++;
Jiri Slaby037ad482006-12-08 02:38:11 -08002202 if (status & UART_MSR_DDSR)
Jiri Slaby55b307d2006-12-08 02:38:14 -08002203 port->icount.dsr++;
Jiri Slaby037ad482006-12-08 02:38:11 -08002204 if (status & UART_MSR_DDCD)
Jiri Slaby55b307d2006-12-08 02:38:14 -08002205 port->icount.dcd++;
Jiri Slaby037ad482006-12-08 02:38:11 -08002206 if (status & UART_MSR_DCTS)
Jiri Slaby55b307d2006-12-08 02:38:14 -08002207 port->icount.cts++;
2208 port->mon_data.modem_status = status;
2209 wake_up_interruptible(&port->delta_msr_wait);
Jiri Slaby037ad482006-12-08 02:38:11 -08002210
Jiri Slaby55b307d2006-12-08 02:38:14 -08002211 if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002212 if (status & UART_MSR_DCD)
Jiri Slaby55b307d2006-12-08 02:38:14 -08002213 wake_up_interruptible(&port->open_wait);
2214 schedule_work(&port->tqueue);
Jiri Slaby037ad482006-12-08 02:38:11 -08002215 }
2216
Jiri Slaby55b307d2006-12-08 02:38:14 -08002217 if (port->flags & ASYNC_CTS_FLOW) {
2218 if (port->tty->hw_stopped) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002219 if (status & UART_MSR_CTS) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002220 port->tty->hw_stopped = 0;
Jiri Slaby037ad482006-12-08 02:38:11 -08002221
Jiri Slaby55b307d2006-12-08 02:38:14 -08002222 if ((port->type != PORT_16550A) &&
2223 (!port->board->chip_flag)) {
2224 outb(port->IER & ~UART_IER_THRI,
2225 port->ioaddr + UART_IER);
2226 port->IER |= UART_IER_THRI;
2227 outb(port->IER, port->ioaddr +
2228 UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002229 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08002230 set_bit(MXSER_EVENT_TXLOW, &port->event);
2231 schedule_work(&port->tqueue);
Jiri Slaby3306ce32006-12-08 02:38:13 -08002232 }
Jiri Slaby037ad482006-12-08 02:38:11 -08002233 } else {
2234 if (!(status & UART_MSR_CTS)) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002235 port->tty->hw_stopped = 1;
2236 if (port->type != PORT_16550A &&
2237 !port->board->chip_flag) {
2238 port->IER &= ~UART_IER_THRI;
2239 outb(port->IER, port->ioaddr +
2240 UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002241 }
2242 }
2243 }
2244 }
2245}
2246
Jiri Slaby55b307d2006-12-08 02:38:14 -08002247static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, struct mxser_port *port)
Jiri Slaby037ad482006-12-08 02:38:11 -08002248{
2249 DECLARE_WAITQUEUE(wait, current);
2250 int retval;
2251 int do_clocal = 0;
2252 unsigned long flags;
2253
2254 /*
2255 * If non-blocking mode is set, or the port is not enabled,
2256 * then make the check up front and then exit.
2257 */
2258 if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002259 port->flags |= ASYNC_NORMAL_ACTIVE;
Jiri Slaby037ad482006-12-08 02:38:11 -08002260 return 0;
2261 }
2262
2263 if (tty->termios->c_cflag & CLOCAL)
2264 do_clocal = 1;
2265
2266 /*
2267 * Block waiting for the carrier detect and the line to become
2268 * free (i.e., not in use by the callout). While we are in
Jiri Slaby55b307d2006-12-08 02:38:14 -08002269 * this loop, port->count is dropped by one, so that
Jiri Slaby037ad482006-12-08 02:38:11 -08002270 * mxser_close() knows when to free things. We restore it upon
2271 * exit, either normal or abnormal.
2272 */
2273 retval = 0;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002274 add_wait_queue(&port->open_wait, &wait);
Jiri Slaby037ad482006-12-08 02:38:11 -08002275
Jiri Slaby55b307d2006-12-08 02:38:14 -08002276 spin_lock_irqsave(&port->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08002277 if (!tty_hung_up_p(filp))
Jiri Slaby55b307d2006-12-08 02:38:14 -08002278 port->count--;
2279 spin_unlock_irqrestore(&port->slock, flags);
2280 port->blocked_open++;
Jiri Slaby037ad482006-12-08 02:38:11 -08002281 while (1) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002282 spin_lock_irqsave(&port->slock, flags);
2283 outb(inb(port->ioaddr + UART_MCR) |
2284 UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR);
2285 spin_unlock_irqrestore(&port->slock, flags);
Jiri Slaby037ad482006-12-08 02:38:11 -08002286 set_current_state(TASK_INTERRUPTIBLE);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002287 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
2288 if (port->flags & ASYNC_HUP_NOTIFY)
Jiri Slaby037ad482006-12-08 02:38:11 -08002289 retval = -EAGAIN;
2290 else
2291 retval = -ERESTARTSYS;
2292 break;
2293 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08002294 if (!(port->flags & ASYNC_CLOSING) &&
Jiri Slaby037ad482006-12-08 02:38:11 -08002295 (do_clocal ||
Jiri Slaby55b307d2006-12-08 02:38:14 -08002296 (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD)))
Jiri Slaby037ad482006-12-08 02:38:11 -08002297 break;
2298 if (signal_pending(current)) {
2299 retval = -ERESTARTSYS;
2300 break;
2301 }
2302 schedule();
2303 }
2304 set_current_state(TASK_RUNNING);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002305 remove_wait_queue(&port->open_wait, &wait);
Jiri Slaby037ad482006-12-08 02:38:11 -08002306 if (!tty_hung_up_p(filp))
Jiri Slaby55b307d2006-12-08 02:38:14 -08002307 port->count++;
2308 port->blocked_open--;
Jiri Slaby037ad482006-12-08 02:38:11 -08002309 if (retval)
2310 return retval;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002311 port->flags |= ASYNC_NORMAL_ACTIVE;
Jiri Slaby037ad482006-12-08 02:38:11 -08002312 return 0;
2313}
2314
Jiri Slaby55b307d2006-12-08 02:38:14 -08002315static int mxser_startup(struct mxser_port *info)
Jiri Slaby037ad482006-12-08 02:38:11 -08002316{
2317 unsigned long page;
2318 unsigned long flags;
2319
2320 page = __get_free_page(GFP_KERNEL);
2321 if (!page)
2322 return -ENOMEM;
2323
2324 spin_lock_irqsave(&info->slock, flags);
2325
2326 if (info->flags & ASYNC_INITIALIZED) {
2327 free_page(page);
2328 spin_unlock_irqrestore(&info->slock, flags);
2329 return 0;
2330 }
2331
Jiri Slaby55b307d2006-12-08 02:38:14 -08002332 if (!info->ioaddr || !info->type) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002333 if (info->tty)
2334 set_bit(TTY_IO_ERROR, &info->tty->flags);
2335 free_page(page);
2336 spin_unlock_irqrestore(&info->slock, flags);
2337 return 0;
2338 }
2339 if (info->xmit_buf)
2340 free_page(page);
2341 else
2342 info->xmit_buf = (unsigned char *) page;
2343
2344 /*
2345 * Clear the FIFO buffers and disable them
2346 * (they will be reenabled in mxser_change_speed())
2347 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002348 if (info->board->chip_flag)
Jiri Slaby037ad482006-12-08 02:38:11 -08002349 outb((UART_FCR_CLEAR_RCVR |
2350 UART_FCR_CLEAR_XMIT |
Jiri Slaby55b307d2006-12-08 02:38:14 -08002351 MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002352 else
2353 outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
Jiri Slaby55b307d2006-12-08 02:38:14 -08002354 info->ioaddr + UART_FCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002355
2356 /*
2357 * At this point there's no way the LSR could still be 0xFF;
2358 * if it is, then bail out, because there's likely no UART
2359 * here.
2360 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002361 if (inb(info->ioaddr + UART_LSR) == 0xff) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002362 spin_unlock_irqrestore(&info->slock, flags);
2363 if (capable(CAP_SYS_ADMIN)) {
2364 if (info->tty)
2365 set_bit(TTY_IO_ERROR, &info->tty->flags);
2366 return 0;
2367 } else
2368 return -ENODEV;
2369 }
2370
2371 /*
2372 * Clear the interrupt registers.
2373 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002374 (void) inb(info->ioaddr + UART_LSR);
2375 (void) inb(info->ioaddr + UART_RX);
2376 (void) inb(info->ioaddr + UART_IIR);
2377 (void) inb(info->ioaddr + UART_MSR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002378
2379 /*
2380 * Now, initialize the UART
2381 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002382 outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR); /* reset DLAB */
Jiri Slaby037ad482006-12-08 02:38:11 -08002383 info->MCR = UART_MCR_DTR | UART_MCR_RTS;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002384 outb(info->MCR, info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002385
2386 /*
2387 * Finally, enable interrupts
2388 */
2389 info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
2390 /* info->IER = UART_IER_RLSI | UART_IER_RDI; */
2391
2392 /* following add by Victor Yu. 08-30-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002393 if (info->board->chip_flag)
Jiri Slaby037ad482006-12-08 02:38:11 -08002394 info->IER |= MOXA_MUST_IER_EGDAI;
2395 /* above add by Victor Yu. 08-30-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002396 outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */
Jiri Slaby037ad482006-12-08 02:38:11 -08002397
2398 /*
2399 * And clear the interrupt registers again for luck.
2400 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002401 (void) inb(info->ioaddr + UART_LSR);
2402 (void) inb(info->ioaddr + UART_RX);
2403 (void) inb(info->ioaddr + UART_IIR);
2404 (void) inb(info->ioaddr + UART_MSR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002405
2406 if (info->tty)
2407 clear_bit(TTY_IO_ERROR, &info->tty->flags);
2408 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
2409
2410 /*
2411 * and set the speed of the serial port
2412 */
2413 spin_unlock_irqrestore(&info->slock, flags);
2414 mxser_change_speed(info, NULL);
2415
2416 info->flags |= ASYNC_INITIALIZED;
2417 return 0;
2418}
2419
2420/*
2421 * This routine will shutdown a serial port; interrupts maybe disabled, and
2422 * DTR is dropped if the hangup on close termio flag is on.
2423 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002424static void mxser_shutdown(struct mxser_port *info)
Jiri Slaby037ad482006-12-08 02:38:11 -08002425{
2426 unsigned long flags;
2427
2428 if (!(info->flags & ASYNC_INITIALIZED))
2429 return;
2430
2431 spin_lock_irqsave(&info->slock, flags);
2432
2433 /*
2434 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
2435 * here so the queue might never be waken up
2436 */
2437 wake_up_interruptible(&info->delta_msr_wait);
2438
2439 /*
2440 * Free the IRQ, if necessary
2441 */
2442 if (info->xmit_buf) {
2443 free_page((unsigned long) info->xmit_buf);
2444 info->xmit_buf = NULL;
2445 }
2446
2447 info->IER = 0;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002448 outb(0x00, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002449
2450 if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
2451 info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002452 outb(info->MCR, info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002453
2454 /* clear Rx/Tx FIFO's */
2455 /* following add by Victor Yu. 08-30-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002456 if (info->board->chip_flag)
2457 outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
2458 MOXA_MUST_FCR_GDA_MODE_ENABLE,
2459 info->ioaddr + UART_FCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002460 else
2461 /* above add by Victor Yu. 08-30-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002462 outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
2463 info->ioaddr + UART_FCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002464
2465 /* read data port to reset things */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002466 (void) inb(info->ioaddr + UART_RX);
Jiri Slaby037ad482006-12-08 02:38:11 -08002467
2468 if (info->tty)
2469 set_bit(TTY_IO_ERROR, &info->tty->flags);
2470
2471 info->flags &= ~ASYNC_INITIALIZED;
2472
2473 /* following add by Victor Yu. 09-23-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002474 if (info->board->chip_flag)
2475 SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -08002476 /* above add by Victor Yu. 09-23-2002 */
2477
2478 spin_unlock_irqrestore(&info->slock, flags);
2479}
2480
2481/*
2482 * This routine is called to set the UART divisor registers to match
2483 * the specified baud rate for a serial port.
2484 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002485static int mxser_change_speed(struct mxser_port *info,
2486 struct termios *old_termios)
Jiri Slaby037ad482006-12-08 02:38:11 -08002487{
2488 unsigned cflag, cval, fcr;
2489 int ret = 0;
2490 unsigned char status;
2491 long baud;
2492 unsigned long flags;
2493
2494 if (!info->tty || !info->tty->termios)
2495 return ret;
2496 cflag = info->tty->termios->c_cflag;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002497 if (!(info->ioaddr))
Jiri Slaby037ad482006-12-08 02:38:11 -08002498 return ret;
2499
2500#ifndef B921600
2501#define B921600 (B460800 +1)
2502#endif
Jiri Slaby55b307d2006-12-08 02:38:14 -08002503 if (mxser_set_baud_method[info->tty->index] == 0) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002504 baud = tty_get_baud_rate(info->tty);
2505 mxser_set_baud(info, baud);
2506 }
2507
2508 /* byte size and parity */
2509 switch (cflag & CSIZE) {
2510 case CS5:
2511 cval = 0x00;
2512 break;
2513 case CS6:
2514 cval = 0x01;
2515 break;
2516 case CS7:
2517 cval = 0x02;
2518 break;
2519 case CS8:
2520 cval = 0x03;
2521 break;
2522 default:
2523 cval = 0x00;
2524 break; /* too keep GCC shut... */
2525 }
2526 if (cflag & CSTOPB)
2527 cval |= 0x04;
2528 if (cflag & PARENB)
2529 cval |= UART_LCR_PARITY;
2530 if (!(cflag & PARODD))
2531 cval |= UART_LCR_EPAR;
2532 if (cflag & CMSPAR)
2533 cval |= UART_LCR_SPAR;
2534
2535 if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002536 if (info->board->chip_flag) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002537 fcr = UART_FCR_ENABLE_FIFO;
2538 fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
2539 SET_MOXA_MUST_FIFO_VALUE(info);
2540 } else
2541 fcr = 0;
2542 } else {
2543 fcr = UART_FCR_ENABLE_FIFO;
2544 /* following add by Victor Yu. 08-30-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002545 if (info->board->chip_flag) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002546 fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
2547 SET_MOXA_MUST_FIFO_VALUE(info);
2548 } else {
2549 /* above add by Victor Yu. 08-30-2002 */
2550 switch (info->rx_trigger) {
2551 case 1:
2552 fcr |= UART_FCR_TRIGGER_1;
2553 break;
2554 case 4:
2555 fcr |= UART_FCR_TRIGGER_4;
2556 break;
2557 case 8:
2558 fcr |= UART_FCR_TRIGGER_8;
2559 break;
2560 default:
2561 fcr |= UART_FCR_TRIGGER_14;
2562 break;
2563 }
2564 }
2565 }
2566
2567 /* CTS flow control flag and modem status interrupts */
2568 info->IER &= ~UART_IER_MSI;
2569 info->MCR &= ~UART_MCR_AFE;
2570 if (cflag & CRTSCTS) {
2571 info->flags |= ASYNC_CTS_FLOW;
2572 info->IER |= UART_IER_MSI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002573 if ((info->type == PORT_16550A) || (info->board->chip_flag)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002574 info->MCR |= UART_MCR_AFE;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002575/* status = mxser_get_msr(info->ioaddr, 0, info->port); */
Jiri Slaby037ad482006-12-08 02:38:11 -08002576/*
2577 save_flags(flags);
2578 cli();
2579 status = inb(baseaddr + UART_MSR);
2580 restore_flags(flags);
2581*/
2582 /* mxser_check_modem_status(info, status); */
2583 } else {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002584/* status = mxser_get_msr(info->ioaddr, 0, info->port); */
Jiri Slaby037ad482006-12-08 02:38:11 -08002585 /* MX_LOCK(&info->slock); */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002586 status = inb(info->ioaddr + UART_MSR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002587 /* MX_UNLOCK(&info->slock); */
2588 if (info->tty->hw_stopped) {
2589 if (status & UART_MSR_CTS) {
2590 info->tty->hw_stopped = 0;
Jiri Slaby3306ce32006-12-08 02:38:13 -08002591 if (info->type != PORT_16550A &&
Jiri Slaby55b307d2006-12-08 02:38:14 -08002592 !info->board->chip_flag) {
Jiri Slaby3306ce32006-12-08 02:38:13 -08002593 outb(info->IER & ~UART_IER_THRI,
Jiri Slaby55b307d2006-12-08 02:38:14 -08002594 info->ioaddr +
2595 UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002596 info->IER |= UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002597 outb(info->IER, info->ioaddr +
2598 UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002599 }
2600 set_bit(MXSER_EVENT_TXLOW, &info->event);
2601 schedule_work(&info->tqueue); }
2602 } else {
2603 if (!(status & UART_MSR_CTS)) {
2604 info->tty->hw_stopped = 1;
2605 if ((info->type != PORT_16550A) &&
Jiri Slaby55b307d2006-12-08 02:38:14 -08002606 (!info->board->chip_flag)) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002607 info->IER &= ~UART_IER_THRI;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002608 outb(info->IER, info->ioaddr +
2609 UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002610 }
2611 }
2612 }
2613 }
2614 } else {
2615 info->flags &= ~ASYNC_CTS_FLOW;
2616 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08002617 outb(info->MCR, info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002618 if (cflag & CLOCAL) {
2619 info->flags &= ~ASYNC_CHECK_CD;
2620 } else {
2621 info->flags |= ASYNC_CHECK_CD;
2622 info->IER |= UART_IER_MSI;
2623 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08002624 outb(info->IER, info->ioaddr + UART_IER);
Jiri Slaby037ad482006-12-08 02:38:11 -08002625
2626 /*
2627 * Set up parity check flag
2628 */
2629 info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
2630 if (I_INPCK(info->tty))
2631 info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
2632 if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
2633 info->read_status_mask |= UART_LSR_BI;
2634
2635 info->ignore_status_mask = 0;
2636
2637 if (I_IGNBRK(info->tty)) {
2638 info->ignore_status_mask |= UART_LSR_BI;
2639 info->read_status_mask |= UART_LSR_BI;
2640 /*
2641 * If we're ignore parity and break indicators, ignore
2642 * overruns too. (For real raw support).
2643 */
2644 if (I_IGNPAR(info->tty)) {
2645 info->ignore_status_mask |=
2646 UART_LSR_OE |
2647 UART_LSR_PE |
2648 UART_LSR_FE;
2649 info->read_status_mask |=
2650 UART_LSR_OE |
2651 UART_LSR_PE |
2652 UART_LSR_FE;
2653 }
2654 }
2655 /* following add by Victor Yu. 09-02-2002 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002656 if (info->board->chip_flag) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002657 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002658 SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty));
2659 SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty));
Jiri Slaby037ad482006-12-08 02:38:11 -08002660 if (I_IXON(info->tty)) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002661 ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -08002662 } else {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002663 DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -08002664 }
2665 if (I_IXOFF(info->tty)) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002666 ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -08002667 } else {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002668 DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -08002669 }
2670 /*
2671 if ( I_IXANY(info->tty) ) {
2672 info->MCR |= MOXA_MUST_MCR_XON_ANY;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002673 ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -08002674 } else {
2675 info->MCR &= ~MOXA_MUST_MCR_XON_ANY;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002676 DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->ioaddr);
Jiri Slaby037ad482006-12-08 02:38:11 -08002677 }
2678 */
2679 spin_unlock_irqrestore(&info->slock, flags);
2680 }
2681 /* above add by Victor Yu. 09-02-2002 */
2682
2683
Jiri Slaby55b307d2006-12-08 02:38:14 -08002684 outb(fcr, info->ioaddr + UART_FCR); /* set fcr */
2685 outb(cval, info->ioaddr + UART_LCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002686
2687 return ret;
2688}
2689
2690
Jiri Slaby55b307d2006-12-08 02:38:14 -08002691static int mxser_set_baud(struct mxser_port *info, long newspd)
Jiri Slaby037ad482006-12-08 02:38:11 -08002692{
2693 int quot = 0;
2694 unsigned char cval;
2695 int ret = 0;
2696 unsigned long flags;
2697
2698 if (!info->tty || !info->tty->termios)
2699 return ret;
2700
Jiri Slaby55b307d2006-12-08 02:38:14 -08002701 if (!(info->ioaddr))
Jiri Slaby037ad482006-12-08 02:38:11 -08002702 return ret;
2703
Jiri Slaby55b307d2006-12-08 02:38:14 -08002704 if (newspd > info->max_baud)
Jiri Slaby037ad482006-12-08 02:38:11 -08002705 return 0;
2706
2707 info->realbaud = newspd;
2708 if (newspd == 134) {
2709 quot = (2 * info->baud_base / 269);
2710 } else if (newspd) {
2711 quot = info->baud_base / newspd;
2712 if (quot == 0)
2713 quot = 1;
2714 } else {
2715 quot = 0;
2716 }
2717
2718 info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
2719 info->timeout += HZ / 50; /* Add .02 seconds of slop */
2720
2721 if (quot) {
2722 spin_lock_irqsave(&info->slock, flags);
2723 info->MCR |= UART_MCR_DTR;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002724 outb(info->MCR, info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002725 spin_unlock_irqrestore(&info->slock, flags);
2726 } else {
2727 spin_lock_irqsave(&info->slock, flags);
2728 info->MCR &= ~UART_MCR_DTR;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002729 outb(info->MCR, info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002730 spin_unlock_irqrestore(&info->slock, flags);
2731 return ret;
2732 }
2733
Jiri Slaby55b307d2006-12-08 02:38:14 -08002734 cval = inb(info->ioaddr + UART_LCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002735
Jiri Slaby55b307d2006-12-08 02:38:14 -08002736 outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR); /* set DLAB */
Jiri Slaby037ad482006-12-08 02:38:11 -08002737
Jiri Slaby55b307d2006-12-08 02:38:14 -08002738 outb(quot & 0xff, info->ioaddr + UART_DLL); /* LS of divisor */
2739 outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */
2740 outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
Jiri Slaby037ad482006-12-08 02:38:11 -08002741
2742
2743 return ret;
2744}
2745
2746/*
2747 * ------------------------------------------------------------
2748 * friends of mxser_ioctl()
2749 * ------------------------------------------------------------
2750 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002751static int mxser_get_serial_info(struct mxser_port *info,
2752 struct serial_struct __user *retinfo)
Jiri Slaby037ad482006-12-08 02:38:11 -08002753{
2754 struct serial_struct tmp;
2755
2756 if (!retinfo)
2757 return -EFAULT;
2758 memset(&tmp, 0, sizeof(tmp));
2759 tmp.type = info->type;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002760 tmp.line = info->tty->index;
2761 tmp.port = info->ioaddr;
2762 tmp.irq = info->board->irq;
Jiri Slaby037ad482006-12-08 02:38:11 -08002763 tmp.flags = info->flags;
2764 tmp.baud_base = info->baud_base;
2765 tmp.close_delay = info->close_delay;
2766 tmp.closing_wait = info->closing_wait;
2767 tmp.custom_divisor = info->custom_divisor;
2768 tmp.hub6 = 0;
2769 if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
2770 return -EFAULT;
2771 return 0;
2772}
2773
Jiri Slaby55b307d2006-12-08 02:38:14 -08002774static int mxser_set_serial_info(struct mxser_port *info,
2775 struct serial_struct __user *new_info)
Jiri Slaby037ad482006-12-08 02:38:11 -08002776{
2777 struct serial_struct new_serial;
2778 unsigned int flags;
2779 int retval = 0;
2780
Jiri Slaby55b307d2006-12-08 02:38:14 -08002781 if (!new_info || !info->ioaddr)
Jiri Slaby037ad482006-12-08 02:38:11 -08002782 return -EFAULT;
2783 if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
2784 return -EFAULT;
2785
Jiri Slaby55b307d2006-12-08 02:38:14 -08002786 if ((new_serial.irq != info->board->irq) ||
2787 (new_serial.port != info->ioaddr) ||
Jiri Slaby037ad482006-12-08 02:38:11 -08002788 (new_serial.custom_divisor != info->custom_divisor) ||
2789 (new_serial.baud_base != info->baud_base))
2790 return -EPERM;
2791
2792 flags = info->flags & ASYNC_SPD_MASK;
2793
2794 if (!capable(CAP_SYS_ADMIN)) {
2795 if ((new_serial.baud_base != info->baud_base) ||
2796 (new_serial.close_delay != info->close_delay) ||
2797 ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK)))
2798 return -EPERM;
2799 info->flags = ((info->flags & ~ASYNC_USR_MASK) |
2800 (new_serial.flags & ASYNC_USR_MASK));
2801 } else {
2802 /*
2803 * OK, past this point, all the error checking has been done.
2804 * At this point, we start making changes.....
2805 */
2806 info->flags = ((info->flags & ~ASYNC_FLAGS) |
2807 (new_serial.flags & ASYNC_FLAGS));
2808 info->close_delay = new_serial.close_delay * HZ / 100;
2809 info->closing_wait = new_serial.closing_wait * HZ / 100;
2810 info->tty->low_latency =
2811 (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
2812 info->tty->low_latency = 0; /* (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; */
2813 }
2814
2815 /* added by casper, 3/17/2000, for mouse */
2816 info->type = new_serial.type;
2817
2818 process_txrx_fifo(info);
2819
2820 if (info->flags & ASYNC_INITIALIZED) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002821 if (flags != (info->flags & ASYNC_SPD_MASK))
Jiri Slaby037ad482006-12-08 02:38:11 -08002822 mxser_change_speed(info, NULL);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002823 } else
Jiri Slaby037ad482006-12-08 02:38:11 -08002824 retval = mxser_startup(info);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002825
Jiri Slaby037ad482006-12-08 02:38:11 -08002826 return retval;
2827}
2828
2829/*
2830 * mxser_get_lsr_info - get line status register info
2831 *
2832 * Purpose: Let user call ioctl() to get info when the UART physically
2833 * is emptied. On bus types like RS485, the transmitter must
2834 * release the bus after transmitting. This must be done when
2835 * the transmit shift register is empty, not be done when the
2836 * transmit holding register is empty. This functionality
2837 * allows an RS485 driver to be written in user space.
2838 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002839static int mxser_get_lsr_info(struct mxser_port *info,
2840 unsigned int __user *value)
Jiri Slaby037ad482006-12-08 02:38:11 -08002841{
2842 unsigned char status;
2843 unsigned int result;
2844 unsigned long flags;
2845
2846 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002847 status = inb(info->ioaddr + UART_LSR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002848 spin_unlock_irqrestore(&info->slock, flags);
2849 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
2850 return put_user(result, value);
2851}
2852
2853/*
2854 * This routine sends a break character out the serial port.
2855 */
Jiri Slaby55b307d2006-12-08 02:38:14 -08002856static void mxser_send_break(struct mxser_port *info, int duration)
Jiri Slaby037ad482006-12-08 02:38:11 -08002857{
2858 unsigned long flags;
2859
Jiri Slaby55b307d2006-12-08 02:38:14 -08002860 if (!info->ioaddr)
Jiri Slaby037ad482006-12-08 02:38:11 -08002861 return;
2862 set_current_state(TASK_INTERRUPTIBLE);
2863 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002864 outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
2865 info->ioaddr + UART_LCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002866 spin_unlock_irqrestore(&info->slock, flags);
2867 schedule_timeout(duration);
2868 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002869 outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
2870 info->ioaddr + UART_LCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002871 spin_unlock_irqrestore(&info->slock, flags);
2872}
2873
2874static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
2875{
Jiri Slaby55b307d2006-12-08 02:38:14 -08002876 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08002877 unsigned char control, status;
2878 unsigned long flags;
2879
2880
2881 if (tty->index == MXSER_PORTS)
2882 return -ENOIOCTLCMD;
2883 if (tty->flags & (1 << TTY_IO_ERROR))
2884 return -EIO;
2885
2886 control = info->MCR;
2887
2888 spin_lock_irqsave(&info->slock, flags);
Jiri Slaby55b307d2006-12-08 02:38:14 -08002889 status = inb(info->ioaddr + UART_MSR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002890 if (status & UART_MSR_ANY_DELTA)
2891 mxser_check_modem_status(info, status);
2892 spin_unlock_irqrestore(&info->slock, flags);
2893 return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
2894 ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
2895 ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
2896 ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
2897 ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
2898 ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
2899}
2900
Jiri Slaby55b307d2006-12-08 02:38:14 -08002901static int mxser_tiocmset(struct tty_struct *tty, struct file *file,
2902 unsigned int set, unsigned int clear)
Jiri Slaby037ad482006-12-08 02:38:11 -08002903{
Jiri Slaby55b307d2006-12-08 02:38:14 -08002904 struct mxser_port *info = tty->driver_data;
Jiri Slaby037ad482006-12-08 02:38:11 -08002905 unsigned long flags;
2906
2907
2908 if (tty->index == MXSER_PORTS)
2909 return -ENOIOCTLCMD;
2910 if (tty->flags & (1 << TTY_IO_ERROR))
2911 return -EIO;
2912
2913 spin_lock_irqsave(&info->slock, flags);
2914
2915 if (set & TIOCM_RTS)
2916 info->MCR |= UART_MCR_RTS;
2917 if (set & TIOCM_DTR)
2918 info->MCR |= UART_MCR_DTR;
2919
2920 if (clear & TIOCM_RTS)
2921 info->MCR &= ~UART_MCR_RTS;
2922 if (clear & TIOCM_DTR)
2923 info->MCR &= ~UART_MCR_DTR;
2924
Jiri Slaby55b307d2006-12-08 02:38:14 -08002925 outb(info->MCR, info->ioaddr + UART_MCR);
Jiri Slaby037ad482006-12-08 02:38:11 -08002926 spin_unlock_irqrestore(&info->slock, flags);
2927 return 0;
2928}
2929
2930
2931static int mxser_read_register(int, unsigned short *);
2932static int mxser_program_mode(int);
2933static void mxser_normal_mode(int);
2934
Jiri Slaby943f2952006-12-08 02:38:15 -08002935static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
Jiri Slaby037ad482006-12-08 02:38:11 -08002936{
2937 int id, i, bits;
2938 unsigned short regs[16], irq;
2939 unsigned char scratch, scratch2;
2940
Jiri Slaby55b307d2006-12-08 02:38:14 -08002941 brd->chip_flag = MOXA_OTHER_UART;
Jiri Slaby037ad482006-12-08 02:38:11 -08002942
2943 id = mxser_read_register(cap, regs);
2944 if (id == C168_ASIC_ID) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002945 brd->board_type = MXSER_BOARD_C168_ISA;
2946 brd->nports = 8;
Jiri Slaby037ad482006-12-08 02:38:11 -08002947 } else if (id == C104_ASIC_ID) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002948 brd->board_type = MXSER_BOARD_C104_ISA;
2949 brd->nports = 4;
Jiri Slaby037ad482006-12-08 02:38:11 -08002950 } else if (id == C102_ASIC_ID) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002951 brd->board_type = MXSER_BOARD_C102_ISA;
2952 brd->nports = 2;
Jiri Slaby037ad482006-12-08 02:38:11 -08002953 } else if (id == CI132_ASIC_ID) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002954 brd->board_type = MXSER_BOARD_CI132;
2955 brd->nports = 2;
Jiri Slaby037ad482006-12-08 02:38:11 -08002956 } else if (id == CI134_ASIC_ID) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002957 brd->board_type = MXSER_BOARD_CI134;
2958 brd->nports = 4;
Jiri Slaby037ad482006-12-08 02:38:11 -08002959 } else if (id == CI104J_ASIC_ID) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002960 brd->board_type = MXSER_BOARD_CI104J;
2961 brd->nports = 4;
Jiri Slaby037ad482006-12-08 02:38:11 -08002962 } else
2963 return 0;
2964
2965 irq = 0;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002966 if (brd->nports == 2) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002967 irq = regs[9] & 0xF000;
2968 irq = irq | (irq >> 4);
2969 if (irq != (regs[9] & 0xFF00))
2970 return MXSER_ERR_IRQ_CONFLIT;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002971 } else if (brd->nports == 4) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002972 irq = regs[9] & 0xF000;
2973 irq = irq | (irq >> 4);
2974 irq = irq | (irq >> 8);
2975 if (irq != regs[9])
2976 return MXSER_ERR_IRQ_CONFLIT;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002977 } else if (brd->nports == 8) {
Jiri Slaby037ad482006-12-08 02:38:11 -08002978 irq = regs[9] & 0xF000;
2979 irq = irq | (irq >> 4);
2980 irq = irq | (irq >> 8);
2981 if ((irq != regs[9]) || (irq != regs[10]))
2982 return MXSER_ERR_IRQ_CONFLIT;
2983 }
2984
2985 if (!irq)
2986 return MXSER_ERR_IRQ;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002987 brd->irq = ((int)(irq & 0xF000) >> 12);
Jiri Slaby037ad482006-12-08 02:38:11 -08002988 for (i = 0; i < 8; i++)
Jiri Slaby55b307d2006-12-08 02:38:14 -08002989 brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8;
Jiri Slaby037ad482006-12-08 02:38:11 -08002990 if ((regs[12] & 0x80) == 0)
2991 return MXSER_ERR_VECTOR;
Jiri Slaby55b307d2006-12-08 02:38:14 -08002992 brd->vector = (int)regs[11]; /* interrupt vector */
Jiri Slaby037ad482006-12-08 02:38:11 -08002993 if (id == 1)
Jiri Slaby55b307d2006-12-08 02:38:14 -08002994 brd->vector_mask = 0x00FF;
Jiri Slaby037ad482006-12-08 02:38:11 -08002995 else
Jiri Slaby55b307d2006-12-08 02:38:14 -08002996 brd->vector_mask = 0x000F;
Jiri Slaby037ad482006-12-08 02:38:11 -08002997 for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
2998 if (regs[12] & bits) {
Jiri Slaby55b307d2006-12-08 02:38:14 -08002999 brd->ports[i].baud_base = 921600;
3000 brd->ports[i].max_baud = 921600; /* add by Victor Yu. 09-04-2002 */
Jiri Slaby037ad482006-12-08 02:38:11 -08003001 } else {
Jiri Slaby55b307d2006-12-08 02:38:14 -08003002 brd->ports[i].baud_base = 115200;
3003 brd->ports[i].max_baud = 115200; /* add by Victor Yu. 09-04-2002 */
Jiri Slaby037ad482006-12-08 02:38:11 -08003004 }
3005 }
3006 scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
3007 outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);
3008 outb(0, cap + UART_EFR); /* EFR is the same as FCR */
3009 outb(scratch2, cap + UART_LCR);
3010 outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);
3011 scratch = inb(cap + UART_IIR);
3012
3013 if (scratch & 0xC0)
Jiri Slaby55b307d2006-12-08 02:38:14 -08003014 brd->uart_type = PORT_16550A;
Jiri Slaby037ad482006-12-08 02:38:11 -08003015 else
Jiri Slaby55b307d2006-12-08 02:38:14 -08003016 brd->uart_type = PORT_16450;
Jiri Slaby037ad482006-12-08 02:38:11 -08003017 if (id == 1)
Jiri Slaby55b307d2006-12-08 02:38:14 -08003018 brd->nports = 8;
Jiri Slaby037ad482006-12-08 02:38:11 -08003019 else
Jiri Slaby55b307d2006-12-08 02:38:14 -08003020 brd->nports = 4;
Jiri Slaby7a7a5c32006-12-08 02:38:17 -08003021 if (!request_region(brd->ports[0].ioaddr, 8 * brd->nports, "mxser(IO)"))
3022 return MXSER_ERR_IOADDR;
3023 if (!request_region(brd->vector, 1, "mxser(vector)")) {
3024 release_region(brd->ports[0].ioaddr, 8 * brd->nports);
3025 return MXSER_ERR_VECTOR;
3026 }
Jiri Slaby55b307d2006-12-08 02:38:14 -08003027 return brd->nports;
Jiri Slaby037ad482006-12-08 02:38:11 -08003028}
3029
3030#define CHIP_SK 0x01 /* Serial Data Clock in Eprom */
3031#define CHIP_DO 0x02 /* Serial Data Output in Eprom */
3032#define CHIP_CS 0x04 /* Serial Chip Select in Eprom */
3033#define CHIP_DI 0x08 /* Serial Data Input in Eprom */
3034#define EN_CCMD 0x000 /* Chip's command register */
3035#define EN0_RSARLO 0x008 /* Remote start address reg 0 */
3036#define EN0_RSARHI 0x009 /* Remote start address reg 1 */
3037#define EN0_RCNTLO 0x00A /* Remote byte count reg WR */
3038#define EN0_RCNTHI 0x00B /* Remote byte count reg WR */
3039#define EN0_DCFG 0x00E /* Data configuration reg WR */
3040#define EN0_PORT 0x010 /* Rcv missed frame error counter RD */
3041#define ENC_PAGE0 0x000 /* Select page 0 of chip registers */
3042#define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */
3043static int mxser_read_register(int port, unsigned short *regs)
3044{
3045 int i, k, value, id;
3046 unsigned int j;
3047
3048 id = mxser_program_mode(port);
3049 if (id < 0)
3050 return id;
3051 for (i = 0; i < 14; i++) {
3052 k = (i & 0x3F) | 0x180;
3053 for (j = 0x100; j > 0; j >>= 1) {
3054 outb(CHIP_CS, port);
3055 if (k & j) {
3056 outb(CHIP_CS | CHIP_DO, port);
3057 outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */
3058 } else {
3059 outb(CHIP_CS, port);
3060 outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */
3061 }
3062 }
3063 (void)inb(port);
3064 value = 0;
3065 for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
3066 outb(CHIP_CS, port);
3067 outb(CHIP_CS | CHIP_SK, port);
3068 if (inb(port) & CHIP_DI)
3069 value |= j;
3070 }
3071 regs[i] = value;
3072 outb(0, port);
3073 }
3074 mxser_normal_mode(port);
3075 return id;
3076}
3077
3078static int mxser_program_mode(int port)
3079{
3080 int id, i, j, n;
3081 /* unsigned long flags; */
3082
3083 spin_lock(&gm_lock);
3084 outb(0, port);
3085 outb(0, port);
3086 outb(0, port);
3087 (void)inb(port);
3088 (void)inb(port);
3089 outb(0, port);
3090 (void)inb(port);
3091 /* restore_flags(flags); */
3092 spin_unlock(&gm_lock);
3093
3094 id = inb(port + 1) & 0x1F;
3095 if ((id != C168_ASIC_ID) &&
3096 (id != C104_ASIC_ID) &&
3097 (id != C102_ASIC_ID) &&
3098 (id != CI132_ASIC_ID) &&
3099 (id != CI134_ASIC_ID) &&
3100 (id != CI104J_ASIC_ID))
3101 return -1;
3102 for (i = 0, j = 0; i < 4; i++) {
3103 n = inb(port + 2);
3104 if (n == 'M') {
3105 j = 1;
3106 } else if ((j == 1) && (n == 1)) {
3107 j = 2;
3108 break;
3109 } else
3110 j = 0;
3111 }
3112 if (j != 2)
3113 id = -2;
3114 return id;
3115}
3116
3117static void mxser_normal_mode(int port)
3118{
3119 int i, n;
3120
3121 outb(0xA5, port + 1);
3122 outb(0x80, port + 3);
3123 outb(12, port + 0); /* 9600 bps */
3124 outb(0, port + 1);
3125 outb(0x03, port + 3); /* 8 data bits */
3126 outb(0x13, port + 4); /* loop back mode */
3127 for (i = 0; i < 16; i++) {
3128 n = inb(port + 5);
3129 if ((n & 0x61) == 0x60)
3130 break;
3131 if ((n & 1) == 1)
3132 (void)inb(port);
3133 }
3134 outb(0x00, port + 4);
3135}
3136
3137module_init(mxser_module_init);
3138module_exit(mxser_module_exit);