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