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