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