~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/char/rocket.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 #define NEW_MODULES
 50 #ifdef LOCAL_ROCKET_H           /* We're building standalone */
 51 #define MODULE
 52 #endif
 53 
 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 */
 63 
 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>
 71 
 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
 90         
 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 */
100 
101 #define ROCKET_PARANOIA_CHECK
102 #define ROCKET_SOFT_FLOW
103 
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
112         
113 
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.
123  */
124 
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. */
138 
139 #define _INLINE_ inline
140 
141 #ifndef NEW_MODULES
142 /*
143  * NB. we must include the kernel idenfication string in to install the module.
144  */
145 /*static*/ char kernel_version[] = UTS_RELEASE;
146 #endif
147 
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);
155 
156 static struct tty_driver rocket_driver, callout_driver;
157 static int rocket_refcount;
158 
159 static int rp_num_ports_open;
160 
161 static struct timer_list rocket_timer;
162 
163 unsigned long board1;
164 unsigned long board2;
165 unsigned long board3;
166 unsigned long board4;
167 unsigned long controller;
168 unsigned long support_low_speed;
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;
174 static unsigned long time_stat_short;
175 static unsigned long time_stat_long;
176 static unsigned long time_counter;
177 #endif
178 
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
195 
196 #if (LINUX_VERSION_CODE < 131336)
197 int copy_from_user(void *to, const void *from_user, unsigned long len)
198 {
199         int     error;
200 
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;
206 }
207 
208 int copy_to_user(void *to_user, const void *from, unsigned long len)
209 {
210         int     error;
211         
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;
217 }
218 
219 static inline int signal_pending(struct task_struct *p)
220 {
221         return (p->signal & ~p->blocked) != 0;
222 }
223 
224 #else
225 #include <asm/uaccess.h>
226 #endif
227 
228 /*
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.
236  */
237 static unsigned char *tmp_buf = 0;
238 static DECLARE_MUTEX(tmp_buf_sem);
239 
240 static void rp_start(struct tty_struct *tty);
241 
242 static inline int rocket_paranoia_check(struct r_port *info,
243                                         kdev_t device, const char *routine)
244 {
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;
253         }
254 #endif
255         return 0;
256 }
257 
258 /*
259  * Here begins the interrupt/polling routine for the Rocketport!
260  */
261 static _INLINE_ void rp_do_receive(struct r_port *info, struct tty_struct *tty,
262                                    CHANNEL_t *cp, unsigned int ChanStatus)
263 {
264         unsigned int CharNStat;
265         int ToRecv, wRecv, space, count;
266         unsigned char   *cbuf;
267         char            *fbuf;
268         
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;
279         
280         /*
281          * determine how many we can actually read in.  If we can't
282          * read any in then we have a software overrun condition.
283          */
284         if (ToRecv > space)
285                 ToRecv = space;
286         
287         /*
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).
291          */
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);
299                 }
300         }
301 
302         /* 
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
306          */
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));
314 
315 #ifdef ROCKET_DEBUG_RECEIVE
316                         printk("%x...", CharNStat);
317 #endif
318 
319                         if (CharNStat & STMBREAKH)
320                                 CharNStat &= ~(STMFRAMEH | STMPARITYH);
321                         if (CharNStat & info->ignore_status_mask) {
322                                 ToRecv--;
323                                 continue;
324                         }
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--;
343                 }
344 
345                 /*
346                  * after we've emptied the FIFO in status mode, turn
347                  * status mode back off
348                  */
349                 if (sGetRxCnt(cp) == 0) {
350 #ifdef ROCKET_DEBUG_RECEIVE
351                         printk("Status mode off.\n");
352 #endif
353                         sDisRxStatusMode(cp);
354                 }
355         } else {
356                 /*
357                  * we aren't in status mode, so read down the FIFO two
358                  * characters at time by doing repeated word IO
359                  * transfer.
360                  */
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;
371         }
372         tty->ldisc.receive_buf(tty, tty->flip.char_buf,
373                                tty->flip.flag_buf, count);
374 }
375 
376 /*
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.
380  */
381 static _INLINE_ void rp_do_transmit(struct r_port *info)
382 {
383         int     c;
384         CHANNEL_t *cp = &info->channel;
385         struct tty_struct *tty;
386         
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;
396         }
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
420         }
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);
428         }
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
433 }
434 
435 /*
436  * This function is called for each port which has signalled an
437  * interrupt.  It checks what interrupts are pending and services
438  * them. 
439  */
440 static _INLINE_ void rp_handle_port(struct r_port *info)
441 {
442         CHANNEL_t *cp;
443         struct tty_struct *tty;
444         unsigned int IntMask, ChanStatus;
445 
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;
451         }
452         if (!info->tty) {
453                 printk("rp: WARNING: rp_handle_port called with info->tty==NULL\n");
454                 return;
455         }
456         cp = &info->channel;
457         tty = info->tty;
458 
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);
466         }
467 #if 0
468         if (IntMask & SRC_INT) {        /* Special receive condition */
469         }
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);
485                 }
486                 info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
487                 wake_up_interruptible(&info->open_wait);
488         }
489 #ifdef ROCKET_DEBUG_INTR
490         if (IntMask & DELTA_CTS) {      /* CTS change */
491                 printk("CTS change...\n");
492         }
493         if (IntMask & DELTA_DSR) {      /* DSR change */
494                 printk("DSR change...\n");
495         }
496 #endif
497 }
498 
499 /*
500  * The top level polling routine.
501  */
502 static void rp_do_poll(unsigned long dummy)
503 {
504         CONTROLLER_t *ctlp;
505         int ctrl, aiop, ch, line;
506         unsigned int xmitmask;
507         unsigned char CtlMask, AiopMask;
508 
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;
512 
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 */
519 
520         for (ctrl=0; ctrl < max_board; ctrl++) {
521                 if (rcktpt_io_addr[ctrl] <= 0)
522                         continue;
523                 ctlp= sCtlNumToCtlPtr(ctrl);
524 
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]);
539                                         }
540                                 }
541                         }
542                 }
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]);
547                 }
548         }
549 
550         /*
551          * Reset the timer so we get called at the next clock tick.
552          */
553         if (rp_num_ports_open) {
554                 mod_timer(&rocket_timer, jiffies + 1);
555         }
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;
571         }
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;
588         }
589 #endif /* TIME_STAT */
590 }
591 /*
592  * Here ends the interrupt/polling routine.
593  */
594 
595 
596 /*
597  * This function initializes the r_port structure, as well as enabling
598  * the port on the RocketPort board.
599  */
600 static void init_r_port(int board, int aiop, int chan)
601 {
602         struct r_port *info;
603         int line;
604         CONTROLLER_T *ctlp;
605         CHANNEL_t       *cp;
606         
607         line = (board << 5) | (aiop << 3) | chan;
608 
609         ctlp= sCtlNumToCtlPtr(board);
610 
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;
615         }
616         memset(info, 0, sizeof(struct r_port));
617         
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);
630 
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;
638         }
639         cp = &info->channel;
640         rp_table[line] = info;
641 }
642 
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
649 
650 /*
651  * This routine configures a rocketport port so according to its
652  * termio settings.
653  */
654 static void configure_r_port(struct r_port *info)
655 {
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;
663         
664         if (!info->tty || !info->tty->termios)
665                 return;
666         cp = &info->channel;
667         cflag = info->tty->termios->c_cflag;
668 
669         /* Byte size and parity */
670         if ((cflag & CSIZE) == CS8) {
671                 sSetData8(cp);
672                 bits = 10;
673         } else {
674                 sSetData7(cp);
675                 bits = 9;
676         }
677         if (cflag & CSTOPB) {
678                 sSetStop2(cp);
679                 bits++;
680         } else {
681                 sSetStop1(cp);
682         }
683         
684         if (cflag & PARENB) {
685                 sEnParity(cp);
686                 bits++;
687                 if (cflag & PARODD) {
688                         sSetOddParity(cp);
689                 } else {
690                         sSetEvenParity(cp);
691                 }
692         } else {
693                 sDisParity(cp);
694         }
695         
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;
705         }
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;
715         }
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);
724         
725         if (cflag & CRTSCTS) {
726                 info->intmask |= DELTA_CTS;
727                 sEnCTSFlowCtl(cp);
728         } else {
729                 info->intmask &= ~DELTA_CTS;
730                 sDisCTSFlowCtl(cp);
731         }
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);
743         }
744 
745         /*
746          * Handle software flow control in the board
747          */
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);
755                 }
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);
762         }
763 #endif
764         
765         /*
766          * Set up ignore/read mask words
767          */
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;
773 
774         /*
775          * Characters to ignore
776          */
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;
782                 /*
783                  * If we're ignoring parity and break indicators,
784                  * ignore overruns too.  (For real raw support).
785                  */
786                 if (I_IGNPAR(info->tty))
787                         info->ignore_status_mask |= STMRCVROVRH;
788         }
789 }
790 
791 static int block_til_ready(struct tty_struct *tty, struct file * filp,
792                            struct r_port *info)
793 {
794         DECLARE_WAITQUEUE(wait, current);
795         int             retval;
796         int             do_clocal = 0, extra_count = 0;
797         unsigned long   flags;
798 
799         /*
800          * If the device is in the middle of being closed, then block
801          * until it's done, and then try again.
802          */
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);
810         }
811 
812         /*
813          * If this is a callout device, then just make sure the normal
814          * device isn't being used.
815          */
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;
829         }
830         
831         /*
832          * If non-blocking mode is set, or the port is not enabled,
833          * then make the check up front and then exit.
834          */
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;
841         }
842 
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;
849         }
850         
851         /*
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.
857          */
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--;
868         }
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);
876                 }
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;
885                 }
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;
894                 }
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();
900         }
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;
916 }       
917 
918 /*
919  * This routine is called whenever a rocketport board is opened.
920  */
921 static int rp_open(struct tty_struct *tty, struct file * filp)
922 {
923         struct r_port *info;
924         int     line, retval;
925         CHANNEL_t       *cp;
926         unsigned long page;
927         
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;
939         }
940         page = get_free_page(GFP_KERNEL);
941         if (!page)
942                 return -ENOMEM;
943 
944         tty->driver_data = info = rp_table[line];
945         
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);
951         }
952         
953         /*
954          * We must not sleep from here until the port is marked fully
955          * in use.
956          */
957         if (rp_table[line] == NULL) {
958                 tty->flags = (1 << TTY_IO_ERROR);
959                 free_page(page);
960                 return 0;
961         }
962         if (!info) {
963                 printk("rp_open: rp_table[%d] is NULL!\n", line);
964                 free_page(page);
965                 return -EIO;
966         }
967         if (info->xmit_buf)
968                 free_page(page);
969         else
970                 info->xmit_buf = (unsigned char *) page;
971         info->tty = tty;
972 
973         if (info->flags & ROCKET_CLOSING) {
974                 interruptible_sleep_on(&info->close_wait);
975                 return ((info->flags & ROCKET_HUP_NOTIFY) ? 
976                         -EAGAIN : -ERESTARTSYS);
977         }
978 
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
987         }
988 #ifdef ROCKET_DEBUG_OPEN
989         printk("rp_open ttyR%d, count=%d\n", info->line, info->count);
990 #endif
991         /*
992          * Info->count is now 1; so it's safe to sleep now.
993          */
994         info->session = current->session;
995         info->pgrp = current->pgrp;
996         
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);       
1006 
1007         sEnInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1008         sSetRxTrigger(cp, TRIG_1);
1009 
1010         sGetChanStatus(cp);
1011         sDisRxStatusMode(cp);
1012         sClrTxXOFF(cp);
1013 
1014         sDisCTSFlowCtl(cp);
1015         sDisTxSoftFlowCtl(cp);
1016 
1017         sEnRxFIFO(cp);
1018         sEnTransmit(cp);
1019 
1020         info->flags |= ROCKET_INITIALIZED;
1021 
1022 #if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
1023         /*
1024          * Set up the tty->alt_speed kludge
1025          */
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
1035 
1036         configure_r_port(info);
1037         if (tty->termios->c_cflag & CBAUD) {
1038                 sSetDTR(cp);
1039                 sSetRTS(cp);
1040         }
1041         
1042         mod_timer(&rocket_timer, jiffies + 1);
1043 
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;
1051         }
1052 
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);
1059         }
1060 
1061         return 0;
1062 }
1063 
1064 static void rp_close(struct tty_struct *tty, struct file * filp)
1065 {
1066         struct r_port * info = (struct r_port *)tty->driver_data;
1067         unsigned long flags;
1068         int timeout;
1069         CHANNEL_t       *cp;
1070 
1071         if (rocket_paranoia_check(info, tty->device, "rp_close"))
1072                 return;
1073 
1074 #ifdef ROCKET_DEBUG_OPEN
1075         printk("rp_close ttyR%d, count = %d\n", info->line, info->count);
1076 #endif
1077         
1078         save_flags(flags); cli();
1079         
1080         if (tty_hung_up_p(filp)) {
1081                 restore_flags(flags);
1082                 return;
1083         }
1084         if ((tty->count == 1) && (info->count != 1)) {
1085                 /*
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.
1091                  */
1092                 printk("rp_close: bad serial port count; tty->count is 1, "
1093                        "info->count is %d\n", info->count);
1094                 info->count = 1;
1095         }
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;
1100         }
1101         if (info->count) {
1102                 restore_flags(flags);
1103                 return;
1104         }
1105         info->flags |= ROCKET_CLOSING;
1106         /*
1107          * Save the termios structure, since this port may have
1108          * separate termios for callout and dialin.
1109          */
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;
1114         
1115         cp = &info->channel;
1116 
1117         /*
1118          * Notify the line discpline to only process XON/XOFF characters
1119          */
1120         tty->closing = 1;
1121 
1122         /*
1123          * If transmission was throttled by the application request,
1124          * just flush the xmit buffer.
1125          */
1126 #if (LINUX_VERSION_CODE >= 131343)
1127         if (tty->flow_stopped)
1128                 rp_flush_buffer(tty);
1129 #endif
1130 
1131         /*
1132          * Wait for the transmit buffer to clear
1133          */
1134         if (info->closing_wait != ROCKET_CLOSING_WAIT_NONE)
1135                 tty_wait_until_sent(tty, info->closing_wait);
1136         /*
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!
1140          */
1141         timeout = (sGetTxCnt(cp)+1) * HZ / info->cps;
1142         if (timeout == 0)
1143                 timeout = 1;
1144         rp_wait_until_sent(tty, timeout);
1145         
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);
1157         }
1158         if (tty->driver.flush_buffer)
1159                 tty->driver.flush_buffer(tty);
1160         if (tty->ldisc.flush_buffer)
1161                 tty->ldisc.flush_buffer(tty);
1162 
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);
1168                 }
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;
1174                 }
1175         }
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);
1180         
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);
1189         
1190 #ifdef ROCKET_DEBUG_OPEN
1191         printk("rp_close ttyR%d complete shutdown\n", info->line);
1192 #endif
1193         
1194 }
1195 
1196 static void rp_set_termios(struct tty_struct *tty, struct termios *old_termios)
1197 {
1198         struct r_port * info = (struct r_port *)tty->driver_data;
1199         CHANNEL_t *cp;
1200         unsigned cflag;
1201         
1202 
1203         if (rocket_paranoia_check(info, tty->device, "rp_set_termios"))
1204                 return;
1205 
1206         cflag = tty->termios->c_cflag;
1207 
1208         if (cflag == old_termios->c_cflag)
1209                 return;
1210 
1211         /*
1212          * This driver doesn't support CS5 or CS6
1213          */
1214         if (((cflag & CSIZE) == CS5) ||
1215             ((cflag & CSIZE) == CS6))
1216                 tty->termios->c_cflag = ((cflag & ~CSIZE) |
1217                                          (old_termios->c_cflag & CSIZE));
1218 
1219         configure_r_port(info);
1220 
1221         cp = &info->channel;
1222 
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);
1228         }
1229         
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);
1236                 }
1237                 sSetDTR(cp);
1238         }
1239         
1240         if ((old_termios->c_cflag & CRTSCTS) &&
1241             !(tty->termios->c_cflag & CRTSCTS)) {
1242                 tty->hw_stopped = 0;
1243                 rp_start(tty);
1244         }
1245 }
1246 
1247 /*
1248  * Here are the routines used by rp_ioctl
1249  */
1250 #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
1251 static void send_break( struct r_port * info, int duration)
1252 {
1253         current->state = TASK_INTERRUPTIBLE;
1254         cli();
1255         sSendBreak(&info->channel);
1256         schedule_timeout(duration);
1257         sClrBreak(&info->channel);
1258         sti();
1259 }
1260 #else
1261 static void rp_break(struct tty_struct *tty, int break_state)
1262 {
1263         struct r_port * info = (struct r_port *)tty->driver_data;
1264         unsigned long flags;
1265         
1266         if (rocket_paranoia_check(info, tty->device, "rp_break"))
1267                 return;
1268 
1269         save_flags(flags); cli();
1270         if (break_state == -1) {
1271                 sSendBreak(&info->channel);
1272         } else {
1273                 sClrBreak(&info->channel);
1274         }
1275         restore_flags(flags);
1276 }
1277 #endif
1278 
1279 static int get_modem_info(struct r_port * info, unsigned int *value)
1280 {
1281         unsigned int control, result, ChanStatus;
1282 
1283         ChanStatus = sGetChanStatusLo(&info->channel);
1284         
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);
1292 
1293         if (copy_to_user(value, &result, sizeof(int)))
1294                 return -EFAULT;
1295         return 0;
1296 }
1297 
1298 static int set_modem_info(struct r_port * info, unsigned int cmd,
1299                           unsigned int *value)
1300 {
1301         unsigned int arg;
1302 
1303         if (copy_from_user(&arg, value, sizeof(int)))
1304                 return -EFAULT;
1305 
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;
1327         }
1328 
1329         sOutDW(info->channel.IndexAddr,
1330                *(DWord_t *) &(info->channel.TxControl[0]));
1331         
1332         return 0;
1333 }
1334 
1335 static int get_config(struct r_port * info, struct rocket_config * retinfo)
1336 {
1337         struct rocket_config tmp;
1338   
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];
1347         
1348         if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
1349                 return -EFAULT;
1350         return 0;
1351 }
1352 
1353 static int set_config(struct r_port * info, struct rocket_config * new_info)
1354 {
1355         struct rocket_config new_serial;
1356 
1357         if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
1358                 return -EFAULT;
1359 
1360 #ifdef CAP_SYS_ADMIN
1361         if (!capable(CAP_SYS_ADMIN))
1362 #else
1363         if (!suser())
1364 #endif
1365         {
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;
1373         }
1374         
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;
1379 
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
1390         
1391         configure_r_port(info);
1392         return 0;
1393 }
1394 
1395 static int get_ports(struct r_port * info, struct rocket_ports * retports)
1396 {
1397         struct rocket_ports tmp;
1398         int     board, port, index;
1399   
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;
1410                 }
1411         }
1412         if (copy_to_user(retports,&tmp,sizeof(*retports)))
1413                 return -EFAULT;
1414         return 0;
1415 }
1416 
1417 static int rp_ioctl(struct tty_struct *tty, struct file * file,
1418                     unsigned int cmd, unsigned long arg)
1419 {
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
1424 
1425         if (cmd != RCKP_GET_PORTS &&
1426             rocket_paranoia_check(info, tty->device, "rp_ioctl"))
1427                 return -ENODEV;
1428 
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;
1442                         }
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;
1463 
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;
1480 
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);
1485                         
1486                 case RCKP_GET_PORTS:
1487                         return get_ports(info, (struct rocket_ports *) arg);
1488                 default:
1489                         return -ENOIOCTLCMD;
1490                 }
1491         return 0;
1492 }
1493 
1494 #if (defined(ROCKET_DEBUG_FLOW) || defined(ROCKET_DEBUG_THROTTLE))
1495 static char *rp_tty_name(struct tty_struct *tty, char *buf)
1496 {
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;
1504 }
1505 #endif
1506 
1507 static void rp_send_xchar(struct tty_struct *tty, char ch)
1508 {
1509         struct r_port *info = (struct r_port *)tty->driver_data;
1510         CHANNEL_t *cp;
1511 
1512         if (rocket_paranoia_check(info, tty->device, "rp_send_xchar"))
1513                 return;
1514 
1515         cp = &info->channel;
1516         if (sGetTxCnt(cp)) 
1517                 sWriteTxPrioByte(cp, ch);
1518         else
1519                 sWriteTxByte(sGetTxRxDataIO(cp), ch);
1520 }
1521 
1522 static void rp_throttle(struct tty_struct * tty)
1523 {
1524         struct r_port *info = (struct r_port *)tty->driver_data;
1525         CHANNEL_t *cp;
1526 #ifdef ROCKET_DEBUG_THROTTLE
1527         char    buf[64];
1528         
1529         printk("throttle %s: %d....\n", rp_tty_name(tty, buf),
1530                tty->ldisc.chars_in_buffer(tty));
1531 #endif
1532 
1533         if (rocket_paranoia_check(info, tty->device, "rp_throttle"))
1534                 return;
1535 
1536         cp = &info->channel;
1537         if (I_IXOFF(tty))
1538                 rp_send_xchar(tty, STOP_CHAR(tty));
1539         
1540         sClrRTS(&info->channel);
1541 }
1542 
1543 static void rp_unthrottle(struct tty_struct * tty)
1544 {
1545         struct r_port *info = (struct r_port *)tty->driver_data;
1546         CHANNEL_t *cp;
1547 #ifdef ROCKET_DEBUG_THROTTLE
1548         char    buf[64];
1549         
1550         printk("unthrottle %s: %d....\n", rp_tty_name(tty, buf),
1551                tty->ldisc.chars_in_buffer(tty));
1552 #endif
1553 
1554         if (rocket_paranoia_check(info, tty->device, "rp_throttle"))
1555                 return;
1556 
1557         cp = &info->channel;
1558         if (I_IXOFF(tty))
1559                 rp_send_xchar(tty, START_CHAR(tty));
1560 
1561         sSetRTS(&info->channel);
1562 }
1563 
1564 /*
1565  * ------------------------------------------------------------
1566  * rp_stop() and rp_start()
1567  *
1568  * This routines are called before setting or resetting tty->stopped.
1569  * They enable or disable transmitter interrupts, as necessary.
1570  * ------------------------------------------------------------
1571  */
1572 static void rp_stop(struct tty_struct *tty)
1573 {
1574         struct r_port * info = (struct r_port *)tty->driver_data;
1575 #ifdef ROCKET_DEBUG_FLOW
1576         char    buf[64];
1577         
1578         printk("stop %s: %d %d....\n", rp_tty_name(tty, buf),
1579                info->xmit_cnt, info->xmit_fifo_room);
1580 #endif
1581 
1582         if (rocket_paranoia_check(info, tty->device, "rp_stop"))
1583                 return;
1584 
1585         if (sGetTxCnt(&info->channel))
1586                 sDisTransmit(&info->channel);
1587 }
1588 
1589 static void rp_start(struct tty_struct *tty)
1590 {
1591         struct r_port * info = (struct r_port *)tty->driver_data;
1592 #ifdef ROCKET_DEBUG_FLOW
1593         char    buf[64];
1594         
1595         printk("start %s: %d %d....\n", rp_tty_name(tty, buf),
1596                info->xmit_cnt, info->xmit_fifo_room);
1597 #endif
1598 
1599         if (rocket_paranoia_check(info, tty->device, "rp_stop"))
1600                 return;
1601 
1602         sEnTransmit(&info->channel);
1603         xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
1604 }
1605 
1606 /*
1607  * rp_wait_until_sent() --- wait until the transmitter is empty
1608  */
1609 static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
1610 {
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;
1616         
1617         if (rocket_paranoia_check(info, tty->device, "rp_wait_until_sent"))
1618                 return;
1619 
1620         cp = &info->channel;
1621 
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;
1641                 }
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;
1652         }
1653         current->state = TASK_RUNNING;
1654 #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1655         printk("txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
1656 #endif
1657 }
1658 
1659 /*
1660  * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
1661  */
1662 static void rp_hangup(struct tty_struct *tty)
1663 {
1664         CHANNEL_t       *cp;
1665         struct r_port * info = (struct r_port *)tty->driver_data;
1666         
1667         if (rocket_paranoia_check(info, tty->device, "rp_hangup"))
1668                 return;
1669 
1670 #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
1671         printk("rp_hangup of ttyR%d...", info->line);
1672 #endif
1673         /*
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.
1677          */
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;
1684         }
1685         if (info->count) {
1686 #ifdef MODULE
1687                 MOD_DEC_USE_COUNT;
1688 #endif
1689                 rp_num_ports_open--;
1690         }
1691         
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;
1696 
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;
1705         
1706         wake_up_interruptible(&info->open_wait);
1707 }
1708 
1709 /*
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.
1714  *
1715  * This gets a little tricky, but I'm pretty sure I got it all right.
1716  */
1717 static void rp_put_char(struct tty_struct *tty, unsigned char ch)
1718 {
1719         struct r_port * info = (struct r_port *)tty->driver_data;
1720         CHANNEL_t       *cp;
1721 
1722         if (rocket_paranoia_check(info, tty->device, "rp_put_char"))
1723                 return;
1724 
1725 #ifdef ROCKET_DEBUG_WRITE
1726         printk("rp_put_char %c...", ch);
1727 #endif
1728         
1729         cp = &info->channel;
1730 
1731         if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
1732                 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1733 
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--;
1743         }
1744 }
1745 
1746 static int rp_write(struct tty_struct * tty, int from_user,
1747                     const unsigned char *buf, int count)
1748 {
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;
1754 
1755         if (count <= 0 || rocket_paranoia_check(info, tty->device, "rp_write"))
1756                 return 0;
1757 
1758 #ifdef ROCKET_DEBUG_WRITE
1759         printk("rp_write %d chars...", count);
1760 #endif
1761         cp = &info->channel;
1762 
1763         if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
1764                 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1765 
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;
1779                         }
1780                         if (info->tty == 0)
1781                                 goto end;
1782                         c = MIN(c, info->xmit_fifo_room);
1783                 }
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;
1791         }
1792         if (!count)
1793                 goto end;
1794         
1795         save_flags(flags);
1796         while (1) {
1797                 if (info->tty == 0) {
1798                         restore_flags(flags);
1799                         goto end;
1800                 }
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;
1805 
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;
1816                         }
1817                         /* In case we got pre-empted */
1818                         if (info->tty == 0)
1819                                 goto end_intr;
1820                 }
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;
1831         }
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);
1842         }
1843         return retval;
1844 }
1845 
1846 /*
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.
1850  */
1851 static int rp_write_room(struct tty_struct *tty)
1852 {
1853         struct r_port * info = (struct r_port *)tty->driver_data;
1854         int     ret;
1855 
1856         if (rocket_paranoia_check(info, tty->device, "rp_write_room"))
1857                 return 0;
1858 
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;
1866 }
1867 
1868 /*
1869  * Return the number of characters in the buffer.  Again, this only
1870  * counts those characters in the in-memory transmit buffer.
1871  */
1872 static int rp_chars_in_buffer(struct tty_struct *tty)
1873 {
1874         struct r_port * info = (struct r_port *)tty->driver_data;
1875         CHANNEL_t       *cp;
1876 
1877         if (rocket_paranoia_check(info, tty->device, "rp_chars_in_buffer"))
1878                 return 0;
1879 
1880         cp = &info->channel;
1881 
1882 #ifdef ROCKET_DEBUG_WRITE
1883         printk("rp_chars_in_buffer returns %d...", info->xmit_cnt);
1884 #endif
1885         return info->xmit_cnt;
1886 }
1887 
1888 static void rp_flush_buffer(struct tty_struct *tty)
1889 {
1890         struct r_port * info = (struct r_port *)tty->driver_data;
1891         CHANNEL_t       *cp;
1892 
1893         if (rocket_paranoia_check(info, tty->device, "rp_flush_buffer"))
1894                 return;
1895 
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);
1903         
1904         cp = &info->channel;
1905         
1906         sFlushTxFIFO(cp);
1907 }
1908 
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)
1914 {
1915         unsigned short          vendor_id, device_id;
1916         int                     ret, error;
1917         static struct pci_dev   ret_struct;
1918         
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;
1925 
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);
1931         }
1932 
1933         memset(&ret_struct, 0, sizeof(ret_struct));
1934         ret_struct.device = device_id;
1935 
1936         return &ret_struct;
1937 }
1938 #endif
1939      
1940 int __init register_PCI(int i, unsigned int bus, unsigned int device_fn)
1941 {
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
1951 
1952         if (!dev)
1953                 return 0;
1954 
1955         if (pci_enable_device(dev))
1956                 return 0;
1957 
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;
2000         }
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);
2013         }
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);
2020         }
2021         return(1);
2022 }
2023 
2024 static int __init init_PCI(int boards_found)
2025 {
2026         unsigned char   bus, device_fn;
2027         int     i, count = 0;
2028 
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++;
2074         }
2075         return(count);
2076 }
2077 #endif
2078 
2079 static int __init init_ISA(int i, int *reserved_controller)
2080 {
2081         int     num_aiops, num_chan;
2082         int     aiop, chan;
2083         unsigned int    aiopio[MAX_AIOPS_PER_BOARD];    
2084         CONTROLLER_t    *ctlp;
2085 
2086         if (rcktpt_io_addr[i] == 0)
2087                 return(0);
2088 
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);
2094         }
2095         
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);
2105         }
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);
2112         }
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");
2123         }
2124         return(1);
2125 }
2126 
2127 
2128 /*
2129  * The module "startup" routine; it's run when the module is loaded.
2130  */
2131 int __init rp_init(void)
2132 {
2133         int i, retval, pci_boards_found, isa_boards_found;
2134         int     reserved_controller = 0;
2135 
2136         printk("Rocketport device driver module, version %s, %s\n",
2137                ROCKET_VERSION, ROCKET_DATE);
2138 
2139         /*
2140          * Set up the timer channel.  If it is already in use by
2141          * some other driver, give up.
2142          */
2143         if (rocket_timer.function) {
2144                 printk("rocket.o: Timer already in use!\n");
2145                 return -EBUSY;
2146         }
2147         init_timer(&rocket_timer);
2148         rocket_timer.function = rp_do_poll;
2149         
2150         /*
2151          * Initialize the array of pointers to our own internal state
2152          * structures.
2153          */
2154         memset(rp_table, 0, sizeof(rp_table));
2155         memset(xmit_flags, 0, sizeof(xmit_flags));
2156 
2157         if (board1 == 0)
2158                 board1 = 0x180;
2159         if (controller == 0)
2160                 controller = board1 + 0x40;
2161 
2162         if (check_region(controller, 4)) {
2163                 printk("Controller IO addresses in use, unloading driver.\n");
2164                 return -EBUSY;
2165         }
2166         
2167         rcktpt_io_addr[0] = board1;
2168         rcktpt_io_addr[1] = board2;
2169         rcktpt_io_addr[2] = board3;
2170         rcktpt_io_addr[3] = board4;
2171 
2172         /*
2173          * If support_low_speed is set, use the slow clock prescale,
2174          * which supports 50 bps
2175          */
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;
2182         }
2183         
2184         /*
2185          * OK, let's probe each of the controllers looking for boards.
2186          */
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++;
2192         }
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");
2199         }
2200 #endif
2201         max_board = pci_boards_found + isa_boards_found;
2202         
2203         if (max_board == 0) {
2204                 printk("No rocketport ports found; unloading driver.\n");
2205                 rocket_timer.function = 0;
2206                 return -ENODEV;
2207         }
2208 
2209         if (reserved_controller == 0)
2210                 request_region(controller, 4, "Comtrol Rocketport");
2211 
2212         /*
2213          * Set up the tty driver structure and then register this
2214          * driver with the tty layer.
2215          */
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;
2232 
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
2254 
2255         /*
2256          * The callout device is just like normal device except for
2257          * the minor number and the subtype code.
2258          */
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;
2264         
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;
2270         }
2271 
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;
2277         }
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
2282 
2283         return 0;
2284 }
2285 
2286 #ifdef MODULE
2287 int init_module(void)
2288 {
2289         return rp_init();
2290 }
2291 
2292 void
2293 cleanup_module( void) {
2294         int     retval;
2295         int     i;
2296         int     released_controller = 0;
2297 
2298         del_timer_sync(&rocket_timer);
2299 
2300         retval = tty_unregister_driver(&callout_driver);
2301         if (retval) {
2302                 printk("Error %d while trying to unregister "
2303                        "rocketport callout driver\n", -retval);
2304         }
2305         retval = tty_unregister_driver(&rocket_driver);
2306         if (retval) {
2307                 printk("Error %d while trying to unregister "
2308                        "rocketport driver\n", -retval);
2309         }
2310         for (i = 0; i < MAX_RP_PORTS; i++) {
2311                 if (rp_table[i])
2312                         kfree(rp_table[i]);
2313         }
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);
2324         }
2325         if (tmp_buf)
2326                 free_page((unsigned long) tmp_buf);
2327         rocket_timer.function = 0;
2328 }
2329 #endif
2330 
2331 /***********************************************************************
2332                 Copyright 1994 Comtrol Corporation.
2333                         All Rights Reserved.
2334 
2335 The following source code is subject to Comtrol Corporation's
2336 Developer's License Agreement.
2337 
2338 This source code is protected by United States copyright law and 
2339 international copyright treaties.
2340 
2341 This source code may only be used to develop software products that
2342 will operate with Comtrol brand hardware.
2343 
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.
2347 
2348 The portions of this source code which you use in your derivative
2349 work must bear Comtrol's copyright notice:
2350 
2351                 Copyright 1994 Comtrol Corporation.
2352 
2353 ***********************************************************************/
2354 
2355 #ifndef TRUE
2356 #define TRUE 1
2357 #endif
2358 
2359 #ifndef FALSE
2360 #define FALSE 0
2361 #endif
2362 
2363 static Byte_t RData[RDATASIZE] =
2364 {
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 
2383 };
2384 
2385 static Byte_t RRegData[RREGDATASIZE]=
2386 {
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 */
2400 };
2401 
2402 CONTROLLER_T sController[CTL_SIZE] =
2403 {
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}}
2408 };
2409 
2410 #if 0
2411 /* IRQ number to MUDBAC register 2 mapping */
2412 Byte_t sIRQMap[16] =
2413 {
2414    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
2415 };
2416 #endif
2417 
2418 Byte_t sBitMapClrTbl[8] =
2419 {
2420    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
2421 };
2422 
2423 Byte_t sBitMapSetTbl[8] =
2424 {
2425    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
2426 };
2427 
2428 int sClockPrescale = 0x14;
2429 
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.
2473 
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.
2477 
2478           If interrupts are to be completely disabled set IRQNum to 0.
2479 
2480           Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
2481           invalid combination.
2482 
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.
2488 
2489           Even if interrupts are globally enabled, they must also be
2490           individually enabled for each channel that is to generate
2491           interrupts.
2492 
2493 Warnings: No range checking on any of the parameters is done.
2494 
2495           No context switches are allowed while executing this function.
2496 
2497           After this function all AIOPs on the controller are disabled,
2498           they can be enabled with sEnAiop().
2499 */
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)
2508 {
2509         int             i;
2510         ByteIO_t        io;
2511 
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 */
2524    {
2525       CtlP->MReg2 = 0;                 /* interrupt disable */
2526       CtlP->MReg3 = 0;                 /* no periodic interrupts */
2527    }
2528    else
2529    {
2530       CtlP->MReg2 = sIRQMap[IRQNum];   /* set IRQ number */
2531       CtlP->MReg3 = Frequency;         /* set frequency */
2532       if(PeriodicOnly)                 /* periodic interrupt only */
2533       {
2534          CtlP->MReg3 |= PERIODIC_ONLY;
2535       }
2536    }
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++)
2544    {
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 */
2551 
2552       CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
2553       if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
2554       {
2555          sDisAiop(CtlP,i);                     /* disable AIOP */
2556          break;                                /* done looking for AIOPs */
2557       }
2558 
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 */
2564    }
2565 
2566    if(CtlP->NumAiop == 0)
2567       return(-1);
2568    else
2569       return(CtlP->NumAiop);
2570 }
2571 
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.
2614 
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.
2618 
2619           If interrupts are to be completely disabled set IRQNum to 0.
2620 
2621           Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
2622           invalid combination.
2623 
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.
2629 
2630           Even if interrupts are globally enabled, they must also be
2631           individually enabled for each channel that is to generate
2632           interrupts.
2633 
2634 Warnings: No range checking on any of the parameters is done.
2635 
2636           No context switches are allowed while executing this function.
2637 
2638           After this function all AIOPs on the controller are disabled,
2639           they can be enabled with sEnAiop().
2640 */
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)
2648 {
2649         int             i;
2650         ByteIO_t        io;
2651 
2652    CtlP->CtlNum = CtlNum;
2653    CtlP->CtlID = CTLID_0001;        /* controller release 1 */
2654    CtlP->BusType = isPCI;        /* controller release 1 */
2655 
2656    CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
2657 
2658    sPCIControllerEOI(CtlP);               /* clear EOI if warm init */
2659    /* Init AIOPs */
2660    CtlP->NumAiop = 0;
2661    for(i=0; i < AiopIOListSize; i++)
2662    {
2663       io = AiopIOList[i];
2664       CtlP->AiopIO[i] = (WordIO_t)io;
2665       CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2666 
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 */
2670 
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 */
2675    }
2676 
2677    if(CtlP->NumAiop == 0)
2678       return(-1);
2679    else
2680       return(CtlP->NumAiop);
2681 }
2682 
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.
2692 
2693 */
2694 int sReadAiopID(ByteIO_t io)
2695 {
2696    Byte_t AiopID;               /* ID byte from AIOP */
2697 
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);
2705 }
2706 
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.
2719 */
2720 int sReadAiopNumChan(WordIO_t io)
2721 {
2722    Word_t x;
2723 
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);
2732 }
2733 
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.
2746 
2747           No context switches are allowed while executing this function.
2748 */
2749 int sInitChan(  CONTROLLER_T *CtlP,
2750                 CHANNEL_T *ChP,
2751                 int AiopNum,
2752                 int ChanNum)
2753 {
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;
2761 
2762    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
2763       return(FALSE);                   /* exceeds num chans in AIOP */
2764 
2765    /* Channel, AIOP, and controller identifiers */
2766    ChP->CtlP = CtlP;
2767    ChP->ChanID = CtlP->AiopID[AiopNum];
2768    ChP->AiopNum = AiopNum;
2769    ChP->ChanNum = ChanNum;
2770 
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;
2778 
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;
2785 
2786    /* Initialize the channel from the RData array */
2787    for(i=0; i < RDATASIZE; i+=4)
2788    {
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]));
2794    }
2795 
2796    ChR = ChP->R;
2797    for(i=0; i < RREGDATASIZE; i+=4)
2798    {
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];
2803    }
2804 
2805    /* Indexed registers */
2806    ChOff = (Word_t)ChanNum * 0x1000;
2807 
2808    if (sClockPrescale == 0x14)
2809            brd9600 = 47;
2810    else
2811            brd9600 = 23;
2812 
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]);
2818 
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]);
2824 
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]);
2830 
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]);
2836 
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]);
2842 
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]);
2848 
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]);
2854 
2855    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
2856    ChP->TxFIFO = ChOff + _TX_FIFO;
2857 
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;
2864 
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 */
2879 
2880    return(TRUE);
2881 }
2882 
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
2888 
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.
2892 
2893 Warnings: No context switches are allowed while executing this function.
2894 
2895           Do not leave the receive processor stopped for more than one
2896           character time.
2897 
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.
2900 */
2901 void sStopRxProcessor(CHANNEL_T *ChP)
2902 {
2903    Byte_t R[4];
2904 
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]);
2910 }
2911 
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.
2925 */
2926 void sFlushRxFIFO(CHANNEL_T *ChP)
2927 {
2928    int i;
2929    Byte_t Ch;                   /* channel number within AIOP */
2930    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
2931 
2932    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
2933       return;                          /* don't need to flush */
2934 
2935    RxFIFOEnabled = FALSE;
2936    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
2937    {
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 */
2942    }
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 */
2953 }
2954 
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.
2968 */
2969 void sFlushTxFIFO(CHANNEL_T *ChP)
2970 {
2971    int i;
2972    Byte_t Ch;                   /* channel number within AIOP */
2973    int TxEnabled;                      /* TRUE if transmitter enabled */
2974 
2975    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
2976       return;                          /* don't need to flush */
2977 
2978    TxEnabled = FALSE;
2979    if(ChP->TxControl[3] & TX_ENABLE)
2980    {
2981       TxEnabled = TRUE;
2982       sDisTransmit(ChP);               /* disable transmitter */
2983    }
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 */
2995 }
2996 
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
3003 
3004 Return:   int: 1 if the bytes is successfully written, otherwise 0.
3005 
3006 Comments: The priority byte is transmitted before any data in the Tx FIFO.
3007 
3008 Warnings: No context switches are allowed while executing this function.
3009 */
3010 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
3011 {
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;
3015 
3016    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
3017    {
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 */
3022 
3023       WordPtr = (Word_t *)(&DWBuf[0]);
3024       *WordPtr = ChP->TxPrioBuf;       /* data byte address */
3025 
3026       DWBuf[2] = Data;                 /* data byte value */
3027       sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
3028 
3029       *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
3030 
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 */
3034    }
3035    else                                /* write it to Tx FIFO */
3036    {
3037       sWriteTxByte(sGetTxRxDataIO(ChP),Data);
3038    }
3039    return(1);                          /* 1 byte sent */
3040 }
3041 
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().
3061 
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.
3065 
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().
3069 
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.
3073 */
3074 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
3075 {
3076    Byte_t Mask;                 /* Interrupt Mask Register */
3077 
3078    ChP->RxControl[2] |=
3079       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
3080 
3081    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
3082 
3083    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
3084 
3085    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
3086 
3087    if(Flags & CHANINT_EN)
3088    {
3089       Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
3090       sOutB(ChP->IntMask,Mask);
3091    }
3092 }
3093 
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().
3113 
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.
3118 */
3119 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
3120 {
3121    Byte_t Mask;                 /* Interrupt Mask Register */
3122 
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]);
3128 
3129    if(Flags & CHANINT_EN)
3130    {
3131       Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
3132       sOutB(ChP->IntMask,Mask);
3133    }
3134 }
3135 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.