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.
7 * Original driver code supplied by Multi-Tech
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)
15 * 9/12/98 alan@redhat.com Rough port to 2.1.x
17 * 10/6/99 sameer Merged the ISA and PCI drivers to
18 * a new unified driver.
19 * 09/06/01 acme@conectiva.com.br use capable, not suser, do
20 * restore_flags on failure in
21 * isicom_send_break, verify put_user
23 * ***********************************************************
25 * To use this driver you also need the support package. You
26 * can find this in RPM format on
27 * ftp://ftp.linux.org.uk/pub/linux/alan
29 * You can find the original tools for this direct from Multitech
30 * ftp://ftp.multitech.com/ISI-Cards/
32 * Having installed the cards the module options (/etc/modprobe.conf)
34 * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4
36 * Omit those entries for boards you don't have installed.
40 #include <linux/module.h>
41 #include <linux/kernel.h>
42 #include <linux/tty.h>
43 #include <linux/termios.h>
45 #include <linux/sched.h>
46 #include <linux/serial.h>
48 #include <linux/miscdevice.h>
49 #include <linux/interrupt.h>
50 #include <linux/timer.h>
51 #include <linux/delay.h>
52 #include <linux/ioport.h>
54 #include <asm/uaccess.h>
56 #include <asm/system.h>
58 #include <linux/pci.h>
60 #include <linux/isicom.h>
62 static struct pci_device_id isicom_pci_tbl
[] = {
63 { VENDOR_ID
, 0x2028, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
64 { VENDOR_ID
, 0x2051, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
65 { VENDOR_ID
, 0x2052, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
66 { VENDOR_ID
, 0x2053, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
67 { VENDOR_ID
, 0x2054, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
68 { VENDOR_ID
, 0x2055, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
69 { VENDOR_ID
, 0x2056, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
70 { VENDOR_ID
, 0x2057, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
71 { VENDOR_ID
, 0x2058, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
74 MODULE_DEVICE_TABLE(pci
, isicom_pci_tbl
);
76 static int prev_card
= 3; /* start servicing isi_card[0] */
77 static struct isi_board
* irq_to_board
[16];
78 static struct tty_driver
*isicom_normal
;
80 static struct isi_board isi_card
[BOARD_COUNT
];
81 static struct isi_port isi_ports
[PORT_COUNT
];
83 static struct timer_list tx
;
84 static char re_schedule
= 1;
86 static unsigned long tx_count
= 0;
89 static int ISILoad_ioctl(struct inode
*inode
, struct file
*filp
, unsigned int cmd
, unsigned long arg
);
91 static void isicom_tx(unsigned long _data
);
92 static void isicom_start(struct tty_struct
* tty
);
94 static unsigned char * tmp_buf
;
95 static DECLARE_MUTEX(tmp_buf_sem
);
97 /* baud index mappings from linux defns to isi */
99 static signed char linuxb_to_isib
[] = {
100 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,
105 * Firmware loader driver specific routines
109 static struct file_operations ISILoad_fops
= {
110 .owner
= THIS_MODULE
,
111 .ioctl
= ISILoad_ioctl
,
114 struct miscdevice isiloader_device
= {
115 ISILOAD_MISC_MINOR
, "isictl", &ISILoad_fops
119 static inline int WaitTillCardIsFree(unsigned short base
)
121 unsigned long count
=0;
122 while( (!(inw(base
+0xe) & 0x1)) && (count
++ < 6000000));
123 if (inw(base
+0xe)&0x1)
129 static int ISILoad_ioctl(struct inode
*inode
, struct file
*filp
,
130 unsigned int cmd
, unsigned long arg
)
132 unsigned int card
, i
, j
, signature
, status
, portcount
= 0;
134 unsigned short word_count
, base
;
136 void __user
*argp
= (void __user
*)arg
;
137 /* exec_record exec_rec; */
139 if(get_user(card
, (int __user
*)argp
))
142 if(card
< 0 || card
>= BOARD_COUNT
)
145 base
=isi_card
[card
].base
;
148 return -ENXIO
; /* disabled or not used */
151 case MIOCTL_RESET_CARD
:
152 if (!capable(CAP_SYS_ADMIN
))
154 printk(KERN_DEBUG
"ISILoad:Resetting Card%d at 0x%x ",card
+1,base
);
158 for(t
=jiffies
+HZ
/100;time_before(jiffies
, t
););
160 outw(0,base
+0x8); /* Reset */
163 for(t
=jiffies
+HZ
;time_before(jiffies
, t
););
166 signature
=(inw(base
+0x4)) & 0xff;
167 if (isi_card
[card
].isa
) {
169 if (!(inw(base
+0xe) & 0x1) || (inw(base
+0x2))) {
171 printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base
+0x2),inw(base
+0xe));
173 printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card
+1,base
);
178 portcount
= inw(base
+0x2);
179 if (!(inw(base
+0xe) & 0x1) || ((portcount
!=0) && (portcount
!=4) && (portcount
!=8))) {
181 printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base
+0x2),inw(base
+0xe));
183 printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card
+1,base
);
191 if (isi_card
[card
].isa
)
192 isi_card
[card
].port_count
= 8;
195 isi_card
[card
].port_count
= 4;
197 isi_card
[card
].port_count
= 8;
199 isi_card
[card
].shift_count
= 12;
202 case 0xcc: isi_card
[card
].port_count
= 16;
203 isi_card
[card
].shift_count
= 11;
206 default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card
+1,base
);
208 printk("Sig=0x%x\n",signature
);
213 return put_user(signature
,(unsigned __user
*)argp
);
215 case MIOCTL_LOAD_FIRMWARE
:
216 if (!capable(CAP_SYS_ADMIN
))
219 if(copy_from_user(&frame
, argp
, sizeof(bin_frame
)))
222 if (WaitTillCardIsFree(base
))
225 outw(0xf0,base
); /* start upload sequence */
227 outw((frame
.addr
), base
);/* lsb of adderess */
229 word_count
=(frame
.count
>> 1) + frame
.count
% 2;
230 outw(word_count
, base
);
231 InterruptTheCard(base
);
233 for(i
=0;i
<=0x2f;i
++); /* a wee bit of delay */
235 if (WaitTillCardIsFree(base
))
238 if ((status
=inw(base
+0x4))!=0) {
239 printk(KERN_WARNING
"ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
240 card
+1, frame
.addr
, frame
.count
, status
);
243 outsw(base
, (void *) frame
.bin_data
, word_count
);
245 InterruptTheCard(base
);
247 for(i
=0;i
<=0x0f;i
++); /* another wee bit of delay */
249 if (WaitTillCardIsFree(base
))
252 if ((status
=inw(base
+0x4))!=0) {
253 printk(KERN_ERR
"ISILoad:Card%d got out of sync.Card Status:0x%x\n",card
+1, status
);
258 case MIOCTL_READ_FIRMWARE
:
259 if (!capable(CAP_SYS_ADMIN
))
262 if(copy_from_user(&frame
, argp
, sizeof(bin_header
)))
265 if (WaitTillCardIsFree(base
))
268 outw(0xf1,base
); /* start download sequence */
270 outw((frame
.addr
), base
);/* lsb of adderess */
272 word_count
=(frame
.count
>> 1) + frame
.count
% 2;
273 outw(word_count
+1, base
);
274 InterruptTheCard(base
);
276 for(i
=0;i
<=0xf;i
++); /* a wee bit of delay */
278 if (WaitTillCardIsFree(base
))
281 if ((status
=inw(base
+0x4))!=0) {
282 printk(KERN_WARNING
"ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
283 card
+1, frame
.addr
, frame
.count
, status
);
288 insw(base
, frame
.bin_data
, word_count
);
289 InterruptTheCard(base
);
291 for(i
=0;i
<=0x0f;i
++); /* another wee bit of delay */
293 if (WaitTillCardIsFree(base
))
296 if ((status
=inw(base
+0x4))!=0) {
297 printk(KERN_ERR
"ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card
+1, status
);
301 if(copy_to_user(argp
, &frame
, sizeof(bin_frame
)))
305 case MIOCTL_XFER_CTRL
:
306 if (!capable(CAP_SYS_ADMIN
))
308 if (WaitTillCardIsFree(base
))
315 InterruptTheCard(base
);
316 outw(0x0, base
+0x4); /* for ISI4608 cards */
318 isi_card
[card
].status
|= FIRMWARE_LOADED
;
323 printk(KERN_DEBUG
"ISILoad: Received Ioctl cmd 0x%x.\n", cmd
);
333 * ISICOM Driver specific routines ...
337 static inline int isicom_paranoia_check(struct isi_port
const * port
, char *name
,
338 const char * routine
)
341 static const char * badmagic
=
342 KERN_WARNING
"ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
343 static const char * badport
=
344 KERN_WARNING
"ISICOM: Warning: NULL isicom port for dev %s in %s.\n";
346 printk(badport
, name
, routine
);
349 if (port
->magic
!= ISICOM_MAGIC
) {
350 printk(badmagic
, name
, routine
);
359 static void isicom_tx(unsigned long _data
)
361 short count
= (BOARD_COUNT
-1), card
, base
;
362 short txcount
, wait
, wrd
, residue
, word_count
, cnt
;
363 struct isi_port
* port
;
364 struct tty_struct
* tty
;
371 /* find next active board */
372 card
= (prev_card
+ 1) & 0x0003;
374 if (isi_card
[card
].status
& BOARD_ACTIVE
)
376 card
= (card
+ 1) & 0x0003;
378 if (!(isi_card
[card
].status
& BOARD_ACTIVE
))
383 count
= isi_card
[card
].port_count
;
384 port
= isi_card
[card
].ports
;
385 base
= isi_card
[card
].base
;
386 for (;count
> 0;count
--, port
++) {
387 /* port not active or tx disabled to force flow control */
388 if (!(port
->status
& ISI_TXOK
))
392 save_flags(flags
); cli();
393 txcount
= min_t(short, TX_SIZE
, port
->xmit_cnt
);
394 if ((txcount
<= 0) || tty
->stopped
|| tty
->hw_stopped
) {
395 restore_flags(flags
);
399 while(((inw(base
+0x0e) & 0x01) == 0) && (wait
-- > 0));
401 restore_flags(flags
);
403 printk(KERN_DEBUG
"ISICOM: isicom_tx:Card(0x%x) found busy.\n",
408 if (!(inw(base
+ 0x02) & (1 << port
->channel
))) {
409 restore_flags(flags
);
411 printk(KERN_DEBUG
"ISICOM: isicom_tx: cannot tx to 0x%x:%d.\n",
412 base
, port
->channel
+ 1);
417 printk(KERN_DEBUG
"ISICOM: txing %d bytes, port%d.\n",
418 txcount
, port
->channel
+1);
420 outw((port
->channel
<< isi_card
[card
].shift_count
) | txcount
425 cnt
= min_t(int, txcount
, (SERIAL_XMIT_SIZE
- port
->xmit_tail
));
426 if (residue
== YES
) {
429 wrd
|= (port
->xmit_buf
[port
->xmit_tail
] << 8);
430 port
->xmit_tail
= (port
->xmit_tail
+ 1) & (SERIAL_XMIT_SIZE
- 1);
442 word_count
= cnt
>> 1;
443 outsw(base
, port
->xmit_buf
+port
->xmit_tail
, word_count
);
444 port
->xmit_tail
= (port
->xmit_tail
+ (word_count
<< 1)) &
445 (SERIAL_XMIT_SIZE
- 1);
446 txcount
-= (word_count
<< 1);
447 port
->xmit_cnt
-= (word_count
<< 1);
450 wrd
= port
->xmit_buf
[port
->xmit_tail
];
451 port
->xmit_tail
= (port
->xmit_tail
+ 1) & (SERIAL_XMIT_SIZE
- 1);
457 InterruptTheCard(base
);
458 if (port
->xmit_cnt
<= 0)
459 port
->status
&= ~ISI_TXOK
;
460 if (port
->xmit_cnt
<= WAKEUP_CHARS
)
461 schedule_work(&port
->bh_tqueue
);
462 restore_flags(flags
);
465 /* schedule another tx for hopefully in about 10ms */
470 tx
.expires
= jiffies
+ HZ
/100;
472 tx
.function
= isicom_tx
;
478 /* Interrupt handlers */
481 static void isicom_bottomhalf(void * data
)
483 struct isi_port
* port
= (struct isi_port
*) data
;
484 struct tty_struct
* tty
= port
->tty
;
490 wake_up_interruptible(&tty
->write_wait
);
493 /* main interrupt handler routine */
494 static irqreturn_t
isicom_interrupt(int irq
, void *dev_id
,
495 struct pt_regs
*regs
)
497 struct isi_board
* card
;
498 struct isi_port
* port
;
499 struct tty_struct
* tty
;
500 unsigned short base
, header
, word_count
, count
;
501 unsigned char channel
;
505 * find the source of interrupt
508 for(count
= 0; count
< BOARD_COUNT
; count
++) {
509 card
= &isi_card
[count
];
510 if (card
->base
!= 0) {
511 if (((card
->isa
== YES
) && (card
->irq
== irq
)) ||
512 ((card
->isa
== NO
) && (card
->irq
== irq
) && (inw(card
->base
+0x0e) & 0x02)))
518 if (!card
|| !(card
->status
& FIRMWARE_LOADED
)) {
519 /* printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);*/
524 if (card
->isa
== NO
) {
526 * disable any interrupts from the PCI card and lower the
529 outw(0x8000, base
+0x04);
530 ClearInterrupt(base
);
533 inw(base
); /* get the dummy word out */
535 channel
= (header
& 0x7800) >> card
->shift_count
;
536 byte_count
= header
& 0xff;
538 printk(KERN_DEBUG
"ISICOM:Intr:(0x%x:%d).\n", base
, channel
+1);
540 if ((channel
+1) > card
->port_count
) {
541 printk(KERN_WARNING
"ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
544 ClearInterrupt(base
);
546 outw(0x0000, base
+0x04); /* enable interrupts */
549 port
= card
->ports
+ channel
;
550 if (!(port
->flags
& ASYNC_INITIALIZED
)) {
552 ClearInterrupt(base
);
554 outw(0x0000, base
+0x04); /* enable interrupts */
560 if (header
& 0x8000) { /* Status Packet */
562 switch(header
& 0xff) {
563 case 0: /* Change in EIA signals */
565 if (port
->flags
& ASYNC_CHECK_CD
) {
566 if (port
->status
& ISI_DCD
) {
567 if (!(header
& ISI_DCD
)) {
568 /* Carrier has been lost */
570 printk(KERN_DEBUG
"ISICOM: interrupt: DCD->low.\n");
572 port
->status
&= ~ISI_DCD
;
573 schedule_work(&port
->hangup_tq
);
577 if (header
& ISI_DCD
) {
578 /* Carrier has been detected */
580 printk(KERN_DEBUG
"ISICOM: interrupt: DCD->high.\n");
582 port
->status
|= ISI_DCD
;
583 wake_up_interruptible(&port
->open_wait
);
588 if (header
& ISI_DCD
)
589 port
->status
|= ISI_DCD
;
591 port
->status
&= ~ISI_DCD
;
594 if (port
->flags
& ASYNC_CTS_FLOW
) {
595 if (port
->tty
->hw_stopped
) {
596 if (header
& ISI_CTS
) {
597 port
->tty
->hw_stopped
= 0;
599 port
->status
|= (ISI_TXOK
| ISI_CTS
);
600 schedule_work(&port
->bh_tqueue
);
604 if (!(header
& ISI_CTS
)) {
605 port
->tty
->hw_stopped
= 1;
607 port
->status
&= ~(ISI_TXOK
| ISI_CTS
);
612 if (header
& ISI_CTS
)
613 port
->status
|= ISI_CTS
;
615 port
->status
&= ~ISI_CTS
;
618 if (header
& ISI_DSR
)
619 port
->status
|= ISI_DSR
;
621 port
->status
&= ~ISI_DSR
;
624 port
->status
|= ISI_RI
;
626 port
->status
&= ~ISI_RI
;
630 case 1: /* Received Break !!! */
631 if (tty
->flip
.count
>= TTY_FLIPBUF_SIZE
)
633 *tty
->flip
.flag_buf_ptr
++ = TTY_BREAK
;
634 /* dunno if this is right */
635 *tty
->flip
.char_buf_ptr
++ = 0;
637 if (port
->flags
& ASYNC_SAK
)
639 schedule_delayed_work(&tty
->flip
.work
, 1);
642 case 2: /* Statistics */
643 printk(KERN_DEBUG
"ISICOM: isicom_interrupt: stats!!!.\n");
647 printk(KERN_WARNING
"ISICOM: Intr: Unknown code in status packet.\n");
651 else { /* Data Packet */
652 count
= min_t(unsigned short, byte_count
, (TTY_FLIPBUF_SIZE
- tty
->flip
.count
));
654 printk(KERN_DEBUG
"ISICOM: Intr: Can rx %d of %d bytes.\n",
657 word_count
= count
>> 1;
658 insw(base
, tty
->flip
.char_buf_ptr
, word_count
);
659 tty
->flip
.char_buf_ptr
+= (word_count
<< 1);
660 byte_count
-= (word_count
<< 1);
661 if (count
& 0x0001) {
662 *tty
->flip
.char_buf_ptr
++ = (char)(inw(base
) & 0xff);
665 memset(tty
->flip
.flag_buf_ptr
, 0, count
);
666 tty
->flip
.flag_buf_ptr
+= count
;
667 tty
->flip
.count
+= count
;
669 if (byte_count
> 0) {
670 printk(KERN_DEBUG
"ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
672 while(byte_count
> 0) { /* drain out unread xtra data */
677 schedule_delayed_work(&tty
->flip
.work
, 1);
679 if (card
->isa
== YES
)
680 ClearInterrupt(base
);
682 outw(0x0000, base
+0x04); /* enable interrupts */
686 /* called with interrupts disabled */
687 static void isicom_config_port(struct isi_port
* port
)
689 struct isi_board
* card
= port
->card
;
690 struct tty_struct
* tty
;
692 unsigned short channel_setup
, wait
, base
= card
->base
;
693 unsigned short channel
= port
->channel
, shift_count
= card
->shift_count
;
694 unsigned char flow_ctrl
;
696 if (!(tty
= port
->tty
) || !tty
->termios
)
699 if (baud
& CBAUDEX
) {
702 /* if CBAUDEX bit is on and the baud is set to either 50 or 75
703 * then the card is programmed for 57.6Kbps or 115Kbps
707 if (baud
< 1 || baud
> 2)
708 port
->tty
->termios
->c_cflag
&= ~CBAUDEX
;
714 /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
715 * by the set_serial_info ioctl ... this is done by
716 * the 'setserial' utility.
719 if ((port
->flags
& ASYNC_SPD_MASK
) == ASYNC_SPD_HI
)
720 baud
++; /* 57.6 Kbps */
721 if ((port
->flags
& ASYNC_SPD_MASK
) == ASYNC_SPD_VHI
)
722 baud
+=2; /* 115 Kbps */
724 if (linuxb_to_isib
[baud
] == -1) {
733 while (((inw(base
+ 0x0e) & 0x0001) == 0) && (wait
-- > 0));
735 printk(KERN_WARNING
"ISICOM: Card found busy in isicom_config_port at channel setup.\n");
738 outw(0x8000 | (channel
<< shift_count
) |0x03, base
);
739 outw(linuxb_to_isib
[baud
] << 8 | 0x03, base
);
741 switch(C_CSIZE(tty
)) {
743 channel_setup
|= ISICOM_CS5
;
746 channel_setup
|= ISICOM_CS6
;
749 channel_setup
|= ISICOM_CS7
;
752 channel_setup
|= ISICOM_CS8
;
757 channel_setup
|= ISICOM_2SB
;
760 channel_setup
|= ISICOM_EVPAR
;
762 channel_setup
|= ISICOM_ODPAR
;
763 outw(channel_setup
, base
);
764 InterruptTheCard(base
);
767 port
->flags
&= ~ASYNC_CHECK_CD
;
769 port
->flags
|= ASYNC_CHECK_CD
;
771 /* flow control settings ...*/
773 port
->flags
&= ~ASYNC_CTS_FLOW
;
774 if (C_CRTSCTS(tty
)) {
775 port
->flags
|= ASYNC_CTS_FLOW
;
776 flow_ctrl
|= ISICOM_CTSRTS
;
779 flow_ctrl
|= ISICOM_RESPOND_XONXOFF
;
781 flow_ctrl
|= ISICOM_INITIATE_XONXOFF
;
784 while (((inw(base
+ 0x0e) & 0x0001) == 0) && (wait
-- > 0));
786 printk(KERN_WARNING
"ISICOM: Card found busy in isicom_config_port at flow setup.\n");
789 outw(0x8000 | (channel
<< shift_count
) |0x04, base
);
790 outw(flow_ctrl
<< 8 | 0x05, base
);
791 outw((STOP_CHAR(tty
)) << 8 | (START_CHAR(tty
)), base
);
792 InterruptTheCard(base
);
794 /* rx enabled -> enable port for rx on the card */
796 card
->port_status
|= (1 << channel
);
797 outw(card
->port_status
, base
+ 0x02);
804 static inline void isicom_setup_board(struct isi_board
* bp
)
807 struct isi_port
* port
;
810 if (bp
->status
& BOARD_ACTIVE
)
814 printk(KERN_DEBUG
"ISICOM: setup_board: drop_dtr_rts start, port_count %d...\n", bp
->port_count
);
816 for(channel
= 0; channel
< bp
->port_count
; channel
++, port
++) {
817 save_flags(flags
); cli();
819 restore_flags(flags
);
822 printk(KERN_DEBUG
"ISICOM: setup_board: drop_dtr_rts stop...\n");
825 bp
->status
|= BOARD_ACTIVE
;
829 static int isicom_setup_port(struct isi_port
* port
)
831 struct isi_board
* card
= port
->card
;
834 if (port
->flags
& ASYNC_INITIALIZED
)
836 if (!port
->xmit_buf
) {
839 if (!(page
= get_zeroed_page(GFP_KERNEL
)))
842 if (port
->xmit_buf
) {
846 port
->xmit_buf
= (unsigned char *) page
;
848 save_flags(flags
); cli();
850 clear_bit(TTY_IO_ERROR
, &port
->tty
->flags
);
851 if (port
->count
== 1)
854 port
->xmit_cnt
= port
->xmit_head
= port
->xmit_tail
= 0;
856 /* discard any residual data */
857 kill_queue(port
, ISICOM_KILLTX
| ISICOM_KILLRX
);
859 isicom_config_port(port
);
860 port
->flags
|= ASYNC_INITIALIZED
;
862 restore_flags(flags
);
867 static int block_til_ready(struct tty_struct
* tty
, struct file
* filp
, struct isi_port
* port
)
869 int do_clocal
= 0, retval
;
870 DECLARE_WAITQUEUE(wait
, current
);
872 /* block if port is in the process of being closed */
874 if (tty_hung_up_p(filp
) || port
->flags
& ASYNC_CLOSING
) {
876 printk(KERN_DEBUG
"ISICOM: block_til_ready: close in progress.\n");
878 interruptible_sleep_on(&port
->close_wait
);
879 if (port
->flags
& ASYNC_HUP_NOTIFY
)
885 /* if non-blocking mode is set ... */
887 if ((filp
->f_flags
& O_NONBLOCK
) || (tty
->flags
& (1 << TTY_IO_ERROR
))) {
889 printk(KERN_DEBUG
"ISICOM: block_til_ready: non-block mode.\n");
891 port
->flags
|= ASYNC_NORMAL_ACTIVE
;
899 printk(KERN_DEBUG
"ISICOM: block_til_ready: CLOCAL set.\n");
902 /* block waiting for DCD to be asserted, and while
903 callout dev is busy */
905 add_wait_queue(&port
->open_wait
, &wait
);
907 if (!tty_hung_up_p(filp
))
910 port
->blocked_open
++;
912 printk(KERN_DEBUG
"ISICOM: block_til_ready: waiting for DCD...\n");
918 set_current_state(TASK_INTERRUPTIBLE
);
919 if (tty_hung_up_p(filp
) || !(port
->flags
& ASYNC_INITIALIZED
)) {
920 if (port
->flags
& ASYNC_HUP_NOTIFY
)
923 retval
= -ERESTARTSYS
;
925 printk(KERN_DEBUG
"ISICOM: block_til_ready: tty_hung_up_p || not init.\n");
929 if (!(port
->flags
& ASYNC_CLOSING
) &&
930 (do_clocal
|| (port
->status
& ISI_DCD
))) {
932 printk(KERN_DEBUG
"ISICOM: block_til_ready: do_clocal || DCD.\n");
936 if (signal_pending(current
)) {
938 printk(KERN_DEBUG
"ISICOM: block_til_ready: sig blocked.\n");
940 retval
= -ERESTARTSYS
;
945 set_current_state(TASK_RUNNING
);
946 remove_wait_queue(&port
->open_wait
, &wait
);
947 if (!tty_hung_up_p(filp
))
949 port
->blocked_open
--;
952 port
->flags
|= ASYNC_NORMAL_ACTIVE
;
956 static int isicom_open(struct tty_struct
* tty
, struct file
* filp
)
958 struct isi_port
* port
;
959 struct isi_board
* card
;
960 unsigned int line
, board
;
964 printk(KERN_DEBUG
"ISICOM: open start!!!.\n");
969 printk(KERN_DEBUG
"line = %d.\n", line
);
972 if ((line
< 0) || (line
> (PORT_COUNT
-1)))
977 printk(KERN_DEBUG
"board = %d.\n", board
);
980 card
= &isi_card
[board
];
981 if (!(card
->status
& FIRMWARE_LOADED
)) {
983 printk(KERN_DEBUG
"ISICOM: Firmware not loaded to card%d.\n", board
);
988 /* open on a port greater than the port count for the card !!! */
989 if (line
> ((board
* 16) + card
->port_count
- 1)) {
990 printk(KERN_ERR
"ISICOM: Open on a port which exceeds the port_count of the card!\n");
993 port
= &isi_ports
[line
];
994 if (isicom_paranoia_check(port
, tty
->name
, "isicom_open"))
998 printk(KERN_DEBUG
"ISICOM: isicom_setup_board ...\n");
1000 isicom_setup_board(card
);
1003 tty
->driver_data
= port
;
1006 printk(KERN_DEBUG
"ISICOM: isicom_setup_port ...\n");
1008 if ((error
= isicom_setup_port(port
))!=0)
1011 printk(KERN_DEBUG
"ISICOM: block_til_ready ...\n");
1013 if ((error
= block_til_ready(tty
, filp
, port
))!=0)
1017 printk(KERN_DEBUG
"ISICOM: open end!!!.\n");
1024 static inline void isicom_shutdown_board(struct isi_board
* bp
)
1027 struct isi_port
* port
;
1029 if (!(bp
->status
& BOARD_ACTIVE
))
1031 bp
->status
&= ~BOARD_ACTIVE
;
1033 for(channel
= 0; channel
< bp
->port_count
; channel
++, port
++) {
1038 static void isicom_shutdown_port(struct isi_port
* port
)
1040 struct isi_board
* card
= port
->card
;
1041 struct tty_struct
* tty
;
1043 if (!(port
->flags
& ASYNC_INITIALIZED
))
1045 if (port
->xmit_buf
) {
1046 free_page((unsigned long) port
->xmit_buf
);
1047 port
->xmit_buf
= NULL
;
1049 if (!(tty
= port
->tty
) || C_HUPCL(tty
))
1050 /* drop dtr on this port */
1053 /* any other port uninits */
1056 set_bit(TTY_IO_ERROR
, &tty
->flags
);
1057 port
->flags
&= ~ASYNC_INITIALIZED
;
1059 if (--card
->count
< 0) {
1060 printk(KERN_DEBUG
"ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
1061 card
->base
, card
->count
);
1065 /* last port was closed , shutdown that boad too */
1067 isicom_shutdown_board(card
);
1070 static void isicom_close(struct tty_struct
* tty
, struct file
* filp
)
1072 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1073 struct isi_board
* card
= port
->card
;
1074 unsigned long flags
;
1078 if (isicom_paranoia_check(port
, tty
->name
, "isicom_close"))
1082 printk(KERN_DEBUG
"ISICOM: Close start!!!.\n");
1085 save_flags(flags
); cli();
1086 if (tty_hung_up_p(filp
)) {
1087 restore_flags(flags
);
1091 if ((tty
->count
== 1) && (port
->count
!= 1)) {
1092 printk(KERN_WARNING
"ISICOM:(0x%x) isicom_close: bad port count"
1093 "tty->count = 1 port count = %d.\n",
1094 card
->base
, port
->count
);
1097 if (--port
->count
< 0) {
1098 printk(KERN_WARNING
"ISICOM:(0x%x) isicom_close: bad port count for"
1099 "channel%d = %d", card
->base
, port
->channel
,
1105 restore_flags(flags
);
1108 port
->flags
|= ASYNC_CLOSING
;
1110 if (port
->closing_wait
!= ASYNC_CLOSING_WAIT_NONE
)
1111 tty_wait_until_sent(tty
, port
->closing_wait
);
1112 /* indicate to the card that no more data can be received
1114 if (port
->flags
& ASYNC_INITIALIZED
) {
1115 card
->port_status
&= ~(1 << port
->channel
);
1116 outw(card
->port_status
, card
->base
+ 0x02);
1118 isicom_shutdown_port(port
);
1119 if (tty
->driver
->flush_buffer
)
1120 tty
->driver
->flush_buffer(tty
);
1122 tty_ldisc_flush(tty
);
1125 if (port
->blocked_open
) {
1126 if (port
->close_delay
) {
1127 set_current_state(TASK_INTERRUPTIBLE
);
1129 printk(KERN_DEBUG
"ISICOM: scheduling until time out.\n");
1131 schedule_timeout(port
->close_delay
);
1133 wake_up_interruptible(&port
->open_wait
);
1135 port
->flags
&= ~(ASYNC_NORMAL_ACTIVE
| ASYNC_CLOSING
);
1136 wake_up_interruptible(&port
->close_wait
);
1137 restore_flags(flags
);
1139 printk(KERN_DEBUG
"ISICOM: Close end!!!.\n");
1144 static int isicom_write(struct tty_struct
* tty
, int from_user
,
1145 const unsigned char * buf
, int count
)
1147 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1148 unsigned long flags
;
1151 printk(KERN_DEBUG
"ISICOM: isicom_write for port%d: %d bytes.\n",
1152 port
->channel
+1, count
);
1154 if (isicom_paranoia_check(port
, tty
->name
, "isicom_write"))
1157 if (!tty
|| !port
->xmit_buf
|| !tmp_buf
)
1160 down(&tmp_buf_sem
); /* acquire xclusive access to tmp_buf */
1165 cnt
= min_t(int, count
, min(SERIAL_XMIT_SIZE
- port
->xmit_cnt
- 1,
1166 SERIAL_XMIT_SIZE
- port
->xmit_head
));
1171 /* the following may block for paging... hence
1172 enabling interrupts but tx routine may have
1173 created more space in xmit_buf when the ctrl
1176 if (copy_from_user(tmp_buf
, buf
, cnt
)) {
1178 restore_flags(flags
);
1182 cnt
= min_t(int, cnt
, min(SERIAL_XMIT_SIZE
- port
->xmit_cnt
- 1,
1183 SERIAL_XMIT_SIZE
- port
->xmit_head
));
1184 memcpy(port
->xmit_buf
+ port
->xmit_head
, tmp_buf
, cnt
);
1187 memcpy(port
->xmit_buf
+ port
->xmit_head
, buf
, cnt
);
1188 port
->xmit_head
= (port
->xmit_head
+ cnt
) & (SERIAL_XMIT_SIZE
- 1);
1189 port
->xmit_cnt
+= cnt
;
1190 restore_flags(flags
);
1197 if (port
->xmit_cnt
&& !tty
->stopped
&& !tty
->hw_stopped
)
1198 port
->status
|= ISI_TXOK
;
1199 restore_flags(flags
);
1201 printk(KERN_DEBUG
"ISICOM: isicom_write %d bytes written.\n", total
);
1206 /* put_char et all */
1207 static void isicom_put_char(struct tty_struct
* tty
, unsigned char ch
)
1209 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1210 unsigned long flags
;
1212 if (isicom_paranoia_check(port
, tty
->name
, "isicom_put_char"))
1215 if (!tty
|| !port
->xmit_buf
)
1218 printk(KERN_DEBUG
"ISICOM: put_char, port %d, char %c.\n", port
->channel
+1, ch
);
1221 save_flags(flags
); cli();
1223 if (port
->xmit_cnt
>= (SERIAL_XMIT_SIZE
- 1)) {
1224 restore_flags(flags
);
1228 port
->xmit_buf
[port
->xmit_head
++] = ch
;
1229 port
->xmit_head
&= (SERIAL_XMIT_SIZE
- 1);
1231 restore_flags(flags
);
1234 /* flush_chars et all */
1235 static void isicom_flush_chars(struct tty_struct
* tty
)
1237 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1239 if (isicom_paranoia_check(port
, tty
->name
, "isicom_flush_chars"))
1242 if (port
->xmit_cnt
<= 0 || tty
->stopped
|| tty
->hw_stopped
||
1246 /* this tells the transmitter to consider this port for
1247 data output to the card ... that's the best we can do. */
1248 port
->status
|= ISI_TXOK
;
1251 /* write_room et all */
1252 static int isicom_write_room(struct tty_struct
* tty
)
1254 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1256 if (isicom_paranoia_check(port
, tty
->name
, "isicom_write_room"))
1259 free
= SERIAL_XMIT_SIZE
- port
->xmit_cnt
- 1;
1265 /* chars_in_buffer et all */
1266 static int isicom_chars_in_buffer(struct tty_struct
* tty
)
1268 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1269 if (isicom_paranoia_check(port
, tty
->name
, "isicom_chars_in_buffer"))
1271 return port
->xmit_cnt
;
1275 static inline void isicom_send_break(struct isi_port
* port
, unsigned long length
)
1277 struct isi_board
* card
= port
->card
;
1279 unsigned short base
= card
->base
;
1280 unsigned long flags
;
1282 save_flags(flags
); cli();
1283 while (((inw(base
+ 0x0e) & 0x0001) == 0) && (wait
-- > 0));
1285 printk(KERN_DEBUG
"ISICOM: Card found busy in isicom_send_break.\n");
1288 outw(0x8000 | ((port
->channel
) << (card
->shift_count
)) | 0x3, base
);
1289 outw((length
& 0xff) << 8 | 0x00, base
);
1290 outw((length
& 0xff00), base
);
1291 InterruptTheCard(base
);
1292 out
: restore_flags(flags
);
1295 static int isicom_tiocmget(struct tty_struct
*tty
, struct file
*file
)
1297 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1298 /* just send the port status */
1299 unsigned short status
= port
->status
;
1301 if (isicom_paranoia_check(port
, tty
->name
, "isicom_ioctl"))
1304 return ((status
& ISI_RTS
) ? TIOCM_RTS
: 0) |
1305 ((status
& ISI_DTR
) ? TIOCM_DTR
: 0) |
1306 ((status
& ISI_DCD
) ? TIOCM_CAR
: 0) |
1307 ((status
& ISI_DSR
) ? TIOCM_DSR
: 0) |
1308 ((status
& ISI_CTS
) ? TIOCM_CTS
: 0) |
1309 ((status
& ISI_RI
) ? TIOCM_RI
: 0);
1312 static int isicom_tiocmset(struct tty_struct
*tty
, struct file
*file
,
1313 unsigned int set
, unsigned int clear
)
1315 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1316 unsigned long flags
;
1318 if (isicom_paranoia_check(port
, tty
->name
, "isicom_ioctl"))
1321 save_flags(flags
); cli();
1322 if (set
& TIOCM_RTS
)
1324 if (set
& TIOCM_DTR
)
1327 if (clear
& TIOCM_RTS
)
1329 if (clear
& TIOCM_DTR
)
1332 restore_flags(flags
);
1336 static int isicom_set_serial_info(struct isi_port
* port
,
1337 struct serial_struct __user
*info
)
1339 struct serial_struct newinfo
;
1340 unsigned long flags
;
1343 if(copy_from_user(&newinfo
, info
, sizeof(newinfo
)))
1346 reconfig_port
= ((port
->flags
& ASYNC_SPD_MASK
) !=
1347 (newinfo
.flags
& ASYNC_SPD_MASK
));
1349 if (!capable(CAP_SYS_ADMIN
)) {
1350 if ((newinfo
.close_delay
!= port
->close_delay
) ||
1351 (newinfo
.closing_wait
!= port
->closing_wait
) ||
1352 ((newinfo
.flags
& ~ASYNC_USR_MASK
) !=
1353 (port
->flags
& ~ASYNC_USR_MASK
)))
1355 port
->flags
= ((port
->flags
& ~ ASYNC_USR_MASK
) |
1356 (newinfo
.flags
& ASYNC_USR_MASK
));
1359 port
->close_delay
= newinfo
.close_delay
;
1360 port
->closing_wait
= newinfo
.closing_wait
;
1361 port
->flags
= ((port
->flags
& ~ASYNC_FLAGS
) |
1362 (newinfo
.flags
& ASYNC_FLAGS
));
1364 if (reconfig_port
) {
1365 save_flags(flags
); cli();
1366 isicom_config_port(port
);
1367 restore_flags(flags
);
1372 static int isicom_get_serial_info(struct isi_port
* port
,
1373 struct serial_struct __user
*info
)
1375 struct serial_struct out_info
;
1377 memset(&out_info
, 0, sizeof(out_info
));
1378 /* out_info.type = ? */
1379 out_info
.line
= port
- isi_ports
;
1380 out_info
.port
= port
->card
->base
;
1381 out_info
.irq
= port
->card
->irq
;
1382 out_info
.flags
= port
->flags
;
1383 /* out_info.baud_base = ? */
1384 out_info
.close_delay
= port
->close_delay
;
1385 out_info
.closing_wait
= port
->closing_wait
;
1386 if(copy_to_user(info
, &out_info
, sizeof(out_info
)))
1391 static int isicom_ioctl(struct tty_struct
* tty
, struct file
* filp
,
1392 unsigned int cmd
, unsigned long arg
)
1394 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1395 void __user
*argp
= (void __user
*)arg
;
1398 if (isicom_paranoia_check(port
, tty
->name
, "isicom_ioctl"))
1403 retval
= tty_check_change(tty
);
1406 tty_wait_until_sent(tty
, 0);
1408 isicom_send_break(port
, HZ
/4);
1412 retval
= tty_check_change(tty
);
1415 tty_wait_until_sent(tty
, 0);
1416 isicom_send_break(port
, arg
? arg
* (HZ
/10) : HZ
/4);
1420 return put_user(C_CLOCAL(tty
) ? 1 : 0, (unsigned long __user
*)argp
);
1423 if(get_user(arg
, (unsigned long __user
*) argp
))
1425 tty
->termios
->c_cflag
=
1426 ((tty
->termios
->c_cflag
& ~CLOCAL
) |
1427 (arg
? CLOCAL
: 0));
1431 return isicom_get_serial_info(port
, argp
);
1434 return isicom_set_serial_info(port
, argp
);
1437 return -ENOIOCTLCMD
;
1442 /* set_termios et all */
1443 static void isicom_set_termios(struct tty_struct
* tty
, struct termios
* old_termios
)
1445 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1446 unsigned long flags
;
1448 if (isicom_paranoia_check(port
, tty
->name
, "isicom_set_termios"))
1451 if (tty
->termios
->c_cflag
== old_termios
->c_cflag
&&
1452 tty
->termios
->c_iflag
== old_termios
->c_iflag
)
1455 save_flags(flags
); cli();
1456 isicom_config_port(port
);
1457 restore_flags(flags
);
1459 if ((old_termios
->c_cflag
& CRTSCTS
) &&
1460 !(tty
->termios
->c_cflag
& CRTSCTS
)) {
1461 tty
->hw_stopped
= 0;
1466 /* throttle et all */
1467 static void isicom_throttle(struct tty_struct
* tty
)
1469 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1470 struct isi_board
* card
= port
->card
;
1471 unsigned long flags
;
1473 if (isicom_paranoia_check(port
, tty
->name
, "isicom_throttle"))
1476 /* tell the card that this port cannot handle any more data for now */
1477 save_flags(flags
); cli();
1478 card
->port_status
&= ~(1 << port
->channel
);
1479 outw(card
->port_status
, card
->base
+ 0x02);
1480 restore_flags(flags
);
1483 /* unthrottle et all */
1484 static void isicom_unthrottle(struct tty_struct
* tty
)
1486 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1487 struct isi_board
* card
= port
->card
;
1488 unsigned long flags
;
1490 if (isicom_paranoia_check(port
, tty
->name
, "isicom_unthrottle"))
1493 /* tell the card that this port is ready to accept more data */
1494 save_flags(flags
); cli();
1495 card
->port_status
|= (1 << port
->channel
);
1496 outw(card
->port_status
, card
->base
+ 0x02);
1497 restore_flags(flags
);
1501 static void isicom_stop(struct tty_struct
* tty
)
1503 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1505 if (isicom_paranoia_check(port
, tty
->name
, "isicom_stop"))
1508 /* this tells the transmitter not to consider this port for
1509 data output to the card. */
1510 port
->status
&= ~ISI_TXOK
;
1514 static void isicom_start(struct tty_struct
* tty
)
1516 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1518 if (isicom_paranoia_check(port
, tty
->name
, "isicom_start"))
1521 /* this tells the transmitter to consider this port for
1522 data output to the card. */
1523 port
->status
|= ISI_TXOK
;
1527 static void do_isicom_hangup(void * data
)
1529 struct isi_port
* port
= (struct isi_port
*) data
;
1530 struct tty_struct
* tty
;
1534 tty_hangup(tty
); /* FIXME: module removal race here - AKPM */
1537 static void isicom_hangup(struct tty_struct
* tty
)
1539 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1541 if (isicom_paranoia_check(port
, tty
->name
, "isicom_hangup"))
1544 isicom_shutdown_port(port
);
1546 port
->flags
&= ~ASYNC_NORMAL_ACTIVE
;
1548 wake_up_interruptible(&port
->open_wait
);
1551 /* flush_buffer et all */
1552 static void isicom_flush_buffer(struct tty_struct
* tty
)
1554 struct isi_port
* port
= (struct isi_port
*) tty
->driver_data
;
1555 unsigned long flags
;
1557 if (isicom_paranoia_check(port
, tty
->name
, "isicom_flush_buffer"))
1560 save_flags(flags
); cli();
1561 port
->xmit_cnt
= port
->xmit_head
= port
->xmit_tail
= 0;
1562 restore_flags(flags
);
1564 wake_up_interruptible(&tty
->write_wait
);
1569 static int register_ioregion(void)
1572 for (count
=0; count
< BOARD_COUNT
; count
++ ) {
1573 if (isi_card
[count
].base
)
1574 if (!request_region(isi_card
[count
].base
,16,ISICOM_NAME
)) {
1575 printk(KERN_DEBUG
"ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
1576 isi_card
[count
].base
,isi_card
[count
].base
+15,count
+1);
1577 isi_card
[count
].base
=0;
1584 static void unregister_ioregion(void)
1587 for (count
=0; count
< BOARD_COUNT
; count
++ )
1588 if (isi_card
[count
].base
) {
1589 release_region(isi_card
[count
].base
,16);
1591 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);
1596 static struct tty_operations isicom_ops
= {
1597 .open
= isicom_open
,
1598 .close
= isicom_close
,
1599 .write
= isicom_write
,
1600 .put_char
= isicom_put_char
,
1601 .flush_chars
= isicom_flush_chars
,
1602 .write_room
= isicom_write_room
,
1603 .chars_in_buffer
= isicom_chars_in_buffer
,
1604 .ioctl
= isicom_ioctl
,
1605 .set_termios
= isicom_set_termios
,
1606 .throttle
= isicom_throttle
,
1607 .unthrottle
= isicom_unthrottle
,
1608 .stop
= isicom_stop
,
1609 .start
= isicom_start
,
1610 .hangup
= isicom_hangup
,
1611 .flush_buffer
= isicom_flush_buffer
,
1612 .tiocmget
= isicom_tiocmget
,
1613 .tiocmset
= isicom_tiocmset
,
1616 static int register_drivers(void)
1620 /* tty driver structure initialization */
1621 isicom_normal
= alloc_tty_driver(PORT_COUNT
);
1625 isicom_normal
->owner
= THIS_MODULE
;
1626 isicom_normal
->name
= "ttyM";
1627 isicom_normal
->devfs_name
= "isicom/";
1628 isicom_normal
->major
= ISICOM_NMAJOR
;
1629 isicom_normal
->minor_start
= 0;
1630 isicom_normal
->type
= TTY_DRIVER_TYPE_SERIAL
;
1631 isicom_normal
->subtype
= SERIAL_TYPE_NORMAL
;
1632 isicom_normal
->init_termios
= tty_std_termios
;
1633 isicom_normal
->init_termios
.c_cflag
=
1634 B9600
| CS8
| CREAD
| HUPCL
|CLOCAL
;
1635 isicom_normal
->flags
= TTY_DRIVER_REAL_RAW
;
1636 tty_set_operations(isicom_normal
, &isicom_ops
);
1638 if ((error
=tty_register_driver(isicom_normal
))!=0) {
1639 printk(KERN_DEBUG
"ISICOM: Couldn't register the dialin driver, error=%d\n",
1641 put_tty_driver(isicom_normal
);
1647 static void unregister_drivers(void)
1649 int error
= tty_unregister_driver(isicom_normal
);
1651 printk(KERN_DEBUG
"ISICOM: couldn't unregister normal driver error=%d.\n",error
);
1652 put_tty_driver(isicom_normal
);
1655 static int register_isr(void)
1657 int count
, done
=0, card
;
1659 unsigned char request
;
1660 for (count
=0; count
< BOARD_COUNT
; count
++ ) {
1661 if (isi_card
[count
].base
) {
1663 * verify if the required irq has already been requested for
1664 * another ISI Card, if so we already have it, else request it
1667 for(card
= 0; card
< count
; card
++)
1668 if ((isi_card
[card
].base
) && (isi_card
[card
].irq
== isi_card
[count
].irq
)) {
1670 if ((isi_card
[count
].isa
== NO
) && (isi_card
[card
].isa
== NO
))
1673 * ISA cards cannot share interrupts with other
1674 * PCI or ISA devices hence disable this card.
1676 release_region(isi_card
[count
].base
,16);
1677 isi_card
[count
].base
= 0;
1681 if(isi_card
[count
].isa
== NO
)
1684 if (request
== YES
) {
1685 if (request_irq(isi_card
[count
].irq
, isicom_interrupt
, SA_INTERRUPT
|flag
, ISICOM_NAME
, NULL
)) {
1686 printk(KERN_WARNING
"ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n",
1687 isi_card
[count
].irq
, count
+1);
1688 release_region(isi_card
[count
].base
,16);
1689 isi_card
[count
].base
=0;
1692 printk(KERN_INFO
"ISICOM: Card%d at 0x%x using irq %d.\n",
1693 count
+1, isi_card
[count
].base
, isi_card
[count
].irq
);
1695 irq_to_board
[isi_card
[count
].irq
]=&isi_card
[count
];
1704 static void unregister_isr(void)
1707 unsigned char freeirq
;
1708 for (count
=0; count
< BOARD_COUNT
; count
++ ) {
1709 if (isi_card
[count
].base
) {
1711 for(card
= 0; card
< count
; card
++)
1712 if ((isi_card
[card
].base
) && (isi_card
[card
].irq
== isi_card
[count
].irq
)) {
1716 if (freeirq
== YES
) {
1717 free_irq(isi_card
[count
].irq
, NULL
);
1719 printk(KERN_DEBUG
"ISICOM: Irq %d released for Card%d.\n",isi_card
[count
].irq
, count
+1);
1726 static int isicom_init(void)
1728 int card
, channel
, base
;
1729 struct isi_port
* port
;
1733 page
= get_zeroed_page(GFP_KERNEL
);
1736 printk(KERN_DEBUG
"ISICOM: Couldn't allocate page for tmp_buf.\n");
1738 printk(KERN_ERR
"ISICOM: Not enough memory...\n");
1742 tmp_buf
= (unsigned char *) page
;
1745 if (!register_ioregion())
1747 printk(KERN_ERR
"ISICOM: All required I/O space found busy.\n");
1748 free_page((unsigned long)tmp_buf
);
1751 if (register_drivers())
1753 unregister_ioregion();
1754 free_page((unsigned long)tmp_buf
);
1757 if (!register_isr())
1759 unregister_drivers();
1760 /* ioports already uregistered in register_isr */
1761 free_page((unsigned long)tmp_buf
);
1765 memset(isi_ports
, 0, sizeof(isi_ports
));
1766 for (card
= 0; card
< BOARD_COUNT
; card
++) {
1767 port
= &isi_ports
[card
* 16];
1768 isi_card
[card
].ports
= port
;
1769 base
= isi_card
[card
].base
;
1770 for (channel
= 0; channel
< 16; channel
++, port
++) {
1771 port
->magic
= ISICOM_MAGIC
;
1772 port
->card
= &isi_card
[card
];
1773 port
->channel
= channel
;
1774 port
->close_delay
= 50 * HZ
/100;
1775 port
->closing_wait
= 3000 * HZ
/100;
1776 INIT_WORK(&port
->hangup_tq
, do_isicom_hangup
, port
);
1777 INIT_WORK(&port
->bh_tqueue
, isicom_bottomhalf
, port
);
1779 init_waitqueue_head(&port
->open_wait
);
1780 init_waitqueue_head(&port
->close_wait
);
1789 * Insmod can set static symbols so keep these static
1795 MODULE_AUTHOR("MultiTech");
1796 MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
1797 MODULE_LICENSE("GPL");
1798 MODULE_PARM(io
, "1-4i");
1799 MODULE_PARM_DESC(io
, "I/O ports for the cards");
1800 MODULE_PARM(irq
, "1-4i");
1801 MODULE_PARM_DESC(irq
, "Interrupts for the cards");
1803 int init_module(void)
1805 struct pci_dev
*dev
= NULL
;
1806 int retval
, card
, idx
, count
;
1807 unsigned char pciirq
;
1808 unsigned int ioaddr
;
1811 for(idx
=0; idx
< BOARD_COUNT
; idx
++) {
1813 isi_card
[idx
].base
=io
[idx
];
1814 isi_card
[idx
].irq
=irq
[idx
];
1815 isi_card
[idx
].isa
=YES
;
1819 isi_card
[idx
].base
= 0;
1820 isi_card
[idx
].irq
= 0;
1824 for (idx
=0 ;idx
< card
; idx
++) {
1825 if (!((isi_card
[idx
].irq
==2)||(isi_card
[idx
].irq
==3)||
1826 (isi_card
[idx
].irq
==4)||(isi_card
[idx
].irq
==5)||
1827 (isi_card
[idx
].irq
==7)||(isi_card
[idx
].irq
==10)||
1828 (isi_card
[idx
].irq
==11)||(isi_card
[idx
].irq
==12)||
1829 (isi_card
[idx
].irq
==15))) {
1831 if (isi_card
[idx
].base
) {
1832 printk(KERN_ERR
"ISICOM: Irq %d unsupported. Disabling Card%d...\n",
1833 isi_card
[idx
].irq
, idx
+1);
1834 isi_card
[idx
].base
=0;
1840 if (card
< BOARD_COUNT
) {
1841 for (idx
=0; idx
< DEVID_COUNT
; idx
++) {
1844 if (!(dev
= pci_find_device(VENDOR_ID
, isicom_pci_tbl
[idx
].device
, dev
)))
1846 if (card
>= BOARD_COUNT
)
1849 if (pci_enable_device(dev
))
1852 /* found a PCI ISI card! */
1853 ioaddr
= pci_resource_start (dev
, 3); /* i.e at offset 0x1c in the
1854 * PCI configuration register
1858 printk(KERN_INFO
"ISI PCI Card(Device ID 0x%x)\n", isicom_pci_tbl
[idx
].device
);
1860 * allot the first empty slot in the array
1862 for (count
=0; count
< BOARD_COUNT
; count
++) {
1863 if (isi_card
[count
].base
== 0) {
1864 isi_card
[count
].base
= ioaddr
;
1865 isi_card
[count
].irq
= pciirq
;
1866 isi_card
[count
].isa
= NO
;
1872 if (card
>= BOARD_COUNT
) break;
1876 if (!(isi_card
[0].base
|| isi_card
[1].base
|| isi_card
[2].base
|| isi_card
[3].base
)) {
1877 printk(KERN_ERR
"ISICOM: No valid card configuration. Driver cannot be initialized...\n");
1881 retval
= misc_register(&isiloader_device
);
1883 printk(KERN_ERR
"ISICOM: Unable to register firmware loader driver.\n");
1887 if (!isicom_init()) {
1888 if (misc_deregister(&isiloader_device
))
1889 printk(KERN_ERR
"ISICOM: Unable to unregister Firmware Loader driver\n");
1894 tx
.expires
= jiffies
+ 1;
1896 tx
.function
= isicom_tx
;
1903 void cleanup_module(void)
1909 printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count
);
1913 printk("ISICOM: uregistering isr ...\n");
1918 printk("ISICOM: unregistering drivers ...\n");
1920 unregister_drivers();
1923 printk("ISICOM: unregistering ioregion ...\n");
1925 unregister_ioregion();
1928 printk("ISICOM: freeing tmp_buf ...\n");
1930 free_page((unsigned long)tmp_buf
);
1933 printk("ISICOM: unregistering firmware loader ...\n");
1935 if (misc_deregister(&isiloader_device
))
1936 printk(KERN_ERR
"ISICOM: Unable to unregister Firmware Loader driver\n");