Blame view

drivers/tty/isicom.c 41.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /*
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   *
   *	Original driver code supplied by Multi-Tech
   *
   *	Changes
8eb04cf34   Alan Cox   tty: trivial - fi...
10
11
   *	1/9/98	alan@lxorguk.ukuu.org.uk
   *					Merge to 2.0.x kernel tree
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
   *					Obtain and use official major/minors
   *					Loader switched to a misc device
   *					(fixed range check bug as a side effect)
   *					Printk clean up
8eb04cf34   Alan Cox   tty: trivial - fi...
16
17
   *	9/12/98	alan@lxorguk.ukuu.org.uk
   *					Rough port to 2.1.x
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
   *
   *	10/6/99 sameer			Merged the ISA and PCI drivers to
   *					a new unified driver.
   *
   *	3/9/99	sameer			Added support for ISI4616 cards.
   *
   *	16/9/99	sameer			We do not force RTS low anymore.
d8d16e474   Jiri Slaby   [PATCH] char/isic...
25
   *					This is to prevent the firmware
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
33
34
35
   *					from getting confused.
   *
   *	26/10/99 sameer			Cosmetic changes:The driver now
   *					dumps the Port Count information
   *					along with I/O address and IRQ.
   *
   *	13/12/99 sameer			Fixed the problem with IRQ sharing.
   *
   *	10/5/00  sameer			Fixed isicom_shutdown_board()
   *					to not lower DTR on all the ports
d8d16e474   Jiri Slaby   [PATCH] char/isic...
36
   *					when the last port on the card is
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
   *					closed.
   *
   *	10/5/00  sameer			Signal mask setup command added
d8d16e474   Jiri Slaby   [PATCH] char/isic...
40
   *					to  isicom_setup_port and
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
   *					isicom_shutdown_port.
   *
   *	24/5/00  sameer			The driver is now SMP aware.
d8d16e474   Jiri Slaby   [PATCH] char/isic...
44
45
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
   *	27/11/00 Vinayak P Risbud	Fixed the Driver Crash Problem
d8d16e474   Jiri Slaby   [PATCH] char/isic...
47
48
   *
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
   *	03/01/01  anil .s		Added support for resetting the
   *					internal modems on ISI cards.
   *
   *	08/02/01  anil .s		Upgraded the driver for kernel
   *					2.4.x
   *
d8d16e474   Jiri Slaby   [PATCH] char/isic...
55
   *	11/04/01  Kevin			Fixed firmware load problem with
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
   *					ISIHP-4X card
d8d16e474   Jiri Slaby   [PATCH] char/isic...
57
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
65
66
   *	30/04/01  anil .s		Fixed the remote login through
   *					ISI port problem. Now the link
   *					does not go down before password
   *					prompt.
   *
   *	03/05/01  anil .s		Fixed the problem with IRQ sharing
   *					among ISI-PCI cards.
   *
   *	03/05/01  anil .s		Added support to display the version
d8d16e474   Jiri Slaby   [PATCH] char/isic...
67
   *					info during insmod as well as module
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
   *					listing by lsmod.
d8d16e474   Jiri Slaby   [PATCH] char/isic...
69
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
75
76
77
   *	10/05/01  anil .s		Done the modifications to the source
   *					file and Install script so that the
   *					same installation can be used for
   *					2.2.x and 2.4.x kernel.
   *
   *	06/06/01  anil .s		Now we drop both dtr and rts during
   *					shutdown_port as well as raise them
   *					during isicom_config_port.
d8d16e474   Jiri Slaby   [PATCH] char/isic...
78
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
   *	09/06/01 acme@conectiva.com.br	use capable, not suser, do
   *					restore_flags on failure in
   *					isicom_send_break, verify put_user
   *					result
   *
d8d16e474   Jiri Slaby   [PATCH] char/isic...
84
85
86
87
88
89
90
   *	11/02/03  ranjeeth		Added support for 230 Kbps and 460 Kbps
   *					Baud index extended to 21
   *
   *	20/03/03  ranjeeth		Made to work for Linux Advanced server.
   *					Taken care of license warning.
   *
   *	10/12/03  Ravindra		Made to work for Fedora Core 1 of
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
97
   *					Red Hat Distribution
   *
   *	06/01/05  Alan Cox 		Merged the ISI and base kernel strands
   *					into a single 2.6 driver
   *
   *	***********************************************************
   *
d8d16e474   Jiri Slaby   [PATCH] char/isic...
98
   *	To use this driver you also need the support package. You
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
   *	can find this in RPM format on
   *		ftp://ftp.linux.org.uk/pub/linux/alan
d8d16e474   Jiri Slaby   [PATCH] char/isic...
101
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
106
107
108
109
110
111
   *	You can find the original tools for this direct from Multitech
   *		ftp://ftp.multitech.com/ISI-Cards/
   *
   *	Having installed the cards the module options (/etc/modprobe.conf)
   *
   *	options isicom   io=card1,card2,card3,card4 irq=card1,card2,card3,card4
   *
   *	Omit those entries for boards you don't have installed.
   *
   *	TODO
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
   *		Merge testing
   *		64-bit verification
   */
db91340b2   Joe Perches   serial: isicom.c:...
115
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  #include <linux/module.h>
e65c1db19   Jiri Slaby   [PATCH] char/isic...
117
  #include <linux/firmware.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
  #include <linux/kernel.h>
  #include <linux/tty.h>
33f0f88f1   Alan Cox   [PATCH] TTY layer...
120
  #include <linux/tty_flip.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
  #include <linux/termios.h>
  #include <linux/fs.h>
  #include <linux/sched.h>
  #include <linux/serial.h>
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
  #include <linux/interrupt.h>
  #include <linux/timer.h>
  #include <linux/delay.h>
  #include <linux/ioport.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
130
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131

251b8dd7e   Alan Cox   isicom: bring int...
132
133
  #include <linux/uaccess.h>
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
138
  #include <asm/system.h>
  
  #include <linux/pci.h>
  
  #include <linux/isicom.h>
aaa246ea7   Jiri Slaby   [PATCH] char/isic...
139
140
141
142
  #define InterruptTheCard(base) outw(0, (base) + 0xc)
  #define ClearInterrupt(base) inw((base) + 0x0a)
  
  #ifdef DEBUG
aaa246ea7   Jiri Slaby   [PATCH] char/isic...
143
144
  #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
  #else
aaa246ea7   Jiri Slaby   [PATCH] char/isic...
145
146
  #define isicom_paranoia_check(a, b, c) 0
  #endif
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
147
148
  static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
  static void __devexit isicom_remove(struct pci_dev *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  static struct pci_device_id isicom_pci_tbl[] = {
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
150
151
152
153
154
155
156
157
158
  	{ PCI_DEVICE(VENDOR_ID, 0x2028) },
  	{ PCI_DEVICE(VENDOR_ID, 0x2051) },
  	{ PCI_DEVICE(VENDOR_ID, 0x2052) },
  	{ PCI_DEVICE(VENDOR_ID, 0x2053) },
  	{ PCI_DEVICE(VENDOR_ID, 0x2054) },
  	{ PCI_DEVICE(VENDOR_ID, 0x2055) },
  	{ PCI_DEVICE(VENDOR_ID, 0x2056) },
  	{ PCI_DEVICE(VENDOR_ID, 0x2057) },
  	{ PCI_DEVICE(VENDOR_ID, 0x2058) },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
  	{ 0 }
  };
  MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
162
163
164
165
166
167
  static struct pci_driver isicom_driver = {
  	.name		= "isicom",
  	.id_table	= isicom_pci_tbl,
  	.probe		= isicom_probe,
  	.remove		= __devexit_p(isicom_remove)
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
  static int prev_card = 3;	/*	start servicing isi_card[0]	*/
  static struct tty_driver *isicom_normal;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  static void isicom_tx(unsigned long _data);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
171
  static void isicom_start(struct tty_struct *tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172

34b55b865   Jiri Slaby   [PATCH] Char: isi...
173
  static DEFINE_TIMER(tx, isicom_tx, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
  /*   baud index mappings from linux defns to isi */
  
  static signed char linuxb_to_isib[] = {
7edc136ab   Jiri Slaby   [PATCH] Char: isi...
177
  	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
  };
  
  struct	isi_board {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
181
  	unsigned long		base;
4969b3a43   Jiri Slaby   Char: isicom, pro...
182
  	int			irq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
  	unsigned char		port_count;
  	unsigned short		status;
a547dfe95   Jiri Slaby   [PATCH] char/isic...
185
  	unsigned short		port_status; /* each bit for each port */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  	unsigned short		shift_count;
251b8dd7e   Alan Cox   isicom: bring int...
187
  	struct isi_port		*ports;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  	signed char		count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
  	spinlock_t		card_lock; /* Card wide lock 11/5/00 -sameer */
  	unsigned long		flags;
938a7023b   Jiri Slaby   [PATCH] Char: isi...
191
  	unsigned int		index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
  };
  
  struct	isi_port {
  	unsigned short		magic;
f1d03228e   Alan Cox   isicom: use tty_port
196
  	struct tty_port		port;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
197
198
  	u16			channel;
  	u16			status;
251b8dd7e   Alan Cox   isicom: bring int...
199
  	struct isi_board	*card;
251b8dd7e   Alan Cox   isicom: bring int...
200
  	unsigned char		*xmit_buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
206
207
208
209
210
211
212
213
  	int			xmit_head;
  	int			xmit_tail;
  	int			xmit_cnt;
  };
  
  static struct isi_board isi_card[BOARD_COUNT];
  static struct isi_port  isi_ports[PORT_COUNT];
  
  /*
   *	Locking functions for card level locking. We need to own both
   *	the kernel lock for the card and have the card in a position that
   *	it wants to talk.
   */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
214

4969b3a43   Jiri Slaby   Char: isicom, pro...
215
  static inline int WaitTillCardIsFree(unsigned long base)
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
216
217
218
219
220
221
222
223
224
225
226
227
  {
  	unsigned int count = 0;
  	unsigned int a = in_atomic(); /* do we run under spinlock? */
  
  	while (!(inw(base + 0xe) & 0x1) && count++ < 100)
  		if (a)
  			mdelay(1);
  		else
  			msleep(1);
  
  	return !(inw(base + 0xe) & 0x1);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
  static int lock_card(struct isi_board *card)
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
230
  	unsigned long base = card->base;
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
231
  	unsigned int retries, a;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

5b21f9ddd   Jiri Slaby   Char: isicom, cle...
233
  	for (retries = 0; retries < 10; retries++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  		spin_lock_irqsave(&card->card_lock, card->flags);
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
235
236
237
238
  		for (a = 0; a < 10; a++) {
  			if (inw(base + 0xe) & 0x1)
  				return 1;
  			udelay(10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  		}
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
240
241
  		spin_unlock_irqrestore(&card->card_lock, card->flags);
  		msleep(10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
  	}
db91340b2   Joe Perches   serial: isicom.c:...
243
244
  	pr_warning("Failed to lock Card (0x%lx)
  ", card->base);
a547dfe95   Jiri Slaby   [PATCH] char/isic...
245

0418726bb   Adrian Bunk   typo fixes: aquir...
246
  	return 0;	/* Failed to acquire the card! */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
249
250
251
252
253
254
255
  static void unlock_card(struct isi_board *card)
  {
  	spin_unlock_irqrestore(&card->card_lock, card->flags);
  }
  
  /*
   *  ISI Card specific ops ...
   */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
256

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
257
  /* card->lock HAS to be held */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
258
  static void raise_dtr(struct isi_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
260
  	struct isi_board *card = port->card;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
261
262
  	unsigned long base = card->base;
  	u16 channel = port->channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
264
  	if (WaitTillCardIsFree(base))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
266
  	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
  	outw(0x0504, base);
  	InterruptTheCard(base);
  	port->status |= ISI_DTR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  }
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
271
  /* card->lock HAS to be held */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
272
273
274
  static inline void drop_dtr(struct isi_port *port)
  {
  	struct isi_board *card = port->card;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
275
276
  	unsigned long base = card->base;
  	u16 channel = port->channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
278
  	if (WaitTillCardIsFree(base))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
280
  	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  	outw(0x0404, base);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
282
  	InterruptTheCard(base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  	port->status &= ~ISI_DTR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  }
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
285
  /* card->lock HAS to be held */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
286
  static inline void raise_rts(struct isi_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
288
  	struct isi_board *card = port->card;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
289
290
  	unsigned long base = card->base;
  	u16 channel = port->channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
292
  	if (WaitTillCardIsFree(base))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
294
  	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  	outw(0x0a04, base);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
296
  	InterruptTheCard(base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
  	port->status |= ISI_RTS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  }
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
299
300
  
  /* card->lock HAS to be held */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
301
  static inline void drop_rts(struct isi_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
  {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
303
  	struct isi_board *card = port->card;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
304
305
  	unsigned long base = card->base;
  	u16 channel = port->channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
307
  	if (WaitTillCardIsFree(base))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
309
  	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
  	outw(0x0804, base);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
311
  	InterruptTheCard(base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  	port->status &= ~ISI_RTS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
  }
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
314
  /* card->lock MUST NOT be held */
5d951fb45   Alan Cox   tty: Pull the dtr...
315

fcc8ac182   Alan Cox   tty: Add carrier ...
316
  static void isicom_dtr_rts(struct tty_port *port, int on)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
  {
5d951fb45   Alan Cox   tty: Pull the dtr...
318
319
  	struct isi_port *ip = container_of(port, struct isi_port, port);
  	struct isi_board *card = ip->card;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
320
  	unsigned long base = card->base;
5d951fb45   Alan Cox   tty: Pull the dtr...
321
  	u16 channel = ip->channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
  
  	if (!lock_card(card))
  		return;
fcc8ac182   Alan Cox   tty: Add carrier ...
325
326
327
328
329
330
331
332
333
334
335
  	if (on) {
  		outw(0x8000 | (channel << card->shift_count) | 0x02, base);
  		outw(0x0f04, base);
  		InterruptTheCard(base);
  		ip->status |= (ISI_DTR | ISI_RTS);
  	} else {
  		outw(0x8000 | (channel << card->shift_count) | 0x02, base);
  		outw(0x0C04, base);
  		InterruptTheCard(base);
  		ip->status &= ~(ISI_DTR | ISI_RTS);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
  	unlock_card(card);
  }
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
338
  /* card->lock HAS to be held */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
339
  static void drop_dtr_rts(struct isi_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
341
  	struct isi_board *card = port->card;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
342
343
  	unsigned long base = card->base;
  	u16 channel = port->channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
345
  	if (WaitTillCardIsFree(base))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
347
  	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  	outw(0x0c04, base);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
349
  	InterruptTheCard(base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
  	port->status &= ~(ISI_RTS | ISI_DTR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
354
355
  /*
   *	ISICOM Driver specific routines ...
   *
   */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
356

aaa246ea7   Jiri Slaby   [PATCH] char/isic...
357
358
  static inline int __isicom_paranoia_check(struct isi_port const *port,
  	char *name, const char *routine)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  	if (!port) {
db91340b2   Joe Perches   serial: isicom.c:...
361
362
363
  		pr_warning("Warning: bad isicom magic for dev %s in %s.
  ",
  			   name, routine);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
366
  		return 1;
  	}
  	if (port->magic != ISICOM_MAGIC) {
db91340b2   Joe Perches   serial: isicom.c:...
367
368
369
  		pr_warning("Warning: NULL isicom port for dev %s in %s.
  ",
  			   name, routine);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  		return 1;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
371
  	}
aaa246ea7   Jiri Slaby   [PATCH] char/isic...
372

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
  	return 0;
  }
d8d16e474   Jiri Slaby   [PATCH] char/isic...
375

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  /*
d8d16e474   Jiri Slaby   [PATCH] char/isic...
377
   *	Transmitter.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
380
381
382
383
384
   *
   *	We shovel data into the card buffers on a regular basis. The card
   *	will do the rest of the work for us.
   */
  
  static void isicom_tx(unsigned long _data)
  {
4969b3a43   Jiri Slaby   Char: isicom, pro...
385
  	unsigned long flags, base;
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
386
  	unsigned int retries;
4969b3a43   Jiri Slaby   Char: isicom, pro...
387
  	short count = (BOARD_COUNT-1), card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  	short txcount, wrd, residue, word_count, cnt;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
389
390
  	struct isi_port *port;
  	struct tty_struct *tty;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
  	/*	find next active board	*/
  	card = (prev_card + 1) & 0x0003;
251b8dd7e   Alan Cox   isicom: bring int...
393
  	while (count-- > 0) {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
394
  		if (isi_card[card].status & BOARD_ACTIVE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  			break;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
396
  		card = (card + 1) & 0x0003;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
  	}
  	if (!(isi_card[card].status & BOARD_ACTIVE))
  		goto sched_again;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
400

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
  	prev_card = card;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
402

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
  	count = isi_card[card].port_count;
  	port = isi_card[card].ports;
  	base = isi_card[card].base;
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
406
407
408
409
410
411
412
413
414
  
  	spin_lock_irqsave(&isi_card[card].card_lock, flags);
  	for (retries = 0; retries < 100; retries++) {
  		if (inw(base + 0xe) & 0x1)
  			break;
  		udelay(2);
  	}
  	if (retries >= 100)
  		goto unlock;
d450b5a01   Alan Cox   tty: kref usage f...
415
416
417
  	tty = tty_port_tty_get(&port->port);
  	if (tty == NULL)
  		goto put_unlock;
251b8dd7e   Alan Cox   isicom: bring int...
418
  	for (; count > 0; count--, port++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  		/* port not active or tx disabled to force flow control */
f1d03228e   Alan Cox   isicom: use tty_port
420
  		if (!(port->port.flags & ASYNC_INITIALIZED) ||
d8d16e474   Jiri Slaby   [PATCH] char/isic...
421
  				!(port->status & ISI_TXOK))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  			continue;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
423

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
425
  		if (txcount <= 0 || tty->stopped || tty->hw_stopped)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
  			continue;
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
427
428
  
  		if (!(inw(base + 0x02) & (1 << port->channel)))
d8d16e474   Jiri Slaby   [PATCH] char/isic...
429
  			continue;
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
430

db91340b2   Joe Perches   serial: isicom.c:...
431
432
433
  		pr_debug("txing %d bytes, port%d.
  ",
  			 txcount, port->channel + 1);
aaa246ea7   Jiri Slaby   [PATCH] char/isic...
434
435
  		outw((port->channel << isi_card[card].shift_count) | txcount,
  			base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  		residue = NO;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
437
  		wrd = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  		while (1) {
a547dfe95   Jiri Slaby   [PATCH] char/isic...
439
440
  			cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
  					- port->xmit_tail));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
  			if (residue == YES) {
  				residue = NO;
  				if (cnt > 0) {
f1d03228e   Alan Cox   isicom: use tty_port
444
  					wrd |= (port->port.xmit_buf[port->xmit_tail]
a547dfe95   Jiri Slaby   [PATCH] char/isic...
445
446
447
  									<< 8);
  					port->xmit_tail = (port->xmit_tail + 1)
  						& (SERIAL_XMIT_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
  					port->xmit_cnt--;
  					txcount--;
  					cnt--;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
451
  					outw(wrd, base);
a547dfe95   Jiri Slaby   [PATCH] char/isic...
452
  				} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
  					outw(wrd, base);
  					break;
  				}
d8d16e474   Jiri Slaby   [PATCH] char/isic...
456
  			}
251b8dd7e   Alan Cox   isicom: bring int...
457
458
  			if (cnt <= 0)
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  			word_count = cnt >> 1;
f1d03228e   Alan Cox   isicom: use tty_port
460
  			outsw(base, port->port.xmit_buf+port->xmit_tail, word_count);
a547dfe95   Jiri Slaby   [PATCH] char/isic...
461
462
  			port->xmit_tail = (port->xmit_tail
  				+ (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
  			txcount -= (word_count << 1);
  			port->xmit_cnt -= (word_count << 1);
  			if (cnt & 0x0001) {
  				residue = YES;
f1d03228e   Alan Cox   isicom: use tty_port
467
  				wrd = port->port.xmit_buf[port->xmit_tail];
a547dfe95   Jiri Slaby   [PATCH] char/isic...
468
469
  				port->xmit_tail = (port->xmit_tail + 1)
  					& (SERIAL_XMIT_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
473
474
475
476
477
478
  				port->xmit_cnt--;
  				txcount--;
  			}
  		}
  
  		InterruptTheCard(base);
  		if (port->xmit_cnt <= 0)
  			port->status &= ~ISI_TXOK;
  		if (port->xmit_cnt <= WAKEUP_CHARS)
0aa5de859   Jiri Slaby   [PATCH] Char: isi...
479
  			tty_wakeup(tty);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
480
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481

d450b5a01   Alan Cox   tty: kref usage f...
482
483
  put_unlock:
  	tty_kref_put(tty);
5b21f9ddd   Jiri Slaby   Char: isicom, cle...
484
485
  unlock:
  	spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
486
487
  	/*	schedule another tx for hopefully in about 10ms	*/
  sched_again:
34b55b865   Jiri Slaby   [PATCH] Char: isi...
488
  	mod_timer(&tx, jiffies + msecs_to_jiffies(10));
d8d16e474   Jiri Slaby   [PATCH] char/isic...
489
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  /*
d8d16e474   Jiri Slaby   [PATCH] char/isic...
491
   *	Main interrupt handler routine
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
   */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
493

7d12e780e   David Howells   IRQ: Maintain reg...
494
  static irqreturn_t isicom_interrupt(int irq, void *dev_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
496
  	struct isi_board *card = dev_id;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
497
498
  	struct isi_port *port;
  	struct tty_struct *tty;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
499
500
  	unsigned long base;
  	u16 header, word_count, count, channel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  	short byte_count;
33f0f88f1   Alan Cox   [PATCH] TTY layer...
502
  	unsigned char *rp;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
503

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
  	if (!card || !(card->status & FIRMWARE_LOADED))
  		return IRQ_NONE;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
506

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
  	base = card->base;
cb4a10ccb   Jiri Slaby   [PATCH] Char: isi...
508
509
510
511
  
  	/* did the card interrupt us? */
  	if (!(inw(base + 0x0e) & 0x02))
  		return IRQ_NONE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
  	spin_lock(&card->card_lock);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
513

18234f88b   Jiri Slaby   [PATCH] Char: isi...
514
515
516
517
518
519
  	/*
  	 * disable any interrupts from the PCI card and lower the
  	 * interrupt line
  	 */
  	outw(0x8000, base+0x04);
  	ClearInterrupt(base);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
520

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
526
  	inw(base);		/* get the dummy word out */
  	header = inw(base);
  	channel = (header & 0x7800) >> card->shift_count;
  	byte_count = header & 0xff;
  
  	if (channel + 1 > card->port_count) {
db91340b2   Joe Perches   serial: isicom.c:...
527
528
529
  		pr_warning("%s(0x%lx): %d(channel) > port_count.
  ",
  			   __func__, base, channel+1);
18234f88b   Jiri Slaby   [PATCH] Char: isi...
530
  		outw(0x0000, base+0x04); /* enable interrupts */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  		spin_unlock(&card->card_lock);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
532
  		return IRQ_HANDLED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
  	}
  	port = card->ports + channel;
f1d03228e   Alan Cox   isicom: use tty_port
535
  	if (!(port->port.flags & ASYNC_INITIALIZED)) {
18234f88b   Jiri Slaby   [PATCH] Char: isi...
536
  		outw(0x0000, base+0x04); /* enable interrupts */
174f13076   Jiri Slaby   [PATCH] Char: isi...
537
  		spin_unlock(&card->card_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
  		return IRQ_HANDLED;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
539
  	}
d450b5a01   Alan Cox   tty: kref usage f...
540
  	tty = tty_port_tty_get(&port->port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
  	if (tty == NULL) {
  		word_count = byte_count >> 1;
251b8dd7e   Alan Cox   isicom: bring int...
543
  		while (byte_count > 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
546
547
548
  			inw(base);
  			byte_count -= 2;
  		}
  		if (byte_count & 0x01)
  			inw(base);
18234f88b   Jiri Slaby   [PATCH] Char: isi...
549
  		outw(0x0000, base+0x04); /* enable interrupts */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
552
  		spin_unlock(&card->card_lock);
  		return IRQ_HANDLED;
  	}
d8d16e474   Jiri Slaby   [PATCH] char/isic...
553

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
  	if (header & 0x8000) {		/* Status Packet */
  		header = inw(base);
251b8dd7e   Alan Cox   isicom: bring int...
556
  		switch (header & 0xff) {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
557
  		case 0:	/* Change in EIA signals */
f1d03228e   Alan Cox   isicom: use tty_port
558
  			if (port->port.flags & ASYNC_CHECK_CD) {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
559
560
561
  				if (port->status & ISI_DCD) {
  					if (!(header & ISI_DCD)) {
  					/* Carrier has been lost  */
db91340b2   Joe Perches   serial: isicom.c:...
562
563
564
  						pr_debug("%s: DCD->low.
  ",
  							 __func__);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
565
  						port->status &= ~ISI_DCD;
0aa5de859   Jiri Slaby   [PATCH] Char: isi...
566
  						tty_hangup(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
  					}
a547dfe95   Jiri Slaby   [PATCH] char/isic...
568
569
  				} else if (header & ISI_DCD) {
  				/* Carrier has been detected */
db91340b2   Joe Perches   serial: isicom.c:...
570
571
572
  					pr_debug("%s: DCD->high.
  ",
  						__func__);
a547dfe95   Jiri Slaby   [PATCH] char/isic...
573
  					port->status |= ISI_DCD;
f1d03228e   Alan Cox   isicom: use tty_port
574
  					wake_up_interruptible(&port->port.open_wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  				}
a547dfe95   Jiri Slaby   [PATCH] char/isic...
576
  			} else {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
577
578
579
580
581
  				if (header & ISI_DCD)
  					port->status |= ISI_DCD;
  				else
  					port->status &= ~ISI_DCD;
  			}
f1d03228e   Alan Cox   isicom: use tty_port
582
  			if (port->port.flags & ASYNC_CTS_FLOW) {
d450b5a01   Alan Cox   tty: kref usage f...
583
  				if (tty->hw_stopped) {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
584
  					if (header & ISI_CTS) {
f1d03228e   Alan Cox   isicom: use tty_port
585
  						port->port.tty->hw_stopped = 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
586
  						/* start tx ing */
a547dfe95   Jiri Slaby   [PATCH] char/isic...
587
588
  						port->status |= (ISI_TXOK
  							| ISI_CTS);
0aa5de859   Jiri Slaby   [PATCH] Char: isi...
589
  						tty_wakeup(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
  					}
a547dfe95   Jiri Slaby   [PATCH] char/isic...
591
  				} else if (!(header & ISI_CTS)) {
d450b5a01   Alan Cox   tty: kref usage f...
592
  					tty->hw_stopped = 1;
a547dfe95   Jiri Slaby   [PATCH] char/isic...
593
594
  					/* stop tx ing */
  					port->status &= ~(ISI_TXOK | ISI_CTS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  				}
a547dfe95   Jiri Slaby   [PATCH] char/isic...
596
  			} else {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
597
598
  				if (header & ISI_CTS)
  					port->status |= ISI_CTS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
  				else
d8d16e474   Jiri Slaby   [PATCH] char/isic...
600
601
602
603
604
605
606
607
608
609
610
611
612
613
  					port->status &= ~ISI_CTS;
  			}
  
  			if (header & ISI_DSR)
  				port->status |= ISI_DSR;
  			else
  				port->status &= ~ISI_DSR;
  
  			if (header & ISI_RI)
  				port->status |= ISI_RI;
  			else
  				port->status &= ~ISI_RI;
  
  			break;
a547dfe95   Jiri Slaby   [PATCH] char/isic...
614
  		case 1:	/* Received Break !!! */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
615
  			tty_insert_flip_char(tty, 0, TTY_BREAK);
f1d03228e   Alan Cox   isicom: use tty_port
616
  			if (port->port.flags & ASYNC_SAK)
d8d16e474   Jiri Slaby   [PATCH] char/isic...
617
618
619
620
621
  				do_SAK(tty);
  			tty_flip_buffer_push(tty);
  			break;
  
  		case 2:	/* Statistics		 */
db91340b2   Joe Perches   serial: isicom.c:...
622
623
  			pr_debug("%s: stats!!!
  ", __func__);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
624
625
626
  			break;
  
  		default:
db91340b2   Joe Perches   serial: isicom.c:...
627
628
629
  			pr_debug("%s: Unknown code in status packet.
  ",
  				 __func__);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
630
631
  			break;
  		}
a547dfe95   Jiri Slaby   [PATCH] char/isic...
632
  	} else {				/* Data   Packet */
33f0f88f1   Alan Cox   [PATCH] TTY layer...
633
634
  
  		count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
db91340b2   Joe Perches   serial: isicom.c:...
635
636
637
  		pr_debug("%s: Can rx %d of %d bytes.
  ",
  			 __func__, count, byte_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
  		word_count = count >> 1;
33f0f88f1   Alan Cox   [PATCH] TTY layer...
639
  		insw(base, rp, word_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
  		byte_count -= (word_count << 1);
  		if (count & 0x0001) {
a547dfe95   Jiri Slaby   [PATCH] char/isic...
642
643
  			tty_insert_flip_char(tty,  inw(base) & 0xff,
  				TTY_NORMAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
  			byte_count -= 2;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
645
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  		if (byte_count > 0) {
db91340b2   Joe Perches   serial: isicom.c:...
647
648
649
  			pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...
  ",
  				 __func__, base, channel + 1);
251b8dd7e   Alan Cox   isicom: bring int...
650
651
  		/* drain out unread xtra data */
  		while (byte_count > 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
653
654
655
  				inw(base);
  				byte_count -= 2;
  			}
  		}
33f0f88f1   Alan Cox   [PATCH] TTY layer...
656
  		tty_flip_buffer_push(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  	}
18234f88b   Jiri Slaby   [PATCH] Char: isi...
658
  	outw(0x0000, base+0x04); /* enable interrupts */
174f13076   Jiri Slaby   [PATCH] Char: isi...
659
  	spin_unlock(&card->card_lock);
d450b5a01   Alan Cox   tty: kref usage f...
660
  	tty_kref_put(tty);
a547dfe95   Jiri Slaby   [PATCH] char/isic...
661

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
  	return IRQ_HANDLED;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
663
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664

d450b5a01   Alan Cox   tty: kref usage f...
665
  static void isicom_config_port(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
  {
d450b5a01   Alan Cox   tty: kref usage f...
667
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
668
  	struct isi_board *card = port->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
  	unsigned long baud;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
670
671
672
  	unsigned long base = card->base;
  	u16 channel_setup, channel = port->channel,
  		shift_count = card->shift_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
  	unsigned char flow_ctrl;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
674

251b8dd7e   Alan Cox   isicom: bring int...
675
  	/* FIXME: Switch to new tty baud API */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
678
  	baud = C_BAUD(tty);
  	if (baud & CBAUDEX) {
  		baud &= ~CBAUDEX;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
679

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
681
682
  		/*  if CBAUDEX bit is on and the baud is set to either 50 or 75
  		 *  then the card is programmed for 57.6Kbps or 115Kbps
  		 *  respectively.
d8d16e474   Jiri Slaby   [PATCH] char/isic...
683
  		 */
7edc136ab   Jiri Slaby   [PATCH] Char: isi...
684
685
  		/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
  		if (baud < 1 || baud > 4)
d450b5a01   Alan Cox   tty: kref usage f...
686
  			tty->termios->c_cflag &= ~CBAUDEX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
688
  		else
  			baud += 15;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
689
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
  	if (baud == 15) {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
691
692
  
  		/*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
694
  		 *  by the set_serial_info ioctl ... this is done by
  		 *  the 'setserial' utility.
d8d16e474   Jiri Slaby   [PATCH] char/isic...
695
  		 */
f1d03228e   Alan Cox   isicom: use tty_port
696
  		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
d8d16e474   Jiri Slaby   [PATCH] char/isic...
697
  			baud++; /*  57.6 Kbps */
f1d03228e   Alan Cox   isicom: use tty_port
698
  		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
251b8dd7e   Alan Cox   isicom: bring int...
699
  			baud += 2; /*  115  Kbps */
f1d03228e   Alan Cox   isicom: use tty_port
700
  		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
7edc136ab   Jiri Slaby   [PATCH] Char: isi...
701
  			baud += 3; /* 230 kbps*/
f1d03228e   Alan Cox   isicom: use tty_port
702
  		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
7edc136ab   Jiri Slaby   [PATCH] Char: isi...
703
  			baud += 4; /* 460 kbps*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
706
  	}
  	if (linuxb_to_isib[baud] == -1) {
  		/* hang up */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
707
708
  		drop_dtr(port);
  		return;
251b8dd7e   Alan Cox   isicom: bring int...
709
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
  		raise_dtr(port);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
711

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
712
  	if (WaitTillCardIsFree(base) == 0) {
251b8dd7e   Alan Cox   isicom: bring int...
713
  		outw(0x8000 | (channel << shift_count) | 0x03, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
  		outw(linuxb_to_isib[baud] << 8 | 0x03, base);
  		channel_setup = 0;
251b8dd7e   Alan Cox   isicom: bring int...
716
  		switch (C_CSIZE(tty)) {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
717
718
719
720
721
722
723
724
725
726
727
728
  		case CS5:
  			channel_setup |= ISICOM_CS5;
  			break;
  		case CS6:
  			channel_setup |= ISICOM_CS6;
  			break;
  		case CS7:
  			channel_setup |= ISICOM_CS7;
  			break;
  		case CS8:
  			channel_setup |= ISICOM_CS8;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
  		}
d8d16e474   Jiri Slaby   [PATCH] char/isic...
730

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
733
734
735
  		if (C_CSTOPB(tty))
  			channel_setup |= ISICOM_2SB;
  		if (C_PARENB(tty)) {
  			channel_setup |= ISICOM_EVPAR;
  			if (C_PARODD(tty))
d8d16e474   Jiri Slaby   [PATCH] char/isic...
736
  				channel_setup |= ISICOM_ODPAR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
  		}
d8d16e474   Jiri Slaby   [PATCH] char/isic...
738
  		outw(channel_setup, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
  		InterruptTheCard(base);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
740
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  	if (C_CLOCAL(tty))
f1d03228e   Alan Cox   isicom: use tty_port
742
  		port->port.flags &= ~ASYNC_CHECK_CD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
  	else
f1d03228e   Alan Cox   isicom: use tty_port
744
  		port->port.flags |= ASYNC_CHECK_CD;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
745

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
  	/* flow control settings ...*/
  	flow_ctrl = 0;
f1d03228e   Alan Cox   isicom: use tty_port
748
  	port->port.flags &= ~ASYNC_CTS_FLOW;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
  	if (C_CRTSCTS(tty)) {
f1d03228e   Alan Cox   isicom: use tty_port
750
  		port->port.flags |= ASYNC_CTS_FLOW;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
  		flow_ctrl |= ISICOM_CTSRTS;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
752
753
  	}
  	if (I_IXON(tty))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
  		flow_ctrl |= ISICOM_RESPOND_XONXOFF;
  	if (I_IXOFF(tty))
d8d16e474   Jiri Slaby   [PATCH] char/isic...
756
  		flow_ctrl |= ISICOM_INITIATE_XONXOFF;
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
757
  	if (WaitTillCardIsFree(base) == 0) {
251b8dd7e   Alan Cox   isicom: bring int...
758
  		outw(0x8000 | (channel << shift_count) | 0x04, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
760
761
  		outw(flow_ctrl << 8 | 0x05, base);
  		outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
  		InterruptTheCard(base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  	}
d8d16e474   Jiri Slaby   [PATCH] char/isic...
763

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
767
768
769
  	/*	rx enabled -> enable port for rx on the card	*/
  	if (C_CREAD(tty)) {
  		card->port_status |= (1 << channel);
  		outw(card->port_status, base + 0x02);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770

d8d16e474   Jiri Slaby   [PATCH] char/isic...
771
772
773
  /* open et all */
  
  static inline void isicom_setup_board(struct isi_board *bp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
  {
  	int channel;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
776
  	struct isi_port *port;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
777

baaa08acb   Alan Cox   tty: isicom: swit...
778
  	bp->count++;
6ed847d8e   Alan Cox   tty: isicom: sort...
779
780
781
782
783
784
  	if (!(bp->status & BOARD_INIT)) {
  		port = bp->ports;
  		for (channel = 0; channel < bp->port_count; channel++, port++)
  			drop_dtr_rts(port);
  	}
  	bp->status |= BOARD_ACTIVE | BOARD_INIT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
  }
d8d16e474   Jiri Slaby   [PATCH] char/isic...
786

6ed847d8e   Alan Cox   tty: isicom: sort...
787
788
  /* Activate and thus setup board are protected from races against shutdown
     by the tty_port mutex */
baaa08acb   Alan Cox   tty: isicom: swit...
789
  static int isicom_activate(struct tty_port *tport, struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
  {
baaa08acb   Alan Cox   tty: isicom: swit...
791
  	struct isi_port *port = container_of(tport, struct isi_port, port);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
792
  	struct isi_board *card = port->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
  	unsigned long flags;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
794

baaa08acb   Alan Cox   tty: isicom: swit...
795
  	if (tty_port_alloc_xmit_buf(tport) < 0)
f1d03228e   Alan Cox   isicom: use tty_port
796
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
798
  
  	spin_lock_irqsave(&card->card_lock, flags);
baaa08acb   Alan Cox   tty: isicom: swit...
799
  	isicom_setup_board(card);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
800

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
  	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
802

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  	/*	discard any residual data	*/
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
804
805
806
807
808
809
  	if (WaitTillCardIsFree(card->base) == 0) {
  		outw(0x8000 | (port->channel << card->shift_count) | 0x02,
  				card->base);
  		outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
  		InterruptTheCard(card->base);
  	}
d450b5a01   Alan Cox   tty: kref usage f...
810
  	isicom_config_port(tty);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
  	spin_unlock_irqrestore(&card->card_lock, flags);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
812
813
814
  
  	return 0;
  }
31f35939d   Alan Cox   tty_port: Add a p...
815
816
817
818
819
  static int isicom_carrier_raised(struct tty_port *port)
  {
  	struct isi_port *ip = container_of(port, struct isi_port, port);
  	return (ip->status & ISI_DCD)?1 : 0;
  }
11d85d7b2   Alan Cox   isicom: split the...
820
  static struct tty_port *isicom_find_port(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
  {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
822
823
  	struct isi_port *port;
  	struct isi_board *card;
17c4edf0c   Jiri Slaby   [PATCH] Char: isi...
824
  	unsigned int board;
11d85d7b2   Alan Cox   isicom: split the...
825
  	int line = tty->index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
  	if (line < 0 || line > PORT_COUNT-1)
11d85d7b2   Alan Cox   isicom: split the...
828
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
830
  	board = BOARD(line);
  	card = &isi_card[board];
d8d16e474   Jiri Slaby   [PATCH] char/isic...
831

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
  	if (!(card->status & FIRMWARE_LOADED))
11d85d7b2   Alan Cox   isicom: split the...
833
  		return NULL;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
834

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
  	/*  open on a port greater than the port count for the card !!! */
  	if (line > ((board * 16) + card->port_count - 1))
11d85d7b2   Alan Cox   isicom: split the...
837
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838

d8d16e474   Jiri Slaby   [PATCH] char/isic...
839
  	port = &isi_ports[line];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
  	if (isicom_paranoia_check(port, tty->name, "isicom_open"))
11d85d7b2   Alan Cox   isicom: split the...
841
842
843
844
  		return NULL;
  
  	return &port->port;
  }
baaa08acb   Alan Cox   tty: isicom: swit...
845

11d85d7b2   Alan Cox   isicom: split the...
846
847
848
  static int isicom_open(struct tty_struct *tty, struct file *filp)
  {
  	struct isi_port *port;
11d85d7b2   Alan Cox   isicom: split the...
849
  	struct tty_port *tport;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
850

11d85d7b2   Alan Cox   isicom: split the...
851
852
853
854
  	tport = isicom_find_port(tty);
  	if (tport == NULL)
  		return -ENODEV;
  	port = container_of(tport, struct isi_port, port);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
855

a2d1e3516   Alan Cox   tty: Fix regressi...
856
  	tty->driver_data = port;
baaa08acb   Alan Cox   tty: isicom: swit...
857
  	return tty_port_open(tport, tty, filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
  }
d8d16e474   Jiri Slaby   [PATCH] char/isic...
859

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
  /* close et all */
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
861
  /* card->lock HAS to be held */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
862
  static void isicom_shutdown_port(struct isi_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
  {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
864
  	struct isi_board *card = port->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
  	if (--card->count < 0) {
db91340b2   Joe Perches   serial: isicom.c:...
867
868
869
  		pr_debug("%s: bad board(0x%lx) count %d.
  ",
  			 __func__, card->base, card->count);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
870
  		card->count = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
  	}
baaa08acb   Alan Cox   tty: isicom: swit...
872
  	/* last port was closed, shutdown that board too */
6ed847d8e   Alan Cox   tty: isicom: sort...
873
874
  	if (!card->count)
  		card->status &= BOARD_ACTIVE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
  }
978e595f8   Alan Cox   tty/serial: lay t...
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
  static void isicom_flush_buffer(struct tty_struct *tty)
  {
  	struct isi_port *port = tty->driver_data;
  	struct isi_board *card = port->card;
  	unsigned long flags;
  
  	if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
  		return;
  
  	spin_lock_irqsave(&card->card_lock, flags);
  	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
  	spin_unlock_irqrestore(&card->card_lock, flags);
  
  	tty_wakeup(tty);
  }
baaa08acb   Alan Cox   tty: isicom: swit...
891
  static void isicom_shutdown(struct tty_port *port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
  {
6f6412b4c   Alan Cox   isicom: Split the...
893
894
  	struct isi_port *ip = container_of(port, struct isi_port, port);
  	struct isi_board *card = ip->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
  	unsigned long flags;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
896

d8d16e474   Jiri Slaby   [PATCH] char/isic...
897
  	/* indicate to the card that no more data can be received
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
899
  	   on this port */
  	spin_lock_irqsave(&card->card_lock, flags);
baaa08acb   Alan Cox   tty: isicom: swit...
900
901
  	card->port_status &= ~(1 << ip->channel);
  	outw(card->port_status, card->base + 0x02);
a6614999e   Alan Cox   tty: Introduce so...
902
  	isicom_shutdown_port(ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
  	spin_unlock_irqrestore(&card->card_lock, flags);
2493c0c16   Alan Cox   tty: isicom: fix ...
904
  	tty_port_free_xmit_buf(port);
6f6412b4c   Alan Cox   isicom: Split the...
905
  }
d8d16e474   Jiri Slaby   [PATCH] char/isic...
906

6f6412b4c   Alan Cox   isicom: Split the...
907
908
909
  static void isicom_close(struct tty_struct *tty, struct file *filp)
  {
  	struct isi_port *ip = tty->driver_data;
a2d1e3516   Alan Cox   tty: Fix regressi...
910
911
912
913
914
915
  	struct tty_port *port;
  
  	if (ip == NULL)
  		return;
  
  	port = &ip->port;
6f6412b4c   Alan Cox   isicom: Split the...
916
917
  	if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
  		return;
baaa08acb   Alan Cox   tty: isicom: swit...
918
  	tty_port_close(port, tty, filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
921
  }
  
  /* write et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
922
923
  static int isicom_write(struct tty_struct *tty,	const unsigned char *buf,
  	int count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
925
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
926
  	struct isi_board *card = port->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
928
929
930
931
  	unsigned long flags;
  	int cnt, total = 0;
  
  	if (isicom_paranoia_check(port, tty->name, "isicom_write"))
  		return 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
932

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
933
  	spin_lock_irqsave(&card->card_lock, flags);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
934

251b8dd7e   Alan Cox   isicom: bring int...
935
  	while (1) {
a547dfe95   Jiri Slaby   [PATCH] char/isic...
936
937
  		cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
  				- 1, SERIAL_XMIT_SIZE - port->xmit_head));
d8d16e474   Jiri Slaby   [PATCH] char/isic...
938
  		if (cnt <= 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  			break;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
940

f1d03228e   Alan Cox   isicom: use tty_port
941
  		memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt);
a547dfe95   Jiri Slaby   [PATCH] char/isic...
942
943
  		port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
  			- 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
946
947
  		port->xmit_cnt += cnt;
  		buf += cnt;
  		count -= cnt;
  		total += cnt;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
948
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
950
951
  	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
  		port->status |= ISI_TXOK;
  	spin_unlock_irqrestore(&card->card_lock, flags);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
952
  	return total;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
955
  }
  
  /* put_char et all */
f34d7a5b7   Alan Cox   tty: The big oper...
956
  static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
958
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
959
  	struct isi_board *card = port->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
  	unsigned long flags;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
961

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
  	if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
f34d7a5b7   Alan Cox   tty: The big oper...
963
  		return 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
964

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
  	spin_lock_irqsave(&card->card_lock, flags);
f34d7a5b7   Alan Cox   tty: The big oper...
966
967
968
969
  	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
  		spin_unlock_irqrestore(&card->card_lock, flags);
  		return 0;
  	}
d8d16e474   Jiri Slaby   [PATCH] char/isic...
970

f1d03228e   Alan Cox   isicom: use tty_port
971
  	port->port.xmit_buf[port->xmit_head++] = ch;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
974
  	port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
  	port->xmit_cnt++;
  	spin_unlock_irqrestore(&card->card_lock, flags);
f34d7a5b7   Alan Cox   tty: The big oper...
975
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
977
978
  }
  
  /* flush_chars et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
979
  static void isicom_flush_chars(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
981
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
982

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
  	if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
985

a547dfe95   Jiri Slaby   [PATCH] char/isic...
986
  	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
f1d03228e   Alan Cox   isicom: use tty_port
987
  			!port->port.xmit_buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
989

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
  	/* this tells the transmitter to consider this port for
  	   data output to the card ... that's the best we can do. */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
992
  	port->status |= ISI_TXOK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
  }
  
  /* write_room et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
996
  static int isicom_write_room(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
998
  	struct isi_port *port = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999
1000
1001
1002
  	int free;
  
  	if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
  		return 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1003

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
1005
1006
1007
1008
1009
1010
  	free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
  	if (free < 0)
  		free = 0;
  	return free;
  }
  
  /* chars_in_buffer et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1011
  static int isicom_chars_in_buffer(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1013
  	struct isi_port *port = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
1015
1016
1017
1018
1019
  	if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
  		return 0;
  	return port->xmit_cnt;
  }
  
  /* ioctl et all */
6d8897243   Alan Cox   isicom: restore u...
1020
  static int isicom_send_break(struct tty_struct *tty, int length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021
  {
6d8897243   Alan Cox   isicom: restore u...
1022
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1023
  	struct isi_board *card = port->card;
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1024
  	unsigned long base = card->base;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1025

6d8897243   Alan Cox   isicom: restore u...
1026
1027
  	if (length == -1)
  		return -EOPNOTSUPP;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1028
  	if (!lock_card(card))
6d8897243   Alan Cox   isicom: restore u...
1029
  		return -EINVAL;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1030

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1031
1032
1033
1034
1035
1036
  	outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
  	outw((length & 0xff) << 8 | 0x00, base);
  	outw((length & 0xff00), base);
  	InterruptTheCard(base);
  
  	unlock_card(card);
6d8897243   Alan Cox   isicom: restore u...
1037
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038
  }
60b33c133   Alan Cox   tiocmget: kill of...
1039
  static int isicom_tiocmget(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1041
  	struct isi_port *port = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
  	/* just send the port status */
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1043
  	u16 status = port->status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044
1045
1046
  
  	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
  		return -ENODEV;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1047

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1048
1049
1050
1051
1052
1053
1054
  	return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
  		((status & ISI_DTR) ? TIOCM_DTR : 0) |
  		((status & ISI_DCD) ? TIOCM_CAR : 0) |
  		((status & ISI_DSR) ? TIOCM_DSR : 0) |
  		((status & ISI_CTS) ? TIOCM_CTS : 0) |
  		((status & ISI_RI ) ? TIOCM_RI  : 0);
  }
20b9d1771   Alan Cox   tiocmset: kill th...
1055
1056
  static int isicom_tiocmset(struct tty_struct *tty,
  					unsigned int set, unsigned int clear)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1058
  	struct isi_port *port = tty->driver_data;
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
1059
  	unsigned long flags;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1060

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
1062
  	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
  		return -ENODEV;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1063

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
1064
  	spin_lock_irqsave(&port->card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1065
1066
1067
1068
1069
1070
1071
1072
1073
  	if (set & TIOCM_RTS)
  		raise_rts(port);
  	if (set & TIOCM_DTR)
  		raise_dtr(port);
  
  	if (clear & TIOCM_RTS)
  		drop_rts(port);
  	if (clear & TIOCM_DTR)
  		drop_dtr(port);
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
1074
  	spin_unlock_irqrestore(&port->card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1075
1076
  
  	return 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1077
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078

d450b5a01   Alan Cox   tty: kref usage f...
1079
1080
  static int isicom_set_serial_info(struct tty_struct *tty,
  					struct serial_struct __user *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1081
  {
d450b5a01   Alan Cox   tty: kref usage f...
1082
  	struct isi_port *port = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
  	struct serial_struct newinfo;
  	int reconfig_port;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1085
  	if (copy_from_user(&newinfo, info, sizeof(newinfo)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
  		return -EFAULT;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1087

ec82db129   Alan Cox   isicom: kill off ...
1088
  	mutex_lock(&port->port.mutex);
f1d03228e   Alan Cox   isicom: use tty_port
1089
  	reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1090
  		(newinfo.flags & ASYNC_SPD_MASK));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1091
  	if (!capable(CAP_SYS_ADMIN)) {
44b7d1b37   Alan Cox   tty: add more tty...
1092
1093
  		if ((newinfo.close_delay != port->port.close_delay) ||
  				(newinfo.closing_wait != port->port.closing_wait) ||
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1094
  				((newinfo.flags & ~ASYNC_USR_MASK) !=
f1d03228e   Alan Cox   isicom: use tty_port
1095
  				(port->port.flags & ~ASYNC_USR_MASK))) {
ec82db129   Alan Cox   isicom: kill off ...
1096
  			mutex_unlock(&port->port.mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097
  			return -EPERM;
1eac49473   Alan Cox   isicom: prepare f...
1098
  		}
f1d03228e   Alan Cox   isicom: use tty_port
1099
  		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
  				(newinfo.flags & ASYNC_USR_MASK));
251b8dd7e   Alan Cox   isicom: bring int...
1101
  	} else {
44b7d1b37   Alan Cox   tty: add more tty...
1102
1103
  		port->port.close_delay = newinfo.close_delay;
  		port->port.closing_wait = newinfo.closing_wait;
f1d03228e   Alan Cox   isicom: use tty_port
1104
  		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
1106
1107
  				(newinfo.flags & ASYNC_FLAGS));
  	}
  	if (reconfig_port) {
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
1108
1109
  		unsigned long flags;
  		spin_lock_irqsave(&port->card->card_lock, flags);
d450b5a01   Alan Cox   tty: kref usage f...
1110
  		isicom_config_port(tty);
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
1111
  		spin_unlock_irqrestore(&port->card->card_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
  	}
ec82db129   Alan Cox   isicom: kill off ...
1113
  	mutex_unlock(&port->port.mutex);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1114
1115
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116

d8d16e474   Jiri Slaby   [PATCH] char/isic...
1117
1118
  static int isicom_get_serial_info(struct isi_port *port,
  	struct serial_struct __user *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
1120
  {
  	struct serial_struct out_info;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1121

ec82db129   Alan Cox   isicom: kill off ...
1122
  	mutex_lock(&port->port.mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
1124
1125
1126
1127
  	memset(&out_info, 0, sizeof(out_info));
  /*	out_info.type = ? */
  	out_info.line = port - isi_ports;
  	out_info.port = port->card->base;
  	out_info.irq = port->card->irq;
f1d03228e   Alan Cox   isicom: use tty_port
1128
  	out_info.flags = port->port.flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1129
  /*	out_info.baud_base = ? */
44b7d1b37   Alan Cox   tty: add more tty...
1130
1131
  	out_info.close_delay = port->port.close_delay;
  	out_info.closing_wait = port->port.closing_wait;
ec82db129   Alan Cox   isicom: kill off ...
1132
  	mutex_unlock(&port->port.mutex);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1133
  	if (copy_to_user(info, &out_info, sizeof(out_info)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
1135
  		return -EFAULT;
  	return 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1136
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137

6caa76b77   Alan Cox   tty: now phase ou...
1138
  static int isicom_ioctl(struct tty_struct *tty,
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1139
  	unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1140
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1141
  	struct isi_port *port = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
  	void __user *argp = (void __user *)arg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
1144
1145
  
  	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
  		return -ENODEV;
251b8dd7e   Alan Cox   isicom: bring int...
1146
  	switch (cmd) {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1147
1148
1149
1150
  	case TIOCGSERIAL:
  		return isicom_get_serial_info(port, argp);
  
  	case TIOCSSERIAL:
d450b5a01   Alan Cox   tty: kref usage f...
1151
  		return isicom_set_serial_info(tty, argp);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1152
1153
1154
  
  	default:
  		return -ENOIOCTLCMD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155
1156
1157
1158
1159
  	}
  	return 0;
  }
  
  /* set_termios et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1160
  static void isicom_set_termios(struct tty_struct *tty,
606d099cd   Alan Cox   [PATCH] tty: swit...
1161
  	struct ktermios *old_termios)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1163
  	struct isi_port *port = tty->driver_data;
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
1164
  	unsigned long flags;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1165

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
1167
  	if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1168

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1169
  	if (tty->termios->c_cflag == old_termios->c_cflag &&
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1170
  			tty->termios->c_iflag == old_termios->c_iflag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1172

cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
1173
  	spin_lock_irqsave(&port->card->card_lock, flags);
d450b5a01   Alan Cox   tty: kref usage f...
1174
  	isicom_config_port(tty);
cfe7c09ac   Jiri Slaby   [PATCH] Char: isi...
1175
  	spin_unlock_irqrestore(&port->card->card_lock, flags);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1176

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
  	if ((old_termios->c_cflag & CRTSCTS) &&
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1178
  			!(tty->termios->c_cflag & CRTSCTS)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
  		tty->hw_stopped = 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1180
1181
  		isicom_start(tty);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
1183
1184
  }
  
  /* throttle et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1185
  static void isicom_throttle(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1187
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1188
  	struct isi_board *card = port->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
1190
  	if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1191

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
1193
1194
1195
1196
1197
  	/* tell the card that this port cannot handle any more data for now */
  	card->port_status &= ~(1 << port->channel);
  	outw(card->port_status, card->base + 0x02);
  }
  
  /* unthrottle et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1198
  static void isicom_unthrottle(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1200
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1201
  	struct isi_board *card = port->card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202
1203
  	if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1204

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
1207
1208
1209
1210
  	/* tell the card that this port is ready to accept more data */
  	card->port_status |= (1 << port->channel);
  	outw(card->port_status, card->base + 0x02);
  }
  
  /* stop et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1211
  static void isicom_stop(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1212
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1213
  	struct isi_port *port = tty->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
1216
  
  	if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1217

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
1219
1220
1221
1222
1223
  	/* this tells the transmitter not to consider this port for
  	   data output to the card. */
  	port->status &= ~ISI_TXOK;
  }
  
  /* start et all */
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1224
  static void isicom_start(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1226
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1227

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
1229
  	if (isicom_paranoia_check(port, tty->name, "isicom_start"))
  		return;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1230

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1231
1232
1233
1234
  	/* this tells the transmitter to consider this port for
  	   data output to the card. */
  	port->status |= ISI_TXOK;
  }
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1235
  static void isicom_hangup(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  {
8070e35c6   Jiri Slaby   [PATCH] char/isic...
1237
  	struct isi_port *port = tty->driver_data;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1238

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
1240
  	if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
  		return;
3e61696bd   Alan Cox   isicom: redo lock...
1241
  	tty_port_hangup(&port->port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1242
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243

9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1244
1245
1246
  /*
   * Driver init and deinit functions
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247

b68e31d0e   Jeff Dike   [PATCH] const str...
1248
  static const struct tty_operations isicom_ops = {
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1249
1250
1251
1252
1253
1254
  	.open			= isicom_open,
  	.close			= isicom_close,
  	.write			= isicom_write,
  	.put_char		= isicom_put_char,
  	.flush_chars		= isicom_flush_chars,
  	.write_room		= isicom_write_room,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1255
  	.chars_in_buffer	= isicom_chars_in_buffer,
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
  	.ioctl			= isicom_ioctl,
  	.set_termios		= isicom_set_termios,
  	.throttle		= isicom_throttle,
  	.unthrottle		= isicom_unthrottle,
  	.stop			= isicom_stop,
  	.start			= isicom_start,
  	.hangup			= isicom_hangup,
  	.flush_buffer		= isicom_flush_buffer,
  	.tiocmget		= isicom_tiocmget,
  	.tiocmset		= isicom_tiocmset,
6d8897243   Alan Cox   isicom: restore u...
1266
  	.break_ctl		= isicom_send_break,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
  };
31f35939d   Alan Cox   tty_port: Add a p...
1268
1269
  static const struct tty_port_operations isicom_port_ops = {
  	.carrier_raised		= isicom_carrier_raised,
fcc8ac182   Alan Cox   tty: Add carrier ...
1270
  	.dtr_rts		= isicom_dtr_rts,
baaa08acb   Alan Cox   tty: isicom: swit...
1271
1272
  	.activate		= isicom_activate,
  	.shutdown		= isicom_shutdown,
31f35939d   Alan Cox   tty_port: Add a p...
1273
  };
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1274
1275
  static int __devinit reset_card(struct pci_dev *pdev,
  	const unsigned int card, unsigned int *signature)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276
  {
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1277
1278
  	struct isi_board *board = pci_get_drvdata(pdev);
  	unsigned long base = board->base;
f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1279
  	unsigned int sig, portcount = 0;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1280
  	int retval = 0;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1281

9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1282
1283
1284
  	dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx
  ", card + 1,
  		base);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1285

9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1286
  	inw(base + 0x8);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1287

f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1288
  	msleep(10);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1289
1290
  
  	outw(0, base + 0x8); /* Reset */
f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1291
  	msleep(1000);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1292

f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
  	sig = inw(base + 0x4) & 0xff;
  
  	if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
  			sig != 0xee) {
  		dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
  			"bad I/O Port Address 0x%lx).
  ", card + 1, base);
  		dev_dbg(&pdev->dev, "Sig=0x%x
  ", sig);
  		retval = -EIO;
  		goto end;
  	}
  
  	msleep(10);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1307

18234f88b   Jiri Slaby   [PATCH] Char: isi...
1308
  	portcount = inw(base + 0x2);
07fb6f26b   Julia Lawall   drivers/char/isic...
1309
  	if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 &&
f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1310
  				portcount != 8 && portcount != 16)) {
898eb71cb   Joe Perches   Add missing newli...
1311
1312
  		dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.
  ",
f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1313
  			card + 1);
18234f88b   Jiri Slaby   [PATCH] Char: isi...
1314
1315
  		retval = -EIO;
  		goto end;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1316
  	}
f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1317
  	switch (sig) {
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1318
1319
1320
  	case 0xa5:
  	case 0xbb:
  	case 0xdd:
18234f88b   Jiri Slaby   [PATCH] Char: isi...
1321
  		board->port_count = (portcount == 4) ? 4 : 8;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1322
1323
1324
  		board->shift_count = 12;
  		break;
  	case 0xcc:
f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1325
  	case 0xee:
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1326
1327
1328
  		board->port_count = 16;
  		board->shift_count = 11;
  		break;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1329
  	}
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1330
1331
  	dev_info(&pdev->dev, "-Done
  ");
f0a0ba6d6   Jiri Slaby   [PATCH] Char: isi...
1332
  	*signature = sig;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1333

9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1334
1335
  end:
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
  }
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
  static int __devinit load_firmware(struct pci_dev *pdev,
  	const unsigned int index, const unsigned int signature)
  {
  	struct isi_board *board = pci_get_drvdata(pdev);
  	const struct firmware *fw;
  	unsigned long base = board->base;
  	unsigned int a;
  	u16 word_count, status;
  	int retval = -EIO;
  	char *name;
  	u8 *data;
  
  	struct stframe {
  		u16	addr;
  		u16	count;
  		u8	data[0];
  	} *frame;
  
  	switch (signature) {
  	case 0xa5:
  		name = "isi608.bin";
  		break;
  	case 0xbb:
  		name = "isi608em.bin";
  		break;
  	case 0xcc:
  		name = "isi616em.bin";
  		break;
  	case 0xdd:
  		name = "isi4608.bin";
  		break;
  	case 0xee:
  		name = "isi4616.bin";
  		break;
  	default:
  		dev_err(&pdev->dev, "Unknown signature.
  ");
  		goto end;
251b8dd7e   Alan Cox   isicom: bring int...
1375
  	}
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1376
1377
1378
1379
  
  	retval = request_firmware(&fw, name, &pdev->dev);
  	if (retval)
  		goto end;
e4e040887   Jiri Slaby   [PATCH] isicom: c...
1380
  	retval = -EIO;
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1381
1382
  	for (frame = (struct stframe *)fw->data;
  			frame < (struct stframe *)(fw->data + fw->size);
e4e040887   Jiri Slaby   [PATCH] isicom: c...
1383
1384
  			frame = (struct stframe *)((u8 *)(frame + 1) +
  				frame->count)) {
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
  		if (WaitTillCardIsFree(base))
  			goto errrelfw;
  
  		outw(0xf0, base);	/* start upload sequence */
  		outw(0x00, base);
  		outw(frame->addr, base); /* lsb of address */
  
  		word_count = frame->count / 2 + frame->count % 2;
  		outw(word_count, base);
  		InterruptTheCard(base);
  
  		udelay(100); /* 0x2f */
  
  		if (WaitTillCardIsFree(base))
  			goto errrelfw;
251b8dd7e   Alan Cox   isicom: bring int...
1400
1401
  		status = inw(base + 0x4);
  		if (status != 0) {
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1402
1403
  			dev_warn(&pdev->dev, "Card%d rejected load header:
  "
ad361c988   Joe Perches   Remove multiple K...
1404
1405
1406
1407
1408
1409
1410
  				 "Address:0x%x
  "
  				 "Count:0x%x
  "
  				 "Status:0x%x
  ",
  				 index + 1, frame->addr, frame->count, status);
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
  			goto errrelfw;
  		}
  		outsw(base, frame->data, word_count);
  
  		InterruptTheCard(base);
  
  		udelay(50); /* 0x0f */
  
  		if (WaitTillCardIsFree(base))
  			goto errrelfw;
251b8dd7e   Alan Cox   isicom: bring int...
1421
1422
  		status = inw(base + 0x4);
  		if (status != 0) {
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1423
1424
1425
1426
1427
  			dev_err(&pdev->dev, "Card%d got out of sync.Card "
  				"Status:0x%x
  ", index + 1, status);
  			goto errrelfw;
  		}
251b8dd7e   Alan Cox   isicom: bring int...
1428
  	}
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1429

e65c1db19   Jiri Slaby   [PATCH] char/isic...
1430
1431
  /* XXX: should we test it by reading it back and comparing with original like
   * in load firmware package? */
e4e040887   Jiri Slaby   [PATCH] isicom: c...
1432
1433
1434
1435
  	for (frame = (struct stframe *)fw->data;
  			frame < (struct stframe *)(fw->data + fw->size);
  			frame = (struct stframe *)((u8 *)(frame + 1) +
  				frame->count)) {
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
  		if (WaitTillCardIsFree(base))
  			goto errrelfw;
  
  		outw(0xf1, base); /* start download sequence */
  		outw(0x00, base);
  		outw(frame->addr, base); /* lsb of address */
  
  		word_count = (frame->count >> 1) + frame->count % 2;
  		outw(word_count + 1, base);
  		InterruptTheCard(base);
  
  		udelay(50); /* 0xf */
  
  		if (WaitTillCardIsFree(base))
  			goto errrelfw;
251b8dd7e   Alan Cox   isicom: bring int...
1451
1452
  		status = inw(base + 0x4);
  		if (status != 0) {
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1453
1454
  			dev_warn(&pdev->dev, "Card%d rejected verify header:
  "
ad361c988   Joe Perches   Remove multiple K...
1455
1456
1457
1458
1459
1460
1461
  				 "Address:0x%x
  "
  				 "Count:0x%x
  "
  				 "Status: 0x%x
  ",
  				 index + 1, frame->addr, frame->count, status);
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1462
1463
1464
1465
  			goto errrelfw;
  		}
  
  		data = kmalloc(word_count * 2, GFP_KERNEL);
f06713784   Jiri Slaby   [PATCH] Char: isi...
1466
1467
1468
1469
1470
1471
  		if (data == NULL) {
  			dev_err(&pdev->dev, "Card%d, firmware upload "
  				"failed, not enough memory
  ", index + 1);
  			goto errrelfw;
  		}
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
  		inw(base);
  		insw(base, data, word_count);
  		InterruptTheCard(base);
  
  		for (a = 0; a < frame->count; a++)
  			if (data[a] != frame->data[a]) {
  				kfree(data);
  				dev_err(&pdev->dev, "Card%d, firmware upload "
  					"failed
  ", index + 1);
  				goto errrelfw;
  			}
  		kfree(data);
  
  		udelay(50); /* 0xf */
  
  		if (WaitTillCardIsFree(base))
  			goto errrelfw;
251b8dd7e   Alan Cox   isicom: bring int...
1490
1491
  		status = inw(base + 0x4);
  		if (status != 0) {
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1492
1493
1494
1495
1496
1497
  			dev_err(&pdev->dev, "Card%d verify got out of sync. "
  				"Card Status:0x%x
  ", index + 1, status);
  			goto errrelfw;
  		}
  	}
e4e040887   Jiri Slaby   [PATCH] isicom: c...
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
  	/* xfer ctrl */
  	if (WaitTillCardIsFree(base))
  		goto errrelfw;
  
  	outw(0xf2, base);
  	outw(0x800, base);
  	outw(0x0, base);
  	outw(0x0, base);
  	InterruptTheCard(base);
  	outw(0x0, base + 0x4); /* for ISI4608 cards */
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1508
1509
1510
1511
1512
1513
1514
1515
  	board->status |= FIRMWARE_LOADED;
  	retval = 0;
  
  errrelfw:
  	release_firmware(fw);
  end:
  	return retval;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1516
1517
1518
  /*
   *	Insmod can set static symbols so keep these static
   */
1ed0c0b73   Jiri Slaby   [PATCH] Char: isi...
1519
  static unsigned int card_count;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1520
1521
1522
1523
  
  static int __devinit isicom_probe(struct pci_dev *pdev,
  	const struct pci_device_id *ent)
  {
9653a69e9   Jiri Slaby   Char: isicom: fix...
1524
  	unsigned int uninitialized_var(signature), index;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1525
  	int retval = -EPERM;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1526
  	struct isi_board *board = NULL;
1ed0c0b73   Jiri Slaby   [PATCH] Char: isi...
1527
  	if (card_count >= BOARD_COUNT)
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1528
  		goto err;
e1e5770bb   Jiri Slaby   tty: isicom, enab...
1529
1530
1531
1532
1533
1534
  	retval = pci_enable_device(pdev);
  	if (retval) {
  		dev_err(&pdev->dev, "failed to enable
  ");
  		goto err;
  	}
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1535
1536
1537
1538
  	dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)
  ", ent->device);
  
  	/* allot the first empty slot in the array */
26e1e8d1d   Dan Carpenter   serial: isicomm: ...
1539
  	for (index = 0; index < BOARD_COUNT; index++) {
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1540
1541
1542
1543
  		if (isi_card[index].base == 0) {
  			board = &isi_card[index];
  			break;
  		}
26e1e8d1d   Dan Carpenter   serial: isicomm: ...
1544
1545
1546
1547
1548
  	}
  	if (index == BOARD_COUNT) {
  		retval = -ENODEV;
  		goto err_disable;
  	}
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1549

938a7023b   Jiri Slaby   [PATCH] Char: isi...
1550
  	board->index = index;
4969b3a43   Jiri Slaby   Char: isicom, pro...
1551
1552
  	board->base = pci_resource_start(pdev, 3);
  	board->irq = pdev->irq;
1ed0c0b73   Jiri Slaby   [PATCH] Char: isi...
1553
  	card_count++;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1554
1555
  
  	pci_set_drvdata(pdev, board);
78028da91   Jiri Slaby   [PATCH] Char: isi...
1556
1557
  	retval = pci_request_region(pdev, 3, ISICOM_NAME);
  	if (retval) {
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1558
1559
1560
1561
1562
  		dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
  			"will be disabled.
  ", board->base, board->base + 15,
  			index + 1);
  		retval = -EBUSY;
1ed0c0b73   Jiri Slaby   [PATCH] Char: isi...
1563
  		goto errdec;
251b8dd7e   Alan Cox   isicom: bring int...
1564
  	}
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1565

09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1566
  	retval = request_irq(board->irq, isicom_interrupt,
9cfb5c05f   Yong Zhang   TTY: irq: Remove ...
1567
  			IRQF_SHARED, ISICOM_NAME, board);
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1568
1569
1570
1571
  	if (retval < 0) {
  		dev_err(&pdev->dev, "Could not install handler at Irq %d. "
  			"Card%d will be disabled.
  ", board->irq, index + 1);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1572
  		goto errunrr;
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1573
  	}
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1574
1575
1576
1577
  
  	retval = reset_card(pdev, index, &signature);
  	if (retval < 0)
  		goto errunri;
e65c1db19   Jiri Slaby   [PATCH] char/isic...
1578
1579
1580
  	retval = load_firmware(pdev, index, signature);
  	if (retval < 0)
  		goto errunri;
938a7023b   Jiri Slaby   [PATCH] Char: isi...
1581
1582
1583
  	for (index = 0; index < board->port_count; index++)
  		tty_register_device(isicom_normal, board->index * 16 + index,
  				&pdev->dev);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1584
1585
1586
1587
1588
  	return 0;
  
  errunri:
  	free_irq(board->irq, board);
  errunrr:
78028da91   Jiri Slaby   [PATCH] Char: isi...
1589
  	pci_release_region(pdev, 3);
1ed0c0b73   Jiri Slaby   [PATCH] Char: isi...
1590
  errdec:
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1591
  	board->base = 0;
1ed0c0b73   Jiri Slaby   [PATCH] Char: isi...
1592
  	card_count--;
26e1e8d1d   Dan Carpenter   serial: isicomm: ...
1593
  err_disable:
e1e5770bb   Jiri Slaby   tty: isicom, enab...
1594
  	pci_disable_device(pdev);
1ed0c0b73   Jiri Slaby   [PATCH] Char: isi...
1595
  err:
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1596
1597
1598
1599
1600
1601
  	return retval;
  }
  
  static void __devexit isicom_remove(struct pci_dev *pdev)
  {
  	struct isi_board *board = pci_get_drvdata(pdev);
938a7023b   Jiri Slaby   [PATCH] Char: isi...
1602
1603
1604
1605
  	unsigned int i;
  
  	for (i = 0; i < board->port_count; i++)
  		tty_unregister_device(isicom_normal, board->index * 16 + i);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1606
1607
  
  	free_irq(board->irq, board);
78028da91   Jiri Slaby   [PATCH] Char: isi...
1608
  	pci_release_region(pdev, 3);
1ed0c0b73   Jiri Slaby   [PATCH] Char: isi...
1609
1610
  	board->base = 0;
  	card_count--;
e1e5770bb   Jiri Slaby   tty: isicom, enab...
1611
  	pci_disable_device(pdev);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1612
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1613

ca2620051   Jiri Slaby   [PATCH] Char: isi...
1614
  static int __init isicom_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
  {
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1616
1617
  	int retval, idx, channel;
  	struct isi_port *port;
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1618

251b8dd7e   Alan Cox   isicom: bring int...
1619
  	for (idx = 0; idx < BOARD_COUNT; idx++) {
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1620
1621
1622
1623
  		port = &isi_ports[idx * 16];
  		isi_card[idx].ports = port;
  		spin_lock_init(&isi_card[idx].card_lock);
  		for (channel = 0; channel < 16; channel++, port++) {
44b7d1b37   Alan Cox   tty: add more tty...
1624
  			tty_port_init(&port->port);
31f35939d   Alan Cox   tty_port: Add a p...
1625
  			port->port.ops = &isicom_port_ops;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1626
1627
1628
  			port->magic = ISICOM_MAGIC;
  			port->card = &isi_card[idx];
  			port->channel = channel;
44b7d1b37   Alan Cox   tty: add more tty...
1629
1630
  			port->port.close_delay = 50 * HZ/100;
  			port->port.closing_wait = 3000 * HZ/100;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1631
  			port->status = 0;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1632
  			/*  . . .  */
251b8dd7e   Alan Cox   isicom: bring int...
1633
  		}
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1634
1635
  		isi_card[idx].base = 0;
  		isi_card[idx].irq = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1636
  	}
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1637

09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1638
1639
1640
1641
  	/* tty driver structure initialization */
  	isicom_normal = alloc_tty_driver(PORT_COUNT);
  	if (!isicom_normal) {
  		retval = -ENOMEM;
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1642
  		goto error;
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
  	}
  
  	isicom_normal->owner			= THIS_MODULE;
  	isicom_normal->name 			= "ttyM";
  	isicom_normal->major			= ISICOM_NMAJOR;
  	isicom_normal->minor_start		= 0;
  	isicom_normal->type			= TTY_DRIVER_TYPE_SERIAL;
  	isicom_normal->subtype			= SERIAL_TYPE_NORMAL;
  	isicom_normal->init_termios		= tty_std_termios;
  	isicom_normal->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL |
  		CLOCAL;
938a7023b   Jiri Slaby   [PATCH] Char: isi...
1654
  	isicom_normal->flags			= TTY_DRIVER_REAL_RAW |
6d8897243   Alan Cox   isicom: restore u...
1655
  		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1656
1657
1658
1659
  	tty_set_operations(isicom_normal, &isicom_ops);
  
  	retval = tty_register_driver(isicom_normal);
  	if (retval) {
db91340b2   Joe Perches   serial: isicom.c:...
1660
1661
  		pr_debug("Couldn't register the dialin driver
  ");
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1662
1663
  		goto err_puttty;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664

9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1665
  	retval = pci_register_driver(&isicom_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1666
  	if (retval < 0) {
db91340b2   Joe Perches   serial: isicom.c:...
1667
1668
  		pr_err("Unable to register pci driver.
  ");
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1669
  		goto err_unrtty;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
  	}
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1671

34b55b865   Jiri Slaby   [PATCH] Char: isi...
1672
  	mod_timer(&tx, jiffies + 1);
d8d16e474   Jiri Slaby   [PATCH] char/isic...
1673

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
  	return 0;
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1675
1676
1677
1678
  err_unrtty:
  	tty_unregister_driver(isicom_normal);
  err_puttty:
  	put_tty_driver(isicom_normal);
9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1679
1680
  error:
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1681
1682
1683
1684
  }
  
  static void __exit isicom_exit(void)
  {
e327325f4   Jiri Slaby   Char: isicom, del...
1685
  	del_timer_sync(&tx);
aaa246ea7   Jiri Slaby   [PATCH] char/isic...
1686

9ac0948b2   Jiri Slaby   [PATCH] char/isic...
1687
  	pci_unregister_driver(&isicom_driver);
09a4a1125   Jiri Slaby   [PATCH] Char: isi...
1688
1689
  	tty_unregister_driver(isicom_normal);
  	put_tty_driver(isicom_normal);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690
  }
ca2620051   Jiri Slaby   [PATCH] Char: isi...
1691
  module_init(isicom_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
  module_exit(isicom_exit);
aaa246ea7   Jiri Slaby   [PATCH] char/isic...
1693
1694
1695
1696
  
  MODULE_AUTHOR("MultiTech");
  MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
  MODULE_LICENSE("GPL");
e6c4ef984   Ben Hutchings   tty: declare MODU...
1697
1698
1699
1700
1701
  MODULE_FIRMWARE("isi608.bin");
  MODULE_FIRMWARE("isi608em.bin");
  MODULE_FIRMWARE("isi616em.bin");
  MODULE_FIRMWARE("isi4608.bin");
  MODULE_FIRMWARE("isi4616.bin");