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