[PATCH] skge: error handling on resume
[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/termios.h>
119 #include <linux/fs.h>
120 #include <linux/sched.h>
121 #include <linux/serial.h>
122 #include <linux/mm.h>
123 #include <linux/miscdevice.h>
124 #include <linux/interrupt.h>
125 #include <linux/timer.h>
126 #include <linux/delay.h>
127 #include <linux/ioport.h>
128
129 #include <asm/uaccess.h>
130 #include <asm/io.h>
131 #include <asm/system.h>
132
133 #include <linux/pci.h>
134
135 #include <linux/isicom.h>
136
137 static struct pci_device_id isicom_pci_tbl[] = {
138         { VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
139         { VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
140         { VENDOR_ID, 0x2052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
141         { VENDOR_ID, 0x2053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
142         { VENDOR_ID, 0x2054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
143         { VENDOR_ID, 0x2055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
144         { VENDOR_ID, 0x2056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
145         { VENDOR_ID, 0x2057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
146         { VENDOR_ID, 0x2058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
147         { 0 }
148 };
149 MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
150
151 static int prev_card = 3;       /*      start servicing isi_card[0]     */
152 static struct tty_driver *isicom_normal;
153
154 static struct timer_list tx;
155 static char re_schedule = 1;
156 #ifdef ISICOM_DEBUG
157 static unsigned long tx_count = 0;
158 #endif
159
160 static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned  int cmd, unsigned long arg);
161
162 static void isicom_tx(unsigned long _data);
163 static void isicom_start(struct tty_struct * tty);
164
165 static unsigned char * tmp_buf;
166 static DECLARE_MUTEX(tmp_buf_sem);
167
168 /*   baud index mappings from linux defns to isi */
169
170 static signed char linuxb_to_isib[] = {
171         -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,     
172         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
602 /*
603  *      ISICOM Driver specific routines ...
604  *
605  */
606  
607 static inline int isicom_paranoia_check(struct isi_port const * port, char *name, 
608                                         const char * routine)
609 {
610 #ifdef ISICOM_DEBUG 
611         static const char * badmagic = 
612                         KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
613         static const char * badport = 
614                         KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n";           
615         if (!port) {
616                 printk(badport, name, routine);
617                 return 1;
618         }
619         if (port->magic != ISICOM_MAGIC) {
620                 printk(badmagic, name, routine);
621                 return 1;
622         }       
623 #endif  
624         return 0;
625 }
626                         
627 /*
628  *      Transmitter. 
629  *
630  *      We shovel data into the card buffers on a regular basis. The card
631  *      will do the rest of the work for us.
632  */
633
634 static void isicom_tx(unsigned long _data)
635 {
636         short count = (BOARD_COUNT-1), card, base;
637         short txcount, wrd, residue, word_count, cnt;
638         struct isi_port * port;
639         struct tty_struct * tty;
640         
641 #ifdef ISICOM_DEBUG
642         ++tx_count;
643 #endif  
644         
645         /*      find next active board  */
646         card = (prev_card + 1) & 0x0003;
647         while(count-- > 0) {
648                 if (isi_card[card].status & BOARD_ACTIVE) 
649                         break;
650                 card = (card + 1) & 0x0003;     
651         }
652         if (!(isi_card[card].status & BOARD_ACTIVE))
653                 goto sched_again;
654                 
655         prev_card = card;
656         
657         count = isi_card[card].port_count;
658         port = isi_card[card].ports;
659         base = isi_card[card].base;
660         for (;count > 0;count--, port++) {
661                 if (!lock_card_at_interrupt(&isi_card[card]))
662                         continue;
663                 /* port not active or tx disabled to force flow control */
664                 if (!(port->flags & ASYNC_INITIALIZED) ||
665                         !(port->status & ISI_TXOK))
666                         unlock_card(&isi_card[card]);
667                         continue;
668                 
669                 tty = port->tty;
670                 
671                 
672                 if(tty == NULL) {
673                         unlock_card(&isi_card[card]);
674                         continue;
675                 }
676                 
677                 txcount = min_t(short, TX_SIZE, port->xmit_cnt);
678                 if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
679                         unlock_card(&isi_card[card]);
680                         continue;
681                 }
682                 if (!(inw(base + 0x02) & (1 << port->channel))) {
683                         unlock_card(&isi_card[card]);
684                         continue;               
685                 }
686 #ifdef ISICOM_DEBUG
687                 printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n", 
688                                 txcount, port->channel+1); 
689 #endif  
690                 outw((port->channel << isi_card[card].shift_count) | txcount
691                                         , base);
692                 residue = NO;
693                 wrd = 0;                        
694                 while (1) {
695                         cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
696                         if (residue == YES) {
697                                 residue = NO;
698                                 if (cnt > 0) {
699                                         wrd |= (port->xmit_buf[port->xmit_tail] << 8);
700                                         port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
701                                         port->xmit_cnt--;
702                                         txcount--;
703                                         cnt--;
704                                         outw(wrd, base);                        
705                                 }
706                                 else {
707                                         outw(wrd, base);
708                                         break;
709                                 }
710                         }               
711                         if (cnt <= 0) break;
712                         word_count = cnt >> 1;
713                         outsw(base, port->xmit_buf+port->xmit_tail, word_count);
714                         port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
715                                                 (SERIAL_XMIT_SIZE - 1);
716                         txcount -= (word_count << 1);
717                         port->xmit_cnt -= (word_count << 1);
718                         if (cnt & 0x0001) {
719                                 residue = YES;
720                                 wrd = port->xmit_buf[port->xmit_tail];
721                                 port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
722                                 port->xmit_cnt--;
723                                 txcount--;
724                         }
725                 }
726
727                 InterruptTheCard(base);
728                 if (port->xmit_cnt <= 0)
729                         port->status &= ~ISI_TXOK;
730                 if (port->xmit_cnt <= WAKEUP_CHARS)
731                         schedule_work(&port->bh_tqueue);
732                 unlock_card(&isi_card[card]);
733         }       
734
735         /*      schedule another tx for hopefully in about 10ms */      
736 sched_again:    
737         if (!re_schedule)       
738                 return;
739         init_timer(&tx);
740         tx.expires = jiffies + HZ/100;
741         tx.data = 0;
742         tx.function = isicom_tx;
743         add_timer(&tx);
744         
745         return; 
746 }               
747  
748 /*      Interrupt handlers      */
749
750  
751 static void isicom_bottomhalf(void * data)
752 {
753         struct isi_port * port = (struct isi_port *) data;
754         struct tty_struct * tty = port->tty;
755         
756         if (!tty)
757                 return;
758
759         tty_wakeup(tty);        
760         wake_up_interruptible(&tty->write_wait);
761 }               
762                 
763 /*
764  *      Main interrupt handler routine 
765  */
766  
767 static irqreturn_t isicom_interrupt(int irq, void *dev_id,
768                                         struct pt_regs *regs)
769 {
770         struct isi_board * card;
771         struct isi_port * port;
772         struct tty_struct * tty;
773         unsigned short base, header, word_count, count;
774         unsigned char channel;
775         short byte_count;
776         
777         card = (struct isi_board *) dev_id;
778
779         if (!card || !(card->status & FIRMWARE_LOADED))
780                 return IRQ_NONE;
781         
782         base = card->base;
783         spin_lock(&card->card_lock);
784         
785         if (card->isa == NO) {
786                 /*
787                  *      disable any interrupts from the PCI card and lower the
788                  *      interrupt line
789                  */
790                 outw(0x8000, base+0x04);
791                 ClearInterrupt(base);
792         }
793         
794         inw(base);              /* get the dummy word out */
795         header = inw(base);
796         channel = (header & 0x7800) >> card->shift_count;
797         byte_count = header & 0xff;
798
799         if (channel + 1 > card->port_count) {
800                 printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
801                                 base, channel+1);
802                 if (card->isa)
803                         ClearInterrupt(base);
804                 else
805                         outw(0x0000, base+0x04); /* enable interrupts */                
806                 spin_unlock(&card->card_lock);
807                 return IRQ_HANDLED;                     
808         }
809         port = card->ports + channel;
810         if (!(port->flags & ASYNC_INITIALIZED)) {
811                 if (card->isa)
812                         ClearInterrupt(base);
813                 else
814                         outw(0x0000, base+0x04); /* enable interrupts */
815                 return IRQ_HANDLED;
816         }       
817                 
818         tty = port->tty;
819         if (tty == NULL) {
820                 word_count = byte_count >> 1;
821                 while(byte_count > 1) {
822                         inw(base);
823                         byte_count -= 2;
824                 }
825                 if (byte_count & 0x01)
826                         inw(base);
827                 if (card->isa == YES)
828                         ClearInterrupt(base);
829                 else
830                         outw(0x0000, base+0x04); /* enable interrupts */
831                 spin_unlock(&card->card_lock);
832                 return IRQ_HANDLED;
833         }
834         
835         if (header & 0x8000) {          /* Status Packet */
836                 header = inw(base);
837                 switch(header & 0xff) {
838                         case 0: /* Change in EIA signals */
839                                 
840                                 if (port->flags & ASYNC_CHECK_CD) {
841                                         if (port->status & ISI_DCD) {
842                                                 if (!(header & ISI_DCD)) {
843                                                 /* Carrier has been lost  */
844 #ifdef ISICOM_DEBUG                                             
845                                                         printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
846 #endif                                                  
847                                                         port->status &= ~ISI_DCD;
848                                                         schedule_work(&port->hangup_tq);
849                                                 }
850                                         }
851                                         else {
852                                                 if (header & ISI_DCD) {
853                                                 /* Carrier has been detected */
854 #ifdef ISICOM_DEBUG
855                                                         printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
856 #endif                                                  
857                                                         port->status |= ISI_DCD;
858                                                         wake_up_interruptible(&port->open_wait);
859                                                 }
860                                         }
861                                 }
862                                 else {
863                                         if (header & ISI_DCD) 
864                                                 port->status |= ISI_DCD;
865                                         else
866                                                 port->status &= ~ISI_DCD;
867                                 }       
868                                 
869                                 if (port->flags & ASYNC_CTS_FLOW) {
870                                         if (port->tty->hw_stopped) {
871                                                 if (header & ISI_CTS) {
872                                                         port->tty->hw_stopped = 0;
873                                                         /* start tx ing */
874                                                         port->status |= (ISI_TXOK | ISI_CTS);
875                                                         schedule_work(&port->bh_tqueue);
876                                                 }
877                                         }
878                                         else {
879                                                 if (!(header & ISI_CTS)) {
880                                                         port->tty->hw_stopped = 1;
881                                                         /* stop tx ing */
882                                                         port->status &= ~(ISI_TXOK | ISI_CTS);
883                                                 }
884                                         }
885                                 }
886                                 else {
887                                         if (header & ISI_CTS) 
888                                                 port->status |= ISI_CTS;
889                                         else
890                                                 port->status &= ~ISI_CTS;
891                                 }
892                                 
893                                 if (header & ISI_DSR) 
894                                         port->status |= ISI_DSR;
895                                 else
896                                         port->status &= ~ISI_DSR;
897                                 
898                                 if (header & ISI_RI) 
899                                         port->status |= ISI_RI;
900                                 else
901                                         port->status &= ~ISI_RI;                                                
902                                 
903                                 break;
904                                 
905                         case 1: /* Received Break !!!    */
906                                 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
907                                         break;
908                                 *tty->flip.flag_buf_ptr++ = TTY_BREAK;
909                                 *tty->flip.char_buf_ptr++ = 0;
910                                 tty->flip.count++;
911                                 if (port->flags & ASYNC_SAK)
912                                         do_SAK(tty);
913                                 schedule_delayed_work(&tty->flip.work, 1);
914                                 break;
915                                 
916                         case 2: /* Statistics            */
917                                 printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");                     
918                                 break;
919                                 
920                         default:
921                                 printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n");
922                                 break;
923                 }        
924         }
925         else {                          /* Data   Packet */
926                 count = min_t(unsigned short, byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
927 #ifdef ISICOM_DEBUG
928                 printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", 
929                                         count, byte_count);
930 #endif                  
931                 word_count = count >> 1;
932                 insw(base, tty->flip.char_buf_ptr, word_count);
933                 tty->flip.char_buf_ptr += (word_count << 1);            
934                 byte_count -= (word_count << 1);
935                 if (count & 0x0001) {
936                         *tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
937                         byte_count -= 2;
938                 }       
939                 memset(tty->flip.flag_buf_ptr, 0, count);
940                 tty->flip.flag_buf_ptr += count;
941                 tty->flip.count += count;
942                 
943                 if (byte_count > 0) {
944                         printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
945                                         base, channel+1);
946                         while(byte_count > 0) { /* drain out unread xtra data */
947                                 inw(base);
948                                 byte_count -= 2;
949                         }
950                 }
951                 schedule_delayed_work(&tty->flip.work, 1);
952         }
953         if (card->isa == YES)
954                 ClearInterrupt(base);
955         else
956                 outw(0x0000, base+0x04); /* enable interrupts */        
957         return IRQ_HANDLED;
958
959
960 static void isicom_config_port(struct isi_port * port)
961 {
962         struct isi_board * card = port->card;
963         struct tty_struct * tty;
964         unsigned long baud;
965         unsigned short channel_setup, base = card->base;
966         unsigned short channel = port->channel, shift_count = card->shift_count;
967         unsigned char flow_ctrl;
968         
969         if (!(tty = port->tty) || !tty->termios)
970                 return;
971         baud = C_BAUD(tty);
972         if (baud & CBAUDEX) {
973                 baud &= ~CBAUDEX;
974                 
975                 /*  if CBAUDEX bit is on and the baud is set to either 50 or 75
976                  *  then the card is programmed for 57.6Kbps or 115Kbps
977                  *  respectively.
978                  */   
979                  
980                 if (baud < 1 || baud > 2)
981                         port->tty->termios->c_cflag &= ~CBAUDEX;
982                 else
983                         baud += 15;
984         }       
985         if (baud == 15) {
986         
987                 /*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set 
988                  *  by the set_serial_info ioctl ... this is done by
989                  *  the 'setserial' utility.
990                  */  
991                         
992                 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
993                         baud++;     /*  57.6 Kbps */
994                 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
995                         baud +=2;   /*  115  Kbps */     
996         }
997         if (linuxb_to_isib[baud] == -1) {
998                 /* hang up */
999                 drop_dtr(port);
1000                 return;
1001         }       
1002         else  
1003                 raise_dtr(port);
1004                 
1005         if (lock_card(card)) {
1006                 outw(0x8000 | (channel << shift_count) |0x03, base);
1007                 outw(linuxb_to_isib[baud] << 8 | 0x03, base);
1008                 channel_setup = 0;
1009                 switch(C_CSIZE(tty)) {
1010                         case CS5:
1011                                 channel_setup |= ISICOM_CS5;
1012                                 break;
1013                         case CS6:
1014                                 channel_setup |= ISICOM_CS6;
1015                                 break;
1016                         case CS7:
1017                                 channel_setup |= ISICOM_CS7;
1018                                 break;
1019                         case CS8:
1020                                 channel_setup |= ISICOM_CS8;
1021                                 break;
1022                 }
1023                         
1024                 if (C_CSTOPB(tty))
1025                         channel_setup |= ISICOM_2SB;
1026                 if (C_PARENB(tty)) {
1027                         channel_setup |= ISICOM_EVPAR;
1028                         if (C_PARODD(tty))
1029                                 channel_setup |= ISICOM_ODPAR;  
1030                 }
1031                 outw(channel_setup, base);      
1032                 InterruptTheCard(base);
1033                 unlock_card(card);      
1034         }       
1035         if (C_CLOCAL(tty))
1036                 port->flags &= ~ASYNC_CHECK_CD;
1037         else
1038                 port->flags |= ASYNC_CHECK_CD;  
1039         
1040         /* flow control settings ...*/
1041         flow_ctrl = 0;
1042         port->flags &= ~ASYNC_CTS_FLOW;
1043         if (C_CRTSCTS(tty)) {
1044                 port->flags |= ASYNC_CTS_FLOW;
1045                 flow_ctrl |= ISICOM_CTSRTS;
1046         }       
1047         if (I_IXON(tty))        
1048                 flow_ctrl |= ISICOM_RESPOND_XONXOFF;
1049         if (I_IXOFF(tty))
1050                 flow_ctrl |= ISICOM_INITIATE_XONXOFF;   
1051                 
1052         if (lock_card(card)) {
1053                 outw(0x8000 | (channel << shift_count) |0x04, base);
1054                 outw(flow_ctrl << 8 | 0x05, base);
1055                 outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
1056                 InterruptTheCard(base);
1057                 unlock_card(card);
1058         }
1059         
1060         /*      rx enabled -> enable port for rx on the card    */
1061         if (C_CREAD(tty)) {
1062                 card->port_status |= (1 << channel);
1063                 outw(card->port_status, base + 0x02);
1064         }
1065 }
1066  
1067 /* open et all */ 
1068
1069 static inline void isicom_setup_board(struct isi_board * bp)
1070 {
1071         int channel;
1072         struct isi_port * port;
1073         unsigned long flags;
1074         
1075         spin_lock_irqsave(&bp->card_lock, flags);
1076         if (bp->status & BOARD_ACTIVE) {
1077                 spin_unlock_irqrestore(&bp->card_lock, flags);
1078                 return;
1079         }
1080         port = bp->ports;
1081         bp->status |= BOARD_ACTIVE;
1082         spin_unlock_irqrestore(&bp->card_lock, flags);
1083         for(channel = 0; channel < bp->port_count; channel++, port++)
1084                 drop_dtr_rts(port);
1085         return;
1086 }
1087  
1088 static int isicom_setup_port(struct isi_port * port)
1089 {
1090         struct isi_board * card = port->card;
1091         unsigned long flags;
1092         
1093         if (port->flags & ASYNC_INITIALIZED) {
1094                 return 0;
1095         }
1096         if (!port->xmit_buf) {
1097                 unsigned long page;
1098                 
1099                 if (!(page = get_zeroed_page(GFP_KERNEL)))
1100                         return -ENOMEM;
1101                 
1102                 if (port->xmit_buf) {
1103                         free_page(page);
1104                         return -ERESTARTSYS;
1105                 }
1106                 port->xmit_buf = (unsigned char *) page;        
1107         }       
1108
1109         spin_lock_irqsave(&card->card_lock, flags);
1110         if (port->tty)
1111                 clear_bit(TTY_IO_ERROR, &port->tty->flags);
1112         if (port->count == 1)
1113                 card->count++;
1114                 
1115         port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1116         
1117         /*      discard any residual data       */
1118         kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
1119         
1120         isicom_config_port(port);
1121         port->flags |= ASYNC_INITIALIZED;
1122         spin_unlock_irqrestore(&card->card_lock, flags);
1123         
1124         return 0;               
1125
1126  
1127 static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port) 
1128 {
1129         struct isi_board * card = port->card;
1130         int do_clocal = 0, retval;
1131         unsigned long flags;
1132         DECLARE_WAITQUEUE(wait, current);
1133
1134         /* block if port is in the process of being closed */
1135
1136         if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
1137 #ifdef ISICOM_DEBUG     
1138                 printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
1139 #endif          
1140                 interruptible_sleep_on(&port->close_wait);
1141                 if (port->flags & ASYNC_HUP_NOTIFY)
1142                         return -EAGAIN;
1143                 else
1144                         return -ERESTARTSYS;
1145         }
1146         
1147         /* if non-blocking mode is set ... */
1148         
1149         if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
1150 #ifdef ISICOM_DEBUG     
1151                 printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
1152 #endif          
1153                 port->flags |= ASYNC_NORMAL_ACTIVE;
1154                 return 0;       
1155         }       
1156         
1157         if (C_CLOCAL(tty))
1158                 do_clocal = 1;
1159         
1160         /* block waiting for DCD to be asserted, and while 
1161                                                 callout dev is busy */
1162         retval = 0;
1163         add_wait_queue(&port->open_wait, &wait);
1164
1165         spin_lock_irqsave(&card->card_lock, flags);
1166         if (!tty_hung_up_p(filp))
1167                 port->count--;
1168         port->blocked_open++;
1169         spin_unlock_irqrestore(&card->card_lock, flags);
1170         
1171         while (1) {
1172                 raise_dtr_rts(port);
1173
1174                 set_current_state(TASK_INTERRUPTIBLE);
1175                 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {        
1176                         if (port->flags & ASYNC_HUP_NOTIFY)
1177                                 retval = -EAGAIN;
1178                         else
1179                                 retval = -ERESTARTSYS;
1180                         break;
1181                 }       
1182                 if (!(port->flags & ASYNC_CLOSING) &&
1183                     (do_clocal || (port->status & ISI_DCD))) {
1184                         break;
1185                 }       
1186                 if (signal_pending(current)) {
1187                         retval = -ERESTARTSYS;
1188                         break;
1189                 }
1190                 schedule();             
1191         }
1192         set_current_state(TASK_RUNNING);
1193         remove_wait_queue(&port->open_wait, &wait);
1194         spin_lock_irqsave(&card->card_lock, flags);
1195         if (!tty_hung_up_p(filp))
1196                 port->count++;
1197         port->blocked_open--;
1198         spin_unlock_irqrestore(&card->card_lock, flags);
1199         if (retval)
1200                 return retval;
1201         port->flags |= ASYNC_NORMAL_ACTIVE;
1202         return 0;
1203 }
1204  
1205 static int isicom_open(struct tty_struct * tty, struct file * filp)
1206 {
1207         struct isi_port * port;
1208         struct isi_board * card;
1209         unsigned int line, board;
1210         int error;
1211
1212         line = tty->index;
1213         if (line < 0 || line > PORT_COUNT-1)
1214                 return -ENODEV;
1215         board = BOARD(line);
1216         card = &isi_card[board];
1217         
1218         if (!(card->status & FIRMWARE_LOADED))
1219                 return -ENODEV;
1220         
1221         /*  open on a port greater than the port count for the card !!! */
1222         if (line > ((board * 16) + card->port_count - 1))
1223                 return -ENODEV;
1224
1225         port = &isi_ports[line];        
1226         if (isicom_paranoia_check(port, tty->name, "isicom_open"))
1227                 return -ENODEV;
1228                 
1229         isicom_setup_board(card);               
1230         
1231         port->count++;
1232         tty->driver_data = port;
1233         port->tty = tty;
1234         if ((error = isicom_setup_port(port))!=0)
1235                 return error;
1236         if ((error = block_til_ready(tty, filp, port))!=0)
1237                 return error;
1238
1239         return 0;               
1240 }
1241  
1242 /* close et all */
1243
1244 static inline void isicom_shutdown_board(struct isi_board * bp)
1245 {
1246         unsigned long flags;
1247
1248         spin_lock_irqsave(&bp->card_lock, flags);
1249         if (bp->status & BOARD_ACTIVE) {
1250                 bp->status &= ~BOARD_ACTIVE;
1251         }
1252         spin_unlock_irqrestore(&bp->card_lock, flags);
1253 }
1254
1255 static void isicom_shutdown_port(struct isi_port * port)
1256 {
1257         struct isi_board * card = port->card;
1258         struct tty_struct * tty;        
1259         unsigned long flags;
1260         
1261         tty = port->tty;
1262
1263         spin_lock_irqsave(&card->card_lock, flags);     
1264         if (!(port->flags & ASYNC_INITIALIZED)) {
1265                 spin_unlock_irqrestore(&card->card_lock, flags);
1266                 return;
1267         }
1268         if (port->xmit_buf) {
1269                 free_page((unsigned long) port->xmit_buf);
1270                 port->xmit_buf = NULL;
1271         }       
1272         port->flags &= ~ASYNC_INITIALIZED;
1273         /* 3rd October 2000 : Vinayak P Risbud */
1274         port->tty = NULL;
1275         spin_unlock_irqrestore(&card->card_lock, flags);
1276         
1277         /*Fix done by Anil .S on 30-04-2001
1278         remote login through isi port has dtr toggle problem
1279         due to which the carrier drops before the password prompt
1280         appears on the remote end. Now we drop the dtr only if the 
1281         HUPCL(Hangup on close) flag is set for the tty*/
1282         
1283         if (C_HUPCL(tty)) 
1284                 /* drop dtr on this port */
1285                 drop_dtr(port);
1286                 
1287         /* any other port uninits  */ 
1288         if (tty)
1289                 set_bit(TTY_IO_ERROR, &tty->flags);
1290         
1291         if (--card->count < 0) {
1292                 printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
1293                         card->base, card->count);
1294                 card->count = 0;        
1295         }
1296         
1297         /* last port was closed , shutdown that boad too */
1298         if(C_HUPCL(tty)) {
1299                 if (!card->count)
1300                         isicom_shutdown_board(card);
1301         }
1302 }
1303
1304 static void isicom_close(struct tty_struct * tty, struct file * filp)
1305 {
1306         struct isi_port * port = (struct isi_port *) tty->driver_data;
1307         struct isi_board * card = port->card;
1308         unsigned long flags;
1309         
1310         if (!port)
1311                 return;
1312         if (isicom_paranoia_check(port, tty->name, "isicom_close"))
1313                 return;
1314         
1315 #ifdef ISICOM_DEBUG             
1316         printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
1317 #endif  
1318         
1319         spin_lock_irqsave(&card->card_lock, flags);
1320         if (tty_hung_up_p(filp)) {
1321                 spin_unlock_irqrestore(&card->card_lock, flags);
1322                 return;
1323         }
1324         
1325         if (tty->count == 1 && port->count != 1) {
1326                 printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
1327                         "tty->count = 1 port count = %d.\n",
1328                         card->base, port->count);
1329                 port->count = 1;
1330         }
1331         if (--port->count < 0) {
1332                 printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
1333                         "channel%d = %d", card->base, port->channel, 
1334                         port->count);
1335                 port->count = 0;        
1336         }
1337         
1338         if (port->count) {
1339                 spin_unlock_irqrestore(&card->card_lock, flags);
1340                 return;
1341         }       
1342         port->flags |= ASYNC_CLOSING;
1343         tty->closing = 1;
1344         spin_unlock_irqrestore(&card->card_lock, flags);
1345         
1346         if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1347                 tty_wait_until_sent(tty, port->closing_wait);
1348         /* indicate to the card that no more data can be received 
1349            on this port */
1350         spin_lock_irqsave(&card->card_lock, flags);
1351         if (port->flags & ASYNC_INITIALIZED) {   
1352                 card->port_status &= ~(1 << port->channel);
1353                 outw(card->port_status, card->base + 0x02);
1354         }       
1355         isicom_shutdown_port(port);
1356         spin_unlock_irqrestore(&card->card_lock, flags);
1357         
1358         if (tty->driver->flush_buffer)
1359                 tty->driver->flush_buffer(tty);
1360         tty_ldisc_flush(tty);
1361
1362         spin_lock_irqsave(&card->card_lock, flags);
1363         tty->closing = 0;
1364
1365         if (port->blocked_open) {
1366                 spin_unlock_irqrestore(&card->card_lock, flags);
1367                 if (port->close_delay) {
1368 #ifdef ISICOM_DEBUG                     
1369                         printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
1370 #endif                  
1371                         msleep_interruptible(jiffies_to_msecs(port->close_delay));
1372                 }
1373                 spin_lock_irqsave(&card->card_lock, flags);
1374                 wake_up_interruptible(&port->open_wait);
1375         }       
1376         port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
1377         wake_up_interruptible(&port->close_wait);
1378         spin_unlock_irqrestore(&card->card_lock, flags);
1379 }
1380
1381 /* write et all */
1382 static int isicom_write(struct tty_struct * tty,
1383                         const unsigned char * buf, int count)
1384 {
1385         struct isi_port * port = (struct isi_port *) tty->driver_data;
1386         struct isi_board * card = port->card;
1387         unsigned long flags;
1388         int cnt, total = 0;
1389
1390         if (isicom_paranoia_check(port, tty->name, "isicom_write"))
1391                 return 0;
1392         
1393         if (!tty || !port->xmit_buf || !tmp_buf)
1394                 return 0;
1395                 
1396         spin_lock_irqsave(&card->card_lock, flags);
1397         
1398         while(1) {      
1399                 cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1400                                             SERIAL_XMIT_SIZE - port->xmit_head));
1401                 if (cnt <= 0) 
1402                         break;
1403                 
1404                 memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
1405                 port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
1406                 port->xmit_cnt += cnt;
1407                 buf += cnt;
1408                 count -= cnt;
1409                 total += cnt;
1410         }               
1411         if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
1412                 port->status |= ISI_TXOK;
1413         spin_unlock_irqrestore(&card->card_lock, flags);
1414         return total;   
1415 }
1416
1417 /* put_char et all */
1418 static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
1419 {
1420         struct isi_port * port = (struct isi_port *) tty->driver_data;
1421         struct isi_board * card = port->card;
1422         unsigned long flags;
1423         
1424         if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
1425                 return;
1426         
1427         if (!tty || !port->xmit_buf)
1428                 return;
1429
1430         spin_lock_irqsave(&card->card_lock, flags);
1431         if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
1432                 spin_unlock_irqrestore(&card->card_lock, flags);
1433                 return;
1434         }
1435         
1436         port->xmit_buf[port->xmit_head++] = ch;
1437         port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
1438         port->xmit_cnt++;
1439         spin_unlock_irqrestore(&card->card_lock, flags);
1440 }
1441
1442 /* flush_chars et all */
1443 static void isicom_flush_chars(struct tty_struct * tty)
1444 {
1445         struct isi_port * port = (struct isi_port *) tty->driver_data;
1446         
1447         if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
1448                 return;
1449         
1450         if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !port->xmit_buf)
1451                 return;
1452                 
1453         /* this tells the transmitter to consider this port for
1454            data output to the card ... that's the best we can do. */
1455         port->status |= ISI_TXOK;       
1456 }
1457
1458 /* write_room et all */
1459 static int isicom_write_room(struct tty_struct * tty)
1460 {
1461         struct isi_port * port = (struct isi_port *) tty->driver_data;
1462         int free;
1463
1464         if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
1465                 return 0;
1466         
1467         free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1468         if (free < 0)
1469                 free = 0;
1470         return free;
1471 }
1472
1473 /* chars_in_buffer et all */
1474 static int isicom_chars_in_buffer(struct tty_struct * tty)
1475 {
1476         struct isi_port * port = (struct isi_port *) tty->driver_data;
1477         if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
1478                 return 0;
1479         return port->xmit_cnt;
1480 }
1481
1482 /* ioctl et all */
1483 static inline void isicom_send_break(struct isi_port * port, unsigned long length)
1484 {
1485         struct isi_board * card = port->card;
1486         unsigned short base = card->base;       
1487         
1488         if(!lock_card(card))
1489                 return;
1490                 
1491         outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
1492         outw((length & 0xff) << 8 | 0x00, base);
1493         outw((length & 0xff00), base);
1494         InterruptTheCard(base);
1495
1496         unlock_card(card);
1497 }
1498
1499 static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
1500 {
1501         struct isi_port * port = (struct isi_port *) tty->driver_data;
1502         /* just send the port status */
1503         unsigned short status = port->status;
1504
1505         if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1506                 return -ENODEV;
1507         
1508         return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
1509                 ((status & ISI_DTR) ? TIOCM_DTR : 0) |
1510                 ((status & ISI_DCD) ? TIOCM_CAR : 0) |
1511                 ((status & ISI_DSR) ? TIOCM_DSR : 0) |
1512                 ((status & ISI_CTS) ? TIOCM_CTS : 0) |
1513                 ((status & ISI_RI ) ? TIOCM_RI  : 0);
1514 }
1515
1516 static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
1517                            unsigned int set, unsigned int clear)
1518 {
1519         struct isi_port * port = (struct isi_port *) tty->driver_data;
1520         
1521         if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1522                 return -ENODEV;
1523         
1524         if (set & TIOCM_RTS)
1525                 raise_rts(port);
1526         if (set & TIOCM_DTR)
1527                 raise_dtr(port);
1528
1529         if (clear & TIOCM_RTS)
1530                 drop_rts(port);
1531         if (clear & TIOCM_DTR)
1532                 drop_dtr(port);
1533
1534         return 0;
1535 }                       
1536
1537 static int isicom_set_serial_info(struct isi_port * port,
1538                                         struct serial_struct __user *info)
1539 {
1540         struct serial_struct newinfo;
1541         int reconfig_port;
1542
1543         if(copy_from_user(&newinfo, info, sizeof(newinfo)))
1544                 return -EFAULT;
1545                 
1546         reconfig_port = ((port->flags & ASYNC_SPD_MASK) != 
1547                          (newinfo.flags & ASYNC_SPD_MASK));
1548         
1549         if (!capable(CAP_SYS_ADMIN)) {
1550                 if ((newinfo.close_delay != port->close_delay) ||
1551                     (newinfo.closing_wait != port->closing_wait) ||
1552                     ((newinfo.flags & ~ASYNC_USR_MASK) != 
1553                      (port->flags & ~ASYNC_USR_MASK)))
1554                         return -EPERM;
1555                 port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
1556                                 (newinfo.flags & ASYNC_USR_MASK));
1557         }       
1558         else {
1559                 port->close_delay = newinfo.close_delay;
1560                 port->closing_wait = newinfo.closing_wait; 
1561                 port->flags = ((port->flags & ~ASYNC_FLAGS) | 
1562                                 (newinfo.flags & ASYNC_FLAGS));
1563         }
1564         if (reconfig_port) {
1565                 isicom_config_port(port);
1566         }
1567         return 0;                
1568 }               
1569
1570 static int isicom_get_serial_info(struct isi_port * port, 
1571                                         struct serial_struct __user *info)
1572 {
1573         struct serial_struct out_info;
1574         
1575         memset(&out_info, 0, sizeof(out_info));
1576 /*      out_info.type = ? */
1577         out_info.line = port - isi_ports;
1578         out_info.port = port->card->base;
1579         out_info.irq = port->card->irq;
1580         out_info.flags = port->flags;
1581 /*      out_info.baud_base = ? */
1582         out_info.close_delay = port->close_delay;
1583         out_info.closing_wait = port->closing_wait;
1584         if(copy_to_user(info, &out_info, sizeof(out_info)))
1585                 return -EFAULT;
1586         return 0;
1587 }                                       
1588
1589 static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
1590                         unsigned int cmd, unsigned long arg) 
1591 {
1592         struct isi_port * port = (struct isi_port *) tty->driver_data;
1593         void __user *argp = (void __user *)arg;
1594         int retval;
1595
1596         if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
1597                 return -ENODEV;
1598
1599         switch(cmd) {
1600                 case TCSBRK:
1601                         retval = tty_check_change(tty);
1602                         if (retval)
1603                                 return retval;
1604                         tty_wait_until_sent(tty, 0);
1605                         if (!arg)
1606                                 isicom_send_break(port, HZ/4);
1607                         return 0;
1608                         
1609                 case TCSBRKP:   
1610                         retval = tty_check_change(tty);
1611                         if (retval)
1612                                 return retval;
1613                         tty_wait_until_sent(tty, 0);
1614                         isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
1615                         return 0;
1616                         
1617                 case TIOCGSOFTCAR:
1618                         return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
1619                         
1620                 case TIOCSSOFTCAR:
1621                         if(get_user(arg, (unsigned long __user *) argp))
1622                                 return -EFAULT;
1623                         tty->termios->c_cflag =
1624                                 ((tty->termios->c_cflag & ~CLOCAL) |
1625                                 (arg ? CLOCAL : 0));
1626                         return 0;       
1627                         
1628                 case TIOCGSERIAL:
1629                         return isicom_get_serial_info(port, argp);
1630                 
1631                 case TIOCSSERIAL:
1632                         return isicom_set_serial_info(port, argp);
1633                                         
1634                 default:
1635                         return -ENOIOCTLCMD;                                            
1636         }
1637         return 0;
1638 }
1639
1640 /* set_termios et all */
1641 static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
1642 {
1643         struct isi_port * port = (struct isi_port *) tty->driver_data;
1644         
1645         if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
1646                 return;
1647         
1648         if (tty->termios->c_cflag == old_termios->c_cflag &&
1649             tty->termios->c_iflag == old_termios->c_iflag)
1650                 return;
1651                 
1652         isicom_config_port(port);
1653         
1654         if ((old_termios->c_cflag & CRTSCTS) &&
1655             !(tty->termios->c_cflag & CRTSCTS)) {       
1656                 tty->hw_stopped = 0;
1657                 isicom_start(tty);   
1658         }    
1659 }
1660
1661 /* throttle et all */
1662 static void isicom_throttle(struct tty_struct * tty)
1663 {
1664         struct isi_port * port = (struct isi_port *) tty->driver_data;
1665         struct isi_board * card = port->card;
1666         
1667         if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
1668                 return;
1669         
1670         /* tell the card that this port cannot handle any more data for now */
1671         card->port_status &= ~(1 << port->channel);
1672         outw(card->port_status, card->base + 0x02);
1673 }
1674
1675 /* unthrottle et all */
1676 static void isicom_unthrottle(struct tty_struct * tty)
1677 {
1678         struct isi_port * port = (struct isi_port *) tty->driver_data;
1679         struct isi_board * card = port->card;
1680         
1681         if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
1682                 return;
1683         
1684         /* tell the card that this port is ready to accept more data */
1685         card->port_status |= (1 << port->channel);
1686         outw(card->port_status, card->base + 0x02);
1687 }
1688
1689 /* stop et all */
1690 static void isicom_stop(struct tty_struct * tty)
1691 {
1692         struct isi_port * port = (struct isi_port *) tty->driver_data;
1693
1694         if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
1695                 return;
1696         
1697         /* this tells the transmitter not to consider this port for
1698            data output to the card. */
1699         port->status &= ~ISI_TXOK;
1700 }
1701
1702 /* start et all */
1703 static void isicom_start(struct tty_struct * tty)
1704 {
1705         struct isi_port * port = (struct isi_port *) tty->driver_data;
1706         
1707         if (isicom_paranoia_check(port, tty->name, "isicom_start"))
1708                 return;
1709         
1710         /* this tells the transmitter to consider this port for
1711            data output to the card. */
1712         port->status |= ISI_TXOK;
1713 }
1714
1715 /* hangup et all */
1716 static void do_isicom_hangup(void * data)
1717 {
1718         struct isi_port * port = (struct isi_port *) data;
1719         struct tty_struct * tty;
1720         
1721         tty = port->tty;
1722         if (tty)
1723                 tty_hangup(tty);
1724 }
1725
1726 static void isicom_hangup(struct tty_struct * tty)
1727 {
1728         struct isi_port * port = (struct isi_port *) tty->driver_data;
1729         
1730         if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
1731                 return;
1732         
1733         isicom_shutdown_port(port);
1734         port->count = 0;
1735         port->flags &= ~ASYNC_NORMAL_ACTIVE;
1736         port->tty = NULL;
1737         wake_up_interruptible(&port->open_wait);
1738 }
1739
1740 /* flush_buffer et all */
1741 static void isicom_flush_buffer(struct tty_struct * tty)
1742 {
1743         struct isi_port * port = (struct isi_port *) tty->driver_data;
1744         struct isi_board * card = port->card;
1745         unsigned long flags;
1746         
1747         if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
1748                 return;
1749         
1750         spin_lock_irqsave(&card->card_lock, flags);
1751         port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1752         spin_unlock_irqrestore(&card->card_lock, flags);
1753         
1754         wake_up_interruptible(&tty->write_wait);
1755         tty_wakeup(tty);
1756 }
1757
1758
1759 static int __devinit register_ioregion(void)
1760 {
1761         int count, done=0;
1762         for (count=0; count < BOARD_COUNT; count++ ) {
1763                 if (isi_card[count].base)
1764                         if (!request_region(isi_card[count].base,16,ISICOM_NAME)) {
1765                                 printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
1766                                         isi_card[count].base,isi_card[count].base+15,count+1);
1767                                 isi_card[count].base=0;
1768                                 done++;
1769                         }
1770         }
1771         return done;
1772 }
1773
1774 static void unregister_ioregion(void)
1775 {
1776         int count;
1777         for (count=0; count < BOARD_COUNT; count++ ) 
1778                 if (isi_card[count].base) {
1779                         release_region(isi_card[count].base,16);
1780 #ifdef ISICOM_DEBUG                     
1781                         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);
1782 #endif                  
1783                 }
1784 }
1785
1786 static struct tty_operations isicom_ops = {
1787         .open   = isicom_open,
1788         .close  = isicom_close,
1789         .write  = isicom_write,
1790         .put_char       = isicom_put_char,
1791         .flush_chars    = isicom_flush_chars,
1792         .write_room     = isicom_write_room,
1793         .chars_in_buffer        = isicom_chars_in_buffer,
1794         .ioctl  = isicom_ioctl,
1795         .set_termios    = isicom_set_termios,
1796         .throttle       = isicom_throttle,
1797         .unthrottle     = isicom_unthrottle,
1798         .stop   = isicom_stop,
1799         .start  = isicom_start,
1800         .hangup = isicom_hangup,
1801         .flush_buffer   = isicom_flush_buffer,
1802         .tiocmget       = isicom_tiocmget,
1803         .tiocmset       = isicom_tiocmset,
1804 };
1805
1806 static int __devinit register_drivers(void)
1807 {
1808         int error;
1809
1810         /* tty driver structure initialization */
1811         isicom_normal = alloc_tty_driver(PORT_COUNT);
1812         if (!isicom_normal)
1813                 return -ENOMEM;
1814
1815         isicom_normal->owner    = THIS_MODULE;
1816         isicom_normal->name     = "ttyM";
1817         isicom_normal->devfs_name = "isicom/";
1818         isicom_normal->major    = ISICOM_NMAJOR;
1819         isicom_normal->minor_start      = 0;
1820         isicom_normal->type     = TTY_DRIVER_TYPE_SERIAL;
1821         isicom_normal->subtype  = SERIAL_TYPE_NORMAL;
1822         isicom_normal->init_termios     = tty_std_termios;
1823         isicom_normal->init_termios.c_cflag     = 
1824                                 B9600 | CS8 | CREAD | HUPCL |CLOCAL;
1825         isicom_normal->flags    = TTY_DRIVER_REAL_RAW;
1826         tty_set_operations(isicom_normal, &isicom_ops);
1827         
1828         if ((error=tty_register_driver(isicom_normal))!=0) {
1829                 printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
1830                         error);
1831                 put_tty_driver(isicom_normal);
1832                 return error;
1833         }
1834         return 0;
1835 }
1836
1837 static void unregister_drivers(void)
1838 {
1839         int error = tty_unregister_driver(isicom_normal);
1840         if (error)
1841                 printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
1842         put_tty_driver(isicom_normal);
1843 }
1844
1845 static int __devinit register_isr(void)
1846 {
1847         int count, done=0;
1848         unsigned long irqflags;
1849
1850         for (count=0; count < BOARD_COUNT; count++ ) {
1851                 if (isi_card[count].base) {
1852                         irqflags = (isi_card[count].isa == YES) ? 
1853                                         SA_INTERRUPT : 
1854                                         (SA_INTERRUPT | SA_SHIRQ);
1855
1856                         if (request_irq(isi_card[count].irq, 
1857                                         isicom_interrupt, 
1858                                         irqflags, 
1859                                         ISICOM_NAME, &isi_card[count])) {
1860
1861                                 printk(KERN_WARNING "ISICOM: Could not"
1862                                         " install handler at Irq %d."
1863                                         " Card%d will be disabled.\n",
1864                                         isi_card[count].irq, count+1);
1865
1866                                 release_region(isi_card[count].base,16);
1867                                 isi_card[count].base=0;
1868                         }
1869                         else
1870                                 done++;
1871                 }       
1872         }
1873         return done;
1874 }
1875
1876 static void __exit unregister_isr(void)
1877 {
1878         int count;
1879
1880         for (count=0; count < BOARD_COUNT; count++ ) {
1881                 if (isi_card[count].base)
1882                         free_irq(isi_card[count].irq, &isi_card[count]);
1883         }
1884 }
1885
1886 static int __devinit isicom_init(void)
1887 {
1888         int card, channel, base;
1889         struct isi_port * port;
1890         unsigned long page;
1891         
1892         if (!tmp_buf) { 
1893                 page = get_zeroed_page(GFP_KERNEL);
1894                 if (!page) {
1895 #ifdef ISICOM_DEBUG             
1896                         printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
1897 #else
1898                         printk(KERN_ERR "ISICOM: Not enough memory...\n");
1899 #endif        
1900                         return 0;
1901                 }       
1902                 tmp_buf = (unsigned char *) page;
1903         }
1904         
1905         if (!register_ioregion()) 
1906         {
1907                 printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");
1908                 free_page((unsigned long)tmp_buf);
1909                 return 0;
1910         }
1911         if (register_drivers()) 
1912         {
1913                 unregister_ioregion();
1914                 free_page((unsigned long)tmp_buf);
1915                 return 0;
1916         }
1917         if (!register_isr()) 
1918         {
1919                 unregister_drivers();
1920                 /*  ioports already uregistered in register_isr */
1921                 free_page((unsigned long)tmp_buf);
1922                 return 0;               
1923         }
1924         
1925         memset(isi_ports, 0, sizeof(isi_ports));
1926         for (card = 0; card < BOARD_COUNT; card++) {
1927                 port = &isi_ports[card * 16];
1928                 isi_card[card].ports = port;
1929                 spin_lock_init(&isi_card[card].card_lock);
1930                 base = isi_card[card].base;
1931                 for (channel = 0; channel < 16; channel++, port++) {
1932                         port->magic = ISICOM_MAGIC;
1933                         port->card = &isi_card[card];
1934                         port->channel = channel;
1935                         port->close_delay = 50 * HZ/100;
1936                         port->closing_wait = 3000 * HZ/100;
1937                         INIT_WORK(&port->hangup_tq, do_isicom_hangup, port);
1938                         INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port);
1939                         port->status = 0;
1940                         init_waitqueue_head(&port->open_wait);                                  
1941                         init_waitqueue_head(&port->close_wait);
1942                         /*  . . .  */
1943                 }
1944         } 
1945         
1946         return 1;       
1947 }
1948
1949 /*
1950  *      Insmod can set static symbols so keep these static
1951  */
1952  
1953 static int io[4];
1954 static int irq[4];
1955
1956 MODULE_AUTHOR("MultiTech");
1957 MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
1958 MODULE_LICENSE("GPL");
1959 module_param_array(io, int, NULL, 0);
1960 MODULE_PARM_DESC(io, "I/O ports for the cards");
1961 module_param_array(irq, int, NULL, 0);
1962 MODULE_PARM_DESC(irq, "Interrupts for the cards");
1963
1964 static int __devinit isicom_setup(void)
1965 {
1966         struct pci_dev *dev = NULL;
1967         int retval, card, idx, count;
1968         unsigned char pciirq;
1969         unsigned int ioaddr;
1970                         
1971         card = 0;
1972         for(idx=0; idx < BOARD_COUNT; idx++) {  
1973                 if (io[idx]) {
1974                         isi_card[idx].base=io[idx];
1975                         isi_card[idx].irq=irq[idx];
1976                         isi_card[idx].isa=YES;
1977                         card++;
1978                 }
1979                 else {
1980                         isi_card[idx].base = 0;
1981                         isi_card[idx].irq = 0;
1982                 }
1983         }
1984         
1985         for (idx=0 ;idx < card; idx++) {
1986                 if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)||
1987                     (isi_card[idx].irq==4)||(isi_card[idx].irq==5)||
1988                     (isi_card[idx].irq==7)||(isi_card[idx].irq==10)||
1989                     (isi_card[idx].irq==11)||(isi_card[idx].irq==12)||
1990                     (isi_card[idx].irq==15))) {
1991                         
1992                         if (isi_card[idx].base) {
1993                                 printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
1994                                         isi_card[idx].irq, idx+1);
1995                                 isi_card[idx].base=0;
1996                                 card--;
1997                         }       
1998                 }
1999         }       
2000         
2001         if (card < BOARD_COUNT) {
2002                 for (idx=0; idx < DEVID_COUNT; idx++) {
2003                         dev = NULL;
2004                         for (;;){
2005                                 if (!(dev = pci_find_device(VENDOR_ID, isicom_pci_tbl[idx].device, dev)))
2006                                         break;
2007                                 if (card >= BOARD_COUNT)
2008                                         break;
2009                                         
2010                                 if (pci_enable_device(dev))
2011                                         break;
2012
2013                                 /* found a PCI ISI card! */
2014                                 ioaddr = pci_resource_start (dev, 3); /* i.e at offset 0x1c in the
2015                                                                        * PCI configuration register
2016                                                                        * space.
2017                                                                        */
2018                                 pciirq = dev->irq;
2019                                 printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", isicom_pci_tbl[idx].device);
2020                                 /*
2021                                  * allot the first empty slot in the array
2022                                  */                             
2023                                 for (count=0; count < BOARD_COUNT; count++) {                           
2024                                         if (isi_card[count].base == 0) {
2025                                                 isi_card[count].base = ioaddr;
2026                                                 isi_card[count].irq = pciirq;
2027                                                 isi_card[count].isa = NO;
2028                                                 card++;
2029                                                 break;
2030                                         }
2031                                 }
2032                         }                               
2033                         if (card >= BOARD_COUNT) break;
2034                 }
2035         }
2036         
2037         if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
2038                 printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); 
2039                 return -EIO;
2040         }       
2041
2042         retval = misc_register(&isiloader_device);
2043         if (retval < 0) {
2044                 printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
2045                 return retval;
2046         }
2047         
2048         if (!isicom_init()) {
2049                 if (misc_deregister(&isiloader_device)) 
2050                         printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
2051                 return -EIO;
2052         }
2053         
2054         init_timer(&tx);
2055         tx.expires = jiffies + 1;
2056         tx.data = 0;
2057         tx.function = isicom_tx;
2058         re_schedule = 1;
2059         add_timer(&tx);
2060         
2061         return 0;
2062 }
2063
2064 static void __exit isicom_exit(void)
2065 {
2066         re_schedule = 0;
2067         /* FIXME */
2068         msleep(1000);
2069         unregister_isr();
2070         unregister_drivers();
2071         unregister_ioregion();  
2072         if(tmp_buf)
2073                 free_page((unsigned long)tmp_buf);
2074         if (misc_deregister(&isiloader_device))
2075                 printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
2076 }
2077
2078 module_init(isicom_setup);
2079 module_exit(isicom_exit);