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