File: /usr/src/linux/drivers/char/rocket.c

1     /*
2      * Rocketport device driver for Linux
3      *
4      * Written by Theodore Ts'o, 1995, 1996, 1997.
5      * 
6      * Copyright (C) 1995, 1996, 1997 by Comtrol, Inc.
7      * 
8      * This program is free software; you can redistribute it and/or
9      * modify it under the terms of the GNU General Public License as
10      * published by the Free Software Foundation; either version 2 of the
11      * License, or (at your option) any later version.
12      * 
13      * This program is distributed in the hope that it will be useful, but
14      * WITHOUT ANY WARRANTY; without even the implied warranty of
15      * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16      * General Public License for more details.
17      * 
18      * You should have received a copy of the GNU General Public License
19      * along with this program; if not, write to the Free Software
20      * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21      */
22     
23     /*
24      * Minor number schema:
25      *
26      * +-------------------------------+
27      * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
28      * +---+-------+-------+-----------+
29      * | C | Board |  AIOP | Port #    |
30      * +---+-------+-------+-----------+
31      *
32      * C=0 implements normal POSIX tty.
33      * C=1 is reserved for the callout device.
34      * 
35      * Normally, the user won't have to worry about the AIOP; as far as
36      * the user is concerned, the lower 5 bits of the minor number address
37      * the ports on a particular board (from 0 up to 32).
38      */
39     
40     /* Kernel includes */
41     
42     #include <linux/config.h>
43     #include <linux/version.h>
44     
45     #ifdef CONFIG_PCI
46     #define ENABLE_PCI
47     #endif
48     
49     #include <linux/module.h>
50     #include <linux/errno.h>
51     #include <linux/major.h>
52     #include <linux/kernel.h>
53     #include <linux/signal.h>
54     #include <linux/slab.h>
55     #include <linux/mm.h>
56     
57     #include <linux/sched.h>
58     #include <linux/timer.h>
59     #include <linux/interrupt.h>
60     #include <linux/tty.h>
61     #include <linux/tty_flip.h>
62     #include <linux/string.h>
63     #include <linux/fcntl.h>
64     #include <linux/ptrace.h>
65     #include <linux/ioport.h>
66     #ifdef ENABLE_PCI
67     #include <linux/pci.h>
68     #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
69     #include <linux/bios32.h>
70     #endif
71     #endif
72     #if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
73     #include <linux/init.h>
74     #endif
75     	
76     #include "rocket_int.h"
77     #ifdef LOCAL_ROCKET_H
78     #include "rocket.h"
79     #include "version.h"
80     #else
81     #include <linux/rocket.h>
82     #define ROCKET_VERSION "1.14c"
83     #define ROCKET_DATE "24-Aug-98"
84     #endif /* LOCAL_ROCKET_H */
85     
86     #define ROCKET_PARANOIA_CHECK
87     #define ROCKET_SOFT_FLOW
88     
89     #undef ROCKET_DEBUG_OPEN
90     #undef ROCKET_DEBUG_INTR
91     #undef ROCKET_DEBUG_WRITE
92     #undef ROCKET_DEBUG_FLOW
93     #undef ROCKET_DEBUG_THROTTLE
94     #undef ROCKET_DEBUG_WAIT_UNTIL_SENT
95     #undef ROCKET_DEBUG_RECEIVE
96     #undef ROCKET_DEBUG_HANGUP
97     	
98     
99     /*   CAUTION!!!!!  The TIME_STAT Function relies on the Pentium 64 bit
100      *    register.  For various reasons related to 1.2.13, the test for this
101      *    register is omitted from this driver.  If you are going to enable
102      *    this option, make sure you are running a Pentium CPU and that a
103      *    cat of /proc/cpuinfo shows ability TS Counters as Yes.  Warning part
104      *    done, don't cry to me if you enable this options and things won't
105      *    work.  If it gives you any problems, then disable the option.  The code
106      *    in this function is pretty straight forward, if it breaks on your
107      *    CPU, there is probably something funny about your CPU.
108      */
109     
110     #undef TIME_STAT	/* For performing timing statistics on driver. */
111     			/* Produces printks, one every TIME_COUNTER loops, eats */
112     			/* some of your CPU time.  Good for testing or */
113     			/* other checking, otherwise, leave it undefed */
114     			/* Doug Ledford */
115     #define TIME_STAT_CPU 100      /* This needs to be set to your processor speed */
116                                    /* For example, 100Mhz CPU, set this to 100 */
117     #define TIME_COUNTER 180000    /* This is how many iterations to run before */
118     			      /* performing the printk statements.   */
119     			      /* 6000 = 1 minute, 360000 = 1 hour, etc. */
120     			      /* Since time_stat is long long, this */
121     			      /* Can be really high if you want :)  */
122     #undef TIME_STAT_VERBOSE   /* Undef this if you want a terse log message. */
123     
124     #define _INLINE_ inline
125     
126     static struct r_port *rp_table[MAX_RP_PORTS];
127     static struct tty_struct *rocket_table[MAX_RP_PORTS];
128     static unsigned int xmit_flags[NUM_BOARDS];
129     static struct termios *rocket_termios[MAX_RP_PORTS];
130     static struct termios *rocket_termios_locked[MAX_RP_PORTS];
131     static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
132     static void rp_flush_buffer(struct tty_struct *tty);
133     
134     static struct tty_driver rocket_driver, callout_driver;
135     static int rocket_refcount;
136     
137     static int rp_num_ports_open;
138     
139     static struct timer_list rocket_timer;
140     
141     unsigned long board1;
142     unsigned long board2;
143     unsigned long board3;
144     unsigned long board4;
145     unsigned long controller;
146     unsigned long support_low_speed;
147     int rp_baud_base = 460800;
148     static unsigned long rcktpt_io_addr[NUM_BOARDS];
149     static int max_board;
150     #ifdef TIME_STAT
151     static unsigned long long time_stat;
152     static unsigned long time_stat_short;
153     static unsigned long time_stat_long;
154     static unsigned long time_counter;
155     #endif
156     
157     #if ((LINUX_VERSION_CODE > 0x020111) && defined(MODULE))
158     MODULE_AUTHOR("Theodore Ts'o");
159     MODULE_DESCRIPTION("Comtrol Rocketport driver");
160     MODULE_LICENSE("GPL");
161     MODULE_PARM(board1,     "i");
162     MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
163     MODULE_PARM(board2,     "i");
164     MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
165     MODULE_PARM(board3,     "i");
166     MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
167     MODULE_PARM(board4,     "i");
168     MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
169     MODULE_PARM(controller, "i");
170     MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
171     MODULE_PARM(support_low_speed, "i");
172     MODULE_PARM_DESC(support_low_speed, "0 means support 50 baud, 1 means support 460400 baud");	
173     #endif
174     
175     #if (LINUX_VERSION_CODE < 131336)
176     int copy_from_user(void *to, const void *from_user, unsigned long len)
177     {
178     	int	error;
179     
180     	error = verify_area(VERIFY_READ, from_user, len);
181     	if (error)
182     		return len;
183     	memcpy_fromfs(to, from_user, len);
184     	return 0;
185     }
186     
187     int copy_to_user(void *to_user, const void *from, unsigned long len)
188     {
189     	int	error;
190     	
191     	error = verify_area(VERIFY_WRITE, to_user, len);
192     	if (error)
193     		return len;
194     	memcpy_tofs(to_user, from, len);
195     	return 0;
196     }
197     
198     static inline int signal_pending(struct task_struct *p)
199     {
200     	return (p->signal & ~p->blocked) != 0;
201     }
202     
203     #else
204     #include <asm/uaccess.h>
205     #endif
206     
207     /*
208      * tmp_buf is used as a temporary buffer by rp_write.  We need to
209      * lock it in case the memcpy_fromfs blocks while swapping in a page,
210      * and some other program tries to do a serial write at the same time.
211      * Since the lock will only come under contention when the system is
212      * swapping and available memory is low, it makes sense to share one
213      * buffer across all the serial ports, since it significantly saves
214      * memory if large numbers of serial ports are open.
215      */
216     static unsigned char *tmp_buf = 0;
217     static DECLARE_MUTEX(tmp_buf_sem);
218     
219     static void rp_start(struct tty_struct *tty);
220     
221     static inline int rocket_paranoia_check(struct r_port *info,
222     					kdev_t device, const char *routine)
223     {
224     #ifdef ROCKET_PARANOIA_CHECK
225     	static const char *badmagic =
226     		"Warning: bad magic number for rocketport struct (%d, %d) in %s\n";
227     	if (!info)
228     		return 1;
229     	if (info->magic != RPORT_MAGIC) {
230     		printk(badmagic, MAJOR(device), MINOR(device), routine);
231     		return 1;
232     	}
233     #endif
234     	return 0;
235     }
236     
237     /*
238      * Here begins the interrupt/polling routine for the Rocketport!
239      */
240     static _INLINE_ void rp_do_receive(struct r_port *info, struct tty_struct *tty,
241     				   CHANNEL_t *cp, unsigned int ChanStatus)
242     {
243     	unsigned int CharNStat;
244     	int ToRecv, wRecv, space, count;
245     	unsigned char	*cbuf;
246     	char		*fbuf;
247     	
248     	ToRecv= sGetRxCnt(cp);
249     	space = 2*TTY_FLIPBUF_SIZE;
250     	cbuf = tty->flip.char_buf;
251     	fbuf = tty->flip.flag_buf;
252     	count = 0;
253     #ifdef ROCKET_DEBUG_INTR
254     	printk("rp_do_receive(%d, %d)...", ToRecv, space);
255     #endif
256     	if (ToRecv == 0 || (space <= 0))
257     		return;
258     	
259     	/*
260     	 * determine how many we can actually read in.  If we can't
261     	 * read any in then we have a software overrun condition.
262     	 */
263     	if (ToRecv > space)
264     		ToRecv = space;
265     	
266     	/*
267     	 * if status indicates there are errored characters in the
268     	 * FIFO, then enter status mode (a word in FIFO holds
269     	 * character and status).
270     	 */
271     	if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
272     		if (!(ChanStatus & STATMODE)) {
273     #ifdef ROCKET_DEBUG_RECEIVE
274     			printk("Entering STATMODE...");
275     #endif
276     			ChanStatus |= STATMODE;
277     			sEnRxStatusMode(cp);
278     		}
279     	}
280     
281     	/* 
282     	 * if we previously entered status mode, then read down the
283     	 * FIFO one word at a time, pulling apart the character and
284     	 * the status.  Update error counters depending on status
285     	 */
286     	if (ChanStatus & STATMODE) {
287     #ifdef ROCKET_DEBUG_RECEIVE
288     		printk("Ignore %x, read %x...", info->ignore_status_mask,
289     		       info->read_status_mask);
290     #endif
291     		while (ToRecv) {
292     			CharNStat= sInW(sGetTxRxDataIO(cp));
293     
294     #ifdef ROCKET_DEBUG_RECEIVE
295     			printk("%x...", CharNStat);
296     #endif
297     
298     			if (CharNStat & STMBREAKH)
299     				CharNStat &= ~(STMFRAMEH | STMPARITYH);
300     			if (CharNStat & info->ignore_status_mask) {
301     				ToRecv--;
302     				continue;
303     			}
304     			CharNStat &= info->read_status_mask;
305     			if (CharNStat & STMBREAKH) {
306     				*fbuf++ = TTY_BREAK;
307     #if 0
308     				if (info->flags & ROCKET_SAK)
309     					do_SAK(tty);
310     #endif
311     			} else if (CharNStat & STMPARITYH)
312     				*fbuf++ = TTY_PARITY;
313     			else if (CharNStat & STMFRAMEH)
314     				*fbuf++ = TTY_FRAME;
315     			else if (CharNStat & STMRCVROVRH)
316     				*fbuf++ =TTY_OVERRUN;
317     			else
318     				*fbuf++ = 0;
319     			*cbuf++ = CharNStat & 0xff;
320     			count++;
321     			ToRecv--;
322     		}
323     
324     		/*
325     		 * after we've emptied the FIFO in status mode, turn
326     		 * status mode back off
327     		 */
328     		if (sGetRxCnt(cp) == 0) {
329     #ifdef ROCKET_DEBUG_RECEIVE
330     			printk("Status mode off.\n");
331     #endif
332     			sDisRxStatusMode(cp);
333     		}
334     	} else {
335     		/*
336     		 * we aren't in status mode, so read down the FIFO two
337     		 * characters at time by doing repeated word IO
338     		 * transfer.
339     		 */
340     		wRecv= ToRecv >> 1;
341     		if (wRecv)
342     			sInStrW(sGetTxRxDataIO(cp), cbuf,
343     				wRecv);
344     		if (ToRecv & 1)
345     			cbuf[ToRecv-1] = sInB(sGetTxRxDataIO(cp));
346     		memset(fbuf, 0, ToRecv);
347     		cbuf += ToRecv;
348     		fbuf += ToRecv;
349     		count += ToRecv;
350     	}
351     	tty->ldisc.receive_buf(tty, tty->flip.char_buf,
352     			       tty->flip.flag_buf, count);
353     }
354     
355     /*
356      * This routine is called when a transmit interrupt is found.  It's
357      * responsible for pushing data found in the transmit buffer out to
358      * the serial card.
359      */
360     static _INLINE_ void rp_do_transmit(struct r_port *info)
361     {
362     	int	c;
363     	CHANNEL_t *cp = &info->channel;
364     	struct tty_struct *tty;
365     	
366     #ifdef ROCKET_DEBUG_INTR
367     	printk("rp_do_transmit ");
368     #endif
369     	if (!info)
370     		return;
371     	if (!info->tty) {
372     		printk("rp: WARNING rp_do_transmit called with info->tty==NULL\n");
373     		xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
374     		return;
375     	}
376     	tty = info->tty;
377     	info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
378     	while (1) {
379     		if (tty->stopped || tty->hw_stopped)
380     			break;
381     		c = MIN(info->xmit_fifo_room,
382     			MIN(info->xmit_cnt,
383     			    XMIT_BUF_SIZE - info->xmit_tail));
384     		if (c <= 0 || info->xmit_fifo_room <= 0)
385     			break;
386     		sOutStrW(sGetTxRxDataIO(cp),
387     			 info->xmit_buf + info->xmit_tail, c/2);
388     		if (c & 1)
389     			sOutB(sGetTxRxDataIO(cp),
390     			      info->xmit_buf[info->xmit_tail + c -
391     					     1]);
392     		info->xmit_tail += c;
393     		info->xmit_tail &= XMIT_BUF_SIZE-1;
394     		info->xmit_cnt -= c;
395     		info->xmit_fifo_room -= c;
396     #ifdef ROCKET_DEBUG_INTR
397     		printk("tx %d chars...", c);
398     #endif
399     	}
400     	if (info->xmit_cnt == 0)
401     		xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
402     	if (info->xmit_cnt < WAKEUP_CHARS) {
403     		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
404     		    tty->ldisc.write_wakeup)
405     			(tty->ldisc.write_wakeup)(tty);
406     		wake_up_interruptible(&tty->write_wait);
407     	}
408     #ifdef ROCKET_DEBUG_INTR
409     	printk("(%d,%d,%d,%d)...", info->xmit_cnt, info->xmit_head,
410     	       info->xmit_tail, info->xmit_fifo_room);
411     #endif
412     }
413     
414     /*
415      * This function is called for each port which has signalled an
416      * interrupt.  It checks what interrupts are pending and services
417      * them. 
418      */
419     static _INLINE_ void rp_handle_port(struct r_port *info)
420     {
421     	CHANNEL_t *cp;
422     	struct tty_struct *tty;
423     	unsigned int IntMask, ChanStatus;
424     
425     	if (!info)
426     		return;
427     	if ( (info->flags & ROCKET_INITIALIZED) == 0 ) {
428     		printk("rp: WARNING: rp_handle_port called with info->flags & NOT_INIT\n");
429     		return;
430     	}
431     	if (!info->tty) {
432     		printk("rp: WARNING: rp_handle_port called with info->tty==NULL\n");
433     		return;
434     	}
435     	cp = &info->channel;
436     	tty = info->tty;
437     
438     	IntMask = sGetChanIntID(cp) & info->intmask;
439     #ifdef ROCKET_DEBUG_INTR
440     	printk("rp_interrupt %02x...", IntMask);
441     #endif
442     	ChanStatus= sGetChanStatus(cp);
443     	if (IntMask & RXF_TRIG) {	/* Rx FIFO trigger level */
444     		rp_do_receive(info, tty, cp, ChanStatus);
445     	}
446     #if 0
447     	if (IntMask & SRC_INT) {	/* Special receive condition */
448     	}
449     #endif
450     	if (IntMask & DELTA_CD) {	/* CD change  */
451     #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || \
452          defined(ROCKET_DEBUG_HANGUP))
453     		printk("ttyR%d CD now %s...", info->line,
454     		       (ChanStatus & CD_ACT) ? "on" : "off");
455     #endif
456     		if (!(ChanStatus & CD_ACT) &&
457     		    info->cd_status &&
458     		    !((info->flags & ROCKET_CALLOUT_ACTIVE) &&
459     		      (info->flags & ROCKET_CALLOUT_NOHUP))) {
460     #ifdef ROCKET_DEBUG_HANGUP
461     			printk("CD drop, calling hangup.\n");
462     #endif
463     			tty_hangup(tty);
464     		}
465     		info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
466     		wake_up_interruptible(&info->open_wait);
467     	}
468     #ifdef ROCKET_DEBUG_INTR
469     	if (IntMask & DELTA_CTS) {	/* CTS change */
470     		printk("CTS change...\n");
471     	}
472     	if (IntMask & DELTA_DSR) {	/* DSR change */
473     		printk("DSR change...\n");
474     	}
475     #endif
476     }
477     
478     /*
479      * The top level polling routine.
480      */
481     static void rp_do_poll(unsigned long dummy)
482     {
483     	CONTROLLER_t *ctlp;
484     	int ctrl, aiop, ch, line;
485     	unsigned int xmitmask;
486     	unsigned char CtlMask, AiopMask;
487     
488     #ifdef TIME_STAT
489     	unsigned long loop_time;
490     	unsigned long long time_stat_tmp=0, time_stat_tmp2=0;
491     
492     	rdtscll(time_stat_tmp);
493     #endif /* TIME_STAT */
494     
495     	for (ctrl=0; ctrl < max_board; ctrl++) {
496     		if (rcktpt_io_addr[ctrl] <= 0)
497     			continue;
498     		ctlp= sCtlNumToCtlPtr(ctrl);
499     
500     #ifdef ENABLE_PCI
501     		if(ctlp->BusType == isPCI)
502     			CtlMask= sPCIGetControllerIntStatus(ctlp);
503     		else
504     #endif
505     			CtlMask= sGetControllerIntStatus(ctlp);
506     		for (aiop=0; CtlMask; CtlMask >>= 1, aiop++) {
507     			if (CtlMask & 1) {
508     				AiopMask= sGetAiopIntStatus(ctlp, aiop);
509     				for (ch=0; AiopMask; AiopMask >>= 1, ch++) {
510     					if (AiopMask & 1) {
511     						line = (ctrl << 5) | 
512     							(aiop << 3) | ch;
513     						rp_handle_port(rp_table[line]);
514     					}
515     				}
516     			}
517     		}
518     		xmitmask = xmit_flags[ctrl];
519     		for (line = ctrl << 5; xmitmask; xmitmask >>= 1, line++) {
520     			if (xmitmask & 1)
521     				rp_do_transmit(rp_table[line]);
522     		}
523     	}
524     
525     	/*
526     	 * Reset the timer so we get called at the next clock tick.
527     	 */
528     	if (rp_num_ports_open) {
529     		mod_timer(&rocket_timer, jiffies + 1);
530     	}
531     #ifdef TIME_STAT
532     	rdtscll(time_stat_tmp2);
533     	time_stat_tmp2 -= time_stat_tmp;
534     	time_stat += time_stat_tmp2;
535     	if (time_counter == 0) 
536     		time_stat_short = time_stat_long = time_stat_tmp2;
537     	else {
538     		if ( time_stat_tmp2 < time_stat_short )
539     			time_stat_short = time_stat_tmp2;
540     		else if ( time_stat_tmp2 > time_stat_long )
541     			time_stat_long = time_stat_tmp2;
542     	}
543     	if ( ++time_counter == TIME_COUNTER ) {
544     		loop_time = (unsigned long) ( ((unsigned long)(time_stat >> 32) * ( (unsigned long)(0xffffffff)/(TIME_STAT_CPU * TIME_COUNTER) ) ) + ((unsigned long)time_stat/(TIME_STAT_CPU*TIME_COUNTER)));
545     #ifdef TIME_STAT_VERBOSE
546     		printk("rp_do_poll: Interrupt Timings\n");
547     		printk("     %5ld iterations; %ld us min,\n",
548     		       (long)TIME_COUNTER, (time_stat_short/TIME_STAT_CPU));
549     		printk("     %5ld us max, %ld us average per iteration.\n",
550     		       (time_stat_long/TIME_STAT_CPU), loop_time);
551     		printk("We want to use < 5,000 us for an iteration.\n");
552     #else /* TIME_STAT_VERBOSE */
553     		printk("rp: %ld loops: %ld min, %ld max, %ld us/loop.\n",
554     		       (long)TIME_COUNTER, (time_stat_short/TIME_STAT_CPU),
555     		       (time_stat_long/TIME_STAT_CPU), loop_time);
556     #endif /* TIME_STAT_VERBOSE */
557     		time_counter = time_stat = 0;
558     		time_stat_short = time_stat_long = 0;
559     	}
560     #endif /* TIME_STAT */
561     }
562     /*
563      * Here ends the interrupt/polling routine.
564      */
565     
566     
567     /*
568      * This function initializes the r_port structure, as well as enabling
569      * the port on the RocketPort board.
570      */
571     static void init_r_port(int board, int aiop, int chan)
572     {
573     	struct r_port *info;
574     	int line;
575     	CONTROLLER_T *ctlp;
576     	CHANNEL_t	*cp;
577     	
578     	line = (board << 5) | (aiop << 3) | chan;
579     
580     	ctlp= sCtlNumToCtlPtr(board);
581     
582     	info = kmalloc(sizeof(struct r_port), GFP_KERNEL);
583     	if (!info) {
584     		printk("Couldn't allocate info struct for line #%d\n", line);
585     		return;
586     	}
587     	memset(info, 0, sizeof(struct r_port));
588     	
589     	info->magic = RPORT_MAGIC;
590     	info->line = line;
591     	info->ctlp = ctlp;
592     	info->board = board;
593     	info->aiop = aiop;
594     	info->chan = chan;
595     	info->closing_wait = 3000;
596     	info->close_delay = 50;
597     	info->callout_termios =callout_driver.init_termios;
598     	info->normal_termios = rocket_driver.init_termios;
599     	init_waitqueue_head(&info->open_wait);
600     	init_waitqueue_head(&info->close_wait);
601     
602     	info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD |
603     		DELTA_CTS | DELTA_DSR;
604     	if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
605     		printk("Rocketport sInitChan(%d, %d, %d) failed!\n",
606     		       board, aiop, chan);
607     		kfree(info);
608     		return;
609     	}
610     	cp = &info->channel;
611     	rp_table[line] = info;
612     }
613     
614     #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
615     static int baud_table[] = {
616     	0, 50, 75, 110, 134, 150, 200, 300,
617     	600, 1200, 1800, 2400, 4800, 9600, 19200,
618     	38400, 57600, 115200, 230400, 460800, 0 };
619     #endif
620     
621     /*
622      * This routine configures a rocketport port so according to its
623      * termio settings.
624      */
625     static void configure_r_port(struct r_port *info)
626     {
627     	unsigned cflag;
628     	unsigned long 	flags;
629     	int	bits, baud;
630     #if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
631     	int i;
632     #endif
633     	CHANNEL_t	*cp;
634     	
635     	if (!info->tty || !info->tty->termios)
636     		return;
637     	cp = &info->channel;
638     	cflag = info->tty->termios->c_cflag;
639     
640     	/* Byte size and parity */
641     	if ((cflag & CSIZE) == CS8) {
642     		sSetData8(cp);
643     		bits = 10;
644     	} else {
645     		sSetData7(cp);
646     		bits = 9;
647     	}
648             if (cflag & CSTOPB) {
649     		sSetStop2(cp);
650     		bits++;
651     	} else {
652     		sSetStop1(cp);
653     	}
654     	
655     	if (cflag & PARENB) {
656     		sEnParity(cp);
657     		bits++;
658     		if (cflag & PARODD) {
659     			sSetOddParity(cp);
660     		} else {
661     			sSetEvenParity(cp);
662     		}
663     	} else {
664     		sDisParity(cp);
665     	}
666     	
667     	/* baud rate */
668     #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
669     	i = cflag & CBAUD;
670     	if (i & CBAUDEX) {
671     		i &= ~CBAUDEX;
672     		if (i < 1 || i > 4) 
673     			info->tty->termios->c_cflag &= ~CBAUDEX;
674     		else
675     			i += 15;
676     	}
677     	if (i == 15) {
678     		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
679     			i += 1;
680     		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
681     			i += 2;
682     		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
683     			i += 3;
684     		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
685     			i += 4;
686     	}
687     	baud = baud_table[i] ? baud_table[i] : 9600;
688     #else
689     	baud = tty_get_baud_rate(info->tty);
690     	if (!baud)
691     		baud = 9600;
692     #endif
693     	info->cps = baud / bits;
694     	sSetBaud(cp, (rp_baud_base/baud) - 1);
695     	
696     	if (cflag & CRTSCTS) {
697     		info->intmask |= DELTA_CTS;
698     		sEnCTSFlowCtl(cp);
699     	} else {
700     		info->intmask &= ~DELTA_CTS;
701     		sDisCTSFlowCtl(cp);
702     	}
703     	sSetRTS(&info->channel);
704     	if (cflag & CLOCAL)
705     		info->intmask &= ~DELTA_CD;
706     	else {
707     		save_flags(flags); cli();
708     		if (sGetChanStatus(cp) & CD_ACT)
709     			info->cd_status = 1;
710     		else
711     			info->cd_status = 0;
712     		info->intmask |= DELTA_CD;
713     		restore_flags(flags);
714     	}
715     
716     	/*
717     	 * Handle software flow control in the board
718     	 */
719     #ifdef ROCKET_SOFT_FLOW
720     	if (I_IXON(info->tty)) {
721     		sEnTxSoftFlowCtl(cp);
722     		if (I_IXANY(info->tty)) {
723     			sEnIXANY(cp);
724     		} else {
725     			sDisIXANY(cp);
726     		}
727     		sSetTxXONChar(cp, START_CHAR(info->tty));
728     		sSetTxXOFFChar(cp, STOP_CHAR(info->tty));
729     	} else {
730     		sDisTxSoftFlowCtl(cp);
731     		sDisIXANY(cp);
732     		sClrTxXOFF(cp);
733     	}
734     #endif
735     	
736     	/*
737     	 * Set up ignore/read mask words
738     	 */
739     	info->read_status_mask = STMRCVROVRH | 0xFF;
740     	if (I_INPCK(info->tty))
741     		info->read_status_mask |= STMFRAMEH | STMPARITYH;
742     	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
743     		info->read_status_mask |= STMBREAKH;
744     
745     	/*
746     	 * Characters to ignore
747     	 */
748     	info->ignore_status_mask = 0;
749     	if (I_IGNPAR(info->tty))
750     		info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
751     	if (I_IGNBRK(info->tty)) {
752     		info->ignore_status_mask |= STMBREAKH;
753     		/*
754     		 * If we're ignoring parity and break indicators,
755     		 * ignore overruns too.  (For real raw support).
756     		 */
757     		if (I_IGNPAR(info->tty))
758     			info->ignore_status_mask |= STMRCVROVRH;
759     	}
760     }
761     
762     static int block_til_ready(struct tty_struct *tty, struct file * filp,
763     			   struct r_port *info)
764     {
765     	DECLARE_WAITQUEUE(wait, current);
766     	int		retval;
767     	int		do_clocal = 0, extra_count = 0;
768     	unsigned long	flags;
769     
770     	/*
771     	 * If the device is in the middle of being closed, then block
772     	 * until it's done, and then try again.
773     	 */
774     	if (tty_hung_up_p(filp))
775     		return ((info->flags & ROCKET_HUP_NOTIFY) ? 
776     			-EAGAIN : -ERESTARTSYS);
777     	if (info->flags & ROCKET_CLOSING) {
778     		interruptible_sleep_on(&info->close_wait);
779     		return ((info->flags & ROCKET_HUP_NOTIFY) ? 
780     			-EAGAIN : -ERESTARTSYS);
781     	}
782     
783     	/*
784     	 * If this is a callout device, then just make sure the normal
785     	 * device isn't being used.
786     	 */
787     	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
788     		if (info->flags & ROCKET_NORMAL_ACTIVE)
789     			return -EBUSY;
790     		if ((info->flags & ROCKET_CALLOUT_ACTIVE) &&
791     		    (info->flags & ROCKET_SESSION_LOCKOUT) &&
792     		    (info->session != current->session))
793     		    return -EBUSY;
794     		if ((info->flags & ROCKET_CALLOUT_ACTIVE) &&
795     		    (info->flags & ROCKET_PGRP_LOCKOUT) &&
796     		    (info->pgrp != current->pgrp))
797     		    return -EBUSY;
798     		info->flags |= ROCKET_CALLOUT_ACTIVE;
799     		return 0;
800     	}
801     	
802     	/*
803     	 * If non-blocking mode is set, or the port is not enabled,
804     	 * then make the check up front and then exit.
805     	 */
806     	if ((filp->f_flags & O_NONBLOCK) ||
807     	    (tty->flags & (1 << TTY_IO_ERROR))) {
808     		if (info->flags & ROCKET_CALLOUT_ACTIVE)
809     			return -EBUSY;
810     		info->flags |= ROCKET_NORMAL_ACTIVE;
811     		return 0;
812     	}
813     
814     	if (info->flags & ROCKET_CALLOUT_ACTIVE) {
815     		if (info->normal_termios.c_cflag & CLOCAL)
816     			do_clocal = 1;
817     	} else {
818     		if (tty->termios->c_cflag & CLOCAL)
819     			do_clocal = 1;
820     	}
821     	
822     	/*
823     	 * Block waiting for the carrier detect and the line to become
824     	 * free (i.e., not in use by the callout).  While we are in
825     	 * this loop, info->count is dropped by one, so that
826     	 * rp_close() knows when to free things.  We restore it upon
827     	 * exit, either normal or abnormal.
828     	 */
829     	retval = 0;
830     	add_wait_queue(&info->open_wait, &wait);
831     #ifdef ROCKET_DEBUG_OPEN
832     	printk("block_til_ready before block: ttyR%d, count = %d\n",
833     	       info->line, info->count);
834     #endif
835     	save_flags(flags); cli();
836     	if (!tty_hung_up_p(filp)) {
837     		extra_count = 1;
838     		info->count--;
839     	}
840     	restore_flags(flags);
841     	info->blocked_open++;
842     	while (1) {
843     		if (!(info->flags & ROCKET_CALLOUT_ACTIVE) &&
844     		    (tty->termios->c_cflag & CBAUD)) {
845     			sSetDTR(&info->channel);
846     			sSetRTS(&info->channel);
847     		}
848     		set_current_state(TASK_INTERRUPTIBLE);
849     		if (tty_hung_up_p(filp) ||
850     		    !(info->flags & ROCKET_INITIALIZED)) {
851     			if (info->flags & ROCKET_HUP_NOTIFY)
852     				retval = -EAGAIN;
853     			else
854     				retval = -ERESTARTSYS;	
855     			break;
856     		}
857     		if (!(info->flags & ROCKET_CALLOUT_ACTIVE) &&
858     		    !(info->flags & ROCKET_CLOSING) &&
859     		    (do_clocal || (sGetChanStatusLo(&info->channel) &
860     				   CD_ACT)))
861     			break;
862     		if (signal_pending(current)) {
863     			retval = -ERESTARTSYS;
864     			break;
865     		}
866     #ifdef ROCKET_DEBUG_OPEN
867     		printk("block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n",
868     		       info->line, info->count, info->flags);
869     #endif
870     		schedule();
871     	}
872     	current->state = TASK_RUNNING;
873     	remove_wait_queue(&info->open_wait, &wait);
874     	cli();
875     	if (extra_count)
876     		info->count++;
877     	restore_flags(flags);
878     	info->blocked_open--;
879     #ifdef ROCKET_DEBUG_OPEN
880     	printk("block_til_ready after blocking: ttyR%d, count = %d\n",
881     	       info->line, info->count);
882     #endif
883     	if (retval)
884     		return retval;
885     	info->flags |= ROCKET_NORMAL_ACTIVE;
886     	return 0;
887     }	
888     
889     /*
890      * This routine is called whenever a rocketport board is opened.
891      */
892     static int rp_open(struct tty_struct *tty, struct file * filp)
893     {
894     	struct r_port *info;
895     	int	line, retval;
896     	CHANNEL_t	*cp;
897     	unsigned long page;
898     	
899     	line = MINOR(tty->device) - tty->driver.minor_start;
900     	if ((line < 0) || (line >= MAX_RP_PORTS))
901     		return -ENODEV;
902     	if (!tmp_buf) {
903     		page = get_free_page(GFP_KERNEL);
904     		if (!page)
905     			return -ENOMEM;
906     		if (tmp_buf)
907     			free_page(page);
908     		else
909     			tmp_buf = (unsigned char *) page;
910     	}
911     	page = get_free_page(GFP_KERNEL);
912     	if (!page)
913     		return -ENOMEM;
914     
915     	tty->driver_data = info = rp_table[line];
916     	
917     	if (info->flags & ROCKET_CLOSING) {
918     		interruptible_sleep_on(&info->close_wait);
919     		free_page(page);
920     		return ((info->flags & ROCKET_HUP_NOTIFY) ?
921     			-EAGAIN : -ERESTARTSYS);
922     	}
923     	
924     	/*
925     	 * We must not sleep from here until the port is marked fully
926     	 * in use.
927     	 */
928     	if (rp_table[line] == NULL) {
929     		tty->flags = (1 << TTY_IO_ERROR);
930     		free_page(page);
931     		return 0;
932     	}
933     	if (!info) {
934     		printk("rp_open: rp_table[%d] is NULL!\n", line);
935     		free_page(page);
936     		return -EIO;
937     	}
938     	if (info->xmit_buf)
939     		free_page(page);
940     	else
941     		info->xmit_buf = (unsigned char *) page;
942     	info->tty = tty;
943     
944     	if (info->flags & ROCKET_CLOSING) {
945     		interruptible_sleep_on(&info->close_wait);
946     		return ((info->flags & ROCKET_HUP_NOTIFY) ? 
947     			-EAGAIN : -ERESTARTSYS);
948     	}
949     
950     	if (info->count++ == 0) {
951     #ifdef MODULE
952     		MOD_INC_USE_COUNT;
953     #endif
954     		rp_num_ports_open++;
955     #ifdef ROCKET_DEBUG_OPEN
956     		printk("rocket mod++ = %d...", rp_num_ports_open);
957     #endif
958     	}
959     #ifdef ROCKET_DEBUG_OPEN
960     	printk("rp_open ttyR%d, count=%d\n", info->line, info->count);
961     #endif
962     	/*
963     	 * Info->count is now 1; so it's safe to sleep now.
964     	 */
965     	info->session = current->session;
966     	info->pgrp = current->pgrp;
967     	
968     	cp = &info->channel;
969     	sSetRxTrigger(cp, TRIG_1);
970     	if (sGetChanStatus(cp) & CD_ACT)
971     		info->cd_status = 1;
972     	else
973     		info->cd_status = 0;
974     	sDisRxStatusMode(cp);
975     	sFlushRxFIFO(cp);	
976     	sFlushTxFIFO(cp);	
977     
978     	sEnInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
979     	sSetRxTrigger(cp, TRIG_1);
980     
981     	sGetChanStatus(cp);
982     	sDisRxStatusMode(cp);
983     	sClrTxXOFF(cp);
984     
985     	sDisCTSFlowCtl(cp);
986     	sDisTxSoftFlowCtl(cp);
987     
988     	sEnRxFIFO(cp);
989     	sEnTransmit(cp);
990     
991     	info->flags |= ROCKET_INITIALIZED;
992     
993     #if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
994     	/*
995     	 * Set up the tty->alt_speed kludge
996     	 */
997     	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
998     		info->tty->alt_speed = 57600;
999     	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
1000     		info->tty->alt_speed = 115200;
1001     	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
1002     		info->tty->alt_speed = 230400;
1003     	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
1004     		info->tty->alt_speed = 460800;
1005     #endif
1006     
1007     	configure_r_port(info);
1008     	if (tty->termios->c_cflag & CBAUD) {
1009     		sSetDTR(cp);
1010     		sSetRTS(cp);
1011     	}
1012     	
1013     	mod_timer(&rocket_timer, jiffies + 1);
1014     
1015     	retval = block_til_ready(tty, filp, info);
1016     	if (retval) {
1017     #ifdef ROCKET_DEBUG_OPEN
1018     		printk("rp_open returning after block_til_ready with %d\n",
1019     		       retval);
1020     #endif
1021     		return retval;
1022     	}
1023     
1024     	if ((info->count == 1) && (info->flags & ROCKET_SPLIT_TERMIOS)) {
1025     		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
1026     			*tty->termios = info->normal_termios;
1027     		else 
1028     			*tty->termios = info->callout_termios;
1029     		configure_r_port(info);
1030     	}
1031     
1032     	return 0;
1033     }
1034     
1035     static void rp_close(struct tty_struct *tty, struct file * filp)
1036     {
1037     	struct r_port * info = (struct r_port *)tty->driver_data;
1038     	unsigned long flags;
1039     	int timeout;
1040     	CHANNEL_t	*cp;
1041     
1042     	if (rocket_paranoia_check(info, tty->device, "rp_close"))
1043     		return;
1044     
1045     #ifdef ROCKET_DEBUG_OPEN
1046     	printk("rp_close ttyR%d, count = %d\n", info->line, info->count);
1047     #endif
1048     	
1049     	save_flags(flags); cli();
1050     	
1051     	if (tty_hung_up_p(filp)) {
1052     		restore_flags(flags);
1053     		return;
1054     	}
1055     	if ((tty->count == 1) && (info->count != 1)) {
1056     		/*
1057     		 * Uh, oh.  tty->count is 1, which means that the tty
1058     		 * structure will be freed.  Info->count should always
1059     		 * be one in these conditions.  If it's greater than
1060     		 * one, we've got real problems, since it means the
1061     		 * serial port won't be shutdown.
1062     		 */
1063     		printk("rp_close: bad serial port count; tty->count is 1, "
1064     		       "info->count is %d\n", info->count);
1065     		info->count = 1;
1066     	}
1067     	if (--info->count < 0) {
1068     		printk("rp_close: bad serial port count for ttyR%d: %d\n",
1069     		       info->line, info->count);
1070     		info->count = 0;
1071     	}
1072     	if (info->count) {
1073     		restore_flags(flags);
1074     		return;
1075     	}
1076     	info->flags |= ROCKET_CLOSING;
1077     	/*
1078     	 * Save the termios structure, since this port may have
1079     	 * separate termios for callout and dialin.
1080     	 */
1081     	if (info->flags & ROCKET_NORMAL_ACTIVE)
1082     		info->normal_termios = *tty->termios;
1083     	if (info->flags & ROCKET_CALLOUT_ACTIVE)
1084     		info->callout_termios = *tty->termios;
1085     	
1086     	cp = &info->channel;
1087     
1088     	/*
1089     	 * Notify the line discpline to only process XON/XOFF characters
1090     	 */
1091     	tty->closing = 1;
1092     
1093     	/*
1094     	 * If transmission was throttled by the application request,
1095     	 * just flush the xmit buffer.
1096     	 */
1097     #if (LINUX_VERSION_CODE >= 131343)
1098     	if (tty->flow_stopped)
1099     		rp_flush_buffer(tty);
1100     #endif
1101     
1102     	/*
1103     	 * Wait for the transmit buffer to clear
1104     	 */
1105     	if (info->closing_wait != ROCKET_CLOSING_WAIT_NONE)
1106     		tty_wait_until_sent(tty, info->closing_wait);
1107     	/*
1108     	 * Before we drop DTR, make sure the UART transmitter
1109     	 * has completely drained; this is especially
1110     	 * important if there is a transmit FIFO!
1111     	 */
1112     	timeout = (sGetTxCnt(cp)+1) * HZ / info->cps;
1113     	if (timeout == 0)
1114     		timeout = 1;
1115     	rp_wait_until_sent(tty, timeout);
1116     	
1117     	xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
1118     	sDisTransmit(cp);
1119     	sDisInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1120     	sDisCTSFlowCtl(cp);
1121     	sDisTxSoftFlowCtl(cp);
1122     	sClrTxXOFF(cp);
1123     	sFlushRxFIFO(cp);	
1124     	sFlushTxFIFO(cp);
1125     	sClrRTS(cp);
1126     	if (C_HUPCL(tty)) {
1127     		sClrDTR(cp);
1128     	}
1129     	if (tty->driver.flush_buffer)
1130     		tty->driver.flush_buffer(tty);
1131     	if (tty->ldisc.flush_buffer)
1132     		tty->ldisc.flush_buffer(tty);
1133     
1134     	xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
1135     	if (info->blocked_open) {
1136     		if (info->close_delay) {
1137     			current->state = TASK_INTERRUPTIBLE;
1138     			schedule_timeout(info->close_delay);
1139     		}
1140     		wake_up_interruptible(&info->open_wait);
1141     	} else {
1142     		if (info->xmit_buf) {
1143     			free_page((unsigned long) info->xmit_buf);
1144     			info->xmit_buf = 0;
1145     		}
1146     	}
1147     	info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING |
1148     			 ROCKET_CALLOUT_ACTIVE | ROCKET_NORMAL_ACTIVE);
1149     	tty->closing = 0;
1150     	wake_up_interruptible(&info->close_wait);
1151     	
1152     #ifdef MODULE
1153     	MOD_DEC_USE_COUNT;
1154     #endif
1155     	rp_num_ports_open--;
1156     #ifdef ROCKET_DEBUG_OPEN
1157     	printk("rocket mod-- = %d...", rp_num_ports_open);
1158     #endif
1159     	restore_flags(flags);
1160     	
1161     #ifdef ROCKET_DEBUG_OPEN
1162     	printk("rp_close ttyR%d complete shutdown\n", info->line);
1163     #endif
1164     	
1165     }
1166     
1167     static void rp_set_termios(struct tty_struct *tty, struct termios *old_termios)
1168     {
1169     	struct r_port * info = (struct r_port *)tty->driver_data;
1170     	CHANNEL_t *cp;
1171     	unsigned cflag;
1172     	
1173     
1174     	if (rocket_paranoia_check(info, tty->device, "rp_set_termios"))
1175     		return;
1176     
1177     	cflag = tty->termios->c_cflag;
1178     
1179     	if (cflag == old_termios->c_cflag)
1180     		return;
1181     
1182     	/*
1183     	 * This driver doesn't support CS5 or CS6
1184     	 */
1185     	if (((cflag & CSIZE) == CS5) ||
1186     	    ((cflag & CSIZE) == CS6))
1187     		tty->termios->c_cflag = ((cflag & ~CSIZE) |
1188     					 (old_termios->c_cflag & CSIZE));
1189     
1190     	configure_r_port(info);
1191     
1192     	cp = &info->channel;
1193     
1194     	/* Handle transition to B0 status */
1195     	if ((old_termios->c_cflag & CBAUD) &&
1196     	    !(tty->termios->c_cflag & CBAUD)) {
1197     		sClrDTR(cp);
1198     		sClrRTS(cp);
1199     	}
1200     	
1201     	/* Handle transition away from B0 status */
1202     	if (!(old_termios->c_cflag & CBAUD) &&
1203     	    (tty->termios->c_cflag & CBAUD)) {
1204     		if (!tty->hw_stopped ||
1205     		    !(tty->termios->c_cflag & CRTSCTS)) {
1206     			sSetRTS(cp);
1207     		}
1208     		sSetDTR(cp);
1209     	}
1210     	
1211     	if ((old_termios->c_cflag & CRTSCTS) &&
1212     	    !(tty->termios->c_cflag & CRTSCTS)) {
1213     		tty->hw_stopped = 0;
1214     		rp_start(tty);
1215     	}
1216     }
1217     
1218     /*
1219      * Here are the routines used by rp_ioctl
1220      */
1221     #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
1222     static void send_break(	struct r_port * info, int duration)
1223     {
1224     	current->state = TASK_INTERRUPTIBLE;
1225     	cli();
1226     	sSendBreak(&info->channel);
1227     	schedule_timeout(duration);
1228     	sClrBreak(&info->channel);
1229     	sti();
1230     }
1231     #else
1232     static void rp_break(struct tty_struct *tty, int break_state)
1233     {
1234     	struct r_port * info = (struct r_port *)tty->driver_data;
1235     	unsigned long flags;
1236     	
1237     	if (rocket_paranoia_check(info, tty->device, "rp_break"))
1238     		return;
1239     
1240     	save_flags(flags); cli();
1241     	if (break_state == -1) {
1242     		sSendBreak(&info->channel);
1243     	} else {
1244     		sClrBreak(&info->channel);
1245     	}
1246     	restore_flags(flags);
1247     }
1248     #endif
1249     
1250     static int get_modem_info(struct r_port * info, unsigned int *value)
1251     {
1252     	unsigned int control, result, ChanStatus;
1253     
1254     	ChanStatus = sGetChanStatusLo(&info->channel);
1255     	
1256     	control = info->channel.TxControl[3];
1257     	result =  ((control & SET_RTS) ? TIOCM_RTS : 0)
1258     		| ((control & SET_DTR) ? TIOCM_DTR : 0)
1259     		| ((ChanStatus  & CD_ACT) ? TIOCM_CAR : 0)
1260     			/* TIOCM_RNG not supported */
1261     		| ((ChanStatus  & DSR_ACT) ? TIOCM_DSR : 0)
1262     		| ((ChanStatus  & CTS_ACT) ? TIOCM_CTS : 0);
1263     
1264     	if (copy_to_user(value, &result, sizeof(int)))
1265     		return -EFAULT;
1266     	return 0;
1267     }
1268     
1269     static int set_modem_info(struct r_port * info, unsigned int cmd,
1270     			  unsigned int *value)
1271     {
1272     	unsigned int arg;
1273     
1274     	if (copy_from_user(&arg, value, sizeof(int)))
1275     		return -EFAULT;
1276     
1277     	switch (cmd) {
1278     	case TIOCMBIS: 
1279     		if (arg & TIOCM_RTS)
1280     			info->channel.TxControl[3] |= SET_RTS;
1281     		if (arg & TIOCM_DTR)
1282     			info->channel.TxControl[3] |= SET_DTR;
1283     		break;
1284     	case TIOCMBIC:
1285     		if (arg & TIOCM_RTS)
1286     			info->channel.TxControl[3] &= ~SET_RTS;
1287     		if (arg & TIOCM_DTR)
1288     			info->channel.TxControl[3] &= ~SET_DTR;
1289     		break;
1290     	case TIOCMSET:
1291     		info->channel.TxControl[3] =
1292     			((info->channel.TxControl[3] & ~(SET_RTS | SET_DTR))
1293     			 | ((arg & TIOCM_RTS) ? SET_RTS : 0)
1294     			 | ((arg & TIOCM_DTR) ? SET_DTR : 0));
1295     		break;
1296     	default:
1297     		return -EINVAL;
1298     	}
1299     
1300     	sOutDW(info->channel.IndexAddr,
1301     	       *(DWord_t *) &(info->channel.TxControl[0]));
1302     	
1303     	return 0;
1304     }
1305     
1306     static int get_config(struct r_port * info, struct rocket_config * retinfo)
1307     {
1308     	struct rocket_config tmp;
1309       
1310     	if (!retinfo)
1311     		return -EFAULT;
1312     	memset(&tmp, 0, sizeof(tmp));
1313     	tmp.line = info->line;
1314     	tmp.flags = info->flags;
1315     	tmp.close_delay = info->close_delay;
1316     	tmp.closing_wait = info->closing_wait;
1317     	tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
1318     	
1319     	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
1320     		return -EFAULT;
1321     	return 0;
1322     }
1323     
1324     static int set_config(struct r_port * info, struct rocket_config * new_info)
1325     {
1326     	struct rocket_config new_serial;
1327     
1328     	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
1329     		return -EFAULT;
1330     
1331     #ifdef CAP_SYS_ADMIN
1332     	if (!capable(CAP_SYS_ADMIN))
1333     #else
1334     	if (!suser())
1335     #endif
1336     	{
1337     		if ((new_serial.flags & ~ROCKET_USR_MASK) !=
1338     		    (info->flags & ~ROCKET_USR_MASK))
1339     			return -EPERM;
1340     		info->flags = ((info->flags & ~ROCKET_USR_MASK) |
1341     			       (new_serial.flags & ROCKET_USR_MASK));
1342     		configure_r_port(info);
1343     		return 0;
1344     	}
1345     	
1346     	info->flags = ((info->flags & ~ROCKET_FLAGS) |
1347     			(new_serial.flags & ROCKET_FLAGS));
1348     	info->close_delay = new_serial.close_delay;
1349     	info->closing_wait = new_serial.closing_wait;
1350     
1351     #if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
1352     	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
1353     		info->tty->alt_speed = 57600;
1354     	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
1355     		info->tty->alt_speed = 115200;
1356     	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
1357     		info->tty->alt_speed = 230400;
1358     	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
1359     		info->tty->alt_speed = 460800;
1360     #endif
1361     	
1362     	configure_r_port(info);
1363     	return 0;
1364     }
1365     
1366     static int get_ports(struct r_port * info, struct rocket_ports * retports)
1367     {
1368     	struct rocket_ports tmp;
1369     	int	board, port, index;
1370       
1371     	if (!retports)
1372     		return -EFAULT;
1373     	memset(&tmp, 0, sizeof(tmp));
1374     	tmp.tty_major = rocket_driver.major;
1375     	tmp.callout_major = callout_driver.major;
1376     	for (board = 0; board < 4; board++) {
1377     		index = board << 5;
1378     		for (port = 0; port < 32; port++, index++) {
1379     			if (rp_table[index])
1380     				tmp.port_bitmap[board] |= 1 << port;
1381     		}
1382     	}
1383     	if (copy_to_user(retports,&tmp,sizeof(*retports)))
1384     		return -EFAULT;
1385     	return 0;
1386     }
1387     
1388     static int rp_ioctl(struct tty_struct *tty, struct file * file,
1389     		    unsigned int cmd, unsigned long arg)
1390     {
1391     	struct r_port * info = (struct r_port *)tty->driver_data;
1392     #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
1393     	int retval, tmp;
1394     #endif
1395     
1396     	if (cmd != RCKP_GET_PORTS &&
1397     	    rocket_paranoia_check(info, tty->device, "rp_ioctl"))
1398     		return -ENODEV;
1399     
1400     	switch (cmd) {
1401     #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
1402     		case TCSBRK:	/* SVID version: non-zero arg --> no break */
1403     			retval = tty_check_change(tty);
1404     			if (retval)
1405     				return retval;
1406     			tty_wait_until_sent(tty, 0);
1407     			if (signal_pending(current))
1408     				return -EINTR;
1409     			if (!arg) {
1410     				send_break(info, HZ/4);	/* 1/4 second */
1411     				if (signal_pending(current))
1412     					return -EINTR;
1413     			}
1414     			return 0;
1415     		case TCSBRKP:	/* support for POSIX tcsendbreak() */
1416     			retval = tty_check_change(tty);
1417     			if (retval)
1418     				return retval;
1419     			tty_wait_until_sent(tty, 0);
1420     			if (signal_pending(current))
1421     				return -EINTR;
1422     			send_break(info, arg ? arg*(HZ/10) : HZ/4);
1423     			if (signal_pending(current))
1424     				return -EINTR;
1425     			return 0;
1426     		case TIOCGSOFTCAR:
1427     			tmp = C_CLOCAL(tty) ? 1 : 0;
1428     			if (copy_to_user((void *)arg, &tmp, sizeof(int)))
1429     				return -EFAULT;
1430     			return 0;
1431     		case TIOCSSOFTCAR:
1432     			if (copy_from_user(&tmp, (void *)arg, sizeof(int)))
1433     				return -EFAULT;
1434     
1435     			tty->termios->c_cflag =
1436     				((tty->termios->c_cflag & ~CLOCAL) |
1437     				 (tmp ? CLOCAL : 0));
1438     			return 0;
1439     #endif
1440     		case TIOCMGET:
1441     			return get_modem_info(info, (unsigned int *) arg);
1442     		case TIOCMBIS:
1443     		case TIOCMBIC:
1444     		case TIOCMSET:
1445     			return set_modem_info(info, cmd, (unsigned int *) arg);
1446     		case RCKP_GET_STRUCT:
1447     			if (copy_to_user((void *) arg, info,
1448     					 sizeof(struct r_port)))
1449     				return -EFAULT;
1450     			return 0;
1451     
1452     		case RCKP_GET_CONFIG:
1453     			return get_config(info, (struct rocket_config *) arg);
1454     		case RCKP_SET_CONFIG:
1455     			return set_config(info, (struct rocket_config *) arg);
1456     			
1457     		case RCKP_GET_PORTS:
1458     			return get_ports(info, (struct rocket_ports *) arg);
1459     		default:
1460     			return -ENOIOCTLCMD;
1461     		}
1462     	return 0;
1463     }
1464     
1465     #if (defined(ROCKET_DEBUG_FLOW) || defined(ROCKET_DEBUG_THROTTLE))
1466     static char *rp_tty_name(struct tty_struct *tty, char *buf)
1467     {
1468     	if (tty)
1469     		sprintf(buf, "%s%d", tty->driver.name,
1470     			MINOR(tty->device) - tty->driver.minor_start +
1471     			tty->driver.name_base);
1472     	else
1473     		strcpy(buf, "NULL tty");
1474     	return buf;
1475     }
1476     #endif
1477     
1478     static void rp_send_xchar(struct tty_struct *tty, char ch)
1479     {
1480     	struct r_port *info = (struct r_port *)tty->driver_data;
1481     	CHANNEL_t *cp;
1482     
1483     	if (rocket_paranoia_check(info, tty->device, "rp_send_xchar"))
1484     		return;
1485     
1486     	cp = &info->channel;
1487     	if (sGetTxCnt(cp)) 
1488     		sWriteTxPrioByte(cp, ch);
1489     	else
1490     		sWriteTxByte(sGetTxRxDataIO(cp), ch);
1491     }
1492     
1493     static void rp_throttle(struct tty_struct * tty)
1494     {
1495     	struct r_port *info = (struct r_port *)tty->driver_data;
1496     	CHANNEL_t *cp;
1497     #ifdef ROCKET_DEBUG_THROTTLE
1498     	char	buf[64];
1499     	
1500     	printk("throttle %s: %d....\n", rp_tty_name(tty, buf),
1501     	       tty->ldisc.chars_in_buffer(tty));
1502     #endif
1503     
1504     	if (rocket_paranoia_check(info, tty->device, "rp_throttle"))
1505     		return;
1506     
1507     	cp = &info->channel;
1508     	if (I_IXOFF(tty))
1509     		rp_send_xchar(tty, STOP_CHAR(tty));
1510     	
1511     	sClrRTS(&info->channel);
1512     }
1513     
1514     static void rp_unthrottle(struct tty_struct * tty)
1515     {
1516     	struct r_port *info = (struct r_port *)tty->driver_data;
1517     	CHANNEL_t *cp;
1518     #ifdef ROCKET_DEBUG_THROTTLE
1519     	char	buf[64];
1520     	
1521     	printk("unthrottle %s: %d....\n", rp_tty_name(tty, buf),
1522     	       tty->ldisc.chars_in_buffer(tty));
1523     #endif
1524     
1525     	if (rocket_paranoia_check(info, tty->device, "rp_throttle"))
1526     		return;
1527     
1528     	cp = &info->channel;
1529     	if (I_IXOFF(tty))
1530     		rp_send_xchar(tty, START_CHAR(tty));
1531     
1532     	sSetRTS(&info->channel);
1533     }
1534     
1535     /*
1536      * ------------------------------------------------------------
1537      * rp_stop() and rp_start()
1538      *
1539      * This routines are called before setting or resetting tty->stopped.
1540      * They enable or disable transmitter interrupts, as necessary.
1541      * ------------------------------------------------------------
1542      */
1543     static void rp_stop(struct tty_struct *tty)
1544     {
1545     	struct r_port * info = (struct r_port *)tty->driver_data;
1546     #ifdef ROCKET_DEBUG_FLOW
1547     	char	buf[64];
1548     	
1549     	printk("stop %s: %d %d....\n", rp_tty_name(tty, buf),
1550     	       info->xmit_cnt, info->xmit_fifo_room);
1551     #endif
1552     
1553     	if (rocket_paranoia_check(info, tty->device, "rp_stop"))
1554     		return;
1555     
1556     	if (sGetTxCnt(&info->channel))
1557     		sDisTransmit(&info->channel);
1558     }
1559     
1560     static void rp_start(struct tty_struct *tty)
1561     {
1562     	struct r_port * info = (struct r_port *)tty->driver_data;
1563     #ifdef ROCKET_DEBUG_FLOW
1564     	char	buf[64];
1565     	
1566     	printk("start %s: %d %d....\n", rp_tty_name(tty, buf),
1567     	       info->xmit_cnt, info->xmit_fifo_room);
1568     #endif
1569     
1570     	if (rocket_paranoia_check(info, tty->device, "rp_stop"))
1571     		return;
1572     
1573     	sEnTransmit(&info->channel);
1574     	xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
1575     }
1576     
1577     /*
1578      * rp_wait_until_sent() --- wait until the transmitter is empty
1579      */
1580     static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
1581     {
1582     	struct r_port *info = (struct r_port *)tty->driver_data;
1583     	CHANNEL_t *cp;
1584     	unsigned long orig_jiffies;
1585     	int check_time, exit_time;
1586     	int txcnt;
1587     	
1588     	if (rocket_paranoia_check(info, tty->device, "rp_wait_until_sent"))
1589     		return;
1590     
1591     	cp = &info->channel;
1592     
1593     	orig_jiffies = jiffies;
1594     #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1595     	printk("In RP_wait_until_sent(%d) (jiff=%lu)...", timeout, jiffies);
1596     	printk("cps=%d...", info->cps);
1597     #endif
1598     	while (1) {
1599     		txcnt = sGetTxCnt(cp);
1600     		if (!txcnt) {
1601     			if (sGetChanStatusLo(cp) & TXSHRMT)
1602     				break;
1603     			check_time = (HZ / info->cps) / 5;
1604     		} else
1605     			check_time = HZ * txcnt / info->cps;
1606     		if (timeout) {
1607     			exit_time = orig_jiffies + timeout - jiffies;
1608     			if (exit_time <= 0)
1609     				break;
1610     			if (exit_time < check_time)
1611     				check_time = exit_time;
1612     		}
1613     		if (check_time == 0)
1614     			check_time = 1;
1615     #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1616     		printk("txcnt = %d (jiff=%lu,check=%d)...", txcnt,
1617     		       jiffies, check_time);
1618     #endif
1619     		current->state = TASK_INTERRUPTIBLE;
1620     		schedule_timeout(check_time);
1621     		if (signal_pending(current))
1622     			break;
1623     	}
1624     	current->state = TASK_RUNNING;
1625     #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1626     	printk("txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
1627     #endif
1628     }
1629     
1630     /*
1631      * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
1632      */
1633     static void rp_hangup(struct tty_struct *tty)
1634     {
1635     	CHANNEL_t	*cp;
1636     	struct r_port * info = (struct r_port *)tty->driver_data;
1637     	
1638     	if (rocket_paranoia_check(info, tty->device, "rp_hangup"))
1639     		return;
1640     
1641     #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
1642     	printk("rp_hangup of ttyR%d...", info->line);
1643     #endif
1644     	/*
1645     	 * If the port is in the process of being closed, just force
1646     	 * the transmit buffer to be empty, and let rp_close handle
1647     	 * the clean up.
1648     	 */
1649     	if (info->flags & ROCKET_CLOSING) {
1650     		cli();
1651     		info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1652     		sti();
1653     		wake_up_interruptible(&tty->write_wait);
1654     		return;
1655     	}
1656     	if (info->count) {
1657     #ifdef MODULE
1658     		MOD_DEC_USE_COUNT;
1659     #endif
1660     		rp_num_ports_open--;
1661     	}
1662     	
1663     	xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
1664     	info->count = 0;
1665     	info->flags &= ~(ROCKET_NORMAL_ACTIVE|ROCKET_CALLOUT_ACTIVE);
1666     	info->tty = 0;
1667     
1668     	cp = &info->channel;
1669     	sDisRxFIFO(cp);
1670     	sDisTransmit(cp);
1671     	sDisInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1672     	sDisCTSFlowCtl(cp);
1673     	sDisTxSoftFlowCtl(cp);
1674     	sClrTxXOFF(cp);
1675     	info->flags &= ~ROCKET_INITIALIZED;
1676     	
1677     	wake_up_interruptible(&info->open_wait);
1678     }
1679     
1680     /*
1681      * The Rocketport write routines.  The Rocketport driver uses a
1682      * double-buffering strategy, with the twist that if the in-memory CPU
1683      * buffer is empty, and there's space in the transmit FIFO, the
1684      * writing routines will write directly to transmit FIFO.
1685      *
1686      * This gets a little tricky, but I'm pretty sure I got it all right.
1687      */
1688     static void rp_put_char(struct tty_struct *tty, unsigned char ch)
1689     {
1690     	struct r_port * info = (struct r_port *)tty->driver_data;
1691     	CHANNEL_t	*cp;
1692     
1693     	if (rocket_paranoia_check(info, tty->device, "rp_put_char"))
1694     		return;
1695     
1696     #ifdef ROCKET_DEBUG_WRITE
1697     	printk("rp_put_char %c...", ch);
1698     #endif
1699     	
1700     	cp = &info->channel;
1701     
1702     	if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
1703     		info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1704     
1705     	if (tty->stopped || tty->hw_stopped ||
1706     	    info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
1707     		info->xmit_buf[info->xmit_head++] = ch;
1708     		info->xmit_head &= XMIT_BUF_SIZE-1;
1709     		info->xmit_cnt++;
1710     		xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
1711     	} else {
1712     		sOutB(sGetTxRxDataIO(cp), ch);
1713     		info->xmit_fifo_room--;
1714     	}
1715     }
1716     
1717     static int rp_write(struct tty_struct * tty, int from_user,
1718     		    const unsigned char *buf, int count)
1719     {
1720     	struct r_port * info = (struct r_port *)tty->driver_data;
1721     	CHANNEL_t	*cp;
1722     	const unsigned char	*b;
1723     	int		c, retval = 0;
1724     	unsigned long	flags;
1725     
1726     	if (count <= 0 || rocket_paranoia_check(info, tty->device, "rp_write"))
1727     		return 0;
1728     
1729     #ifdef ROCKET_DEBUG_WRITE
1730     	printk("rp_write %d chars...", count);
1731     #endif
1732     	cp = &info->channel;
1733     
1734     	if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
1735     		info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1736     
1737     	if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0
1738     	    && info->xmit_fifo_room >= 0) {
1739     		c = MIN(count, info->xmit_fifo_room);
1740     		b = buf;
1741     		if (from_user) {
1742     			down(&tmp_buf_sem);
1743     			c -= copy_from_user(tmp_buf, buf, c);
1744     			b = tmp_buf;
1745     			up(&tmp_buf_sem);
1746     			/* In case we got pre-empted */
1747     			if (!c) {
1748     				retval = -EFAULT;
1749     				goto end;
1750     			}
1751     			if (info->tty == 0)
1752     				goto end;
1753     			c = MIN(c, info->xmit_fifo_room);
1754     		}
1755     		sOutStrW(sGetTxRxDataIO(cp), b, c/2);
1756     		if (c & 1)
1757     			sOutB(sGetTxRxDataIO(cp), b[c-1]);
1758     		retval += c;
1759     		buf += c;
1760     		count -= c;
1761     		info->xmit_fifo_room -= c;
1762     	}
1763     	if (!count)
1764     		goto end;
1765     	
1766     	save_flags(flags);
1767     	while (1) {
1768     		if (info->tty == 0) {
1769     			restore_flags(flags);
1770     			goto end;
1771     		}
1772     		c = MIN(count, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1,
1773     				   XMIT_BUF_SIZE - info->xmit_head));
1774     		if (c <= 0)
1775     			break;
1776     
1777     		b = buf;
1778     		if (from_user) {
1779     			down(&tmp_buf_sem);
1780     			c -= copy_from_user(tmp_buf, buf, c);
1781     			b = tmp_buf;
1782     			up(&tmp_buf_sem);
1783     			if (!c) {
1784     				if (retval == 0)
1785     					retval = -EFAULT;
1786     				goto end_intr;
1787     			}
1788     			/* In case we got pre-empted */
1789     			if (info->tty == 0)
1790     				goto end_intr;
1791     		}
1792     		cli();
1793     		c = MIN(c, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1,
1794     			       XMIT_BUF_SIZE - info->xmit_head));
1795     		memcpy(info->xmit_buf + info->xmit_head, b, c);
1796     		info->xmit_head = (info->xmit_head + c) & (XMIT_BUF_SIZE-1);
1797     		info->xmit_cnt += c;
1798     		restore_flags(flags);
1799     		buf += c;
1800     		count -= c;
1801     		retval += c;
1802     	}
1803     end_intr:
1804     	if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
1805     		xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
1806     	restore_flags(flags);
1807     end:
1808     	if (info->xmit_cnt < WAKEUP_CHARS) {
1809     		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1810     		    tty->ldisc.write_wakeup)
1811     			(tty->ldisc.write_wakeup)(tty);
1812     		wake_up_interruptible(&tty->write_wait);
1813     	}
1814     	return retval;
1815     }
1816     
1817     /*
1818      * Return the number of characters that can be sent.  We estimate
1819      * only using the in-memory transmit buffer only, and ignore the
1820      * potential space in the transmit FIFO.
1821      */
1822     static int rp_write_room(struct tty_struct *tty)
1823     {
1824     	struct r_port * info = (struct r_port *)tty->driver_data;
1825     	int	ret;
1826     
1827     	if (rocket_paranoia_check(info, tty->device, "rp_write_room"))
1828     		return 0;
1829     
1830     	ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
1831     	if (ret < 0)
1832     		ret = 0;
1833     #ifdef ROCKET_DEBUG_WRITE
1834     	printk("rp_write_room returns %d...", ret);
1835     #endif
1836     	return ret;
1837     }
1838     
1839     /*
1840      * Return the number of characters in the buffer.  Again, this only
1841      * counts those characters in the in-memory transmit buffer.
1842      */
1843     static int rp_chars_in_buffer(struct tty_struct *tty)
1844     {
1845     	struct r_port * info = (struct r_port *)tty->driver_data;
1846     	CHANNEL_t	*cp;
1847     
1848     	if (rocket_paranoia_check(info, tty->device, "rp_chars_in_buffer"))
1849     		return 0;
1850     
1851     	cp = &info->channel;
1852     
1853     #ifdef ROCKET_DEBUG_WRITE
1854     	printk("rp_chars_in_buffer returns %d...", info->xmit_cnt);
1855     #endif
1856     	return info->xmit_cnt;
1857     }
1858     
1859     static void rp_flush_buffer(struct tty_struct *tty)
1860     {
1861     	struct r_port * info = (struct r_port *)tty->driver_data;
1862     	CHANNEL_t	*cp;
1863     
1864     	if (rocket_paranoia_check(info, tty->device, "rp_flush_buffer"))
1865     		return;
1866     
1867     	cli();
1868     	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1869     	sti();
1870     	wake_up_interruptible(&tty->write_wait);
1871     	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1872     	    tty->ldisc.write_wakeup)
1873     		(tty->ldisc.write_wakeup)(tty);
1874     	
1875     	cp = &info->channel;
1876     	
1877     	sFlushTxFIFO(cp);
1878     }
1879     
1880     #ifdef ENABLE_PCI
1881     #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
1882     /* For compatibility */
1883     static struct pci_dev *pci_find_slot(unsigned char bus,
1884     				     unsigned char device_fn)
1885     {
1886     	unsigned short		vendor_id, device_id;
1887     	int			ret, error;
1888     	static struct pci_dev	ret_struct;
1889     	
1890     	error = pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID,
1891     		&vendor_id);
1892     	ret = pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID,
1893     		&device_id);
1894     	if (error == 0)
1895     		error = ret;
1896     
1897     	if (error) {
1898     		printk("PCI RocketPort error: %s not initializing due to error"
1899     		       "reading configuration space\n",
1900     		       pcibios_strerror(error));
1901     		return(0);
1902     	}
1903     
1904     	memset(&ret_struct, 0, sizeof(ret_struct));
1905     	ret_struct.device = device_id;
1906     
1907     	return &ret_struct;
1908     }
1909     #endif
1910          
1911     int __init register_PCI(int i, unsigned int bus, unsigned int device_fn)
1912     {
1913     	int	num_aiops, aiop, max_num_aiops, num_chan, chan;
1914     	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];
1915     	char *str;
1916     	CONTROLLER_t	*ctlp;
1917     	struct pci_dev *dev = pci_find_slot(bus, device_fn);
1918     #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
1919     	int	ret;
1920     	unsigned int port;
1921     #endif
1922     
1923     	if (!dev)
1924     		return 0;
1925     
1926     	if (pci_enable_device(dev))
1927     		return 0;
1928     
1929     	rcktpt_io_addr[i] = pci_resource_start (dev, 0);
1930     	switch(dev->device) {
1931     	case PCI_DEVICE_ID_RP4QUAD:
1932     		str = "Quadcable";
1933     		max_num_aiops = 1;
1934     		break;
1935     	case PCI_DEVICE_ID_RP8OCTA:
1936     		str = "Octacable";
1937     		max_num_aiops = 1;
1938     		break;
1939     	case PCI_DEVICE_ID_RP8INTF:
1940     		str = "8";
1941     		max_num_aiops = 1;
1942     		break;
1943     	case PCI_DEVICE_ID_RP8J:
1944     		str = "8J";
1945     		max_num_aiops = 1;
1946     		break;
1947     	case PCI_DEVICE_ID_RP16INTF:
1948     		str = "16";
1949     		max_num_aiops = 2;
1950     		break;
1951     	case PCI_DEVICE_ID_RP32INTF:
1952     		str = "32";
1953     		max_num_aiops = 4;
1954     		break;
1955     	case PCI_DEVICE_ID_RPP4:
1956     		str = "Plus Quadcable";
1957     		max_num_aiops = 1;
1958     		break;
1959     	case PCI_DEVICE_ID_RPP8:
1960     		str = "Plus Octacable";
1961     		max_num_aiops = 1;
1962     		break;
1963     	case PCI_DEVICE_ID_RP8M:
1964     		str = "8-port Modem";
1965     		max_num_aiops = 1;
1966     		break;
1967     	default:
1968     		str = "(unknown/unsupported)";
1969     		max_num_aiops = 0;
1970     		break;
1971     	}
1972     	for(aiop=0;aiop < max_num_aiops;aiop++)
1973     		aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
1974     	ctlp = sCtlNumToCtlPtr(i);
1975     	num_aiops = sPCIInitController(ctlp, i,
1976     					aiopio, max_num_aiops, 0,
1977     					FREQ_DIS, 0);
1978     	printk("Rocketport controller #%d found at %02x:%02x, "
1979     	       "%d AIOP(s) (PCI Rocketport %s)\n", i, bus, device_fn,
1980     	       num_aiops, str);
1981     	if(num_aiops <= 0) {
1982     		rcktpt_io_addr[i] = 0;
1983     		return(0);
1984     	}
1985     	for(aiop = 0;aiop < num_aiops; aiop++) {
1986     		sResetAiopByNum(ctlp, aiop);
1987     		sEnAiop(ctlp, aiop);
1988     		num_chan = sGetAiopNumChan(ctlp, aiop);
1989     		for(chan=0;chan < num_chan; chan++)
1990     			init_r_port(i, aiop, chan);
1991     	}
1992     	return(1);
1993     }
1994     
1995     static int __init init_PCI(int boards_found)
1996     {
1997     	unsigned char	bus, device_fn;
1998     	int	i, count = 0;
1999     
2000     	for(i=0; i < (NUM_BOARDS - boards_found); i++) {
2001     		if (!pcibios_find_device(PCI_VENDOR_ID_RP,
2002     			PCI_DEVICE_ID_RP4QUAD, i, &bus, &device_fn)) 
2003     			if (register_PCI(count+boards_found, bus, device_fn))
2004     				count++;
2005     		if (!pcibios_find_device(PCI_VENDOR_ID_RP,
2006     			PCI_DEVICE_ID_RP8J, i, &bus, &device_fn)) 
2007     			if (register_PCI(count+boards_found, bus, device_fn))
2008     				count++;
2009     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2010     			PCI_DEVICE_ID_RP8OCTA, i, &bus, &device_fn)) 
2011     			if(register_PCI(count+boards_found, bus, device_fn))
2012     				count++;
2013     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2014     			PCI_DEVICE_ID_RP8INTF, i, &bus, &device_fn)) 
2015     			if(register_PCI(count+boards_found, bus, device_fn))
2016     				count++;
2017     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2018     			PCI_DEVICE_ID_RP16INTF, i, &bus, &device_fn)) 
2019     			if(register_PCI(count+boards_found, bus, device_fn))
2020     				count++;
2021     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2022     			PCI_DEVICE_ID_RP32INTF, i, &bus, &device_fn)) 
2023     			if(register_PCI(count+boards_found, bus, device_fn))
2024     				count++;
2025     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2026     			PCI_DEVICE_ID_RP4QUAD, i, &bus, &device_fn)) 
2027     			if(register_PCI(count+boards_found, bus, device_fn))
2028     				count++;
2029     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2030     			PCI_DEVICE_ID_RP8J, i, &bus, &device_fn)) 
2031     			if(register_PCI(count+boards_found, bus, device_fn))
2032     				count++;
2033     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2034     			PCI_DEVICE_ID_RPP4, i, &bus, &device_fn)) 
2035     			if(register_PCI(count+boards_found, bus, device_fn))
2036     				count++;
2037     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2038     			PCI_DEVICE_ID_RPP8, i, &bus, &device_fn)) 
2039     			if(register_PCI(count+boards_found, bus, device_fn))
2040     				count++;
2041     		if(!pcibios_find_device(PCI_VENDOR_ID_RP,
2042     			PCI_DEVICE_ID_RP8M, i, &bus, &device_fn)) 
2043     			if(register_PCI(count+boards_found, bus, device_fn))
2044     				count++;
2045     	}
2046     	return(count);
2047     }
2048     #endif
2049     
2050     static int __init init_ISA(int i, int *reserved_controller)
2051     {
2052     	int	num_aiops, num_chan;
2053     	int	aiop, chan;
2054     	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];	
2055     	CONTROLLER_t	*ctlp;
2056     
2057     	if (rcktpt_io_addr[i] == 0)
2058     		return(0);
2059     
2060     	if (check_region(rcktpt_io_addr[i],64)) {
2061     		printk("RocketPort board address 0x%lx in use...\n",
2062     			rcktpt_io_addr[i]);
2063     		rcktpt_io_addr[i] = 0;
2064     		return(0);
2065     	}
2066     	
2067     	for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
2068     		aiopio[aiop]= rcktpt_io_addr[i] + (aiop * 0x400);
2069     	ctlp= sCtlNumToCtlPtr(i);
2070     	num_aiops = sInitController(ctlp, i, controller + (i*0x400),
2071     				    aiopio, MAX_AIOPS_PER_BOARD, 0,
2072     				    FREQ_DIS, 0);
2073     	if (num_aiops <= 0) {
2074     		rcktpt_io_addr[i] = 0;
2075     		return(0);
2076     	}
2077     	for (aiop = 0; aiop < num_aiops; aiop++) {
2078     		sResetAiopByNum(ctlp, aiop);
2079     		sEnAiop(ctlp, aiop);
2080     		num_chan = sGetAiopNumChan(ctlp,aiop);
2081     		for (chan=0; chan < num_chan; chan++)
2082     			init_r_port(i, aiop, chan);
2083     	}
2084     	printk("Rocketport controller #%d found at 0x%lx, "
2085     	       "%d AIOPs\n", i, rcktpt_io_addr[i],
2086     	       num_aiops);
2087     	if (rcktpt_io_addr[i] + 0x40 == controller) {
2088     		*reserved_controller = 1;
2089     		request_region(rcktpt_io_addr[i], 68,
2090     				       "Comtrol Rocketport");
2091     	} else {
2092     		request_region(rcktpt_io_addr[i], 64,
2093     			       "Comtrol Rocketport");
2094     	}
2095     	return(1);
2096     }
2097     
2098     
2099     /*
2100      * The module "startup" routine; it's run when the module is loaded.
2101      */
2102     int __init rp_init(void)
2103     {
2104     	int i, retval, pci_boards_found, isa_boards_found;
2105     	int	reserved_controller = 0;
2106     
2107     	printk("Rocketport device driver module, version %s, %s\n",
2108     	       ROCKET_VERSION, ROCKET_DATE);
2109     
2110     	/*
2111     	 * Set up the timer channel.  If it is already in use by
2112     	 * some other driver, give up.
2113     	 */
2114     	if (rocket_timer.function) {
2115     		printk("rocket.o: Timer already in use!\n");
2116     		return -EBUSY;
2117     	}
2118     	init_timer(&rocket_timer);
2119     	rocket_timer.function = rp_do_poll;
2120     	
2121     	/*
2122     	 * Initialize the array of pointers to our own internal state
2123     	 * structures.
2124     	 */
2125     	memset(rp_table, 0, sizeof(rp_table));
2126     	memset(xmit_flags, 0, sizeof(xmit_flags));
2127     
2128     	if (board1 == 0)
2129     		board1 = 0x180;
2130     	if (controller == 0)
2131     		controller = board1 + 0x40;
2132     
2133     	if (check_region(controller, 4)) {
2134     		printk("Controller IO addresses in use, unloading driver.\n");
2135     		return -EBUSY;
2136     	}
2137     	
2138     	rcktpt_io_addr[0] = board1;
2139     	rcktpt_io_addr[1] = board2;
2140     	rcktpt_io_addr[2] = board3;
2141     	rcktpt_io_addr[3] = board4;
2142     
2143     	/*
2144     	 * If support_low_speed is set, use the slow clock prescale,
2145     	 * which supports 50 bps
2146     	 */
2147     	if (support_low_speed) {
2148     		sClockPrescale = 0x19;	/* mod 9 (divide by 10) prescale */
2149     		rp_baud_base = 230400;
2150     	} else {
2151     		sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */
2152     		rp_baud_base = 460800;
2153     	}
2154     	
2155     	/*
2156     	 * OK, let's probe each of the controllers looking for boards.
2157     	 */
2158     	isa_boards_found = 0;
2159     	pci_boards_found = 0;
2160     	for (i=0; i < NUM_BOARDS; i++) {
2161     		if(init_ISA(i, &reserved_controller))
2162     			isa_boards_found++;
2163     	}
2164     #ifdef ENABLE_PCI
2165     	if (pcibios_present()) {
2166     		if(isa_boards_found < NUM_BOARDS)
2167     			pci_boards_found = init_PCI(isa_boards_found);
2168     	} else {
2169     		printk("No PCI BIOS found\n");
2170     	}
2171     #endif
2172     	max_board = pci_boards_found + isa_boards_found;
2173     	
2174     	if (max_board == 0) {
2175     		printk("No rocketport ports found; unloading driver.\n");
2176     		rocket_timer.function = 0;
2177     		return -ENODEV;
2178     	}
2179     
2180     	if (reserved_controller == 0)
2181     		request_region(controller, 4, "Comtrol Rocketport");
2182     
2183     	/*
2184     	 * Set up the tty driver structure and then register this
2185     	 * driver with the tty layer.
2186     	 */
2187     	memset(&rocket_driver, 0, sizeof(struct tty_driver));
2188     	rocket_driver.magic = TTY_DRIVER_MAGIC;
2189     #ifdef CONFIG_DEVFS_FS
2190     	rocket_driver.name = "tts/R%d";
2191     #else
2192     	rocket_driver.name = "ttyR";
2193     #endif
2194     	rocket_driver.major = TTY_ROCKET_MAJOR;
2195     	rocket_driver.minor_start = 0;
2196     	rocket_driver.num = MAX_RP_PORTS;
2197     	rocket_driver.type = TTY_DRIVER_TYPE_SERIAL;
2198     	rocket_driver.subtype = SERIAL_TYPE_NORMAL;
2199     	rocket_driver.init_termios = tty_std_termios;
2200     	rocket_driver.init_termios.c_cflag =
2201     		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2202     	rocket_driver.flags = TTY_DRIVER_REAL_RAW;
2203     	rocket_driver.refcount = &rocket_refcount;
2204     	rocket_driver.table = rocket_table;
2205     	rocket_driver.termios = rocket_termios;
2206     	rocket_driver.termios_locked = rocket_termios_locked;
2207     
2208     	rocket_driver.open = rp_open;
2209     	rocket_driver.close = rp_close;
2210     	rocket_driver.write = rp_write;
2211     	rocket_driver.put_char = rp_put_char;
2212     	rocket_driver.write_room = rp_write_room;
2213     	rocket_driver.chars_in_buffer = rp_chars_in_buffer;
2214     	rocket_driver.flush_buffer = rp_flush_buffer;
2215     	rocket_driver.ioctl = rp_ioctl;
2216     	rocket_driver.throttle = rp_throttle;
2217     	rocket_driver.unthrottle = rp_unthrottle;
2218     	rocket_driver.set_termios = rp_set_termios;
2219     	rocket_driver.stop = rp_stop;
2220     	rocket_driver.start = rp_start;
2221     	rocket_driver.hangup = rp_hangup;
2222     #if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
2223     	rocket_driver.break_ctl = rp_break;
2224     #endif
2225     #if (LINUX_VERSION_CODE >= 131343)
2226     	rocket_driver.send_xchar = rp_send_xchar;
2227     	rocket_driver.wait_until_sent = rp_wait_until_sent;
2228     #endif
2229     
2230     	/*
2231     	 * The callout device is just like normal device except for
2232     	 * the minor number and the subtype code.
2233     	 */
2234     	callout_driver = rocket_driver;
2235     #ifdef CONFIG_DEVFS_FS
2236     	callout_driver.name = "cua/R%d";
2237     #else
2238     	callout_driver.name = "cur";
2239     #endif
2240     	callout_driver.major = CUA_ROCKET_MAJOR;
2241     	callout_driver.minor_start = 0;
2242     	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
2243     	
2244     	retval = tty_register_driver(&callout_driver);
2245     	if (retval < 0) {
2246     		printk("Couldn't install Rocketport callout driver "
2247     		       "(error %d)\n", -retval);
2248     		return -1;
2249     	}
2250     
2251     	retval = tty_register_driver(&rocket_driver);
2252     	if (retval < 0) {
2253     		printk("Couldn't install tty Rocketport driver "
2254     		       "(error %d)\n", -retval);
2255     		return -1;
2256     	}
2257     #ifdef ROCKET_DEBUG_OPEN
2258     	printk("Rocketport driver is major %d, callout is %d\n",
2259     	       rocket_driver.major, callout_driver.major);
2260     #endif
2261     
2262     	return 0;
2263     }
2264     
2265     #ifdef MODULE
2266     int init_module(void)
2267     {
2268     	return rp_init();
2269     }
2270     
2271     void
2272     cleanup_module( void) {
2273     	int	retval;
2274     	int	i;
2275     	int	released_controller = 0;
2276     
2277     	del_timer_sync(&rocket_timer);
2278     
2279     	retval = tty_unregister_driver(&callout_driver);
2280     	if (retval) {
2281     		printk("Error %d while trying to unregister "
2282     		       "rocketport callout driver\n", -retval);
2283     	}
2284     	retval = tty_unregister_driver(&rocket_driver);
2285     	if (retval) {
2286     		printk("Error %d while trying to unregister "
2287     		       "rocketport driver\n", -retval);
2288     	}
2289     	for (i = 0; i < MAX_RP_PORTS; i++) {
2290     		if (rp_table[i])
2291     			kfree(rp_table[i]);
2292     	}
2293     	for (i=0; i < NUM_BOARDS; i++) {
2294     		if (rcktpt_io_addr[i] <= 0)
2295     			continue;
2296     		if (rcktpt_io_addr[i] + 0x40 == controller) {
2297     			released_controller++;
2298     			release_region(rcktpt_io_addr[i], 68);
2299     		} else
2300     			release_region(rcktpt_io_addr[i], 64);
2301     		if (released_controller == 0)
2302     			release_region(controller, 4);
2303     	}
2304     	if (tmp_buf)
2305     		free_page((unsigned long) tmp_buf);
2306     	rocket_timer.function = 0;
2307     }
2308     #endif
2309     
2310     /***********************************************************************
2311     		Copyright 1994 Comtrol Corporation.
2312     			All Rights Reserved.
2313     
2314     The following source code is subject to Comtrol Corporation's
2315     Developer's License Agreement.
2316     
2317     This source code is protected by United States copyright law and 
2318     international copyright treaties.
2319     
2320     This source code may only be used to develop software products that
2321     will operate with Comtrol brand hardware.
2322     
2323     You may not reproduce nor distribute this source code in its original
2324     form but must produce a derivative work which includes portions of
2325     this source code only.
2326     
2327     The portions of this source code which you use in your derivative
2328     work must bear Comtrol's copyright notice:
2329     
2330     		Copyright 1994 Comtrol Corporation.
2331     
2332     ***********************************************************************/
2333     
2334     #ifndef TRUE
2335     #define TRUE 1
2336     #endif
2337     
2338     #ifndef FALSE
2339     #define FALSE 0
2340     #endif
2341     
2342     static Byte_t RData[RDATASIZE] =
2343     {
2344        0x00, 0x09, 0xf6, 0x82,
2345        0x02, 0x09, 0x86, 0xfb,
2346        0x04, 0x09, 0x00, 0x0a,
2347        0x06, 0x09, 0x01, 0x0a,
2348        0x08, 0x09, 0x8a, 0x13,
2349        0x0a, 0x09, 0xc5, 0x11,
2350        0x0c, 0x09, 0x86, 0x85,
2351        0x0e, 0x09, 0x20, 0x0a,
2352        0x10, 0x09, 0x21, 0x0a,
2353        0x12, 0x09, 0x41, 0xff,
2354        0x14, 0x09, 0x82, 0x00,
2355        0x16, 0x09, 0x82, 0x7b,
2356        0x18, 0x09, 0x8a, 0x7d,
2357        0x1a, 0x09, 0x88, 0x81,
2358        0x1c, 0x09, 0x86, 0x7a,
2359        0x1e, 0x09, 0x84, 0x81,
2360        0x20, 0x09, 0x82, 0x7c,
2361        0x22, 0x09, 0x0a, 0x0a 
2362     };
2363     
2364     static Byte_t RRegData[RREGDATASIZE]=
2365     {
2366        0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
2367        0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
2368        0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
2369        0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
2370        0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
2371        0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
2372        0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
2373        0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
2374        0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
2375        0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
2376        0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
2377        0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
2378        0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
2379     };
2380     
2381     CONTROLLER_T sController[CTL_SIZE] =
2382     {
2383        {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
2384        {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
2385        {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
2386        {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}
2387     };
2388     
2389     #if 0
2390     /* IRQ number to MUDBAC register 2 mapping */
2391     Byte_t sIRQMap[16] =
2392     {
2393        0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
2394     };
2395     #endif
2396     
2397     Byte_t sBitMapClrTbl[8] =
2398     {
2399        0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
2400     };
2401     
2402     Byte_t sBitMapSetTbl[8] =
2403     {
2404        0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
2405     };
2406     
2407     int sClockPrescale = 0x14;
2408     
2409     /***************************************************************************
2410     Function: sInitController
2411     Purpose:  Initialization of controller global registers and controller
2412               structure.
2413     Call:     sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
2414                               IRQNum,Frequency,PeriodicOnly)
2415               CONTROLLER_T *CtlP; Ptr to controller structure
2416               int CtlNum; Controller number
2417               ByteIO_t MudbacIO; Mudbac base I/O address.
2418               ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
2419                  This list must be in the order the AIOPs will be found on the
2420                  controller.  Once an AIOP in the list is not found, it is
2421                  assumed that there are no more AIOPs on the controller.
2422               int AiopIOListSize; Number of addresses in AiopIOList
2423               int IRQNum; Interrupt Request number.  Can be any of the following:
2424                              0: Disable global interrupts
2425                              3: IRQ 3
2426                              4: IRQ 4
2427                              5: IRQ 5
2428                              9: IRQ 9
2429                              10: IRQ 10
2430                              11: IRQ 11
2431                              12: IRQ 12
2432                              15: IRQ 15
2433               Byte_t Frequency: A flag identifying the frequency
2434                        of the periodic interrupt, can be any one of the following:
2435                           FREQ_DIS - periodic interrupt disabled
2436                           FREQ_137HZ - 137 Hertz
2437                           FREQ_69HZ - 69 Hertz
2438                           FREQ_34HZ - 34 Hertz
2439                           FREQ_17HZ - 17 Hertz
2440                           FREQ_9HZ - 9 Hertz
2441                           FREQ_4HZ - 4 Hertz
2442                        If IRQNum is set to 0 the Frequency parameter is
2443                        overidden, it is forced to a value of FREQ_DIS.
2444               int PeriodicOnly: TRUE if all interrupts except the periodic
2445                                    interrupt are to be blocked.
2446                                 FALSE is both the periodic interrupt and
2447                                    other channel interrupts are allowed.
2448                                 If IRQNum is set to 0 the PeriodicOnly parameter is
2449                                    overidden, it is forced to a value of FALSE.
2450     Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
2451                    initialization failed.
2452     
2453     Comments:
2454               If periodic interrupts are to be disabled but AIOP interrupts
2455               are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
2456     
2457               If interrupts are to be completely disabled set IRQNum to 0.
2458     
2459               Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
2460               invalid combination.
2461     
2462               This function performs initialization of global interrupt modes,
2463               but it does not actually enable global interrupts.  To enable
2464               and disable global interrupts use functions sEnGlobalInt() and
2465               sDisGlobalInt().  Enabling of global interrupts is normally not
2466               done until all other initializations are complete.
2467     
2468               Even if interrupts are globally enabled, they must also be
2469               individually enabled for each channel that is to generate
2470               interrupts.
2471     
2472     Warnings: No range checking on any of the parameters is done.
2473     
2474               No context switches are allowed while executing this function.
2475     
2476               After this function all AIOPs on the controller are disabled,
2477               they can be enabled with sEnAiop().
2478     */
2479     int sInitController(	CONTROLLER_T *CtlP,
2480     			int CtlNum,
2481     			ByteIO_t MudbacIO,
2482     			ByteIO_t *AiopIOList,
2483     			int AiopIOListSize,
2484     			int IRQNum,
2485     			Byte_t Frequency,
2486     			int PeriodicOnly)
2487     {
2488     	int		i;
2489     	ByteIO_t	io;
2490     
2491        CtlP->CtlNum = CtlNum;
2492        CtlP->CtlID = CTLID_0001;        /* controller release 1 */
2493        CtlP->BusType = isISA;     
2494        CtlP->MBaseIO = MudbacIO;
2495        CtlP->MReg1IO = MudbacIO + 1;
2496        CtlP->MReg2IO = MudbacIO + 2;
2497        CtlP->MReg3IO = MudbacIO + 3;
2498     #if 1
2499        CtlP->MReg2 = 0;                 /* interrupt disable */
2500        CtlP->MReg3 = 0;                 /* no periodic interrupts */
2501     #else
2502        if(sIRQMap[IRQNum] == 0)            /* interrupts globally disabled */
2503        {
2504           CtlP->MReg2 = 0;                 /* interrupt disable */
2505           CtlP->MReg3 = 0;                 /* no periodic interrupts */
2506        }
2507        else
2508        {
2509           CtlP->MReg2 = sIRQMap[IRQNum];   /* set IRQ number */
2510           CtlP->MReg3 = Frequency;         /* set frequency */
2511           if(PeriodicOnly)                 /* periodic interrupt only */
2512           {
2513              CtlP->MReg3 |= PERIODIC_ONLY;
2514           }
2515        }
2516     #endif
2517        sOutB(CtlP->MReg2IO,CtlP->MReg2);
2518        sOutB(CtlP->MReg3IO,CtlP->MReg3);
2519        sControllerEOI(CtlP);               /* clear EOI if warm init */
2520        /* Init AIOPs */
2521        CtlP->NumAiop = 0;
2522        for(i=0; i < AiopIOListSize; i++)
2523        {
2524           io = AiopIOList[i];
2525           CtlP->AiopIO[i] = (WordIO_t)io;
2526           CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2527           sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
2528           sOutB(MudbacIO,(Byte_t)(io >> 6));	/* set up AIOP I/O in MUDBAC */
2529           sEnAiop(CtlP,i);                         /* enable the AIOP */
2530     
2531           CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
2532           if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
2533           {
2534              sDisAiop(CtlP,i);                     /* disable AIOP */
2535              break;                                /* done looking for AIOPs */
2536           }
2537     
2538           CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
2539           sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
2540           sOutB(io + _INDX_DATA,sClockPrescale);
2541           CtlP->NumAiop++;                         /* bump count of AIOPs */
2542           sDisAiop(CtlP,i);                        /* disable AIOP */
2543        }
2544     
2545        if(CtlP->NumAiop == 0)
2546           return(-1);
2547        else
2548           return(CtlP->NumAiop);
2549     }
2550     
2551     /***************************************************************************
2552     Function: sPCIInitController
2553     Purpose:  Initialization of controller global registers and controller
2554               structure.
2555     Call:     sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
2556                               IRQNum,Frequency,PeriodicOnly)
2557               CONTROLLER_T *CtlP; Ptr to controller structure
2558               int CtlNum; Controller number
2559               ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
2560                  This list must be in the order the AIOPs will be found on the
2561                  controller.  Once an AIOP in the list is not found, it is
2562                  assumed that there are no more AIOPs on the controller.
2563               int AiopIOListSize; Number of addresses in AiopIOList
2564               int IRQNum; Interrupt Request number.  Can be any of the following:
2565                              0: Disable global interrupts
2566                              3: IRQ 3
2567                              4: IRQ 4
2568                              5: IRQ 5
2569                              9: IRQ 9
2570                              10: IRQ 10
2571                              11: IRQ 11
2572                              12: IRQ 12
2573                              15: IRQ 15
2574               Byte_t Frequency: A flag identifying the frequency
2575                        of the periodic interrupt, can be any one of the following:
2576                           FREQ_DIS - periodic interrupt disabled
2577                           FREQ_137HZ - 137 Hertz
2578                           FREQ_69HZ - 69 Hertz
2579                           FREQ_34HZ - 34 Hertz
2580                           FREQ_17HZ - 17 Hertz
2581                           FREQ_9HZ - 9 Hertz
2582                           FREQ_4HZ - 4 Hertz
2583                        If IRQNum is set to 0 the Frequency parameter is
2584                        overidden, it is forced to a value of FREQ_DIS.
2585               int PeriodicOnly: TRUE if all interrupts except the periodic
2586                                    interrupt are to be blocked.
2587                                 FALSE is both the periodic interrupt and
2588                                    other channel interrupts are allowed.
2589                                 If IRQNum is set to 0 the PeriodicOnly parameter is
2590                                    overidden, it is forced to a value of FALSE.
2591     Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
2592                    initialization failed.
2593     
2594     Comments:
2595               If periodic interrupts are to be disabled but AIOP interrupts
2596               are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
2597     
2598               If interrupts are to be completely disabled set IRQNum to 0.
2599     
2600               Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
2601               invalid combination.
2602     
2603               This function performs initialization of global interrupt modes,
2604               but it does not actually enable global interrupts.  To enable
2605               and disable global interrupts use functions sEnGlobalInt() and
2606               sDisGlobalInt().  Enabling of global interrupts is normally not
2607               done until all other initializations are complete.
2608     
2609               Even if interrupts are globally enabled, they must also be
2610               individually enabled for each channel that is to generate
2611               interrupts.
2612     
2613     Warnings: No range checking on any of the parameters is done.
2614     
2615               No context switches are allowed while executing this function.
2616     
2617               After this function all AIOPs on the controller are disabled,
2618               they can be enabled with sEnAiop().
2619     */
2620     int sPCIInitController(	CONTROLLER_T *CtlP,
2621     			int CtlNum,
2622     			ByteIO_t *AiopIOList,
2623     			int AiopIOListSize,
2624     			int IRQNum,
2625     			Byte_t Frequency,
2626     			int PeriodicOnly)
2627     {
2628     	int		i;
2629     	ByteIO_t	io;
2630     
2631        CtlP->CtlNum = CtlNum;
2632        CtlP->CtlID = CTLID_0001;        /* controller release 1 */
2633        CtlP->BusType = isPCI;        /* controller release 1 */
2634     
2635        CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
2636     
2637        sPCIControllerEOI(CtlP);               /* clear EOI if warm init */
2638        /* Init AIOPs */
2639        CtlP->NumAiop = 0;
2640        for(i=0; i < AiopIOListSize; i++)
2641        {
2642           io = AiopIOList[i];
2643           CtlP->AiopIO[i] = (WordIO_t)io;
2644           CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2645     
2646           CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
2647           if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
2648              break;                                /* done looking for AIOPs */
2649     
2650           CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
2651           sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
2652           sOutB(io + _INDX_DATA,sClockPrescale);
2653           CtlP->NumAiop++;                         /* bump count of AIOPs */
2654        }
2655     
2656        if(CtlP->NumAiop == 0)
2657           return(-1);
2658        else
2659           return(CtlP->NumAiop);
2660     }
2661     
2662     /***************************************************************************
2663     Function: sReadAiopID
2664     Purpose:  Read the AIOP idenfication number directly from an AIOP.
2665     Call:     sReadAiopID(io)
2666               ByteIO_t io: AIOP base I/O address
2667     Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
2668                      is replace by an identifying number.
2669               Flag AIOPID_NULL if no valid AIOP is found
2670     Warnings: No context switches are allowed while executing this function.
2671     
2672     */
2673     int sReadAiopID(ByteIO_t io)
2674     {
2675        Byte_t AiopID;               /* ID byte from AIOP */
2676     
2677        sOutB(io + _CMD_REG,RESET_ALL);     /* reset AIOP */
2678        sOutB(io + _CMD_REG,0x0);
2679        AiopID = sInB(io + _CHN_STAT0) & 0x07;
2680        if(AiopID == 0x06)
2681           return(1);
2682        else                                /* AIOP does not exist */
2683           return(-1);
2684     }
2685     
2686     /***************************************************************************
2687     Function: sReadAiopNumChan
2688     Purpose:  Read the number of channels available in an AIOP directly from
2689               an AIOP.
2690     Call:     sReadAiopNumChan(io)
2691               WordIO_t io: AIOP base I/O address
2692     Return:   int: The number of channels available
2693     Comments: The number of channels is determined by write/reads from identical
2694               offsets within the SRAM address spaces for channels 0 and 4.
2695               If the channel 4 space is mirrored to channel 0 it is a 4 channel
2696               AIOP, otherwise it is an 8 channel.
2697     Warnings: No context switches are allowed while executing this function.
2698     */
2699     int sReadAiopNumChan(WordIO_t io)
2700     {
2701        Word_t x;
2702     
2703        sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
2704        sOutW(io + _INDX_ADDR,0);       /* read from SRAM, chan 0 */
2705        x = sInW(io + _INDX_DATA);
2706        sOutW(io + _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
2707        if(x != sInW(io + _INDX_DATA))  /* if different must be 8 chan */
2708           return(8);
2709        else
2710           return(4);
2711     }
2712     
2713     /***************************************************************************
2714     Function: sInitChan
2715     Purpose:  Initialization of a channel and channel structure
2716     Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
2717               CONTROLLER_T *CtlP; Ptr to controller structure
2718               CHANNEL_T *ChP; Ptr to channel structure
2719               int AiopNum; AIOP number within controller
2720               int ChanNum; Channel number within AIOP
2721     Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
2722                    number exceeds number of channels available in AIOP.
2723     Comments: This function must be called before a channel can be used.
2724     Warnings: No range checking on any of the parameters is done.
2725     
2726               No context switches are allowed while executing this function.
2727     */
2728     int sInitChan(	CONTROLLER_T *CtlP,
2729     		CHANNEL_T *ChP,
2730     		int AiopNum,
2731     		int ChanNum)
2732     {
2733        int i;
2734        WordIO_t AiopIO;
2735        WordIO_t ChIOOff;
2736        Byte_t *ChR;
2737        Word_t ChOff;
2738        static Byte_t R[4];
2739        int brd9600;
2740     
2741        if(ChanNum >= CtlP->AiopNumChan[AiopNum])
2742           return(FALSE);                   /* exceeds num chans in AIOP */
2743     
2744        /* Channel, AIOP, and controller identifiers */
2745        ChP->CtlP = CtlP;
2746        ChP->ChanID = CtlP->AiopID[AiopNum];
2747        ChP->AiopNum = AiopNum;
2748        ChP->ChanNum = ChanNum;
2749     
2750        /* Global direct addresses */
2751        AiopIO = CtlP->AiopIO[AiopNum];
2752        ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
2753        ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
2754        ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
2755        ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
2756        ChP->IndexData = AiopIO + _INDX_DATA;
2757     
2758        /* Channel direct addresses */
2759        ChIOOff = AiopIO + ChP->ChanNum * 2;
2760        ChP->TxRxData = ChIOOff + _TD0;
2761        ChP->ChanStat = ChIOOff + _CHN_STAT0;
2762        ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
2763        ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
2764     
2765        /* Initialize the channel from the RData array */
2766        for(i=0; i < RDATASIZE; i+=4)
2767        {
2768           R[0] = RData[i];
2769           R[1] = RData[i+1] + 0x10 * ChanNum;
2770           R[2] = RData[i+2];
2771           R[3] = RData[i+3];
2772           sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
2773        }
2774     
2775        ChR = ChP->R;
2776        for(i=0; i < RREGDATASIZE; i+=4)
2777        {
2778           ChR[i] = RRegData[i];
2779           ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
2780           ChR[i+2] = RRegData[i+2];
2781           ChR[i+3] = RRegData[i+3];
2782        }
2783     
2784        /* Indexed registers */
2785        ChOff = (Word_t)ChanNum * 0x1000;
2786     
2787        if (sClockPrescale == 0x14)
2788     	   brd9600 = 47;
2789        else
2790     	   brd9600 = 23;
2791     
2792        ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
2793        ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
2794        ChP->BaudDiv[2] = (Byte_t)brd9600;
2795        ChP->BaudDiv[3] = (Byte_t)(brd9600 >> 8);
2796        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
2797     
2798        ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
2799        ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
2800        ChP->TxControl[2] = 0;
2801        ChP->TxControl[3] = 0;
2802        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
2803     
2804        ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
2805        ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
2806        ChP->RxControl[2] = 0;
2807        ChP->RxControl[3] = 0;
2808        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
2809     
2810        ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
2811        ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
2812        ChP->TxEnables[2] = 0;
2813        ChP->TxEnables[3] = 0;
2814        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
2815     
2816        ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
2817        ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
2818        ChP->TxCompare[2] = 0;
2819        ChP->TxCompare[3] = 0;
2820        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
2821     
2822        ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
2823        ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
2824        ChP->TxReplace1[2] = 0;
2825        ChP->TxReplace1[3] = 0;
2826        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
2827     
2828        ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
2829        ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
2830        ChP->TxReplace2[2] = 0;
2831        ChP->TxReplace2[3] = 0;
2832        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
2833     
2834        ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
2835        ChP->TxFIFO = ChOff + _TX_FIFO;
2836     
2837        sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
2838        sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
2839        sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
2840        sOutW(ChP->IndexData,0);
2841        ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
2842        ChP->RxFIFO = ChOff + _RX_FIFO;
2843     
2844        sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
2845        sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
2846        sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
2847        sOutW(ChP->IndexData,0);
2848        sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
2849        sOutW(ChP->IndexData,0);
2850        ChP->TxPrioCnt = ChOff + _TXP_CNT;
2851        sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
2852        sOutB(ChP->IndexData,0);
2853        ChP->TxPrioPtr = ChOff + _TXP_PNTR;
2854        sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
2855        sOutB(ChP->IndexData,0);
2856        ChP->TxPrioBuf = ChOff + _TXP_BUF;
2857        sEnRxProcessor(ChP);                /* start the Rx processor */
2858     
2859        return(TRUE);
2860     }
2861     
2862     /***************************************************************************
2863     Function: sStopRxProcessor
2864     Purpose:  Stop the receive processor from processing a channel.
2865     Call:     sStopRxProcessor(ChP)
2866               CHANNEL_T *ChP; Ptr to channel structure
2867     
2868     Comments: The receive processor can be started again with sStartRxProcessor().
2869               This function causes the receive processor to skip over the
2870               stopped channel.  It does not stop it from processing other channels.
2871     
2872     Warnings: No context switches are allowed while executing this function.
2873     
2874               Do not leave the receive processor stopped for more than one
2875               character time.
2876     
2877               After calling this function a delay of 4 uS is required to ensure
2878               that the receive processor is no longer processing this channel.
2879     */
2880     void sStopRxProcessor(CHANNEL_T *ChP)
2881     {
2882        Byte_t R[4];
2883     
2884        R[0] = ChP->R[0];
2885        R[1] = ChP->R[1];
2886        R[2] = 0x0a;
2887        R[3] = ChP->R[3];
2888        sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
2889     }
2890     
2891     /***************************************************************************
2892     Function: sFlushRxFIFO
2893     Purpose:  Flush the Rx FIFO
2894     Call:     sFlushRxFIFO(ChP)
2895               CHANNEL_T *ChP; Ptr to channel structure
2896     Return:   void
2897     Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
2898               while it is being flushed the receive processor is stopped
2899               and the transmitter is disabled.  After these operations a
2900               4 uS delay is done before clearing the pointers to allow
2901               the receive processor to stop.  These items are handled inside
2902               this function.
2903     Warnings: No context switches are allowed while executing this function.
2904     */
2905     void sFlushRxFIFO(CHANNEL_T *ChP)
2906     {
2907        int i;
2908        Byte_t Ch;                   /* channel number within AIOP */
2909        int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
2910     
2911        if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
2912           return;                          /* don't need to flush */
2913     
2914        RxFIFOEnabled = FALSE;
2915        if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
2916        {
2917           RxFIFOEnabled = TRUE;
2918           sDisRxFIFO(ChP);                 /* disable it */
2919           for(i=0; i < 2000/200; i++)	/* delay 2 uS to allow proc to disable FIFO*/
2920              sInB(ChP->IntChan);		/* depends on bus i/o timing */
2921        }
2922        sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
2923        Ch = (Byte_t)sGetChanNum(ChP);
2924        sOutB(ChP->Cmd,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
2925        sOutB(ChP->Cmd,Ch);                 /* remove reset Rx FIFO count */
2926        sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
2927        sOutW(ChP->IndexData,0);
2928        sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
2929        sOutW(ChP->IndexData,0);
2930        if(RxFIFOEnabled)
2931           sEnRxFIFO(ChP);                  /* enable Rx FIFO */
2932     }
2933     
2934     /***************************************************************************
2935     Function: sFlushTxFIFO
2936     Purpose:  Flush the Tx FIFO
2937     Call:     sFlushTxFIFO(ChP)
2938               CHANNEL_T *ChP; Ptr to channel structure
2939     Return:   void
2940     Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
2941               while it is being flushed the receive processor is stopped
2942               and the transmitter is disabled.  After these operations a
2943               4 uS delay is done before clearing the pointers to allow
2944               the receive processor to stop.  These items are handled inside
2945               this function.
2946     Warnings: No context switches are allowed while executing this function.
2947     */
2948     void sFlushTxFIFO(CHANNEL_T *ChP)
2949     {
2950        int i;
2951        Byte_t Ch;                   /* channel number within AIOP */
2952        int TxEnabled;                      /* TRUE if transmitter enabled */
2953     
2954        if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
2955           return;                          /* don't need to flush */
2956     
2957        TxEnabled = FALSE;
2958        if(ChP->TxControl[3] & TX_ENABLE)
2959        {
2960           TxEnabled = TRUE;
2961           sDisTransmit(ChP);               /* disable transmitter */
2962        }
2963        sStopRxProcessor(ChP);              /* stop Rx processor */
2964        for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
2965           sInB(ChP->IntChan);	/* depends on bus i/o timing */
2966        Ch = (Byte_t)sGetChanNum(ChP);
2967        sOutB(ChP->Cmd,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
2968        sOutB(ChP->Cmd,Ch);                 /* remove reset Tx FIFO count */
2969        sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
2970        sOutW(ChP->IndexData,0);
2971        if(TxEnabled)
2972           sEnTransmit(ChP);                /* enable transmitter */
2973        sStartRxProcessor(ChP);             /* restart Rx processor */
2974     }
2975     
2976     /***************************************************************************
2977     Function: sWriteTxPrioByte
2978     Purpose:  Write a byte of priority transmit data to a channel
2979     Call:     sWriteTxPrioByte(ChP,Data)
2980               CHANNEL_T *ChP; Ptr to channel structure
2981               Byte_t Data; The transmit data byte
2982     
2983     Return:   int: 1 if the bytes is successfully written, otherwise 0.
2984     
2985     Comments: The priority byte is transmitted before any data in the Tx FIFO.
2986     
2987     Warnings: No context switches are allowed while executing this function.
2988     */
2989     int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
2990     {
2991        Byte_t DWBuf[4];             /* buffer for double word writes */
2992        Word_t *WordPtr;          /* must be far because Win SS != DS */
2993        register DWordIO_t IndexAddr;
2994     
2995        if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
2996        {
2997           IndexAddr = ChP->IndexAddr;
2998           sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
2999           if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
3000              return(0);                    /* nothing sent */
3001     
3002           WordPtr = (Word_t *)(&DWBuf[0]);
3003           *WordPtr = ChP->TxPrioBuf;       /* data byte address */
3004     
3005           DWBuf[2] = Data;                 /* data byte value */
3006           sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
3007     
3008           *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
3009     
3010           DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
3011           DWBuf[3] = 0;                    /* priority buffer pointer */
3012           sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
3013        }
3014        else                                /* write it to Tx FIFO */
3015        {
3016           sWriteTxByte(sGetTxRxDataIO(ChP),Data);
3017        }
3018        return(1);                          /* 1 byte sent */
3019     }
3020     
3021     /***************************************************************************
3022     Function: sEnInterrupts
3023     Purpose:  Enable one or more interrupts for a channel
3024     Call:     sEnInterrupts(ChP,Flags)
3025               CHANNEL_T *ChP; Ptr to channel structure
3026               Word_t Flags: Interrupt enable flags, can be any combination
3027                  of the following flags:
3028                     TXINT_EN:   Interrupt on Tx FIFO empty
3029                     RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
3030                                 sSetRxTrigger())
3031                     SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
3032                     MCINT_EN:   Interrupt on modem input change
3033                     CHANINT_EN: Allow channel interrupt signal to the AIOP's
3034                                 Interrupt Channel Register.
3035     Return:   void
3036     Comments: If an interrupt enable flag is set in Flags, that interrupt will be
3037               enabled.  If an interrupt enable flag is not set in Flags, that
3038               interrupt will not be changed.  Interrupts can be disabled with
3039               function sDisInterrupts().
3040     
3041               This function sets the appropriate bit for the channel in the AIOP's
3042               Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
3043               this channel's bit to be set in the AIOP's Interrupt Channel Register.
3044     
3045               Interrupts must also be globally enabled before channel interrupts
3046               will be passed on to the host.  This is done with function
3047               sEnGlobalInt().
3048     
3049               In some cases it may be desirable to disable interrupts globally but
3050               enable channel interrupts.  This would allow the global interrupt
3051               status register to be used to determine which AIOPs need service.
3052     */
3053     void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
3054     {
3055        Byte_t Mask;                 /* Interrupt Mask Register */
3056     
3057        ChP->RxControl[2] |=
3058           ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
3059     
3060        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
3061     
3062        ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
3063     
3064        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
3065     
3066        if(Flags & CHANINT_EN)
3067        {
3068           Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
3069           sOutB(ChP->IntMask,Mask);
3070        }
3071     }
3072     
3073     /***************************************************************************
3074     Function: sDisInterrupts
3075     Purpose:  Disable one or more interrupts for a channel
3076     Call:     sDisInterrupts(ChP,Flags)
3077               CHANNEL_T *ChP; Ptr to channel structure
3078               Word_t Flags: Interrupt flags, can be any combination
3079                  of the following flags:
3080                     TXINT_EN:   Interrupt on Tx FIFO empty
3081                     RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
3082                                 sSetRxTrigger())
3083                     SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
3084                     MCINT_EN:   Interrupt on modem input change
3085                     CHANINT_EN: Disable channel interrupt signal to the
3086                                 AIOP's Interrupt Channel Register.
3087     Return:   void
3088     Comments: If an interrupt flag is set in Flags, that interrupt will be
3089               disabled.  If an interrupt flag is not set in Flags, that
3090               interrupt will not be changed.  Interrupts can be enabled with
3091               function sEnInterrupts().
3092     
3093               This function clears the appropriate bit for the channel in the AIOP's
3094               Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
3095               this channel's bit from being set in the AIOP's Interrupt Channel
3096               Register.
3097     */
3098     void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
3099     {
3100        Byte_t Mask;                 /* Interrupt Mask Register */
3101     
3102        ChP->RxControl[2] &=
3103              ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
3104        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
3105        ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
3106        sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
3107     
3108        if(Flags & CHANINT_EN)
3109        {
3110           Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
3111           sOutB(ChP->IntMask,Mask);
3112        }
3113     }
3114