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