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