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