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