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