blob: 106f225e745fa72f07a8689f11eff4f1b0bdcb06 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * RocketPort device driver for Linux
3 *
4 * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000.
5 *
6 * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
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 * Kernel Synchronization:
25 *
26 * This driver has 2 kernel control paths - exception handlers (calls into the driver
27 * from user mode) and the timer bottom half (tasklet). This is a polled driver, interrupts
28 * are not used.
29 *
30 * Critical data:
31 * - rp_table[], accessed through passed "info" pointers, is a global (static) array of
32 * serial port state information and the xmit_buf circular buffer. Protected by
33 * a per port spinlock.
34 * - xmit_flags[], an array of ints indexed by line (port) number, indicating that there
35 * is data to be transmitted. Protected by atomic bit operations.
36 * - rp_num_ports, int indicating number of open ports, protected by atomic operations.
37 *
38 * rp_write() and rp_write_char() functions use a per port semaphore to protect against
39 * simultaneous access to the same port by more than one process.
40 */
41
42/****** Defines ******/
43#ifdef PCI_NUM_RESOURCES
44#define PCI_BASE_ADDRESS(dev, r) ((dev)->resource[r].start)
45#else
46#define PCI_BASE_ADDRESS(dev, r) ((dev)->base_address[r])
47#endif
48
49#define ROCKET_PARANOIA_CHECK
50#define ROCKET_DISABLE_SIMUSAGE
51
52#undef ROCKET_SOFT_FLOW
53#undef ROCKET_DEBUG_OPEN
54#undef ROCKET_DEBUG_INTR
55#undef ROCKET_DEBUG_WRITE
56#undef ROCKET_DEBUG_FLOW
57#undef ROCKET_DEBUG_THROTTLE
58#undef ROCKET_DEBUG_WAIT_UNTIL_SENT
59#undef ROCKET_DEBUG_RECEIVE
60#undef ROCKET_DEBUG_HANGUP
61#undef REV_PCI_ORDER
62#undef ROCKET_DEBUG_IO
63
64#define POLL_PERIOD HZ/100 /* Polling period .01 seconds (10ms) */
65
66/****** Kernel includes ******/
67
68#ifdef MODVERSIONS
69#include <config/modversions.h>
70#endif
71
72#include <linux/module.h>
73#include <linux/errno.h>
74#include <linux/major.h>
75#include <linux/kernel.h>
76#include <linux/signal.h>
77#include <linux/slab.h>
78#include <linux/mm.h>
79#include <linux/sched.h>
80#include <linux/timer.h>
81#include <linux/interrupt.h>
82#include <linux/tty.h>
83#include <linux/tty_driver.h>
84#include <linux/tty_flip.h>
85#include <linux/string.h>
86#include <linux/fcntl.h>
87#include <linux/ptrace.h>
88#include <linux/ioport.h>
89#include <linux/delay.h>
90#include <linux/wait.h>
91#include <linux/pci.h>
92#include <asm/uaccess.h>
93#include <asm/atomic.h>
94#include <linux/bitops.h>
95#include <linux/spinlock.h>
96#include <asm/semaphore.h>
97#include <linux/init.h>
98
99/****** RocketPort includes ******/
100
101#include "rocket_int.h"
102#include "rocket.h"
103
104#define ROCKET_VERSION "2.09"
105#define ROCKET_DATE "12-June-2003"
106
107/****** RocketPort Local Variables ******/
108
109static struct tty_driver *rocket_driver;
110
111static struct rocket_version driver_version = {
112 ROCKET_VERSION, ROCKET_DATE
113};
114
115static struct r_port *rp_table[MAX_RP_PORTS]; /* The main repository of serial port state information. */
116static unsigned int xmit_flags[NUM_BOARDS]; /* Bit significant, indicates port had data to transmit. */
117 /* eg. Bit 0 indicates port 0 has xmit data, ... */
118static atomic_t rp_num_ports_open; /* Number of serial ports open */
119static struct timer_list rocket_timer;
120
121static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */
122static unsigned long board2;
123static unsigned long board3;
124static unsigned long board4;
125static unsigned long controller;
126static int support_low_speed;
127static unsigned long modem1;
128static unsigned long modem2;
129static unsigned long modem3;
130static unsigned long modem4;
131static unsigned long pc104_1[8];
132static unsigned long pc104_2[8];
133static unsigned long pc104_3[8];
134static unsigned long pc104_4[8];
135static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 };
136
137static int rp_baud_base[NUM_BOARDS]; /* Board config info (Someday make a per-board structure) */
138static unsigned long rcktpt_io_addr[NUM_BOARDS];
139static int rcktpt_type[NUM_BOARDS];
140static int is_PCI[NUM_BOARDS];
141static rocketModel_t rocketModel[NUM_BOARDS];
142static int max_board;
143
144/*
145 * The following arrays define the interrupt bits corresponding to each AIOP.
146 * These bits are different between the ISA and regular PCI boards and the
147 * Universal PCI boards.
148 */
149
150static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
151 AIOP_INTR_BIT_0,
152 AIOP_INTR_BIT_1,
153 AIOP_INTR_BIT_2,
154 AIOP_INTR_BIT_3
155};
156
157static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
158 UPCI_AIOP_INTR_BIT_0,
159 UPCI_AIOP_INTR_BIT_1,
160 UPCI_AIOP_INTR_BIT_2,
161 UPCI_AIOP_INTR_BIT_3
162};
163
Adrian Bunkf15313b2005-06-25 14:59:05 -0700164static Byte_t RData[RDATASIZE] = {
165 0x00, 0x09, 0xf6, 0x82,
166 0x02, 0x09, 0x86, 0xfb,
167 0x04, 0x09, 0x00, 0x0a,
168 0x06, 0x09, 0x01, 0x0a,
169 0x08, 0x09, 0x8a, 0x13,
170 0x0a, 0x09, 0xc5, 0x11,
171 0x0c, 0x09, 0x86, 0x85,
172 0x0e, 0x09, 0x20, 0x0a,
173 0x10, 0x09, 0x21, 0x0a,
174 0x12, 0x09, 0x41, 0xff,
175 0x14, 0x09, 0x82, 0x00,
176 0x16, 0x09, 0x82, 0x7b,
177 0x18, 0x09, 0x8a, 0x7d,
178 0x1a, 0x09, 0x88, 0x81,
179 0x1c, 0x09, 0x86, 0x7a,
180 0x1e, 0x09, 0x84, 0x81,
181 0x20, 0x09, 0x82, 0x7c,
182 0x22, 0x09, 0x0a, 0x0a
183};
184
185static Byte_t RRegData[RREGDATASIZE] = {
186 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
187 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
188 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
189 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
190 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
191 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
192 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
193 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
194 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
195 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
196 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
197 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
198 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
199};
200
201static CONTROLLER_T sController[CTL_SIZE] = {
202 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
203 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
204 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
205 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
206 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
207 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
208 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
209 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
210};
211
212static Byte_t sBitMapClrTbl[8] = {
213 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
214};
215
216static Byte_t sBitMapSetTbl[8] = {
217 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
218};
219
220static int sClockPrescale = 0x14;
221
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222/*
223 * Line number is the ttySIx number (x), the Minor number. We
224 * assign them sequentially, starting at zero. The following
225 * array keeps track of the line number assigned to a given board/aiop/channel.
226 */
227static unsigned char lineNumbers[MAX_RP_PORTS];
228static unsigned long nextLineNumber;
229
230/***** RocketPort Static Prototypes *********/
231static int __init init_ISA(int i);
232static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
233static void rp_flush_buffer(struct tty_struct *tty);
234static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
235static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
236static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
237static void rp_start(struct tty_struct *tty);
Adrian Bunkf15313b2005-06-25 14:59:05 -0700238static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
239 int ChanNum);
240static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
241static void sFlushRxFIFO(CHANNEL_T * ChP);
242static void sFlushTxFIFO(CHANNEL_T * ChP);
243static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
244static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
245static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
246static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
247static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
248static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
249 ByteIO_t * AiopIOList, int AiopIOListSize,
250 WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
251 int PeriodicOnly, int altChanRingIndicator,
252 int UPCIRingInd);
253static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
254 ByteIO_t * AiopIOList, int AiopIOListSize,
255 int IRQNum, Byte_t Frequency, int PeriodicOnly);
256static int sReadAiopID(ByteIO_t io);
257static int sReadAiopNumChan(WordIO_t io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259MODULE_AUTHOR("Theodore Ts'o");
260MODULE_DESCRIPTION("Comtrol RocketPort driver");
261module_param(board1, ulong, 0);
262MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
263module_param(board2, ulong, 0);
264MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
265module_param(board3, ulong, 0);
266MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
267module_param(board4, ulong, 0);
268MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
269module_param(controller, ulong, 0);
270MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
271module_param(support_low_speed, bool, 0);
272MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud");
273module_param(modem1, ulong, 0);
274MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem");
275module_param(modem2, ulong, 0);
276MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem");
277module_param(modem3, ulong, 0);
278MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem");
279module_param(modem4, ulong, 0);
280MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem");
281module_param_array(pc104_1, ulong, NULL, 0);
282MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,...");
283module_param_array(pc104_2, ulong, NULL, 0);
284MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,...");
285module_param_array(pc104_3, ulong, NULL, 0);
286MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,...");
287module_param_array(pc104_4, ulong, NULL, 0);
288MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
289
Bjorn Helgaasd269cdd2005-10-30 15:03:14 -0800290static int rp_init(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291static void rp_cleanup_module(void);
292
293module_init(rp_init);
294module_exit(rp_cleanup_module);
295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297MODULE_LICENSE("Dual BSD/GPL");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
299/*************************************************************************/
300/* Module code starts here */
301
302static inline int rocket_paranoia_check(struct r_port *info,
303 const char *routine)
304{
305#ifdef ROCKET_PARANOIA_CHECK
306 if (!info)
307 return 1;
308 if (info->magic != RPORT_MAGIC) {
309 printk(KERN_INFO "Warning: bad magic number for rocketport struct in %s\n",
310 routine);
311 return 1;
312 }
313#endif
314 return 0;
315}
316
317
318/* Serial port receive data function. Called (from timer poll) when an AIOPIC signals
319 * that receive data is present on a serial port. Pulls data from FIFO, moves it into the
320 * tty layer.
321 */
322static void rp_do_receive(struct r_port *info,
323 struct tty_struct *tty,
324 CHANNEL_t * cp, unsigned int ChanStatus)
325{
326 unsigned int CharNStat;
Paul Fulghumcc44a812006-06-25 05:49:12 -0700327 int ToRecv, wRecv, space;
328 unsigned char *cbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330 ToRecv = sGetRxCnt(cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331#ifdef ROCKET_DEBUG_INTR
Paul Fulghumcc44a812006-06-25 05:49:12 -0700332 printk(KERN_INFO "rp_do_receive(%d)...", ToRecv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333#endif
Paul Fulghumcc44a812006-06-25 05:49:12 -0700334 if (ToRecv == 0)
335 return;
Alan Cox33f0f882006-01-09 20:54:13 -0800336
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 /*
338 * if status indicates there are errored characters in the
339 * FIFO, then enter status mode (a word in FIFO holds
340 * character and status).
341 */
342 if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
343 if (!(ChanStatus & STATMODE)) {
344#ifdef ROCKET_DEBUG_RECEIVE
345 printk(KERN_INFO "Entering STATMODE...");
346#endif
347 ChanStatus |= STATMODE;
348 sEnRxStatusMode(cp);
349 }
350 }
351
352 /*
353 * if we previously entered status mode, then read down the
354 * FIFO one word at a time, pulling apart the character and
355 * the status. Update error counters depending on status
356 */
357 if (ChanStatus & STATMODE) {
358#ifdef ROCKET_DEBUG_RECEIVE
359 printk(KERN_INFO "Ignore %x, read %x...", info->ignore_status_mask,
360 info->read_status_mask);
361#endif
362 while (ToRecv) {
Paul Fulghumcc44a812006-06-25 05:49:12 -0700363 char flag;
364
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 CharNStat = sInW(sGetTxRxDataIO(cp));
366#ifdef ROCKET_DEBUG_RECEIVE
367 printk(KERN_INFO "%x...", CharNStat);
368#endif
369 if (CharNStat & STMBREAKH)
370 CharNStat &= ~(STMFRAMEH | STMPARITYH);
371 if (CharNStat & info->ignore_status_mask) {
372 ToRecv--;
373 continue;
374 }
375 CharNStat &= info->read_status_mask;
376 if (CharNStat & STMBREAKH)
Paul Fulghumcc44a812006-06-25 05:49:12 -0700377 flag = TTY_BREAK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 else if (CharNStat & STMPARITYH)
Paul Fulghumcc44a812006-06-25 05:49:12 -0700379 flag = TTY_PARITY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 else if (CharNStat & STMFRAMEH)
Paul Fulghumcc44a812006-06-25 05:49:12 -0700381 flag = TTY_FRAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 else if (CharNStat & STMRCVROVRH)
Paul Fulghumcc44a812006-06-25 05:49:12 -0700383 flag = TTY_OVERRUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 else
Paul Fulghumcc44a812006-06-25 05:49:12 -0700385 flag = TTY_NORMAL;
386 tty_insert_flip_char(tty, CharNStat & 0xff, flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 ToRecv--;
388 }
389
390 /*
391 * after we've emptied the FIFO in status mode, turn
392 * status mode back off
393 */
394 if (sGetRxCnt(cp) == 0) {
395#ifdef ROCKET_DEBUG_RECEIVE
396 printk(KERN_INFO "Status mode off.\n");
397#endif
398 sDisRxStatusMode(cp);
399 }
400 } else {
401 /*
402 * we aren't in status mode, so read down the FIFO two
403 * characters at time by doing repeated word IO
404 * transfer.
405 */
Paul Fulghumcc44a812006-06-25 05:49:12 -0700406 space = tty_prepare_flip_string(tty, &cbuf, ToRecv);
407 if (space < ToRecv) {
408#ifdef ROCKET_DEBUG_RECEIVE
409 printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
410#endif
411 if (space <= 0)
412 return;
413 ToRecv = space;
414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 wRecv = ToRecv >> 1;
416 if (wRecv)
417 sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
418 if (ToRecv & 1)
419 cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 }
421 /* Push the data up to the tty layer */
Paul Fulghumcc44a812006-06-25 05:49:12 -0700422 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423}
424
425/*
426 * Serial port transmit data function. Called from the timer polling loop as a
427 * result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready
428 * to be sent out the serial port. Data is buffered in rp_table[line].xmit_buf, it is
429 * moved to the port's xmit FIFO. *info is critical data, protected by spinlocks.
430 */
431static void rp_do_transmit(struct r_port *info)
432{
433 int c;
434 CHANNEL_t *cp = &info->channel;
435 struct tty_struct *tty;
436 unsigned long flags;
437
438#ifdef ROCKET_DEBUG_INTR
439 printk(KERN_INFO "rp_do_transmit ");
440#endif
441 if (!info)
442 return;
443 if (!info->tty) {
444 printk(KERN_INFO "rp: WARNING rp_do_transmit called with info->tty==NULL\n");
445 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
446 return;
447 }
448
449 spin_lock_irqsave(&info->slock, flags);
450 tty = info->tty;
451 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
452
453 /* Loop sending data to FIFO until done or FIFO full */
454 while (1) {
455 if (tty->stopped || tty->hw_stopped)
456 break;
457 c = min(info->xmit_fifo_room, min(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
458 if (c <= 0 || info->xmit_fifo_room <= 0)
459 break;
460 sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
461 if (c & 1)
462 sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]);
463 info->xmit_tail += c;
464 info->xmit_tail &= XMIT_BUF_SIZE - 1;
465 info->xmit_cnt -= c;
466 info->xmit_fifo_room -= c;
467#ifdef ROCKET_DEBUG_INTR
468 printk(KERN_INFO "tx %d chars...", c);
469#endif
470 }
471
472 if (info->xmit_cnt == 0)
473 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
474
475 if (info->xmit_cnt < WAKEUP_CHARS) {
476 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477#ifdef ROCKETPORT_HAVE_POLL_WAIT
478 wake_up_interruptible(&tty->poll_wait);
479#endif
480 }
481
482 spin_unlock_irqrestore(&info->slock, flags);
483
484#ifdef ROCKET_DEBUG_INTR
485 printk(KERN_INFO "(%d,%d,%d,%d)...", info->xmit_cnt, info->xmit_head,
486 info->xmit_tail, info->xmit_fifo_room);
487#endif
488}
489
490/*
491 * Called when a serial port signals it has read data in it's RX FIFO.
492 * It checks what interrupts are pending and services them, including
493 * receiving serial data.
494 */
495static void rp_handle_port(struct r_port *info)
496{
497 CHANNEL_t *cp;
498 struct tty_struct *tty;
499 unsigned int IntMask, ChanStatus;
500
501 if (!info)
502 return;
503
504 if ((info->flags & ROCKET_INITIALIZED) == 0) {
505 printk(KERN_INFO "rp: WARNING: rp_handle_port called with info->flags & NOT_INIT\n");
506 return;
507 }
508 if (!info->tty) {
509 printk(KERN_INFO "rp: WARNING: rp_handle_port called with info->tty==NULL\n");
510 return;
511 }
512 cp = &info->channel;
513 tty = info->tty;
514
515 IntMask = sGetChanIntID(cp) & info->intmask;
516#ifdef ROCKET_DEBUG_INTR
517 printk(KERN_INFO "rp_interrupt %02x...", IntMask);
518#endif
519 ChanStatus = sGetChanStatus(cp);
520 if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */
521 rp_do_receive(info, tty, cp, ChanStatus);
522 }
523 if (IntMask & DELTA_CD) { /* CD change */
524#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP))
525 printk(KERN_INFO "ttyR%d CD now %s...", info->line,
526 (ChanStatus & CD_ACT) ? "on" : "off");
527#endif
528 if (!(ChanStatus & CD_ACT) && info->cd_status) {
529#ifdef ROCKET_DEBUG_HANGUP
530 printk(KERN_INFO "CD drop, calling hangup.\n");
531#endif
532 tty_hangup(tty);
533 }
534 info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
535 wake_up_interruptible(&info->open_wait);
536 }
537#ifdef ROCKET_DEBUG_INTR
538 if (IntMask & DELTA_CTS) { /* CTS change */
539 printk(KERN_INFO "CTS change...\n");
540 }
541 if (IntMask & DELTA_DSR) { /* DSR change */
542 printk(KERN_INFO "DSR change...\n");
543 }
544#endif
545}
546
547/*
548 * The top level polling routine. Repeats every 1/100 HZ (10ms).
549 */
550static void rp_do_poll(unsigned long dummy)
551{
552 CONTROLLER_t *ctlp;
553 int ctrl, aiop, ch, line, i;
554 unsigned int xmitmask;
555 unsigned int CtlMask;
556 unsigned char AiopMask;
557 Word_t bit;
558
559 /* Walk through all the boards (ctrl's) */
560 for (ctrl = 0; ctrl < max_board; ctrl++) {
561 if (rcktpt_io_addr[ctrl] <= 0)
562 continue;
563
564 /* Get a ptr to the board's control struct */
565 ctlp = sCtlNumToCtlPtr(ctrl);
566
567 /* Get the interupt status from the board */
568#ifdef CONFIG_PCI
569 if (ctlp->BusType == isPCI)
570 CtlMask = sPCIGetControllerIntStatus(ctlp);
571 else
572#endif
573 CtlMask = sGetControllerIntStatus(ctlp);
574
575 /* Check if any AIOP read bits are set */
576 for (aiop = 0; CtlMask; aiop++) {
577 bit = ctlp->AiopIntrBits[aiop];
578 if (CtlMask & bit) {
579 CtlMask &= ~bit;
580 AiopMask = sGetAiopIntStatus(ctlp, aiop);
581
582 /* Check if any port read bits are set */
583 for (ch = 0; AiopMask; AiopMask >>= 1, ch++) {
584 if (AiopMask & 1) {
585
586 /* Get the line number (/dev/ttyRx number). */
587 /* Read the data from the port. */
588 line = GetLineNumber(ctrl, aiop, ch);
589 rp_handle_port(rp_table[line]);
590 }
591 }
592 }
593 }
594
595 xmitmask = xmit_flags[ctrl];
596
597 /*
598 * xmit_flags contains bit-significant flags, indicating there is data
599 * to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port
600 * 1, ... (32 total possible). The variable i has the aiop and ch
601 * numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc).
602 */
603 if (xmitmask) {
604 for (i = 0; i < rocketModel[ctrl].numPorts; i++) {
605 if (xmitmask & (1 << i)) {
606 aiop = (i & 0x18) >> 3;
607 ch = i & 0x07;
608 line = GetLineNumber(ctrl, aiop, ch);
609 rp_do_transmit(rp_table[line]);
610 }
611 }
612 }
613 }
614
615 /*
616 * Reset the timer so we get called at the next clock tick (10ms).
617 */
618 if (atomic_read(&rp_num_ports_open))
619 mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
620}
621
622/*
623 * Initializes the r_port structure for a port, as well as enabling the port on
624 * the board.
625 * Inputs: board, aiop, chan numbers
626 */
627static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
628{
629 unsigned rocketMode;
630 struct r_port *info;
631 int line;
632 CONTROLLER_T *ctlp;
633
634 /* Get the next available line number */
635 line = SetLineNumber(board, aiop, chan);
636
637 ctlp = sCtlNumToCtlPtr(board);
638
639 /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */
640 info = kmalloc(sizeof (struct r_port), GFP_KERNEL);
641 if (!info) {
642 printk(KERN_INFO "Couldn't allocate info struct for line #%d\n", line);
643 return;
644 }
645 memset(info, 0, sizeof (struct r_port));
646
647 info->magic = RPORT_MAGIC;
648 info->line = line;
649 info->ctlp = ctlp;
650 info->board = board;
651 info->aiop = aiop;
652 info->chan = chan;
653 info->closing_wait = 3000;
654 info->close_delay = 50;
655 init_waitqueue_head(&info->open_wait);
656 init_waitqueue_head(&info->close_wait);
657 info->flags &= ~ROCKET_MODE_MASK;
658 switch (pc104[board][line]) {
659 case 422:
660 info->flags |= ROCKET_MODE_RS422;
661 break;
662 case 485:
663 info->flags |= ROCKET_MODE_RS485;
664 break;
665 case 232:
666 default:
667 info->flags |= ROCKET_MODE_RS232;
668 break;
669 }
670
671 info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
672 if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
673 printk(KERN_INFO "RocketPort sInitChan(%d, %d, %d) failed!\n", board, aiop, chan);
674 kfree(info);
675 return;
676 }
677
678 rocketMode = info->flags & ROCKET_MODE_MASK;
679
680 if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485))
681 sEnRTSToggle(&info->channel);
682 else
683 sDisRTSToggle(&info->channel);
684
685 if (ctlp->boardType == ROCKET_TYPE_PC104) {
686 switch (rocketMode) {
687 case ROCKET_MODE_RS485:
688 sSetInterfaceMode(&info->channel, InterfaceModeRS485);
689 break;
690 case ROCKET_MODE_RS422:
691 sSetInterfaceMode(&info->channel, InterfaceModeRS422);
692 break;
693 case ROCKET_MODE_RS232:
694 default:
695 if (info->flags & ROCKET_RTS_TOGGLE)
696 sSetInterfaceMode(&info->channel, InterfaceModeRS232T);
697 else
698 sSetInterfaceMode(&info->channel, InterfaceModeRS232);
699 break;
700 }
701 }
702 spin_lock_init(&info->slock);
703 sema_init(&info->write_sem, 1);
704 rp_table[line] = info;
705 if (pci_dev)
706 tty_register_device(rocket_driver, line, &pci_dev->dev);
707}
708
709/*
710 * Configures a rocketport port according to its termio settings. Called from
711 * user mode into the driver (exception handler). *info CD manipulation is spinlock protected.
712 */
713static void configure_r_port(struct r_port *info,
Alan Cox606d0992006-12-08 02:38:45 -0800714 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
716 unsigned cflag;
717 unsigned long flags;
718 unsigned rocketMode;
719 int bits, baud, divisor;
720 CHANNEL_t *cp;
721
722 if (!info->tty || !info->tty->termios)
723 return;
724 cp = &info->channel;
725 cflag = info->tty->termios->c_cflag;
726
727 /* Byte size and parity */
728 if ((cflag & CSIZE) == CS8) {
729 sSetData8(cp);
730 bits = 10;
731 } else {
732 sSetData7(cp);
733 bits = 9;
734 }
735 if (cflag & CSTOPB) {
736 sSetStop2(cp);
737 bits++;
738 } else {
739 sSetStop1(cp);
740 }
741
742 if (cflag & PARENB) {
743 sEnParity(cp);
744 bits++;
745 if (cflag & PARODD) {
746 sSetOddParity(cp);
747 } else {
748 sSetEvenParity(cp);
749 }
750 } else {
751 sDisParity(cp);
752 }
753
754 /* baud rate */
755 baud = tty_get_baud_rate(info->tty);
756 if (!baud)
757 baud = 9600;
758 divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
759 if ((divisor >= 8192 || divisor < 0) && old_termios) {
760 info->tty->termios->c_cflag &= ~CBAUD;
761 info->tty->termios->c_cflag |=
762 (old_termios->c_cflag & CBAUD);
763 baud = tty_get_baud_rate(info->tty);
764 if (!baud)
765 baud = 9600;
766 divisor = (rp_baud_base[info->board] / baud) - 1;
767 }
768 if (divisor >= 8192 || divisor < 0) {
769 baud = 9600;
770 divisor = (rp_baud_base[info->board] / baud) - 1;
771 }
772 info->cps = baud / bits;
773 sSetBaud(cp, divisor);
774
775 if (cflag & CRTSCTS) {
776 info->intmask |= DELTA_CTS;
777 sEnCTSFlowCtl(cp);
778 } else {
779 info->intmask &= ~DELTA_CTS;
780 sDisCTSFlowCtl(cp);
781 }
782 if (cflag & CLOCAL) {
783 info->intmask &= ~DELTA_CD;
784 } else {
785 spin_lock_irqsave(&info->slock, flags);
786 if (sGetChanStatus(cp) & CD_ACT)
787 info->cd_status = 1;
788 else
789 info->cd_status = 0;
790 info->intmask |= DELTA_CD;
791 spin_unlock_irqrestore(&info->slock, flags);
792 }
793
794 /*
795 * Handle software flow control in the board
796 */
797#ifdef ROCKET_SOFT_FLOW
798 if (I_IXON(info->tty)) {
799 sEnTxSoftFlowCtl(cp);
800 if (I_IXANY(info->tty)) {
801 sEnIXANY(cp);
802 } else {
803 sDisIXANY(cp);
804 }
805 sSetTxXONChar(cp, START_CHAR(info->tty));
806 sSetTxXOFFChar(cp, STOP_CHAR(info->tty));
807 } else {
808 sDisTxSoftFlowCtl(cp);
809 sDisIXANY(cp);
810 sClrTxXOFF(cp);
811 }
812#endif
813
814 /*
815 * Set up ignore/read mask words
816 */
817 info->read_status_mask = STMRCVROVRH | 0xFF;
818 if (I_INPCK(info->tty))
819 info->read_status_mask |= STMFRAMEH | STMPARITYH;
820 if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
821 info->read_status_mask |= STMBREAKH;
822
823 /*
824 * Characters to ignore
825 */
826 info->ignore_status_mask = 0;
827 if (I_IGNPAR(info->tty))
828 info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
829 if (I_IGNBRK(info->tty)) {
830 info->ignore_status_mask |= STMBREAKH;
831 /*
832 * If we're ignoring parity and break indicators,
833 * ignore overruns too. (For real raw support).
834 */
835 if (I_IGNPAR(info->tty))
836 info->ignore_status_mask |= STMRCVROVRH;
837 }
838
839 rocketMode = info->flags & ROCKET_MODE_MASK;
840
841 if ((info->flags & ROCKET_RTS_TOGGLE)
842 || (rocketMode == ROCKET_MODE_RS485))
843 sEnRTSToggle(cp);
844 else
845 sDisRTSToggle(cp);
846
847 sSetRTS(&info->channel);
848
849 if (cp->CtlP->boardType == ROCKET_TYPE_PC104) {
850 switch (rocketMode) {
851 case ROCKET_MODE_RS485:
852 sSetInterfaceMode(cp, InterfaceModeRS485);
853 break;
854 case ROCKET_MODE_RS422:
855 sSetInterfaceMode(cp, InterfaceModeRS422);
856 break;
857 case ROCKET_MODE_RS232:
858 default:
859 if (info->flags & ROCKET_RTS_TOGGLE)
860 sSetInterfaceMode(cp, InterfaceModeRS232T);
861 else
862 sSetInterfaceMode(cp, InterfaceModeRS232);
863 break;
864 }
865 }
866}
867
868/* info->count is considered critical, protected by spinlocks. */
869static int block_til_ready(struct tty_struct *tty, struct file *filp,
870 struct r_port *info)
871{
872 DECLARE_WAITQUEUE(wait, current);
873 int retval;
874 int do_clocal = 0, extra_count = 0;
875 unsigned long flags;
876
877 /*
878 * If the device is in the middle of being closed, then block
879 * until it's done, and then try again.
880 */
881 if (tty_hung_up_p(filp))
882 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
883 if (info->flags & ROCKET_CLOSING) {
884 interruptible_sleep_on(&info->close_wait);
885 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
886 }
887
888 /*
889 * If non-blocking mode is set, or the port is not enabled,
890 * then make the check up front and then exit.
891 */
892 if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
893 info->flags |= ROCKET_NORMAL_ACTIVE;
894 return 0;
895 }
896 if (tty->termios->c_cflag & CLOCAL)
897 do_clocal = 1;
898
899 /*
900 * Block waiting for the carrier detect and the line to become free. While we are in
901 * this loop, info->count is dropped by one, so that rp_close() knows when to free things.
902 * We restore it upon exit, either normal or abnormal.
903 */
904 retval = 0;
905 add_wait_queue(&info->open_wait, &wait);
906#ifdef ROCKET_DEBUG_OPEN
907 printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, info->count);
908#endif
909 spin_lock_irqsave(&info->slock, flags);
910
911#ifdef ROCKET_DISABLE_SIMUSAGE
912 info->flags |= ROCKET_NORMAL_ACTIVE;
913#else
914 if (!tty_hung_up_p(filp)) {
915 extra_count = 1;
916 info->count--;
917 }
918#endif
919 info->blocked_open++;
920
921 spin_unlock_irqrestore(&info->slock, flags);
922
923 while (1) {
924 if (tty->termios->c_cflag & CBAUD) {
925 sSetDTR(&info->channel);
926 sSetRTS(&info->channel);
927 }
928 set_current_state(TASK_INTERRUPTIBLE);
929 if (tty_hung_up_p(filp) || !(info->flags & ROCKET_INITIALIZED)) {
930 if (info->flags & ROCKET_HUP_NOTIFY)
931 retval = -EAGAIN;
932 else
933 retval = -ERESTARTSYS;
934 break;
935 }
936 if (!(info->flags & ROCKET_CLOSING) && (do_clocal || (sGetChanStatusLo(&info->channel) & CD_ACT)))
937 break;
938 if (signal_pending(current)) {
939 retval = -ERESTARTSYS;
940 break;
941 }
942#ifdef ROCKET_DEBUG_OPEN
943 printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n",
944 info->line, info->count, info->flags);
945#endif
946 schedule(); /* Don't hold spinlock here, will hang PC */
947 }
948 current->state = TASK_RUNNING;
949 remove_wait_queue(&info->open_wait, &wait);
950
951 spin_lock_irqsave(&info->slock, flags);
952
953 if (extra_count)
954 info->count++;
955 info->blocked_open--;
956
957 spin_unlock_irqrestore(&info->slock, flags);
958
959#ifdef ROCKET_DEBUG_OPEN
960 printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n",
961 info->line, info->count);
962#endif
963 if (retval)
964 return retval;
965 info->flags |= ROCKET_NORMAL_ACTIVE;
966 return 0;
967}
968
969/*
970 * Exception handler that opens a serial port. Creates xmit_buf storage, fills in
971 * port's r_port struct. Initializes the port hardware.
972 */
973static int rp_open(struct tty_struct *tty, struct file *filp)
974{
975 struct r_port *info;
976 int line = 0, retval;
977 CHANNEL_t *cp;
978 unsigned long page;
979
980 line = TTY_GET_LINE(tty);
981 if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL))
982 return -ENXIO;
983
984 page = __get_free_page(GFP_KERNEL);
985 if (!page)
986 return -ENOMEM;
987
988 if (info->flags & ROCKET_CLOSING) {
989 interruptible_sleep_on(&info->close_wait);
990 free_page(page);
991 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
992 }
993
994 /*
995 * We must not sleep from here until the port is marked fully in use.
996 */
997 if (info->xmit_buf)
998 free_page(page);
999 else
1000 info->xmit_buf = (unsigned char *) page;
1001
1002 tty->driver_data = info;
1003 info->tty = tty;
1004
1005 if (info->count++ == 0) {
1006 atomic_inc(&rp_num_ports_open);
1007
1008#ifdef ROCKET_DEBUG_OPEN
1009 printk(KERN_INFO "rocket mod++ = %d...", atomic_read(&rp_num_ports_open));
1010#endif
1011 }
1012#ifdef ROCKET_DEBUG_OPEN
1013 printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->count);
1014#endif
1015
1016 /*
1017 * Info->count is now 1; so it's safe to sleep now.
1018 */
Cedric Le Goater937949d2006-12-08 02:37:54 -08001019 info->session = process_session(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 info->pgrp = process_group(current);
1021
1022 if ((info->flags & ROCKET_INITIALIZED) == 0) {
1023 cp = &info->channel;
1024 sSetRxTrigger(cp, TRIG_1);
1025 if (sGetChanStatus(cp) & CD_ACT)
1026 info->cd_status = 1;
1027 else
1028 info->cd_status = 0;
1029 sDisRxStatusMode(cp);
1030 sFlushRxFIFO(cp);
1031 sFlushTxFIFO(cp);
1032
1033 sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
1034 sSetRxTrigger(cp, TRIG_1);
1035
1036 sGetChanStatus(cp);
1037 sDisRxStatusMode(cp);
1038 sClrTxXOFF(cp);
1039
1040 sDisCTSFlowCtl(cp);
1041 sDisTxSoftFlowCtl(cp);
1042
1043 sEnRxFIFO(cp);
1044 sEnTransmit(cp);
1045
1046 info->flags |= ROCKET_INITIALIZED;
1047
1048 /*
1049 * Set up the tty->alt_speed kludge
1050 */
1051 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
1052 info->tty->alt_speed = 57600;
1053 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
1054 info->tty->alt_speed = 115200;
1055 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
1056 info->tty->alt_speed = 230400;
1057 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
1058 info->tty->alt_speed = 460800;
1059
1060 configure_r_port(info, NULL);
1061 if (tty->termios->c_cflag & CBAUD) {
1062 sSetDTR(cp);
1063 sSetRTS(cp);
1064 }
1065 }
1066 /* Starts (or resets) the maint polling loop */
1067 mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
1068
1069 retval = block_til_ready(tty, filp, info);
1070 if (retval) {
1071#ifdef ROCKET_DEBUG_OPEN
1072 printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval);
1073#endif
1074 return retval;
1075 }
1076 return 0;
1077}
1078
1079/*
1080 * Exception handler that closes a serial port. info->count is considered critical.
1081 */
1082static void rp_close(struct tty_struct *tty, struct file *filp)
1083{
1084 struct r_port *info = (struct r_port *) tty->driver_data;
1085 unsigned long flags;
1086 int timeout;
1087 CHANNEL_t *cp;
1088
1089 if (rocket_paranoia_check(info, "rp_close"))
1090 return;
1091
1092#ifdef ROCKET_DEBUG_OPEN
1093 printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->count);
1094#endif
1095
1096 if (tty_hung_up_p(filp))
1097 return;
1098 spin_lock_irqsave(&info->slock, flags);
1099
1100 if ((tty->count == 1) && (info->count != 1)) {
1101 /*
1102 * Uh, oh. tty->count is 1, which means that the tty
1103 * structure will be freed. Info->count should always
1104 * be one in these conditions. If it's greater than
1105 * one, we've got real problems, since it means the
1106 * serial port won't be shutdown.
1107 */
1108 printk(KERN_INFO "rp_close: bad serial port count; tty->count is 1, "
1109 "info->count is %d\n", info->count);
1110 info->count = 1;
1111 }
1112 if (--info->count < 0) {
1113 printk(KERN_INFO "rp_close: bad serial port count for ttyR%d: %d\n",
1114 info->line, info->count);
1115 info->count = 0;
1116 }
1117 if (info->count) {
1118 spin_unlock_irqrestore(&info->slock, flags);
1119 return;
1120 }
1121 info->flags |= ROCKET_CLOSING;
1122 spin_unlock_irqrestore(&info->slock, flags);
1123
1124 cp = &info->channel;
1125
1126 /*
1127 * Notify the line discpline to only process XON/XOFF characters
1128 */
1129 tty->closing = 1;
1130
1131 /*
1132 * If transmission was throttled by the application request,
1133 * just flush the xmit buffer.
1134 */
1135 if (tty->flow_stopped)
1136 rp_flush_buffer(tty);
1137
1138 /*
1139 * Wait for the transmit buffer to clear
1140 */
1141 if (info->closing_wait != ROCKET_CLOSING_WAIT_NONE)
1142 tty_wait_until_sent(tty, info->closing_wait);
1143 /*
1144 * Before we drop DTR, make sure the UART transmitter
1145 * has completely drained; this is especially
1146 * important if there is a transmit FIFO!
1147 */
1148 timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps;
1149 if (timeout == 0)
1150 timeout = 1;
1151 rp_wait_until_sent(tty, timeout);
1152 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1153
1154 sDisTransmit(cp);
1155 sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
1156 sDisCTSFlowCtl(cp);
1157 sDisTxSoftFlowCtl(cp);
1158 sClrTxXOFF(cp);
1159 sFlushRxFIFO(cp);
1160 sFlushTxFIFO(cp);
1161 sClrRTS(cp);
1162 if (C_HUPCL(tty))
1163 sClrDTR(cp);
1164
1165 if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty))
1166 TTY_DRIVER_FLUSH_BUFFER(tty);
1167
1168 tty_ldisc_flush(tty);
1169
1170 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1171
1172 if (info->blocked_open) {
1173 if (info->close_delay) {
1174 msleep_interruptible(jiffies_to_msecs(info->close_delay));
1175 }
1176 wake_up_interruptible(&info->open_wait);
1177 } else {
1178 if (info->xmit_buf) {
1179 free_page((unsigned long) info->xmit_buf);
1180 info->xmit_buf = NULL;
1181 }
1182 }
1183 info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING | ROCKET_NORMAL_ACTIVE);
1184 tty->closing = 0;
1185 wake_up_interruptible(&info->close_wait);
1186 atomic_dec(&rp_num_ports_open);
1187
1188#ifdef ROCKET_DEBUG_OPEN
1189 printk(KERN_INFO "rocket mod-- = %d...", atomic_read(&rp_num_ports_open));
1190 printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line);
1191#endif
1192
1193}
1194
1195static void rp_set_termios(struct tty_struct *tty,
Alan Cox606d0992006-12-08 02:38:45 -08001196 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197{
1198 struct r_port *info = (struct r_port *) tty->driver_data;
1199 CHANNEL_t *cp;
1200 unsigned cflag;
1201
1202 if (rocket_paranoia_check(info, "rp_set_termios"))
1203 return;
1204
1205 cflag = tty->termios->c_cflag;
1206
1207 if (cflag == old_termios->c_cflag)
1208 return;
1209
1210 /*
1211 * This driver doesn't support CS5 or CS6
1212 */
1213 if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
1214 tty->termios->c_cflag =
1215 ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
1216
1217 configure_r_port(info, old_termios);
1218
1219 cp = &info->channel;
1220
1221 /* Handle transition to B0 status */
1222 if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
1223 sClrDTR(cp);
1224 sClrRTS(cp);
1225 }
1226
1227 /* Handle transition away from B0 status */
1228 if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) {
1229 if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS))
1230 sSetRTS(cp);
1231 sSetDTR(cp);
1232 }
1233
1234 if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
1235 tty->hw_stopped = 0;
1236 rp_start(tty);
1237 }
1238}
1239
1240static void rp_break(struct tty_struct *tty, int break_state)
1241{
1242 struct r_port *info = (struct r_port *) tty->driver_data;
1243 unsigned long flags;
1244
1245 if (rocket_paranoia_check(info, "rp_break"))
1246 return;
1247
1248 spin_lock_irqsave(&info->slock, flags);
1249 if (break_state == -1)
1250 sSendBreak(&info->channel);
1251 else
1252 sClrBreak(&info->channel);
1253 spin_unlock_irqrestore(&info->slock, flags);
1254}
1255
1256/*
1257 * sGetChanRI used to be a macro in rocket_int.h. When the functionality for
1258 * the UPCI boards was added, it was decided to make this a function because
1259 * the macro was getting too complicated. All cases except the first one
1260 * (UPCIRingInd) are taken directly from the original macro.
1261 */
1262static int sGetChanRI(CHANNEL_T * ChP)
1263{
1264 CONTROLLER_t *CtlP = ChP->CtlP;
1265 int ChanNum = ChP->ChanNum;
1266 int RingInd = 0;
1267
1268 if (CtlP->UPCIRingInd)
1269 RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]);
1270 else if (CtlP->AltChanRingIndicator)
1271 RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT;
1272 else if (CtlP->boardType == ROCKET_TYPE_PC104)
1273 RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]);
1274
1275 return RingInd;
1276}
1277
1278/********************************************************************************************/
1279/* Here are the routines used by rp_ioctl. These are all called from exception handlers. */
1280
1281/*
1282 * Returns the state of the serial modem control lines. These next 2 functions
1283 * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
1284 */
1285static int rp_tiocmget(struct tty_struct *tty, struct file *file)
1286{
1287 struct r_port *info = (struct r_port *)tty->driver_data;
1288 unsigned int control, result, ChanStatus;
1289
1290 ChanStatus = sGetChanStatusLo(&info->channel);
1291 control = info->channel.TxControl[3];
1292 result = ((control & SET_RTS) ? TIOCM_RTS : 0) |
1293 ((control & SET_DTR) ? TIOCM_DTR : 0) |
1294 ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
1295 (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
1296 ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
1297 ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
1298
1299 return result;
1300}
1301
1302/*
1303 * Sets the modem control lines
1304 */
1305static int rp_tiocmset(struct tty_struct *tty, struct file *file,
1306 unsigned int set, unsigned int clear)
1307{
1308 struct r_port *info = (struct r_port *)tty->driver_data;
1309
1310 if (set & TIOCM_RTS)
1311 info->channel.TxControl[3] |= SET_RTS;
1312 if (set & TIOCM_DTR)
1313 info->channel.TxControl[3] |= SET_DTR;
1314 if (clear & TIOCM_RTS)
1315 info->channel.TxControl[3] &= ~SET_RTS;
1316 if (clear & TIOCM_DTR)
1317 info->channel.TxControl[3] &= ~SET_DTR;
1318
1319 sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0]));
1320 return 0;
1321}
1322
1323static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
1324{
1325 struct rocket_config tmp;
1326
1327 if (!retinfo)
1328 return -EFAULT;
1329 memset(&tmp, 0, sizeof (tmp));
1330 tmp.line = info->line;
1331 tmp.flags = info->flags;
1332 tmp.close_delay = info->close_delay;
1333 tmp.closing_wait = info->closing_wait;
1334 tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
1335
1336 if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
1337 return -EFAULT;
1338 return 0;
1339}
1340
1341static int set_config(struct r_port *info, struct rocket_config __user *new_info)
1342{
1343 struct rocket_config new_serial;
1344
1345 if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
1346 return -EFAULT;
1347
1348 if (!capable(CAP_SYS_ADMIN))
1349 {
1350 if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
1351 return -EPERM;
1352 info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
1353 configure_r_port(info, NULL);
1354 return 0;
1355 }
1356
1357 info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
1358 info->close_delay = new_serial.close_delay;
1359 info->closing_wait = new_serial.closing_wait;
1360
1361 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
1362 info->tty->alt_speed = 57600;
1363 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
1364 info->tty->alt_speed = 115200;
1365 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
1366 info->tty->alt_speed = 230400;
1367 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
1368 info->tty->alt_speed = 460800;
1369
1370 configure_r_port(info, NULL);
1371 return 0;
1372}
1373
1374/*
1375 * This function fills in a rocket_ports struct with information
1376 * about what boards/ports are in the system. This info is passed
1377 * to user space. See setrocket.c where the info is used to create
1378 * the /dev/ttyRx ports.
1379 */
1380static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
1381{
1382 struct rocket_ports tmp;
1383 int board;
1384
1385 if (!retports)
1386 return -EFAULT;
1387 memset(&tmp, 0, sizeof (tmp));
1388 tmp.tty_major = rocket_driver->major;
1389
1390 for (board = 0; board < 4; board++) {
1391 tmp.rocketModel[board].model = rocketModel[board].model;
1392 strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString);
1393 tmp.rocketModel[board].numPorts = rocketModel[board].numPorts;
1394 tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
1395 tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber;
1396 }
1397 if (copy_to_user(retports, &tmp, sizeof (*retports)))
1398 return -EFAULT;
1399 return 0;
1400}
1401
1402static int reset_rm2(struct r_port *info, void __user *arg)
1403{
1404 int reset;
1405
1406 if (copy_from_user(&reset, arg, sizeof (int)))
1407 return -EFAULT;
1408 if (reset)
1409 reset = 1;
1410
1411 if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII &&
1412 rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII)
1413 return -EINVAL;
1414
1415 if (info->ctlp->BusType == isISA)
1416 sModemReset(info->ctlp, info->chan, reset);
1417 else
1418 sPCIModemReset(info->ctlp, info->chan, reset);
1419
1420 return 0;
1421}
1422
1423static int get_version(struct r_port *info, struct rocket_version __user *retvers)
1424{
1425 if (copy_to_user(retvers, &driver_version, sizeof (*retvers)))
1426 return -EFAULT;
1427 return 0;
1428}
1429
1430/* IOCTL call handler into the driver */
1431static int rp_ioctl(struct tty_struct *tty, struct file *file,
1432 unsigned int cmd, unsigned long arg)
1433{
1434 struct r_port *info = (struct r_port *) tty->driver_data;
1435 void __user *argp = (void __user *)arg;
1436
1437 if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
1438 return -ENXIO;
1439
1440 switch (cmd) {
1441 case RCKP_GET_STRUCT:
1442 if (copy_to_user(argp, info, sizeof (struct r_port)))
1443 return -EFAULT;
1444 return 0;
1445 case RCKP_GET_CONFIG:
1446 return get_config(info, argp);
1447 case RCKP_SET_CONFIG:
1448 return set_config(info, argp);
1449 case RCKP_GET_PORTS:
1450 return get_ports(info, argp);
1451 case RCKP_RESET_RM2:
1452 return reset_rm2(info, argp);
1453 case RCKP_GET_VERSION:
1454 return get_version(info, argp);
1455 default:
1456 return -ENOIOCTLCMD;
1457 }
1458 return 0;
1459}
1460
1461static void rp_send_xchar(struct tty_struct *tty, char ch)
1462{
1463 struct r_port *info = (struct r_port *) tty->driver_data;
1464 CHANNEL_t *cp;
1465
1466 if (rocket_paranoia_check(info, "rp_send_xchar"))
1467 return;
1468
1469 cp = &info->channel;
1470 if (sGetTxCnt(cp))
1471 sWriteTxPrioByte(cp, ch);
1472 else
1473 sWriteTxByte(sGetTxRxDataIO(cp), ch);
1474}
1475
1476static void rp_throttle(struct tty_struct *tty)
1477{
1478 struct r_port *info = (struct r_port *) tty->driver_data;
1479 CHANNEL_t *cp;
1480
1481#ifdef ROCKET_DEBUG_THROTTLE
1482 printk(KERN_INFO "throttle %s: %d....\n", tty->name,
1483 tty->ldisc.chars_in_buffer(tty));
1484#endif
1485
1486 if (rocket_paranoia_check(info, "rp_throttle"))
1487 return;
1488
1489 cp = &info->channel;
1490 if (I_IXOFF(tty))
1491 rp_send_xchar(tty, STOP_CHAR(tty));
1492
1493 sClrRTS(&info->channel);
1494}
1495
1496static void rp_unthrottle(struct tty_struct *tty)
1497{
1498 struct r_port *info = (struct r_port *) tty->driver_data;
1499 CHANNEL_t *cp;
1500#ifdef ROCKET_DEBUG_THROTTLE
1501 printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
1502 tty->ldisc.chars_in_buffer(tty));
1503#endif
1504
1505 if (rocket_paranoia_check(info, "rp_throttle"))
1506 return;
1507
1508 cp = &info->channel;
1509 if (I_IXOFF(tty))
1510 rp_send_xchar(tty, START_CHAR(tty));
1511
1512 sSetRTS(&info->channel);
1513}
1514
1515/*
1516 * ------------------------------------------------------------
1517 * rp_stop() and rp_start()
1518 *
1519 * This routines are called before setting or resetting tty->stopped.
1520 * They enable or disable transmitter interrupts, as necessary.
1521 * ------------------------------------------------------------
1522 */
1523static void rp_stop(struct tty_struct *tty)
1524{
1525 struct r_port *info = (struct r_port *) tty->driver_data;
1526
1527#ifdef ROCKET_DEBUG_FLOW
1528 printk(KERN_INFO "stop %s: %d %d....\n", tty->name,
1529 info->xmit_cnt, info->xmit_fifo_room);
1530#endif
1531
1532 if (rocket_paranoia_check(info, "rp_stop"))
1533 return;
1534
1535 if (sGetTxCnt(&info->channel))
1536 sDisTransmit(&info->channel);
1537}
1538
1539static void rp_start(struct tty_struct *tty)
1540{
1541 struct r_port *info = (struct r_port *) tty->driver_data;
1542
1543#ifdef ROCKET_DEBUG_FLOW
1544 printk(KERN_INFO "start %s: %d %d....\n", tty->name,
1545 info->xmit_cnt, info->xmit_fifo_room);
1546#endif
1547
1548 if (rocket_paranoia_check(info, "rp_stop"))
1549 return;
1550
1551 sEnTransmit(&info->channel);
1552 set_bit((info->aiop * 8) + info->chan,
1553 (void *) &xmit_flags[info->board]);
1554}
1555
1556/*
1557 * rp_wait_until_sent() --- wait until the transmitter is empty
1558 */
1559static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
1560{
1561 struct r_port *info = (struct r_port *) tty->driver_data;
1562 CHANNEL_t *cp;
1563 unsigned long orig_jiffies;
1564 int check_time, exit_time;
1565 int txcnt;
1566
1567 if (rocket_paranoia_check(info, "rp_wait_until_sent"))
1568 return;
1569
1570 cp = &info->channel;
1571
1572 orig_jiffies = jiffies;
1573#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1574 printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...", timeout,
1575 jiffies);
1576 printk(KERN_INFO "cps=%d...", info->cps);
1577#endif
1578 while (1) {
1579 txcnt = sGetTxCnt(cp);
1580 if (!txcnt) {
1581 if (sGetChanStatusLo(cp) & TXSHRMT)
1582 break;
1583 check_time = (HZ / info->cps) / 5;
1584 } else {
1585 check_time = HZ * txcnt / info->cps;
1586 }
1587 if (timeout) {
1588 exit_time = orig_jiffies + timeout - jiffies;
1589 if (exit_time <= 0)
1590 break;
1591 if (exit_time < check_time)
1592 check_time = exit_time;
1593 }
1594 if (check_time == 0)
1595 check_time = 1;
1596#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1597 printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...", txcnt, jiffies, check_time);
1598#endif
1599 msleep_interruptible(jiffies_to_msecs(check_time));
1600 if (signal_pending(current))
1601 break;
1602 }
1603 current->state = TASK_RUNNING;
1604#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1605 printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
1606#endif
1607}
1608
1609/*
1610 * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
1611 */
1612static void rp_hangup(struct tty_struct *tty)
1613{
1614 CHANNEL_t *cp;
1615 struct r_port *info = (struct r_port *) tty->driver_data;
1616
1617 if (rocket_paranoia_check(info, "rp_hangup"))
1618 return;
1619
1620#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
1621 printk(KERN_INFO "rp_hangup of ttyR%d...", info->line);
1622#endif
1623 rp_flush_buffer(tty);
1624 if (info->flags & ROCKET_CLOSING)
1625 return;
1626 if (info->count)
1627 atomic_dec(&rp_num_ports_open);
1628 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1629
1630 info->count = 0;
1631 info->flags &= ~ROCKET_NORMAL_ACTIVE;
1632 info->tty = NULL;
1633
1634 cp = &info->channel;
1635 sDisRxFIFO(cp);
1636 sDisTransmit(cp);
1637 sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
1638 sDisCTSFlowCtl(cp);
1639 sDisTxSoftFlowCtl(cp);
1640 sClrTxXOFF(cp);
1641 info->flags &= ~ROCKET_INITIALIZED;
1642
1643 wake_up_interruptible(&info->open_wait);
1644}
1645
1646/*
1647 * Exception handler - write char routine. The RocketPort driver uses a
1648 * double-buffering strategy, with the twist that if the in-memory CPU
1649 * buffer is empty, and there's space in the transmit FIFO, the
1650 * writing routines will write directly to transmit FIFO.
1651 * Write buffer and counters protected by spinlocks
1652 */
1653static void rp_put_char(struct tty_struct *tty, unsigned char ch)
1654{
1655 struct r_port *info = (struct r_port *) tty->driver_data;
1656 CHANNEL_t *cp;
1657 unsigned long flags;
1658
1659 if (rocket_paranoia_check(info, "rp_put_char"))
1660 return;
1661
1662 /* Grab the port write semaphore, locking out other processes that try to write to this port */
1663 down(&info->write_sem);
1664
1665#ifdef ROCKET_DEBUG_WRITE
1666 printk(KERN_INFO "rp_put_char %c...", ch);
1667#endif
1668
1669 spin_lock_irqsave(&info->slock, flags);
1670 cp = &info->channel;
1671
1672 if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
1673 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1674
1675 if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
1676 info->xmit_buf[info->xmit_head++] = ch;
1677 info->xmit_head &= XMIT_BUF_SIZE - 1;
1678 info->xmit_cnt++;
1679 set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1680 } else {
1681 sOutB(sGetTxRxDataIO(cp), ch);
1682 info->xmit_fifo_room--;
1683 }
1684 spin_unlock_irqrestore(&info->slock, flags);
1685 up(&info->write_sem);
1686}
1687
1688/*
1689 * Exception handler - write routine, called when user app writes to the device.
1690 * A per port write semaphore is used to protect from another process writing to
1691 * this port at the same time. This other process could be running on the other CPU
1692 * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out).
1693 * Spinlocks protect the info xmit members.
1694 */
1695static int rp_write(struct tty_struct *tty,
1696 const unsigned char *buf, int count)
1697{
1698 struct r_port *info = (struct r_port *) tty->driver_data;
1699 CHANNEL_t *cp;
1700 const unsigned char *b;
1701 int c, retval = 0;
1702 unsigned long flags;
1703
1704 if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
1705 return 0;
1706
1707 down_interruptible(&info->write_sem);
1708
1709#ifdef ROCKET_DEBUG_WRITE
1710 printk(KERN_INFO "rp_write %d chars...", count);
1711#endif
1712 cp = &info->channel;
1713
1714 if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count)
1715 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1716
1717 /*
1718 * If the write queue for the port is empty, and there is FIFO space, stuff bytes
1719 * into FIFO. Use the write queue for temp storage.
1720 */
1721 if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
1722 c = min(count, info->xmit_fifo_room);
1723 b = buf;
1724
1725 /* Push data into FIFO, 2 bytes at a time */
1726 sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2);
1727
1728 /* If there is a byte remaining, write it */
1729 if (c & 1)
1730 sOutB(sGetTxRxDataIO(cp), b[c - 1]);
1731
1732 retval += c;
1733 buf += c;
1734 count -= c;
1735
1736 spin_lock_irqsave(&info->slock, flags);
1737 info->xmit_fifo_room -= c;
1738 spin_unlock_irqrestore(&info->slock, flags);
1739 }
1740
1741 /* If count is zero, we wrote it all and are done */
1742 if (!count)
1743 goto end;
1744
1745 /* Write remaining data into the port's xmit_buf */
1746 while (1) {
1747 if (info->tty == 0) /* Seemingly obligatory check... */
1748 goto end;
1749
1750 c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
1751 if (c <= 0)
1752 break;
1753
1754 b = buf;
1755 memcpy(info->xmit_buf + info->xmit_head, b, c);
1756
1757 spin_lock_irqsave(&info->slock, flags);
1758 info->xmit_head =
1759 (info->xmit_head + c) & (XMIT_BUF_SIZE - 1);
1760 info->xmit_cnt += c;
1761 spin_unlock_irqrestore(&info->slock, flags);
1762
1763 buf += c;
1764 count -= c;
1765 retval += c;
1766 }
1767
1768 if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
1769 set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1770
1771end:
1772 if (info->xmit_cnt < WAKEUP_CHARS) {
1773 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774#ifdef ROCKETPORT_HAVE_POLL_WAIT
1775 wake_up_interruptible(&tty->poll_wait);
1776#endif
1777 }
1778 up(&info->write_sem);
1779 return retval;
1780}
1781
1782/*
1783 * Return the number of characters that can be sent. We estimate
1784 * only using the in-memory transmit buffer only, and ignore the
1785 * potential space in the transmit FIFO.
1786 */
1787static int rp_write_room(struct tty_struct *tty)
1788{
1789 struct r_port *info = (struct r_port *) tty->driver_data;
1790 int ret;
1791
1792 if (rocket_paranoia_check(info, "rp_write_room"))
1793 return 0;
1794
1795 ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
1796 if (ret < 0)
1797 ret = 0;
1798#ifdef ROCKET_DEBUG_WRITE
1799 printk(KERN_INFO "rp_write_room returns %d...", ret);
1800#endif
1801 return ret;
1802}
1803
1804/*
1805 * Return the number of characters in the buffer. Again, this only
1806 * counts those characters in the in-memory transmit buffer.
1807 */
1808static int rp_chars_in_buffer(struct tty_struct *tty)
1809{
1810 struct r_port *info = (struct r_port *) tty->driver_data;
1811 CHANNEL_t *cp;
1812
1813 if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
1814 return 0;
1815
1816 cp = &info->channel;
1817
1818#ifdef ROCKET_DEBUG_WRITE
1819 printk(KERN_INFO "rp_chars_in_buffer returns %d...", info->xmit_cnt);
1820#endif
1821 return info->xmit_cnt;
1822}
1823
1824/*
1825 * Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the
1826 * r_port struct for the port. Note that spinlock are used to protect info members,
1827 * do not call this function if the spinlock is already held.
1828 */
1829static void rp_flush_buffer(struct tty_struct *tty)
1830{
1831 struct r_port *info = (struct r_port *) tty->driver_data;
1832 CHANNEL_t *cp;
1833 unsigned long flags;
1834
1835 if (rocket_paranoia_check(info, "rp_flush_buffer"))
1836 return;
1837
1838 spin_lock_irqsave(&info->slock, flags);
1839 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1840 spin_unlock_irqrestore(&info->slock, flags);
1841
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842#ifdef ROCKETPORT_HAVE_POLL_WAIT
1843 wake_up_interruptible(&tty->poll_wait);
1844#endif
1845 tty_wakeup(tty);
1846
1847 cp = &info->channel;
1848 sFlushTxFIFO(cp);
1849}
1850
1851#ifdef CONFIG_PCI
1852
1853/*
1854 * Called when a PCI card is found. Retrieves and stores model information,
1855 * init's aiopic and serial port hardware.
1856 * Inputs: i is the board number (0-n)
1857 */
Adrian Bunkf15313b2005-06-25 14:59:05 -07001858static __init int register_PCI(int i, struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859{
1860 int num_aiops, aiop, max_num_aiops, num_chan, chan;
1861 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1862 char *str, *board_type;
1863 CONTROLLER_t *ctlp;
1864
1865 int fast_clock = 0;
1866 int altChanRingIndicator = 0;
1867 int ports_per_aiop = 8;
1868 int ret;
1869 unsigned int class_rev;
1870 WordIO_t ConfigIO = 0;
1871 ByteIO_t UPCIRingInd = 0;
1872
1873 if (!dev || pci_enable_device(dev))
1874 return 0;
1875
1876 rcktpt_io_addr[i] = pci_resource_start(dev, 0);
1877 ret = pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
1878
1879 if (ret) {
1880 printk(KERN_INFO " Error during register_PCI(), unable to read config dword \n");
1881 return 0;
1882 }
1883
1884 rcktpt_type[i] = ROCKET_TYPE_NORMAL;
1885 rocketModel[i].loadrm2 = 0;
1886 rocketModel[i].startingPortNumber = nextLineNumber;
1887
1888 /* Depending on the model, set up some config variables */
1889 switch (dev->device) {
1890 case PCI_DEVICE_ID_RP4QUAD:
1891 str = "Quadcable";
1892 max_num_aiops = 1;
1893 ports_per_aiop = 4;
1894 rocketModel[i].model = MODEL_RP4QUAD;
1895 strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable");
1896 rocketModel[i].numPorts = 4;
1897 break;
1898 case PCI_DEVICE_ID_RP8OCTA:
1899 str = "Octacable";
1900 max_num_aiops = 1;
1901 rocketModel[i].model = MODEL_RP8OCTA;
1902 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
1903 rocketModel[i].numPorts = 8;
1904 break;
1905 case PCI_DEVICE_ID_URP8OCTA:
1906 str = "Octacable";
1907 max_num_aiops = 1;
1908 rocketModel[i].model = MODEL_UPCI_RP8OCTA;
1909 strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
1910 rocketModel[i].numPorts = 8;
1911 break;
1912 case PCI_DEVICE_ID_RP8INTF:
1913 str = "8";
1914 max_num_aiops = 1;
1915 rocketModel[i].model = MODEL_RP8INTF;
1916 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
1917 rocketModel[i].numPorts = 8;
1918 break;
1919 case PCI_DEVICE_ID_URP8INTF:
1920 str = "8";
1921 max_num_aiops = 1;
1922 rocketModel[i].model = MODEL_UPCI_RP8INTF;
1923 strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
1924 rocketModel[i].numPorts = 8;
1925 break;
1926 case PCI_DEVICE_ID_RP8J:
1927 str = "8J";
1928 max_num_aiops = 1;
1929 rocketModel[i].model = MODEL_RP8J;
1930 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
1931 rocketModel[i].numPorts = 8;
1932 break;
1933 case PCI_DEVICE_ID_RP4J:
1934 str = "4J";
1935 max_num_aiops = 1;
1936 ports_per_aiop = 4;
1937 rocketModel[i].model = MODEL_RP4J;
1938 strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors");
1939 rocketModel[i].numPorts = 4;
1940 break;
1941 case PCI_DEVICE_ID_RP8SNI:
1942 str = "8 (DB78 Custom)";
1943 max_num_aiops = 1;
1944 rocketModel[i].model = MODEL_RP8SNI;
1945 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
1946 rocketModel[i].numPorts = 8;
1947 break;
1948 case PCI_DEVICE_ID_RP16SNI:
1949 str = "16 (DB78 Custom)";
1950 max_num_aiops = 2;
1951 rocketModel[i].model = MODEL_RP16SNI;
1952 strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
1953 rocketModel[i].numPorts = 16;
1954 break;
1955 case PCI_DEVICE_ID_RP16INTF:
1956 str = "16";
1957 max_num_aiops = 2;
1958 rocketModel[i].model = MODEL_RP16INTF;
1959 strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
1960 rocketModel[i].numPorts = 16;
1961 break;
1962 case PCI_DEVICE_ID_URP16INTF:
1963 str = "16";
1964 max_num_aiops = 2;
1965 rocketModel[i].model = MODEL_UPCI_RP16INTF;
1966 strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
1967 rocketModel[i].numPorts = 16;
1968 break;
1969 case PCI_DEVICE_ID_CRP16INTF:
1970 str = "16";
1971 max_num_aiops = 2;
1972 rocketModel[i].model = MODEL_CPCI_RP16INTF;
1973 strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
1974 rocketModel[i].numPorts = 16;
1975 break;
1976 case PCI_DEVICE_ID_RP32INTF:
1977 str = "32";
1978 max_num_aiops = 4;
1979 rocketModel[i].model = MODEL_RP32INTF;
1980 strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
1981 rocketModel[i].numPorts = 32;
1982 break;
1983 case PCI_DEVICE_ID_URP32INTF:
1984 str = "32";
1985 max_num_aiops = 4;
1986 rocketModel[i].model = MODEL_UPCI_RP32INTF;
1987 strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
1988 rocketModel[i].numPorts = 32;
1989 break;
1990 case PCI_DEVICE_ID_RPP4:
1991 str = "Plus Quadcable";
1992 max_num_aiops = 1;
1993 ports_per_aiop = 4;
1994 altChanRingIndicator++;
1995 fast_clock++;
1996 rocketModel[i].model = MODEL_RPP4;
1997 strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port");
1998 rocketModel[i].numPorts = 4;
1999 break;
2000 case PCI_DEVICE_ID_RPP8:
2001 str = "Plus Octacable";
2002 max_num_aiops = 2;
2003 ports_per_aiop = 4;
2004 altChanRingIndicator++;
2005 fast_clock++;
2006 rocketModel[i].model = MODEL_RPP8;
2007 strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port");
2008 rocketModel[i].numPorts = 8;
2009 break;
2010 case PCI_DEVICE_ID_RP2_232:
2011 str = "Plus 2 (RS-232)";
2012 max_num_aiops = 1;
2013 ports_per_aiop = 2;
2014 altChanRingIndicator++;
2015 fast_clock++;
2016 rocketModel[i].model = MODEL_RP2_232;
2017 strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232");
2018 rocketModel[i].numPorts = 2;
2019 break;
2020 case PCI_DEVICE_ID_RP2_422:
2021 str = "Plus 2 (RS-422)";
2022 max_num_aiops = 1;
2023 ports_per_aiop = 2;
2024 altChanRingIndicator++;
2025 fast_clock++;
2026 rocketModel[i].model = MODEL_RP2_422;
2027 strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422");
2028 rocketModel[i].numPorts = 2;
2029 break;
2030 case PCI_DEVICE_ID_RP6M:
2031
2032 max_num_aiops = 1;
2033 ports_per_aiop = 6;
2034 str = "6-port";
2035
2036 /* If class_rev is 1, the rocketmodem flash must be loaded. If it is 2 it is a "socketed" version. */
2037 if ((class_rev & 0xFF) == 1) {
2038 rcktpt_type[i] = ROCKET_TYPE_MODEMII;
2039 rocketModel[i].loadrm2 = 1;
2040 } else {
2041 rcktpt_type[i] = ROCKET_TYPE_MODEM;
2042 }
2043
2044 rocketModel[i].model = MODEL_RP6M;
2045 strcpy(rocketModel[i].modelString, "RocketModem 6 port");
2046 rocketModel[i].numPorts = 6;
2047 break;
2048 case PCI_DEVICE_ID_RP4M:
2049 max_num_aiops = 1;
2050 ports_per_aiop = 4;
2051 str = "4-port";
2052 if ((class_rev & 0xFF) == 1) {
2053 rcktpt_type[i] = ROCKET_TYPE_MODEMII;
2054 rocketModel[i].loadrm2 = 1;
2055 } else {
2056 rcktpt_type[i] = ROCKET_TYPE_MODEM;
2057 }
2058
2059 rocketModel[i].model = MODEL_RP4M;
2060 strcpy(rocketModel[i].modelString, "RocketModem 4 port");
2061 rocketModel[i].numPorts = 4;
2062 break;
2063 default:
2064 str = "(unknown/unsupported)";
2065 max_num_aiops = 0;
2066 break;
2067 }
2068
2069 /*
2070 * Check for UPCI boards.
2071 */
2072
2073 switch (dev->device) {
2074 case PCI_DEVICE_ID_URP32INTF:
2075 case PCI_DEVICE_ID_URP8INTF:
2076 case PCI_DEVICE_ID_URP16INTF:
2077 case PCI_DEVICE_ID_CRP16INTF:
2078 case PCI_DEVICE_ID_URP8OCTA:
2079 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2080 ConfigIO = pci_resource_start(dev, 1);
2081 if (dev->device == PCI_DEVICE_ID_URP8OCTA) {
2082 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2083
2084 /*
2085 * Check for octa or quad cable.
2086 */
2087 if (!
2088 (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
2089 PCI_GPIO_CTRL_8PORT)) {
2090 str = "Quadcable";
2091 ports_per_aiop = 4;
2092 rocketModel[i].numPorts = 4;
2093 }
2094 }
2095 break;
2096 case PCI_DEVICE_ID_UPCI_RM3_8PORT:
2097 str = "8 ports";
2098 max_num_aiops = 1;
2099 rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
2100 strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
2101 rocketModel[i].numPorts = 8;
2102 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2103 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2104 ConfigIO = pci_resource_start(dev, 1);
2105 rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
2106 break;
2107 case PCI_DEVICE_ID_UPCI_RM3_4PORT:
2108 str = "4 ports";
2109 max_num_aiops = 1;
2110 rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
2111 strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
2112 rocketModel[i].numPorts = 4;
2113 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2114 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2115 ConfigIO = pci_resource_start(dev, 1);
2116 rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
2117 break;
2118 default:
2119 break;
2120 }
2121
2122 switch (rcktpt_type[i]) {
2123 case ROCKET_TYPE_MODEM:
2124 board_type = "RocketModem";
2125 break;
2126 case ROCKET_TYPE_MODEMII:
2127 board_type = "RocketModem II";
2128 break;
2129 case ROCKET_TYPE_MODEMIII:
2130 board_type = "RocketModem III";
2131 break;
2132 default:
2133 board_type = "RocketPort";
2134 break;
2135 }
2136
2137 if (fast_clock) {
2138 sClockPrescale = 0x12; /* mod 2 (divide by 3) */
2139 rp_baud_base[i] = 921600;
2140 } else {
2141 /*
2142 * If support_low_speed is set, use the slow clock
2143 * prescale, which supports 50 bps
2144 */
2145 if (support_low_speed) {
2146 /* mod 9 (divide by 10) prescale */
2147 sClockPrescale = 0x19;
2148 rp_baud_base[i] = 230400;
2149 } else {
2150 /* mod 4 (devide by 5) prescale */
2151 sClockPrescale = 0x14;
2152 rp_baud_base[i] = 460800;
2153 }
2154 }
2155
2156 for (aiop = 0; aiop < max_num_aiops; aiop++)
2157 aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
2158 ctlp = sCtlNumToCtlPtr(i);
2159 num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd);
2160 for (aiop = 0; aiop < max_num_aiops; aiop++)
2161 ctlp->AiopNumChan[aiop] = ports_per_aiop;
2162
2163 printk("Comtrol PCI controller #%d ID 0x%x found in bus:slot:fn %s at address %04lx, "
2164 "%d AIOP(s) (%s)\n", i, dev->device, pci_name(dev),
2165 rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString);
2166 printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
2167 rocketModel[i].modelString,
2168 rocketModel[i].startingPortNumber,
2169 rocketModel[i].startingPortNumber +
2170 rocketModel[i].numPorts - 1);
2171
2172 if (num_aiops <= 0) {
2173 rcktpt_io_addr[i] = 0;
2174 return (0);
2175 }
2176 is_PCI[i] = 1;
2177
2178 /* Reset the AIOPIC, init the serial ports */
2179 for (aiop = 0; aiop < num_aiops; aiop++) {
2180 sResetAiopByNum(ctlp, aiop);
2181 num_chan = ports_per_aiop;
2182 for (chan = 0; chan < num_chan; chan++)
2183 init_r_port(i, aiop, chan, dev);
2184 }
2185
2186 /* Rocket modems must be reset */
2187 if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
2188 (rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
2189 (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
2190 num_chan = ports_per_aiop;
2191 for (chan = 0; chan < num_chan; chan++)
2192 sPCIModemReset(ctlp, chan, 1);
2193 mdelay(500);
2194 for (chan = 0; chan < num_chan; chan++)
2195 sPCIModemReset(ctlp, chan, 0);
2196 mdelay(500);
2197 rmSpeakerReset(ctlp, rocketModel[i].model);
2198 }
2199 return (1);
2200}
2201
2202/*
2203 * Probes for PCI cards, inits them if found
2204 * Input: board_found = number of ISA boards already found, or the
2205 * starting board number
2206 * Returns: Number of PCI boards found
2207 */
2208static int __init init_PCI(int boards_found)
2209{
2210 struct pci_dev *dev = NULL;
2211 int count = 0;
2212
2213 /* Work through the PCI device list, pulling out ours */
Alan Cox606d0992006-12-08 02:38:45 -08002214 while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 if (register_PCI(count + boards_found, dev))
2216 count++;
2217 }
2218 return (count);
2219}
2220
2221#endif /* CONFIG_PCI */
2222
2223/*
2224 * Probes for ISA cards
2225 * Input: i = the board number to look for
2226 * Returns: 1 if board found, 0 else
2227 */
2228static int __init init_ISA(int i)
2229{
2230 int num_aiops, num_chan = 0, total_num_chan = 0;
2231 int aiop, chan;
2232 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
2233 CONTROLLER_t *ctlp;
2234 char *type_string;
2235
2236 /* If io_addr is zero, no board configured */
2237 if (rcktpt_io_addr[i] == 0)
2238 return (0);
2239
2240 /* Reserve the IO region */
2241 if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) {
2242 printk(KERN_INFO "Unable to reserve IO region for configured ISA RocketPort at address 0x%lx, board not installed...\n", rcktpt_io_addr[i]);
2243 rcktpt_io_addr[i] = 0;
2244 return (0);
2245 }
2246
2247 ctlp = sCtlNumToCtlPtr(i);
2248
2249 ctlp->boardType = rcktpt_type[i];
2250
2251 switch (rcktpt_type[i]) {
2252 case ROCKET_TYPE_PC104:
2253 type_string = "(PC104)";
2254 break;
2255 case ROCKET_TYPE_MODEM:
2256 type_string = "(RocketModem)";
2257 break;
2258 case ROCKET_TYPE_MODEMII:
2259 type_string = "(RocketModem II)";
2260 break;
2261 default:
2262 type_string = "";
2263 break;
2264 }
2265
2266 /*
2267 * If support_low_speed is set, use the slow clock prescale,
2268 * which supports 50 bps
2269 */
2270 if (support_low_speed) {
2271 sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */
2272 rp_baud_base[i] = 230400;
2273 } else {
2274 sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */
2275 rp_baud_base[i] = 460800;
2276 }
2277
2278 for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
2279 aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400);
2280
2281 num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
2282
2283 if (ctlp->boardType == ROCKET_TYPE_PC104) {
2284 sEnAiop(ctlp, 2); /* only one AIOPIC, but these */
2285 sEnAiop(ctlp, 3); /* CSels used for other stuff */
2286 }
2287
2288 /* If something went wrong initing the AIOP's release the ISA IO memory */
2289 if (num_aiops <= 0) {
2290 release_region(rcktpt_io_addr[i], 64);
2291 rcktpt_io_addr[i] = 0;
2292 return (0);
2293 }
2294
2295 rocketModel[i].startingPortNumber = nextLineNumber;
2296
2297 for (aiop = 0; aiop < num_aiops; aiop++) {
2298 sResetAiopByNum(ctlp, aiop);
2299 sEnAiop(ctlp, aiop);
2300 num_chan = sGetAiopNumChan(ctlp, aiop);
2301 total_num_chan += num_chan;
2302 for (chan = 0; chan < num_chan; chan++)
2303 init_r_port(i, aiop, chan, NULL);
2304 }
2305 is_PCI[i] = 0;
2306 if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) {
2307 num_chan = sGetAiopNumChan(ctlp, 0);
2308 total_num_chan = num_chan;
2309 for (chan = 0; chan < num_chan; chan++)
2310 sModemReset(ctlp, chan, 1);
2311 mdelay(500);
2312 for (chan = 0; chan < num_chan; chan++)
2313 sModemReset(ctlp, chan, 0);
2314 mdelay(500);
2315 strcpy(rocketModel[i].modelString, "RocketModem ISA");
2316 } else {
2317 strcpy(rocketModel[i].modelString, "RocketPort ISA");
2318 }
2319 rocketModel[i].numPorts = total_num_chan;
2320 rocketModel[i].model = MODEL_ISA;
2321
2322 printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n",
2323 i, rcktpt_io_addr[i], num_aiops, type_string);
2324
2325 printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
2326 rocketModel[i].modelString,
2327 rocketModel[i].startingPortNumber,
2328 rocketModel[i].startingPortNumber +
2329 rocketModel[i].numPorts - 1);
2330
2331 return (1);
2332}
2333
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002334static const struct tty_operations rocket_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 .open = rp_open,
2336 .close = rp_close,
2337 .write = rp_write,
2338 .put_char = rp_put_char,
2339 .write_room = rp_write_room,
2340 .chars_in_buffer = rp_chars_in_buffer,
2341 .flush_buffer = rp_flush_buffer,
2342 .ioctl = rp_ioctl,
2343 .throttle = rp_throttle,
2344 .unthrottle = rp_unthrottle,
2345 .set_termios = rp_set_termios,
2346 .stop = rp_stop,
2347 .start = rp_start,
2348 .hangup = rp_hangup,
2349 .break_ctl = rp_break,
2350 .send_xchar = rp_send_xchar,
2351 .wait_until_sent = rp_wait_until_sent,
2352 .tiocmget = rp_tiocmget,
2353 .tiocmset = rp_tiocmset,
2354};
2355
2356/*
2357 * The module "startup" routine; it's run when the module is loaded.
2358 */
Bjorn Helgaasd269cdd2005-10-30 15:03:14 -08002359static int __init rp_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360{
2361 int retval, pci_boards_found, isa_boards_found, i;
2362
2363 printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
2364 ROCKET_VERSION, ROCKET_DATE);
2365
2366 rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
2367 if (!rocket_driver)
2368 return -ENOMEM;
2369
2370 /*
2371 * Set up the timer channel.
2372 */
2373 init_timer(&rocket_timer);
2374 rocket_timer.function = rp_do_poll;
2375
2376 /*
2377 * Initialize the array of pointers to our own internal state
2378 * structures.
2379 */
2380 memset(rp_table, 0, sizeof (rp_table));
2381 memset(xmit_flags, 0, sizeof (xmit_flags));
2382
2383 for (i = 0; i < MAX_RP_PORTS; i++)
2384 lineNumbers[i] = 0;
2385 nextLineNumber = 0;
2386 memset(rocketModel, 0, sizeof (rocketModel));
2387
2388 /*
2389 * If board 1 is non-zero, there is at least one ISA configured. If controller is
2390 * zero, use the default controller IO address of board1 + 0x40.
2391 */
2392 if (board1) {
2393 if (controller == 0)
2394 controller = board1 + 0x40;
2395 } else {
2396 controller = 0; /* Used as a flag, meaning no ISA boards */
2397 }
2398
2399 /* If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
2400 if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
2401 printk(KERN_INFO "Unable to reserve IO region for first configured ISA RocketPort controller 0x%lx. Driver exiting \n", controller);
2402 return -EBUSY;
2403 }
2404
2405 /* Store ISA variable retrieved from command line or .conf file. */
2406 rcktpt_io_addr[0] = board1;
2407 rcktpt_io_addr[1] = board2;
2408 rcktpt_io_addr[2] = board3;
2409 rcktpt_io_addr[3] = board4;
2410
2411 rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2412 rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0];
2413 rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2414 rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1];
2415 rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2416 rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2];
2417 rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2418 rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3];
2419
2420 /*
2421 * Set up the tty driver structure and then register this
2422 * driver with the tty layer.
2423 */
2424
2425 rocket_driver->owner = THIS_MODULE;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07002426 rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 rocket_driver->name = "ttyR";
2428 rocket_driver->driver_name = "Comtrol RocketPort";
2429 rocket_driver->major = TTY_ROCKET_MAJOR;
2430 rocket_driver->minor_start = 0;
2431 rocket_driver->type = TTY_DRIVER_TYPE_SERIAL;
2432 rocket_driver->subtype = SERIAL_TYPE_NORMAL;
2433 rocket_driver->init_termios = tty_std_termios;
2434 rocket_driver->init_termios.c_cflag =
2435 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Alan Cox606d0992006-12-08 02:38:45 -08002436 rocket_driver->init_termios.c_ispeed = 9600;
2437 rocket_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438#ifdef ROCKET_SOFT_FLOW
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07002439 rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440#endif
2441 tty_set_operations(rocket_driver, &rocket_ops);
2442
2443 retval = tty_register_driver(rocket_driver);
2444 if (retval < 0) {
2445 printk(KERN_INFO "Couldn't install tty RocketPort driver (error %d)\n", -retval);
2446 put_tty_driver(rocket_driver);
2447 return -1;
2448 }
2449
2450#ifdef ROCKET_DEBUG_OPEN
2451 printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major);
2452#endif
2453
2454 /*
2455 * OK, let's probe each of the controllers looking for boards. Any boards found
2456 * will be initialized here.
2457 */
2458 isa_boards_found = 0;
2459 pci_boards_found = 0;
2460
2461 for (i = 0; i < NUM_BOARDS; i++) {
2462 if (init_ISA(i))
2463 isa_boards_found++;
2464 }
2465
2466#ifdef CONFIG_PCI
2467 if (isa_boards_found < NUM_BOARDS)
2468 pci_boards_found = init_PCI(isa_boards_found);
2469#endif
2470
2471 max_board = pci_boards_found + isa_boards_found;
2472
2473 if (max_board == 0) {
2474 printk(KERN_INFO "No rocketport ports found; unloading driver.\n");
2475 del_timer_sync(&rocket_timer);
2476 tty_unregister_driver(rocket_driver);
2477 put_tty_driver(rocket_driver);
2478 return -ENXIO;
2479 }
2480
2481 return 0;
2482}
2483
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
2485static void rp_cleanup_module(void)
2486{
2487 int retval;
2488 int i;
2489
2490 del_timer_sync(&rocket_timer);
2491
2492 retval = tty_unregister_driver(rocket_driver);
2493 if (retval)
2494 printk(KERN_INFO "Error %d while trying to unregister "
2495 "rocketport driver\n", -retval);
2496 put_tty_driver(rocket_driver);
2497
Jesper Juhl735d5662005-11-07 01:01:29 -08002498 for (i = 0; i < MAX_RP_PORTS; i++)
2499 kfree(rp_table[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500
2501 for (i = 0; i < NUM_BOARDS; i++) {
2502 if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
2503 continue;
2504 release_region(rcktpt_io_addr[i], 64);
2505 }
2506 if (controller)
2507 release_region(controller, 4);
2508}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510/***************************************************************************
2511Function: sInitController
2512Purpose: Initialization of controller global registers and controller
2513 structure.
2514Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
2515 IRQNum,Frequency,PeriodicOnly)
2516 CONTROLLER_T *CtlP; Ptr to controller structure
2517 int CtlNum; Controller number
2518 ByteIO_t MudbacIO; Mudbac base I/O address.
2519 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
2520 This list must be in the order the AIOPs will be found on the
2521 controller. Once an AIOP in the list is not found, it is
2522 assumed that there are no more AIOPs on the controller.
2523 int AiopIOListSize; Number of addresses in AiopIOList
2524 int IRQNum; Interrupt Request number. Can be any of the following:
2525 0: Disable global interrupts
2526 3: IRQ 3
2527 4: IRQ 4
2528 5: IRQ 5
2529 9: IRQ 9
2530 10: IRQ 10
2531 11: IRQ 11
2532 12: IRQ 12
2533 15: IRQ 15
2534 Byte_t Frequency: A flag identifying the frequency
2535 of the periodic interrupt, can be any one of the following:
2536 FREQ_DIS - periodic interrupt disabled
2537 FREQ_137HZ - 137 Hertz
2538 FREQ_69HZ - 69 Hertz
2539 FREQ_34HZ - 34 Hertz
2540 FREQ_17HZ - 17 Hertz
2541 FREQ_9HZ - 9 Hertz
2542 FREQ_4HZ - 4 Hertz
2543 If IRQNum is set to 0 the Frequency parameter is
2544 overidden, it is forced to a value of FREQ_DIS.
Adrian Bunkf15313b2005-06-25 14:59:05 -07002545 int PeriodicOnly: 1 if all interrupts except the periodic
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 interrupt are to be blocked.
Adrian Bunkf15313b2005-06-25 14:59:05 -07002547 0 is both the periodic interrupt and
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 other channel interrupts are allowed.
2549 If IRQNum is set to 0 the PeriodicOnly parameter is
Adrian Bunkf15313b2005-06-25 14:59:05 -07002550 overidden, it is forced to a value of 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
2552 initialization failed.
2553
2554Comments:
2555 If periodic interrupts are to be disabled but AIOP interrupts
Adrian Bunkf15313b2005-06-25 14:59:05 -07002556 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
2558 If interrupts are to be completely disabled set IRQNum to 0.
2559
Adrian Bunkf15313b2005-06-25 14:59:05 -07002560 Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 invalid combination.
2562
2563 This function performs initialization of global interrupt modes,
2564 but it does not actually enable global interrupts. To enable
2565 and disable global interrupts use functions sEnGlobalInt() and
2566 sDisGlobalInt(). Enabling of global interrupts is normally not
2567 done until all other initializations are complete.
2568
2569 Even if interrupts are globally enabled, they must also be
2570 individually enabled for each channel that is to generate
2571 interrupts.
2572
2573Warnings: No range checking on any of the parameters is done.
2574
2575 No context switches are allowed while executing this function.
2576
2577 After this function all AIOPs on the controller are disabled,
2578 they can be enabled with sEnAiop().
2579*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002580static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
2581 ByteIO_t * AiopIOList, int AiopIOListSize,
2582 int IRQNum, Byte_t Frequency, int PeriodicOnly)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583{
2584 int i;
2585 ByteIO_t io;
2586 int done;
2587
2588 CtlP->AiopIntrBits = aiop_intr_bits;
2589 CtlP->AltChanRingIndicator = 0;
2590 CtlP->CtlNum = CtlNum;
2591 CtlP->CtlID = CTLID_0001; /* controller release 1 */
2592 CtlP->BusType = isISA;
2593 CtlP->MBaseIO = MudbacIO;
2594 CtlP->MReg1IO = MudbacIO + 1;
2595 CtlP->MReg2IO = MudbacIO + 2;
2596 CtlP->MReg3IO = MudbacIO + 3;
2597#if 1
2598 CtlP->MReg2 = 0; /* interrupt disable */
2599 CtlP->MReg3 = 0; /* no periodic interrupts */
2600#else
2601 if (sIRQMap[IRQNum] == 0) { /* interrupts globally disabled */
2602 CtlP->MReg2 = 0; /* interrupt disable */
2603 CtlP->MReg3 = 0; /* no periodic interrupts */
2604 } else {
2605 CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
2606 CtlP->MReg3 = Frequency; /* set frequency */
2607 if (PeriodicOnly) { /* periodic interrupt only */
2608 CtlP->MReg3 |= PERIODIC_ONLY;
2609 }
2610 }
2611#endif
2612 sOutB(CtlP->MReg2IO, CtlP->MReg2);
2613 sOutB(CtlP->MReg3IO, CtlP->MReg3);
2614 sControllerEOI(CtlP); /* clear EOI if warm init */
2615 /* Init AIOPs */
2616 CtlP->NumAiop = 0;
2617 for (i = done = 0; i < AiopIOListSize; i++) {
2618 io = AiopIOList[i];
2619 CtlP->AiopIO[i] = (WordIO_t) io;
2620 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2621 sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03)); /* AIOP index */
2622 sOutB(MudbacIO, (Byte_t) (io >> 6)); /* set up AIOP I/O in MUDBAC */
2623 if (done)
2624 continue;
2625 sEnAiop(CtlP, i); /* enable the AIOP */
2626 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
2627 if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
2628 done = 1; /* done looking for AIOPs */
2629 else {
2630 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
2631 sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
2632 sOutB(io + _INDX_DATA, sClockPrescale);
2633 CtlP->NumAiop++; /* bump count of AIOPs */
2634 }
2635 sDisAiop(CtlP, i); /* disable AIOP */
2636 }
2637
2638 if (CtlP->NumAiop == 0)
2639 return (-1);
2640 else
2641 return (CtlP->NumAiop);
2642}
2643
2644/***************************************************************************
2645Function: sPCIInitController
2646Purpose: Initialization of controller global registers and controller
2647 structure.
2648Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
2649 IRQNum,Frequency,PeriodicOnly)
2650 CONTROLLER_T *CtlP; Ptr to controller structure
2651 int CtlNum; Controller number
2652 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
2653 This list must be in the order the AIOPs will be found on the
2654 controller. Once an AIOP in the list is not found, it is
2655 assumed that there are no more AIOPs on the controller.
2656 int AiopIOListSize; Number of addresses in AiopIOList
2657 int IRQNum; Interrupt Request number. Can be any of the following:
2658 0: Disable global interrupts
2659 3: IRQ 3
2660 4: IRQ 4
2661 5: IRQ 5
2662 9: IRQ 9
2663 10: IRQ 10
2664 11: IRQ 11
2665 12: IRQ 12
2666 15: IRQ 15
2667 Byte_t Frequency: A flag identifying the frequency
2668 of the periodic interrupt, can be any one of the following:
2669 FREQ_DIS - periodic interrupt disabled
2670 FREQ_137HZ - 137 Hertz
2671 FREQ_69HZ - 69 Hertz
2672 FREQ_34HZ - 34 Hertz
2673 FREQ_17HZ - 17 Hertz
2674 FREQ_9HZ - 9 Hertz
2675 FREQ_4HZ - 4 Hertz
2676 If IRQNum is set to 0 the Frequency parameter is
2677 overidden, it is forced to a value of FREQ_DIS.
Adrian Bunkf15313b2005-06-25 14:59:05 -07002678 int PeriodicOnly: 1 if all interrupts except the periodic
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 interrupt are to be blocked.
Adrian Bunkf15313b2005-06-25 14:59:05 -07002680 0 is both the periodic interrupt and
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 other channel interrupts are allowed.
2682 If IRQNum is set to 0 the PeriodicOnly parameter is
Adrian Bunkf15313b2005-06-25 14:59:05 -07002683 overidden, it is forced to a value of 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
2685 initialization failed.
2686
2687Comments:
2688 If periodic interrupts are to be disabled but AIOP interrupts
Adrian Bunkf15313b2005-06-25 14:59:05 -07002689 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690
2691 If interrupts are to be completely disabled set IRQNum to 0.
2692
Adrian Bunkf15313b2005-06-25 14:59:05 -07002693 Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 invalid combination.
2695
2696 This function performs initialization of global interrupt modes,
2697 but it does not actually enable global interrupts. To enable
2698 and disable global interrupts use functions sEnGlobalInt() and
2699 sDisGlobalInt(). Enabling of global interrupts is normally not
2700 done until all other initializations are complete.
2701
2702 Even if interrupts are globally enabled, they must also be
2703 individually enabled for each channel that is to generate
2704 interrupts.
2705
2706Warnings: No range checking on any of the parameters is done.
2707
2708 No context switches are allowed while executing this function.
2709
2710 After this function all AIOPs on the controller are disabled,
2711 they can be enabled with sEnAiop().
2712*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002713static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
2714 ByteIO_t * AiopIOList, int AiopIOListSize,
2715 WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
2716 int PeriodicOnly, int altChanRingIndicator,
2717 int UPCIRingInd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718{
2719 int i;
2720 ByteIO_t io;
2721
2722 CtlP->AltChanRingIndicator = altChanRingIndicator;
2723 CtlP->UPCIRingInd = UPCIRingInd;
2724 CtlP->CtlNum = CtlNum;
2725 CtlP->CtlID = CTLID_0001; /* controller release 1 */
2726 CtlP->BusType = isPCI; /* controller release 1 */
2727
2728 if (ConfigIO) {
2729 CtlP->isUPCI = 1;
2730 CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
2731 CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
2732 CtlP->AiopIntrBits = upci_aiop_intr_bits;
2733 } else {
2734 CtlP->isUPCI = 0;
2735 CtlP->PCIIO =
2736 (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
2737 CtlP->AiopIntrBits = aiop_intr_bits;
2738 }
2739
2740 sPCIControllerEOI(CtlP); /* clear EOI if warm init */
2741 /* Init AIOPs */
2742 CtlP->NumAiop = 0;
2743 for (i = 0; i < AiopIOListSize; i++) {
2744 io = AiopIOList[i];
2745 CtlP->AiopIO[i] = (WordIO_t) io;
2746 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2747
2748 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
2749 if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
2750 break; /* done looking for AIOPs */
2751
2752 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
2753 sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
2754 sOutB(io + _INDX_DATA, sClockPrescale);
2755 CtlP->NumAiop++; /* bump count of AIOPs */
2756 }
2757
2758 if (CtlP->NumAiop == 0)
2759 return (-1);
2760 else
2761 return (CtlP->NumAiop);
2762}
2763
2764/***************************************************************************
2765Function: sReadAiopID
2766Purpose: Read the AIOP idenfication number directly from an AIOP.
2767Call: sReadAiopID(io)
2768 ByteIO_t io: AIOP base I/O address
2769Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
2770 is replace by an identifying number.
2771 Flag AIOPID_NULL if no valid AIOP is found
2772Warnings: No context switches are allowed while executing this function.
2773
2774*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002775static int sReadAiopID(ByteIO_t io)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776{
2777 Byte_t AiopID; /* ID byte from AIOP */
2778
2779 sOutB(io + _CMD_REG, RESET_ALL); /* reset AIOP */
2780 sOutB(io + _CMD_REG, 0x0);
2781 AiopID = sInW(io + _CHN_STAT0) & 0x07;
2782 if (AiopID == 0x06)
2783 return (1);
2784 else /* AIOP does not exist */
2785 return (-1);
2786}
2787
2788/***************************************************************************
2789Function: sReadAiopNumChan
2790Purpose: Read the number of channels available in an AIOP directly from
2791 an AIOP.
2792Call: sReadAiopNumChan(io)
2793 WordIO_t io: AIOP base I/O address
2794Return: int: The number of channels available
2795Comments: The number of channels is determined by write/reads from identical
2796 offsets within the SRAM address spaces for channels 0 and 4.
2797 If the channel 4 space is mirrored to channel 0 it is a 4 channel
2798 AIOP, otherwise it is an 8 channel.
2799Warnings: No context switches are allowed while executing this function.
2800*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002801static int sReadAiopNumChan(WordIO_t io)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802{
2803 Word_t x;
2804 static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
2805
2806 /* write to chan 0 SRAM */
2807 sOutDW((DWordIO_t) io + _INDX_ADDR, *((DWord_t *) & R[0]));
2808 sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */
2809 x = sInW(io + _INDX_DATA);
2810 sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */
2811 if (x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
2812 return (8);
2813 else
2814 return (4);
2815}
2816
2817/***************************************************************************
2818Function: sInitChan
2819Purpose: Initialization of a channel and channel structure
2820Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
2821 CONTROLLER_T *CtlP; Ptr to controller structure
2822 CHANNEL_T *ChP; Ptr to channel structure
2823 int AiopNum; AIOP number within controller
2824 int ChanNum; Channel number within AIOP
Adrian Bunkf15313b2005-06-25 14:59:05 -07002825Return: int: 1 if initialization succeeded, 0 if it fails because channel
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 number exceeds number of channels available in AIOP.
2827Comments: This function must be called before a channel can be used.
2828Warnings: No range checking on any of the parameters is done.
2829
2830 No context switches are allowed while executing this function.
2831*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002832static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
2833 int ChanNum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834{
2835 int i;
2836 WordIO_t AiopIO;
2837 WordIO_t ChIOOff;
2838 Byte_t *ChR;
2839 Word_t ChOff;
2840 static Byte_t R[4];
2841 int brd9600;
2842
2843 if (ChanNum >= CtlP->AiopNumChan[AiopNum])
Adrian Bunkf15313b2005-06-25 14:59:05 -07002844 return 0; /* exceeds num chans in AIOP */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845
2846 /* Channel, AIOP, and controller identifiers */
2847 ChP->CtlP = CtlP;
2848 ChP->ChanID = CtlP->AiopID[AiopNum];
2849 ChP->AiopNum = AiopNum;
2850 ChP->ChanNum = ChanNum;
2851
2852 /* Global direct addresses */
2853 AiopIO = CtlP->AiopIO[AiopNum];
2854 ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG;
2855 ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN;
2856 ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK;
2857 ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR;
2858 ChP->IndexData = AiopIO + _INDX_DATA;
2859
2860 /* Channel direct addresses */
2861 ChIOOff = AiopIO + ChP->ChanNum * 2;
2862 ChP->TxRxData = ChIOOff + _TD0;
2863 ChP->ChanStat = ChIOOff + _CHN_STAT0;
2864 ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
2865 ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0;
2866
2867 /* Initialize the channel from the RData array */
2868 for (i = 0; i < RDATASIZE; i += 4) {
2869 R[0] = RData[i];
2870 R[1] = RData[i + 1] + 0x10 * ChanNum;
2871 R[2] = RData[i + 2];
2872 R[3] = RData[i + 3];
2873 sOutDW(ChP->IndexAddr, *((DWord_t *) & R[0]));
2874 }
2875
2876 ChR = ChP->R;
2877 for (i = 0; i < RREGDATASIZE; i += 4) {
2878 ChR[i] = RRegData[i];
2879 ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum;
2880 ChR[i + 2] = RRegData[i + 2];
2881 ChR[i + 3] = RRegData[i + 3];
2882 }
2883
2884 /* Indexed registers */
2885 ChOff = (Word_t) ChanNum *0x1000;
2886
2887 if (sClockPrescale == 0x14)
2888 brd9600 = 47;
2889 else
2890 brd9600 = 23;
2891
2892 ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD);
2893 ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
2894 ChP->BaudDiv[2] = (Byte_t) brd9600;
2895 ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
2896 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->BaudDiv[0]);
2897
2898 ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
2899 ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
2900 ChP->TxControl[2] = 0;
2901 ChP->TxControl[3] = 0;
2902 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
2903
2904 ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
2905 ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
2906 ChP->RxControl[2] = 0;
2907 ChP->RxControl[3] = 0;
2908 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
2909
2910 ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
2911 ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
2912 ChP->TxEnables[2] = 0;
2913 ChP->TxEnables[3] = 0;
2914 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxEnables[0]);
2915
2916 ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
2917 ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
2918 ChP->TxCompare[2] = 0;
2919 ChP->TxCompare[3] = 0;
2920 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxCompare[0]);
2921
2922 ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
2923 ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
2924 ChP->TxReplace1[2] = 0;
2925 ChP->TxReplace1[3] = 0;
2926 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace1[0]);
2927
2928 ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
2929 ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
2930 ChP->TxReplace2[2] = 0;
2931 ChP->TxReplace2[3] = 0;
2932 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace2[0]);
2933
2934 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
2935 ChP->TxFIFO = ChOff + _TX_FIFO;
2936
2937 sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
2938 sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Tx FIFO count */
2939 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
2940 sOutW(ChP->IndexData, 0);
2941 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
2942 ChP->RxFIFO = ChOff + _RX_FIFO;
2943
2944 sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
2945 sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Rx FIFO count */
2946 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
2947 sOutW(ChP->IndexData, 0);
2948 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
2949 sOutW(ChP->IndexData, 0);
2950 ChP->TxPrioCnt = ChOff + _TXP_CNT;
2951 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt);
2952 sOutB(ChP->IndexData, 0);
2953 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
2954 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr);
2955 sOutB(ChP->IndexData, 0);
2956 ChP->TxPrioBuf = ChOff + _TXP_BUF;
2957 sEnRxProcessor(ChP); /* start the Rx processor */
2958
Adrian Bunkf15313b2005-06-25 14:59:05 -07002959 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960}
2961
2962/***************************************************************************
2963Function: sStopRxProcessor
2964Purpose: Stop the receive processor from processing a channel.
2965Call: sStopRxProcessor(ChP)
2966 CHANNEL_T *ChP; Ptr to channel structure
2967
2968Comments: The receive processor can be started again with sStartRxProcessor().
2969 This function causes the receive processor to skip over the
2970 stopped channel. It does not stop it from processing other channels.
2971
2972Warnings: No context switches are allowed while executing this function.
2973
2974 Do not leave the receive processor stopped for more than one
2975 character time.
2976
2977 After calling this function a delay of 4 uS is required to ensure
2978 that the receive processor is no longer processing this channel.
2979*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002980static void sStopRxProcessor(CHANNEL_T * ChP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981{
2982 Byte_t R[4];
2983
2984 R[0] = ChP->R[0];
2985 R[1] = ChP->R[1];
2986 R[2] = 0x0a;
2987 R[3] = ChP->R[3];
2988 sOutDW(ChP->IndexAddr, *(DWord_t *) & R[0]);
2989}
2990
2991/***************************************************************************
2992Function: sFlushRxFIFO
2993Purpose: Flush the Rx FIFO
2994Call: sFlushRxFIFO(ChP)
2995 CHANNEL_T *ChP; Ptr to channel structure
2996Return: void
2997Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
2998 while it is being flushed the receive processor is stopped
2999 and the transmitter is disabled. After these operations a
3000 4 uS delay is done before clearing the pointers to allow
3001 the receive processor to stop. These items are handled inside
3002 this function.
3003Warnings: No context switches are allowed while executing this function.
3004*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003005static void sFlushRxFIFO(CHANNEL_T * ChP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006{
3007 int i;
3008 Byte_t Ch; /* channel number within AIOP */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003009 int RxFIFOEnabled; /* 1 if Rx FIFO enabled */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
3011 if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
3012 return; /* don't need to flush */
3013
Adrian Bunkf15313b2005-06-25 14:59:05 -07003014 RxFIFOEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003016 RxFIFOEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 sDisRxFIFO(ChP); /* disable it */
3018 for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */
3019 sInB(ChP->IntChan); /* depends on bus i/o timing */
3020 }
3021 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
3022 Ch = (Byte_t) sGetChanNum(ChP);
3023 sOutB(ChP->Cmd, Ch | RESRXFCNT); /* apply reset Rx FIFO count */
3024 sOutB(ChP->Cmd, Ch); /* remove reset Rx FIFO count */
3025 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
3026 sOutW(ChP->IndexData, 0);
3027 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
3028 sOutW(ChP->IndexData, 0);
3029 if (RxFIFOEnabled)
3030 sEnRxFIFO(ChP); /* enable Rx FIFO */
3031}
3032
3033/***************************************************************************
3034Function: sFlushTxFIFO
3035Purpose: Flush the Tx FIFO
3036Call: sFlushTxFIFO(ChP)
3037 CHANNEL_T *ChP; Ptr to channel structure
3038Return: void
3039Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
3040 while it is being flushed the receive processor is stopped
3041 and the transmitter is disabled. After these operations a
3042 4 uS delay is done before clearing the pointers to allow
3043 the receive processor to stop. These items are handled inside
3044 this function.
3045Warnings: No context switches are allowed while executing this function.
3046*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003047static void sFlushTxFIFO(CHANNEL_T * ChP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048{
3049 int i;
3050 Byte_t Ch; /* channel number within AIOP */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003051 int TxEnabled; /* 1 if transmitter enabled */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052
3053 if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
3054 return; /* don't need to flush */
3055
Adrian Bunkf15313b2005-06-25 14:59:05 -07003056 TxEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 if (ChP->TxControl[3] & TX_ENABLE) {
Adrian Bunkf15313b2005-06-25 14:59:05 -07003058 TxEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 sDisTransmit(ChP); /* disable transmitter */
3060 }
3061 sStopRxProcessor(ChP); /* stop Rx processor */
3062 for (i = 0; i < 4000 / 200; i++) /* delay 4 uS to allow proc to stop */
3063 sInB(ChP->IntChan); /* depends on bus i/o timing */
3064 Ch = (Byte_t) sGetChanNum(ChP);
3065 sOutB(ChP->Cmd, Ch | RESTXFCNT); /* apply reset Tx FIFO count */
3066 sOutB(ChP->Cmd, Ch); /* remove reset Tx FIFO count */
3067 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
3068 sOutW(ChP->IndexData, 0);
3069 if (TxEnabled)
3070 sEnTransmit(ChP); /* enable transmitter */
3071 sStartRxProcessor(ChP); /* restart Rx processor */
3072}
3073
3074/***************************************************************************
3075Function: sWriteTxPrioByte
3076Purpose: Write a byte of priority transmit data to a channel
3077Call: sWriteTxPrioByte(ChP,Data)
3078 CHANNEL_T *ChP; Ptr to channel structure
3079 Byte_t Data; The transmit data byte
3080
3081Return: int: 1 if the bytes is successfully written, otherwise 0.
3082
3083Comments: The priority byte is transmitted before any data in the Tx FIFO.
3084
3085Warnings: No context switches are allowed while executing this function.
3086*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003087static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088{
3089 Byte_t DWBuf[4]; /* buffer for double word writes */
3090 Word_t *WordPtr; /* must be far because Win SS != DS */
3091 register DWordIO_t IndexAddr;
3092
3093 if (sGetTxCnt(ChP) > 1) { /* write it to Tx priority buffer */
3094 IndexAddr = ChP->IndexAddr;
3095 sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt); /* get priority buffer status */
3096 if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND) /* priority buffer busy */
3097 return (0); /* nothing sent */
3098
3099 WordPtr = (Word_t *) (&DWBuf[0]);
3100 *WordPtr = ChP->TxPrioBuf; /* data byte address */
3101
3102 DWBuf[2] = Data; /* data byte value */
3103 sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */
3104
3105 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
3106
3107 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
3108 DWBuf[3] = 0; /* priority buffer pointer */
3109 sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */
3110 } else { /* write it to Tx FIFO */
3111
3112 sWriteTxByte(sGetTxRxDataIO(ChP), Data);
3113 }
3114 return (1); /* 1 byte sent */
3115}
3116
3117/***************************************************************************
3118Function: sEnInterrupts
3119Purpose: Enable one or more interrupts for a channel
3120Call: sEnInterrupts(ChP,Flags)
3121 CHANNEL_T *ChP; Ptr to channel structure
3122 Word_t Flags: Interrupt enable flags, can be any combination
3123 of the following flags:
3124 TXINT_EN: Interrupt on Tx FIFO empty
3125 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
3126 sSetRxTrigger())
3127 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
3128 MCINT_EN: Interrupt on modem input change
3129 CHANINT_EN: Allow channel interrupt signal to the AIOP's
3130 Interrupt Channel Register.
3131Return: void
3132Comments: If an interrupt enable flag is set in Flags, that interrupt will be
3133 enabled. If an interrupt enable flag is not set in Flags, that
3134 interrupt will not be changed. Interrupts can be disabled with
3135 function sDisInterrupts().
3136
3137 This function sets the appropriate bit for the channel in the AIOP's
3138 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
3139 this channel's bit to be set in the AIOP's Interrupt Channel Register.
3140
3141 Interrupts must also be globally enabled before channel interrupts
3142 will be passed on to the host. This is done with function
3143 sEnGlobalInt().
3144
3145 In some cases it may be desirable to disable interrupts globally but
3146 enable channel interrupts. This would allow the global interrupt
3147 status register to be used to determine which AIOPs need service.
3148*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003149static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150{
3151 Byte_t Mask; /* Interrupt Mask Register */
3152
3153 ChP->RxControl[2] |=
3154 ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
3155
3156 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
3157
3158 ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
3159
3160 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
3161
3162 if (Flags & CHANINT_EN) {
3163 Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
3164 sOutB(ChP->IntMask, Mask);
3165 }
3166}
3167
3168/***************************************************************************
3169Function: sDisInterrupts
3170Purpose: Disable one or more interrupts for a channel
3171Call: sDisInterrupts(ChP,Flags)
3172 CHANNEL_T *ChP; Ptr to channel structure
3173 Word_t Flags: Interrupt flags, can be any combination
3174 of the following flags:
3175 TXINT_EN: Interrupt on Tx FIFO empty
3176 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
3177 sSetRxTrigger())
3178 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
3179 MCINT_EN: Interrupt on modem input change
3180 CHANINT_EN: Disable channel interrupt signal to the
3181 AIOP's Interrupt Channel Register.
3182Return: void
3183Comments: If an interrupt flag is set in Flags, that interrupt will be
3184 disabled. If an interrupt flag is not set in Flags, that
3185 interrupt will not be changed. Interrupts can be enabled with
3186 function sEnInterrupts().
3187
3188 This function clears the appropriate bit for the channel in the AIOP's
3189 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
3190 this channel's bit from being set in the AIOP's Interrupt Channel
3191 Register.
3192*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003193static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194{
3195 Byte_t Mask; /* Interrupt Mask Register */
3196
3197 ChP->RxControl[2] &=
3198 ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
3199 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
3200 ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
3201 sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
3202
3203 if (Flags & CHANINT_EN) {
3204 Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
3205 sOutB(ChP->IntMask, Mask);
3206 }
3207}
3208
Adrian Bunkf15313b2005-06-25 14:59:05 -07003209static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210{
3211 sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
3212}
3213
3214/*
3215 * Not an official SSCI function, but how to reset RocketModems.
3216 * ISA bus version
3217 */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003218static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219{
3220 ByteIO_t addr;
3221 Byte_t val;
3222
3223 addr = CtlP->AiopIO[0] + 0x400;
3224 val = sInB(CtlP->MReg3IO);
3225 /* if AIOP[1] is not enabled, enable it */
3226 if ((val & 2) == 0) {
3227 val = sInB(CtlP->MReg2IO);
3228 sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03));
3229 sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6));
3230 }
3231
3232 sEnAiop(CtlP, 1);
3233 if (!on)
3234 addr += 8;
3235 sOutB(addr + chan, 0); /* apply or remove reset */
3236 sDisAiop(CtlP, 1);
3237}
3238
3239/*
3240 * Not an official SSCI function, but how to reset RocketModems.
3241 * PCI bus version
3242 */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003243static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244{
3245 ByteIO_t addr;
3246
3247 addr = CtlP->AiopIO[0] + 0x40; /* 2nd AIOP */
3248 if (!on)
3249 addr += 8;
3250 sOutB(addr + chan, 0); /* apply or remove reset */
3251}
3252
3253/* Resets the speaker controller on RocketModem II and III devices */
3254static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
3255{
3256 ByteIO_t addr;
3257
3258 /* RocketModem II speaker control is at the 8th port location of offset 0x40 */
3259 if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
3260 addr = CtlP->AiopIO[0] + 0x4F;
3261 sOutB(addr, 0);
3262 }
3263
3264 /* RocketModem III speaker control is at the 1st port location of offset 0x80 */
3265 if ((model == MODEL_UPCI_RM3_8PORT)
3266 || (model == MODEL_UPCI_RM3_4PORT)) {
3267 addr = CtlP->AiopIO[0] + 0x88;
3268 sOutB(addr, 0);
3269 }
3270}
3271
3272/* Returns the line number given the controller (board), aiop and channel number */
3273static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
3274{
3275 return lineNumbers[(ctrl << 5) | (aiop << 3) | ch];
3276}
3277
3278/*
3279 * Stores the line number associated with a given controller (board), aiop
3280 * and channel number.
3281 * Returns: The line number assigned
3282 */
3283static unsigned char SetLineNumber(int ctrl, int aiop, int ch)
3284{
3285 lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++;
3286 return (nextLineNumber - 1);
3287}