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