]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/char/isicom.c
tty: USB does not need the filp argument in the drivers
[mirror_ubuntu-zesty-kernel.git] / drivers / char / isicom.c
CommitLineData
1da177e4
LT
1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version
5 * 2 of the License, or (at your option) any later version.
6 *
7 * Original driver code supplied by Multi-Tech
8 *
9 * Changes
8eb04cf3
AC
10 * 1/9/98 alan@lxorguk.ukuu.org.uk
11 * Merge to 2.0.x kernel tree
1da177e4
LT
12 * Obtain and use official major/minors
13 * Loader switched to a misc device
14 * (fixed range check bug as a side effect)
15 * Printk clean up
8eb04cf3
AC
16 * 9/12/98 alan@lxorguk.ukuu.org.uk
17 * Rough port to 2.1.x
1da177e4
LT
18 *
19 * 10/6/99 sameer Merged the ISA and PCI drivers to
20 * a new unified driver.
21 *
22 * 3/9/99 sameer Added support for ISI4616 cards.
23 *
24 * 16/9/99 sameer We do not force RTS low anymore.
d8d16e47 25 * This is to prevent the firmware
1da177e4
LT
26 * from getting confused.
27 *
28 * 26/10/99 sameer Cosmetic changes:The driver now
29 * dumps the Port Count information
30 * along with I/O address and IRQ.
31 *
32 * 13/12/99 sameer Fixed the problem with IRQ sharing.
33 *
34 * 10/5/00 sameer Fixed isicom_shutdown_board()
35 * to not lower DTR on all the ports
d8d16e47 36 * when the last port on the card is
1da177e4
LT
37 * closed.
38 *
39 * 10/5/00 sameer Signal mask setup command added
d8d16e47 40 * to isicom_setup_port and
1da177e4
LT
41 * isicom_shutdown_port.
42 *
43 * 24/5/00 sameer The driver is now SMP aware.
d8d16e47
JS
44 *
45 *
1da177e4 46 * 27/11/00 Vinayak P Risbud Fixed the Driver Crash Problem
d8d16e47
JS
47 *
48 *
1da177e4
LT
49 * 03/01/01 anil .s Added support for resetting the
50 * internal modems on ISI cards.
51 *
52 * 08/02/01 anil .s Upgraded the driver for kernel
53 * 2.4.x
54 *
d8d16e47 55 * 11/04/01 Kevin Fixed firmware load problem with
1da177e4 56 * ISIHP-4X card
d8d16e47 57 *
1da177e4
LT
58 * 30/04/01 anil .s Fixed the remote login through
59 * ISI port problem. Now the link
60 * does not go down before password
61 * prompt.
62 *
63 * 03/05/01 anil .s Fixed the problem with IRQ sharing
64 * among ISI-PCI cards.
65 *
66 * 03/05/01 anil .s Added support to display the version
d8d16e47 67 * info during insmod as well as module
1da177e4 68 * listing by lsmod.
d8d16e47 69 *
1da177e4
LT
70 * 10/05/01 anil .s Done the modifications to the source
71 * file and Install script so that the
72 * same installation can be used for
73 * 2.2.x and 2.4.x kernel.
74 *
75 * 06/06/01 anil .s Now we drop both dtr and rts during
76 * shutdown_port as well as raise them
77 * during isicom_config_port.
d8d16e47 78 *
1da177e4
LT
79 * 09/06/01 acme@conectiva.com.br use capable, not suser, do
80 * restore_flags on failure in
81 * isicom_send_break, verify put_user
82 * result
83 *
d8d16e47
JS
84 * 11/02/03 ranjeeth Added support for 230 Kbps and 460 Kbps
85 * Baud index extended to 21
86 *
87 * 20/03/03 ranjeeth Made to work for Linux Advanced server.
88 * Taken care of license warning.
89 *
90 * 10/12/03 Ravindra Made to work for Fedora Core 1 of
1da177e4
LT
91 * Red Hat Distribution
92 *
93 * 06/01/05 Alan Cox Merged the ISI and base kernel strands
94 * into a single 2.6 driver
95 *
96 * ***********************************************************
97 *
d8d16e47 98 * To use this driver you also need the support package. You
1da177e4
LT
99 * can find this in RPM format on
100 * ftp://ftp.linux.org.uk/pub/linux/alan
d8d16e47 101 *
1da177e4
LT
102 * You can find the original tools for this direct from Multitech
103 * ftp://ftp.multitech.com/ISI-Cards/
104 *
105 * Having installed the cards the module options (/etc/modprobe.conf)
106 *
107 * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4
108 *
109 * Omit those entries for boards you don't have installed.
110 *
111 * TODO
1da177e4
LT
112 * Merge testing
113 * 64-bit verification
114 */
115
116#include <linux/module.h>
e65c1db1 117#include <linux/firmware.h>
1da177e4
LT
118#include <linux/kernel.h>
119#include <linux/tty.h>
33f0f88f 120#include <linux/tty_flip.h>
1da177e4
LT
121#include <linux/termios.h>
122#include <linux/fs.h>
123#include <linux/sched.h>
124#include <linux/serial.h>
405f5571 125#include <linux/smp_lock.h>
1da177e4 126#include <linux/mm.h>
1da177e4
LT
127#include <linux/interrupt.h>
128#include <linux/timer.h>
129#include <linux/delay.h>
130#include <linux/ioport.h>
131
251b8dd7
AC
132#include <linux/uaccess.h>
133#include <linux/io.h>
1da177e4
LT
134#include <asm/system.h>
135
136#include <linux/pci.h>
137
138#include <linux/isicom.h>
139
aaa246ea
JS
140#define InterruptTheCard(base) outw(0, (base) + 0xc)
141#define ClearInterrupt(base) inw((base) + 0x0a)
142
73b52572 143#define pr_dbg(str...) pr_debug("ISICOM: " str)
aaa246ea 144#ifdef DEBUG
aaa246ea
JS
145#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
146#else
aaa246ea
JS
147#define isicom_paranoia_check(a, b, c) 0
148#endif
149
9ac0948b
JS
150static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
151static void __devexit isicom_remove(struct pci_dev *);
152
1da177e4 153static struct pci_device_id isicom_pci_tbl[] = {
9ac0948b
JS
154 { PCI_DEVICE(VENDOR_ID, 0x2028) },
155 { PCI_DEVICE(VENDOR_ID, 0x2051) },
156 { PCI_DEVICE(VENDOR_ID, 0x2052) },
157 { PCI_DEVICE(VENDOR_ID, 0x2053) },
158 { PCI_DEVICE(VENDOR_ID, 0x2054) },
159 { PCI_DEVICE(VENDOR_ID, 0x2055) },
160 { PCI_DEVICE(VENDOR_ID, 0x2056) },
161 { PCI_DEVICE(VENDOR_ID, 0x2057) },
162 { PCI_DEVICE(VENDOR_ID, 0x2058) },
1da177e4
LT
163 { 0 }
164};
165MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
166
9ac0948b
JS
167static struct pci_driver isicom_driver = {
168 .name = "isicom",
169 .id_table = isicom_pci_tbl,
170 .probe = isicom_probe,
171 .remove = __devexit_p(isicom_remove)
172};
173
1da177e4
LT
174static int prev_card = 3; /* start servicing isi_card[0] */
175static struct tty_driver *isicom_normal;
176
1da177e4 177static void isicom_tx(unsigned long _data);
d8d16e47 178static void isicom_start(struct tty_struct *tty);
1da177e4 179
34b55b86
JS
180static DEFINE_TIMER(tx, isicom_tx, 0, 0);
181
1da177e4
LT
182/* baud index mappings from linux defns to isi */
183
184static signed char linuxb_to_isib[] = {
7edc136a 185 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
1da177e4
LT
186};
187
188struct isi_board {
8070e35c 189 unsigned long base;
4969b3a4 190 int irq;
1da177e4
LT
191 unsigned char port_count;
192 unsigned short status;
a547dfe9 193 unsigned short port_status; /* each bit for each port */
1da177e4 194 unsigned short shift_count;
251b8dd7 195 struct isi_port *ports;
1da177e4 196 signed char count;
1da177e4
LT
197 spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */
198 unsigned long flags;
938a7023 199 unsigned int index;
1da177e4
LT
200};
201
202struct isi_port {
203 unsigned short magic;
f1d03228 204 struct tty_port port;
8070e35c
JS
205 u16 channel;
206 u16 status;
251b8dd7 207 struct isi_board *card;
251b8dd7 208 unsigned char *xmit_buf;
1da177e4
LT
209 int xmit_head;
210 int xmit_tail;
211 int xmit_cnt;
212};
213
214static struct isi_board isi_card[BOARD_COUNT];
215static struct isi_port isi_ports[PORT_COUNT];
216
217/*
218 * Locking functions for card level locking. We need to own both
219 * the kernel lock for the card and have the card in a position that
220 * it wants to talk.
221 */
d8d16e47 222
4969b3a4 223static inline int WaitTillCardIsFree(unsigned long base)
cfe7c09a
JS
224{
225 unsigned int count = 0;
226 unsigned int a = in_atomic(); /* do we run under spinlock? */
227
228 while (!(inw(base + 0xe) & 0x1) && count++ < 100)
229 if (a)
230 mdelay(1);
231 else
232 msleep(1);
233
234 return !(inw(base + 0xe) & 0x1);
235}
236
1da177e4
LT
237static int lock_card(struct isi_board *card)
238{
8070e35c 239 unsigned long base = card->base;
5b21f9dd 240 unsigned int retries, a;
1da177e4 241
5b21f9dd 242 for (retries = 0; retries < 10; retries++) {
1da177e4 243 spin_lock_irqsave(&card->card_lock, card->flags);
5b21f9dd
JS
244 for (a = 0; a < 10; a++) {
245 if (inw(base + 0xe) & 0x1)
246 return 1;
247 udelay(10);
1da177e4 248 }
5b21f9dd
JS
249 spin_unlock_irqrestore(&card->card_lock, card->flags);
250 msleep(10);
1da177e4 251 }
a547dfe9
JS
252 printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
253 card->base);
254
0418726b 255 return 0; /* Failed to acquire the card! */
1da177e4
LT
256}
257
1da177e4
LT
258static void unlock_card(struct isi_board *card)
259{
260 spin_unlock_irqrestore(&card->card_lock, card->flags);
261}
262
263/*
264 * ISI Card specific ops ...
265 */
d8d16e47 266
cfe7c09a 267/* card->lock HAS to be held */
d8d16e47 268static void raise_dtr(struct isi_port *port)
1da177e4 269{
d8d16e47 270 struct isi_board *card = port->card;
8070e35c
JS
271 unsigned long base = card->base;
272 u16 channel = port->channel;
1da177e4 273
cfe7c09a 274 if (WaitTillCardIsFree(base))
1da177e4
LT
275 return;
276
d8d16e47 277 outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4
LT
278 outw(0x0504, base);
279 InterruptTheCard(base);
280 port->status |= ISI_DTR;
1da177e4
LT
281}
282
cfe7c09a 283/* card->lock HAS to be held */
d8d16e47
JS
284static inline void drop_dtr(struct isi_port *port)
285{
286 struct isi_board *card = port->card;
8070e35c
JS
287 unsigned long base = card->base;
288 u16 channel = port->channel;
1da177e4 289
cfe7c09a 290 if (WaitTillCardIsFree(base))
1da177e4
LT
291 return;
292
d8d16e47 293 outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4 294 outw(0x0404, base);
d8d16e47 295 InterruptTheCard(base);
1da177e4 296 port->status &= ~ISI_DTR;
1da177e4
LT
297}
298
cfe7c09a 299/* card->lock HAS to be held */
d8d16e47 300static inline void raise_rts(struct isi_port *port)
1da177e4 301{
d8d16e47 302 struct isi_board *card = port->card;
8070e35c
JS
303 unsigned long base = card->base;
304 u16 channel = port->channel;
1da177e4 305
cfe7c09a 306 if (WaitTillCardIsFree(base))
1da177e4
LT
307 return;
308
d8d16e47 309 outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4 310 outw(0x0a04, base);
d8d16e47 311 InterruptTheCard(base);
1da177e4 312 port->status |= ISI_RTS;
1da177e4 313}
cfe7c09a
JS
314
315/* card->lock HAS to be held */
d8d16e47 316static inline void drop_rts(struct isi_port *port)
1da177e4 317{
d8d16e47 318 struct isi_board *card = port->card;
8070e35c
JS
319 unsigned long base = card->base;
320 u16 channel = port->channel;
1da177e4 321
cfe7c09a 322 if (WaitTillCardIsFree(base))
1da177e4
LT
323 return;
324
d8d16e47 325 outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4 326 outw(0x0804, base);
d8d16e47 327 InterruptTheCard(base);
1da177e4 328 port->status &= ~ISI_RTS;
1da177e4
LT
329}
330
cfe7c09a 331/* card->lock MUST NOT be held */
5d951fb4 332
fcc8ac18 333static void isicom_dtr_rts(struct tty_port *port, int on)
1da177e4 334{
5d951fb4
AC
335 struct isi_port *ip = container_of(port, struct isi_port, port);
336 struct isi_board *card = ip->card;
8070e35c 337 unsigned long base = card->base;
5d951fb4 338 u16 channel = ip->channel;
1da177e4
LT
339
340 if (!lock_card(card))
341 return;
342
fcc8ac18
AC
343 if (on) {
344 outw(0x8000 | (channel << card->shift_count) | 0x02, base);
345 outw(0x0f04, base);
346 InterruptTheCard(base);
347 ip->status |= (ISI_DTR | ISI_RTS);
348 } else {
349 outw(0x8000 | (channel << card->shift_count) | 0x02, base);
350 outw(0x0C04, base);
351 InterruptTheCard(base);
352 ip->status &= ~(ISI_DTR | ISI_RTS);
353 }
1da177e4
LT
354 unlock_card(card);
355}
356
cfe7c09a 357/* card->lock HAS to be held */
d8d16e47 358static void drop_dtr_rts(struct isi_port *port)
1da177e4 359{
d8d16e47 360 struct isi_board *card = port->card;
8070e35c
JS
361 unsigned long base = card->base;
362 u16 channel = port->channel;
1da177e4 363
cfe7c09a 364 if (WaitTillCardIsFree(base))
1da177e4
LT
365 return;
366
d8d16e47 367 outw(0x8000 | (channel << card->shift_count) | 0x02, base);
1da177e4 368 outw(0x0c04, base);
d8d16e47 369 InterruptTheCard(base);
1da177e4 370 port->status &= ~(ISI_RTS | ISI_DTR);
1da177e4
LT
371}
372
1da177e4
LT
373/*
374 * ISICOM Driver specific routines ...
375 *
376 */
d8d16e47 377
aaa246ea
JS
378static inline int __isicom_paranoia_check(struct isi_port const *port,
379 char *name, const char *routine)
1da177e4 380{
1da177e4 381 if (!port) {
aaa246ea
JS
382 printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
383 "dev %s in %s.\n", name, routine);
1da177e4
LT
384 return 1;
385 }
386 if (port->magic != ISICOM_MAGIC) {
aaa246ea
JS
387 printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
388 "dev %s in %s.\n", name, routine);
1da177e4 389 return 1;
d8d16e47 390 }
aaa246ea 391
1da177e4
LT
392 return 0;
393}
d8d16e47 394
1da177e4 395/*
d8d16e47 396 * Transmitter.
1da177e4
LT
397 *
398 * We shovel data into the card buffers on a regular basis. The card
399 * will do the rest of the work for us.
400 */
401
402static void isicom_tx(unsigned long _data)
403{
4969b3a4 404 unsigned long flags, base;
5b21f9dd 405 unsigned int retries;
4969b3a4 406 short count = (BOARD_COUNT-1), card;
1da177e4 407 short txcount, wrd, residue, word_count, cnt;
d8d16e47
JS
408 struct isi_port *port;
409 struct tty_struct *tty;
410
1da177e4
LT
411 /* find next active board */
412 card = (prev_card + 1) & 0x0003;
251b8dd7 413 while (count-- > 0) {
d8d16e47 414 if (isi_card[card].status & BOARD_ACTIVE)
1da177e4 415 break;
d8d16e47 416 card = (card + 1) & 0x0003;
1da177e4
LT
417 }
418 if (!(isi_card[card].status & BOARD_ACTIVE))
419 goto sched_again;
d8d16e47 420
1da177e4 421 prev_card = card;
d8d16e47 422
1da177e4
LT
423 count = isi_card[card].port_count;
424 port = isi_card[card].ports;
425 base = isi_card[card].base;
5b21f9dd
JS
426
427 spin_lock_irqsave(&isi_card[card].card_lock, flags);
428 for (retries = 0; retries < 100; retries++) {
429 if (inw(base + 0xe) & 0x1)
430 break;
431 udelay(2);
432 }
433 if (retries >= 100)
434 goto unlock;
435
d450b5a0
AC
436 tty = tty_port_tty_get(&port->port);
437 if (tty == NULL)
438 goto put_unlock;
439
251b8dd7 440 for (; count > 0; count--, port++) {
1da177e4 441 /* port not active or tx disabled to force flow control */
f1d03228 442 if (!(port->port.flags & ASYNC_INITIALIZED) ||
d8d16e47 443 !(port->status & ISI_TXOK))
1da177e4 444 continue;
d8d16e47 445
1da177e4 446 txcount = min_t(short, TX_SIZE, port->xmit_cnt);
5b21f9dd 447 if (txcount <= 0 || tty->stopped || tty->hw_stopped)
1da177e4 448 continue;
5b21f9dd
JS
449
450 if (!(inw(base + 0x02) & (1 << port->channel)))
d8d16e47 451 continue;
5b21f9dd 452
aaa246ea
JS
453 pr_dbg("txing %d bytes, port%d.\n", txcount,
454 port->channel + 1);
455 outw((port->channel << isi_card[card].shift_count) | txcount,
456 base);
1da177e4 457 residue = NO;
d8d16e47 458 wrd = 0;
1da177e4 459 while (1) {
a547dfe9
JS
460 cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
461 - port->xmit_tail));
1da177e4
LT
462 if (residue == YES) {
463 residue = NO;
464 if (cnt > 0) {
f1d03228 465 wrd |= (port->port.xmit_buf[port->xmit_tail]
a547dfe9
JS
466 << 8);
467 port->xmit_tail = (port->xmit_tail + 1)
468 & (SERIAL_XMIT_SIZE - 1);
1da177e4
LT
469 port->xmit_cnt--;
470 txcount--;
471 cnt--;
d8d16e47 472 outw(wrd, base);
a547dfe9 473 } else {
1da177e4
LT
474 outw(wrd, base);
475 break;
476 }
d8d16e47 477 }
251b8dd7
AC
478 if (cnt <= 0)
479 break;
1da177e4 480 word_count = cnt >> 1;
f1d03228 481 outsw(base, port->port.xmit_buf+port->xmit_tail, word_count);
a547dfe9
JS
482 port->xmit_tail = (port->xmit_tail
483 + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
1da177e4
LT
484 txcount -= (word_count << 1);
485 port->xmit_cnt -= (word_count << 1);
486 if (cnt & 0x0001) {
487 residue = YES;
f1d03228 488 wrd = port->port.xmit_buf[port->xmit_tail];
a547dfe9
JS
489 port->xmit_tail = (port->xmit_tail + 1)
490 & (SERIAL_XMIT_SIZE - 1);
1da177e4
LT
491 port->xmit_cnt--;
492 txcount--;
493 }
494 }
495
496 InterruptTheCard(base);
497 if (port->xmit_cnt <= 0)
498 port->status &= ~ISI_TXOK;
499 if (port->xmit_cnt <= WAKEUP_CHARS)
0aa5de85 500 tty_wakeup(tty);
d8d16e47 501 }
1da177e4 502
d450b5a0
AC
503put_unlock:
504 tty_kref_put(tty);
5b21f9dd
JS
505unlock:
506 spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
d8d16e47
JS
507 /* schedule another tx for hopefully in about 10ms */
508sched_again:
34b55b86 509 mod_timer(&tx, jiffies + msecs_to_jiffies(10));
d8d16e47
JS
510}
511
1da177e4 512/*
d8d16e47 513 * Main interrupt handler routine
1da177e4 514 */
d8d16e47 515
7d12e780 516static irqreturn_t isicom_interrupt(int irq, void *dev_id)
1da177e4 517{
8070e35c 518 struct isi_board *card = dev_id;
d8d16e47
JS
519 struct isi_port *port;
520 struct tty_struct *tty;
8070e35c
JS
521 unsigned long base;
522 u16 header, word_count, count, channel;
1da177e4 523 short byte_count;
33f0f88f 524 unsigned char *rp;
d8d16e47 525
1da177e4
LT
526 if (!card || !(card->status & FIRMWARE_LOADED))
527 return IRQ_NONE;
d8d16e47 528
1da177e4 529 base = card->base;
cb4a10cc
JS
530
531 /* did the card interrupt us? */
532 if (!(inw(base + 0x0e) & 0x02))
533 return IRQ_NONE;
534
1da177e4 535 spin_lock(&card->card_lock);
d8d16e47 536
18234f88
JS
537 /*
538 * disable any interrupts from the PCI card and lower the
539 * interrupt line
540 */
541 outw(0x8000, base+0x04);
542 ClearInterrupt(base);
d8d16e47 543
1da177e4
LT
544 inw(base); /* get the dummy word out */
545 header = inw(base);
546 channel = (header & 0x7800) >> card->shift_count;
547 byte_count = header & 0xff;
548
549 if (channel + 1 > card->port_count) {
a547dfe9
JS
550 printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
551 "%d(channel) > port_count.\n", base, channel+1);
18234f88 552 outw(0x0000, base+0x04); /* enable interrupts */
1da177e4 553 spin_unlock(&card->card_lock);
d8d16e47 554 return IRQ_HANDLED;
1da177e4
LT
555 }
556 port = card->ports + channel;
f1d03228 557 if (!(port->port.flags & ASYNC_INITIALIZED)) {
18234f88 558 outw(0x0000, base+0x04); /* enable interrupts */
174f1307 559 spin_unlock(&card->card_lock);
1da177e4 560 return IRQ_HANDLED;
d8d16e47
JS
561 }
562
d450b5a0 563 tty = tty_port_tty_get(&port->port);
1da177e4
LT
564 if (tty == NULL) {
565 word_count = byte_count >> 1;
251b8dd7 566 while (byte_count > 1) {
1da177e4
LT
567 inw(base);
568 byte_count -= 2;
569 }
570 if (byte_count & 0x01)
571 inw(base);
18234f88 572 outw(0x0000, base+0x04); /* enable interrupts */
1da177e4
LT
573 spin_unlock(&card->card_lock);
574 return IRQ_HANDLED;
575 }
d8d16e47 576
1da177e4
LT
577 if (header & 0x8000) { /* Status Packet */
578 header = inw(base);
251b8dd7 579 switch (header & 0xff) {
d8d16e47 580 case 0: /* Change in EIA signals */
f1d03228 581 if (port->port.flags & ASYNC_CHECK_CD) {
d8d16e47
JS
582 if (port->status & ISI_DCD) {
583 if (!(header & ISI_DCD)) {
584 /* Carrier has been lost */
a547dfe9
JS
585 pr_dbg("interrupt: DCD->low.\n"
586 );
d8d16e47 587 port->status &= ~ISI_DCD;
0aa5de85 588 tty_hangup(tty);
1da177e4 589 }
a547dfe9
JS
590 } else if (header & ISI_DCD) {
591 /* Carrier has been detected */
592 pr_dbg("interrupt: DCD->high.\n");
593 port->status |= ISI_DCD;
f1d03228 594 wake_up_interruptible(&port->port.open_wait);
1da177e4 595 }
a547dfe9 596 } else {
d8d16e47
JS
597 if (header & ISI_DCD)
598 port->status |= ISI_DCD;
599 else
600 port->status &= ~ISI_DCD;
601 }
602
f1d03228 603 if (port->port.flags & ASYNC_CTS_FLOW) {
d450b5a0 604 if (tty->hw_stopped) {
d8d16e47 605 if (header & ISI_CTS) {
f1d03228 606 port->port.tty->hw_stopped = 0;
d8d16e47 607 /* start tx ing */
a547dfe9
JS
608 port->status |= (ISI_TXOK
609 | ISI_CTS);
0aa5de85 610 tty_wakeup(tty);
1da177e4 611 }
a547dfe9 612 } else if (!(header & ISI_CTS)) {
d450b5a0 613 tty->hw_stopped = 1;
a547dfe9
JS
614 /* stop tx ing */
615 port->status &= ~(ISI_TXOK | ISI_CTS);
1da177e4 616 }
a547dfe9 617 } else {
d8d16e47
JS
618 if (header & ISI_CTS)
619 port->status |= ISI_CTS;
1da177e4 620 else
d8d16e47
JS
621 port->status &= ~ISI_CTS;
622 }
623
624 if (header & ISI_DSR)
625 port->status |= ISI_DSR;
626 else
627 port->status &= ~ISI_DSR;
628
629 if (header & ISI_RI)
630 port->status |= ISI_RI;
631 else
632 port->status &= ~ISI_RI;
633
634 break;
635
a547dfe9 636 case 1: /* Received Break !!! */
d8d16e47 637 tty_insert_flip_char(tty, 0, TTY_BREAK);
f1d03228 638 if (port->port.flags & ASYNC_SAK)
d8d16e47
JS
639 do_SAK(tty);
640 tty_flip_buffer_push(tty);
641 break;
642
643 case 2: /* Statistics */
aaa246ea 644 pr_dbg("isicom_interrupt: stats!!!.\n");
d8d16e47
JS
645 break;
646
647 default:
aaa246ea 648 pr_dbg("Intr: Unknown code in status packet.\n");
d8d16e47
JS
649 break;
650 }
a547dfe9 651 } else { /* Data Packet */
33f0f88f
AC
652
653 count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
aaa246ea 654 pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
1da177e4 655 word_count = count >> 1;
33f0f88f 656 insw(base, rp, word_count);
1da177e4
LT
657 byte_count -= (word_count << 1);
658 if (count & 0x0001) {
a547dfe9
JS
659 tty_insert_flip_char(tty, inw(base) & 0xff,
660 TTY_NORMAL);
1da177e4 661 byte_count -= 2;
d8d16e47 662 }
1da177e4 663 if (byte_count > 0) {
aaa246ea
JS
664 pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
665 "bytes...\n", base, channel + 1);
251b8dd7
AC
666 /* drain out unread xtra data */
667 while (byte_count > 0) {
1da177e4
LT
668 inw(base);
669 byte_count -= 2;
670 }
671 }
33f0f88f 672 tty_flip_buffer_push(tty);
1da177e4 673 }
18234f88 674 outw(0x0000, base+0x04); /* enable interrupts */
174f1307 675 spin_unlock(&card->card_lock);
d450b5a0 676 tty_kref_put(tty);
a547dfe9 677
1da177e4 678 return IRQ_HANDLED;
d8d16e47 679}
1da177e4 680
d450b5a0 681static void isicom_config_port(struct tty_struct *tty)
1da177e4 682{
d450b5a0 683 struct isi_port *port = tty->driver_data;
d8d16e47 684 struct isi_board *card = port->card;
1da177e4 685 unsigned long baud;
8070e35c
JS
686 unsigned long base = card->base;
687 u16 channel_setup, channel = port->channel,
688 shift_count = card->shift_count;
1da177e4 689 unsigned char flow_ctrl;
d8d16e47 690
251b8dd7 691 /* FIXME: Switch to new tty baud API */
1da177e4
LT
692 baud = C_BAUD(tty);
693 if (baud & CBAUDEX) {
694 baud &= ~CBAUDEX;
d8d16e47 695
1da177e4
LT
696 /* if CBAUDEX bit is on and the baud is set to either 50 or 75
697 * then the card is programmed for 57.6Kbps or 115Kbps
698 * respectively.
d8d16e47
JS
699 */
700
7edc136a
JS
701 /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
702 if (baud < 1 || baud > 4)
d450b5a0 703 tty->termios->c_cflag &= ~CBAUDEX;
1da177e4
LT
704 else
705 baud += 15;
d8d16e47 706 }
1da177e4 707 if (baud == 15) {
d8d16e47
JS
708
709 /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
1da177e4
LT
710 * by the set_serial_info ioctl ... this is done by
711 * the 'setserial' utility.
d8d16e47
JS
712 */
713
f1d03228 714 if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
d8d16e47 715 baud++; /* 57.6 Kbps */
f1d03228 716 if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
251b8dd7 717 baud += 2; /* 115 Kbps */
f1d03228 718 if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
7edc136a 719 baud += 3; /* 230 kbps*/
f1d03228 720 if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
7edc136a 721 baud += 4; /* 460 kbps*/
1da177e4
LT
722 }
723 if (linuxb_to_isib[baud] == -1) {
724 /* hang up */
d8d16e47
JS
725 drop_dtr(port);
726 return;
251b8dd7 727 } else
1da177e4 728 raise_dtr(port);
d8d16e47 729
cfe7c09a 730 if (WaitTillCardIsFree(base) == 0) {
251b8dd7 731 outw(0x8000 | (channel << shift_count) | 0x03, base);
1da177e4
LT
732 outw(linuxb_to_isib[baud] << 8 | 0x03, base);
733 channel_setup = 0;
251b8dd7 734 switch (C_CSIZE(tty)) {
d8d16e47
JS
735 case CS5:
736 channel_setup |= ISICOM_CS5;
737 break;
738 case CS6:
739 channel_setup |= ISICOM_CS6;
740 break;
741 case CS7:
742 channel_setup |= ISICOM_CS7;
743 break;
744 case CS8:
745 channel_setup |= ISICOM_CS8;
746 break;
1da177e4 747 }
d8d16e47 748
1da177e4
LT
749 if (C_CSTOPB(tty))
750 channel_setup |= ISICOM_2SB;
751 if (C_PARENB(tty)) {
752 channel_setup |= ISICOM_EVPAR;
753 if (C_PARODD(tty))
d8d16e47 754 channel_setup |= ISICOM_ODPAR;
1da177e4 755 }
d8d16e47 756 outw(channel_setup, base);
1da177e4 757 InterruptTheCard(base);
d8d16e47 758 }
1da177e4 759 if (C_CLOCAL(tty))
f1d03228 760 port->port.flags &= ~ASYNC_CHECK_CD;
1da177e4 761 else
f1d03228 762 port->port.flags |= ASYNC_CHECK_CD;
d8d16e47 763
1da177e4
LT
764 /* flow control settings ...*/
765 flow_ctrl = 0;
f1d03228 766 port->port.flags &= ~ASYNC_CTS_FLOW;
1da177e4 767 if (C_CRTSCTS(tty)) {
f1d03228 768 port->port.flags |= ASYNC_CTS_FLOW;
1da177e4 769 flow_ctrl |= ISICOM_CTSRTS;
d8d16e47
JS
770 }
771 if (I_IXON(tty))
1da177e4
LT
772 flow_ctrl |= ISICOM_RESPOND_XONXOFF;
773 if (I_IXOFF(tty))
d8d16e47
JS
774 flow_ctrl |= ISICOM_INITIATE_XONXOFF;
775
cfe7c09a 776 if (WaitTillCardIsFree(base) == 0) {
251b8dd7 777 outw(0x8000 | (channel << shift_count) | 0x04, base);
1da177e4
LT
778 outw(flow_ctrl << 8 | 0x05, base);
779 outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
780 InterruptTheCard(base);
1da177e4 781 }
d8d16e47 782
1da177e4
LT
783 /* rx enabled -> enable port for rx on the card */
784 if (C_CREAD(tty)) {
785 card->port_status |= (1 << channel);
786 outw(card->port_status, base + 0x02);
787 }
788}
1da177e4 789
d8d16e47
JS
790/* open et all */
791
792static inline void isicom_setup_board(struct isi_board *bp)
1da177e4
LT
793{
794 int channel;
d8d16e47 795 struct isi_port *port;
1da177e4 796 unsigned long flags;
d8d16e47 797
1da177e4
LT
798 spin_lock_irqsave(&bp->card_lock, flags);
799 if (bp->status & BOARD_ACTIVE) {
800 spin_unlock_irqrestore(&bp->card_lock, flags);
801 return;
802 }
803 port = bp->ports;
804 bp->status |= BOARD_ACTIVE;
d8d16e47 805 for (channel = 0; channel < bp->port_count; channel++, port++)
1da177e4 806 drop_dtr_rts(port);
cfe7c09a 807 spin_unlock_irqrestore(&bp->card_lock, flags);
1da177e4 808}
d8d16e47 809
d450b5a0 810static int isicom_setup_port(struct tty_struct *tty)
1da177e4 811{
d450b5a0 812 struct isi_port *port = tty->driver_data;
d8d16e47 813 struct isi_board *card = port->card;
1da177e4 814 unsigned long flags;
d8d16e47 815
f1d03228 816 if (port->port.flags & ASYNC_INITIALIZED)
1da177e4 817 return 0;
f1d03228
AC
818 if (tty_port_alloc_xmit_buf(&port->port) < 0)
819 return -ENOMEM;
1da177e4
LT
820
821 spin_lock_irqsave(&card->card_lock, flags);
d450b5a0 822 clear_bit(TTY_IO_ERROR, &tty->flags);
f1d03228 823 if (port->port.count == 1)
1da177e4 824 card->count++;
d8d16e47 825
1da177e4 826 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
d8d16e47 827
1da177e4 828 /* discard any residual data */
cfe7c09a
JS
829 if (WaitTillCardIsFree(card->base) == 0) {
830 outw(0x8000 | (port->channel << card->shift_count) | 0x02,
831 card->base);
832 outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
833 InterruptTheCard(card->base);
834 }
d8d16e47 835
d450b5a0 836 isicom_config_port(tty);
f1d03228 837 port->port.flags |= ASYNC_INITIALIZED;
1da177e4 838 spin_unlock_irqrestore(&card->card_lock, flags);
d8d16e47
JS
839
840 return 0;
841}
842
31f35939
AC
843static int isicom_carrier_raised(struct tty_port *port)
844{
845 struct isi_port *ip = container_of(port, struct isi_port, port);
846 return (ip->status & ISI_DCD)?1 : 0;
847}
848
d8d16e47 849static int isicom_open(struct tty_struct *tty, struct file *filp)
1da177e4 850{
d8d16e47
JS
851 struct isi_port *port;
852 struct isi_board *card;
17c4edf0
JS
853 unsigned int board;
854 int error, line;
1da177e4
LT
855
856 line = tty->index;
857 if (line < 0 || line > PORT_COUNT-1)
858 return -ENODEV;
859 board = BOARD(line);
860 card = &isi_card[board];
d8d16e47 861
1da177e4
LT
862 if (!(card->status & FIRMWARE_LOADED))
863 return -ENODEV;
d8d16e47 864
1da177e4
LT
865 /* open on a port greater than the port count for the card !!! */
866 if (line > ((board * 16) + card->port_count - 1))
867 return -ENODEV;
868
d8d16e47 869 port = &isi_ports[line];
1da177e4
LT
870 if (isicom_paranoia_check(port, tty->name, "isicom_open"))
871 return -ENODEV;
d8d16e47
JS
872
873 isicom_setup_board(card);
874
36c621d8 875 /* FIXME: locking on port.count etc */
f1d03228 876 port->port.count++;
1da177e4 877 tty->driver_data = port;
d450b5a0
AC
878 tty_port_tty_set(&port->port, tty);
879 error = isicom_setup_port(tty);
251b8dd7 880 if (error == 0)
36c621d8 881 error = tty_port_block_til_ready(&port->port, tty, filp);
251b8dd7 882 return error;
1da177e4 883}
d8d16e47 884
1da177e4
LT
885/* close et all */
886
d8d16e47 887static inline void isicom_shutdown_board(struct isi_board *bp)
1da177e4 888{
251b8dd7 889 if (bp->status & BOARD_ACTIVE)
1da177e4 890 bp->status &= ~BOARD_ACTIVE;
1da177e4
LT
891}
892
cfe7c09a 893/* card->lock HAS to be held */
d8d16e47 894static void isicom_shutdown_port(struct isi_port *port)
1da177e4 895{
d8d16e47
JS
896 struct isi_board *card = port->card;
897 struct tty_struct *tty;
d8d16e47 898
d450b5a0 899 tty = tty_port_tty_get(&port->port);
1da177e4 900
d450b5a0
AC
901 if (!(port->port.flags & ASYNC_INITIALIZED)) {
902 tty_kref_put(tty);
1da177e4 903 return;
d450b5a0 904 }
cfe7c09a 905
f1d03228
AC
906 tty_port_free_xmit_buf(&port->port);
907 port->port.flags &= ~ASYNC_INITIALIZED;
1da177e4 908 /* 3rd October 2000 : Vinayak P Risbud */
d450b5a0 909 tty_port_tty_set(&port->port, NULL);
d8d16e47 910
1da177e4
LT
911 /*Fix done by Anil .S on 30-04-2001
912 remote login through isi port has dtr toggle problem
913 due to which the carrier drops before the password prompt
d8d16e47 914 appears on the remote end. Now we drop the dtr only if the
1da177e4 915 HUPCL(Hangup on close) flag is set for the tty*/
d8d16e47
JS
916
917 if (C_HUPCL(tty))
1da177e4
LT
918 /* drop dtr on this port */
919 drop_dtr(port);
d8d16e47
JS
920
921 /* any other port uninits */
1da177e4
LT
922 if (tty)
923 set_bit(TTY_IO_ERROR, &tty->flags);
d8d16e47 924
1da177e4 925 if (--card->count < 0) {
aaa246ea 926 pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
1da177e4 927 card->base, card->count);
d8d16e47 928 card->count = 0;
1da177e4 929 }
d8d16e47 930
a547dfe9 931 /* last port was closed, shutdown that boad too */
d8d16e47 932 if (C_HUPCL(tty)) {
1da177e4
LT
933 if (!card->count)
934 isicom_shutdown_board(card);
935 }
bbb8e6bf 936 tty_kref_put(tty);
1da177e4
LT
937}
938
978e595f
AC
939static void isicom_flush_buffer(struct tty_struct *tty)
940{
941 struct isi_port *port = tty->driver_data;
942 struct isi_board *card = port->card;
943 unsigned long flags;
944
945 if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
946 return;
947
948 spin_lock_irqsave(&card->card_lock, flags);
949 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
950 spin_unlock_irqrestore(&card->card_lock, flags);
951
952 tty_wakeup(tty);
953}
954
6f6412b4 955static void isicom_close_port(struct tty_port *port)
1da177e4 956{
6f6412b4
AC
957 struct isi_port *ip = container_of(port, struct isi_port, port);
958 struct isi_board *card = ip->card;
1da177e4 959 unsigned long flags;
d8d16e47 960
d8d16e47 961 /* indicate to the card that no more data can be received
1da177e4
LT
962 on this port */
963 spin_lock_irqsave(&card->card_lock, flags);
a6614999
AC
964 if (port->flags & ASYNC_INITIALIZED) {
965 card->port_status &= ~(1 << ip->channel);
1da177e4 966 outw(card->port_status, card->base + 0x02);
d8d16e47 967 }
a6614999 968 isicom_shutdown_port(ip);
1da177e4 969 spin_unlock_irqrestore(&card->card_lock, flags);
6f6412b4 970}
d8d16e47 971
6f6412b4
AC
972static void isicom_close(struct tty_struct *tty, struct file *filp)
973{
974 struct isi_port *ip = tty->driver_data;
975 struct tty_port *port = &ip->port;
976 if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
977 return;
978
979 if (tty_port_close_start(port, tty, filp) == 0)
980 return;
981 isicom_close_port(port);
978e595f 982 isicom_flush_buffer(tty);
a6614999 983 tty_port_close_end(port, tty);
1da177e4
LT
984}
985
986/* write et all */
d8d16e47
JS
987static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
988 int count)
1da177e4 989{
8070e35c 990 struct isi_port *port = tty->driver_data;
d8d16e47 991 struct isi_board *card = port->card;
1da177e4
LT
992 unsigned long flags;
993 int cnt, total = 0;
994
995 if (isicom_paranoia_check(port, tty->name, "isicom_write"))
996 return 0;
d8d16e47 997
1da177e4 998 spin_lock_irqsave(&card->card_lock, flags);
d8d16e47 999
251b8dd7 1000 while (1) {
a547dfe9
JS
1001 cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
1002 - 1, SERIAL_XMIT_SIZE - port->xmit_head));
d8d16e47 1003 if (cnt <= 0)
1da177e4 1004 break;
d8d16e47 1005
f1d03228 1006 memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt);
a547dfe9
JS
1007 port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
1008 - 1);
1da177e4
LT
1009 port->xmit_cnt += cnt;
1010 buf += cnt;
1011 count -= cnt;
1012 total += cnt;
d8d16e47 1013 }
1da177e4
LT
1014 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
1015 port->status |= ISI_TXOK;
1016 spin_unlock_irqrestore(&card->card_lock, flags);
d8d16e47 1017 return total;
1da177e4
LT
1018}
1019
1020/* put_char et all */
f34d7a5b 1021static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
1da177e4 1022{
8070e35c 1023 struct isi_port *port = tty->driver_data;
d8d16e47 1024 struct isi_board *card = port->card;
1da177e4 1025 unsigned long flags;
d8d16e47 1026
1da177e4 1027 if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
f34d7a5b 1028 return 0;
d8d16e47 1029
1da177e4 1030 spin_lock_irqsave(&card->card_lock, flags);
f34d7a5b
AC
1031 if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
1032 spin_unlock_irqrestore(&card->card_lock, flags);
1033 return 0;
1034 }
d8d16e47 1035
f1d03228 1036 port->port.xmit_buf[port->xmit_head++] = ch;
1da177e4
LT
1037 port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
1038 port->xmit_cnt++;
1039 spin_unlock_irqrestore(&card->card_lock, flags);
f34d7a5b 1040 return 1;
1da177e4
LT
1041}
1042
1043/* flush_chars et all */
d8d16e47 1044static void isicom_flush_chars(struct tty_struct *tty)
1da177e4 1045{
8070e35c 1046 struct isi_port *port = tty->driver_data;
d8d16e47 1047
1da177e4
LT
1048 if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
1049 return;
d8d16e47 1050
a547dfe9 1051 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
f1d03228 1052 !port->port.xmit_buf)
1da177e4 1053 return;
d8d16e47 1054
1da177e4
LT
1055 /* this tells the transmitter to consider this port for
1056 data output to the card ... that's the best we can do. */
d8d16e47 1057 port->status |= ISI_TXOK;
1da177e4
LT
1058}
1059
1060/* write_room et all */
d8d16e47 1061static int isicom_write_room(struct tty_struct *tty)
1da177e4 1062{
8070e35c 1063 struct isi_port *port = tty->driver_data;
1da177e4
LT
1064 int free;
1065
1066 if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
1067 return 0;
d8d16e47 1068
1da177e4
LT
1069 free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1070 if (free < 0)
1071 free = 0;
1072 return free;
1073}
1074
1075/* chars_in_buffer et all */
d8d16e47 1076static int isicom_chars_in_buffer(struct tty_struct *tty)
1da177e4 1077{
8070e35c 1078 struct isi_port *port = tty->driver_data;
1da177e4
LT
1079 if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
1080 return 0;
1081 return port->xmit_cnt;
1082}
1083
1084/* ioctl et all */
6d889724 1085static int isicom_send_break(struct tty_struct *tty, int length)
1da177e4 1086{
6d889724 1087 struct isi_port *port = tty->driver_data;
d8d16e47 1088 struct isi_board *card = port->card;
8070e35c 1089 unsigned long base = card->base;
d8d16e47 1090
6d889724
AC
1091 if (length == -1)
1092 return -EOPNOTSUPP;
1093
d8d16e47 1094 if (!lock_card(card))
6d889724 1095 return -EINVAL;
d8d16e47 1096
1da177e4
LT
1097 outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
1098 outw((length & 0xff) << 8 | 0x00, base);
1099 outw((length & 0xff00), base);
1100 InterruptTheCard(base);
1101
1102 unlock_card(card);
6d889724 1103 return 0;
1da177e4
LT
1104}
1105
1106static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
1107{
8070e35c 1108 struct isi_port *port = tty->driver_data;
1da177e4 1109 /* just send the port status */
8070e35c 1110 u16 status = port->status;
1da177e4
LT
1111
1112 if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1113 return -ENODEV;
d8d16e47 1114
1da177e4
LT
1115 return ((status & ISI_RTS) ? TIOCM_RTS : 0) |
1116 ((status & ISI_DTR) ? TIOCM_DTR : 0) |
1117 ((status & ISI_DCD) ? TIOCM_CAR : 0) |
1118 ((status & ISI_DSR) ? TIOCM_DSR : 0) |
1119 ((status & ISI_CTS) ? TIOCM_CTS : 0) |
1120 ((status & ISI_RI ) ? TIOCM_RI : 0);
1121}
1122
1123static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
d8d16e47 1124 unsigned int set, unsigned int clear)
1da177e4 1125{
8070e35c 1126 struct isi_port *port = tty->driver_data;
cfe7c09a 1127 unsigned long flags;
d8d16e47 1128
1da177e4
LT
1129 if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1130 return -ENODEV;
d8d16e47 1131
cfe7c09a 1132 spin_lock_irqsave(&port->card->card_lock, flags);
1da177e4
LT
1133 if (set & TIOCM_RTS)
1134 raise_rts(port);
1135 if (set & TIOCM_DTR)
1136 raise_dtr(port);
1137
1138 if (clear & TIOCM_RTS)
1139 drop_rts(port);
1140 if (clear & TIOCM_DTR)
1141 drop_dtr(port);
cfe7c09a 1142 spin_unlock_irqrestore(&port->card->card_lock, flags);
1da177e4
LT
1143
1144 return 0;
d8d16e47 1145}
1da177e4 1146
d450b5a0
AC
1147static int isicom_set_serial_info(struct tty_struct *tty,
1148 struct serial_struct __user *info)
1da177e4 1149{
d450b5a0 1150 struct isi_port *port = tty->driver_data;
1da177e4
LT
1151 struct serial_struct newinfo;
1152 int reconfig_port;
1153
d8d16e47 1154 if (copy_from_user(&newinfo, info, sizeof(newinfo)))
1da177e4 1155 return -EFAULT;
d8d16e47 1156
1eac4947
AC
1157 lock_kernel();
1158
f1d03228 1159 reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
d8d16e47
JS
1160 (newinfo.flags & ASYNC_SPD_MASK));
1161
1da177e4 1162 if (!capable(CAP_SYS_ADMIN)) {
44b7d1b3
AC
1163 if ((newinfo.close_delay != port->port.close_delay) ||
1164 (newinfo.closing_wait != port->port.closing_wait) ||
d8d16e47 1165 ((newinfo.flags & ~ASYNC_USR_MASK) !=
f1d03228 1166 (port->port.flags & ~ASYNC_USR_MASK))) {
1eac4947 1167 unlock_kernel();
1da177e4 1168 return -EPERM;
1eac4947 1169 }
f1d03228 1170 port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
1da177e4 1171 (newinfo.flags & ASYNC_USR_MASK));
251b8dd7 1172 } else {
44b7d1b3
AC
1173 port->port.close_delay = newinfo.close_delay;
1174 port->port.closing_wait = newinfo.closing_wait;
f1d03228 1175 port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
1da177e4
LT
1176 (newinfo.flags & ASYNC_FLAGS));
1177 }
1178 if (reconfig_port) {
cfe7c09a
JS
1179 unsigned long flags;
1180 spin_lock_irqsave(&port->card->card_lock, flags);
d450b5a0 1181 isicom_config_port(tty);
cfe7c09a 1182 spin_unlock_irqrestore(&port->card->card_lock, flags);
1da177e4 1183 }
1eac4947 1184 unlock_kernel();
d8d16e47
JS
1185 return 0;
1186}
1da177e4 1187
d8d16e47
JS
1188static int isicom_get_serial_info(struct isi_port *port,
1189 struct serial_struct __user *info)
1da177e4
LT
1190{
1191 struct serial_struct out_info;
d8d16e47 1192
1eac4947 1193 lock_kernel();
1da177e4
LT
1194 memset(&out_info, 0, sizeof(out_info));
1195/* out_info.type = ? */
1196 out_info.line = port - isi_ports;
1197 out_info.port = port->card->base;
1198 out_info.irq = port->card->irq;
f1d03228 1199 out_info.flags = port->port.flags;
1da177e4 1200/* out_info.baud_base = ? */
44b7d1b3
AC
1201 out_info.close_delay = port->port.close_delay;
1202 out_info.closing_wait = port->port.closing_wait;
1eac4947 1203 unlock_kernel();
d8d16e47 1204 if (copy_to_user(info, &out_info, sizeof(out_info)))
1da177e4
LT
1205 return -EFAULT;
1206 return 0;
d8d16e47 1207}
1da177e4 1208
d8d16e47
JS
1209static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
1210 unsigned int cmd, unsigned long arg)
1da177e4 1211{
8070e35c 1212 struct isi_port *port = tty->driver_data;
1da177e4 1213 void __user *argp = (void __user *)arg;
1da177e4
LT
1214
1215 if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1216 return -ENODEV;
1217
251b8dd7 1218 switch (cmd) {
d8d16e47
JS
1219 case TIOCGSERIAL:
1220 return isicom_get_serial_info(port, argp);
1221
1222 case TIOCSSERIAL:
d450b5a0 1223 return isicom_set_serial_info(tty, argp);
d8d16e47
JS
1224
1225 default:
1226 return -ENOIOCTLCMD;
1da177e4
LT
1227 }
1228 return 0;
1229}
1230
1231/* set_termios et all */
d8d16e47 1232static void isicom_set_termios(struct tty_struct *tty,
606d099c 1233 struct ktermios *old_termios)
1da177e4 1234{
8070e35c 1235 struct isi_port *port = tty->driver_data;
cfe7c09a 1236 unsigned long flags;
d8d16e47 1237
1da177e4
LT
1238 if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
1239 return;
d8d16e47 1240
1da177e4 1241 if (tty->termios->c_cflag == old_termios->c_cflag &&
d8d16e47 1242 tty->termios->c_iflag == old_termios->c_iflag)
1da177e4 1243 return;
d8d16e47 1244
cfe7c09a 1245 spin_lock_irqsave(&port->card->card_lock, flags);
d450b5a0 1246 isicom_config_port(tty);
cfe7c09a 1247 spin_unlock_irqrestore(&port->card->card_lock, flags);
d8d16e47 1248
1da177e4 1249 if ((old_termios->c_cflag & CRTSCTS) &&
d8d16e47 1250 !(tty->termios->c_cflag & CRTSCTS)) {
1da177e4 1251 tty->hw_stopped = 0;
d8d16e47
JS
1252 isicom_start(tty);
1253 }
1da177e4
LT
1254}
1255
1256/* throttle et all */
d8d16e47 1257static void isicom_throttle(struct tty_struct *tty)
1da177e4 1258{
8070e35c 1259 struct isi_port *port = tty->driver_data;
d8d16e47
JS
1260 struct isi_board *card = port->card;
1261
1da177e4
LT
1262 if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
1263 return;
d8d16e47 1264
1da177e4
LT
1265 /* tell the card that this port cannot handle any more data for now */
1266 card->port_status &= ~(1 << port->channel);
1267 outw(card->port_status, card->base + 0x02);
1268}
1269
1270/* unthrottle et all */
d8d16e47 1271static void isicom_unthrottle(struct tty_struct *tty)
1da177e4 1272{
8070e35c 1273 struct isi_port *port = tty->driver_data;
d8d16e47
JS
1274 struct isi_board *card = port->card;
1275
1da177e4
LT
1276 if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
1277 return;
d8d16e47 1278
1da177e4
LT
1279 /* tell the card that this port is ready to accept more data */
1280 card->port_status |= (1 << port->channel);
1281 outw(card->port_status, card->base + 0x02);
1282}
1283
1284/* stop et all */
d8d16e47 1285static void isicom_stop(struct tty_struct *tty)
1da177e4 1286{
8070e35c 1287 struct isi_port *port = tty->driver_data;
1da177e4
LT
1288
1289 if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
1290 return;
d8d16e47 1291
1da177e4
LT
1292 /* this tells the transmitter not to consider this port for
1293 data output to the card. */
1294 port->status &= ~ISI_TXOK;
1295}
1296
1297/* start et all */
d8d16e47 1298static void isicom_start(struct tty_struct *tty)
1da177e4 1299{
8070e35c 1300 struct isi_port *port = tty->driver_data;
d8d16e47 1301
1da177e4
LT
1302 if (isicom_paranoia_check(port, tty->name, "isicom_start"))
1303 return;
d8d16e47 1304
1da177e4
LT
1305 /* this tells the transmitter to consider this port for
1306 data output to the card. */
1307 port->status |= ISI_TXOK;
1308}
1309
d8d16e47 1310static void isicom_hangup(struct tty_struct *tty)
1da177e4 1311{
8070e35c 1312 struct isi_port *port = tty->driver_data;
cfe7c09a 1313 unsigned long flags;
d8d16e47 1314
1da177e4
LT
1315 if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
1316 return;
d8d16e47 1317
cfe7c09a 1318 spin_lock_irqsave(&port->card->card_lock, flags);
1da177e4 1319 isicom_shutdown_port(port);
cfe7c09a
JS
1320 spin_unlock_irqrestore(&port->card->card_lock, flags);
1321
3e61696b 1322 tty_port_hangup(&port->port);
1da177e4
LT
1323}
1324
1da177e4 1325
9ac0948b
JS
1326/*
1327 * Driver init and deinit functions
1328 */
1da177e4 1329
b68e31d0 1330static const struct tty_operations isicom_ops = {
d8d16e47
JS
1331 .open = isicom_open,
1332 .close = isicom_close,
1333 .write = isicom_write,
1334 .put_char = isicom_put_char,
1335 .flush_chars = isicom_flush_chars,
1336 .write_room = isicom_write_room,
1da177e4 1337 .chars_in_buffer = isicom_chars_in_buffer,
d8d16e47
JS
1338 .ioctl = isicom_ioctl,
1339 .set_termios = isicom_set_termios,
1340 .throttle = isicom_throttle,
1341 .unthrottle = isicom_unthrottle,
1342 .stop = isicom_stop,
1343 .start = isicom_start,
1344 .hangup = isicom_hangup,
1345 .flush_buffer = isicom_flush_buffer,
1346 .tiocmget = isicom_tiocmget,
1347 .tiocmset = isicom_tiocmset,
6d889724 1348 .break_ctl = isicom_send_break,
1da177e4
LT
1349};
1350
31f35939
AC
1351static const struct tty_port_operations isicom_port_ops = {
1352 .carrier_raised = isicom_carrier_raised,
fcc8ac18 1353 .dtr_rts = isicom_dtr_rts,
31f35939
AC
1354};
1355
9ac0948b
JS
1356static int __devinit reset_card(struct pci_dev *pdev,
1357 const unsigned int card, unsigned int *signature)
1da177e4 1358{
9ac0948b
JS
1359 struct isi_board *board = pci_get_drvdata(pdev);
1360 unsigned long base = board->base;
f0a0ba6d 1361 unsigned int sig, portcount = 0;
9ac0948b 1362 int retval = 0;
d8d16e47 1363
9ac0948b
JS
1364 dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
1365 base);
d8d16e47 1366
9ac0948b 1367 inw(base + 0x8);
d8d16e47 1368
f0a0ba6d 1369 msleep(10);
9ac0948b
JS
1370
1371 outw(0, base + 0x8); /* Reset */
1372
f0a0ba6d 1373 msleep(1000);
9ac0948b 1374
f0a0ba6d
JS
1375 sig = inw(base + 0x4) & 0xff;
1376
1377 if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
1378 sig != 0xee) {
1379 dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
1380 "bad I/O Port Address 0x%lx).\n", card + 1, base);
1381 dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
1382 retval = -EIO;
1383 goto end;
1384 }
1385
1386 msleep(10);
9ac0948b 1387
18234f88 1388 portcount = inw(base + 0x2);
07fb6f26 1389 if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 &&
f0a0ba6d 1390 portcount != 8 && portcount != 16)) {
898eb71c 1391 dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
f0a0ba6d 1392 card + 1);
18234f88
JS
1393 retval = -EIO;
1394 goto end;
9ac0948b
JS
1395 }
1396
f0a0ba6d 1397 switch (sig) {
9ac0948b
JS
1398 case 0xa5:
1399 case 0xbb:
1400 case 0xdd:
18234f88 1401 board->port_count = (portcount == 4) ? 4 : 8;
9ac0948b
JS
1402 board->shift_count = 12;
1403 break;
1404 case 0xcc:
f0a0ba6d 1405 case 0xee:
9ac0948b
JS
1406 board->port_count = 16;
1407 board->shift_count = 11;
1408 break;
d8d16e47 1409 }
9ac0948b 1410 dev_info(&pdev->dev, "-Done\n");
f0a0ba6d 1411 *signature = sig;
d8d16e47 1412
9ac0948b
JS
1413end:
1414 return retval;
1da177e4
LT
1415}
1416
e65c1db1
JS
1417static int __devinit load_firmware(struct pci_dev *pdev,
1418 const unsigned int index, const unsigned int signature)
1419{
1420 struct isi_board *board = pci_get_drvdata(pdev);
1421 const struct firmware *fw;
1422 unsigned long base = board->base;
1423 unsigned int a;
1424 u16 word_count, status;
1425 int retval = -EIO;
1426 char *name;
1427 u8 *data;
1428
1429 struct stframe {
1430 u16 addr;
1431 u16 count;
1432 u8 data[0];
1433 } *frame;
1434
1435 switch (signature) {
1436 case 0xa5:
1437 name = "isi608.bin";
1438 break;
1439 case 0xbb:
1440 name = "isi608em.bin";
1441 break;
1442 case 0xcc:
1443 name = "isi616em.bin";
1444 break;
1445 case 0xdd:
1446 name = "isi4608.bin";
1447 break;
1448 case 0xee:
1449 name = "isi4616.bin";
1450 break;
1451 default:
1452 dev_err(&pdev->dev, "Unknown signature.\n");
1453 goto end;
251b8dd7 1454 }
e65c1db1
JS
1455
1456 retval = request_firmware(&fw, name, &pdev->dev);
1457 if (retval)
1458 goto end;
1459
e4e04088
JS
1460 retval = -EIO;
1461
e65c1db1
JS
1462 for (frame = (struct stframe *)fw->data;
1463 frame < (struct stframe *)(fw->data + fw->size);
e4e04088
JS
1464 frame = (struct stframe *)((u8 *)(frame + 1) +
1465 frame->count)) {
e65c1db1
JS
1466 if (WaitTillCardIsFree(base))
1467 goto errrelfw;
1468
1469 outw(0xf0, base); /* start upload sequence */
1470 outw(0x00, base);
1471 outw(frame->addr, base); /* lsb of address */
1472
1473 word_count = frame->count / 2 + frame->count % 2;
1474 outw(word_count, base);
1475 InterruptTheCard(base);
1476
1477 udelay(100); /* 0x2f */
1478
1479 if (WaitTillCardIsFree(base))
1480 goto errrelfw;
1481
251b8dd7
AC
1482 status = inw(base + 0x4);
1483 if (status != 0) {
e65c1db1 1484 dev_warn(&pdev->dev, "Card%d rejected load header:\n"
ad361c98
JP
1485 "Address:0x%x\n"
1486 "Count:0x%x\n"
1487 "Status:0x%x\n",
1488 index + 1, frame->addr, frame->count, status);
e65c1db1
JS
1489 goto errrelfw;
1490 }
1491 outsw(base, frame->data, word_count);
1492
1493 InterruptTheCard(base);
1494
1495 udelay(50); /* 0x0f */
1496
1497 if (WaitTillCardIsFree(base))
1498 goto errrelfw;
1499
251b8dd7
AC
1500 status = inw(base + 0x4);
1501 if (status != 0) {
e65c1db1
JS
1502 dev_err(&pdev->dev, "Card%d got out of sync.Card "
1503 "Status:0x%x\n", index + 1, status);
1504 goto errrelfw;
1505 }
251b8dd7 1506 }
e65c1db1 1507
e65c1db1
JS
1508/* XXX: should we test it by reading it back and comparing with original like
1509 * in load firmware package? */
e4e04088
JS
1510 for (frame = (struct stframe *)fw->data;
1511 frame < (struct stframe *)(fw->data + fw->size);
1512 frame = (struct stframe *)((u8 *)(frame + 1) +
1513 frame->count)) {
e65c1db1
JS
1514 if (WaitTillCardIsFree(base))
1515 goto errrelfw;
1516
1517 outw(0xf1, base); /* start download sequence */
1518 outw(0x00, base);
1519 outw(frame->addr, base); /* lsb of address */
1520
1521 word_count = (frame->count >> 1) + frame->count % 2;
1522 outw(word_count + 1, base);
1523 InterruptTheCard(base);
1524
1525 udelay(50); /* 0xf */
1526
1527 if (WaitTillCardIsFree(base))
1528 goto errrelfw;
1529
251b8dd7
AC
1530 status = inw(base + 0x4);
1531 if (status != 0) {
e65c1db1 1532 dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
ad361c98
JP
1533 "Address:0x%x\n"
1534 "Count:0x%x\n"
1535 "Status: 0x%x\n",
1536 index + 1, frame->addr, frame->count, status);
e65c1db1
JS
1537 goto errrelfw;
1538 }
1539
1540 data = kmalloc(word_count * 2, GFP_KERNEL);
f0671378
JS
1541 if (data == NULL) {
1542 dev_err(&pdev->dev, "Card%d, firmware upload "
1543 "failed, not enough memory\n", index + 1);
1544 goto errrelfw;
1545 }
e65c1db1
JS
1546 inw(base);
1547 insw(base, data, word_count);
1548 InterruptTheCard(base);
1549
1550 for (a = 0; a < frame->count; a++)
1551 if (data[a] != frame->data[a]) {
1552 kfree(data);
1553 dev_err(&pdev->dev, "Card%d, firmware upload "
1554 "failed\n", index + 1);
1555 goto errrelfw;
1556 }
1557 kfree(data);
1558
1559 udelay(50); /* 0xf */
1560
1561 if (WaitTillCardIsFree(base))
1562 goto errrelfw;
1563
251b8dd7
AC
1564 status = inw(base + 0x4);
1565 if (status != 0) {
e65c1db1
JS
1566 dev_err(&pdev->dev, "Card%d verify got out of sync. "
1567 "Card Status:0x%x\n", index + 1, status);
1568 goto errrelfw;
1569 }
1570 }
1571
e4e04088
JS
1572 /* xfer ctrl */
1573 if (WaitTillCardIsFree(base))
1574 goto errrelfw;
1575
1576 outw(0xf2, base);
1577 outw(0x800, base);
1578 outw(0x0, base);
1579 outw(0x0, base);
1580 InterruptTheCard(base);
1581 outw(0x0, base + 0x4); /* for ISI4608 cards */
1582
e65c1db1
JS
1583 board->status |= FIRMWARE_LOADED;
1584 retval = 0;
1585
1586errrelfw:
1587 release_firmware(fw);
1588end:
1589 return retval;
1590}
1591
1da177e4
LT
1592/*
1593 * Insmod can set static symbols so keep these static
1594 */
1ed0c0b7 1595static unsigned int card_count;
9ac0948b
JS
1596
1597static int __devinit isicom_probe(struct pci_dev *pdev,
1598 const struct pci_device_id *ent)
1599{
9653a69e 1600 unsigned int uninitialized_var(signature), index;
9ac0948b 1601 int retval = -EPERM;
9ac0948b
JS
1602 struct isi_board *board = NULL;
1603
1ed0c0b7 1604 if (card_count >= BOARD_COUNT)
9ac0948b
JS
1605 goto err;
1606
e1e5770b
JS
1607 retval = pci_enable_device(pdev);
1608 if (retval) {
1609 dev_err(&pdev->dev, "failed to enable\n");
1610 goto err;
1611 }
1612
9ac0948b
JS
1613 dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
1614
1615 /* allot the first empty slot in the array */
1616 for (index = 0; index < BOARD_COUNT; index++)
1617 if (isi_card[index].base == 0) {
1618 board = &isi_card[index];
1619 break;
1620 }
1621
938a7023 1622 board->index = index;
4969b3a4
JS
1623 board->base = pci_resource_start(pdev, 3);
1624 board->irq = pdev->irq;
1ed0c0b7 1625 card_count++;
9ac0948b
JS
1626
1627 pci_set_drvdata(pdev, board);
1628
78028da9
JS
1629 retval = pci_request_region(pdev, 3, ISICOM_NAME);
1630 if (retval) {
09a4a112
JS
1631 dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
1632 "will be disabled.\n", board->base, board->base + 15,
1633 index + 1);
1634 retval = -EBUSY;
1ed0c0b7 1635 goto errdec;
251b8dd7 1636 }
9ac0948b 1637
09a4a112
JS
1638 retval = request_irq(board->irq, isicom_interrupt,
1639 IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
1640 if (retval < 0) {
1641 dev_err(&pdev->dev, "Could not install handler at Irq %d. "
1642 "Card%d will be disabled.\n", board->irq, index + 1);
9ac0948b 1643 goto errunrr;
09a4a112 1644 }
9ac0948b
JS
1645
1646 retval = reset_card(pdev, index, &signature);
1647 if (retval < 0)
1648 goto errunri;
1649
e65c1db1
JS
1650 retval = load_firmware(pdev, index, signature);
1651 if (retval < 0)
1652 goto errunri;
1653
938a7023
JS
1654 for (index = 0; index < board->port_count; index++)
1655 tty_register_device(isicom_normal, board->index * 16 + index,
1656 &pdev->dev);
1657
9ac0948b
JS
1658 return 0;
1659
1660errunri:
1661 free_irq(board->irq, board);
1662errunrr:
78028da9 1663 pci_release_region(pdev, 3);
1ed0c0b7 1664errdec:
9ac0948b 1665 board->base = 0;
1ed0c0b7 1666 card_count--;
e1e5770b 1667 pci_disable_device(pdev);
1ed0c0b7 1668err:
9ac0948b
JS
1669 return retval;
1670}
1671
1672static void __devexit isicom_remove(struct pci_dev *pdev)
1673{
1674 struct isi_board *board = pci_get_drvdata(pdev);
938a7023
JS
1675 unsigned int i;
1676
1677 for (i = 0; i < board->port_count; i++)
1678 tty_unregister_device(isicom_normal, board->index * 16 + i);
9ac0948b
JS
1679
1680 free_irq(board->irq, board);
78028da9 1681 pci_release_region(pdev, 3);
1ed0c0b7
JS
1682 board->base = 0;
1683 card_count--;
e1e5770b 1684 pci_disable_device(pdev);
9ac0948b 1685}
1da177e4 1686
ca262005 1687static int __init isicom_init(void)
1da177e4 1688{
9ac0948b
JS
1689 int retval, idx, channel;
1690 struct isi_port *port;
d8d16e47 1691
251b8dd7 1692 for (idx = 0; idx < BOARD_COUNT; idx++) {
9ac0948b
JS
1693 port = &isi_ports[idx * 16];
1694 isi_card[idx].ports = port;
1695 spin_lock_init(&isi_card[idx].card_lock);
1696 for (channel = 0; channel < 16; channel++, port++) {
44b7d1b3 1697 tty_port_init(&port->port);
31f35939 1698 port->port.ops = &isicom_port_ops;
9ac0948b
JS
1699 port->magic = ISICOM_MAGIC;
1700 port->card = &isi_card[idx];
1701 port->channel = channel;
44b7d1b3
AC
1702 port->port.close_delay = 50 * HZ/100;
1703 port->port.closing_wait = 3000 * HZ/100;
9ac0948b 1704 port->status = 0;
9ac0948b 1705 /* . . . */
251b8dd7 1706 }
9ac0948b
JS
1707 isi_card[idx].base = 0;
1708 isi_card[idx].irq = 0;
1da177e4 1709 }
d8d16e47 1710
09a4a112
JS
1711 /* tty driver structure initialization */
1712 isicom_normal = alloc_tty_driver(PORT_COUNT);
1713 if (!isicom_normal) {
1714 retval = -ENOMEM;
9ac0948b 1715 goto error;
09a4a112
JS
1716 }
1717
1718 isicom_normal->owner = THIS_MODULE;
1719 isicom_normal->name = "ttyM";
1720 isicom_normal->major = ISICOM_NMAJOR;
1721 isicom_normal->minor_start = 0;
1722 isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
1723 isicom_normal->subtype = SERIAL_TYPE_NORMAL;
1724 isicom_normal->init_termios = tty_std_termios;
1725 isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
1726 CLOCAL;
938a7023 1727 isicom_normal->flags = TTY_DRIVER_REAL_RAW |
6d889724 1728 TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
09a4a112
JS
1729 tty_set_operations(isicom_normal, &isicom_ops);
1730
1731 retval = tty_register_driver(isicom_normal);
1732 if (retval) {
1733 pr_dbg("Couldn't register the dialin driver\n");
1734 goto err_puttty;
1735 }
1da177e4 1736
9ac0948b 1737 retval = pci_register_driver(&isicom_driver);
1da177e4 1738 if (retval < 0) {
9ac0948b 1739 printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
09a4a112 1740 goto err_unrtty;
1da177e4 1741 }
d8d16e47 1742
34b55b86 1743 mod_timer(&tx, jiffies + 1);
d8d16e47 1744
1da177e4 1745 return 0;
09a4a112
JS
1746err_unrtty:
1747 tty_unregister_driver(isicom_normal);
1748err_puttty:
1749 put_tty_driver(isicom_normal);
9ac0948b
JS
1750error:
1751 return retval;
1da177e4
LT
1752}
1753
1754static void __exit isicom_exit(void)
1755{
e327325f 1756 del_timer_sync(&tx);
aaa246ea 1757
9ac0948b 1758 pci_unregister_driver(&isicom_driver);
09a4a112
JS
1759 tty_unregister_driver(isicom_normal);
1760 put_tty_driver(isicom_normal);
1da177e4
LT
1761}
1762
ca262005 1763module_init(isicom_init);
1da177e4 1764module_exit(isicom_exit);
aaa246ea
JS
1765
1766MODULE_AUTHOR("MultiTech");
1767MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
1768MODULE_LICENSE("GPL");