Blame view

drivers/tty/moxa.c 52.1 KB
e3b3d0f54   Greg Kroah-Hartman   tty: add SPDX ide...
1
  // SPDX-License-Identifier: GPL-2.0+
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
  /*****************************************************************************/
  /*
   *           moxa.c  -- MOXA Intellio family multiport serial driver.
   *
b9705b603   Jiri Slaby   Char: moxa, updat...
6
7
   *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com).
   *      Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
   *
   *      This code is loosely based on the Linux serial driver, written by
   *      Linus Torvalds, Theodore T'so and others.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
16
17
18
   */
  
  /*
   *    MOXA Intellio Series Driver
   *      for             : LINUX
   *      date            : 1999/1/7
   *      version         : 5.1
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/mm.h>
  #include <linux/ioport.h>
  #include <linux/errno.h>
037182346   Jiri Slaby   Char: moxa, add f...
24
  #include <linux/firmware.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  #include <linux/signal.h>
  #include <linux/sched.h>
  #include <linux/timer.h>
  #include <linux/interrupt.h>
  #include <linux/tty.h>
  #include <linux/tty_flip.h>
  #include <linux/major.h>
  #include <linux/string.h>
  #include <linux/fcntl.h>
  #include <linux/ptrace.h>
  #include <linux/serial.h>
  #include <linux/tty_driver.h>
  #include <linux/delay.h>
  #include <linux/pci.h>
  #include <linux/init.h>
  #include <linux/bitops.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
41
  #include <linux/slab.h>
5a3c6b251   Manuel Zerpies   drivers/tty: use ...
42
  #include <linux/ratelimit.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  #include <asm/io.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
45
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

037182346   Jiri Slaby   Char: moxa, add f...
47
  #include "moxa.h"
b9705b603   Jiri Slaby   Char: moxa, updat...
48
  #define MOXA_VERSION		"6.0k"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49

037182346   Jiri Slaby   Char: moxa, add f...
50
  #define MOXA_FW_HDRLEN		32
11324edd4   Jiri Slaby   [PATCH] Char: mox...
51
  #define MOXAMAJOR		172
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52

11324edd4   Jiri Slaby   [PATCH] Char: mox...
53
  #define MAX_BOARDS		4	/* Don't change this value */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  #define MAX_PORTS_PER_BOARD	32	/* Don't change this value */
11324edd4   Jiri Slaby   [PATCH] Char: mox...
55
  #define MAX_PORTS		(MAX_BOARDS * MAX_PORTS_PER_BOARD)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56

08d01c792   Jiri Slaby   Char: moxa, intro...
57
58
  #define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \
  		(brd)->boardType == MOXA_BOARD_C320_PCI)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
  /*
   *    Define the Moxa PCI vendor and device IDs.
   */
11324edd4   Jiri Slaby   [PATCH] Char: mox...
62
63
  #define MOXA_BUS_TYPE_ISA	0
  #define MOXA_BUS_TYPE_PCI	1
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  enum {
  	MOXA_BOARD_C218_PCI = 1,
  	MOXA_BOARD_C218_ISA,
  	MOXA_BOARD_C320_PCI,
  	MOXA_BOARD_C320_ISA,
  	MOXA_BOARD_CP204J,
  };
  
  static char *moxa_brdname[] =
  {
  	"C218 Turbo PCI series",
  	"C218 Turbo ISA series",
  	"C320 Turbo PCI series",
  	"C320 Turbo ISA series",
  	"CP-204J series",
  };
  
  #ifdef CONFIG_PCI
50bd842b3   Arvind Yadav   tty: moxa: consti...
83
  static const struct pci_device_id moxa_pcibrds[] = {
5ebb4078a   Jiri Slaby   [PATCH] Char: mox...
84
85
86
87
88
89
  	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218),
  		.driver_data = MOXA_BOARD_C218_PCI },
  	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320),
  		.driver_data = MOXA_BOARD_C320_PCI },
  	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J),
  		.driver_data = MOXA_BOARD_CP204J },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
  	{ 0 }
  };
  MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
  #endif /* CONFIG_PCI */
037182346   Jiri Slaby   Char: moxa, add f...
94
  struct moxa_port;
8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
95
  static struct moxa_board_conf {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
  	int boardType;
  	int numPorts;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  	int busType;
8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
99

810ab09b2   Jiri Slaby   Char: moxa, centr...
100
  	unsigned int ready;
8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
101

037182346   Jiri Slaby   Char: moxa, add f...
102
  	struct moxa_port *ports;
8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
103
104
105
106
107
108
109
110
111
112
113
114
  	void __iomem *basemem;
  	void __iomem *intNdx;
  	void __iomem *intPend;
  	void __iomem *intTable;
  } moxa_boards[MAX_BOARDS];
  
  struct mxser_mstatus {
  	tcflag_t cflag;
  	int cts;
  	int dsr;
  	int ri;
  	int dcd;
9dff89cd8   Jiri Slaby   [PATCH] Char: mox...
115
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116

8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
117
118
119
120
  struct moxaq_str {
  	int inq;
  	int outq;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121

8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
122
  struct moxa_port {
9de6a51fe   Alan Cox   moxa: use tty_port
123
  	struct tty_port port;
b4173f457   Jiri Slaby   Char: moxa, remov...
124
  	struct moxa_board_conf *board;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
125
  	void __iomem *tableAddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  	int type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  	int cflag;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
128
  	unsigned long statusflags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129

8482bcd58   Alan Cox   tty: moxa: Fix mo...
130
  	u8 DCDState;		/* Protected by the port lock */
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
131
132
  	u8 lineCtrl;
  	u8 lowChkFlag;
8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
133
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134

74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
135
136
137
138
139
  struct mon_str {
  	int tick;
  	int rxcnt[MAX_PORTS];
  	int txcnt[MAX_PORTS];
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  /* statusflags */
a808ac0c4   Alan Cox   tty: moxa: Lockin...
141
142
143
  #define TXSTOPPED	1
  #define LOWWAIT 	2
  #define EMPTYWAIT	3
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  #define WAKEUP_CHARS		256
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  static int ttymajor = MOXAMAJOR;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
148
149
  static struct mon_str moxaLog;
  static unsigned int moxaFuncTout = HZ / 2;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
150
  static unsigned int moxaLowWaterChk;
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
151
  static DEFINE_MUTEX(moxa_openlock);
e8c62103f   Alan Cox   tty: moxa: split ...
152
  static DEFINE_SPINLOCK(moxa_lock);
c6fc826e4   Rakib Mullick   tty: moxa: remove...
153

d353eca4e   Jiri Slaby   Char: moxa, clean...
154
155
156
  static unsigned long baseaddr[MAX_BOARDS];
  static unsigned int type[MAX_BOARDS];
  static unsigned int numports[MAX_BOARDS];
793be8984   Jiri Slaby   TTY: moxa, conver...
157
  static struct tty_port moxa_service_port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
  
  MODULE_AUTHOR("William Chen");
  MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
  MODULE_LICENSE("GPL");
e6c4ef984   Ben Hutchings   tty: declare MODU...
162
163
164
  MODULE_FIRMWARE("c218tunx.cod");
  MODULE_FIRMWARE("cp204unx.cod");
  MODULE_FIRMWARE("c320tunx.cod");
c6fc826e4   Rakib Mullick   tty: moxa: remove...
165

d353eca4e   Jiri Slaby   Char: moxa, clean...
166
167
  module_param_array(type, uint, NULL, 0);
  MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
3b60daf86   David Howells   Annotate hardware...
168
  module_param_hw_array(baseaddr, ulong, ioport, NULL, 0);
d353eca4e   Jiri Slaby   Char: moxa, clean...
169
170
171
  MODULE_PARM_DESC(baseaddr, "base address");
  module_param_array(numports, uint, NULL, 0);
  MODULE_PARM_DESC(numports, "numports (ignored for C218)");
c6fc826e4   Rakib Mullick   tty: moxa: remove...
172

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  module_param(ttymajor, int, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
  /*
   * static functions:
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
182
183
  static int moxa_open(struct tty_struct *, struct file *);
  static void moxa_close(struct tty_struct *, struct file *);
  static int moxa_write(struct tty_struct *, const unsigned char *, int);
  static int moxa_write_room(struct tty_struct *);
  static void moxa_flush_buffer(struct tty_struct *);
  static int moxa_chars_in_buffer(struct tty_struct *);
606d099cd   Alan Cox   [PATCH] tty: swit...
184
  static void moxa_set_termios(struct tty_struct *, struct ktermios *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
  static void moxa_stop(struct tty_struct *);
  static void moxa_start(struct tty_struct *);
  static void moxa_hangup(struct tty_struct *);
60b33c133   Alan Cox   tiocmget: kill of...
188
  static int moxa_tiocmget(struct tty_struct *tty);
20b9d1771   Alan Cox   tiocmset: kill th...
189
  static int moxa_tiocmset(struct tty_struct *tty,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  			 unsigned int set, unsigned int clear);
24ed960ab   Kees Cook   treewide: Switch ...
191
  static void moxa_poll(struct timer_list *);
db1acaa63   Alan Cox   moxa: first pass ...
192
  static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
f176178ba   Alan Cox   tty: moxa: Use mo...
193
  static void moxa_shutdown(struct tty_port *);
31f35939d   Alan Cox   tty_port: Add a p...
194
  static int moxa_carrier_raised(struct tty_port *);
f176178ba   Alan Cox   tty: moxa: Use mo...
195
  static void moxa_dtr_rts(struct tty_port *, int);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
  /*
   * moxa board interface functions:
   */
b4173f457   Jiri Slaby   Char: moxa, remov...
199
200
201
202
203
204
205
  static void MoxaPortEnable(struct moxa_port *);
  static void MoxaPortDisable(struct moxa_port *);
  static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t);
  static int MoxaPortGetLineOut(struct moxa_port *, int *, int *);
  static void MoxaPortLineCtrl(struct moxa_port *, int, int);
  static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
  static int MoxaPortLineStatus(struct moxa_port *);
b4173f457   Jiri Slaby   Char: moxa, remov...
206
  static void MoxaPortFlushData(struct moxa_port *, int);
d450b5a01   Alan Cox   tty: kref usage f...
207
  static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
208
  static int MoxaPortReadData(struct moxa_port *);
b4173f457   Jiri Slaby   Char: moxa, remov...
209
210
211
212
213
  static int MoxaPortTxQueue(struct moxa_port *);
  static int MoxaPortRxQueue(struct moxa_port *);
  static int MoxaPortTxFree(struct moxa_port *);
  static void MoxaPortTxDisable(struct moxa_port *);
  static void MoxaPortTxEnable(struct moxa_port *);
1c729ab15   Al Viro   moxa: switch to -...
214
215
  static int moxa_get_serial_info(struct tty_struct *, struct serial_struct *);
  static int moxa_set_serial_info(struct tty_struct *, struct serial_struct *);
b4173f457   Jiri Slaby   Char: moxa, remov...
216
  static void MoxaSetFifo(struct moxa_port *port, int enable);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217

74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
218
219
220
  /*
   * I/O functions
   */
a808ac0c4   Alan Cox   tty: moxa: Lockin...
221
  static DEFINE_SPINLOCK(moxafunc_lock);
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
222
223
224
225
226
227
228
  static void moxa_wait_finish(void __iomem *ofsAddr)
  {
  	unsigned long end = jiffies + moxaFuncTout;
  
  	while (readw(ofsAddr + FuncCode) != 0)
  		if (time_after(jiffies, end))
  			return;
5a3c6b251   Manuel Zerpies   drivers/tty: use ...
229
230
231
  	if (readw(ofsAddr + FuncCode) != 0)
  		printk_ratelimited(KERN_WARNING "moxa function expired
  ");
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
232
  }
eaa95a8da   Jiri Slaby   Char: moxa, littl...
233
  static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
234
  {
f5c5a36d2   Alan Cox   tty: moxa: rework...
235
236
          unsigned long flags;
          spin_lock_irqsave(&moxafunc_lock, flags);
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
237
238
239
  	writew(arg, ofsAddr + FuncArg);
  	writew(cmd, ofsAddr + FuncCode);
  	moxa_wait_finish(ofsAddr);
f5c5a36d2   Alan Cox   tty: moxa: rework...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  	spin_unlock_irqrestore(&moxafunc_lock, flags);
  }
  
  static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg)
  {
          unsigned long flags;
          u16 ret;
          spin_lock_irqsave(&moxafunc_lock, flags);
  	writew(arg, ofsAddr + FuncArg);
  	writew(cmd, ofsAddr + FuncCode);
  	moxa_wait_finish(ofsAddr);
  	ret = readw(ofsAddr + FuncArg);
  	spin_unlock_irqrestore(&moxafunc_lock, flags);
  	return ret;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
254
  }
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
255
256
257
258
259
260
261
262
263
264
265
266
267
  static void moxa_low_water_check(void __iomem *ofsAddr)
  {
  	u16 rptr, wptr, mask, len;
  
  	if (readb(ofsAddr + FlagStat) & Xoff_state) {
  		rptr = readw(ofsAddr + RXrptr);
  		wptr = readw(ofsAddr + RXwptr);
  		mask = readw(ofsAddr + RX_mask);
  		len = (wptr - rptr) & mask;
  		if (len <= Low_water)
  			moxafunc(ofsAddr, FC_SendXon, 0);
  	}
  }
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
268
269
270
  /*
   * TTY operations
   */
6caa76b77   Alan Cox   tty: now phase ou...
271
  static int moxa_ioctl(struct tty_struct *tty,
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
272
273
274
275
  		      unsigned int cmd, unsigned long arg)
  {
  	struct moxa_port *ch = tty->driver_data;
  	void __user *argp = (void __user *)arg;
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
276
  	int status, ret = 0;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
277
278
279
280
281
282
283
284
285
286
287
  
  	if (tty->index == MAX_PORTS) {
  		if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE &&
  				cmd != MOXA_GETMSTATUS)
  			return -EINVAL;
  	} else if (!ch)
  		return -ENODEV;
  
  	switch (cmd) {
  	case MOXA_GETDATACOUNT:
  		moxaLog.tick = jiffies;
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
288
289
290
  		if (copy_to_user(argp, &moxaLog, sizeof(moxaLog)))
  			ret = -EFAULT;
  		break;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
291
292
  	case MOXA_FLUSH_QUEUE:
  		MoxaPortFlushData(ch, arg);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
293
  		break;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
294
295
296
297
298
299
300
301
302
303
  	case MOXA_GET_IOQUEUE: {
  		struct moxaq_str __user *argm = argp;
  		struct moxaq_str tmp;
  		struct moxa_port *p;
  		unsigned int i, j;
  
  		for (i = 0; i < MAX_BOARDS; i++) {
  			p = moxa_boards[i].ports;
  			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
  				memset(&tmp, 0, sizeof(tmp));
e8c62103f   Alan Cox   tty: moxa: split ...
304
  				spin_lock_bh(&moxa_lock);
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
305
306
307
308
  				if (moxa_boards[i].ready) {
  					tmp.inq = MoxaPortRxQueue(p);
  					tmp.outq = MoxaPortTxQueue(p);
  				}
e8c62103f   Alan Cox   tty: moxa: split ...
309
310
  				spin_unlock_bh(&moxa_lock);
  				if (copy_to_user(argm, &tmp, sizeof(tmp)))
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
311
312
313
  					return -EFAULT;
  			}
  		}
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
314
  		break;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
315
316
  	} case MOXA_GET_OQUEUE:
  		status = MoxaPortTxQueue(ch);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
317
318
  		ret = put_user(status, (unsigned long __user *)argp);
  		break;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
319
320
  	case MOXA_GET_IQUEUE:
  		status = MoxaPortRxQueue(ch);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
321
322
  		ret = put_user(status, (unsigned long __user *)argp);
  		break;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
323
324
325
326
327
328
329
330
331
  	case MOXA_GETMSTATUS: {
  		struct mxser_mstatus __user *argm = argp;
  		struct mxser_mstatus tmp;
  		struct moxa_port *p;
  		unsigned int i, j;
  
  		for (i = 0; i < MAX_BOARDS; i++) {
  			p = moxa_boards[i].ports;
  			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
d450b5a01   Alan Cox   tty: kref usage f...
332
  				struct tty_struct *ttyp;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
333
  				memset(&tmp, 0, sizeof(tmp));
e8c62103f   Alan Cox   tty: moxa: split ...
334
335
336
  				spin_lock_bh(&moxa_lock);
  				if (!moxa_boards[i].ready) {
  				        spin_unlock_bh(&moxa_lock);
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
337
  					goto copy;
e8c62103f   Alan Cox   tty: moxa: split ...
338
                                  }
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
339
340
  
  				status = MoxaPortLineStatus(p);
e8c62103f   Alan Cox   tty: moxa: split ...
341
  				spin_unlock_bh(&moxa_lock);
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
342
343
344
345
346
347
  				if (status & 1)
  					tmp.cts = 1;
  				if (status & 2)
  					tmp.dsr = 1;
  				if (status & 4)
  					tmp.dcd = 1;
d450b5a01   Alan Cox   tty: kref usage f...
348
  				ttyp = tty_port_tty_get(&p->port);
adc8d746c   Alan Cox   tty: move the ter...
349
  				if (!ttyp)
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
350
351
  					tmp.cflag = p->cflag;
  				else
adc8d746c   Alan Cox   tty: move the ter...
352
  					tmp.cflag = ttyp->termios.c_cflag;
df43daaae   Julia Lawall   drivers/tty/moxa....
353
  				tty_kref_put(ttyp);
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
354
  copy:
e8c62103f   Alan Cox   tty: moxa: split ...
355
  				if (copy_to_user(argm, &tmp, sizeof(tmp)))
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
356
357
358
  					return -EFAULT;
  			}
  		}
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
359
  		break;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
360
  	}
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
361
362
  	default:
  		ret = -ENOIOCTLCMD;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
363
  	}
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
364
  	return ret;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
365
  }
9e98966c7   Alan Cox   tty: rework break...
366
  static int moxa_break_ctl(struct tty_struct *tty, int state)
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
367
368
369
370
371
  {
  	struct moxa_port *port = tty->driver_data;
  
  	moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
  			Magic_code);
9e98966c7   Alan Cox   tty: rework break...
372
  	return 0;
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
373
  }
b68e31d0e   Jeff Dike   [PATCH] const str...
374
  static const struct tty_operations moxa_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
380
  	.open = moxa_open,
  	.close = moxa_close,
  	.write = moxa_write,
  	.write_room = moxa_write_room,
  	.flush_buffer = moxa_flush_buffer,
  	.chars_in_buffer = moxa_chars_in_buffer,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  	.ioctl = moxa_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
385
  	.set_termios = moxa_set_termios,
  	.stop = moxa_stop,
  	.start = moxa_start,
  	.hangup = moxa_hangup,
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
386
  	.break_ctl = moxa_break_ctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
  	.tiocmget = moxa_tiocmget,
  	.tiocmset = moxa_tiocmset,
1c729ab15   Al Viro   moxa: switch to -...
389
390
  	.set_serial = moxa_set_serial_info,
  	.get_serial = moxa_get_serial_info,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  };
31f35939d   Alan Cox   tty_port: Add a p...
392
393
  static const struct tty_port_operations moxa_port_ops = {
  	.carrier_raised = moxa_carrier_raised,
f176178ba   Alan Cox   tty: moxa: Use mo...
394
395
  	.dtr_rts = moxa_dtr_rts,
  	.shutdown = moxa_shutdown,
31f35939d   Alan Cox   tty_port: Add a p...
396
  };
aa7e5221f   Jiri Slaby   [PATCH] Char: mox...
397
  static struct tty_driver *moxaDriver;
1d27e3e22   Kees Cook   timer: Remove exp...
398
  static DEFINE_TIMER(moxaTimer, moxa_poll);
33f0f88f1   Alan Cox   [PATCH] TTY layer...
399

74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
400
401
402
  /*
   * HW init
   */
037182346   Jiri Slaby   Char: moxa, add f...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model)
  {
  	switch (brd->boardType) {
  	case MOXA_BOARD_C218_ISA:
  	case MOXA_BOARD_C218_PCI:
  		if (model != 1)
  			goto err;
  		break;
  	case MOXA_BOARD_CP204J:
  		if (model != 3)
  			goto err;
  		break;
  	default:
  		if (model != 2)
  			goto err;
  		break;
  	}
  	return 0;
  err:
  	return -EINVAL;
  }
  
  static int moxa_check_fw(const void *ptr)
  {
  	const __le16 *lptr = ptr;
  
  	if (*lptr != cpu_to_le16(0x7980))
  		return -EINVAL;
  
  	return 0;
  }
  
  static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf,
  		size_t len)
  {
  	void __iomem *baseAddr = brd->basemem;
  	u16 tmp;
  
  	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
  	msleep(10);
  	memset_io(baseAddr, 0, 4096);
  	memcpy_toio(baseAddr, buf, len);	/* download BIOS */
  	writeb(0, baseAddr + Control_reg);	/* restart */
  
  	msleep(2000);
  
  	switch (brd->boardType) {
  	case MOXA_BOARD_C218_ISA:
  	case MOXA_BOARD_C218_PCI:
  		tmp = readw(baseAddr + C218_key);
  		if (tmp != C218_KeyCode)
  			goto err;
  		break;
  	case MOXA_BOARD_CP204J:
  		tmp = readw(baseAddr + C218_key);
  		if (tmp != CP204J_KeyCode)
  			goto err;
  		break;
  	default:
  		tmp = readw(baseAddr + C320_key);
  		if (tmp != C320_KeyCode)
  			goto err;
  		tmp = readw(baseAddr + C320_status);
  		if (tmp != STS_init) {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
467
  			printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic "
037182346   Jiri Slaby   Char: moxa, add f...
468
469
470
471
472
473
474
475
476
  					"module not found
  ");
  			return -EIO;
  		}
  		break;
  	}
  
  	return 0;
  err:
eaa95a8da   Jiri Slaby   Char: moxa, littl...
477
478
  	printk(KERN_ERR "MOXA: bios upload failed -- board not found
  ");
037182346   Jiri Slaby   Char: moxa, add f...
479
480
481
482
483
484
485
486
487
  	return -EIO;
  }
  
  static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr,
  		size_t len)
  {
  	void __iomem *baseAddr = brd->basemem;
  
  	if (len < 7168) {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
488
489
  		printk(KERN_ERR "MOXA: invalid 320 bios -- too short
  ");
037182346   Jiri Slaby   Char: moxa, add f...
490
491
492
493
494
495
496
497
498
499
500
  		return -EINVAL;
  	}
  
  	writew(len - 7168 - 2, baseAddr + C320bapi_len);
  	writeb(1, baseAddr + Control_reg);	/* Select Page 1 */
  	memcpy_toio(baseAddr + DynPage_addr, ptr, 7168);
  	writeb(2, baseAddr + Control_reg);	/* Select Page 2 */
  	memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168);
  
  	return 0;
  }
5292bcd38   Jiri Slaby   Char: moxa, merge...
501
  static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
037182346   Jiri Slaby   Char: moxa, add f...
502
503
504
  		size_t len)
  {
  	void __iomem *baseAddr = brd->basemem;
b46f69cd2   Harvey Harrison   char: moxa.c spar...
505
  	const __le16 *uptr = ptr;
037182346   Jiri Slaby   Char: moxa, add f...
506
  	size_t wlen, len2, j;
5292bcd38   Jiri Slaby   Char: moxa, merge...
507
  	unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
08d01c792   Jiri Slaby   Char: moxa, intro...
508
  	unsigned int i, retry;
037182346   Jiri Slaby   Char: moxa, add f...
509
  	u16 usum, keycode;
5292bcd38   Jiri Slaby   Char: moxa, merge...
510
511
  	keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode :
  				C218_KeyCode;
037182346   Jiri Slaby   Char: moxa, add f...
512

5292bcd38   Jiri Slaby   Char: moxa, merge...
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
  	switch (brd->boardType) {
  	case MOXA_BOARD_CP204J:
  	case MOXA_BOARD_C218_ISA:
  	case MOXA_BOARD_C218_PCI:
  		key = C218_key;
  		loadbuf = C218_LoadBuf;
  		loadlen = C218DLoad_len;
  		checksum = C218check_sum;
  		checksum_ok = C218chksum_ok;
  		break;
  	default:
  		key = C320_key;
  		keycode = C320_KeyCode;
  		loadbuf = C320_LoadBuf;
  		loadlen = C320DLoad_len;
  		checksum = C320check_sum;
  		checksum_ok = C320chksum_ok;
  		break;
037182346   Jiri Slaby   Char: moxa, add f...
531
  	}
037182346   Jiri Slaby   Char: moxa, add f...
532
533
534
535
536
537
538
539
540
541
542
543
  
  	usum = 0;
  	wlen = len >> 1;
  	for (i = 0; i < wlen; i++)
  		usum += le16_to_cpu(uptr[i]);
  	retry = 0;
  	do {
  		wlen = len >> 1;
  		j = 0;
  		while (wlen) {
  			len2 = (wlen > 2048) ? 2048 : wlen;
  			wlen -= len2;
5292bcd38   Jiri Slaby   Char: moxa, merge...
544
  			memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1);
037182346   Jiri Slaby   Char: moxa, add f...
545
  			j += len2 << 1;
5292bcd38   Jiri Slaby   Char: moxa, merge...
546
547
548
549
550
  
  			writew(len2, baseAddr + loadlen);
  			writew(0, baseAddr + key);
  			for (i = 0; i < 100; i++) {
  				if (readw(baseAddr + key) == keycode)
037182346   Jiri Slaby   Char: moxa, add f...
551
552
553
  					break;
  				msleep(10);
  			}
5292bcd38   Jiri Slaby   Char: moxa, merge...
554
  			if (readw(baseAddr + key) != keycode)
037182346   Jiri Slaby   Char: moxa, add f...
555
556
  				return -EIO;
  		}
5292bcd38   Jiri Slaby   Char: moxa, merge...
557
558
559
560
561
  		writew(0, baseAddr + loadlen);
  		writew(usum, baseAddr + checksum);
  		writew(0, baseAddr + key);
  		for (i = 0; i < 100; i++) {
  			if (readw(baseAddr + key) == keycode)
037182346   Jiri Slaby   Char: moxa, add f...
562
563
564
565
  				break;
  			msleep(10);
  		}
  		retry++;
5292bcd38   Jiri Slaby   Char: moxa, merge...
566
567
  	} while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3));
  	if (readb(baseAddr + checksum_ok) != 1)
037182346   Jiri Slaby   Char: moxa, add f...
568
  		return -EIO;
5292bcd38   Jiri Slaby   Char: moxa, merge...
569
  	writew(0, baseAddr + key);
037182346   Jiri Slaby   Char: moxa, add f...
570
571
572
573
574
575
576
  	for (i = 0; i < 600; i++) {
  		if (readw(baseAddr + Magic_no) == Magic_code)
  			break;
  		msleep(10);
  	}
  	if (readw(baseAddr + Magic_no) != Magic_code)
  		return -EIO;
08d01c792   Jiri Slaby   Char: moxa, intro...
577
  	if (MOXA_IS_320(brd)) {
5292bcd38   Jiri Slaby   Char: moxa, merge...
578
579
580
581
582
583
584
585
586
  		if (brd->busType == MOXA_BUS_TYPE_PCI) {	/* ASIC board */
  			writew(0x3800, baseAddr + TMS320_PORT1);
  			writew(0x3900, baseAddr + TMS320_PORT2);
  			writew(28499, baseAddr + TMS320_CLOCK);
  		} else {
  			writew(0x3200, baseAddr + TMS320_PORT1);
  			writew(0x3400, baseAddr + TMS320_PORT2);
  			writew(19999, baseAddr + TMS320_CLOCK);
  		}
037182346   Jiri Slaby   Char: moxa, add f...
587
588
589
590
591
592
593
594
595
596
  	}
  	writew(1, baseAddr + Disable_IRQ);
  	writew(0, baseAddr + Magic_no);
  	for (i = 0; i < 500; i++) {
  		if (readw(baseAddr + Magic_no) == Magic_code)
  			break;
  		msleep(10);
  	}
  	if (readw(baseAddr + Magic_no) != Magic_code)
  		return -EIO;
08d01c792   Jiri Slaby   Char: moxa, intro...
597
  	if (MOXA_IS_320(brd)) {
5292bcd38   Jiri Slaby   Char: moxa, merge...
598
599
600
601
602
603
604
605
606
607
608
609
610
  		j = readw(baseAddr + Module_cnt);
  		if (j <= 0)
  			return -EIO;
  		brd->numPorts = j * 8;
  		writew(j, baseAddr + Module_no);
  		writew(0, baseAddr + Magic_no);
  		for (i = 0; i < 600; i++) {
  			if (readw(baseAddr + Magic_no) == Magic_code)
  				break;
  			msleep(10);
  		}
  		if (readw(baseAddr + Magic_no) != Magic_code)
  			return -EIO;
037182346   Jiri Slaby   Char: moxa, add f...
611
  	}
037182346   Jiri Slaby   Char: moxa, add f...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
  	brd->intNdx = baseAddr + IRQindex;
  	brd->intPend = baseAddr + IRQpending;
  	brd->intTable = baseAddr + IRQtable;
  
  	return 0;
  }
  
  static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
  		size_t len)
  {
  	void __iomem *ofsAddr, *baseAddr = brd->basemem;
  	struct moxa_port *port;
  	int retval, i;
  
  	if (len % 2) {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
627
628
  		printk(KERN_ERR "MOXA: bios length is not even
  ");
037182346   Jiri Slaby   Char: moxa, add f...
629
630
  		return -EINVAL;
  	}
5292bcd38   Jiri Slaby   Char: moxa, merge...
631
632
633
  	retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */
  	if (retval)
  		return retval;
037182346   Jiri Slaby   Char: moxa, add f...
634
635
636
637
  	switch (brd->boardType) {
  	case MOXA_BOARD_C218_ISA:
  	case MOXA_BOARD_C218_PCI:
  	case MOXA_BOARD_CP204J:
037182346   Jiri Slaby   Char: moxa, add f...
638
639
  		port = brd->ports;
  		for (i = 0; i < brd->numPorts; i++, port++) {
b4173f457   Jiri Slaby   Char: moxa, remov...
640
  			port->board = brd;
037182346   Jiri Slaby   Char: moxa, add f...
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  			port->DCDState = 0;
  			port->tableAddr = baseAddr + Extern_table +
  					Extern_size * i;
  			ofsAddr = port->tableAddr;
  			writew(C218rx_mask, ofsAddr + RX_mask);
  			writew(C218tx_mask, ofsAddr + TX_mask);
  			writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
  			writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
  
  			writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
  			writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
  
  		}
  		break;
  	default:
037182346   Jiri Slaby   Char: moxa, add f...
656
657
  		port = brd->ports;
  		for (i = 0; i < brd->numPorts; i++, port++) {
b4173f457   Jiri Slaby   Char: moxa, remov...
658
  			port->board = brd;
037182346   Jiri Slaby   Char: moxa, add f...
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
  			port->DCDState = 0;
  			port->tableAddr = baseAddr + Extern_table +
  					Extern_size * i;
  			ofsAddr = port->tableAddr;
  			switch (brd->numPorts) {
  			case 8:
  				writew(C320p8rx_mask, ofsAddr + RX_mask);
  				writew(C320p8tx_mask, ofsAddr + TX_mask);
  				writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
  				writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
  				writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
  				writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
  
  				break;
  			case 16:
  				writew(C320p16rx_mask, ofsAddr + RX_mask);
  				writew(C320p16tx_mask, ofsAddr + TX_mask);
  				writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
  				writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
  				writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
  				writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
  				break;
  
  			case 24:
  				writew(C320p24rx_mask, ofsAddr + RX_mask);
  				writew(C320p24tx_mask, ofsAddr + TX_mask);
  				writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
  				writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
  				writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
  				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
  				break;
  			case 32:
  				writew(C320p32rx_mask, ofsAddr + RX_mask);
  				writew(C320p32tx_mask, ofsAddr + TX_mask);
  				writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
  				writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
  				writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
  				writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
  				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
  				break;
  			}
  		}
  		break;
  	}
037182346   Jiri Slaby   Char: moxa, add f...
703
704
705
706
707
  	return 0;
  }
  
  static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw)
  {
2bca76e89   David Howells   Fix a const assig...
708
  	const void *ptr = fw->data;
037182346   Jiri Slaby   Char: moxa, add f...
709
710
711
712
713
714
715
716
717
718
719
720
  	char rsn[64];
  	u16 lens[5];
  	size_t len;
  	unsigned int a, lenp, lencnt;
  	int ret = -EINVAL;
  	struct {
  		__le32 magic;	/* 0x34303430 */
  		u8 reserved1[2];
  		u8 type;	/* UNIX = 3 */
  		u8 model;	/* C218T=1, C320T=2, CP204=3 */
  		u8 reserved2[8];
  		__le16 len[5];
2bca76e89   David Howells   Fix a const assig...
721
  	} const *hdr = ptr;
037182346   Jiri Slaby   Char: moxa, add f...
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
  
  	BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens));
  
  	if (fw->size < MOXA_FW_HDRLEN) {
  		strcpy(rsn, "too short (even header won't fit)");
  		goto err;
  	}
  	if (hdr->magic != cpu_to_le32(0x30343034)) {
  		sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic));
  		goto err;
  	}
  	if (hdr->type != 3) {
  		sprintf(rsn, "not for linux, type is %u", hdr->type);
  		goto err;
  	}
  	if (moxa_check_fw_model(brd, hdr->model)) {
  		sprintf(rsn, "not for this card, model is %u", hdr->model);
  		goto err;
  	}
  
  	len = MOXA_FW_HDRLEN;
  	lencnt = hdr->model == 2 ? 5 : 3;
  	for (a = 0; a < ARRAY_SIZE(lens); a++) {
  		lens[a] = le16_to_cpu(hdr->len[a]);
  		if (lens[a] && len + lens[a] <= fw->size &&
  				moxa_check_fw(&fw->data[len]))
eaa95a8da   Jiri Slaby   Char: moxa, littl...
748
  			printk(KERN_WARNING "MOXA firmware: unexpected input "
037182346   Jiri Slaby   Char: moxa, add f...
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  				"at offset %u, but going on
  ", (u32)len);
  		if (!lens[a] && a < lencnt) {
  			sprintf(rsn, "too few entries in fw file");
  			goto err;
  		}
  		len += lens[a];
  	}
  
  	if (len != fw->size) {
  		sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size,
  				(u32)len);
  		goto err;
  	}
  
  	ptr += MOXA_FW_HDRLEN;
  	lenp = 0; /* bios */
  
  	strcpy(rsn, "read above");
  
  	ret = moxa_load_bios(brd, ptr, lens[lenp]);
  	if (ret)
  		goto err;
  
  	/* we skip the tty section (lens[1]), since we don't need it */
  	ptr += lens[lenp] + lens[lenp + 1];
  	lenp += 2; /* comm */
  
  	if (hdr->model == 2) {
  		ret = moxa_load_320b(brd, ptr, lens[lenp]);
  		if (ret)
  			goto err;
  		/* skip another tty */
  		ptr += lens[lenp] + lens[lenp + 1];
  		lenp += 2;
  	}
  
  	ret = moxa_load_code(brd, ptr, lens[lenp]);
  	if (ret)
  		goto err;
  
  	return 0;
  err:
  	printk(KERN_ERR "firmware failed to load, reason: %s
  ", rsn);
  	return ret;
  }
  
  static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
  {
  	const struct firmware *fw;
  	const char *file;
810ab09b2   Jiri Slaby   Char: moxa, centr...
801
  	struct moxa_port *p;
793be8984   Jiri Slaby   TTY: moxa, conver...
802
  	unsigned int i, first_idx;
037182346   Jiri Slaby   Char: moxa, add f...
803
  	int ret;
810ab09b2   Jiri Slaby   Char: moxa, centr...
804
805
806
807
808
809
810
811
812
813
  	brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
  			GFP_KERNEL);
  	if (brd->ports == NULL) {
  		printk(KERN_ERR "cannot allocate memory for ports
  ");
  		ret = -ENOMEM;
  		goto err;
  	}
  
  	for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
44b7d1b37   Alan Cox   tty: add more tty...
814
  		tty_port_init(&p->port);
31f35939d   Alan Cox   tty_port: Add a p...
815
  		p->port.ops = &moxa_port_ops;
810ab09b2   Jiri Slaby   Char: moxa, centr...
816
  		p->type = PORT_16550A;
810ab09b2   Jiri Slaby   Char: moxa, centr...
817
  		p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
810ab09b2   Jiri Slaby   Char: moxa, centr...
818
  	}
037182346   Jiri Slaby   Char: moxa, add f...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
  	switch (brd->boardType) {
  	case MOXA_BOARD_C218_ISA:
  	case MOXA_BOARD_C218_PCI:
  		file = "c218tunx.cod";
  		break;
  	case MOXA_BOARD_CP204J:
  		file = "cp204unx.cod";
  		break;
  	default:
  		file = "c320tunx.cod";
  		break;
  	}
  
  	ret = request_firmware(&fw, file, dev);
  	if (ret) {
ec09cd562   Jiri Slaby   Char: moxa, add f...
834
835
836
837
838
  		printk(KERN_ERR "MOXA: request_firmware failed. Make sure "
  				"you've placed '%s' file into your firmware "
  				"loader directory (e.g. /lib/firmware)
  ",
  				file);
810ab09b2   Jiri Slaby   Char: moxa, centr...
839
  		goto err_free;
037182346   Jiri Slaby   Char: moxa, add f...
840
841
842
843
844
  	}
  
  	ret = moxa_load_fw(brd, fw);
  
  	release_firmware(fw);
810ab09b2   Jiri Slaby   Char: moxa, centr...
845
846
847
  
  	if (ret)
  		goto err_free;
2a5413416   Jiri Slaby   Char: moxa, seria...
848
  	spin_lock_bh(&moxa_lock);
810ab09b2   Jiri Slaby   Char: moxa, centr...
849
  	brd->ready = 1;
0bcc4caad   Jiri Slaby   Char: moxa, timer...
850
851
  	if (!timer_pending(&moxaTimer))
  		mod_timer(&moxaTimer, jiffies + HZ / 50);
2a5413416   Jiri Slaby   Char: moxa, seria...
852
  	spin_unlock_bh(&moxa_lock);
0bcc4caad   Jiri Slaby   Char: moxa, timer...
853

793be8984   Jiri Slaby   TTY: moxa, conver...
854
855
856
857
  	first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD;
  	for (i = 0; i < brd->numPorts; i++)
  		tty_port_register_device(&brd->ports[i].port, moxaDriver,
  				first_idx + i, dev);
810ab09b2   Jiri Slaby   Char: moxa, centr...
858
859
  	return 0;
  err_free:
191c5f102   Jiri Slaby   TTY: call tty_por...
860
861
  	for (i = 0; i < MAX_PORTS_PER_BOARD; i++)
  		tty_port_destroy(&brd->ports[i].port);
810ab09b2   Jiri Slaby   Char: moxa, centr...
862
863
  	kfree(brd->ports);
  err:
037182346   Jiri Slaby   Char: moxa, add f...
864
865
  	return ret;
  }
810ab09b2   Jiri Slaby   Char: moxa, centr...
866
867
  static void moxa_board_deinit(struct moxa_board_conf *brd)
  {
793be8984   Jiri Slaby   TTY: moxa, conver...
868
  	unsigned int a, opened, first_idx;
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
869
870
  
  	mutex_lock(&moxa_openlock);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
871
  	spin_lock_bh(&moxa_lock);
810ab09b2   Jiri Slaby   Char: moxa, centr...
872
  	brd->ready = 0;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
873
  	spin_unlock_bh(&moxa_lock);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
874
875
876
  
  	/* pci hot-un-plug support */
  	for (a = 0; a < brd->numPorts; a++)
d41861ca1   Peter Hurley   tty: Replace ASYN...
877
  		if (tty_port_initialized(&brd->ports[a].port))
aa27a094e   Jiri Slaby   TTY: add tty_port...
878
  			tty_port_tty_hangup(&brd->ports[a].port, false);
191c5f102   Jiri Slaby   TTY: call tty_por...
879
880
  	for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
  		tty_port_destroy(&brd->ports[a].port);
aa27a094e   Jiri Slaby   TTY: add tty_port...
881

a8f5cda06   Jiri Slaby   Char: moxa, rewor...
882
883
884
  	while (1) {
  		opened = 0;
  		for (a = 0; a < brd->numPorts; a++)
d41861ca1   Peter Hurley   tty: Replace ASYN...
885
  			if (tty_port_initialized(&brd->ports[a].port))
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
886
887
888
889
890
891
892
  				opened++;
  		mutex_unlock(&moxa_openlock);
  		if (!opened)
  			break;
  		msleep(50);
  		mutex_lock(&moxa_openlock);
  	}
793be8984   Jiri Slaby   TTY: moxa, conver...
893
894
895
  	first_idx = (brd - moxa_boards) * MAX_PORTS_PER_BOARD;
  	for (a = 0; a < brd->numPorts; a++)
  		tty_unregister_device(moxaDriver, first_idx + a);
810ab09b2   Jiri Slaby   Char: moxa, centr...
896
897
898
899
  	iounmap(brd->basemem);
  	brd->basemem = NULL;
  	kfree(brd->ports);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
  #ifdef CONFIG_PCI
9671f0992   Bill Pemberton   tty: remove use o...
901
  static int moxa_pci_probe(struct pci_dev *pdev,
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
902
  		const struct pci_device_id *ent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
  {
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
904
905
906
907
908
909
  	struct moxa_board_conf *board;
  	unsigned int i;
  	int board_type = ent->driver_data;
  	int retval;
  
  	retval = pci_enable_device(pdev);
7aeb95daf   Jiri Slaby   Char: moxa, clean...
910
911
912
  	if (retval) {
  		dev_err(&pdev->dev, "can't enable pci device
  ");
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
913
  		goto err;
7aeb95daf   Jiri Slaby   Char: moxa, clean...
914
  	}
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
915
916
917
918
919
920
921
  
  	for (i = 0; i < MAX_BOARDS; i++)
  		if (moxa_boards[i].basemem == NULL)
  			break;
  
  	retval = -ENODEV;
  	if (i >= MAX_BOARDS) {
7aeb95daf   Jiri Slaby   Char: moxa, clean...
922
  		dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards "
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
923
924
925
926
927
928
  				"found. Board is ignored.
  ", MAX_BOARDS);
  		goto err;
  	}
  
  	board = &moxa_boards[i];
e46a5e3ff   Jiri Slaby   Char: moxa, pci i...
929
930
931
932
933
934
935
  
  	retval = pci_request_region(pdev, 2, "moxa-base");
  	if (retval) {
  		dev_err(&pdev->dev, "can't request pci region 2
  ");
  		goto err;
  	}
4bdc0d676   Christoph Hellwig   remove ioremap_no...
936
  	board->basemem = ioremap(pci_resource_start(pdev, 2), 0x4000);
7aeb95daf   Jiri Slaby   Char: moxa, clean...
937
938
939
  	if (board->basemem == NULL) {
  		dev_err(&pdev->dev, "can't remap io space 2
  ");
386d95b3a   Julia Lawall   drivers/tty/moxa....
940
  		retval = -ENOMEM;
e46a5e3ff   Jiri Slaby   Char: moxa, pci i...
941
  		goto err_reg;
7aeb95daf   Jiri Slaby   Char: moxa, clean...
942
  	}
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
943

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
  	board->boardType = board_type;
  	switch (board_type) {
  	case MOXA_BOARD_C218_ISA:
  	case MOXA_BOARD_C218_PCI:
  		board->numPorts = 8;
  		break;
  
  	case MOXA_BOARD_CP204J:
  		board->numPorts = 4;
  		break;
  	default:
  		board->numPorts = 0;
  		break;
  	}
  	board->busType = MOXA_BUS_TYPE_PCI;
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
959

037182346   Jiri Slaby   Char: moxa, add f...
960
961
962
  	retval = moxa_init_board(board, &pdev->dev);
  	if (retval)
  		goto err_base;
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
963
  	pci_set_drvdata(pdev, board);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964

bb9f910a1   Jiri Slaby   Char: moxa, notif...
965
966
967
  	dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)
  ",
  			moxa_brdname[board_type - 1], board->numPorts);
eaa95a8da   Jiri Slaby   Char: moxa, littl...
968
  	return 0;
037182346   Jiri Slaby   Char: moxa, add f...
969
970
971
  err_base:
  	iounmap(board->basemem);
  	board->basemem = NULL;
e46a5e3ff   Jiri Slaby   Char: moxa, pci i...
972
973
  err_reg:
  	pci_release_region(pdev, 2);
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
974
975
976
  err:
  	return retval;
  }
ae8d8a146   Bill Pemberton   tty: remove use o...
977
  static void moxa_pci_remove(struct pci_dev *pdev)
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
978
979
  {
  	struct moxa_board_conf *brd = pci_get_drvdata(pdev);
810ab09b2   Jiri Slaby   Char: moxa, centr...
980
  	moxa_board_deinit(brd);
e46a5e3ff   Jiri Slaby   Char: moxa, pci i...
981
  	pci_release_region(pdev, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
  }
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
983
984
985
986
987
  
  static struct pci_driver moxa_pci_driver = {
  	.name = "moxa",
  	.id_table = moxa_pcibrds,
  	.probe = moxa_pci_probe,
91116cba5   Bill Pemberton   tty: remove use o...
988
  	.remove = moxa_pci_remove
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
989
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
992
993
  #endif /* CONFIG_PCI */
  
  static int __init moxa_init(void)
  {
810ab09b2   Jiri Slaby   Char: moxa, centr...
994
  	unsigned int isabrds = 0;
d353eca4e   Jiri Slaby   Char: moxa, clean...
995
  	int retval = 0;
c6fc826e4   Rakib Mullick   tty: moxa: remove...
996
997
  	struct moxa_board_conf *brd = moxa_boards;
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998

7aeb95daf   Jiri Slaby   Char: moxa, clean...
999
1000
1001
  	printk(KERN_INFO "MOXA Intellio family driver version %s
  ",
  			MOXA_VERSION);
793be8984   Jiri Slaby   TTY: moxa, conver...
1002
1003
1004
1005
1006
1007
  
  	tty_port_init(&moxa_service_port);
  
  	moxaDriver = tty_alloc_driver(MAX_PORTS + 1,
  			TTY_DRIVER_REAL_RAW |
  			TTY_DRIVER_DYNAMIC_DEV);
c3a6344ae   Dan Carpenter   TTY: tty_alloc_dr...
1008
1009
  	if (IS_ERR(moxaDriver))
  		return PTR_ERR(moxaDriver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010

9b4e3b13b   Sergey Vlasov   [SERIAL] Fix moxa...
1011
  	moxaDriver->name = "ttyMX";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
1013
1014
1015
1016
  	moxaDriver->major = ttymajor;
  	moxaDriver->minor_start = 0;
  	moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
  	moxaDriver->subtype = SERIAL_TYPE_NORMAL;
  	moxaDriver->init_termios = tty_std_termios;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
  	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
606d099cd   Alan Cox   [PATCH] tty: swit...
1018
1019
  	moxaDriver->init_termios.c_ispeed = 9600;
  	moxaDriver->init_termios.c_ospeed = 9600;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
  	tty_set_operations(moxaDriver, &moxa_ops);
793be8984   Jiri Slaby   TTY: moxa, conver...
1021
1022
  	/* Having one more port only for ioctls is ugly */
  	tty_port_link_device(&moxa_service_port, moxaDriver, MAX_PORTS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
  	if (tty_register_driver(moxaDriver)) {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1025
1026
  		printk(KERN_ERR "can't register MOXA Smartio tty driver!
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
1028
1029
  		put_tty_driver(moxaDriver);
  		return -1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030

d353eca4e   Jiri Slaby   Char: moxa, clean...
1031
  	/* Find the boards defined from module args. */
c6fc826e4   Rakib Mullick   tty: moxa: remove...
1032

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
  	for (i = 0; i < MAX_BOARDS; i++) {
d353eca4e   Jiri Slaby   Char: moxa, clean...
1034
1035
1036
1037
  		if (!baseaddr[i])
  			break;
  		if (type[i] == MOXA_BOARD_C218_ISA ||
  				type[i] == MOXA_BOARD_C320_ISA) {
7aeb95daf   Jiri Slaby   Char: moxa, clean...
1038
1039
  			pr_debug("Moxa board %2d: %s board(baseAddr=%lx)
  ",
d353eca4e   Jiri Slaby   Char: moxa, clean...
1040
1041
1042
1043
1044
1045
  					isabrds + 1, moxa_brdname[type[i] - 1],
  					baseaddr[i]);
  			brd->boardType = type[i];
  			brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
  					numports[i];
  			brd->busType = MOXA_BUS_TYPE_ISA;
4bdc0d676   Christoph Hellwig   remove ioremap_no...
1046
  			brd->basemem = ioremap(baseaddr[i], 0x4000);
d353eca4e   Jiri Slaby   Char: moxa, clean...
1047
  			if (!brd->basemem) {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1048
1049
  				printk(KERN_ERR "MOXA: can't remap %lx
  ",
d353eca4e   Jiri Slaby   Char: moxa, clean...
1050
  						baseaddr[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
1052
  				continue;
  			}
037182346   Jiri Slaby   Char: moxa, add f...
1053
1054
1055
1056
1057
  			if (moxa_init_board(brd, NULL)) {
  				iounmap(brd->basemem);
  				brd->basemem = NULL;
  				continue;
  			}
d353eca4e   Jiri Slaby   Char: moxa, clean...
1058

e0525393b   Hans Wennborg   TTY: fix decimal ...
1059
  			printk(KERN_INFO "MOXA isa board found at 0x%.8lx and "
bb9f910a1   Jiri Slaby   Char: moxa, notif...
1060
1061
1062
  					"ready (%u ports, firmware loaded)
  ",
  					baseaddr[i], brd->numPorts);
d353eca4e   Jiri Slaby   Char: moxa, clean...
1063
1064
  			brd++;
  			isabrds++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
1066
  		}
  	}
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
1067

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
  #ifdef CONFIG_PCI
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
1069
1070
  	retval = pci_register_driver(&moxa_pci_driver);
  	if (retval) {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1071
1072
  		printk(KERN_ERR "Can't register MOXA pci driver!
  ");
d353eca4e   Jiri Slaby   Char: moxa, clean...
1073
  		if (isabrds)
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
1074
  			retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1075
1076
  	}
  #endif
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
1077

a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
1078
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1079
1080
1081
1082
  }
  
  static void __exit moxa_exit(void)
  {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1083
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084

9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
1085
  #ifdef CONFIG_PCI
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
1086
  	pci_unregister_driver(&moxa_pci_driver);
9cde5bf02   Jiri Slaby   [PATCH] Char: mox...
1087
  #endif
a784bf7c1   Jiri Slaby   [PATCH] Char: mox...
1088

810ab09b2   Jiri Slaby   Char: moxa, centr...
1089
1090
1091
  	for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */
  		if (moxa_boards[i].ready)
  			moxa_board_deinit(&moxa_boards[i]);
2a5413416   Jiri Slaby   Char: moxa, seria...
1092
1093
1094
1095
1096
1097
1098
1099
  
  	del_timer_sync(&moxaTimer);
  
  	if (tty_unregister_driver(moxaDriver))
  		printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
  				"serial driver
  ");
  	put_tty_driver(moxaDriver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
1101
1102
1103
  }
  
  module_init(moxa_init);
  module_exit(moxa_exit);
f176178ba   Alan Cox   tty: moxa: Use mo...
1104
  static void moxa_shutdown(struct tty_port *port)
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1105
  {
f176178ba   Alan Cox   tty: moxa: Use mo...
1106
1107
  	struct moxa_port *ch = container_of(port, struct moxa_port, port);
          MoxaPortDisable(ch);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1108
  	MoxaPortFlushData(ch, 2);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1109
  }
31f35939d   Alan Cox   tty_port: Add a p...
1110
1111
1112
1113
  static int moxa_carrier_raised(struct tty_port *port)
  {
  	struct moxa_port *ch = container_of(port, struct moxa_port, port);
  	int dcd;
8482bcd58   Alan Cox   tty: moxa: Fix mo...
1114
  	spin_lock_irq(&port->lock);
31f35939d   Alan Cox   tty_port: Add a p...
1115
  	dcd = ch->DCDState;
8482bcd58   Alan Cox   tty: moxa: Fix mo...
1116
  	spin_unlock_irq(&port->lock);
31f35939d   Alan Cox   tty_port: Add a p...
1117
1118
  	return dcd;
  }
f176178ba   Alan Cox   tty: moxa: Use mo...
1119
  static void moxa_dtr_rts(struct tty_port *port, int onoff)
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1120
  {
f176178ba   Alan Cox   tty: moxa: Use mo...
1121
1122
  	struct moxa_port *ch = container_of(port, struct moxa_port, port);
  	MoxaPortLineCtrl(ch, onoff, onoff);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1123
  }
f176178ba   Alan Cox   tty: moxa: Use mo...
1124

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
1126
  static int moxa_open(struct tty_struct *tty, struct file *filp)
  {
810ab09b2   Jiri Slaby   Char: moxa, centr...
1127
  	struct moxa_board_conf *brd;
8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
1128
  	struct moxa_port *ch;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1129
  	int port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130

11324edd4   Jiri Slaby   [PATCH] Char: mox...
1131
  	port = tty->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
  	if (port == MAX_PORTS) {
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
1133
  		return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
  	}
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1135
1136
  	if (mutex_lock_interruptible(&moxa_openlock))
  		return -ERESTARTSYS;
810ab09b2   Jiri Slaby   Char: moxa, centr...
1137
  	brd = &moxa_boards[port / MAX_PORTS_PER_BOARD];
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1138
1139
  	if (!brd->ready) {
  		mutex_unlock(&moxa_openlock);
810ab09b2   Jiri Slaby   Char: moxa, centr...
1140
  		return -ENODEV;
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1141
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142

f0e852772   Dirk Eibach   moxa: prevent ope...
1143
1144
1145
1146
  	if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) {
  		mutex_unlock(&moxa_openlock);
  		return -ENODEV;
  	}
810ab09b2   Jiri Slaby   Char: moxa, centr...
1147
  	ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
9de6a51fe   Alan Cox   moxa: use tty_port
1148
  	ch->port.count++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
  	tty->driver_data = ch;
d450b5a01   Alan Cox   tty: kref usage f...
1150
  	tty_port_tty_set(&ch->port, tty);
f176178ba   Alan Cox   tty: moxa: Use mo...
1151
  	mutex_lock(&ch->port.mutex);
d41861ca1   Peter Hurley   tty: Replace ASYN...
1152
  	if (!tty_port_initialized(&ch->port)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
  		ch->statusflags = 0;
adc8d746c   Alan Cox   tty: move the ter...
1154
  		moxa_set_tty_param(tty, &tty->termios);
b4173f457   Jiri Slaby   Char: moxa, remov...
1155
1156
  		MoxaPortLineCtrl(ch, 1, 1);
  		MoxaPortEnable(ch);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1157
  		MoxaSetFifo(ch, ch->type == PORT_16550A);
d41861ca1   Peter Hurley   tty: Replace ASYN...
1158
  		tty_port_set_initialized(&ch->port, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
  	}
f176178ba   Alan Cox   tty: moxa: Use mo...
1160
  	mutex_unlock(&ch->port.mutex);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1161
  	mutex_unlock(&moxa_openlock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162

7c31bdb6b   Jiri Slaby   Char: moxa, do no...
1163
  	return tty_port_block_til_ready(&ch->port, tty, filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164
1165
1166
1167
  }
  
  static void moxa_close(struct tty_struct *tty, struct file *filp)
  {
f176178ba   Alan Cox   tty: moxa: Use mo...
1168
  	struct moxa_port *ch = tty->driver_data;
adc8d746c   Alan Cox   tty: move the ter...
1169
  	ch->cflag = tty->termios.c_cflag;
f176178ba   Alan Cox   tty: moxa: Use mo...
1170
  	tty_port_close(&ch->port, tty, filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
1172
1173
1174
1175
  }
  
  static int moxa_write(struct tty_struct *tty,
  		      const unsigned char *buf, int count)
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1176
  	struct moxa_port *ch = tty->driver_data;
0ad7c9af3   Jiri Slaby   Char: moxa, fix l...
1177
  	unsigned long flags;
b4173f457   Jiri Slaby   Char: moxa, remov...
1178
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  	if (ch == NULL)
b4173f457   Jiri Slaby   Char: moxa, remov...
1181
  		return 0;
33f0f88f1   Alan Cox   [PATCH] TTY layer...
1182

0ad7c9af3   Jiri Slaby   Char: moxa, fix l...
1183
  	spin_lock_irqsave(&moxa_lock, flags);
d450b5a01   Alan Cox   tty: kref usage f...
1184
  	len = MoxaPortWriteData(tty, buf, count);
0ad7c9af3   Jiri Slaby   Char: moxa, fix l...
1185
  	spin_unlock_irqrestore(&moxa_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186

a808ac0c4   Alan Cox   tty: moxa: Lockin...
1187
  	set_bit(LOWWAIT, &ch->statusflags);
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1188
  	return len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
1190
1191
1192
  }
  
  static int moxa_write_room(struct tty_struct *tty)
  {
8f8ecbad0   Jiri Slaby   [PATCH] Char: mox...
1193
  	struct moxa_port *ch;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194
1195
  
  	if (tty->stopped)
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1196
  		return 0;
b4173f457   Jiri Slaby   Char: moxa, remov...
1197
  	ch = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
  	if (ch == NULL)
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1199
  		return 0;
b4173f457   Jiri Slaby   Char: moxa, remov...
1200
  	return MoxaPortTxFree(ch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
1202
1203
1204
  }
  
  static void moxa_flush_buffer(struct tty_struct *tty)
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1205
  	struct moxa_port *ch = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
1207
1208
  
  	if (ch == NULL)
  		return;
b4173f457   Jiri Slaby   Char: moxa, remov...
1209
  	MoxaPortFlushData(ch, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
1211
1212
1213
1214
  	tty_wakeup(tty);
  }
  
  static int moxa_chars_in_buffer(struct tty_struct *tty)
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1215
  	struct moxa_port *ch = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1216
  	int chars;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217

b4173f457   Jiri Slaby   Char: moxa, remov...
1218
  	chars = MoxaPortTxQueue(ch);
f710ebd7f   Alan Cox   tty: moxa: Kill t...
1219
  	if (chars)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220
1221
1222
1223
  		/*
  		 * Make it possible to wakeup anything waiting for output
  		 * in tty_ioctl.c, etc.
  		 */
f710ebd7f   Alan Cox   tty: moxa: Kill t...
1224
          	set_bit(EMPTYWAIT, &ch->statusflags);
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1225
  	return chars;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
  }
60b33c133   Alan Cox   tiocmget: kill of...
1227
  static int moxa_tiocmget(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  {
8482bcd58   Alan Cox   tty: moxa: Fix mo...
1229
  	struct moxa_port *ch = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
  	int flag = 0, dtr, rts;
b4173f457   Jiri Slaby   Char: moxa, remov...
1231
  	MoxaPortGetLineOut(ch, &dtr, &rts);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
1233
1234
1235
  	if (dtr)
  		flag |= TIOCM_DTR;
  	if (rts)
  		flag |= TIOCM_RTS;
b4173f457   Jiri Slaby   Char: moxa, remov...
1236
  	dtr = MoxaPortLineStatus(ch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237
1238
1239
1240
1241
1242
1243
1244
  	if (dtr & 1)
  		flag |= TIOCM_CTS;
  	if (dtr & 2)
  		flag |= TIOCM_DSR;
  	if (dtr & 4)
  		flag |= TIOCM_CD;
  	return flag;
  }
20b9d1771   Alan Cox   tiocmset: kill th...
1245
  static int moxa_tiocmset(struct tty_struct *tty,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
1247
  			 unsigned int set, unsigned int clear)
  {
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1248
  	struct moxa_port *ch;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249
  	int dtr, rts;
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1250
1251
1252
1253
  	mutex_lock(&moxa_openlock);
  	ch = tty->driver_data;
  	if (!ch) {
  		mutex_unlock(&moxa_openlock);
74d7d97b9   Jiri Slaby   Char: moxa, ioctl...
1254
  		return -EINVAL;
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1255
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256

b4173f457   Jiri Slaby   Char: moxa, remov...
1257
  	MoxaPortGetLineOut(ch, &dtr, &rts);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258
1259
1260
1261
1262
1263
1264
1265
  	if (set & TIOCM_RTS)
  		rts = 1;
  	if (set & TIOCM_DTR)
  		dtr = 1;
  	if (clear & TIOCM_RTS)
  		rts = 0;
  	if (clear & TIOCM_DTR)
  		dtr = 0;
b4173f457   Jiri Slaby   Char: moxa, remov...
1266
  	MoxaPortLineCtrl(ch, dtr, rts);
a8f5cda06   Jiri Slaby   Char: moxa, rewor...
1267
  	mutex_unlock(&moxa_openlock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1268
1269
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
  static void moxa_set_termios(struct tty_struct *tty,
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1271
  		struct ktermios *old_termios)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
  {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1273
  	struct moxa_port *ch = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
1275
1276
  
  	if (ch == NULL)
  		return;
db1acaa63   Alan Cox   moxa: first pass ...
1277
  	moxa_set_tty_param(tty, old_termios);
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1278
  	if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
9de6a51fe   Alan Cox   moxa: use tty_port
1279
  		wake_up_interruptible(&ch->port.open_wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280
1281
1282
1283
  }
  
  static void moxa_stop(struct tty_struct *tty)
  {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1284
  	struct moxa_port *ch = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285
1286
1287
  
  	if (ch == NULL)
  		return;
b4173f457   Jiri Slaby   Char: moxa, remov...
1288
  	MoxaPortTxDisable(ch);
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1289
  	set_bit(TXSTOPPED, &ch->statusflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
1291
1292
1293
1294
  }
  
  
  static void moxa_start(struct tty_struct *tty)
  {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1295
  	struct moxa_port *ch = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1296
1297
1298
  
  	if (ch == NULL)
  		return;
58112dfbf   Dan Carpenter   tty: moxa: fix bi...
1299
  	if (!test_bit(TXSTOPPED, &ch->statusflags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
  		return;
b4173f457   Jiri Slaby   Char: moxa, remov...
1301
  	MoxaPortTxEnable(ch);
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1302
  	clear_bit(TXSTOPPED, &ch->statusflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
1304
1305
1306
  }
  
  static void moxa_hangup(struct tty_struct *tty)
  {
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1307
  	struct moxa_port *ch = tty->driver_data;
f176178ba   Alan Cox   tty: moxa: Use mo...
1308
  	tty_port_hangup(&ch->port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
  }
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1310
  static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1311
  {
8482bcd58   Alan Cox   tty: moxa: Fix mo...
1312
  	unsigned long flags;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1313
  	dcd = !!dcd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314

8482bcd58   Alan Cox   tty: moxa: Fix mo...
1315
  	spin_lock_irqsave(&p->port.lock, flags);
d450b5a01   Alan Cox   tty: kref usage f...
1316
  	if (dcd != p->DCDState) {
8482bcd58   Alan Cox   tty: moxa: Fix mo...
1317
1318
          	p->DCDState = dcd;
          	spin_unlock_irqrestore(&p->port.lock, flags);
aa27a094e   Jiri Slaby   TTY: add tty_port...
1319
1320
  		if (!dcd)
  			tty_port_tty_hangup(&p->port, true);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1321
  	}
8482bcd58   Alan Cox   tty: moxa: Fix mo...
1322
1323
  	else
  		spin_unlock_irqrestore(&p->port.lock, flags);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1324
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325

7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1326
1327
1328
  static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
  		u16 __iomem *ip)
  {
d450b5a01   Alan Cox   tty: kref usage f...
1329
  	struct tty_struct *tty = tty_port_tty_get(&p->port);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1330
  	void __iomem *ofsAddr;
d41861ca1   Peter Hurley   tty: Replace ASYN...
1331
  	unsigned int inited = tty_port_initialized(&p->port);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1332
1333
1334
  	u16 intr;
  
  	if (tty) {
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1335
  		if (test_bit(EMPTYWAIT, &p->statusflags) &&
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1336
  				MoxaPortTxQueue(p) == 0) {
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1337
  			clear_bit(EMPTYWAIT, &p->statusflags);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1338
1339
  			tty_wakeup(tty);
  		}
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1340
  		if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped &&
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1341
  				MoxaPortTxQueue(p) <= WAKEUP_CHARS) {
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1342
  			clear_bit(LOWWAIT, &p->statusflags);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1343
1344
  			tty_wakeup(tty);
  		}
97ef38b82   Peter Hurley   tty: Replace TTY_...
1345
  		if (inited && !tty_throttled(tty) &&
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1346
1347
  				MoxaPortRxQueue(p) > 0) { /* RX */
  			MoxaPortReadData(p);
6732c8bb8   Jiri Slaby   TTY: switch tty_s...
1348
  			tty_schedule_flip(&p->port);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1349
1350
  		}
  	} else {
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1351
  		clear_bit(EMPTYWAIT, &p->statusflags);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1352
  		MoxaPortFlushData(p, 0); /* flush RX */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
  	}
0bcc4caad   Jiri Slaby   Char: moxa, timer...
1354

7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1355
  	if (!handle) /* nothing else to do */
0e0fd7d73   Jiri Slaby   tty: moxa, fix re...
1356
  		goto put;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1357
1358
1359
  
  	intr = readw(ip); /* port irq status */
  	if (intr == 0)
0e0fd7d73   Jiri Slaby   tty: moxa, fix re...
1360
  		goto put;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1361
1362
1363
1364
1365
1366
1367
1368
  
  	writew(0, ip); /* ACK port */
  	ofsAddr = p->tableAddr;
  	if (intr & IntrTx) /* disable tx intr */
  		writew(readw(ofsAddr + HostStat) & ~WakeupTx,
  				ofsAddr + HostStat);
  
  	if (!inited)
0e0fd7d73   Jiri Slaby   tty: moxa, fix re...
1369
  		goto put;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1370
1371
  
  	if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
92a19f9ce   Jiri Slaby   TTY: switch tty_i...
1372
  		tty_insert_flip_char(&p->port, 0, TTY_BREAK);
6732c8bb8   Jiri Slaby   TTY: switch tty_s...
1373
  		tty_schedule_flip(&p->port);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1374
1375
1376
1377
  	}
  
  	if (intr & IntrLine)
  		moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
0e0fd7d73   Jiri Slaby   tty: moxa, fix re...
1378
1379
  put:
  	tty_kref_put(tty);
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1380
1381
1382
  
  	return 0;
  }
24ed960ab   Kees Cook   treewide: Switch ...
1383
  static void moxa_poll(struct timer_list *unused)
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1384
1385
1386
  {
  	struct moxa_board_conf *brd;
  	u16 __iomem *ip;
2a5413416   Jiri Slaby   Char: moxa, seria...
1387
  	unsigned int card, port, served = 0;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1388
1389
  
  	spin_lock(&moxa_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
  	for (card = 0; card < MAX_BOARDS; card++) {
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1391
1392
  		brd = &moxa_boards[card];
  		if (!brd->ready)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
  			continue;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1394

2a5413416   Jiri Slaby   Char: moxa, seria...
1395
  		served++;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
  		ip = NULL;
  		if (readb(brd->intPend) == 0xff)
  			ip = brd->intTable + readb(brd->intNdx);
  
  		for (port = 0; port < brd->numPorts; port++)
  			moxa_poll_port(&brd->ports[port], !!ip, ip + port);
  
  		if (ip)
  			writeb(0, brd->intPend); /* ACK */
  
  		if (moxaLowWaterChk) {
  			struct moxa_port *p = brd->ports;
  			for (port = 0; port < brd->numPorts; port++, p++)
  				if (p->lowChkFlag) {
  					p->lowChkFlag = 0;
  					moxa_low_water_check(p->tableAddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1413
1414
  		}
  	}
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1415
  	moxaLowWaterChk = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1416

2a5413416   Jiri Slaby   Char: moxa, seria...
1417
1418
1419
  	if (served)
  		mod_timer(&moxaTimer, jiffies + HZ / 50);
  	spin_unlock(&moxa_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
1421
1422
  }
  
  /******************************************************************************/
db1acaa63   Alan Cox   moxa: first pass ...
1423
  static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
  {
adc8d746c   Alan Cox   tty: move the ter...
1425
  	register struct ktermios *ts = &tty->termios;
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1426
  	struct moxa_port *ch = tty->driver_data;
db1acaa63   Alan Cox   moxa: first pass ...
1427
  	int rts, cts, txflow, rxflow, xany, baud;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1428

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429
1430
1431
1432
1433
1434
1435
1436
1437
  	rts = cts = txflow = rxflow = xany = 0;
  	if (ts->c_cflag & CRTSCTS)
  		rts = cts = 1;
  	if (ts->c_iflag & IXON)
  		txflow = 1;
  	if (ts->c_iflag & IXOFF)
  		rxflow = 1;
  	if (ts->c_iflag & IXANY)
  		xany = 1;
db1acaa63   Alan Cox   moxa: first pass ...
1438

b4173f457   Jiri Slaby   Char: moxa, remov...
1439
1440
  	MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);
  	baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));
db1acaa63   Alan Cox   moxa: first pass ...
1441
1442
1443
1444
  	if (baud == -1)
  		baud = tty_termios_baud_rate(old_termios);
  	/* Not put the baud rate into the termios data */
  	tty_encode_baud_rate(tty, baud, baud);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1446
1447
  /*****************************************************************************
   *	Driver level functions: 					     *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
   *****************************************************************************/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449

b4173f457   Jiri Slaby   Char: moxa, remov...
1450
  static void MoxaPortFlushData(struct moxa_port *port, int mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1451
1452
  {
  	void __iomem *ofsAddr;
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1453
  	if (mode < 0 || mode > 2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
  		return;
b4173f457   Jiri Slaby   Char: moxa, remov...
1455
  	ofsAddr = port->tableAddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456
1457
  	moxafunc(ofsAddr, FC_FlushQueue, mode);
  	if (mode != 1) {
b4173f457   Jiri Slaby   Char: moxa, remov...
1458
  		port->lowChkFlag = 0;
6f56b658b   Jiri Slaby   Char: moxa, funct...
1459
  		moxa_low_water_check(ofsAddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
1461
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
  /*
   *    Moxa Port Number Description:
   *
   *      MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
   *      the port number using in MOXA driver functions will be 0 to 31 for
   *      first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
   *      to 127 for fourth. For example, if you setup three MOXA boards,
   *      first board is C218, second board is C320-16 and third board is
   *      C320-32. The port number of first board (C218 - 8 ports) is from
   *      0 to 7. The port number of second board (C320 - 16 ports) is form
   *      32 to 47. The port number of third board (C320 - 32 ports) is from
   *      64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
   *      127 will be invalid.
   *
   *
   *      Moxa Functions Description:
   *
   *      Function 1:     Driver initialization routine, this routine must be
   *                      called when initialized driver.
   *      Syntax:
   *      void MoxaDriverInit();
   *
   *
   *      Function 2:     Moxa driver private IOCTL command processing.
   *      Syntax:
   *      int  MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
   *
   *           unsigned int cmd   : IOCTL command
   *           unsigned long arg  : IOCTL argument
   *           int port           : port number (0 - 127)
   *
   *           return:    0  (OK)
   *                      -EINVAL
   *                      -ENOIOCTLCMD
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
   *      Function 6:     Enable this port to start Tx/Rx data.
   *      Syntax:
   *      void MoxaPortEnable(int port);
   *           int port           : port number (0 - 127)
   *
   *
   *      Function 7:     Disable this port
   *      Syntax:
   *      void MoxaPortDisable(int port);
   *           int port           : port number (0 - 127)
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1510
1511
   *      Function 10:    Setting baud rate of this port.
   *      Syntax:
08d01c792   Jiri Slaby   Char: moxa, intro...
1512
   *      speed_t MoxaPortSetBaud(int port, speed_t baud);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
   *           int port           : port number (0 - 127)
   *           long baud          : baud rate (50 - 115200)
   *
   *           return:    0       : this port is invalid or baud < 50
   *                      50 - 115200 : the real baud rate set to the port, if
   *                                    the argument baud is large than maximun
   *                                    available baud rate, the real setting
   *                                    baud rate will be the maximun baud rate.
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
1524
   *      Function 12:    Configure the port.
   *      Syntax:
606d099cd   Alan Cox   [PATCH] tty: swit...
1525
   *      int  MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
   *           int port           : port number (0 - 127)
606d099cd   Alan Cox   [PATCH] tty: swit...
1527
   *           struct ktermios * termio : termio structure pointer
c7bce3097   Alan Cox   [PATCH] serial: F...
1528
   *	     speed_t baud	: baud rate
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
   *
   *           return:    -1      : this port is invalid or termio == NULL
   *                      0       : setting O.K.
   *
   *
   *      Function 13:    Get the DTR/RTS state of this port.
   *      Syntax:
   *      int  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
   *           int port           : port number (0 - 127)
   *           int * dtrState     : pointer to INT to receive the current DTR
   *                                state. (if NULL, this function will not
   *                                write to this address)
   *           int * rtsState     : pointer to INT to receive the current RTS
   *                                state. (if NULL, this function will not
   *                                write to this address)
   *
   *           return:    -1      : this port is invalid
   *                      0       : O.K.
   *
   *
   *      Function 14:    Setting the DTR/RTS output state of this port.
   *      Syntax:
   *      void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
   *           int port           : port number (0 - 127)
   *           int dtrState       : DTR output state (0: off, 1: on)
   *           int rtsState       : RTS output state (0: off, 1: on)
   *
   *
   *      Function 15:    Setting the flow control of this port.
   *      Syntax:
   *      void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
   *                            int txFlow,int xany);
   *           int port           : port number (0 - 127)
   *           int rtsFlow        : H/W RTS flow control (0: no, 1: yes)
   *           int ctsFlow        : H/W CTS flow control (0: no, 1: yes)
   *           int rxFlow         : S/W Rx XON/XOFF flow control (0: no, 1: yes)
   *           int txFlow         : S/W Tx XON/XOFF flow control (0: no, 1: yes)
   *           int xany           : S/W XANY flow control (0: no, 1: yes)
   *
   *
   *      Function 16:    Get ths line status of this port
   *      Syntax:
   *      int  MoxaPortLineStatus(int port);
   *           int port           : port number (0 - 127)
   *
   *           return:    Bit 0 - CTS state (0: off, 1: on)
   *                      Bit 1 - DSR state (0: off, 1: on)
   *                      Bit 2 - DCD state (0: off, 1: on)
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
   *      Function 19:    Flush the Rx/Tx buffer data of this port.
   *      Syntax:
   *      void MoxaPortFlushData(int port, int mode);
   *           int port           : port number (0 - 127)
   *           int mode    
   *                      0       : flush the Rx buffer 
   *                      1       : flush the Tx buffer 
   *                      2       : flush the Rx and Tx buffer 
   *
   *
   *      Function 20:    Write data.
   *      Syntax:
   *      int  MoxaPortWriteData(int port, unsigned char * buffer, int length);
   *           int port           : port number (0 - 127)
   *           unsigned char * buffer     : pointer to write data buffer.
   *           int length         : write data length
   *
   *           return:    0 - length      : real write data length
   *
   *
   *      Function 21:    Read data.
   *      Syntax:
33f0f88f1   Alan Cox   [PATCH] TTY layer...
1601
   *      int  MoxaPortReadData(int port, struct tty_struct *tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
   *           int port           : port number (0 - 127)
33f0f88f1   Alan Cox   [PATCH] TTY layer...
1603
   *	     struct tty_struct *tty : tty for data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604
1605
1606
1607
   *
   *           return:    0 - length      : real read data length
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
   *      Function 24:    Get the Tx buffer current queued data bytes
   *      Syntax:
   *      int  MoxaPortTxQueue(int port);
   *           int port           : port number (0 - 127)
   *
   *           return:    ..      : Tx buffer current queued data bytes
   *
   *
   *      Function 25:    Get the Tx buffer current free space
   *      Syntax:
   *      int  MoxaPortTxFree(int port);
   *           int port           : port number (0 - 127)
   *
   *           return:    ..      : Tx buffer current free space
   *
   *
   *      Function 26:    Get the Rx buffer current queued data bytes
   *      Syntax:
   *      int  MoxaPortRxQueue(int port);
   *           int port           : port number (0 - 127)
   *
   *           return:    ..      : Rx buffer current queued data bytes
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
   *      Function 28:    Disable port data transmission.
   *      Syntax:
   *      void MoxaPortTxDisable(int port);
   *           int port           : port number (0 - 127)
   *
   *
   *      Function 29:    Enable port data transmission.
   *      Syntax:
   *      void MoxaPortTxEnable(int port);
   *           int port           : port number (0 - 127)
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
1645
1646
1647
1648
1649
1650
1651
   *      Function 31:    Get the received BREAK signal count and reset it.
   *      Syntax:
   *      int  MoxaPortResetBrkCnt(int port);
   *           int port           : port number (0 - 127)
   *
   *           return:    0 - ..  : BREAK signal count
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1652
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653

b4173f457   Jiri Slaby   Char: moxa, remov...
1654
  static void MoxaPortEnable(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1655
1656
  {
  	void __iomem *ofsAddr;
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1657
  	u16 lowwater = 512;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658

b4173f457   Jiri Slaby   Char: moxa, remov...
1659
  	ofsAddr = port->tableAddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1660
  	writew(lowwater, ofsAddr + Low_water);
08d01c792   Jiri Slaby   Char: moxa, intro...
1661
  	if (MOXA_IS_320(port->board))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1662
  		moxafunc(ofsAddr, FC_SetBreakIrq, 0);
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1663
1664
1665
  	else
  		writew(readw(ofsAddr + HostStat) | WakeupBreak,
  				ofsAddr + HostStat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1666
1667
1668
1669
1670
1671
1672
  
  	moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
  	moxafunc(ofsAddr, FC_FlushQueue, 2);
  
  	moxafunc(ofsAddr, FC_EnableCH, Magic_code);
  	MoxaPortLineStatus(port);
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1673
  static void MoxaPortDisable(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1675
  	void __iomem *ofsAddr = port->tableAddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
1677
1678
1679
1680
1681
  
  	moxafunc(ofsAddr, FC_SetFlowCtl, 0);	/* disable flow control */
  	moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
  	writew(0, ofsAddr + HostStat);
  	moxafunc(ofsAddr, FC_DisableCH, Magic_code);
  }
08d01c792   Jiri Slaby   Char: moxa, intro...
1682
  static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683
  {
08d01c792   Jiri Slaby   Char: moxa, intro...
1684
1685
1686
  	void __iomem *ofsAddr = port->tableAddr;
  	unsigned int clock, val;
  	speed_t max;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1687

08d01c792   Jiri Slaby   Char: moxa, intro...
1688
1689
  	max = MOXA_IS_320(port->board) ? 460800 : 921600;
  	if (baud < 50)
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1690
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1691
1692
  	if (baud > max)
  		baud = max;
08d01c792   Jiri Slaby   Char: moxa, intro...
1693
  	clock = 921600;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1694
1695
1696
  	val = clock / baud;
  	moxafunc(ofsAddr, FC_SetBaud, val);
  	baud = clock / val;
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1697
  	return baud;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1698
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1699
1700
  static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
  		speed_t baud)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701
1702
  {
  	void __iomem *ofsAddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
  	tcflag_t mode = 0;
b4173f457   Jiri Slaby   Char: moxa, remov...
1704
  	ofsAddr = port->tableAddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
  
  	mode = termio->c_cflag & CSIZE;
  	if (mode == CS5)
  		mode = MX_CS5;
  	else if (mode == CS6)
  		mode = MX_CS6;
  	else if (mode == CS7)
  		mode = MX_CS7;
  	else if (mode == CS8)
  		mode = MX_CS8;
  
  	if (termio->c_cflag & CSTOPB) {
  		if (mode == MX_CS5)
  			mode |= MX_STOP15;
  		else
  			mode |= MX_STOP2;
  	} else
  		mode |= MX_STOP1;
  
  	if (termio->c_cflag & PARENB) {
d8dcbdd08   Lars Kanis   tty: moxa: Add su...
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
  		if (termio->c_cflag & PARODD) {
  			if (termio->c_cflag & CMSPAR)
  				mode |= MX_PARMARK;
  			else
  				mode |= MX_PARODD;
  		} else {
  			if (termio->c_cflag & CMSPAR)
  				mode |= MX_PARSPACE;
  			else
  				mode |= MX_PAREVEN;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
1737
  	} else
  		mode |= MX_PARNONE;
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1738
  	moxafunc(ofsAddr, FC_SetDataMode, (u16)mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1739

08d01c792   Jiri Slaby   Char: moxa, intro...
1740
1741
  	if (MOXA_IS_320(port->board) && baud >= 921600)
  		return -1;
db1acaa63   Alan Cox   moxa: first pass ...
1742
  	baud = MoxaPortSetBaud(port, baud);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1743
1744
  
  	if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
f5c5a36d2   Alan Cox   tty: moxa: rework...
1745
  	        spin_lock_irq(&moxafunc_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1746
1747
1748
  		writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
  		writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
  		writeb(FC_SetXonXoff, ofsAddr + FuncCode);
6f56b658b   Jiri Slaby   Char: moxa, funct...
1749
  		moxa_wait_finish(ofsAddr);
a808ac0c4   Alan Cox   tty: moxa: Lockin...
1750
  		spin_unlock_irq(&moxafunc_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
1752
  
  	}
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1753
  	return baud;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1754
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1755
1756
  static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState,
  		int *rtsState)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1757
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1758
1759
1760
1761
  	if (dtrState)
  		*dtrState = !!(port->lineCtrl & DTR_ON);
  	if (rtsState)
  		*rtsState = !!(port->lineCtrl & RTS_ON);
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1762
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1764
  static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1765
  {
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1766
  	u8 mode = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1767

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1768
1769
1770
1771
  	if (dtr)
  		mode |= DTR_ON;
  	if (rts)
  		mode |= RTS_ON;
b4173f457   Jiri Slaby   Char: moxa, remov...
1772
1773
  	port->lineCtrl = mode;
  	moxafunc(port->tableAddr, FC_LineControl, mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1774
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1775
1776
  static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts,
  		int txflow, int rxflow, int txany)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1777
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1778
  	int mode = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1779

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
  	if (rts)
  		mode |= RTS_FlowCtl;
  	if (cts)
  		mode |= CTS_FlowCtl;
  	if (txflow)
  		mode |= Tx_FlowCtl;
  	if (rxflow)
  		mode |= Rx_FlowCtl;
  	if (txany)
  		mode |= IXM_IXANY;
b4173f457   Jiri Slaby   Char: moxa, remov...
1790
  	moxafunc(port->tableAddr, FC_SetFlowCtl, mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1792
  static int MoxaPortLineStatus(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1793
1794
1795
  {
  	void __iomem *ofsAddr;
  	int val;
b4173f457   Jiri Slaby   Char: moxa, remov...
1796
  	ofsAddr = port->tableAddr;
f5c5a36d2   Alan Cox   tty: moxa: rework...
1797
1798
1799
  	if (MOXA_IS_320(port->board))
  		val = moxafuncret(ofsAddr, FC_LineStatus, 0);
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800
  		val = readw(ofsAddr + FlagStat) >> 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
  	val &= 0x0B;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1802
  	if (val & 8)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803
  		val |= 4;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1804
  	moxa_new_dcdstate(port, val & 8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805
  	val &= 7;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1806
  	return val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1807
  }
d450b5a01   Alan Cox   tty: kref usage f...
1808
  static int MoxaPortWriteData(struct tty_struct *tty,
2108eba5c   Jiri Slaby   Char: moxa, clean...
1809
  		const unsigned char *buffer, int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1810
  {
d450b5a01   Alan Cox   tty: kref usage f...
1811
  	struct moxa_port *port = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1812
  	void __iomem *baseAddr, *ofsAddr, *ofs;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1813
1814
1815
  	unsigned int c, total;
  	u16 head, tail, tx_mask, spage, epage;
  	u16 pageno, pageofs, bufhead;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1816

b4173f457   Jiri Slaby   Char: moxa, remov...
1817
1818
  	ofsAddr = port->tableAddr;
  	baseAddr = port->board->basemem;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1819
1820
1821
1822
1823
  	tx_mask = readw(ofsAddr + TX_mask);
  	spage = readw(ofsAddr + Page_txb);
  	epage = readw(ofsAddr + EndPage_txb);
  	tail = readw(ofsAddr + TXwptr);
  	head = readw(ofsAddr + TXrptr);
2108eba5c   Jiri Slaby   Char: moxa, clean...
1824
  	c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825
1826
  	if (c > len)
  		c = len;
9de6a51fe   Alan Cox   moxa: use tty_port
1827
  	moxaLog.txcnt[port->port.tty->index] += c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
  	total = c;
  	if (spage == epage) {
  		bufhead = readw(ofsAddr + Ofs_txb);
  		writew(spage, baseAddr + Control_reg);
  		while (c > 0) {
  			if (head > tail)
  				len = head - tail - 1;
  			else
  				len = tx_mask + 1 - tail;
  			len = (c > len) ? len : c;
  			ofs = baseAddr + DynPage_addr + bufhead + tail;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1839
1840
  			memcpy_toio(ofs, buffer, len);
  			buffer += len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841
1842
1843
  			tail = (tail + len) & tx_mask;
  			c -= len;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1845
1846
  		pageno = spage + (tail >> 13);
  		pageofs = tail & Page_mask;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1847
1848
1849
1850
  		while (c > 0) {
  			len = Page_size - pageofs;
  			if (len > c)
  				len = c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1851
1852
  			writeb(pageno, baseAddr + Control_reg);
  			ofs = baseAddr + DynPage_addr + pageofs;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1853
1854
  			memcpy_toio(ofs, buffer, len);
  			buffer += len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855
1856
1857
  			if (++pageno == epage)
  				pageno = spage;
  			pageofs = 0;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1858
1859
1860
  			c -= len;
  		}
  		tail = (tail + total) & tx_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1861
  	}
2108eba5c   Jiri Slaby   Char: moxa, clean...
1862
  	writew(tail, ofsAddr + TXwptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1863
  	writeb(1, ofsAddr + CD180TXirq);	/* start to send */
2108eba5c   Jiri Slaby   Char: moxa, clean...
1864
  	return total;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1865
  }
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1866
  static int MoxaPortReadData(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1867
  {
9de6a51fe   Alan Cox   moxa: use tty_port
1868
  	struct tty_struct *tty = port->port.tty;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1869
  	unsigned char *dst;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
  	void __iomem *baseAddr, *ofsAddr, *ofs;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1871
1872
1873
  	unsigned int count, len, total;
  	u16 tail, rx_mask, spage, epage;
  	u16 pageno, pageofs, bufhead, head;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874

b4173f457   Jiri Slaby   Char: moxa, remov...
1875
1876
  	ofsAddr = port->tableAddr;
  	baseAddr = port->board->basemem;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1877
1878
1879
1880
1881
  	head = readw(ofsAddr + RXrptr);
  	tail = readw(ofsAddr + RXwptr);
  	rx_mask = readw(ofsAddr + RX_mask);
  	spage = readw(ofsAddr + Page_rxb);
  	epage = readw(ofsAddr + EndPage_rxb);
2108eba5c   Jiri Slaby   Char: moxa, clean...
1882
  	count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1883
  	if (count == 0)
33f0f88f1   Alan Cox   [PATCH] TTY layer...
1884
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1885

33f0f88f1   Alan Cox   [PATCH] TTY layer...
1886
  	total = count;
7bcf97d1d   Jiri Slaby   Char: moxa, merge...
1887
  	moxaLog.rxcnt[tty->index] += total;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1888
1889
1890
1891
  	if (spage == epage) {
  		bufhead = readw(ofsAddr + Ofs_rxb);
  		writew(spage, baseAddr + Control_reg);
  		while (count > 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1892
  			ofs = baseAddr + DynPage_addr + bufhead + head;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1893
1894
  			len = (tail >= head) ? (tail - head) :
  					(rx_mask + 1 - head);
2f6933571   Jiri Slaby   TTY: convert more...
1895
  			len = tty_prepare_flip_string(&port->port, &dst,
2108eba5c   Jiri Slaby   Char: moxa, clean...
1896
1897
  					min(len, count));
  			memcpy_fromio(dst, ofs, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1898
1899
1900
  			head = (head + len) & rx_mask;
  			count -= len;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902
1903
  		pageno = spage + (head >> 13);
  		pageofs = head & Page_mask;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1904
  		while (count > 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1905
1906
  			writew(pageno, baseAddr + Control_reg);
  			ofs = baseAddr + DynPage_addr + pageofs;
2f6933571   Jiri Slaby   TTY: convert more...
1907
  			len = tty_prepare_flip_string(&port->port, &dst,
2108eba5c   Jiri Slaby   Char: moxa, clean...
1908
1909
1910
1911
1912
1913
  					min(Page_size - pageofs, count));
  			memcpy_fromio(dst, ofs, len);
  
  			count -= len;
  			pageofs = (pageofs + len) & Page_mask;
  			if (pageofs == 0 && ++pageno == epage)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1914
  				pageno = spage;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1915
1916
  		}
  		head = (head + total) & rx_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1917
  	}
2108eba5c   Jiri Slaby   Char: moxa, clean...
1918
1919
  	writew(head, ofsAddr + RXrptr);
  	if (readb(ofsAddr + FlagStat) & Xoff_state) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1920
  		moxaLowWaterChk = 1;
b4173f457   Jiri Slaby   Char: moxa, remov...
1921
  		port->lowChkFlag = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1922
  	}
2108eba5c   Jiri Slaby   Char: moxa, clean...
1923
  	return total;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1924
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1925
  static int MoxaPortTxQueue(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1927
  	void __iomem *ofsAddr = port->tableAddr;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1928
  	u16 rptr, wptr, mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1929

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
1932
  	rptr = readw(ofsAddr + TXrptr);
  	wptr = readw(ofsAddr + TXwptr);
  	mask = readw(ofsAddr + TX_mask);
2108eba5c   Jiri Slaby   Char: moxa, clean...
1933
  	return (wptr - rptr) & mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1935
  static int MoxaPortTxFree(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1936
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1937
  	void __iomem *ofsAddr = port->tableAddr;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1938
  	u16 rptr, wptr, mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1939

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1940
1941
1942
  	rptr = readw(ofsAddr + TXrptr);
  	wptr = readw(ofsAddr + TXwptr);
  	mask = readw(ofsAddr + TX_mask);
2108eba5c   Jiri Slaby   Char: moxa, clean...
1943
  	return mask - ((wptr - rptr) & mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1944
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1945
  static int MoxaPortRxQueue(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1946
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1947
  	void __iomem *ofsAddr = port->tableAddr;
2108eba5c   Jiri Slaby   Char: moxa, clean...
1948
  	u16 rptr, wptr, mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1949

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1950
1951
1952
  	rptr = readw(ofsAddr + RXrptr);
  	wptr = readw(ofsAddr + RXwptr);
  	mask = readw(ofsAddr + RX_mask);
2108eba5c   Jiri Slaby   Char: moxa, clean...
1953
  	return (wptr - rptr) & mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1954
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1955
  static void MoxaPortTxDisable(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1957
  	moxafunc(port->tableAddr, FC_SetXoffState, Magic_code);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1958
  }
b4173f457   Jiri Slaby   Char: moxa, remov...
1959
  static void MoxaPortTxEnable(struct moxa_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1960
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
1961
  	moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1962
  }
1c729ab15   Al Viro   moxa: switch to -...
1963
1964
  static int moxa_get_serial_info(struct tty_struct *tty,
  		struct serial_struct *ss)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1965
  {
1c729ab15   Al Viro   moxa: switch to -...
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
  	struct moxa_port *info = tty->driver_data;
  
  	if (tty->index == MAX_PORTS)
  		return -EINVAL;
  	if (!info)
  		return -ENODEV;
  	mutex_lock(&info->port.mutex);
  	ss->type = info->type,
  	ss->line = info->port.tty->index,
  	ss->flags = info->port.flags,
  	ss->baud_base = 921600,
  	ss->close_delay = info->port.close_delay;
  	mutex_unlock(&info->port.mutex);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1980
  }
1c729ab15   Al Viro   moxa: switch to -...
1981
1982
  static int moxa_set_serial_info(struct tty_struct *tty,
  		struct serial_struct *ss)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1983
  {
1c729ab15   Al Viro   moxa: switch to -...
1984
  	struct moxa_port *info = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1985

1c729ab15   Al Viro   moxa: switch to -...
1986
1987
1988
1989
  	if (tty->index == MAX_PORTS)
  		return -EINVAL;
  	if (!info)
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1990

1c729ab15   Al Viro   moxa: switch to -...
1991
1992
1993
  	if (ss->irq != 0 || ss->port != 0 ||
  			ss->custom_divisor != 0 ||
  			ss->baud_base != 921600)
eaa95a8da   Jiri Slaby   Char: moxa, littl...
1994
  		return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1995

1c729ab15   Al Viro   moxa: switch to -...
1996
  	mutex_lock(&info->port.mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1997
  	if (!capable(CAP_SYS_ADMIN)) {
1c729ab15   Al Viro   moxa: switch to -...
1998
1999
2000
  		if (((ss->flags & ~ASYNC_USR_MASK) !=
  		     (info->port.flags & ~ASYNC_USR_MASK))) {
  			mutex_unlock(&info->port.mutex);
eaa95a8da   Jiri Slaby   Char: moxa, littl...
2001
  			return -EPERM;
1c729ab15   Al Viro   moxa: switch to -...
2002
2003
2004
  		}
  	}
  	info->port.close_delay = ss->close_delay * HZ / 100;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2005

1c729ab15   Al Viro   moxa: switch to -...
2006
  	MoxaSetFifo(info, ss->type == PORT_16550A);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2007

1c729ab15   Al Viro   moxa: switch to -...
2008
2009
  	info->type = ss->type;
  	mutex_unlock(&info->port.mutex);
eaa95a8da   Jiri Slaby   Char: moxa, littl...
2010
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2011
2012
2013
2014
2015
2016
2017
  }
  
  
  
  /*****************************************************************************
   *	Static local functions: 					     *
   *****************************************************************************/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2018

b4173f457   Jiri Slaby   Char: moxa, remov...
2019
  static void MoxaSetFifo(struct moxa_port *port, int enable)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2020
  {
b4173f457   Jiri Slaby   Char: moxa, remov...
2021
  	void __iomem *ofsAddr = port->tableAddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2022
2023
2024
2025
2026
2027
2028
2029
2030
  
  	if (!enable) {
  		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
  		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
  	} else {
  		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
  		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
  	}
  }