* better
[mascara-docs.git] / i386 / linux-2.3.21 / drivers / char / isicom.c
blob041858997e11e70c6f99da559348c43866963226
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.
7 * Original driver code supplied by Multi-Tech
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
17 * 10/6/99 sameer Merged the ISA and PCI drivers to
18 * a new unified driver.
19 * ***********************************************************
21 * To use this driver you also need the support package. You
22 * can find this in RPM format on
23 * ftp://ftp.linux.org.uk/pub/linux/alan
25 * You can find the original tools for this direct from Multitech
26 * ftp://ftp.multitech.com/ISI-Cards/
28 * Having installed the cards the module options (/etc/conf.modules)
30 * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4
32 * Omit those entries for boards you don't have installed.
36 #include <linux/module.h>
37 #include <linux/version.h>
38 #include <linux/kernel.h>
39 #include <linux/tty.h>
40 #include <linux/termios.h>
41 #include <linux/fs.h>
42 #include <linux/sched.h>
43 #include <linux/serial.h>
44 #include <linux/mm.h>
45 #include <linux/miscdevice.h>
46 #include <linux/interrupt.h>
47 #include <linux/timer.h>
48 #include <linux/ioport.h>
50 #include <asm/segment.h>
51 #include <asm/uaccess.h>
52 #include <asm/io.h>
53 #include <asm/system.h>
55 #include <linux/pci.h>
57 #include <linux/isicom.h>
59 static int device_id[] = { 0x2028,
60 0x2051,
61 0x2052,
62 0x2053,
63 0x2054,
64 0x2055,
65 0x2056,
66 0x2057,
67 0x2058
70 static int isicom_refcount = 0;
71 static int prev_card = 3; /* start servicing isi_card[0] */
72 static struct isi_board * irq_to_board[16] = { NULL, };
73 static struct tty_driver isicom_normal, isicom_callout;
74 static struct tty_struct * isicom_table[PORT_COUNT] = { NULL, };
75 static struct termios * isicom_termios[PORT_COUNT] = { NULL, };
76 static struct termios * isicom_termios_locked[PORT_COUNT] = { NULL, };
78 static struct isi_board isi_card[BOARD_COUNT];
79 static struct isi_port isi_ports[PORT_COUNT];
81 DECLARE_TASK_QUEUE(tq_isicom);
83 static struct timer_list tx;
84 static char re_schedule = 1;
85 #ifdef ISICOM_DEBUG
86 static unsigned long tx_count = 0;
87 #endif
89 static int ISILoad_open(struct inode *inode, struct file *filp);
90 static int ISILoad_release(struct inode *inode, struct file *filp);
91 static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
93 static void isicom_tx(unsigned long _data);
94 static void isicom_start(struct tty_struct * tty);
96 static unsigned char * tmp_buf = 0;
97 static DECLARE_MUTEX(tmp_buf_sem);
99 /* baud index mappings from linux defns to isi */
101 static char linuxb_to_isib[] = {
102 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,
103 18, 19
107 * Firmware loader driver specific routines
111 static struct file_operations ISILoad_fops = {
112 NULL, /* lseek */
113 NULL, /* read */
114 NULL, /* write */
115 NULL, /* readdir */
116 NULL, /* select */
117 ISILoad_ioctl,
118 NULL, /* mmap */
119 ISILoad_open,
120 NULL, /* flush */
121 ISILoad_release,
122 NULL, /* fsync */
123 NULL, /* fasync */
124 NULL, /* check_media_change */
125 NULL, /* revalidate */
128 struct miscdevice isiloader_device = {
129 ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
133 extern inline int WaitTillCardIsFree(unsigned short base)
135 unsigned long count=0;
136 while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
137 if (inw(base+0xe)&0x1)
138 return 0;
139 else
140 return 1;
143 static int ISILoad_open(struct inode *inode, struct file *filp)
145 #ifdef ISICOM_DEBUG
146 printk(KERN_DEBUG "ISILoad:Firmware loader Opened!!!\n");
147 #endif
148 MOD_INC_USE_COUNT;
149 return 0;
152 static int ISILoad_release(struct inode *inode, struct file *filp)
154 #ifdef ISICOM_DEBUG
155 printk(KERN_DEBUG "ISILoad:Firmware loader Close(Release)d\n",);
156 #endif
157 MOD_DEC_USE_COUNT;
158 return 0;
161 static int ISILoad_ioctl(struct inode *inode, struct file *filp,
162 unsigned int cmd, unsigned long arg)
164 unsigned int card, i, j, signature, status, portcount = 0;
165 unsigned short word_count, base;
166 bin_frame frame;
167 /* exec_record exec_rec; */
169 if(get_user(card, (int *)arg))
170 return -EFAULT;
172 if(card < 0 || card >= BOARD_COUNT)
173 return -ENXIO;
175 base=isi_card[card].base;
177 if(base==0)
178 return -ENXIO; /* disabled or not used */
180 switch(cmd) {
181 case MIOCTL_RESET_CARD:
182 if (!capable(CAP_SYS_ADMIN))
183 return -EPERM;
184 printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
186 inw(base+0x8);
188 for(i=jiffies+HZ/100;time_before(jiffies, i););
190 outw(0,base+0x8); /* Reset */
192 for(j=1;j<=3;j++) {
193 for(i=jiffies+HZ;time_before(jiffies, i););
194 printk(".");
196 signature=(inw(base+0x4)) & 0xff;
197 if (isi_card[card].isa) {
199 if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
200 #ifdef ISICOM_DEBUG
201 printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
202 #endif
203 printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
204 return -EIO;
207 else {
208 portcount = inw(base+0x2);
209 if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) {
210 #ifdef ISICOM_DEBUG
211 printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
212 #endif
213 printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
214 return -EIO;
217 switch(signature) {
218 case 0xa5:
219 case 0xbb:
220 case 0xdd:
221 if (isi_card[card].isa)
222 isi_card[card].port_count = 8;
223 else {
224 if (portcount == 4)
225 isi_card[card].port_count = 4;
226 else
227 isi_card[card].port_count = 8;
229 isi_card[card].shift_count = 12;
230 break;
232 case 0xcc: isi_card[card].port_count = 16;
233 isi_card[card].shift_count = 11;
234 break;
236 default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
237 #ifdef ISICOM_DEBUG
238 printk("Sig=0x%x\n",signature);
239 #endif
240 return -EIO;
242 printk("-Done\n");
243 return put_user(signature,(unsigned int*)arg);
245 case MIOCTL_LOAD_FIRMWARE:
246 if (!capable(CAP_SYS_ADMIN))
247 return -EPERM;
249 if(copy_from_user(&frame, (void *) arg, sizeof(bin_frame)))
250 return -EFAULT;
252 if (WaitTillCardIsFree(base))
253 return -EIO;
255 outw(0xf0,base); /* start upload sequence */
256 outw(0x00,base);
257 outw((frame.addr), base);/* lsb of adderess */
259 word_count=(frame.count >> 1) + frame.count % 2;
260 outw(word_count, base);
261 InterruptTheCard(base);
263 for(i=0;i<=0x2f;i++); /* a wee bit of delay */
265 if (WaitTillCardIsFree(base))
266 return -EIO;
268 if ((status=inw(base+0x4))!=0) {
269 printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
270 card+1, frame.addr, frame.count, status);
271 return -EIO;
273 outsw(base, (void *) frame.bin_data, word_count);
275 InterruptTheCard(base);
277 for(i=0;i<=0x0f;i++); /* another wee bit of delay */
279 if (WaitTillCardIsFree(base))
280 return -EIO;
282 if ((status=inw(base+0x4))!=0) {
283 printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status);
284 return -EIO;
286 return 0;
288 case MIOCTL_READ_FIRMWARE:
289 if (!capable(CAP_SYS_ADMIN))
290 return -EPERM;
292 if(copy_from_user(&frame, (void *) arg, sizeof(bin_header)))
293 return -EFAULT;
295 if (WaitTillCardIsFree(base))
296 return -EIO;
298 outw(0xf1,base); /* start download sequence */
299 outw(0x00,base);
300 outw((frame.addr), base);/* lsb of adderess */
302 word_count=(frame.count >> 1) + frame.count % 2;
303 outw(word_count+1, base);
304 InterruptTheCard(base);
306 for(i=0;i<=0xf;i++); /* a wee bit of delay */
308 if (WaitTillCardIsFree(base))
309 return -EIO;
311 if ((status=inw(base+0x4))!=0) {
312 printk(KERN_WARNING "ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
313 card+1, frame.addr, frame.count, status);
314 return -EIO;
317 inw(base);
318 insw(base, frame.bin_data, word_count);
319 InterruptTheCard(base);
321 for(i=0;i<=0x0f;i++); /* another wee bit of delay */
323 if (WaitTillCardIsFree(base))
324 return -EIO;
326 if ((status=inw(base+0x4))!=0) {
327 printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card+1, status);
328 return -EIO;
331 if(copy_to_user((void *) arg, &frame, sizeof(bin_frame)))
332 return -EFAULT;
333 return 0;
335 case MIOCTL_XFER_CTRL:
336 if (!capable(CAP_SYS_ADMIN))
337 return -EPERM;
338 if (WaitTillCardIsFree(base))
339 return -EIO;
341 outw(0xf2, base);
342 outw(0x800, base);
343 outw(0x0, base);
344 outw(0x0, base);
345 InterruptTheCard(base);
346 outw(0x0, base+0x4); /* for ISI4608 cards */
348 isi_card[card].status |= FIRMWARE_LOADED;
349 return 0;
351 default:
352 #ifdef ISICOM_DEBUG
353 printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.\n", cmd);
354 #endif
355 return -ENOIOCTLCMD;
363 * ISICOM Driver specific routines ...
367 static inline int isicom_paranoia_check(struct isi_port const * port, kdev_t dev,
368 const char * routine)
370 #ifdef ISICOM_DEBUG
371 static const char * badmagic =
372 KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
373 static const char * badport =
374 KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n";
375 if (!port) {
376 printk(badport, kdevname(dev), routine);
377 return 1;
379 if (port->magic != ISICOM_MAGIC) {
380 printk(badmagic, kdevname(dev), routine);
381 return 1;
383 #endif
384 return 0;
387 extern inline void schedule_bh(struct isi_port * port)
389 queue_task(&port->bh_tqueue, &tq_isicom);
390 mark_bh(ISICOM_BH);
393 /* Transmitter */
395 static void isicom_tx(unsigned long _data)
397 short count = (BOARD_COUNT-1), card, base;
398 short txcount, wait, wrd, residue, word_count, cnt;
399 struct isi_port * port;
400 struct tty_struct * tty;
401 unsigned long flags;
403 #ifdef ISICOM_DEBUG
404 ++tx_count;
405 #endif
407 /* find next active board */
408 card = (prev_card + 1) & 0x0003;
409 while(count-- > 0) {
410 if (isi_card[card].status & BOARD_ACTIVE)
411 break;
412 card = (card + 1) & 0x0003;
414 if (!(isi_card[card].status & BOARD_ACTIVE))
415 goto sched_again;
417 prev_card = card;
419 count = isi_card[card].port_count;
420 port = isi_card[card].ports;
421 base = isi_card[card].base;
422 for (;count > 0;count--, port++) {
423 /* port not active or tx disabled to force flow control */
424 if (!(port->status & ISI_TXOK))
425 continue;
427 tty = port->tty;
428 save_flags(flags); cli();
429 txcount = MIN(TX_SIZE, port->xmit_cnt);
430 if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
431 restore_flags(flags);
432 continue;
434 wait = 200;
435 while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
436 if (wait <= 0) {
437 restore_flags(flags);
438 #ifdef ISICOM_DEBUG
439 printk(KERN_DEBUG "ISICOM: isicom_tx:Card(0x%x) found busy.\n",
440 card);
441 #endif
442 continue;
444 if (!(inw(base + 0x02) & (1 << port->channel))) {
445 restore_flags(flags);
446 #ifdef ISICOM_DEBUG
447 printk(KERN_DEBUG "ISICOM: isicom_tx: cannot tx to 0x%x:%d.\n",
448 base, port->channel + 1);
449 #endif
450 continue;
452 #ifdef ISICOM_DEBUG
453 printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n",
454 txcount, port->channel+1);
455 #endif
456 outw((port->channel << isi_card[card].shift_count) | txcount
457 , base);
458 residue = NO;
459 wrd = 0;
460 while (1) {
461 cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
462 if (residue == YES) {
463 residue = NO;
464 if (cnt > 0) {
465 wrd |= (port->xmit_buf[port->xmit_tail] << 8);
466 port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
467 port->xmit_cnt--;
468 txcount--;
469 cnt--;
470 outw(wrd, base);
472 else {
473 outw(wrd, base);
474 break;
477 if (cnt <= 0) break;
478 word_count = cnt >> 1;
479 outsw(base, port->xmit_buf+port->xmit_tail, word_count);
480 port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
481 (SERIAL_XMIT_SIZE - 1);
482 txcount -= (word_count << 1);
483 port->xmit_cnt -= (word_count << 1);
484 if (cnt & 0x0001) {
485 residue = YES;
486 wrd = port->xmit_buf[port->xmit_tail];
487 port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
488 port->xmit_cnt--;
489 txcount--;
493 InterruptTheCard(base);
494 if (port->xmit_cnt <= 0)
495 port->status &= ~ISI_TXOK;
496 if (port->xmit_cnt <= WAKEUP_CHARS)
497 schedule_bh(port);
498 restore_flags(flags);
501 /* schedule another tx for hopefully in about 10ms */
502 sched_again:
503 if (!re_schedule)
504 return;
505 init_timer(&tx);
506 tx.expires = jiffies + HZ/100;
507 tx.data = 0;
508 tx.function = isicom_tx;
509 add_timer(&tx);
511 return;
514 /* Interrupt handlers */
516 static void do_isicom_bh(void)
518 run_task_queue(&tq_isicom);
523 static void isicom_bottomhalf(void * data)
525 struct isi_port * port = (struct isi_port *) data;
526 struct tty_struct * tty = port->tty;
528 if (!tty)
529 return;
531 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
532 tty->ldisc.write_wakeup)
533 (tty->ldisc.write_wakeup)(tty);
534 wake_up_interruptible(&tty->write_wait);
537 /* main interrupt handler routine */
538 static void isicom_interrupt(int irq, void * dev_id, struct pt_regs * regs)
540 struct isi_board * card;
541 struct isi_port * port;
542 struct tty_struct * tty;
543 unsigned short base, header, word_count, count;
544 unsigned char channel;
545 short byte_count;
548 * find the source of interrupt
551 for(count = 0; count < BOARD_COUNT; count++) {
552 card = &isi_card[count];
553 if (card->base != 0) {
554 if (((card->isa == YES) && (card->irq == irq)) ||
555 ((card->isa == NO) && (card->irq == irq) && (inw(card->base+0x0e) & 0x02)))
556 break;
558 card = NULL;
561 if (!card || !(card->status & FIRMWARE_LOADED)) {
562 /* printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);*/
563 return;
566 base = card->base;
567 if (card->isa == NO) {
569 * disable any interrupts from the PCI card and lower the
570 * interrupt line
572 outw(0x8000, base+0x04);
573 ClearInterrupt(base);
576 inw(base); /* get the dummy word out */
577 header = inw(base);
578 channel = (header & 0x7800) >> card->shift_count;
579 byte_count = header & 0xff;
580 #ifdef ISICOM_DEBUG
581 printk(KERN_DEBUG "ISICOM:Intr:(0x%x:%d).\n", base, channel+1);
582 #endif
583 if ((channel+1) > card->port_count) {
584 printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
585 base, channel+1);
586 if (card->isa)
587 ClearInterrupt(base);
588 else
589 outw(0x0000, base+0x04); /* enable interrupts */
590 return;
592 port = card->ports + channel;
593 if (!(port->flags & ASYNC_INITIALIZED)) {
594 if (card->isa)
595 ClearInterrupt(base);
596 else
597 outw(0x0000, base+0x04); /* enable interrupts */
598 return;
601 tty = port->tty;
603 if (header & 0x8000) { /* Status Packet */
604 header = inw(base);
605 switch(header & 0xff) {
606 case 0: /* Change in EIA signals */
608 if (port->flags & ASYNC_CHECK_CD) {
609 if (port->status & ISI_DCD) {
610 if (!(header & ISI_DCD)) {
611 /* Carrier has been lost */
612 #ifdef ISICOM_DEBUG
613 printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
614 #endif
615 port->status &= ~ISI_DCD;
616 if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
617 (port->flags & ASYNC_CALLOUT_NOHUP)))
618 queue_task(&port->hangup_tq,
619 &tq_scheduler);
622 else {
623 if (header & ISI_DCD) {
624 /* Carrier has been detected */
625 #ifdef ISICOM_DEBUG
626 printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
627 #endif
628 port->status |= ISI_DCD;
629 wake_up_interruptible(&port->open_wait);
633 else {
634 if (header & ISI_DCD)
635 port->status |= ISI_DCD;
636 else
637 port->status &= ~ISI_DCD;
640 if (port->flags & ASYNC_CTS_FLOW) {
641 if (port->tty->hw_stopped) {
642 if (header & ISI_CTS) {
643 port->tty->hw_stopped = 0;
644 /* start tx ing */
645 port->status |= (ISI_TXOK | ISI_CTS);
646 schedule_bh(port);
649 else {
650 if (!(header & ISI_CTS)) {
651 port->tty->hw_stopped = 1;
652 /* stop tx ing */
653 port->status &= ~(ISI_TXOK | ISI_CTS);
657 else {
658 if (header & ISI_CTS)
659 port->status |= ISI_CTS;
660 else
661 port->status &= ~ISI_CTS;
664 if (header & ISI_DSR)
665 port->status |= ISI_DSR;
666 else
667 port->status &= ~ISI_DSR;
669 if (header & ISI_RI)
670 port->status |= ISI_RI;
671 else
672 port->status &= ~ISI_RI;
674 break;
676 case 1: /* Received Break !!! */
677 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
678 break;
679 *tty->flip.flag_buf_ptr++ = TTY_BREAK;
680 /* dunno if this is right */
681 *tty->flip.char_buf_ptr++ = 0;
682 tty->flip.count++;
683 if (port->flags & ASYNC_SAK)
684 do_SAK(tty);
685 queue_task(&tty->flip.tqueue, &tq_timer);
686 break;
688 case 2: /* Statistics */
689 printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");
690 break;
692 default:
693 printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n");
694 break;
697 else { /* Data Packet */
698 count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
699 #ifdef ISICOM_DEBUG
700 printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n",
701 count, byte_count);
702 #endif
703 word_count = count >> 1;
704 insw(base, tty->flip.char_buf_ptr, word_count);
705 tty->flip.char_buf_ptr += (word_count << 1);
706 byte_count -= (word_count << 1);
707 if (count & 0x0001) {
708 *tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
709 byte_count -= 2;
711 memset(tty->flip.flag_buf_ptr, 0, count);
712 tty->flip.flag_buf_ptr += count;
713 tty->flip.count += count;
715 if (byte_count > 0) {
716 printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
717 base, channel+1);
718 while(byte_count > 0) { /* drain out unread xtra data */
719 inw(base);
720 byte_count -= 2;
723 queue_task(&tty->flip.tqueue, &tq_timer);
725 if (card->isa == YES)
726 ClearInterrupt(base);
727 else
728 outw(0x0000, base+0x04); /* enable interrupts */
729 return;
732 /* called with interrupts disabled */
733 static void isicom_config_port(struct isi_port * port)
735 struct isi_board * card = port->card;
736 struct tty_struct * tty;
737 unsigned long baud;
738 unsigned short channel_setup, wait, base = card->base;
739 unsigned short channel = port->channel, shift_count = card->shift_count;
740 unsigned char flow_ctrl;
742 if (!(tty = port->tty) || !tty->termios)
743 return;
744 baud = C_BAUD(tty);
745 if (baud & CBAUDEX) {
746 baud &= ~CBAUDEX;
748 /* if CBAUDEX bit is on and the baud is set to either 50 or 75
749 * then the card is programmed for 57.6Kbps or 115Kbps
750 * respectively.
753 if (baud < 1 || baud > 2)
754 port->tty->termios->c_cflag &= ~CBAUDEX;
755 else
756 baud += 15;
758 if (baud == 15) {
760 /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
761 * by the set_serial_info ioctl ... this is done by
762 * the 'setserial' utility.
765 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
766 baud++; /* 57.6 Kbps */
767 if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
768 baud +=2; /* 115 Kbps */
770 if (linuxb_to_isib[baud] == -1) {
771 /* hang up */
772 drop_dtr(port);
773 return;
775 else
776 raise_dtr(port);
778 wait = 100;
779 while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
780 if (!wait) {
781 printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at channel setup.\n");
782 return;
784 outw(0x8000 | (channel << shift_count) |0x03, base);
785 outw(linuxb_to_isib[baud] << 8 | 0x03, base);
786 channel_setup = 0;
787 switch(C_CSIZE(tty)) {
788 case CS5:
789 channel_setup |= ISICOM_CS5;
790 break;
791 case CS6:
792 channel_setup |= ISICOM_CS6;
793 break;
794 case CS7:
795 channel_setup |= ISICOM_CS7;
796 break;
797 case CS8:
798 channel_setup |= ISICOM_CS8;
799 break;
802 if (C_CSTOPB(tty))
803 channel_setup |= ISICOM_2SB;
805 if (C_PARENB(tty))
806 channel_setup |= ISICOM_EVPAR;
807 if (C_PARODD(tty))
808 channel_setup |= ISICOM_ODPAR;
809 outw(channel_setup, base);
810 InterruptTheCard(base);
812 if (C_CLOCAL(tty))
813 port->flags &= ~ASYNC_CHECK_CD;
814 else
815 port->flags |= ASYNC_CHECK_CD;
817 /* flow control settings ...*/
818 flow_ctrl = 0;
819 port->flags &= ~ASYNC_CTS_FLOW;
820 if (C_CRTSCTS(tty)) {
821 port->flags |= ASYNC_CTS_FLOW;
822 flow_ctrl |= ISICOM_CTSRTS;
824 if (I_IXON(tty))
825 flow_ctrl |= ISICOM_RESPOND_XONXOFF;
826 if (I_IXOFF(tty))
827 flow_ctrl |= ISICOM_INITIATE_XONXOFF;
829 wait = 100;
830 while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
831 if (!wait) {
832 printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at flow setup.\n");
833 return;
835 outw(0x8000 | (channel << shift_count) |0x04, base);
836 outw(flow_ctrl << 8 | 0x05, base);
837 outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
838 InterruptTheCard(base);
840 /* rx enabled -> enable port for rx on the card */
841 if (C_CREAD(tty)) {
842 card->port_status |= (1 << channel);
843 outw(card->port_status, base + 0x02);
848 /* open et all */
850 extern inline void isicom_setup_board(struct isi_board * bp)
852 int channel;
853 struct isi_port * port;
854 unsigned long flags;
856 if (bp->status & BOARD_ACTIVE)
857 return;
858 port = bp->ports;
859 #ifdef ISICOM_DEBUG
860 printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts start, port_count %d...\n", bp->port_count);
861 #endif
862 for(channel = 0; channel < bp->port_count; channel++, port++) {
863 save_flags(flags); cli();
864 drop_dtr_rts(port);
865 restore_flags(flags);
867 #ifdef ISICOM_DEBUG
868 printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts stop...\n");
869 #endif
871 bp->status |= BOARD_ACTIVE;
872 MOD_INC_USE_COUNT;
873 return;
876 static int isicom_setup_port(struct isi_port * port)
878 struct isi_board * card = port->card;
879 unsigned long flags;
881 if (port->flags & ASYNC_INITIALIZED)
882 return 0;
883 if (!port->xmit_buf) {
884 unsigned long page;
886 if (!(page = get_free_page(GFP_KERNEL)))
887 return -ENOMEM;
889 if (port->xmit_buf) {
890 free_page(page);
891 return -ERESTARTSYS;
893 port->xmit_buf = (unsigned char *) page;
895 save_flags(flags); cli();
896 if (port->tty)
897 clear_bit(TTY_IO_ERROR, &port->tty->flags);
898 if (port->count == 1)
899 card->count++;
901 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
903 /* discard any residual data */
904 kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
906 isicom_config_port(port);
907 port->flags |= ASYNC_INITIALIZED;
909 restore_flags(flags);
911 return 0;
914 static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port)
916 int do_clocal = 0, retval;
917 DECLARE_WAITQUEUE(wait, current);
919 /* block if port is in the process of being closed */
921 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
922 #ifdef ISICOM_DEBUG
923 printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
924 #endif
925 interruptible_sleep_on(&port->close_wait);
926 if (port->flags & ASYNC_HUP_NOTIFY)
927 return -EAGAIN;
928 else
929 return -ERESTARTSYS;
932 /* trying to open a callout device... check for constraints */
934 if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
935 #ifdef ISICOM_DEBUG
936 printk(KERN_DEBUG "ISICOM: bl_ti_rdy: callout open.\n");
937 #endif
938 if (port->flags & ASYNC_NORMAL_ACTIVE)
939 return -EBUSY;
940 if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
941 (port->flags & ASYNC_SESSION_LOCKOUT) &&
942 (port->session != current->session))
943 return -EBUSY;
945 if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
946 (port->flags & ASYNC_PGRP_LOCKOUT) &&
947 (port->pgrp != current->pgrp))
948 return -EBUSY;
949 port->flags |= ASYNC_CALLOUT_ACTIVE;
950 cli();
951 raise_dtr_rts(port);
952 sti();
953 return 0;
956 /* if non-blocking mode is set ... */
958 if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
959 #ifdef ISICOM_DEBUG
960 printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
961 #endif
962 if (port->flags & ASYNC_CALLOUT_ACTIVE)
963 return -EBUSY;
964 port->flags |= ASYNC_NORMAL_ACTIVE;
965 return 0;
968 if (port->flags & ASYNC_CALLOUT_ACTIVE) {
969 if (port->normal_termios.c_cflag & CLOCAL)
970 do_clocal = 1;
971 } else {
972 if (C_CLOCAL(tty))
973 do_clocal = 1;
975 #ifdef ISICOM_DEBUG
976 if (do_clocal)
977 printk(KERN_DEBUG "ISICOM: block_til_ready: CLOCAL set.\n");
978 #endif
980 /* block waiting for DCD to be asserted, and while
981 callout dev is busy */
982 retval = 0;
983 add_wait_queue(&port->open_wait, &wait);
984 cli();
985 if (!tty_hung_up_p(filp))
986 port->count--;
987 sti();
988 port->blocked_open++;
989 #ifdef ISICOM_DEBUG
990 printk(KERN_DEBUG "ISICOM: block_til_ready: waiting for DCD...\n");
991 #endif
992 while (1) {
993 cli();
994 if (!(port->flags & ASYNC_CALLOUT_ACTIVE))
995 raise_dtr_rts(port);
997 sti();
998 set_current_state(TASK_INTERRUPTIBLE);
999 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
1000 if (port->flags & ASYNC_HUP_NOTIFY)
1001 retval = -EAGAIN;
1002 else
1003 retval = -ERESTARTSYS;
1004 #ifdef ISICOM_DEBUG
1005 printk(KERN_DEBUG "ISICOM: block_til_ready: tty_hung_up_p || not init.\n");
1006 #endif
1007 break;
1009 if (!(port->flags & ASYNC_CALLOUT_ACTIVE) &&
1010 !(port->flags & ASYNC_CLOSING) &&
1011 (do_clocal || (port->status & ISI_DCD))) {
1012 #ifdef ISICOM_DEBUG
1013 printk(KERN_DEBUG "ISICOM: block_til_ready: do_clocal || DCD.\n");
1014 #endif
1015 break;
1017 if (signal_pending(current)) {
1018 #ifdef ISICOM_DEBUG
1019 printk(KERN_DEBUG "ISICOM: block_til_ready: sig blocked.\n");
1020 #endif
1021 retval = -ERESTARTSYS;
1022 break;
1024 schedule();
1026 current->state = TASK_RUNNING;
1027 remove_wait_queue(&port->open_wait, &wait);
1028 if (!tty_hung_up_p(filp))
1029 port->count++;
1030 port->blocked_open--;
1031 if (retval)
1032 return retval;
1033 port->flags |= ASYNC_NORMAL_ACTIVE;
1034 return 0;
1037 static int isicom_open(struct tty_struct * tty, struct file * filp)
1039 struct isi_port * port;
1040 struct isi_board * card;
1041 unsigned int line, board;
1042 unsigned long flags;
1043 int error;
1045 #ifdef ISICOM_DEBUG
1046 printk(KERN_DEBUG "ISICOM: open start!!!.\n");
1047 #endif
1048 line = MINOR(tty->device) - tty->driver.minor_start;
1050 #ifdef ISICOM_DEBUG
1051 printk(KERN_DEBUG "line = %d.\n", line);
1052 #endif
1054 if ((line < 0) || (line > (PORT_COUNT-1)))
1055 return -ENODEV;
1056 board = BOARD(line);
1058 #ifdef ISICOM_DEBUG
1059 printk(KERN_DEBUG "board = %d.\n", board);
1060 #endif
1062 card = &isi_card[board];
1063 if (!(card->status & FIRMWARE_LOADED)) {
1064 #ifdef ISICOM_DEBUG
1065 printk(KERN_DEBUG"ISICOM: Firmware not loaded to card%d.\n", board);
1066 #endif
1067 return -ENODEV;
1070 /* open on a port greater than the port count for the card !!! */
1071 if (line > ((board * 16) + card->port_count - 1)) {
1072 printk(KERN_ERR "ISICOM: Open on a port which exceeds the port_count of the card!\n");
1073 return -ENODEV;
1075 port = &isi_ports[line];
1076 if (isicom_paranoia_check(port, tty->device, "isicom_open"))
1077 return -ENODEV;
1079 #ifdef ISICOM_DEBUG
1080 printk(KERN_DEBUG "ISICOM: isicom_setup_board ...\n");
1081 #endif
1082 isicom_setup_board(card);
1084 port->count++;
1085 tty->driver_data = port;
1086 port->tty = tty;
1087 #ifdef ISICOM_DEBUG
1088 printk(KERN_DEBUG "ISICOM: isicom_setup_port ...\n");
1089 #endif
1090 if ((error = isicom_setup_port(port))!=0)
1091 return error;
1092 #ifdef ISICOM_DEBUG
1093 printk(KERN_DEBUG "ISICOM: block_til_ready ...\n");
1094 #endif
1095 if ((error = block_til_ready(tty, filp, port))!=0)
1096 return error;
1098 if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
1099 if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
1100 *tty->termios = port->normal_termios;
1101 else
1102 *tty->termios = port->callout_termios;
1103 save_flags(flags); cli();
1104 isicom_config_port(port);
1105 restore_flags(flags);
1108 port->session = current->session;
1109 port->pgrp = current->pgrp;
1110 #ifdef ISICOM_DEBUG
1111 printk(KERN_DEBUG "ISICOM: open end!!!.\n");
1112 #endif
1113 return 0;
1116 /* close et all */
1118 extern inline void isicom_shutdown_board(struct isi_board * bp)
1120 int channel;
1121 struct isi_port * port;
1123 if (!(bp->status & BOARD_ACTIVE))
1124 return;
1125 bp->status &= ~BOARD_ACTIVE;
1126 port = bp->ports;
1127 for(channel = 0; channel < bp->port_count; channel++, port++) {
1128 drop_dtr_rts(port);
1130 MOD_DEC_USE_COUNT;
1133 static void isicom_shutdown_port(struct isi_port * port)
1135 struct isi_board * card = port->card;
1136 struct tty_struct * tty;
1138 if (!(port->flags & ASYNC_INITIALIZED))
1139 return;
1140 if (port->xmit_buf) {
1141 free_page((unsigned long) port->xmit_buf);
1142 port->xmit_buf = NULL;
1144 if (!(tty = port->tty) || C_HUPCL(tty))
1145 /* drop dtr on this port */
1146 drop_dtr(port);
1148 /* any other port uninits */
1150 if (tty)
1151 set_bit(TTY_IO_ERROR, &tty->flags);
1152 port->flags &= ~ASYNC_INITIALIZED;
1154 if (--card->count < 0) {
1155 printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
1156 card->base, card->count);
1157 card->count = 0;
1160 /* last port was closed , shutdown that boad too */
1161 if (!card->count)
1162 isicom_shutdown_board(card);
1165 static void isicom_close(struct tty_struct * tty, struct file * filp)
1167 struct isi_port * port = (struct isi_port *) tty->driver_data;
1168 struct isi_board * card = port->card;
1169 unsigned long flags;
1171 if (!port)
1172 return;
1173 if (isicom_paranoia_check(port, tty->device, "isicom_close"))
1174 return;
1176 #ifdef ISICOM_DEBUG
1177 printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
1178 #endif
1180 save_flags(flags); cli();
1181 if (tty_hung_up_p(filp)) {
1182 restore_flags(flags);
1183 return;
1186 if ((tty->count == 1) && (port->count != 1)) {
1187 printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
1188 "tty->count = 1 port count = %d.\n",
1189 card->base, port->count);
1190 port->count = 1;
1192 if (--port->count < 0) {
1193 printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
1194 "channel%d = %d", card->base, port->channel,
1195 port->count);
1196 port->count = 0;
1199 if (port->count) {
1200 restore_flags(flags);
1201 return;
1203 port->flags |= ASYNC_CLOSING;
1205 * save termios struct since callout and dialin termios may be
1206 * different.
1208 if (port->flags & ASYNC_NORMAL_ACTIVE)
1209 port->normal_termios = *tty->termios;
1210 if (port->flags & ASYNC_CALLOUT_ACTIVE)
1211 port->callout_termios = *tty->termios;
1213 tty->closing = 1;
1214 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1215 tty_wait_until_sent(tty, port->closing_wait);
1216 /* indicate to the card that no more data can be received
1217 on this port */
1218 if (port->flags & ASYNC_INITIALIZED) {
1219 card->port_status &= ~(1 << port->channel);
1220 outw(card->port_status, card->base + 0x02);
1222 isicom_shutdown_port(port);
1223 if (tty->driver.flush_buffer)
1224 tty->driver.flush_buffer(tty);
1225 if (tty->ldisc.flush_buffer)
1226 tty->ldisc.flush_buffer(tty);
1227 tty->closing = 0;
1228 port->tty = 0;
1229 if (port->blocked_open) {
1230 if (port->close_delay) {
1231 current->state = TASK_INTERRUPTIBLE;
1232 #ifdef ISICOM_DEBUG
1233 printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
1234 #endif
1235 schedule_timeout(port->close_delay);
1237 wake_up_interruptible(&port->open_wait);
1239 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
1240 ASYNC_CLOSING);
1241 wake_up_interruptible(&port->close_wait);
1242 restore_flags(flags);
1243 #ifdef ISICOM_DEBUG
1244 printk(KERN_DEBUG "ISICOM: Close end!!!.\n");
1245 #endif
1248 /* write et all */
1249 static int isicom_write(struct tty_struct * tty, int from_user,
1250 const unsigned char * buf, int count)
1252 struct isi_port * port = (struct isi_port *) tty->driver_data;
1253 unsigned long flags;
1254 int cnt, total = 0;
1255 #ifdef ISICOM_DEBUG
1256 printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n",
1257 port->channel+1, count);
1258 #endif
1259 if (isicom_paranoia_check(port, tty->device, "isicom_write"))
1260 return 0;
1262 if (!tty || !port->xmit_buf || !tmp_buf)
1263 return 0;
1264 if (from_user)
1265 down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */
1267 save_flags(flags);
1268 while(1) {
1269 cli();
1270 cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1271 SERIAL_XMIT_SIZE - port->xmit_head));
1272 if (cnt <= 0)
1273 break;
1275 if (from_user) {
1276 /* the following may block for paging... hence
1277 enabling interrupts but tx routine may have
1278 created more space in xmit_buf when the ctrl
1279 gets back here */
1280 sti();
1281 copy_from_user(tmp_buf, buf, cnt);
1282 cli();
1283 cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1284 SERIAL_XMIT_SIZE - port->xmit_head));
1285 memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
1287 else
1288 memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
1289 port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
1290 port->xmit_cnt += cnt;
1291 restore_flags(flags);
1292 buf += cnt;
1293 count -= cnt;
1294 total += cnt;
1296 if (from_user)
1297 up(&tmp_buf_sem);
1298 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
1299 port->status |= ISI_TXOK;
1300 restore_flags(flags);
1301 #ifdef ISICOM_DEBUG
1302 printk(KERN_DEBUG "ISICOM: isicom_write %d bytes written.\n", total);
1303 #endif
1304 return total;
1307 /* put_char et all */
1308 static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
1310 struct isi_port * port = (struct isi_port *) tty->driver_data;
1311 unsigned long flags;
1313 if (isicom_paranoia_check(port, tty->device, "isicom_put_char"))
1314 return;
1316 if (!tty || !port->xmit_buf)
1317 return;
1318 #ifdef ISICOM_DEBUG
1319 printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch);
1320 #endif
1322 save_flags(flags); cli();
1324 if (port->xmit_cnt >= (SERIAL_XMIT_SIZE - 1)) {
1325 restore_flags(flags);
1326 return;
1329 port->xmit_buf[port->xmit_head++] = ch;
1330 port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
1331 port->xmit_cnt++;
1332 restore_flags(flags);
1335 /* flush_chars et all */
1336 static void isicom_flush_chars(struct tty_struct * tty)
1338 struct isi_port * port = (struct isi_port *) tty->driver_data;
1340 if (isicom_paranoia_check(port, tty->device, "isicom_flush_chars"))
1341 return;
1343 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1344 !port->xmit_buf)
1345 return;
1347 /* this tells the transmitter to consider this port for
1348 data output to the card ... that's the best we can do. */
1349 port->status |= ISI_TXOK;
1352 /* write_room et all */
1353 static int isicom_write_room(struct tty_struct * tty)
1355 struct isi_port * port = (struct isi_port *) tty->driver_data;
1356 int free;
1357 if (isicom_paranoia_check(port, tty->device, "isicom_write_room"))
1358 return 0;
1360 free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1361 if (free < 0)
1362 free = 0;
1363 return free;
1366 /* chars_in_buffer et all */
1367 static int isicom_chars_in_buffer(struct tty_struct * tty)
1369 struct isi_port * port = (struct isi_port *) tty->driver_data;
1370 if (isicom_paranoia_check(port, tty->device, "isicom_chars_in_buffer"))
1371 return 0;
1372 return port->xmit_cnt;
1375 /* ioctl et all */
1376 extern inline void isicom_send_break(struct isi_port * port, unsigned long length)
1378 struct isi_board * card = port->card;
1379 short wait = 10;
1380 unsigned short base = card->base;
1381 unsigned long flags;
1383 save_flags(flags); cli();
1384 while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
1385 if (!wait) {
1386 printk(KERN_DEBUG "ISICOM: Card found busy in isicom_send_break.\n");
1387 return;
1389 outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
1390 outw((length & 0xff) << 8 | 0x00, base);
1391 outw((length & 0xff00), base);
1392 InterruptTheCard(base);
1393 restore_flags(flags);
1396 static int isicom_get_modem_info(struct isi_port * port, unsigned int * value)
1398 /* just send the port status */
1399 unsigned int info;
1400 unsigned short status = port->status;
1402 info = ((status & ISI_RTS) ? TIOCM_RTS : 0) |
1403 ((status & ISI_DTR) ? TIOCM_DTR : 0) |
1404 ((status & ISI_DCD) ? TIOCM_CAR : 0) |
1405 ((status & ISI_DSR) ? TIOCM_DSR : 0) |
1406 ((status & ISI_CTS) ? TIOCM_CTS : 0) |
1407 ((status & ISI_RI ) ? TIOCM_RI : 0);
1408 put_user(info, (unsigned int *) value);
1409 return 0;
1412 static int isicom_set_modem_info(struct isi_port * port, unsigned int cmd,
1413 unsigned int * value)
1415 unsigned int arg;
1416 unsigned long flags;
1418 if(get_user(arg, value))
1419 return -EFAULT;
1421 save_flags(flags); cli();
1423 switch(cmd) {
1424 case TIOCMBIS:
1425 if (arg & TIOCM_RTS)
1426 raise_rts(port);
1427 if (arg & TIOCM_DTR)
1428 raise_dtr(port);
1429 break;
1431 case TIOCMBIC:
1432 if (arg & TIOCM_RTS)
1433 drop_rts(port);
1434 if (arg & TIOCM_DTR)
1435 drop_dtr(port);
1436 break;
1438 case TIOCMSET:
1439 if (arg & TIOCM_RTS)
1440 raise_rts(port);
1441 else
1442 drop_rts(port);
1444 if (arg & TIOCM_DTR)
1445 raise_dtr(port);
1446 else
1447 drop_dtr(port);
1448 break;
1450 default:
1451 restore_flags(flags);
1452 return -EINVAL;
1454 restore_flags(flags);
1455 return 0;
1458 static int isicom_set_serial_info(struct isi_port * port,
1459 struct serial_struct * info)
1461 struct serial_struct newinfo;
1462 unsigned long flags;
1463 int reconfig_port;
1465 if(copy_from_user(&newinfo, info, sizeof(newinfo)))
1466 return -EFAULT;
1468 reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
1469 (newinfo.flags & ASYNC_SPD_MASK));
1471 if (!suser()) {
1472 if ((newinfo.close_delay != port->close_delay) ||
1473 (newinfo.closing_wait != port->closing_wait) ||
1474 ((newinfo.flags & ~ASYNC_USR_MASK) !=
1475 (port->flags & ~ASYNC_USR_MASK)))
1476 return -EPERM;
1477 port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
1478 (newinfo.flags & ASYNC_USR_MASK));
1480 else {
1481 port->close_delay = newinfo.close_delay;
1482 port->closing_wait = newinfo.closing_wait;
1483 port->flags = ((port->flags & ~ASYNC_FLAGS) |
1484 (newinfo.flags & ASYNC_FLAGS));
1486 if (reconfig_port) {
1487 save_flags(flags); cli();
1488 isicom_config_port(port);
1489 restore_flags(flags);
1491 return 0;
1494 static int isicom_get_serial_info(struct isi_port * port,
1495 struct serial_struct * info)
1497 struct serial_struct out_info;
1499 memset(&out_info, 0, sizeof(out_info));
1500 /* out_info.type = ? */
1501 out_info.line = port - isi_ports;
1502 out_info.port = port->card->base;
1503 out_info.irq = port->card->irq;
1504 out_info.flags = port->flags;
1505 /* out_info.baud_base = ? */
1506 out_info.close_delay = port->close_delay;
1507 out_info.closing_wait = port->closing_wait;
1508 if(copy_to_user(info, &out_info, sizeof(out_info)))
1509 return -EFAULT;
1510 return 0;
1513 static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
1514 unsigned int cmd, unsigned long arg)
1516 struct isi_port * port = (struct isi_port *) tty->driver_data;
1517 int retval;
1519 if (isicom_paranoia_check(port, tty->device, "isicom_ioctl"))
1520 return -ENODEV;
1522 switch(cmd) {
1523 case TCSBRK:
1524 retval = tty_check_change(tty);
1525 if (retval)
1526 return retval;
1527 tty_wait_until_sent(tty, 0);
1528 if (!arg)
1529 isicom_send_break(port, HZ/4);
1530 return 0;
1532 case TCSBRKP:
1533 retval = tty_check_change(tty);
1534 if (retval)
1535 return retval;
1536 tty_wait_until_sent(tty, 0);
1537 isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
1538 return 0;
1540 case TIOCGSOFTCAR:
1541 return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
1543 case TIOCSSOFTCAR:
1544 if(get_user(arg, (unsigned long *) arg))
1545 return -EFAULT;
1546 tty->termios->c_cflag =
1547 ((tty->termios->c_cflag & ~CLOCAL) |
1548 (arg ? CLOCAL : 0));
1549 return 0;
1551 case TIOCMGET:
1552 return isicom_get_modem_info(port, (unsigned int*) arg);
1554 case TIOCMBIS:
1555 case TIOCMBIC:
1556 case TIOCMSET:
1557 return isicom_set_modem_info(port, cmd,
1558 (unsigned int *) arg);
1560 case TIOCGSERIAL:
1561 return isicom_get_serial_info(port,
1562 (struct serial_struct *) arg);
1564 case TIOCSSERIAL:
1565 return isicom_set_serial_info(port,
1566 (struct serial_struct *) arg);
1568 default:
1569 return -ENOIOCTLCMD;
1571 return 0;
1574 /* set_termios et all */
1575 static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
1577 struct isi_port * port = (struct isi_port *) tty->driver_data;
1578 unsigned long flags;
1580 if (isicom_paranoia_check(port, tty->device, "isicom_set_termios"))
1581 return;
1583 if (tty->termios->c_cflag == old_termios->c_cflag &&
1584 tty->termios->c_iflag == old_termios->c_iflag)
1585 return;
1587 save_flags(flags); cli();
1588 isicom_config_port(port);
1589 restore_flags(flags);
1591 if ((old_termios->c_cflag & CRTSCTS) &&
1592 !(tty->termios->c_cflag & CRTSCTS)) {
1593 tty->hw_stopped = 0;
1594 isicom_start(tty);
1598 /* throttle et all */
1599 static void isicom_throttle(struct tty_struct * tty)
1601 struct isi_port * port = (struct isi_port *) tty->driver_data;
1602 struct isi_board * card = port->card;
1603 unsigned long flags;
1605 if (isicom_paranoia_check(port, tty->device, "isicom_throttle"))
1606 return;
1608 /* tell the card that this port cannot handle any more data for now */
1609 save_flags(flags); cli();
1610 card->port_status &= ~(1 << port->channel);
1611 outw(card->port_status, card->base + 0x02);
1612 restore_flags(flags);
1615 /* unthrottle et all */
1616 static void isicom_unthrottle(struct tty_struct * tty)
1618 struct isi_port * port = (struct isi_port *) tty->driver_data;
1619 struct isi_board * card = port->card;
1620 unsigned long flags;
1622 if (isicom_paranoia_check(port, tty->device, "isicom_unthrottle"))
1623 return;
1625 /* tell the card that this port is ready to accept more data */
1626 save_flags(flags); cli();
1627 card->port_status |= (1 << port->channel);
1628 outw(card->port_status, card->base + 0x02);
1629 restore_flags(flags);
1632 /* stop et all */
1633 static void isicom_stop(struct tty_struct * tty)
1635 struct isi_port * port = (struct isi_port *) tty->driver_data;
1637 if (isicom_paranoia_check(port, tty->device, "isicom_stop"))
1638 return;
1640 /* this tells the transmitter not to consider this port for
1641 data output to the card. */
1642 port->status &= ~ISI_TXOK;
1645 /* start et all */
1646 static void isicom_start(struct tty_struct * tty)
1648 struct isi_port * port = (struct isi_port *) tty->driver_data;
1650 if (isicom_paranoia_check(port, tty->device, "isicom_start"))
1651 return;
1653 /* this tells the transmitter to consider this port for
1654 data output to the card. */
1655 port->status |= ISI_TXOK;
1658 /* hangup et all */
1659 static void do_isicom_hangup(void * data)
1661 struct isi_port * port = (struct isi_port *) data;
1662 struct tty_struct * tty;
1664 tty = port->tty;
1665 if (!tty)
1666 return;
1668 tty_hangup(tty);
1671 static void isicom_hangup(struct tty_struct * tty)
1673 struct isi_port * port = (struct isi_port *) tty->driver_data;
1675 if (isicom_paranoia_check(port, tty->device, "isicom_hangup"))
1676 return;
1678 isicom_shutdown_port(port);
1679 port->count = 0;
1680 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
1681 port->tty = 0;
1682 wake_up_interruptible(&port->open_wait);
1685 /* flush_buffer et all */
1686 static void isicom_flush_buffer(struct tty_struct * tty)
1688 struct isi_port * port = (struct isi_port *) tty->driver_data;
1689 unsigned long flags;
1691 if (isicom_paranoia_check(port, tty->device, "isicom_flush_buffer"))
1692 return;
1694 save_flags(flags); cli();
1695 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1696 restore_flags(flags);
1698 wake_up_interruptible(&tty->write_wait);
1699 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1700 tty->ldisc.write_wakeup)
1701 (tty->ldisc.write_wakeup)(tty);
1705 static int register_ioregion(void)
1707 int count, done=0;
1708 for (count=0; count < BOARD_COUNT; count++ ) {
1709 if (isi_card[count].base) {
1710 if (check_region(isi_card[count].base,16)) {
1711 printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
1712 isi_card[count].base,isi_card[count].base+15,count+1);
1713 isi_card[count].base=0;
1715 else {
1716 request_region(isi_card[count].base,16,ISICOM_NAME);
1717 #ifdef ISICOM_DEBUG
1718 printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x requested for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
1719 #endif
1720 done++;
1724 return done;
1727 static void unregister_ioregion(void)
1729 int count;
1730 for (count=0; count < BOARD_COUNT; count++ )
1731 if (isi_card[count].base) {
1732 release_region(isi_card[count].base,16);
1733 #ifdef ISICOM_DEBUG
1734 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);
1735 #endif
1739 static int register_drivers(void)
1741 int error;
1743 /* tty driver structure initialization */
1744 memset(&isicom_normal, 0, sizeof(struct tty_driver));
1745 isicom_normal.magic = TTY_DRIVER_MAGIC;
1746 isicom_normal.name = "ttyM";
1747 isicom_normal.major = ISICOM_NMAJOR;
1748 isicom_normal.minor_start = 0;
1749 isicom_normal.num = PORT_COUNT;
1750 isicom_normal.type = TTY_DRIVER_TYPE_SERIAL;
1751 isicom_normal.subtype = SERIAL_TYPE_NORMAL;
1752 isicom_normal.init_termios = tty_std_termios;
1753 isicom_normal.init_termios.c_cflag =
1754 B9600 | CS8 | CREAD | HUPCL |CLOCAL;
1755 isicom_normal.flags = TTY_DRIVER_REAL_RAW;
1756 isicom_normal.refcount = &isicom_refcount;
1758 isicom_normal.table = isicom_table;
1759 isicom_normal.termios = isicom_termios;
1760 isicom_normal.termios_locked = isicom_termios_locked;
1762 isicom_normal.open = isicom_open;
1763 isicom_normal.close = isicom_close;
1764 isicom_normal.write = isicom_write;
1765 isicom_normal.put_char = isicom_put_char;
1766 isicom_normal.flush_chars = isicom_flush_chars;
1767 isicom_normal.write_room = isicom_write_room;
1768 isicom_normal.chars_in_buffer = isicom_chars_in_buffer;
1769 isicom_normal.ioctl = isicom_ioctl;
1770 isicom_normal.set_termios = isicom_set_termios;
1771 isicom_normal.throttle = isicom_throttle;
1772 isicom_normal.unthrottle = isicom_unthrottle;
1773 isicom_normal.stop = isicom_stop;
1774 isicom_normal.start = isicom_start;
1775 isicom_normal.hangup = isicom_hangup;
1776 isicom_normal.flush_buffer = isicom_flush_buffer;
1778 /* callout device */
1780 isicom_callout = isicom_normal;
1781 isicom_callout.name = "cum";
1782 isicom_callout.major = ISICOM_CMAJOR;
1783 isicom_callout.subtype = SERIAL_TYPE_CALLOUT;
1785 if ((error=tty_register_driver(&isicom_normal))!=0) {
1786 printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
1787 error);
1788 return error;
1790 if ((error=tty_register_driver(&isicom_callout))!=0) {
1791 tty_unregister_driver(&isicom_normal);
1792 printk(KERN_DEBUG "ISICOM: Couldn't register the callout driver, error=%d\n",
1793 error);
1794 return error;
1796 return 0;
1799 static void unregister_drivers(void)
1801 int error;
1802 if ((error=tty_unregister_driver(&isicom_callout))!=0)
1803 printk(KERN_DEBUG "ISICOM: couldn't unregister callout driver error=%d.\n",error);
1804 if (tty_unregister_driver(&isicom_normal))
1805 printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
1808 static int register_isr(void)
1810 int count, done=0, card;
1811 int flag;
1812 unsigned char request;
1813 for (count=0; count < BOARD_COUNT; count++ ) {
1814 if (isi_card[count].base) {
1816 * verify if the required irq has already been requested for
1817 * another ISI Card, if so we already have it, else request it
1819 request = YES;
1820 for(card = 0; card < count; card++)
1821 if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) {
1822 request = NO;
1823 if ((isi_card[count].isa == NO) && (isi_card[card].isa == NO))
1824 break;
1826 * ISA cards cannot share interrupts with other
1827 * PCI or ISA devices hence disable this card.
1829 release_region(isi_card[count].base,16);
1830 isi_card[count].base = 0;
1831 break;
1833 flag=0;
1834 if(isi_card[count].isa == NO)
1835 flag |= SA_SHIRQ;
1837 if (request == YES) {
1838 if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT|flag, ISICOM_NAME, NULL)) {
1839 printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n",
1840 isi_card[count].irq, count+1);
1841 release_region(isi_card[count].base,16);
1842 isi_card[count].base=0;
1844 else {
1845 printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n",
1846 count+1, isi_card[count].base, isi_card[count].irq);
1848 irq_to_board[isi_card[count].irq]=&isi_card[count];
1849 done++;
1854 return done;
1857 static void unregister_isr(void)
1859 int count, card;
1860 unsigned char freeirq;
1861 for (count=0; count < BOARD_COUNT; count++ ) {
1862 if (isi_card[count].base) {
1863 freeirq = YES;
1864 for(card = 0; card < count; card++)
1865 if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) {
1866 freeirq = NO;
1867 break;
1869 if (freeirq == YES) {
1870 free_irq(isi_card[count].irq, NULL);
1871 #ifdef ISICOM_DEBUG
1872 printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1);
1873 #endif
1879 static int isicom_init(void)
1881 int card, channel, base;
1882 struct isi_port * port;
1883 unsigned long page;
1885 if (!tmp_buf) {
1886 page = get_free_page(GFP_KERNEL);
1887 if (!page) {
1888 #ifdef ISICOM_DEBUG
1889 printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
1890 #else
1891 printk(KERN_ERR "ISICOM: Not enough memory...\n");
1892 #endif
1893 return 0;
1895 tmp_buf = (unsigned char *) page;
1898 if (!register_ioregion())
1900 printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");
1901 free_page((unsigned long)tmp_buf);
1902 return 0;
1904 if (register_drivers())
1906 unregister_ioregion();
1907 free_page((unsigned long)tmp_buf);
1908 return 0;
1910 if (!register_isr())
1912 unregister_drivers();
1913 /* ioports already uregistered in register_isr */
1914 free_page((unsigned long)tmp_buf);
1915 return 0;
1918 /* initialize bottom half */
1919 init_bh(ISICOM_BH, do_isicom_bh);
1922 memset(isi_ports, 0, sizeof(isi_ports));
1923 for (card = 0; card < BOARD_COUNT; card++) {
1924 port = &isi_ports[card * 16];
1925 isi_card[card].ports = port;
1926 base = isi_card[card].base;
1927 for (channel = 0; channel < 16; channel++, port++) {
1928 port->magic = ISICOM_MAGIC;
1929 port->card = &isi_card[card];
1930 port->channel = channel;
1931 port->normal_termios = isicom_normal.init_termios;
1932 port->callout_termios = isicom_callout.init_termios;
1933 port->close_delay = 50 * HZ/100;
1934 port->closing_wait = 3000 * HZ/100;
1935 port->hangup_tq.routine = do_isicom_hangup;
1936 port->hangup_tq.data = port;
1937 port->bh_tqueue.routine = isicom_bottomhalf;
1938 port->bh_tqueue.data = port;
1939 port->status = 0;
1940 init_waitqueue_head(&port->open_wait);
1941 init_waitqueue_head(&port->close_wait);
1942 /* . . . */
1946 return 1;
1950 * Insmod can set static symbols so keep these static
1953 static int io[4];
1954 static int irq[4];
1956 MODULE_AUTHOR("MultiTech");
1957 MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
1958 MODULE_PARM(io, "1-4i");
1959 MODULE_PARM_DESC(io, "I/O ports for the cards");
1960 MODULE_PARM(irq, "1-4i");
1961 MODULE_PARM_DESC(irq, "Interrupts for the cards");
1963 int init_module(void)
1965 struct pci_dev *dev = NULL;
1966 int retval, card, idx, count;
1967 unsigned char pciirq;
1968 unsigned int ioaddr;
1970 card = 0;
1971 for(idx=0; idx < BOARD_COUNT; idx++) {
1972 if (io[idx]) {
1973 isi_card[idx].base=io[idx];
1974 isi_card[idx].irq=irq[idx];
1975 isi_card[idx].isa=YES;
1976 card++;
1978 else {
1979 isi_card[idx].base = 0;
1980 isi_card[idx].irq = 0;
1984 for (idx=0 ;idx < card; idx++) {
1985 if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)||
1986 (isi_card[idx].irq==4)||(isi_card[idx].irq==5)||
1987 (isi_card[idx].irq==7)||(isi_card[idx].irq==10)||
1988 (isi_card[idx].irq==11)||(isi_card[idx].irq==12)||
1989 (isi_card[idx].irq==15))) {
1991 if (isi_card[idx].base) {
1992 printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
1993 isi_card[idx].irq, idx+1);
1994 isi_card[idx].base=0;
1995 card--;
2000 if (pci_present() && (card < BOARD_COUNT)) {
2001 for (idx=0; idx < DEVID_COUNT; idx++) {
2002 dev = NULL;
2003 for (;;){
2004 if (!(dev = pci_find_device(VENDOR_ID, device_id[idx], dev)))
2005 break;
2006 if (card >= BOARD_COUNT)
2007 break;
2009 /* found a PCI ISI card! */
2010 ioaddr = dev->resource[3].start; /* i.e at offset 0x1c in the
2011 * PCI configuration register
2012 * space.
2014 ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
2015 pciirq = dev->irq;
2016 printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", device_id[idx]);
2018 * allot the first empty slot in the array
2020 for (count=0; count < BOARD_COUNT; count++) {
2021 if (isi_card[count].base == 0) {
2022 isi_card[count].base = ioaddr;
2023 isi_card[count].irq = pciirq;
2024 isi_card[count].isa = NO;
2025 card++;
2026 break;
2030 if (card >= BOARD_COUNT) break;
2034 if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
2035 printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n");
2036 return -EIO;
2038 retval=misc_register(&isiloader_device);
2039 if (retval<0) {
2040 printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
2041 return -EIO;
2044 if (!isicom_init()) {
2045 if (misc_deregister(&isiloader_device))
2046 printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
2047 return -EIO;
2050 init_timer(&tx);
2051 tx.expires = jiffies + 1;
2052 tx.data = 0;
2053 tx.function = isicom_tx;
2054 re_schedule = 1;
2055 add_timer(&tx);
2057 return 0;
2060 void cleanup_module(void)
2062 re_schedule = 0;
2063 current->state = TASK_INTERRUPTIBLE;
2064 schedule_timeout(HZ);
2065 disable_bh(ISICOM_BH);
2067 #ifdef ISICOM_DEBUG
2068 printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);
2069 #endif
2071 #ifdef ISICOM_DEBUG
2072 printk("ISICOM: uregistering isr ...\n");
2073 #endif
2074 unregister_isr();
2076 #ifdef ISICOM_DEBUG
2077 printk("ISICOM: unregistering drivers ...\n");
2078 #endif
2079 unregister_drivers();
2081 #ifdef ISICOM_DEBUG
2082 printk("ISICOM: unregistering ioregion ...\n");
2083 #endif
2084 unregister_ioregion();
2086 #ifdef ISICOM_DEBUG
2087 printk("ISICOM: freeing tmp_buf ...\n");
2088 #endif
2089 free_page((unsigned long)tmp_buf);
2091 #ifdef ISICOM_DEBUG
2092 printk("ISICOM: unregistering firmware loader ...\n");
2093 #endif
2094 if (misc_deregister(&isiloader_device))
2095 printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");