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