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