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