[PATCH] freepgt: remove MM_VM_SIZE(mm)
[linux-2.6/kvm.git] / drivers / char / rocket.c
blob5bcbeb0cb9ae8988f09174821ad246d287a1d609
1 /*
2 * RocketPort device driver for Linux
4 * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000.
5 *
6 * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * Kernel Synchronization:
26 * This driver has 2 kernel control paths - exception handlers (calls into the driver
27 * from user mode) and the timer bottom half (tasklet). This is a polled driver, interrupts
28 * are not used.
30 * Critical data:
31 * - rp_table[], accessed through passed "info" pointers, is a global (static) array of
32 * serial port state information and the xmit_buf circular buffer. Protected by
33 * a per port spinlock.
34 * - xmit_flags[], an array of ints indexed by line (port) number, indicating that there
35 * is data to be transmitted. Protected by atomic bit operations.
36 * - rp_num_ports, int indicating number of open ports, protected by atomic operations.
38 * rp_write() and rp_write_char() functions use a per port semaphore to protect against
39 * simultaneous access to the same port by more than one process.
42 /****** Defines ******/
43 #ifdef PCI_NUM_RESOURCES
44 #define PCI_BASE_ADDRESS(dev, r) ((dev)->resource[r].start)
45 #else
46 #define PCI_BASE_ADDRESS(dev, r) ((dev)->base_address[r])
47 #endif
49 #define ROCKET_PARANOIA_CHECK
50 #define ROCKET_DISABLE_SIMUSAGE
52 #undef ROCKET_SOFT_FLOW
53 #undef ROCKET_DEBUG_OPEN
54 #undef ROCKET_DEBUG_INTR
55 #undef ROCKET_DEBUG_WRITE
56 #undef ROCKET_DEBUG_FLOW
57 #undef ROCKET_DEBUG_THROTTLE
58 #undef ROCKET_DEBUG_WAIT_UNTIL_SENT
59 #undef ROCKET_DEBUG_RECEIVE
60 #undef ROCKET_DEBUG_HANGUP
61 #undef REV_PCI_ORDER
62 #undef ROCKET_DEBUG_IO
64 #define POLL_PERIOD HZ/100 /* Polling period .01 seconds (10ms) */
66 /****** Kernel includes ******/
68 #ifdef MODVERSIONS
69 #include <config/modversions.h>
70 #endif
72 #include <linux/module.h>
73 #include <linux/errno.h>
74 #include <linux/major.h>
75 #include <linux/kernel.h>
76 #include <linux/signal.h>
77 #include <linux/slab.h>
78 #include <linux/mm.h>
79 #include <linux/sched.h>
80 #include <linux/timer.h>
81 #include <linux/interrupt.h>
82 #include <linux/tty.h>
83 #include <linux/tty_driver.h>
84 #include <linux/tty_flip.h>
85 #include <linux/string.h>
86 #include <linux/fcntl.h>
87 #include <linux/ptrace.h>
88 #include <linux/ioport.h>
89 #include <linux/delay.h>
90 #include <linux/wait.h>
91 #include <linux/pci.h>
92 #include <asm/uaccess.h>
93 #include <asm/atomic.h>
94 #include <linux/bitops.h>
95 #include <linux/spinlock.h>
96 #include <asm/semaphore.h>
97 #include <linux/init.h>
99 /****** RocketPort includes ******/
101 #include "rocket_int.h"
102 #include "rocket.h"
104 #define ROCKET_VERSION "2.09"
105 #define ROCKET_DATE "12-June-2003"
107 /****** RocketPort Local Variables ******/
109 static struct tty_driver *rocket_driver;
111 static struct rocket_version driver_version = {
112 ROCKET_VERSION, ROCKET_DATE
115 static struct r_port *rp_table[MAX_RP_PORTS]; /* The main repository of serial port state information. */
116 static unsigned int xmit_flags[NUM_BOARDS]; /* Bit significant, indicates port had data to transmit. */
117 /* eg. Bit 0 indicates port 0 has xmit data, ... */
118 static atomic_t rp_num_ports_open; /* Number of serial ports open */
119 static struct timer_list rocket_timer;
121 static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */
122 static unsigned long board2;
123 static unsigned long board3;
124 static unsigned long board4;
125 static unsigned long controller;
126 static int support_low_speed;
127 static unsigned long modem1;
128 static unsigned long modem2;
129 static unsigned long modem3;
130 static unsigned long modem4;
131 static unsigned long pc104_1[8];
132 static unsigned long pc104_2[8];
133 static unsigned long pc104_3[8];
134 static unsigned long pc104_4[8];
135 static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 };
137 static int rp_baud_base[NUM_BOARDS]; /* Board config info (Someday make a per-board structure) */
138 static unsigned long rcktpt_io_addr[NUM_BOARDS];
139 static int rcktpt_type[NUM_BOARDS];
140 static int is_PCI[NUM_BOARDS];
141 static rocketModel_t rocketModel[NUM_BOARDS];
142 static int max_board;
145 * The following arrays define the interrupt bits corresponding to each AIOP.
146 * These bits are different between the ISA and regular PCI boards and the
147 * Universal PCI boards.
150 static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
151 AIOP_INTR_BIT_0,
152 AIOP_INTR_BIT_1,
153 AIOP_INTR_BIT_2,
154 AIOP_INTR_BIT_3
157 static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
158 UPCI_AIOP_INTR_BIT_0,
159 UPCI_AIOP_INTR_BIT_1,
160 UPCI_AIOP_INTR_BIT_2,
161 UPCI_AIOP_INTR_BIT_3
165 * Line number is the ttySIx number (x), the Minor number. We
166 * assign them sequentially, starting at zero. The following
167 * array keeps track of the line number assigned to a given board/aiop/channel.
169 static unsigned char lineNumbers[MAX_RP_PORTS];
170 static unsigned long nextLineNumber;
172 /***** RocketPort Static Prototypes *********/
173 static int __init init_ISA(int i);
174 static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
175 static void rp_flush_buffer(struct tty_struct *tty);
176 static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
177 static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
178 static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
179 static void rp_start(struct tty_struct *tty);
181 #ifdef MODULE
182 MODULE_AUTHOR("Theodore Ts'o");
183 MODULE_DESCRIPTION("Comtrol RocketPort driver");
184 module_param(board1, ulong, 0);
185 MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
186 module_param(board2, ulong, 0);
187 MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
188 module_param(board3, ulong, 0);
189 MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
190 module_param(board4, ulong, 0);
191 MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
192 module_param(controller, ulong, 0);
193 MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
194 module_param(support_low_speed, bool, 0);
195 MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud");
196 module_param(modem1, ulong, 0);
197 MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem");
198 module_param(modem2, ulong, 0);
199 MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem");
200 module_param(modem3, ulong, 0);
201 MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem");
202 module_param(modem4, ulong, 0);
203 MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem");
204 module_param_array(pc104_1, ulong, NULL, 0);
205 MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,...");
206 module_param_array(pc104_2, ulong, NULL, 0);
207 MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,...");
208 module_param_array(pc104_3, ulong, NULL, 0);
209 MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,...");
210 module_param_array(pc104_4, ulong, NULL, 0);
211 MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
213 int rp_init(void);
214 static void rp_cleanup_module(void);
216 module_init(rp_init);
217 module_exit(rp_cleanup_module);
219 #endif
221 #ifdef MODULE_LICENSE
222 MODULE_LICENSE("Dual BSD/GPL");
223 #endif
225 /*************************************************************************/
226 /* Module code starts here */
228 static inline int rocket_paranoia_check(struct r_port *info,
229 const char *routine)
231 #ifdef ROCKET_PARANOIA_CHECK
232 if (!info)
233 return 1;
234 if (info->magic != RPORT_MAGIC) {
235 printk(KERN_INFO "Warning: bad magic number for rocketport struct in %s\n",
236 routine);
237 return 1;
239 #endif
240 return 0;
244 /* Serial port receive data function. Called (from timer poll) when an AIOPIC signals
245 * that receive data is present on a serial port. Pulls data from FIFO, moves it into the
246 * tty layer.
248 static void rp_do_receive(struct r_port *info,
249 struct tty_struct *tty,
250 CHANNEL_t * cp, unsigned int ChanStatus)
252 unsigned int CharNStat;
253 int ToRecv, wRecv, space = 0, count;
254 unsigned char *cbuf;
255 char *fbuf;
256 struct tty_ldisc *ld;
258 ld = tty_ldisc_ref(tty);
260 ToRecv = sGetRxCnt(cp);
261 if (ld)
262 space = ld->receive_room(tty);
263 if (space > 2 * TTY_FLIPBUF_SIZE)
264 space = 2 * TTY_FLIPBUF_SIZE;
265 cbuf = tty->flip.char_buf;
266 fbuf = tty->flip.flag_buf;
267 count = 0;
268 #ifdef ROCKET_DEBUG_INTR
269 printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space);
270 #endif
273 * determine how many we can actually read in. If we can't
274 * read any in then we have a software overrun condition.
276 if (ToRecv > space)
277 ToRecv = space;
279 if (ToRecv <= 0)
280 return;
283 * if status indicates there are errored characters in the
284 * FIFO, then enter status mode (a word in FIFO holds
285 * character and status).
287 if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
288 if (!(ChanStatus & STATMODE)) {
289 #ifdef ROCKET_DEBUG_RECEIVE
290 printk(KERN_INFO "Entering STATMODE...");
291 #endif
292 ChanStatus |= STATMODE;
293 sEnRxStatusMode(cp);
298 * if we previously entered status mode, then read down the
299 * FIFO one word at a time, pulling apart the character and
300 * the status. Update error counters depending on status
302 if (ChanStatus & STATMODE) {
303 #ifdef ROCKET_DEBUG_RECEIVE
304 printk(KERN_INFO "Ignore %x, read %x...", info->ignore_status_mask,
305 info->read_status_mask);
306 #endif
307 while (ToRecv) {
308 CharNStat = sInW(sGetTxRxDataIO(cp));
309 #ifdef ROCKET_DEBUG_RECEIVE
310 printk(KERN_INFO "%x...", CharNStat);
311 #endif
312 if (CharNStat & STMBREAKH)
313 CharNStat &= ~(STMFRAMEH | STMPARITYH);
314 if (CharNStat & info->ignore_status_mask) {
315 ToRecv--;
316 continue;
318 CharNStat &= info->read_status_mask;
319 if (CharNStat & STMBREAKH)
320 *fbuf++ = TTY_BREAK;
321 else if (CharNStat & STMPARITYH)
322 *fbuf++ = TTY_PARITY;
323 else if (CharNStat & STMFRAMEH)
324 *fbuf++ = TTY_FRAME;
325 else if (CharNStat & STMRCVROVRH)
326 *fbuf++ = TTY_OVERRUN;
327 else
328 *fbuf++ = 0;
329 *cbuf++ = CharNStat & 0xff;
330 count++;
331 ToRecv--;
335 * after we've emptied the FIFO in status mode, turn
336 * status mode back off
338 if (sGetRxCnt(cp) == 0) {
339 #ifdef ROCKET_DEBUG_RECEIVE
340 printk(KERN_INFO "Status mode off.\n");
341 #endif
342 sDisRxStatusMode(cp);
344 } else {
346 * we aren't in status mode, so read down the FIFO two
347 * characters at time by doing repeated word IO
348 * transfer.
350 wRecv = ToRecv >> 1;
351 if (wRecv)
352 sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
353 if (ToRecv & 1)
354 cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
355 memset(fbuf, 0, ToRecv);
356 cbuf += ToRecv;
357 fbuf += ToRecv;
358 count += ToRecv;
360 /* Push the data up to the tty layer */
361 ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
362 tty_ldisc_deref(ld);
366 * Serial port transmit data function. Called from the timer polling loop as a
367 * result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready
368 * to be sent out the serial port. Data is buffered in rp_table[line].xmit_buf, it is
369 * moved to the port's xmit FIFO. *info is critical data, protected by spinlocks.
371 static void rp_do_transmit(struct r_port *info)
373 int c;
374 CHANNEL_t *cp = &info->channel;
375 struct tty_struct *tty;
376 unsigned long flags;
378 #ifdef ROCKET_DEBUG_INTR
379 printk(KERN_INFO "rp_do_transmit ");
380 #endif
381 if (!info)
382 return;
383 if (!info->tty) {
384 printk(KERN_INFO "rp: WARNING rp_do_transmit called with info->tty==NULL\n");
385 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
386 return;
389 spin_lock_irqsave(&info->slock, flags);
390 tty = info->tty;
391 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
393 /* Loop sending data to FIFO until done or FIFO full */
394 while (1) {
395 if (tty->stopped || tty->hw_stopped)
396 break;
397 c = min(info->xmit_fifo_room, min(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
398 if (c <= 0 || info->xmit_fifo_room <= 0)
399 break;
400 sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
401 if (c & 1)
402 sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]);
403 info->xmit_tail += c;
404 info->xmit_tail &= XMIT_BUF_SIZE - 1;
405 info->xmit_cnt -= c;
406 info->xmit_fifo_room -= c;
407 #ifdef ROCKET_DEBUG_INTR
408 printk(KERN_INFO "tx %d chars...", c);
409 #endif
412 if (info->xmit_cnt == 0)
413 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
415 if (info->xmit_cnt < WAKEUP_CHARS) {
416 tty_wakeup(tty);
417 wake_up_interruptible(&tty->write_wait);
418 #ifdef ROCKETPORT_HAVE_POLL_WAIT
419 wake_up_interruptible(&tty->poll_wait);
420 #endif
423 spin_unlock_irqrestore(&info->slock, flags);
425 #ifdef ROCKET_DEBUG_INTR
426 printk(KERN_INFO "(%d,%d,%d,%d)...", info->xmit_cnt, info->xmit_head,
427 info->xmit_tail, info->xmit_fifo_room);
428 #endif
432 * Called when a serial port signals it has read data in it's RX FIFO.
433 * It checks what interrupts are pending and services them, including
434 * receiving serial data.
436 static void rp_handle_port(struct r_port *info)
438 CHANNEL_t *cp;
439 struct tty_struct *tty;
440 unsigned int IntMask, ChanStatus;
442 if (!info)
443 return;
445 if ((info->flags & ROCKET_INITIALIZED) == 0) {
446 printk(KERN_INFO "rp: WARNING: rp_handle_port called with info->flags & NOT_INIT\n");
447 return;
449 if (!info->tty) {
450 printk(KERN_INFO "rp: WARNING: rp_handle_port called with info->tty==NULL\n");
451 return;
453 cp = &info->channel;
454 tty = info->tty;
456 IntMask = sGetChanIntID(cp) & info->intmask;
457 #ifdef ROCKET_DEBUG_INTR
458 printk(KERN_INFO "rp_interrupt %02x...", IntMask);
459 #endif
460 ChanStatus = sGetChanStatus(cp);
461 if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */
462 rp_do_receive(info, tty, cp, ChanStatus);
464 if (IntMask & DELTA_CD) { /* CD change */
465 #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP))
466 printk(KERN_INFO "ttyR%d CD now %s...", info->line,
467 (ChanStatus & CD_ACT) ? "on" : "off");
468 #endif
469 if (!(ChanStatus & CD_ACT) && info->cd_status) {
470 #ifdef ROCKET_DEBUG_HANGUP
471 printk(KERN_INFO "CD drop, calling hangup.\n");
472 #endif
473 tty_hangup(tty);
475 info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
476 wake_up_interruptible(&info->open_wait);
478 #ifdef ROCKET_DEBUG_INTR
479 if (IntMask & DELTA_CTS) { /* CTS change */
480 printk(KERN_INFO "CTS change...\n");
482 if (IntMask & DELTA_DSR) { /* DSR change */
483 printk(KERN_INFO "DSR change...\n");
485 #endif
489 * The top level polling routine. Repeats every 1/100 HZ (10ms).
491 static void rp_do_poll(unsigned long dummy)
493 CONTROLLER_t *ctlp;
494 int ctrl, aiop, ch, line, i;
495 unsigned int xmitmask;
496 unsigned int CtlMask;
497 unsigned char AiopMask;
498 Word_t bit;
500 /* Walk through all the boards (ctrl's) */
501 for (ctrl = 0; ctrl < max_board; ctrl++) {
502 if (rcktpt_io_addr[ctrl] <= 0)
503 continue;
505 /* Get a ptr to the board's control struct */
506 ctlp = sCtlNumToCtlPtr(ctrl);
508 /* Get the interupt status from the board */
509 #ifdef CONFIG_PCI
510 if (ctlp->BusType == isPCI)
511 CtlMask = sPCIGetControllerIntStatus(ctlp);
512 else
513 #endif
514 CtlMask = sGetControllerIntStatus(ctlp);
516 /* Check if any AIOP read bits are set */
517 for (aiop = 0; CtlMask; aiop++) {
518 bit = ctlp->AiopIntrBits[aiop];
519 if (CtlMask & bit) {
520 CtlMask &= ~bit;
521 AiopMask = sGetAiopIntStatus(ctlp, aiop);
523 /* Check if any port read bits are set */
524 for (ch = 0; AiopMask; AiopMask >>= 1, ch++) {
525 if (AiopMask & 1) {
527 /* Get the line number (/dev/ttyRx number). */
528 /* Read the data from the port. */
529 line = GetLineNumber(ctrl, aiop, ch);
530 rp_handle_port(rp_table[line]);
536 xmitmask = xmit_flags[ctrl];
539 * xmit_flags contains bit-significant flags, indicating there is data
540 * to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port
541 * 1, ... (32 total possible). The variable i has the aiop and ch
542 * numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc).
544 if (xmitmask) {
545 for (i = 0; i < rocketModel[ctrl].numPorts; i++) {
546 if (xmitmask & (1 << i)) {
547 aiop = (i & 0x18) >> 3;
548 ch = i & 0x07;
549 line = GetLineNumber(ctrl, aiop, ch);
550 rp_do_transmit(rp_table[line]);
557 * Reset the timer so we get called at the next clock tick (10ms).
559 if (atomic_read(&rp_num_ports_open))
560 mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
564 * Initializes the r_port structure for a port, as well as enabling the port on
565 * the board.
566 * Inputs: board, aiop, chan numbers
568 static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
570 unsigned rocketMode;
571 struct r_port *info;
572 int line;
573 CONTROLLER_T *ctlp;
575 /* Get the next available line number */
576 line = SetLineNumber(board, aiop, chan);
578 ctlp = sCtlNumToCtlPtr(board);
580 /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */
581 info = kmalloc(sizeof (struct r_port), GFP_KERNEL);
582 if (!info) {
583 printk(KERN_INFO "Couldn't allocate info struct for line #%d\n", line);
584 return;
586 memset(info, 0, sizeof (struct r_port));
588 info->magic = RPORT_MAGIC;
589 info->line = line;
590 info->ctlp = ctlp;
591 info->board = board;
592 info->aiop = aiop;
593 info->chan = chan;
594 info->closing_wait = 3000;
595 info->close_delay = 50;
596 init_waitqueue_head(&info->open_wait);
597 init_waitqueue_head(&info->close_wait);
598 info->flags &= ~ROCKET_MODE_MASK;
599 switch (pc104[board][line]) {
600 case 422:
601 info->flags |= ROCKET_MODE_RS422;
602 break;
603 case 485:
604 info->flags |= ROCKET_MODE_RS485;
605 break;
606 case 232:
607 default:
608 info->flags |= ROCKET_MODE_RS232;
609 break;
612 info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
613 if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
614 printk(KERN_INFO "RocketPort sInitChan(%d, %d, %d) failed!\n", board, aiop, chan);
615 kfree(info);
616 return;
619 rocketMode = info->flags & ROCKET_MODE_MASK;
621 if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485))
622 sEnRTSToggle(&info->channel);
623 else
624 sDisRTSToggle(&info->channel);
626 if (ctlp->boardType == ROCKET_TYPE_PC104) {
627 switch (rocketMode) {
628 case ROCKET_MODE_RS485:
629 sSetInterfaceMode(&info->channel, InterfaceModeRS485);
630 break;
631 case ROCKET_MODE_RS422:
632 sSetInterfaceMode(&info->channel, InterfaceModeRS422);
633 break;
634 case ROCKET_MODE_RS232:
635 default:
636 if (info->flags & ROCKET_RTS_TOGGLE)
637 sSetInterfaceMode(&info->channel, InterfaceModeRS232T);
638 else
639 sSetInterfaceMode(&info->channel, InterfaceModeRS232);
640 break;
643 spin_lock_init(&info->slock);
644 sema_init(&info->write_sem, 1);
645 rp_table[line] = info;
646 if (pci_dev)
647 tty_register_device(rocket_driver, line, &pci_dev->dev);
651 * Configures a rocketport port according to its termio settings. Called from
652 * user mode into the driver (exception handler). *info CD manipulation is spinlock protected.
654 static void configure_r_port(struct r_port *info,
655 struct termios *old_termios)
657 unsigned cflag;
658 unsigned long flags;
659 unsigned rocketMode;
660 int bits, baud, divisor;
661 CHANNEL_t *cp;
663 if (!info->tty || !info->tty->termios)
664 return;
665 cp = &info->channel;
666 cflag = info->tty->termios->c_cflag;
668 /* Byte size and parity */
669 if ((cflag & CSIZE) == CS8) {
670 sSetData8(cp);
671 bits = 10;
672 } else {
673 sSetData7(cp);
674 bits = 9;
676 if (cflag & CSTOPB) {
677 sSetStop2(cp);
678 bits++;
679 } else {
680 sSetStop1(cp);
683 if (cflag & PARENB) {
684 sEnParity(cp);
685 bits++;
686 if (cflag & PARODD) {
687 sSetOddParity(cp);
688 } else {
689 sSetEvenParity(cp);
691 } else {
692 sDisParity(cp);
695 /* baud rate */
696 baud = tty_get_baud_rate(info->tty);
697 if (!baud)
698 baud = 9600;
699 divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
700 if ((divisor >= 8192 || divisor < 0) && old_termios) {
701 info->tty->termios->c_cflag &= ~CBAUD;
702 info->tty->termios->c_cflag |=
703 (old_termios->c_cflag & CBAUD);
704 baud = tty_get_baud_rate(info->tty);
705 if (!baud)
706 baud = 9600;
707 divisor = (rp_baud_base[info->board] / baud) - 1;
709 if (divisor >= 8192 || divisor < 0) {
710 baud = 9600;
711 divisor = (rp_baud_base[info->board] / baud) - 1;
713 info->cps = baud / bits;
714 sSetBaud(cp, divisor);
716 if (cflag & CRTSCTS) {
717 info->intmask |= DELTA_CTS;
718 sEnCTSFlowCtl(cp);
719 } else {
720 info->intmask &= ~DELTA_CTS;
721 sDisCTSFlowCtl(cp);
723 if (cflag & CLOCAL) {
724 info->intmask &= ~DELTA_CD;
725 } else {
726 spin_lock_irqsave(&info->slock, flags);
727 if (sGetChanStatus(cp) & CD_ACT)
728 info->cd_status = 1;
729 else
730 info->cd_status = 0;
731 info->intmask |= DELTA_CD;
732 spin_unlock_irqrestore(&info->slock, flags);
736 * Handle software flow control in the board
738 #ifdef ROCKET_SOFT_FLOW
739 if (I_IXON(info->tty)) {
740 sEnTxSoftFlowCtl(cp);
741 if (I_IXANY(info->tty)) {
742 sEnIXANY(cp);
743 } else {
744 sDisIXANY(cp);
746 sSetTxXONChar(cp, START_CHAR(info->tty));
747 sSetTxXOFFChar(cp, STOP_CHAR(info->tty));
748 } else {
749 sDisTxSoftFlowCtl(cp);
750 sDisIXANY(cp);
751 sClrTxXOFF(cp);
753 #endif
756 * Set up ignore/read mask words
758 info->read_status_mask = STMRCVROVRH | 0xFF;
759 if (I_INPCK(info->tty))
760 info->read_status_mask |= STMFRAMEH | STMPARITYH;
761 if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
762 info->read_status_mask |= STMBREAKH;
765 * Characters to ignore
767 info->ignore_status_mask = 0;
768 if (I_IGNPAR(info->tty))
769 info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
770 if (I_IGNBRK(info->tty)) {
771 info->ignore_status_mask |= STMBREAKH;
773 * If we're ignoring parity and break indicators,
774 * ignore overruns too. (For real raw support).
776 if (I_IGNPAR(info->tty))
777 info->ignore_status_mask |= STMRCVROVRH;
780 rocketMode = info->flags & ROCKET_MODE_MASK;
782 if ((info->flags & ROCKET_RTS_TOGGLE)
783 || (rocketMode == ROCKET_MODE_RS485))
784 sEnRTSToggle(cp);
785 else
786 sDisRTSToggle(cp);
788 sSetRTS(&info->channel);
790 if (cp->CtlP->boardType == ROCKET_TYPE_PC104) {
791 switch (rocketMode) {
792 case ROCKET_MODE_RS485:
793 sSetInterfaceMode(cp, InterfaceModeRS485);
794 break;
795 case ROCKET_MODE_RS422:
796 sSetInterfaceMode(cp, InterfaceModeRS422);
797 break;
798 case ROCKET_MODE_RS232:
799 default:
800 if (info->flags & ROCKET_RTS_TOGGLE)
801 sSetInterfaceMode(cp, InterfaceModeRS232T);
802 else
803 sSetInterfaceMode(cp, InterfaceModeRS232);
804 break;
809 /* info->count is considered critical, protected by spinlocks. */
810 static int block_til_ready(struct tty_struct *tty, struct file *filp,
811 struct r_port *info)
813 DECLARE_WAITQUEUE(wait, current);
814 int retval;
815 int do_clocal = 0, extra_count = 0;
816 unsigned long flags;
819 * If the device is in the middle of being closed, then block
820 * until it's done, and then try again.
822 if (tty_hung_up_p(filp))
823 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
824 if (info->flags & ROCKET_CLOSING) {
825 interruptible_sleep_on(&info->close_wait);
826 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
830 * If non-blocking mode is set, or the port is not enabled,
831 * then make the check up front and then exit.
833 if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
834 info->flags |= ROCKET_NORMAL_ACTIVE;
835 return 0;
837 if (tty->termios->c_cflag & CLOCAL)
838 do_clocal = 1;
841 * Block waiting for the carrier detect and the line to become free. While we are in
842 * this loop, info->count is dropped by one, so that rp_close() knows when to free things.
843 * We restore it upon exit, either normal or abnormal.
845 retval = 0;
846 add_wait_queue(&info->open_wait, &wait);
847 #ifdef ROCKET_DEBUG_OPEN
848 printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, info->count);
849 #endif
850 spin_lock_irqsave(&info->slock, flags);
852 #ifdef ROCKET_DISABLE_SIMUSAGE
853 info->flags |= ROCKET_NORMAL_ACTIVE;
854 #else
855 if (!tty_hung_up_p(filp)) {
856 extra_count = 1;
857 info->count--;
859 #endif
860 info->blocked_open++;
862 spin_unlock_irqrestore(&info->slock, flags);
864 while (1) {
865 if (tty->termios->c_cflag & CBAUD) {
866 sSetDTR(&info->channel);
867 sSetRTS(&info->channel);
869 set_current_state(TASK_INTERRUPTIBLE);
870 if (tty_hung_up_p(filp) || !(info->flags & ROCKET_INITIALIZED)) {
871 if (info->flags & ROCKET_HUP_NOTIFY)
872 retval = -EAGAIN;
873 else
874 retval = -ERESTARTSYS;
875 break;
877 if (!(info->flags & ROCKET_CLOSING) && (do_clocal || (sGetChanStatusLo(&info->channel) & CD_ACT)))
878 break;
879 if (signal_pending(current)) {
880 retval = -ERESTARTSYS;
881 break;
883 #ifdef ROCKET_DEBUG_OPEN
884 printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n",
885 info->line, info->count, info->flags);
886 #endif
887 schedule(); /* Don't hold spinlock here, will hang PC */
889 current->state = TASK_RUNNING;
890 remove_wait_queue(&info->open_wait, &wait);
892 spin_lock_irqsave(&info->slock, flags);
894 if (extra_count)
895 info->count++;
896 info->blocked_open--;
898 spin_unlock_irqrestore(&info->slock, flags);
900 #ifdef ROCKET_DEBUG_OPEN
901 printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n",
902 info->line, info->count);
903 #endif
904 if (retval)
905 return retval;
906 info->flags |= ROCKET_NORMAL_ACTIVE;
907 return 0;
911 * Exception handler that opens a serial port. Creates xmit_buf storage, fills in
912 * port's r_port struct. Initializes the port hardware.
914 static int rp_open(struct tty_struct *tty, struct file *filp)
916 struct r_port *info;
917 int line = 0, retval;
918 CHANNEL_t *cp;
919 unsigned long page;
921 line = TTY_GET_LINE(tty);
922 if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL))
923 return -ENXIO;
925 page = __get_free_page(GFP_KERNEL);
926 if (!page)
927 return -ENOMEM;
929 if (info->flags & ROCKET_CLOSING) {
930 interruptible_sleep_on(&info->close_wait);
931 free_page(page);
932 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
936 * We must not sleep from here until the port is marked fully in use.
938 if (info->xmit_buf)
939 free_page(page);
940 else
941 info->xmit_buf = (unsigned char *) page;
943 tty->driver_data = info;
944 info->tty = tty;
946 if (info->count++ == 0) {
947 atomic_inc(&rp_num_ports_open);
949 #ifdef ROCKET_DEBUG_OPEN
950 printk(KERN_INFO "rocket mod++ = %d...", atomic_read(&rp_num_ports_open));
951 #endif
953 #ifdef ROCKET_DEBUG_OPEN
954 printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->count);
955 #endif
958 * Info->count is now 1; so it's safe to sleep now.
960 info->session = current->signal->session;
961 info->pgrp = process_group(current);
963 if ((info->flags & ROCKET_INITIALIZED) == 0) {
964 cp = &info->channel;
965 sSetRxTrigger(cp, TRIG_1);
966 if (sGetChanStatus(cp) & CD_ACT)
967 info->cd_status = 1;
968 else
969 info->cd_status = 0;
970 sDisRxStatusMode(cp);
971 sFlushRxFIFO(cp);
972 sFlushTxFIFO(cp);
974 sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
975 sSetRxTrigger(cp, TRIG_1);
977 sGetChanStatus(cp);
978 sDisRxStatusMode(cp);
979 sClrTxXOFF(cp);
981 sDisCTSFlowCtl(cp);
982 sDisTxSoftFlowCtl(cp);
984 sEnRxFIFO(cp);
985 sEnTransmit(cp);
987 info->flags |= ROCKET_INITIALIZED;
990 * Set up the tty->alt_speed kludge
992 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
993 info->tty->alt_speed = 57600;
994 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
995 info->tty->alt_speed = 115200;
996 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
997 info->tty->alt_speed = 230400;
998 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
999 info->tty->alt_speed = 460800;
1001 configure_r_port(info, NULL);
1002 if (tty->termios->c_cflag & CBAUD) {
1003 sSetDTR(cp);
1004 sSetRTS(cp);
1007 /* Starts (or resets) the maint polling loop */
1008 mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
1010 retval = block_til_ready(tty, filp, info);
1011 if (retval) {
1012 #ifdef ROCKET_DEBUG_OPEN
1013 printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval);
1014 #endif
1015 return retval;
1017 return 0;
1021 * Exception handler that closes a serial port. info->count is considered critical.
1023 static void rp_close(struct tty_struct *tty, struct file *filp)
1025 struct r_port *info = (struct r_port *) tty->driver_data;
1026 unsigned long flags;
1027 int timeout;
1028 CHANNEL_t *cp;
1030 if (rocket_paranoia_check(info, "rp_close"))
1031 return;
1033 #ifdef ROCKET_DEBUG_OPEN
1034 printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->count);
1035 #endif
1037 if (tty_hung_up_p(filp))
1038 return;
1039 spin_lock_irqsave(&info->slock, flags);
1041 if ((tty->count == 1) && (info->count != 1)) {
1043 * Uh, oh. tty->count is 1, which means that the tty
1044 * structure will be freed. Info->count should always
1045 * be one in these conditions. If it's greater than
1046 * one, we've got real problems, since it means the
1047 * serial port won't be shutdown.
1049 printk(KERN_INFO "rp_close: bad serial port count; tty->count is 1, "
1050 "info->count is %d\n", info->count);
1051 info->count = 1;
1053 if (--info->count < 0) {
1054 printk(KERN_INFO "rp_close: bad serial port count for ttyR%d: %d\n",
1055 info->line, info->count);
1056 info->count = 0;
1058 if (info->count) {
1059 spin_unlock_irqrestore(&info->slock, flags);
1060 return;
1062 info->flags |= ROCKET_CLOSING;
1063 spin_unlock_irqrestore(&info->slock, flags);
1065 cp = &info->channel;
1068 * Notify the line discpline to only process XON/XOFF characters
1070 tty->closing = 1;
1073 * If transmission was throttled by the application request,
1074 * just flush the xmit buffer.
1076 if (tty->flow_stopped)
1077 rp_flush_buffer(tty);
1080 * Wait for the transmit buffer to clear
1082 if (info->closing_wait != ROCKET_CLOSING_WAIT_NONE)
1083 tty_wait_until_sent(tty, info->closing_wait);
1085 * Before we drop DTR, make sure the UART transmitter
1086 * has completely drained; this is especially
1087 * important if there is a transmit FIFO!
1089 timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps;
1090 if (timeout == 0)
1091 timeout = 1;
1092 rp_wait_until_sent(tty, timeout);
1093 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1095 sDisTransmit(cp);
1096 sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
1097 sDisCTSFlowCtl(cp);
1098 sDisTxSoftFlowCtl(cp);
1099 sClrTxXOFF(cp);
1100 sFlushRxFIFO(cp);
1101 sFlushTxFIFO(cp);
1102 sClrRTS(cp);
1103 if (C_HUPCL(tty))
1104 sClrDTR(cp);
1106 if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty))
1107 TTY_DRIVER_FLUSH_BUFFER(tty);
1109 tty_ldisc_flush(tty);
1111 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1113 if (info->blocked_open) {
1114 if (info->close_delay) {
1115 msleep_interruptible(jiffies_to_msecs(info->close_delay));
1117 wake_up_interruptible(&info->open_wait);
1118 } else {
1119 if (info->xmit_buf) {
1120 free_page((unsigned long) info->xmit_buf);
1121 info->xmit_buf = NULL;
1124 info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING | ROCKET_NORMAL_ACTIVE);
1125 tty->closing = 0;
1126 wake_up_interruptible(&info->close_wait);
1127 atomic_dec(&rp_num_ports_open);
1129 #ifdef ROCKET_DEBUG_OPEN
1130 printk(KERN_INFO "rocket mod-- = %d...", atomic_read(&rp_num_ports_open));
1131 printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line);
1132 #endif
1136 static void rp_set_termios(struct tty_struct *tty,
1137 struct termios *old_termios)
1139 struct r_port *info = (struct r_port *) tty->driver_data;
1140 CHANNEL_t *cp;
1141 unsigned cflag;
1143 if (rocket_paranoia_check(info, "rp_set_termios"))
1144 return;
1146 cflag = tty->termios->c_cflag;
1148 if (cflag == old_termios->c_cflag)
1149 return;
1152 * This driver doesn't support CS5 or CS6
1154 if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
1155 tty->termios->c_cflag =
1156 ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
1158 configure_r_port(info, old_termios);
1160 cp = &info->channel;
1162 /* Handle transition to B0 status */
1163 if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
1164 sClrDTR(cp);
1165 sClrRTS(cp);
1168 /* Handle transition away from B0 status */
1169 if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) {
1170 if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS))
1171 sSetRTS(cp);
1172 sSetDTR(cp);
1175 if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
1176 tty->hw_stopped = 0;
1177 rp_start(tty);
1181 static void rp_break(struct tty_struct *tty, int break_state)
1183 struct r_port *info = (struct r_port *) tty->driver_data;
1184 unsigned long flags;
1186 if (rocket_paranoia_check(info, "rp_break"))
1187 return;
1189 spin_lock_irqsave(&info->slock, flags);
1190 if (break_state == -1)
1191 sSendBreak(&info->channel);
1192 else
1193 sClrBreak(&info->channel);
1194 spin_unlock_irqrestore(&info->slock, flags);
1198 * sGetChanRI used to be a macro in rocket_int.h. When the functionality for
1199 * the UPCI boards was added, it was decided to make this a function because
1200 * the macro was getting too complicated. All cases except the first one
1201 * (UPCIRingInd) are taken directly from the original macro.
1203 static int sGetChanRI(CHANNEL_T * ChP)
1205 CONTROLLER_t *CtlP = ChP->CtlP;
1206 int ChanNum = ChP->ChanNum;
1207 int RingInd = 0;
1209 if (CtlP->UPCIRingInd)
1210 RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]);
1211 else if (CtlP->AltChanRingIndicator)
1212 RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT;
1213 else if (CtlP->boardType == ROCKET_TYPE_PC104)
1214 RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]);
1216 return RingInd;
1219 /********************************************************************************************/
1220 /* Here are the routines used by rp_ioctl. These are all called from exception handlers. */
1223 * Returns the state of the serial modem control lines. These next 2 functions
1224 * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
1226 static int rp_tiocmget(struct tty_struct *tty, struct file *file)
1228 struct r_port *info = (struct r_port *)tty->driver_data;
1229 unsigned int control, result, ChanStatus;
1231 ChanStatus = sGetChanStatusLo(&info->channel);
1232 control = info->channel.TxControl[3];
1233 result = ((control & SET_RTS) ? TIOCM_RTS : 0) |
1234 ((control & SET_DTR) ? TIOCM_DTR : 0) |
1235 ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
1236 (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
1237 ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
1238 ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
1240 return result;
1244 * Sets the modem control lines
1246 static int rp_tiocmset(struct tty_struct *tty, struct file *file,
1247 unsigned int set, unsigned int clear)
1249 struct r_port *info = (struct r_port *)tty->driver_data;
1251 if (set & TIOCM_RTS)
1252 info->channel.TxControl[3] |= SET_RTS;
1253 if (set & TIOCM_DTR)
1254 info->channel.TxControl[3] |= SET_DTR;
1255 if (clear & TIOCM_RTS)
1256 info->channel.TxControl[3] &= ~SET_RTS;
1257 if (clear & TIOCM_DTR)
1258 info->channel.TxControl[3] &= ~SET_DTR;
1260 sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0]));
1261 return 0;
1264 static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
1266 struct rocket_config tmp;
1268 if (!retinfo)
1269 return -EFAULT;
1270 memset(&tmp, 0, sizeof (tmp));
1271 tmp.line = info->line;
1272 tmp.flags = info->flags;
1273 tmp.close_delay = info->close_delay;
1274 tmp.closing_wait = info->closing_wait;
1275 tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
1277 if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
1278 return -EFAULT;
1279 return 0;
1282 static int set_config(struct r_port *info, struct rocket_config __user *new_info)
1284 struct rocket_config new_serial;
1286 if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
1287 return -EFAULT;
1289 if (!capable(CAP_SYS_ADMIN))
1291 if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
1292 return -EPERM;
1293 info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
1294 configure_r_port(info, NULL);
1295 return 0;
1298 info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
1299 info->close_delay = new_serial.close_delay;
1300 info->closing_wait = new_serial.closing_wait;
1302 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
1303 info->tty->alt_speed = 57600;
1304 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
1305 info->tty->alt_speed = 115200;
1306 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
1307 info->tty->alt_speed = 230400;
1308 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
1309 info->tty->alt_speed = 460800;
1311 configure_r_port(info, NULL);
1312 return 0;
1316 * This function fills in a rocket_ports struct with information
1317 * about what boards/ports are in the system. This info is passed
1318 * to user space. See setrocket.c where the info is used to create
1319 * the /dev/ttyRx ports.
1321 static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
1323 struct rocket_ports tmp;
1324 int board;
1326 if (!retports)
1327 return -EFAULT;
1328 memset(&tmp, 0, sizeof (tmp));
1329 tmp.tty_major = rocket_driver->major;
1331 for (board = 0; board < 4; board++) {
1332 tmp.rocketModel[board].model = rocketModel[board].model;
1333 strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString);
1334 tmp.rocketModel[board].numPorts = rocketModel[board].numPorts;
1335 tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
1336 tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber;
1338 if (copy_to_user(retports, &tmp, sizeof (*retports)))
1339 return -EFAULT;
1340 return 0;
1343 static int reset_rm2(struct r_port *info, void __user *arg)
1345 int reset;
1347 if (copy_from_user(&reset, arg, sizeof (int)))
1348 return -EFAULT;
1349 if (reset)
1350 reset = 1;
1352 if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII &&
1353 rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII)
1354 return -EINVAL;
1356 if (info->ctlp->BusType == isISA)
1357 sModemReset(info->ctlp, info->chan, reset);
1358 else
1359 sPCIModemReset(info->ctlp, info->chan, reset);
1361 return 0;
1364 static int get_version(struct r_port *info, struct rocket_version __user *retvers)
1366 if (copy_to_user(retvers, &driver_version, sizeof (*retvers)))
1367 return -EFAULT;
1368 return 0;
1371 /* IOCTL call handler into the driver */
1372 static int rp_ioctl(struct tty_struct *tty, struct file *file,
1373 unsigned int cmd, unsigned long arg)
1375 struct r_port *info = (struct r_port *) tty->driver_data;
1376 void __user *argp = (void __user *)arg;
1378 if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
1379 return -ENXIO;
1381 switch (cmd) {
1382 case RCKP_GET_STRUCT:
1383 if (copy_to_user(argp, info, sizeof (struct r_port)))
1384 return -EFAULT;
1385 return 0;
1386 case RCKP_GET_CONFIG:
1387 return get_config(info, argp);
1388 case RCKP_SET_CONFIG:
1389 return set_config(info, argp);
1390 case RCKP_GET_PORTS:
1391 return get_ports(info, argp);
1392 case RCKP_RESET_RM2:
1393 return reset_rm2(info, argp);
1394 case RCKP_GET_VERSION:
1395 return get_version(info, argp);
1396 default:
1397 return -ENOIOCTLCMD;
1399 return 0;
1402 static void rp_send_xchar(struct tty_struct *tty, char ch)
1404 struct r_port *info = (struct r_port *) tty->driver_data;
1405 CHANNEL_t *cp;
1407 if (rocket_paranoia_check(info, "rp_send_xchar"))
1408 return;
1410 cp = &info->channel;
1411 if (sGetTxCnt(cp))
1412 sWriteTxPrioByte(cp, ch);
1413 else
1414 sWriteTxByte(sGetTxRxDataIO(cp), ch);
1417 static void rp_throttle(struct tty_struct *tty)
1419 struct r_port *info = (struct r_port *) tty->driver_data;
1420 CHANNEL_t *cp;
1422 #ifdef ROCKET_DEBUG_THROTTLE
1423 printk(KERN_INFO "throttle %s: %d....\n", tty->name,
1424 tty->ldisc.chars_in_buffer(tty));
1425 #endif
1427 if (rocket_paranoia_check(info, "rp_throttle"))
1428 return;
1430 cp = &info->channel;
1431 if (I_IXOFF(tty))
1432 rp_send_xchar(tty, STOP_CHAR(tty));
1434 sClrRTS(&info->channel);
1437 static void rp_unthrottle(struct tty_struct *tty)
1439 struct r_port *info = (struct r_port *) tty->driver_data;
1440 CHANNEL_t *cp;
1441 #ifdef ROCKET_DEBUG_THROTTLE
1442 printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
1443 tty->ldisc.chars_in_buffer(tty));
1444 #endif
1446 if (rocket_paranoia_check(info, "rp_throttle"))
1447 return;
1449 cp = &info->channel;
1450 if (I_IXOFF(tty))
1451 rp_send_xchar(tty, START_CHAR(tty));
1453 sSetRTS(&info->channel);
1457 * ------------------------------------------------------------
1458 * rp_stop() and rp_start()
1460 * This routines are called before setting or resetting tty->stopped.
1461 * They enable or disable transmitter interrupts, as necessary.
1462 * ------------------------------------------------------------
1464 static void rp_stop(struct tty_struct *tty)
1466 struct r_port *info = (struct r_port *) tty->driver_data;
1468 #ifdef ROCKET_DEBUG_FLOW
1469 printk(KERN_INFO "stop %s: %d %d....\n", tty->name,
1470 info->xmit_cnt, info->xmit_fifo_room);
1471 #endif
1473 if (rocket_paranoia_check(info, "rp_stop"))
1474 return;
1476 if (sGetTxCnt(&info->channel))
1477 sDisTransmit(&info->channel);
1480 static void rp_start(struct tty_struct *tty)
1482 struct r_port *info = (struct r_port *) tty->driver_data;
1484 #ifdef ROCKET_DEBUG_FLOW
1485 printk(KERN_INFO "start %s: %d %d....\n", tty->name,
1486 info->xmit_cnt, info->xmit_fifo_room);
1487 #endif
1489 if (rocket_paranoia_check(info, "rp_stop"))
1490 return;
1492 sEnTransmit(&info->channel);
1493 set_bit((info->aiop * 8) + info->chan,
1494 (void *) &xmit_flags[info->board]);
1498 * rp_wait_until_sent() --- wait until the transmitter is empty
1500 static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
1502 struct r_port *info = (struct r_port *) tty->driver_data;
1503 CHANNEL_t *cp;
1504 unsigned long orig_jiffies;
1505 int check_time, exit_time;
1506 int txcnt;
1508 if (rocket_paranoia_check(info, "rp_wait_until_sent"))
1509 return;
1511 cp = &info->channel;
1513 orig_jiffies = jiffies;
1514 #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1515 printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...", timeout,
1516 jiffies);
1517 printk(KERN_INFO "cps=%d...", info->cps);
1518 #endif
1519 while (1) {
1520 txcnt = sGetTxCnt(cp);
1521 if (!txcnt) {
1522 if (sGetChanStatusLo(cp) & TXSHRMT)
1523 break;
1524 check_time = (HZ / info->cps) / 5;
1525 } else {
1526 check_time = HZ * txcnt / info->cps;
1528 if (timeout) {
1529 exit_time = orig_jiffies + timeout - jiffies;
1530 if (exit_time <= 0)
1531 break;
1532 if (exit_time < check_time)
1533 check_time = exit_time;
1535 if (check_time == 0)
1536 check_time = 1;
1537 #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1538 printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...", txcnt, jiffies, check_time);
1539 #endif
1540 msleep_interruptible(jiffies_to_msecs(check_time));
1541 if (signal_pending(current))
1542 break;
1544 current->state = TASK_RUNNING;
1545 #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1546 printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
1547 #endif
1551 * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
1553 static void rp_hangup(struct tty_struct *tty)
1555 CHANNEL_t *cp;
1556 struct r_port *info = (struct r_port *) tty->driver_data;
1558 if (rocket_paranoia_check(info, "rp_hangup"))
1559 return;
1561 #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
1562 printk(KERN_INFO "rp_hangup of ttyR%d...", info->line);
1563 #endif
1564 rp_flush_buffer(tty);
1565 if (info->flags & ROCKET_CLOSING)
1566 return;
1567 if (info->count)
1568 atomic_dec(&rp_num_ports_open);
1569 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1571 info->count = 0;
1572 info->flags &= ~ROCKET_NORMAL_ACTIVE;
1573 info->tty = NULL;
1575 cp = &info->channel;
1576 sDisRxFIFO(cp);
1577 sDisTransmit(cp);
1578 sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
1579 sDisCTSFlowCtl(cp);
1580 sDisTxSoftFlowCtl(cp);
1581 sClrTxXOFF(cp);
1582 info->flags &= ~ROCKET_INITIALIZED;
1584 wake_up_interruptible(&info->open_wait);
1588 * Exception handler - write char routine. The RocketPort driver uses a
1589 * double-buffering strategy, with the twist that if the in-memory CPU
1590 * buffer is empty, and there's space in the transmit FIFO, the
1591 * writing routines will write directly to transmit FIFO.
1592 * Write buffer and counters protected by spinlocks
1594 static void rp_put_char(struct tty_struct *tty, unsigned char ch)
1596 struct r_port *info = (struct r_port *) tty->driver_data;
1597 CHANNEL_t *cp;
1598 unsigned long flags;
1600 if (rocket_paranoia_check(info, "rp_put_char"))
1601 return;
1603 /* Grab the port write semaphore, locking out other processes that try to write to this port */
1604 down(&info->write_sem);
1606 #ifdef ROCKET_DEBUG_WRITE
1607 printk(KERN_INFO "rp_put_char %c...", ch);
1608 #endif
1610 spin_lock_irqsave(&info->slock, flags);
1611 cp = &info->channel;
1613 if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
1614 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1616 if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
1617 info->xmit_buf[info->xmit_head++] = ch;
1618 info->xmit_head &= XMIT_BUF_SIZE - 1;
1619 info->xmit_cnt++;
1620 set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1621 } else {
1622 sOutB(sGetTxRxDataIO(cp), ch);
1623 info->xmit_fifo_room--;
1625 spin_unlock_irqrestore(&info->slock, flags);
1626 up(&info->write_sem);
1630 * Exception handler - write routine, called when user app writes to the device.
1631 * A per port write semaphore is used to protect from another process writing to
1632 * this port at the same time. This other process could be running on the other CPU
1633 * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out).
1634 * Spinlocks protect the info xmit members.
1636 static int rp_write(struct tty_struct *tty,
1637 const unsigned char *buf, int count)
1639 struct r_port *info = (struct r_port *) tty->driver_data;
1640 CHANNEL_t *cp;
1641 const unsigned char *b;
1642 int c, retval = 0;
1643 unsigned long flags;
1645 if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
1646 return 0;
1648 down_interruptible(&info->write_sem);
1650 #ifdef ROCKET_DEBUG_WRITE
1651 printk(KERN_INFO "rp_write %d chars...", count);
1652 #endif
1653 cp = &info->channel;
1655 if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count)
1656 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1659 * If the write queue for the port is empty, and there is FIFO space, stuff bytes
1660 * into FIFO. Use the write queue for temp storage.
1662 if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
1663 c = min(count, info->xmit_fifo_room);
1664 b = buf;
1666 /* Push data into FIFO, 2 bytes at a time */
1667 sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2);
1669 /* If there is a byte remaining, write it */
1670 if (c & 1)
1671 sOutB(sGetTxRxDataIO(cp), b[c - 1]);
1673 retval += c;
1674 buf += c;
1675 count -= c;
1677 spin_lock_irqsave(&info->slock, flags);
1678 info->xmit_fifo_room -= c;
1679 spin_unlock_irqrestore(&info->slock, flags);
1682 /* If count is zero, we wrote it all and are done */
1683 if (!count)
1684 goto end;
1686 /* Write remaining data into the port's xmit_buf */
1687 while (1) {
1688 if (info->tty == 0) /* Seemingly obligatory check... */
1689 goto end;
1691 c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
1692 if (c <= 0)
1693 break;
1695 b = buf;
1696 memcpy(info->xmit_buf + info->xmit_head, b, c);
1698 spin_lock_irqsave(&info->slock, flags);
1699 info->xmit_head =
1700 (info->xmit_head + c) & (XMIT_BUF_SIZE - 1);
1701 info->xmit_cnt += c;
1702 spin_unlock_irqrestore(&info->slock, flags);
1704 buf += c;
1705 count -= c;
1706 retval += c;
1709 if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
1710 set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1712 end:
1713 if (info->xmit_cnt < WAKEUP_CHARS) {
1714 tty_wakeup(tty);
1715 wake_up_interruptible(&tty->write_wait);
1716 #ifdef ROCKETPORT_HAVE_POLL_WAIT
1717 wake_up_interruptible(&tty->poll_wait);
1718 #endif
1720 up(&info->write_sem);
1721 return retval;
1725 * Return the number of characters that can be sent. We estimate
1726 * only using the in-memory transmit buffer only, and ignore the
1727 * potential space in the transmit FIFO.
1729 static int rp_write_room(struct tty_struct *tty)
1731 struct r_port *info = (struct r_port *) tty->driver_data;
1732 int ret;
1734 if (rocket_paranoia_check(info, "rp_write_room"))
1735 return 0;
1737 ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
1738 if (ret < 0)
1739 ret = 0;
1740 #ifdef ROCKET_DEBUG_WRITE
1741 printk(KERN_INFO "rp_write_room returns %d...", ret);
1742 #endif
1743 return ret;
1747 * Return the number of characters in the buffer. Again, this only
1748 * counts those characters in the in-memory transmit buffer.
1750 static int rp_chars_in_buffer(struct tty_struct *tty)
1752 struct r_port *info = (struct r_port *) tty->driver_data;
1753 CHANNEL_t *cp;
1755 if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
1756 return 0;
1758 cp = &info->channel;
1760 #ifdef ROCKET_DEBUG_WRITE
1761 printk(KERN_INFO "rp_chars_in_buffer returns %d...", info->xmit_cnt);
1762 #endif
1763 return info->xmit_cnt;
1767 * Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the
1768 * r_port struct for the port. Note that spinlock are used to protect info members,
1769 * do not call this function if the spinlock is already held.
1771 static void rp_flush_buffer(struct tty_struct *tty)
1773 struct r_port *info = (struct r_port *) tty->driver_data;
1774 CHANNEL_t *cp;
1775 unsigned long flags;
1777 if (rocket_paranoia_check(info, "rp_flush_buffer"))
1778 return;
1780 spin_lock_irqsave(&info->slock, flags);
1781 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1782 spin_unlock_irqrestore(&info->slock, flags);
1784 wake_up_interruptible(&tty->write_wait);
1785 #ifdef ROCKETPORT_HAVE_POLL_WAIT
1786 wake_up_interruptible(&tty->poll_wait);
1787 #endif
1788 tty_wakeup(tty);
1790 cp = &info->channel;
1791 sFlushTxFIFO(cp);
1794 #ifdef CONFIG_PCI
1797 * Called when a PCI card is found. Retrieves and stores model information,
1798 * init's aiopic and serial port hardware.
1799 * Inputs: i is the board number (0-n)
1801 __init int register_PCI(int i, struct pci_dev *dev)
1803 int num_aiops, aiop, max_num_aiops, num_chan, chan;
1804 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1805 char *str, *board_type;
1806 CONTROLLER_t *ctlp;
1808 int fast_clock = 0;
1809 int altChanRingIndicator = 0;
1810 int ports_per_aiop = 8;
1811 int ret;
1812 unsigned int class_rev;
1813 WordIO_t ConfigIO = 0;
1814 ByteIO_t UPCIRingInd = 0;
1816 if (!dev || pci_enable_device(dev))
1817 return 0;
1819 rcktpt_io_addr[i] = pci_resource_start(dev, 0);
1820 ret = pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
1822 if (ret) {
1823 printk(KERN_INFO " Error during register_PCI(), unable to read config dword \n");
1824 return 0;
1827 rcktpt_type[i] = ROCKET_TYPE_NORMAL;
1828 rocketModel[i].loadrm2 = 0;
1829 rocketModel[i].startingPortNumber = nextLineNumber;
1831 /* Depending on the model, set up some config variables */
1832 switch (dev->device) {
1833 case PCI_DEVICE_ID_RP4QUAD:
1834 str = "Quadcable";
1835 max_num_aiops = 1;
1836 ports_per_aiop = 4;
1837 rocketModel[i].model = MODEL_RP4QUAD;
1838 strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable");
1839 rocketModel[i].numPorts = 4;
1840 break;
1841 case PCI_DEVICE_ID_RP8OCTA:
1842 str = "Octacable";
1843 max_num_aiops = 1;
1844 rocketModel[i].model = MODEL_RP8OCTA;
1845 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
1846 rocketModel[i].numPorts = 8;
1847 break;
1848 case PCI_DEVICE_ID_URP8OCTA:
1849 str = "Octacable";
1850 max_num_aiops = 1;
1851 rocketModel[i].model = MODEL_UPCI_RP8OCTA;
1852 strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
1853 rocketModel[i].numPorts = 8;
1854 break;
1855 case PCI_DEVICE_ID_RP8INTF:
1856 str = "8";
1857 max_num_aiops = 1;
1858 rocketModel[i].model = MODEL_RP8INTF;
1859 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
1860 rocketModel[i].numPorts = 8;
1861 break;
1862 case PCI_DEVICE_ID_URP8INTF:
1863 str = "8";
1864 max_num_aiops = 1;
1865 rocketModel[i].model = MODEL_UPCI_RP8INTF;
1866 strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
1867 rocketModel[i].numPorts = 8;
1868 break;
1869 case PCI_DEVICE_ID_RP8J:
1870 str = "8J";
1871 max_num_aiops = 1;
1872 rocketModel[i].model = MODEL_RP8J;
1873 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
1874 rocketModel[i].numPorts = 8;
1875 break;
1876 case PCI_DEVICE_ID_RP4J:
1877 str = "4J";
1878 max_num_aiops = 1;
1879 ports_per_aiop = 4;
1880 rocketModel[i].model = MODEL_RP4J;
1881 strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors");
1882 rocketModel[i].numPorts = 4;
1883 break;
1884 case PCI_DEVICE_ID_RP8SNI:
1885 str = "8 (DB78 Custom)";
1886 max_num_aiops = 1;
1887 rocketModel[i].model = MODEL_RP8SNI;
1888 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
1889 rocketModel[i].numPorts = 8;
1890 break;
1891 case PCI_DEVICE_ID_RP16SNI:
1892 str = "16 (DB78 Custom)";
1893 max_num_aiops = 2;
1894 rocketModel[i].model = MODEL_RP16SNI;
1895 strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
1896 rocketModel[i].numPorts = 16;
1897 break;
1898 case PCI_DEVICE_ID_RP16INTF:
1899 str = "16";
1900 max_num_aiops = 2;
1901 rocketModel[i].model = MODEL_RP16INTF;
1902 strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
1903 rocketModel[i].numPorts = 16;
1904 break;
1905 case PCI_DEVICE_ID_URP16INTF:
1906 str = "16";
1907 max_num_aiops = 2;
1908 rocketModel[i].model = MODEL_UPCI_RP16INTF;
1909 strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
1910 rocketModel[i].numPorts = 16;
1911 break;
1912 case PCI_DEVICE_ID_CRP16INTF:
1913 str = "16";
1914 max_num_aiops = 2;
1915 rocketModel[i].model = MODEL_CPCI_RP16INTF;
1916 strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
1917 rocketModel[i].numPorts = 16;
1918 break;
1919 case PCI_DEVICE_ID_RP32INTF:
1920 str = "32";
1921 max_num_aiops = 4;
1922 rocketModel[i].model = MODEL_RP32INTF;
1923 strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
1924 rocketModel[i].numPorts = 32;
1925 break;
1926 case PCI_DEVICE_ID_URP32INTF:
1927 str = "32";
1928 max_num_aiops = 4;
1929 rocketModel[i].model = MODEL_UPCI_RP32INTF;
1930 strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
1931 rocketModel[i].numPorts = 32;
1932 break;
1933 case PCI_DEVICE_ID_RPP4:
1934 str = "Plus Quadcable";
1935 max_num_aiops = 1;
1936 ports_per_aiop = 4;
1937 altChanRingIndicator++;
1938 fast_clock++;
1939 rocketModel[i].model = MODEL_RPP4;
1940 strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port");
1941 rocketModel[i].numPorts = 4;
1942 break;
1943 case PCI_DEVICE_ID_RPP8:
1944 str = "Plus Octacable";
1945 max_num_aiops = 2;
1946 ports_per_aiop = 4;
1947 altChanRingIndicator++;
1948 fast_clock++;
1949 rocketModel[i].model = MODEL_RPP8;
1950 strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port");
1951 rocketModel[i].numPorts = 8;
1952 break;
1953 case PCI_DEVICE_ID_RP2_232:
1954 str = "Plus 2 (RS-232)";
1955 max_num_aiops = 1;
1956 ports_per_aiop = 2;
1957 altChanRingIndicator++;
1958 fast_clock++;
1959 rocketModel[i].model = MODEL_RP2_232;
1960 strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232");
1961 rocketModel[i].numPorts = 2;
1962 break;
1963 case PCI_DEVICE_ID_RP2_422:
1964 str = "Plus 2 (RS-422)";
1965 max_num_aiops = 1;
1966 ports_per_aiop = 2;
1967 altChanRingIndicator++;
1968 fast_clock++;
1969 rocketModel[i].model = MODEL_RP2_422;
1970 strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422");
1971 rocketModel[i].numPorts = 2;
1972 break;
1973 case PCI_DEVICE_ID_RP6M:
1975 max_num_aiops = 1;
1976 ports_per_aiop = 6;
1977 str = "6-port";
1979 /* If class_rev is 1, the rocketmodem flash must be loaded. If it is 2 it is a "socketed" version. */
1980 if ((class_rev & 0xFF) == 1) {
1981 rcktpt_type[i] = ROCKET_TYPE_MODEMII;
1982 rocketModel[i].loadrm2 = 1;
1983 } else {
1984 rcktpt_type[i] = ROCKET_TYPE_MODEM;
1987 rocketModel[i].model = MODEL_RP6M;
1988 strcpy(rocketModel[i].modelString, "RocketModem 6 port");
1989 rocketModel[i].numPorts = 6;
1990 break;
1991 case PCI_DEVICE_ID_RP4M:
1992 max_num_aiops = 1;
1993 ports_per_aiop = 4;
1994 str = "4-port";
1995 if ((class_rev & 0xFF) == 1) {
1996 rcktpt_type[i] = ROCKET_TYPE_MODEMII;
1997 rocketModel[i].loadrm2 = 1;
1998 } else {
1999 rcktpt_type[i] = ROCKET_TYPE_MODEM;
2002 rocketModel[i].model = MODEL_RP4M;
2003 strcpy(rocketModel[i].modelString, "RocketModem 4 port");
2004 rocketModel[i].numPorts = 4;
2005 break;
2006 default:
2007 str = "(unknown/unsupported)";
2008 max_num_aiops = 0;
2009 break;
2013 * Check for UPCI boards.
2016 switch (dev->device) {
2017 case PCI_DEVICE_ID_URP32INTF:
2018 case PCI_DEVICE_ID_URP8INTF:
2019 case PCI_DEVICE_ID_URP16INTF:
2020 case PCI_DEVICE_ID_CRP16INTF:
2021 case PCI_DEVICE_ID_URP8OCTA:
2022 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2023 ConfigIO = pci_resource_start(dev, 1);
2024 if (dev->device == PCI_DEVICE_ID_URP8OCTA) {
2025 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2028 * Check for octa or quad cable.
2030 if (!
2031 (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
2032 PCI_GPIO_CTRL_8PORT)) {
2033 str = "Quadcable";
2034 ports_per_aiop = 4;
2035 rocketModel[i].numPorts = 4;
2038 break;
2039 case PCI_DEVICE_ID_UPCI_RM3_8PORT:
2040 str = "8 ports";
2041 max_num_aiops = 1;
2042 rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
2043 strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
2044 rocketModel[i].numPorts = 8;
2045 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2046 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2047 ConfigIO = pci_resource_start(dev, 1);
2048 rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
2049 break;
2050 case PCI_DEVICE_ID_UPCI_RM3_4PORT:
2051 str = "4 ports";
2052 max_num_aiops = 1;
2053 rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
2054 strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
2055 rocketModel[i].numPorts = 4;
2056 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2057 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2058 ConfigIO = pci_resource_start(dev, 1);
2059 rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
2060 break;
2061 default:
2062 break;
2065 switch (rcktpt_type[i]) {
2066 case ROCKET_TYPE_MODEM:
2067 board_type = "RocketModem";
2068 break;
2069 case ROCKET_TYPE_MODEMII:
2070 board_type = "RocketModem II";
2071 break;
2072 case ROCKET_TYPE_MODEMIII:
2073 board_type = "RocketModem III";
2074 break;
2075 default:
2076 board_type = "RocketPort";
2077 break;
2080 if (fast_clock) {
2081 sClockPrescale = 0x12; /* mod 2 (divide by 3) */
2082 rp_baud_base[i] = 921600;
2083 } else {
2085 * If support_low_speed is set, use the slow clock
2086 * prescale, which supports 50 bps
2088 if (support_low_speed) {
2089 /* mod 9 (divide by 10) prescale */
2090 sClockPrescale = 0x19;
2091 rp_baud_base[i] = 230400;
2092 } else {
2093 /* mod 4 (devide by 5) prescale */
2094 sClockPrescale = 0x14;
2095 rp_baud_base[i] = 460800;
2099 for (aiop = 0; aiop < max_num_aiops; aiop++)
2100 aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
2101 ctlp = sCtlNumToCtlPtr(i);
2102 num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd);
2103 for (aiop = 0; aiop < max_num_aiops; aiop++)
2104 ctlp->AiopNumChan[aiop] = ports_per_aiop;
2106 printk("Comtrol PCI controller #%d ID 0x%x found in bus:slot:fn %s at address %04lx, "
2107 "%d AIOP(s) (%s)\n", i, dev->device, pci_name(dev),
2108 rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString);
2109 printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
2110 rocketModel[i].modelString,
2111 rocketModel[i].startingPortNumber,
2112 rocketModel[i].startingPortNumber +
2113 rocketModel[i].numPorts - 1);
2115 if (num_aiops <= 0) {
2116 rcktpt_io_addr[i] = 0;
2117 return (0);
2119 is_PCI[i] = 1;
2121 /* Reset the AIOPIC, init the serial ports */
2122 for (aiop = 0; aiop < num_aiops; aiop++) {
2123 sResetAiopByNum(ctlp, aiop);
2124 num_chan = ports_per_aiop;
2125 for (chan = 0; chan < num_chan; chan++)
2126 init_r_port(i, aiop, chan, dev);
2129 /* Rocket modems must be reset */
2130 if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
2131 (rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
2132 (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
2133 num_chan = ports_per_aiop;
2134 for (chan = 0; chan < num_chan; chan++)
2135 sPCIModemReset(ctlp, chan, 1);
2136 mdelay(500);
2137 for (chan = 0; chan < num_chan; chan++)
2138 sPCIModemReset(ctlp, chan, 0);
2139 mdelay(500);
2140 rmSpeakerReset(ctlp, rocketModel[i].model);
2142 return (1);
2146 * Probes for PCI cards, inits them if found
2147 * Input: board_found = number of ISA boards already found, or the
2148 * starting board number
2149 * Returns: Number of PCI boards found
2151 static int __init init_PCI(int boards_found)
2153 struct pci_dev *dev = NULL;
2154 int count = 0;
2156 /* Work through the PCI device list, pulling out ours */
2157 while ((dev = pci_find_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
2158 if (register_PCI(count + boards_found, dev))
2159 count++;
2161 return (count);
2164 #endif /* CONFIG_PCI */
2167 * Probes for ISA cards
2168 * Input: i = the board number to look for
2169 * Returns: 1 if board found, 0 else
2171 static int __init init_ISA(int i)
2173 int num_aiops, num_chan = 0, total_num_chan = 0;
2174 int aiop, chan;
2175 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
2176 CONTROLLER_t *ctlp;
2177 char *type_string;
2179 /* If io_addr is zero, no board configured */
2180 if (rcktpt_io_addr[i] == 0)
2181 return (0);
2183 /* Reserve the IO region */
2184 if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) {
2185 printk(KERN_INFO "Unable to reserve IO region for configured ISA RocketPort at address 0x%lx, board not installed...\n", rcktpt_io_addr[i]);
2186 rcktpt_io_addr[i] = 0;
2187 return (0);
2190 ctlp = sCtlNumToCtlPtr(i);
2192 ctlp->boardType = rcktpt_type[i];
2194 switch (rcktpt_type[i]) {
2195 case ROCKET_TYPE_PC104:
2196 type_string = "(PC104)";
2197 break;
2198 case ROCKET_TYPE_MODEM:
2199 type_string = "(RocketModem)";
2200 break;
2201 case ROCKET_TYPE_MODEMII:
2202 type_string = "(RocketModem II)";
2203 break;
2204 default:
2205 type_string = "";
2206 break;
2210 * If support_low_speed is set, use the slow clock prescale,
2211 * which supports 50 bps
2213 if (support_low_speed) {
2214 sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */
2215 rp_baud_base[i] = 230400;
2216 } else {
2217 sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */
2218 rp_baud_base[i] = 460800;
2221 for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
2222 aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400);
2224 num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
2226 if (ctlp->boardType == ROCKET_TYPE_PC104) {
2227 sEnAiop(ctlp, 2); /* only one AIOPIC, but these */
2228 sEnAiop(ctlp, 3); /* CSels used for other stuff */
2231 /* If something went wrong initing the AIOP's release the ISA IO memory */
2232 if (num_aiops <= 0) {
2233 release_region(rcktpt_io_addr[i], 64);
2234 rcktpt_io_addr[i] = 0;
2235 return (0);
2238 rocketModel[i].startingPortNumber = nextLineNumber;
2240 for (aiop = 0; aiop < num_aiops; aiop++) {
2241 sResetAiopByNum(ctlp, aiop);
2242 sEnAiop(ctlp, aiop);
2243 num_chan = sGetAiopNumChan(ctlp, aiop);
2244 total_num_chan += num_chan;
2245 for (chan = 0; chan < num_chan; chan++)
2246 init_r_port(i, aiop, chan, NULL);
2248 is_PCI[i] = 0;
2249 if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) {
2250 num_chan = sGetAiopNumChan(ctlp, 0);
2251 total_num_chan = num_chan;
2252 for (chan = 0; chan < num_chan; chan++)
2253 sModemReset(ctlp, chan, 1);
2254 mdelay(500);
2255 for (chan = 0; chan < num_chan; chan++)
2256 sModemReset(ctlp, chan, 0);
2257 mdelay(500);
2258 strcpy(rocketModel[i].modelString, "RocketModem ISA");
2259 } else {
2260 strcpy(rocketModel[i].modelString, "RocketPort ISA");
2262 rocketModel[i].numPorts = total_num_chan;
2263 rocketModel[i].model = MODEL_ISA;
2265 printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n",
2266 i, rcktpt_io_addr[i], num_aiops, type_string);
2268 printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
2269 rocketModel[i].modelString,
2270 rocketModel[i].startingPortNumber,
2271 rocketModel[i].startingPortNumber +
2272 rocketModel[i].numPorts - 1);
2274 return (1);
2277 static struct tty_operations rocket_ops = {
2278 .open = rp_open,
2279 .close = rp_close,
2280 .write = rp_write,
2281 .put_char = rp_put_char,
2282 .write_room = rp_write_room,
2283 .chars_in_buffer = rp_chars_in_buffer,
2284 .flush_buffer = rp_flush_buffer,
2285 .ioctl = rp_ioctl,
2286 .throttle = rp_throttle,
2287 .unthrottle = rp_unthrottle,
2288 .set_termios = rp_set_termios,
2289 .stop = rp_stop,
2290 .start = rp_start,
2291 .hangup = rp_hangup,
2292 .break_ctl = rp_break,
2293 .send_xchar = rp_send_xchar,
2294 .wait_until_sent = rp_wait_until_sent,
2295 .tiocmget = rp_tiocmget,
2296 .tiocmset = rp_tiocmset,
2300 * The module "startup" routine; it's run when the module is loaded.
2302 int __init rp_init(void)
2304 int retval, pci_boards_found, isa_boards_found, i;
2306 printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
2307 ROCKET_VERSION, ROCKET_DATE);
2309 rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
2310 if (!rocket_driver)
2311 return -ENOMEM;
2314 * Set up the timer channel.
2316 init_timer(&rocket_timer);
2317 rocket_timer.function = rp_do_poll;
2320 * Initialize the array of pointers to our own internal state
2321 * structures.
2323 memset(rp_table, 0, sizeof (rp_table));
2324 memset(xmit_flags, 0, sizeof (xmit_flags));
2326 for (i = 0; i < MAX_RP_PORTS; i++)
2327 lineNumbers[i] = 0;
2328 nextLineNumber = 0;
2329 memset(rocketModel, 0, sizeof (rocketModel));
2332 * If board 1 is non-zero, there is at least one ISA configured. If controller is
2333 * zero, use the default controller IO address of board1 + 0x40.
2335 if (board1) {
2336 if (controller == 0)
2337 controller = board1 + 0x40;
2338 } else {
2339 controller = 0; /* Used as a flag, meaning no ISA boards */
2342 /* If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
2343 if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
2344 printk(KERN_INFO "Unable to reserve IO region for first configured ISA RocketPort controller 0x%lx. Driver exiting \n", controller);
2345 return -EBUSY;
2348 /* Store ISA variable retrieved from command line or .conf file. */
2349 rcktpt_io_addr[0] = board1;
2350 rcktpt_io_addr[1] = board2;
2351 rcktpt_io_addr[2] = board3;
2352 rcktpt_io_addr[3] = board4;
2354 rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2355 rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0];
2356 rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2357 rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1];
2358 rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2359 rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2];
2360 rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2361 rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3];
2364 * Set up the tty driver structure and then register this
2365 * driver with the tty layer.
2368 rocket_driver->owner = THIS_MODULE;
2369 rocket_driver->flags = TTY_DRIVER_NO_DEVFS;
2370 rocket_driver->devfs_name = "tts/R";
2371 rocket_driver->name = "ttyR";
2372 rocket_driver->driver_name = "Comtrol RocketPort";
2373 rocket_driver->major = TTY_ROCKET_MAJOR;
2374 rocket_driver->minor_start = 0;
2375 rocket_driver->type = TTY_DRIVER_TYPE_SERIAL;
2376 rocket_driver->subtype = SERIAL_TYPE_NORMAL;
2377 rocket_driver->init_termios = tty_std_termios;
2378 rocket_driver->init_termios.c_cflag =
2379 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2380 #ifdef ROCKET_SOFT_FLOW
2381 rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
2382 #endif
2383 tty_set_operations(rocket_driver, &rocket_ops);
2385 retval = tty_register_driver(rocket_driver);
2386 if (retval < 0) {
2387 printk(KERN_INFO "Couldn't install tty RocketPort driver (error %d)\n", -retval);
2388 put_tty_driver(rocket_driver);
2389 return -1;
2392 #ifdef ROCKET_DEBUG_OPEN
2393 printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major);
2394 #endif
2397 * OK, let's probe each of the controllers looking for boards. Any boards found
2398 * will be initialized here.
2400 isa_boards_found = 0;
2401 pci_boards_found = 0;
2403 for (i = 0; i < NUM_BOARDS; i++) {
2404 if (init_ISA(i))
2405 isa_boards_found++;
2408 #ifdef CONFIG_PCI
2409 if (isa_boards_found < NUM_BOARDS)
2410 pci_boards_found = init_PCI(isa_boards_found);
2411 #endif
2413 max_board = pci_boards_found + isa_boards_found;
2415 if (max_board == 0) {
2416 printk(KERN_INFO "No rocketport ports found; unloading driver.\n");
2417 del_timer_sync(&rocket_timer);
2418 tty_unregister_driver(rocket_driver);
2419 put_tty_driver(rocket_driver);
2420 return -ENXIO;
2423 return 0;
2426 #ifdef MODULE
2428 static void rp_cleanup_module(void)
2430 int retval;
2431 int i;
2433 del_timer_sync(&rocket_timer);
2435 retval = tty_unregister_driver(rocket_driver);
2436 if (retval)
2437 printk(KERN_INFO "Error %d while trying to unregister "
2438 "rocketport driver\n", -retval);
2439 put_tty_driver(rocket_driver);
2441 for (i = 0; i < MAX_RP_PORTS; i++) {
2442 if (rp_table[i])
2443 kfree(rp_table[i]);
2446 for (i = 0; i < NUM_BOARDS; i++) {
2447 if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
2448 continue;
2449 release_region(rcktpt_io_addr[i], 64);
2451 if (controller)
2452 release_region(controller, 4);
2454 #endif
2456 #ifndef TRUE
2457 #define TRUE 1
2458 #endif
2460 #ifndef FALSE
2461 #define FALSE 0
2462 #endif
2464 static Byte_t RData[RDATASIZE] = {
2465 0x00, 0x09, 0xf6, 0x82,
2466 0x02, 0x09, 0x86, 0xfb,
2467 0x04, 0x09, 0x00, 0x0a,
2468 0x06, 0x09, 0x01, 0x0a,
2469 0x08, 0x09, 0x8a, 0x13,
2470 0x0a, 0x09, 0xc5, 0x11,
2471 0x0c, 0x09, 0x86, 0x85,
2472 0x0e, 0x09, 0x20, 0x0a,
2473 0x10, 0x09, 0x21, 0x0a,
2474 0x12, 0x09, 0x41, 0xff,
2475 0x14, 0x09, 0x82, 0x00,
2476 0x16, 0x09, 0x82, 0x7b,
2477 0x18, 0x09, 0x8a, 0x7d,
2478 0x1a, 0x09, 0x88, 0x81,
2479 0x1c, 0x09, 0x86, 0x7a,
2480 0x1e, 0x09, 0x84, 0x81,
2481 0x20, 0x09, 0x82, 0x7c,
2482 0x22, 0x09, 0x0a, 0x0a
2485 static Byte_t RRegData[RREGDATASIZE] = {
2486 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
2487 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
2488 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
2489 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
2490 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
2491 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
2492 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
2493 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
2494 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
2495 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
2496 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
2497 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
2498 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
2501 CONTROLLER_T sController[CTL_SIZE] = {
2502 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
2503 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
2504 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
2505 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
2506 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
2507 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
2508 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
2509 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
2512 Byte_t sBitMapClrTbl[8] = {
2513 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
2516 Byte_t sBitMapSetTbl[8] = {
2517 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
2520 int sClockPrescale = 0x14;
2522 /***************************************************************************
2523 Function: sInitController
2524 Purpose: Initialization of controller global registers and controller
2525 structure.
2526 Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
2527 IRQNum,Frequency,PeriodicOnly)
2528 CONTROLLER_T *CtlP; Ptr to controller structure
2529 int CtlNum; Controller number
2530 ByteIO_t MudbacIO; Mudbac base I/O address.
2531 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
2532 This list must be in the order the AIOPs will be found on the
2533 controller. Once an AIOP in the list is not found, it is
2534 assumed that there are no more AIOPs on the controller.
2535 int AiopIOListSize; Number of addresses in AiopIOList
2536 int IRQNum; Interrupt Request number. Can be any of the following:
2537 0: Disable global interrupts
2538 3: IRQ 3
2539 4: IRQ 4
2540 5: IRQ 5
2541 9: IRQ 9
2542 10: IRQ 10
2543 11: IRQ 11
2544 12: IRQ 12
2545 15: IRQ 15
2546 Byte_t Frequency: A flag identifying the frequency
2547 of the periodic interrupt, can be any one of the following:
2548 FREQ_DIS - periodic interrupt disabled
2549 FREQ_137HZ - 137 Hertz
2550 FREQ_69HZ - 69 Hertz
2551 FREQ_34HZ - 34 Hertz
2552 FREQ_17HZ - 17 Hertz
2553 FREQ_9HZ - 9 Hertz
2554 FREQ_4HZ - 4 Hertz
2555 If IRQNum is set to 0 the Frequency parameter is
2556 overidden, it is forced to a value of FREQ_DIS.
2557 int PeriodicOnly: TRUE if all interrupts except the periodic
2558 interrupt are to be blocked.
2559 FALSE is both the periodic interrupt and
2560 other channel interrupts are allowed.
2561 If IRQNum is set to 0 the PeriodicOnly parameter is
2562 overidden, it is forced to a value of FALSE.
2563 Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
2564 initialization failed.
2566 Comments:
2567 If periodic interrupts are to be disabled but AIOP interrupts
2568 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
2570 If interrupts are to be completely disabled set IRQNum to 0.
2572 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
2573 invalid combination.
2575 This function performs initialization of global interrupt modes,
2576 but it does not actually enable global interrupts. To enable
2577 and disable global interrupts use functions sEnGlobalInt() and
2578 sDisGlobalInt(). Enabling of global interrupts is normally not
2579 done until all other initializations are complete.
2581 Even if interrupts are globally enabled, they must also be
2582 individually enabled for each channel that is to generate
2583 interrupts.
2585 Warnings: No range checking on any of the parameters is done.
2587 No context switches are allowed while executing this function.
2589 After this function all AIOPs on the controller are disabled,
2590 they can be enabled with sEnAiop().
2592 int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
2593 ByteIO_t * AiopIOList, int AiopIOListSize, int IRQNum,
2594 Byte_t Frequency, int PeriodicOnly)
2596 int i;
2597 ByteIO_t io;
2598 int done;
2600 CtlP->AiopIntrBits = aiop_intr_bits;
2601 CtlP->AltChanRingIndicator = 0;
2602 CtlP->CtlNum = CtlNum;
2603 CtlP->CtlID = CTLID_0001; /* controller release 1 */
2604 CtlP->BusType = isISA;
2605 CtlP->MBaseIO = MudbacIO;
2606 CtlP->MReg1IO = MudbacIO + 1;
2607 CtlP->MReg2IO = MudbacIO + 2;
2608 CtlP->MReg3IO = MudbacIO + 3;
2609 #if 1
2610 CtlP->MReg2 = 0; /* interrupt disable */
2611 CtlP->MReg3 = 0; /* no periodic interrupts */
2612 #else
2613 if (sIRQMap[IRQNum] == 0) { /* interrupts globally disabled */
2614 CtlP->MReg2 = 0; /* interrupt disable */
2615 CtlP->MReg3 = 0; /* no periodic interrupts */
2616 } else {
2617 CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
2618 CtlP->MReg3 = Frequency; /* set frequency */
2619 if (PeriodicOnly) { /* periodic interrupt only */
2620 CtlP->MReg3 |= PERIODIC_ONLY;
2623 #endif
2624 sOutB(CtlP->MReg2IO, CtlP->MReg2);
2625 sOutB(CtlP->MReg3IO, CtlP->MReg3);
2626 sControllerEOI(CtlP); /* clear EOI if warm init */
2627 /* Init AIOPs */
2628 CtlP->NumAiop = 0;
2629 for (i = done = 0; i < AiopIOListSize; i++) {
2630 io = AiopIOList[i];
2631 CtlP->AiopIO[i] = (WordIO_t) io;
2632 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2633 sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03)); /* AIOP index */
2634 sOutB(MudbacIO, (Byte_t) (io >> 6)); /* set up AIOP I/O in MUDBAC */
2635 if (done)
2636 continue;
2637 sEnAiop(CtlP, i); /* enable the AIOP */
2638 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
2639 if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
2640 done = 1; /* done looking for AIOPs */
2641 else {
2642 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
2643 sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
2644 sOutB(io + _INDX_DATA, sClockPrescale);
2645 CtlP->NumAiop++; /* bump count of AIOPs */
2647 sDisAiop(CtlP, i); /* disable AIOP */
2650 if (CtlP->NumAiop == 0)
2651 return (-1);
2652 else
2653 return (CtlP->NumAiop);
2656 /***************************************************************************
2657 Function: sPCIInitController
2658 Purpose: Initialization of controller global registers and controller
2659 structure.
2660 Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
2661 IRQNum,Frequency,PeriodicOnly)
2662 CONTROLLER_T *CtlP; Ptr to controller structure
2663 int CtlNum; Controller number
2664 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
2665 This list must be in the order the AIOPs will be found on the
2666 controller. Once an AIOP in the list is not found, it is
2667 assumed that there are no more AIOPs on the controller.
2668 int AiopIOListSize; Number of addresses in AiopIOList
2669 int IRQNum; Interrupt Request number. Can be any of the following:
2670 0: Disable global interrupts
2671 3: IRQ 3
2672 4: IRQ 4
2673 5: IRQ 5
2674 9: IRQ 9
2675 10: IRQ 10
2676 11: IRQ 11
2677 12: IRQ 12
2678 15: IRQ 15
2679 Byte_t Frequency: A flag identifying the frequency
2680 of the periodic interrupt, can be any one of the following:
2681 FREQ_DIS - periodic interrupt disabled
2682 FREQ_137HZ - 137 Hertz
2683 FREQ_69HZ - 69 Hertz
2684 FREQ_34HZ - 34 Hertz
2685 FREQ_17HZ - 17 Hertz
2686 FREQ_9HZ - 9 Hertz
2687 FREQ_4HZ - 4 Hertz
2688 If IRQNum is set to 0 the Frequency parameter is
2689 overidden, it is forced to a value of FREQ_DIS.
2690 int PeriodicOnly: TRUE if all interrupts except the periodic
2691 interrupt are to be blocked.
2692 FALSE is both the periodic interrupt and
2693 other channel interrupts are allowed.
2694 If IRQNum is set to 0 the PeriodicOnly parameter is
2695 overidden, it is forced to a value of FALSE.
2696 Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
2697 initialization failed.
2699 Comments:
2700 If periodic interrupts are to be disabled but AIOP interrupts
2701 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
2703 If interrupts are to be completely disabled set IRQNum to 0.
2705 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
2706 invalid combination.
2708 This function performs initialization of global interrupt modes,
2709 but it does not actually enable global interrupts. To enable
2710 and disable global interrupts use functions sEnGlobalInt() and
2711 sDisGlobalInt(). Enabling of global interrupts is normally not
2712 done until all other initializations are complete.
2714 Even if interrupts are globally enabled, they must also be
2715 individually enabled for each channel that is to generate
2716 interrupts.
2718 Warnings: No range checking on any of the parameters is done.
2720 No context switches are allowed while executing this function.
2722 After this function all AIOPs on the controller are disabled,
2723 they can be enabled with sEnAiop().
2725 int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
2726 ByteIO_t * AiopIOList, int AiopIOListSize,
2727 WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
2728 int PeriodicOnly, int altChanRingIndicator,
2729 int UPCIRingInd)
2731 int i;
2732 ByteIO_t io;
2734 CtlP->AltChanRingIndicator = altChanRingIndicator;
2735 CtlP->UPCIRingInd = UPCIRingInd;
2736 CtlP->CtlNum = CtlNum;
2737 CtlP->CtlID = CTLID_0001; /* controller release 1 */
2738 CtlP->BusType = isPCI; /* controller release 1 */
2740 if (ConfigIO) {
2741 CtlP->isUPCI = 1;
2742 CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
2743 CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
2744 CtlP->AiopIntrBits = upci_aiop_intr_bits;
2745 } else {
2746 CtlP->isUPCI = 0;
2747 CtlP->PCIIO =
2748 (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
2749 CtlP->AiopIntrBits = aiop_intr_bits;
2752 sPCIControllerEOI(CtlP); /* clear EOI if warm init */
2753 /* Init AIOPs */
2754 CtlP->NumAiop = 0;
2755 for (i = 0; i < AiopIOListSize; i++) {
2756 io = AiopIOList[i];
2757 CtlP->AiopIO[i] = (WordIO_t) io;
2758 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2760 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
2761 if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
2762 break; /* done looking for AIOPs */
2764 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
2765 sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
2766 sOutB(io + _INDX_DATA, sClockPrescale);
2767 CtlP->NumAiop++; /* bump count of AIOPs */
2770 if (CtlP->NumAiop == 0)
2771 return (-1);
2772 else
2773 return (CtlP->NumAiop);
2776 /***************************************************************************
2777 Function: sReadAiopID
2778 Purpose: Read the AIOP idenfication number directly from an AIOP.
2779 Call: sReadAiopID(io)
2780 ByteIO_t io: AIOP base I/O address
2781 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
2782 is replace by an identifying number.
2783 Flag AIOPID_NULL if no valid AIOP is found
2784 Warnings: No context switches are allowed while executing this function.
2787 int sReadAiopID(ByteIO_t io)
2789 Byte_t AiopID; /* ID byte from AIOP */
2791 sOutB(io + _CMD_REG, RESET_ALL); /* reset AIOP */
2792 sOutB(io + _CMD_REG, 0x0);
2793 AiopID = sInW(io + _CHN_STAT0) & 0x07;
2794 if (AiopID == 0x06)
2795 return (1);
2796 else /* AIOP does not exist */
2797 return (-1);
2800 /***************************************************************************
2801 Function: sReadAiopNumChan
2802 Purpose: Read the number of channels available in an AIOP directly from
2803 an AIOP.
2804 Call: sReadAiopNumChan(io)
2805 WordIO_t io: AIOP base I/O address
2806 Return: int: The number of channels available
2807 Comments: The number of channels is determined by write/reads from identical
2808 offsets within the SRAM address spaces for channels 0 and 4.
2809 If the channel 4 space is mirrored to channel 0 it is a 4 channel
2810 AIOP, otherwise it is an 8 channel.
2811 Warnings: No context switches are allowed while executing this function.
2813 int sReadAiopNumChan(WordIO_t io)
2815 Word_t x;
2816 static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
2818 /* write to chan 0 SRAM */
2819 sOutDW((DWordIO_t) io + _INDX_ADDR, *((DWord_t *) & R[0]));
2820 sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */
2821 x = sInW(io + _INDX_DATA);
2822 sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */
2823 if (x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
2824 return (8);
2825 else
2826 return (4);
2829 /***************************************************************************
2830 Function: sInitChan
2831 Purpose: Initialization of a channel and channel structure
2832 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
2833 CONTROLLER_T *CtlP; Ptr to controller structure
2834 CHANNEL_T *ChP; Ptr to channel structure
2835 int AiopNum; AIOP number within controller
2836 int ChanNum; Channel number within AIOP
2837 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
2838 number exceeds number of channels available in AIOP.
2839 Comments: This function must be called before a channel can be used.
2840 Warnings: No range checking on any of the parameters is done.
2842 No context switches are allowed while executing this function.
2844 int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
2845 int ChanNum)
2847 int i;
2848 WordIO_t AiopIO;
2849 WordIO_t ChIOOff;
2850 Byte_t *ChR;
2851 Word_t ChOff;
2852 static Byte_t R[4];
2853 int brd9600;
2855 if (ChanNum >= CtlP->AiopNumChan[AiopNum])
2856 return (FALSE); /* exceeds num chans in AIOP */
2858 /* Channel, AIOP, and controller identifiers */
2859 ChP->CtlP = CtlP;
2860 ChP->ChanID = CtlP->AiopID[AiopNum];
2861 ChP->AiopNum = AiopNum;
2862 ChP->ChanNum = ChanNum;
2864 /* Global direct addresses */
2865 AiopIO = CtlP->AiopIO[AiopNum];
2866 ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG;
2867 ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN;
2868 ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK;
2869 ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR;
2870 ChP->IndexData = AiopIO + _INDX_DATA;
2872 /* Channel direct addresses */
2873 ChIOOff = AiopIO + ChP->ChanNum * 2;
2874 ChP->TxRxData = ChIOOff + _TD0;
2875 ChP->ChanStat = ChIOOff + _CHN_STAT0;
2876 ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
2877 ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0;
2879 /* Initialize the channel from the RData array */
2880 for (i = 0; i < RDATASIZE; i += 4) {
2881 R[0] = RData[i];
2882 R[1] = RData[i + 1] + 0x10 * ChanNum;
2883 R[2] = RData[i + 2];
2884 R[3] = RData[i + 3];
2885 sOutDW(ChP->IndexAddr, *((DWord_t *) & R[0]));
2888 ChR = ChP->R;
2889 for (i = 0; i < RREGDATASIZE; i += 4) {
2890 ChR[i] = RRegData[i];
2891 ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum;
2892 ChR[i + 2] = RRegData[i + 2];
2893 ChR[i + 3] = RRegData[i + 3];
2896 /* Indexed registers */
2897 ChOff = (Word_t) ChanNum *0x1000;
2899 if (sClockPrescale == 0x14)
2900 brd9600 = 47;
2901 else
2902 brd9600 = 23;
2904 ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD);
2905 ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
2906 ChP->BaudDiv[2] = (Byte_t) brd9600;
2907 ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
2908 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->BaudDiv[0]);
2910 ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
2911 ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
2912 ChP->TxControl[2] = 0;
2913 ChP->TxControl[3] = 0;
2914 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
2916 ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
2917 ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
2918 ChP->RxControl[2] = 0;
2919 ChP->RxControl[3] = 0;
2920 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
2922 ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
2923 ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
2924 ChP->TxEnables[2] = 0;
2925 ChP->TxEnables[3] = 0;
2926 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxEnables[0]);
2928 ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
2929 ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
2930 ChP->TxCompare[2] = 0;
2931 ChP->TxCompare[3] = 0;
2932 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxCompare[0]);
2934 ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
2935 ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
2936 ChP->TxReplace1[2] = 0;
2937 ChP->TxReplace1[3] = 0;
2938 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace1[0]);
2940 ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
2941 ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
2942 ChP->TxReplace2[2] = 0;
2943 ChP->TxReplace2[3] = 0;
2944 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace2[0]);
2946 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
2947 ChP->TxFIFO = ChOff + _TX_FIFO;
2949 sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
2950 sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Tx FIFO count */
2951 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
2952 sOutW(ChP->IndexData, 0);
2953 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
2954 ChP->RxFIFO = ChOff + _RX_FIFO;
2956 sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
2957 sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Rx FIFO count */
2958 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
2959 sOutW(ChP->IndexData, 0);
2960 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
2961 sOutW(ChP->IndexData, 0);
2962 ChP->TxPrioCnt = ChOff + _TXP_CNT;
2963 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt);
2964 sOutB(ChP->IndexData, 0);
2965 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
2966 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr);
2967 sOutB(ChP->IndexData, 0);
2968 ChP->TxPrioBuf = ChOff + _TXP_BUF;
2969 sEnRxProcessor(ChP); /* start the Rx processor */
2971 return (TRUE);
2974 /***************************************************************************
2975 Function: sStopRxProcessor
2976 Purpose: Stop the receive processor from processing a channel.
2977 Call: sStopRxProcessor(ChP)
2978 CHANNEL_T *ChP; Ptr to channel structure
2980 Comments: The receive processor can be started again with sStartRxProcessor().
2981 This function causes the receive processor to skip over the
2982 stopped channel. It does not stop it from processing other channels.
2984 Warnings: No context switches are allowed while executing this function.
2986 Do not leave the receive processor stopped for more than one
2987 character time.
2989 After calling this function a delay of 4 uS is required to ensure
2990 that the receive processor is no longer processing this channel.
2992 void sStopRxProcessor(CHANNEL_T * ChP)
2994 Byte_t R[4];
2996 R[0] = ChP->R[0];
2997 R[1] = ChP->R[1];
2998 R[2] = 0x0a;
2999 R[3] = ChP->R[3];
3000 sOutDW(ChP->IndexAddr, *(DWord_t *) & R[0]);
3003 /***************************************************************************
3004 Function: sFlushRxFIFO
3005 Purpose: Flush the Rx FIFO
3006 Call: sFlushRxFIFO(ChP)
3007 CHANNEL_T *ChP; Ptr to channel structure
3008 Return: void
3009 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
3010 while it is being flushed the receive processor is stopped
3011 and the transmitter is disabled. After these operations a
3012 4 uS delay is done before clearing the pointers to allow
3013 the receive processor to stop. These items are handled inside
3014 this function.
3015 Warnings: No context switches are allowed while executing this function.
3017 void sFlushRxFIFO(CHANNEL_T * ChP)
3019 int i;
3020 Byte_t Ch; /* channel number within AIOP */
3021 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
3023 if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
3024 return; /* don't need to flush */
3026 RxFIFOEnabled = FALSE;
3027 if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */
3028 RxFIFOEnabled = TRUE;
3029 sDisRxFIFO(ChP); /* disable it */
3030 for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */
3031 sInB(ChP->IntChan); /* depends on bus i/o timing */
3033 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
3034 Ch = (Byte_t) sGetChanNum(ChP);
3035 sOutB(ChP->Cmd, Ch | RESRXFCNT); /* apply reset Rx FIFO count */
3036 sOutB(ChP->Cmd, Ch); /* remove reset Rx FIFO count */
3037 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
3038 sOutW(ChP->IndexData, 0);
3039 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
3040 sOutW(ChP->IndexData, 0);
3041 if (RxFIFOEnabled)
3042 sEnRxFIFO(ChP); /* enable Rx FIFO */
3045 /***************************************************************************
3046 Function: sFlushTxFIFO
3047 Purpose: Flush the Tx FIFO
3048 Call: sFlushTxFIFO(ChP)
3049 CHANNEL_T *ChP; Ptr to channel structure
3050 Return: void
3051 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
3052 while it is being flushed the receive processor is stopped
3053 and the transmitter is disabled. After these operations a
3054 4 uS delay is done before clearing the pointers to allow
3055 the receive processor to stop. These items are handled inside
3056 this function.
3057 Warnings: No context switches are allowed while executing this function.
3059 void sFlushTxFIFO(CHANNEL_T * ChP)
3061 int i;
3062 Byte_t Ch; /* channel number within AIOP */
3063 int TxEnabled; /* TRUE if transmitter enabled */
3065 if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
3066 return; /* don't need to flush */
3068 TxEnabled = FALSE;
3069 if (ChP->TxControl[3] & TX_ENABLE) {
3070 TxEnabled = TRUE;
3071 sDisTransmit(ChP); /* disable transmitter */
3073 sStopRxProcessor(ChP); /* stop Rx processor */
3074 for (i = 0; i < 4000 / 200; i++) /* delay 4 uS to allow proc to stop */
3075 sInB(ChP->IntChan); /* depends on bus i/o timing */
3076 Ch = (Byte_t) sGetChanNum(ChP);
3077 sOutB(ChP->Cmd, Ch | RESTXFCNT); /* apply reset Tx FIFO count */
3078 sOutB(ChP->Cmd, Ch); /* remove reset Tx FIFO count */
3079 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
3080 sOutW(ChP->IndexData, 0);
3081 if (TxEnabled)
3082 sEnTransmit(ChP); /* enable transmitter */
3083 sStartRxProcessor(ChP); /* restart Rx processor */
3086 /***************************************************************************
3087 Function: sWriteTxPrioByte
3088 Purpose: Write a byte of priority transmit data to a channel
3089 Call: sWriteTxPrioByte(ChP,Data)
3090 CHANNEL_T *ChP; Ptr to channel structure
3091 Byte_t Data; The transmit data byte
3093 Return: int: 1 if the bytes is successfully written, otherwise 0.
3095 Comments: The priority byte is transmitted before any data in the Tx FIFO.
3097 Warnings: No context switches are allowed while executing this function.
3099 int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
3101 Byte_t DWBuf[4]; /* buffer for double word writes */
3102 Word_t *WordPtr; /* must be far because Win SS != DS */
3103 register DWordIO_t IndexAddr;
3105 if (sGetTxCnt(ChP) > 1) { /* write it to Tx priority buffer */
3106 IndexAddr = ChP->IndexAddr;
3107 sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt); /* get priority buffer status */
3108 if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND) /* priority buffer busy */
3109 return (0); /* nothing sent */
3111 WordPtr = (Word_t *) (&DWBuf[0]);
3112 *WordPtr = ChP->TxPrioBuf; /* data byte address */
3114 DWBuf[2] = Data; /* data byte value */
3115 sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */
3117 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
3119 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
3120 DWBuf[3] = 0; /* priority buffer pointer */
3121 sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */
3122 } else { /* write it to Tx FIFO */
3124 sWriteTxByte(sGetTxRxDataIO(ChP), Data);
3126 return (1); /* 1 byte sent */
3129 /***************************************************************************
3130 Function: sEnInterrupts
3131 Purpose: Enable one or more interrupts for a channel
3132 Call: sEnInterrupts(ChP,Flags)
3133 CHANNEL_T *ChP; Ptr to channel structure
3134 Word_t Flags: Interrupt enable flags, can be any combination
3135 of the following flags:
3136 TXINT_EN: Interrupt on Tx FIFO empty
3137 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
3138 sSetRxTrigger())
3139 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
3140 MCINT_EN: Interrupt on modem input change
3141 CHANINT_EN: Allow channel interrupt signal to the AIOP's
3142 Interrupt Channel Register.
3143 Return: void
3144 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
3145 enabled. If an interrupt enable flag is not set in Flags, that
3146 interrupt will not be changed. Interrupts can be disabled with
3147 function sDisInterrupts().
3149 This function sets the appropriate bit for the channel in the AIOP's
3150 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
3151 this channel's bit to be set in the AIOP's Interrupt Channel Register.
3153 Interrupts must also be globally enabled before channel interrupts
3154 will be passed on to the host. This is done with function
3155 sEnGlobalInt().
3157 In some cases it may be desirable to disable interrupts globally but
3158 enable channel interrupts. This would allow the global interrupt
3159 status register to be used to determine which AIOPs need service.
3161 void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
3163 Byte_t Mask; /* Interrupt Mask Register */
3165 ChP->RxControl[2] |=
3166 ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
3168 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
3170 ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
3172 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
3174 if (Flags & CHANINT_EN) {
3175 Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
3176 sOutB(ChP->IntMask, Mask);
3180 /***************************************************************************
3181 Function: sDisInterrupts
3182 Purpose: Disable one or more interrupts for a channel
3183 Call: sDisInterrupts(ChP,Flags)
3184 CHANNEL_T *ChP; Ptr to channel structure
3185 Word_t Flags: Interrupt flags, can be any combination
3186 of the following flags:
3187 TXINT_EN: Interrupt on Tx FIFO empty
3188 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
3189 sSetRxTrigger())
3190 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
3191 MCINT_EN: Interrupt on modem input change
3192 CHANINT_EN: Disable channel interrupt signal to the
3193 AIOP's Interrupt Channel Register.
3194 Return: void
3195 Comments: If an interrupt flag is set in Flags, that interrupt will be
3196 disabled. If an interrupt flag is not set in Flags, that
3197 interrupt will not be changed. Interrupts can be enabled with
3198 function sEnInterrupts().
3200 This function clears the appropriate bit for the channel in the AIOP's
3201 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
3202 this channel's bit from being set in the AIOP's Interrupt Channel
3203 Register.
3205 void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
3207 Byte_t Mask; /* Interrupt Mask Register */
3209 ChP->RxControl[2] &=
3210 ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
3211 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
3212 ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
3213 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
3215 if (Flags & CHANINT_EN) {
3216 Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
3217 sOutB(ChP->IntMask, Mask);
3221 void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
3223 sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
3227 * Not an official SSCI function, but how to reset RocketModems.
3228 * ISA bus version
3230 void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
3232 ByteIO_t addr;
3233 Byte_t val;
3235 addr = CtlP->AiopIO[0] + 0x400;
3236 val = sInB(CtlP->MReg3IO);
3237 /* if AIOP[1] is not enabled, enable it */
3238 if ((val & 2) == 0) {
3239 val = sInB(CtlP->MReg2IO);
3240 sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03));
3241 sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6));
3244 sEnAiop(CtlP, 1);
3245 if (!on)
3246 addr += 8;
3247 sOutB(addr + chan, 0); /* apply or remove reset */
3248 sDisAiop(CtlP, 1);
3252 * Not an official SSCI function, but how to reset RocketModems.
3253 * PCI bus version
3255 void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
3257 ByteIO_t addr;
3259 addr = CtlP->AiopIO[0] + 0x40; /* 2nd AIOP */
3260 if (!on)
3261 addr += 8;
3262 sOutB(addr + chan, 0); /* apply or remove reset */
3265 /* Resets the speaker controller on RocketModem II and III devices */
3266 static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
3268 ByteIO_t addr;
3270 /* RocketModem II speaker control is at the 8th port location of offset 0x40 */
3271 if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
3272 addr = CtlP->AiopIO[0] + 0x4F;
3273 sOutB(addr, 0);
3276 /* RocketModem III speaker control is at the 1st port location of offset 0x80 */
3277 if ((model == MODEL_UPCI_RM3_8PORT)
3278 || (model == MODEL_UPCI_RM3_4PORT)) {
3279 addr = CtlP->AiopIO[0] + 0x88;
3280 sOutB(addr, 0);
3284 /* Returns the line number given the controller (board), aiop and channel number */
3285 static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
3287 return lineNumbers[(ctrl << 5) | (aiop << 3) | ch];
3291 * Stores the line number associated with a given controller (board), aiop
3292 * and channel number.
3293 * Returns: The line number assigned
3295 static unsigned char SetLineNumber(int ctrl, int aiop, int ch)
3297 lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++;
3298 return (nextLineNumber - 1);