blob: f4d9c39934881177c4aa45323ff90a45cebc3b86 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * RocketPort device driver for Linux
3 *
4 * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000.
5 *
6 * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23/*
24 * Kernel Synchronization:
25 *
26 * This driver has 2 kernel control paths - exception handlers (calls into the driver
27 * from user mode) and the timer bottom half (tasklet). This is a polled driver, interrupts
28 * are not used.
29 *
30 * Critical data:
31 * - rp_table[], accessed through passed "info" pointers, is a global (static) array of
32 * serial port state information and the xmit_buf circular buffer. Protected by
33 * a per port spinlock.
34 * - xmit_flags[], an array of ints indexed by line (port) number, indicating that there
35 * is data to be transmitted. Protected by atomic bit operations.
36 * - rp_num_ports, int indicating number of open ports, protected by atomic operations.
37 *
38 * rp_write() and rp_write_char() functions use a per port semaphore to protect against
39 * simultaneous access to the same port by more than one process.
40 */
41
42/****** Defines ******/
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#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
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#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>
Alan Cox44b7d1b2008-07-16 21:57:18 +010075#include <linux/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/string.h>
77#include <linux/fcntl.h>
78#include <linux/ptrace.h>
Matthias Kaehlcke69f545e2007-05-08 00:32:00 -070079#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#include <linux/ioport.h>
81#include <linux/delay.h>
Jiri Slaby8cf5a8c2007-10-18 03:06:25 -070082#include <linux/completion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070083#include <linux/wait.h>
84#include <linux/pci.h>
Alan Cox44b7d1b2008-07-16 21:57:18 +010085#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086#include <asm/atomic.h>
Al Viro457fb602008-03-19 16:27:48 +000087#include <asm/unaligned.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070088#include <linux/bitops.h>
89#include <linux/spinlock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070090#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
Jiri Slaby40565f12007-02-12 00:52:31 -0800102static void rp_do_poll(unsigned long dummy);
103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104static 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 */
Jiri Slaby40565f12007-02-12 00:52:31 -0800114static DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
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;
Alan Cox31f35932009-01-02 13:45:05 +0000138static const struct tty_port_operations rocket_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
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
Adrian Bunkf15313b2005-06-25 14:59:05 -0700160static 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218/*
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);
Adrian Bunkf15313b2005-06-25 14:59:05 -0700234static 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255MODULE_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
Bjorn Helgaasd269cdd2005-10-30 15:03:14 -0800286static int rp_init(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287static void rp_cleanup_module(void);
288
289module_init(rp_init);
290module_exit(rp_cleanup_module);
291
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293MODULE_LICENSE("Dual BSD/GPL");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
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) {
Jiri Slaby68562b72008-02-07 00:16:33 -0800305 printk(KERN_WARNING "Warning: bad magic number for rocketport "
306 "struct in %s\n", routine);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 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;
Paul Fulghumcc44a812006-06-25 05:49:12 -0700323 int ToRecv, wRecv, space;
324 unsigned char *cbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
326 ToRecv = sGetRxCnt(cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327#ifdef ROCKET_DEBUG_INTR
Jiri Slaby68562b72008-02-07 00:16:33 -0800328 printk(KERN_INFO "rp_do_receive(%d)...\n", ToRecv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329#endif
Paul Fulghumcc44a812006-06-25 05:49:12 -0700330 if (ToRecv == 0)
331 return;
Alan Cox33f0f882006-01-09 20:54:13 -0800332
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 /*
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
Jiri Slaby68562b72008-02-07 00:16:33 -0800341 printk(KERN_INFO "Entering STATMODE...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342#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
Jiri Slaby68562b72008-02-07 00:16:33 -0800355 printk(KERN_INFO "Ignore %x, read %x...\n",
356 info->ignore_status_mask, info->read_status_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357#endif
358 while (ToRecv) {
Paul Fulghumcc44a812006-06-25 05:49:12 -0700359 char flag;
360
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 CharNStat = sInW(sGetTxRxDataIO(cp));
362#ifdef ROCKET_DEBUG_RECEIVE
Jiri Slaby68562b72008-02-07 00:16:33 -0800363 printk(KERN_INFO "%x...\n", CharNStat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364#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)
Paul Fulghumcc44a812006-06-25 05:49:12 -0700373 flag = TTY_BREAK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 else if (CharNStat & STMPARITYH)
Paul Fulghumcc44a812006-06-25 05:49:12 -0700375 flag = TTY_PARITY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 else if (CharNStat & STMFRAMEH)
Paul Fulghumcc44a812006-06-25 05:49:12 -0700377 flag = TTY_FRAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 else if (CharNStat & STMRCVROVRH)
Paul Fulghumcc44a812006-06-25 05:49:12 -0700379 flag = TTY_OVERRUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 else
Paul Fulghumcc44a812006-06-25 05:49:12 -0700381 flag = TTY_NORMAL;
382 tty_insert_flip_char(tty, CharNStat & 0xff, flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 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 */
Paul Fulghumcc44a812006-06-25 05:49:12 -0700402 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 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 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));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 }
417 /* Push the data up to the tty layer */
Paul Fulghumcc44a812006-06-25 05:49:12 -0700418 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419}
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
Jiri Slaby68562b72008-02-07 00:16:33 -0800435 printk(KERN_DEBUG "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436#endif
437 if (!info)
438 return;
Alan Coxe60a1082008-07-16 21:56:18 +0100439 if (!info->port.tty) {
Jiri Slaby68562b72008-02-07 00:16:33 -0800440 printk(KERN_WARNING "rp: WARNING %s called with "
Alan Coxe60a1082008-07-16 21:56:18 +0100441 "info->port.tty==NULL\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
443 return;
444 }
445
446 spin_lock_irqsave(&info->slock, flags);
Alan Coxe60a1082008-07-16 21:56:18 +0100447 tty = info->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 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;
Harvey Harrison709107f2008-04-30 00:53:51 -0700454 c = min(info->xmit_fifo_room, info->xmit_cnt);
455 c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 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
Jiri Slaby68562b72008-02-07 00:16:33 -0800466 printk(KERN_INFO "tx %d chars...\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467#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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475#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
Jiri Slaby68562b72008-02-07 00:16:33 -0800483 printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 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
502 if ((info->flags & ROCKET_INITIALIZED) == 0) {
Jiri Slaby68562b72008-02-07 00:16:33 -0800503 printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
504 "info->flags & NOT_INIT\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 return;
506 }
Alan Coxe60a1082008-07-16 21:56:18 +0100507 if (!info->port.tty) {
Jiri Slaby68562b72008-02-07 00:16:33 -0800508 printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
Alan Coxe60a1082008-07-16 21:56:18 +0100509 "info->port.tty==NULL\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 return;
511 }
512 cp = &info->channel;
Alan Coxe60a1082008-07-16 21:56:18 +0100513 tty = info->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
515 IntMask = sGetChanIntID(cp) & info->intmask;
516#ifdef ROCKET_DEBUG_INTR
Jiri Slaby68562b72008-02-07 00:16:33 -0800517 printk(KERN_INFO "rp_interrupt %02x...\n", IntMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518#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))
Jiri Slaby68562b72008-02-07 00:16:33 -0800525 printk(KERN_INFO "ttyR%d CD now %s...\n", info->line,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 (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;
Alan Coxe60a1082008-07-16 21:56:18 +0100535 wake_up_interruptible(&info->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 }
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;
Jiri Slaby6c0286b2007-10-18 03:06:29 -0700553 int ctrl, aiop, ch, line;
554 unsigned int xmitmask, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 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
Robert P. J. Day3a4fa0a2007-10-19 23:10:43 +0200567 /* Get the interrupt status from the board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568#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 */
Yoann Padioleaudd00cc42007-07-19 01:49:03 -0700640 info = kzalloc(sizeof (struct r_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 if (!info) {
Jiri Slaby68562b72008-02-07 00:16:33 -0800642 printk(KERN_ERR "Couldn't allocate info struct for line #%d\n",
643 line);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 return;
645 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
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;
Alan Cox31f35932009-01-02 13:45:05 +0000653 tty_port_init(&info->port);
654 info->port.ops = &rocket_port_ops;
Jiri Slaby8cf5a8c2007-10-18 03:06:25 -0700655 init_completion(&info->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 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) {
Jiri Slaby68562b72008-02-07 00:16:33 -0800672 printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
673 board, aiop, chan);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 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);
Matthias Kaehlcke69f545e2007-05-08 00:32:00 -0700703 mutex_init(&info->write_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 rp_table[line] = info;
Jiri Slabyac6aec22007-10-18 03:06:26 -0700705 tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
706 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707}
708
709/*
710 * Configures a rocketport port according to its termio settings. Called from
711 * user mode into the driver (exception handler). *info CD manipulation is spinlock protected.
712 */
713static void configure_r_port(struct r_port *info,
Alan Cox606d0992006-12-08 02:38:45 -0800714 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
716 unsigned cflag;
717 unsigned long flags;
718 unsigned rocketMode;
719 int bits, baud, divisor;
720 CHANNEL_t *cp;
Alan Coxe60a1082008-07-16 21:56:18 +0100721 struct ktermios *t = info->port.tty->termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 cp = &info->channel;
Alan Cox6df35262008-02-08 04:18:45 -0800724 cflag = t->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
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 */
Alan Coxe60a1082008-07-16 21:56:18 +0100754 baud = tty_get_baud_rate(info->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 if (!baud)
756 baud = 9600;
757 divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
758 if ((divisor >= 8192 || divisor < 0) && old_termios) {
Alan Cox6df35262008-02-08 04:18:45 -0800759 baud = tty_termios_baud_rate(old_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 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
Alan Cox6df35262008-02-08 04:18:45 -0800771 /* FIXME: Should really back compute a baud rate from the divisor */
Alan Coxe60a1082008-07-16 21:56:18 +0100772 tty_encode_baud_rate(info->port.tty, baud, baud);
Alan Cox6df35262008-02-08 04:18:45 -0800773
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 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
Alan Coxe60a1082008-07-16 21:56:18 +0100797 if (I_IXON(info->port.tty)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 sEnTxSoftFlowCtl(cp);
Alan Coxe60a1082008-07-16 21:56:18 +0100799 if (I_IXANY(info->port.tty)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 sEnIXANY(cp);
801 } else {
802 sDisIXANY(cp);
803 }
Alan Coxe60a1082008-07-16 21:56:18 +0100804 sSetTxXONChar(cp, START_CHAR(info->port.tty));
805 sSetTxXOFFChar(cp, STOP_CHAR(info->port.tty));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 } 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;
Alan Coxe60a1082008-07-16 21:56:18 +0100817 if (I_INPCK(info->port.tty))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 info->read_status_mask |= STMFRAMEH | STMPARITYH;
Alan Coxe60a1082008-07-16 21:56:18 +0100819 if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 info->read_status_mask |= STMBREAKH;
821
822 /*
823 * Characters to ignore
824 */
825 info->ignore_status_mask = 0;
Alan Coxe60a1082008-07-16 21:56:18 +0100826 if (I_IGNPAR(info->port.tty))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
Alan Coxe60a1082008-07-16 21:56:18 +0100828 if (I_IGNBRK(info->port.tty)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 info->ignore_status_mask |= STMBREAKH;
830 /*
831 * If we're ignoring parity and break indicators,
832 * ignore overruns too. (For real raw support).
833 */
Alan Coxe60a1082008-07-16 21:56:18 +0100834 if (I_IGNPAR(info->port.tty))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 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
Alan Cox31f35932009-01-02 13:45:05 +0000867static 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
Alan Cox5d951fb2009-01-02 13:45:19 +0000873static 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
Alan Coxe60a1082008-07-16 21:56:18 +0100880/* info->port.count is considered critical, protected by spinlocks. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881static int block_til_ready(struct tty_struct *tty, struct file *filp,
882 struct r_port *info)
883{
884 DECLARE_WAITQUEUE(wait, current);
Alan Cox31f35932009-01-02 13:45:05 +0000885 struct tty_port *port = &info->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 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))
895 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
896 if (info->flags & ROCKET_CLOSING) {
Jiri Slaby8cf5a8c2007-10-18 03:06:25 -0700897 if (wait_for_completion_interruptible(&info->close_wait))
898 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
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))) {
907 info->flags |= ROCKET_NORMAL_ACTIVE;
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
Alan Cox31f35932009-01-02 13:45:05 +0000915 * this loop, port->count is dropped by one, so that rp_close() knows when to free things.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 * We restore it upon exit, either normal or abnormal.
917 */
918 retval = 0;
Alan Cox31f35932009-01-02 13:45:05 +0000919 add_wait_queue(&port->open_wait, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920#ifdef ROCKET_DEBUG_OPEN
Alan Cox31f35932009-01-02 13:45:05 +0000921 printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, port->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922#endif
923 spin_lock_irqsave(&info->slock, flags);
924
925#ifdef ROCKET_DISABLE_SIMUSAGE
926 info->flags |= ROCKET_NORMAL_ACTIVE;
927#else
928 if (!tty_hung_up_p(filp)) {
929 extra_count = 1;
Alan Cox31f35932009-01-02 13:45:05 +0000930 port->count--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 }
932#endif
Alan Cox31f35932009-01-02 13:45:05 +0000933 port->blocked_open++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
935 spin_unlock_irqrestore(&info->slock, flags);
936
937 while (1) {
Alan Cox5d951fb2009-01-02 13:45:19 +0000938 if (tty->termios->c_cflag & CBAUD)
939 tty_port_raise_dtr_rts(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 set_current_state(TASK_INTERRUPTIBLE);
941 if (tty_hung_up_p(filp) || !(info->flags & ROCKET_INITIALIZED)) {
942 if (info->flags & ROCKET_HUP_NOTIFY)
943 retval = -EAGAIN;
944 else
945 retval = -ERESTARTSYS;
946 break;
947 }
Alan Cox31f35932009-01-02 13:45:05 +0000948 if (!(info->flags & ROCKET_CLOSING) &&
949 (do_clocal || tty_port_carrier_raised(port)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 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",
Alan Cox31f35932009-01-02 13:45:05 +0000957 info->line, port->count, info->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958#endif
959 schedule(); /* Don't hold spinlock here, will hang PC */
960 }
Milind Arun Choudharycc0a8fb2007-05-08 00:30:52 -0700961 __set_current_state(TASK_RUNNING);
Alan Cox31f35932009-01-02 13:45:05 +0000962 remove_wait_queue(&port->open_wait, &wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
964 spin_lock_irqsave(&info->slock, flags);
965
966 if (extra_count)
Alan Cox31f35932009-01-02 13:45:05 +0000967 port->count++;
968 port->blocked_open--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969
970 spin_unlock_irqrestore(&info->slock, flags);
971
972#ifdef ROCKET_DEBUG_OPEN
973 printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n",
Alan Cox31f35932009-01-02 13:45:05 +0000974 info->line, port->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975#endif
976 if (retval)
977 return retval;
978 info->flags |= ROCKET_NORMAL_ACTIVE;
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
Jiri Slabyf6de0c92008-02-07 00:16:33 -0800993 line = tty->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 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
1001 if (info->flags & ROCKET_CLOSING) {
Jiri Slaby8cf5a8c2007-10-18 03:06:25 -07001002 retval = wait_for_completion_interruptible(&info->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 free_page(page);
Jiri Slaby8cf5a8c2007-10-18 03:06:25 -07001004 if (retval)
1005 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
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;
Alan Coxe60a1082008-07-16 21:56:18 +01001018 info->port.tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
Alan Coxe60a1082008-07-16 21:56:18 +01001020 if (info->port.count++ == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 atomic_inc(&rp_num_ports_open);
1022
1023#ifdef ROCKET_DEBUG_OPEN
Jiri Slaby68562b72008-02-07 00:16:33 -08001024 printk(KERN_INFO "rocket mod++ = %d...\n",
1025 atomic_read(&rp_num_ports_open));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026#endif
1027 }
1028#ifdef ROCKET_DEBUG_OPEN
Alan Coxe60a1082008-07-16 21:56:18 +01001029 printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030#endif
1031
1032 /*
1033 * Info->count is now 1; so it's safe to sleep now.
1034 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if ((info->flags & ROCKET_INITIALIZED) == 0) {
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
1059 info->flags |= ROCKET_INITIALIZED;
1060
1061 /*
1062 * Set up the tty->alt_speed kludge
1063 */
1064 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
Alan Coxe60a1082008-07-16 21:56:18 +01001065 info->port.tty->alt_speed = 57600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
Alan Coxe60a1082008-07-16 21:56:18 +01001067 info->port.tty->alt_speed = 115200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
Alan Coxe60a1082008-07-16 21:56:18 +01001069 info->port.tty->alt_speed = 230400;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
Alan Coxe60a1082008-07-16 21:56:18 +01001071 info->port.tty->alt_speed = 460800;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
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/*
Alan Coxe60a1082008-07-16 21:56:18 +01001093 * Exception handler that closes a serial port. info->port.count is considered critical.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 */
1095static void rp_close(struct tty_struct *tty, struct file *filp)
1096{
1097 struct r_port *info = (struct r_port *) tty->driver_data;
1098 unsigned long flags;
1099 int timeout;
1100 CHANNEL_t *cp;
1101
1102 if (rocket_paranoia_check(info, "rp_close"))
1103 return;
1104
1105#ifdef ROCKET_DEBUG_OPEN
Alan Coxe60a1082008-07-16 21:56:18 +01001106 printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107#endif
1108
1109 if (tty_hung_up_p(filp))
1110 return;
1111 spin_lock_irqsave(&info->slock, flags);
1112
Alan Coxe60a1082008-07-16 21:56:18 +01001113 if ((tty->count == 1) && (info->port.count != 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 /*
1115 * Uh, oh. tty->count is 1, which means that the tty
1116 * structure will be freed. Info->count should always
1117 * be one in these conditions. If it's greater than
1118 * one, we've got real problems, since it means the
1119 * serial port won't be shutdown.
1120 */
Jiri Slaby68562b72008-02-07 00:16:33 -08001121 printk(KERN_WARNING "rp_close: bad serial port count; "
Alan Coxe60a1082008-07-16 21:56:18 +01001122 "tty->count is 1, info->port.count is %d\n", info->port.count);
1123 info->port.count = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
Alan Coxe60a1082008-07-16 21:56:18 +01001125 if (--info->port.count < 0) {
Jiri Slaby68562b72008-02-07 00:16:33 -08001126 printk(KERN_WARNING "rp_close: bad serial port count for "
Alan Coxe60a1082008-07-16 21:56:18 +01001127 "ttyR%d: %d\n", info->line, info->port.count);
1128 info->port.count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 }
Alan Coxe60a1082008-07-16 21:56:18 +01001130 if (info->port.count) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 spin_unlock_irqrestore(&info->slock, flags);
1132 return;
1133 }
1134 info->flags |= ROCKET_CLOSING;
1135 spin_unlock_irqrestore(&info->slock, flags);
1136
1137 cp = &info->channel;
1138
1139 /*
1140 * Notify the line discpline to only process XON/XOFF characters
1141 */
1142 tty->closing = 1;
1143
1144 /*
1145 * If transmission was throttled by the application request,
1146 * just flush the xmit buffer.
1147 */
1148 if (tty->flow_stopped)
1149 rp_flush_buffer(tty);
1150
1151 /*
1152 * Wait for the transmit buffer to clear
1153 */
Alan Cox44b7d1b2008-07-16 21:57:18 +01001154 if (info->port.closing_wait != ROCKET_CLOSING_WAIT_NONE)
1155 tty_wait_until_sent(tty, info->port.closing_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 /*
1157 * Before we drop DTR, make sure the UART transmitter
1158 * has completely drained; this is especially
1159 * important if there is a transmit FIFO!
1160 */
1161 timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps;
1162 if (timeout == 0)
1163 timeout = 1;
1164 rp_wait_until_sent(tty, timeout);
1165 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1166
1167 sDisTransmit(cp);
1168 sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
1169 sDisCTSFlowCtl(cp);
1170 sDisTxSoftFlowCtl(cp);
1171 sClrTxXOFF(cp);
1172 sFlushRxFIFO(cp);
1173 sFlushTxFIFO(cp);
1174 sClrRTS(cp);
1175 if (C_HUPCL(tty))
1176 sClrDTR(cp);
1177
Jiri Slabyf6de0c92008-02-07 00:16:33 -08001178 rp_flush_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
1180 tty_ldisc_flush(tty);
1181
1182 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1183
Alan Coxe60a1082008-07-16 21:56:18 +01001184 if (info->port.blocked_open) {
Alan Cox44b7d1b2008-07-16 21:57:18 +01001185 if (info->port.close_delay) {
1186 msleep_interruptible(jiffies_to_msecs(info->port.close_delay));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 }
Alan Coxe60a1082008-07-16 21:56:18 +01001188 wake_up_interruptible(&info->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 } else {
1190 if (info->xmit_buf) {
1191 free_page((unsigned long) info->xmit_buf);
1192 info->xmit_buf = NULL;
1193 }
1194 }
1195 info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING | ROCKET_NORMAL_ACTIVE);
1196 tty->closing = 0;
Jiri Slaby8cf5a8c2007-10-18 03:06:25 -07001197 complete_all(&info->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 atomic_dec(&rp_num_ports_open);
1199
1200#ifdef ROCKET_DEBUG_OPEN
Jiri Slaby68562b72008-02-07 00:16:33 -08001201 printk(KERN_INFO "rocket mod-- = %d...\n",
1202 atomic_read(&rp_num_ports_open));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line);
1204#endif
1205
1206}
1207
1208static void rp_set_termios(struct tty_struct *tty,
Alan Cox606d0992006-12-08 02:38:45 -08001209 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
1211 struct r_port *info = (struct r_port *) tty->driver_data;
1212 CHANNEL_t *cp;
1213 unsigned cflag;
1214
1215 if (rocket_paranoia_check(info, "rp_set_termios"))
1216 return;
1217
1218 cflag = tty->termios->c_cflag;
1219
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 /*
1221 * This driver doesn't support CS5 or CS6
1222 */
1223 if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
1224 tty->termios->c_cflag =
1225 ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
Alan Cox6df35262008-02-08 04:18:45 -08001226 /* Or CMSPAR */
1227 tty->termios->c_cflag &= ~CMSPAR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 configure_r_port(info, old_termios);
1230
1231 cp = &info->channel;
1232
1233 /* Handle transition to B0 status */
1234 if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
1235 sClrDTR(cp);
1236 sClrRTS(cp);
1237 }
1238
1239 /* Handle transition away from B0 status */
1240 if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) {
1241 if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS))
1242 sSetRTS(cp);
1243 sSetDTR(cp);
1244 }
1245
1246 if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
1247 tty->hw_stopped = 0;
1248 rp_start(tty);
1249 }
1250}
1251
Alan Cox9e989662008-07-22 11:18:03 +01001252static int rp_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253{
1254 struct r_port *info = (struct r_port *) tty->driver_data;
1255 unsigned long flags;
1256
1257 if (rocket_paranoia_check(info, "rp_break"))
Alan Cox9e989662008-07-22 11:18:03 +01001258 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
1260 spin_lock_irqsave(&info->slock, flags);
1261 if (break_state == -1)
1262 sSendBreak(&info->channel);
1263 else
1264 sClrBreak(&info->channel);
1265 spin_unlock_irqrestore(&info->slock, flags);
Alan Cox9e989662008-07-22 11:18:03 +01001266 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267}
1268
1269/*
1270 * sGetChanRI used to be a macro in rocket_int.h. When the functionality for
1271 * the UPCI boards was added, it was decided to make this a function because
1272 * the macro was getting too complicated. All cases except the first one
1273 * (UPCIRingInd) are taken directly from the original macro.
1274 */
1275static int sGetChanRI(CHANNEL_T * ChP)
1276{
1277 CONTROLLER_t *CtlP = ChP->CtlP;
1278 int ChanNum = ChP->ChanNum;
1279 int RingInd = 0;
1280
1281 if (CtlP->UPCIRingInd)
1282 RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]);
1283 else if (CtlP->AltChanRingIndicator)
1284 RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT;
1285 else if (CtlP->boardType == ROCKET_TYPE_PC104)
1286 RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]);
1287
1288 return RingInd;
1289}
1290
1291/********************************************************************************************/
1292/* Here are the routines used by rp_ioctl. These are all called from exception handlers. */
1293
1294/*
1295 * Returns the state of the serial modem control lines. These next 2 functions
1296 * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
1297 */
1298static int rp_tiocmget(struct tty_struct *tty, struct file *file)
1299{
1300 struct r_port *info = (struct r_port *)tty->driver_data;
1301 unsigned int control, result, ChanStatus;
1302
1303 ChanStatus = sGetChanStatusLo(&info->channel);
1304 control = info->channel.TxControl[3];
1305 result = ((control & SET_RTS) ? TIOCM_RTS : 0) |
1306 ((control & SET_DTR) ? TIOCM_DTR : 0) |
1307 ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
1308 (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
1309 ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
1310 ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
1311
1312 return result;
1313}
1314
1315/*
1316 * Sets the modem control lines
1317 */
1318static int rp_tiocmset(struct tty_struct *tty, struct file *file,
1319 unsigned int set, unsigned int clear)
1320{
1321 struct r_port *info = (struct r_port *)tty->driver_data;
1322
1323 if (set & TIOCM_RTS)
1324 info->channel.TxControl[3] |= SET_RTS;
1325 if (set & TIOCM_DTR)
1326 info->channel.TxControl[3] |= SET_DTR;
1327 if (clear & TIOCM_RTS)
1328 info->channel.TxControl[3] &= ~SET_RTS;
1329 if (clear & TIOCM_DTR)
1330 info->channel.TxControl[3] &= ~SET_DTR;
1331
Al Viro457fb602008-03-19 16:27:48 +00001332 out32(info->channel.IndexAddr, info->channel.TxControl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 return 0;
1334}
1335
1336static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
1337{
1338 struct rocket_config tmp;
1339
1340 if (!retinfo)
1341 return -EFAULT;
1342 memset(&tmp, 0, sizeof (tmp));
1343 tmp.line = info->line;
1344 tmp.flags = info->flags;
Alan Cox44b7d1b2008-07-16 21:57:18 +01001345 tmp.close_delay = info->port.close_delay;
1346 tmp.closing_wait = info->port.closing_wait;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
1348
1349 if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
1350 return -EFAULT;
1351 return 0;
1352}
1353
1354static int set_config(struct r_port *info, struct rocket_config __user *new_info)
1355{
1356 struct rocket_config new_serial;
1357
1358 if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
1359 return -EFAULT;
1360
1361 if (!capable(CAP_SYS_ADMIN))
1362 {
1363 if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
1364 return -EPERM;
1365 info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
1366 configure_r_port(info, NULL);
1367 return 0;
1368 }
1369
1370 info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
Alan Cox44b7d1b2008-07-16 21:57:18 +01001371 info->port.close_delay = new_serial.close_delay;
1372 info->port.closing_wait = new_serial.closing_wait;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
1374 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
Alan Coxe60a1082008-07-16 21:56:18 +01001375 info->port.tty->alt_speed = 57600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
Alan Coxe60a1082008-07-16 21:56:18 +01001377 info->port.tty->alt_speed = 115200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
Alan Coxe60a1082008-07-16 21:56:18 +01001379 info->port.tty->alt_speed = 230400;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
Alan Coxe60a1082008-07-16 21:56:18 +01001381 info->port.tty->alt_speed = 460800;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
1383 configure_r_port(info, NULL);
1384 return 0;
1385}
1386
1387/*
1388 * This function fills in a rocket_ports struct with information
1389 * about what boards/ports are in the system. This info is passed
1390 * to user space. See setrocket.c where the info is used to create
1391 * the /dev/ttyRx ports.
1392 */
1393static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
1394{
1395 struct rocket_ports tmp;
1396 int board;
1397
1398 if (!retports)
1399 return -EFAULT;
1400 memset(&tmp, 0, sizeof (tmp));
1401 tmp.tty_major = rocket_driver->major;
1402
1403 for (board = 0; board < 4; board++) {
1404 tmp.rocketModel[board].model = rocketModel[board].model;
1405 strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString);
1406 tmp.rocketModel[board].numPorts = rocketModel[board].numPorts;
1407 tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
1408 tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber;
1409 }
1410 if (copy_to_user(retports, &tmp, sizeof (*retports)))
1411 return -EFAULT;
1412 return 0;
1413}
1414
1415static int reset_rm2(struct r_port *info, void __user *arg)
1416{
1417 int reset;
1418
Alan Cox4129a6452008-02-08 04:18:45 -08001419 if (!capable(CAP_SYS_ADMIN))
1420 return -EPERM;
1421
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 if (copy_from_user(&reset, arg, sizeof (int)))
1423 return -EFAULT;
1424 if (reset)
1425 reset = 1;
1426
1427 if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII &&
1428 rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII)
1429 return -EINVAL;
1430
1431 if (info->ctlp->BusType == isISA)
1432 sModemReset(info->ctlp, info->chan, reset);
1433 else
1434 sPCIModemReset(info->ctlp, info->chan, reset);
1435
1436 return 0;
1437}
1438
1439static int get_version(struct r_port *info, struct rocket_version __user *retvers)
1440{
1441 if (copy_to_user(retvers, &driver_version, sizeof (*retvers)))
1442 return -EFAULT;
1443 return 0;
1444}
1445
1446/* IOCTL call handler into the driver */
1447static int rp_ioctl(struct tty_struct *tty, struct file *file,
1448 unsigned int cmd, unsigned long arg)
1449{
1450 struct r_port *info = (struct r_port *) tty->driver_data;
1451 void __user *argp = (void __user *)arg;
Alan Coxbdf183a2008-04-30 00:53:21 -07001452 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454 if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
1455 return -ENXIO;
1456
Alan Coxbdf183a2008-04-30 00:53:21 -07001457 lock_kernel();
1458
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 switch (cmd) {
1460 case RCKP_GET_STRUCT:
1461 if (copy_to_user(argp, info, sizeof (struct r_port)))
Alan Coxbdf183a2008-04-30 00:53:21 -07001462 ret = -EFAULT;
1463 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 case RCKP_GET_CONFIG:
Alan Coxbdf183a2008-04-30 00:53:21 -07001465 ret = get_config(info, argp);
1466 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 case RCKP_SET_CONFIG:
Alan Coxbdf183a2008-04-30 00:53:21 -07001468 ret = set_config(info, argp);
1469 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 case RCKP_GET_PORTS:
Alan Coxbdf183a2008-04-30 00:53:21 -07001471 ret = get_ports(info, argp);
1472 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 case RCKP_RESET_RM2:
Alan Coxbdf183a2008-04-30 00:53:21 -07001474 ret = reset_rm2(info, argp);
1475 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 case RCKP_GET_VERSION:
Alan Coxbdf183a2008-04-30 00:53:21 -07001477 ret = get_version(info, argp);
1478 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 default:
Alan Coxbdf183a2008-04-30 00:53:21 -07001480 ret = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 }
Alan Coxbdf183a2008-04-30 00:53:21 -07001482 unlock_kernel();
1483 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484}
1485
1486static void rp_send_xchar(struct tty_struct *tty, char ch)
1487{
1488 struct r_port *info = (struct r_port *) tty->driver_data;
1489 CHANNEL_t *cp;
1490
1491 if (rocket_paranoia_check(info, "rp_send_xchar"))
1492 return;
1493
1494 cp = &info->channel;
1495 if (sGetTxCnt(cp))
1496 sWriteTxPrioByte(cp, ch);
1497 else
1498 sWriteTxByte(sGetTxRxDataIO(cp), ch);
1499}
1500
1501static void rp_throttle(struct tty_struct *tty)
1502{
1503 struct r_port *info = (struct r_port *) tty->driver_data;
1504 CHANNEL_t *cp;
1505
1506#ifdef ROCKET_DEBUG_THROTTLE
1507 printk(KERN_INFO "throttle %s: %d....\n", tty->name,
1508 tty->ldisc.chars_in_buffer(tty));
1509#endif
1510
1511 if (rocket_paranoia_check(info, "rp_throttle"))
1512 return;
1513
1514 cp = &info->channel;
1515 if (I_IXOFF(tty))
1516 rp_send_xchar(tty, STOP_CHAR(tty));
1517
1518 sClrRTS(&info->channel);
1519}
1520
1521static void rp_unthrottle(struct tty_struct *tty)
1522{
1523 struct r_port *info = (struct r_port *) tty->driver_data;
1524 CHANNEL_t *cp;
1525#ifdef ROCKET_DEBUG_THROTTLE
1526 printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
1527 tty->ldisc.chars_in_buffer(tty));
1528#endif
1529
1530 if (rocket_paranoia_check(info, "rp_throttle"))
1531 return;
1532
1533 cp = &info->channel;
1534 if (I_IXOFF(tty))
1535 rp_send_xchar(tty, START_CHAR(tty));
1536
1537 sSetRTS(&info->channel);
1538}
1539
1540/*
1541 * ------------------------------------------------------------
1542 * rp_stop() and rp_start()
1543 *
1544 * This routines are called before setting or resetting tty->stopped.
1545 * They enable or disable transmitter interrupts, as necessary.
1546 * ------------------------------------------------------------
1547 */
1548static void rp_stop(struct tty_struct *tty)
1549{
1550 struct r_port *info = (struct r_port *) tty->driver_data;
1551
1552#ifdef ROCKET_DEBUG_FLOW
1553 printk(KERN_INFO "stop %s: %d %d....\n", tty->name,
1554 info->xmit_cnt, info->xmit_fifo_room);
1555#endif
1556
1557 if (rocket_paranoia_check(info, "rp_stop"))
1558 return;
1559
1560 if (sGetTxCnt(&info->channel))
1561 sDisTransmit(&info->channel);
1562}
1563
1564static void rp_start(struct tty_struct *tty)
1565{
1566 struct r_port *info = (struct r_port *) tty->driver_data;
1567
1568#ifdef ROCKET_DEBUG_FLOW
1569 printk(KERN_INFO "start %s: %d %d....\n", tty->name,
1570 info->xmit_cnt, info->xmit_fifo_room);
1571#endif
1572
1573 if (rocket_paranoia_check(info, "rp_stop"))
1574 return;
1575
1576 sEnTransmit(&info->channel);
1577 set_bit((info->aiop * 8) + info->chan,
1578 (void *) &xmit_flags[info->board]);
1579}
1580
1581/*
1582 * rp_wait_until_sent() --- wait until the transmitter is empty
1583 */
1584static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
1585{
1586 struct r_port *info = (struct r_port *) tty->driver_data;
1587 CHANNEL_t *cp;
1588 unsigned long orig_jiffies;
1589 int check_time, exit_time;
1590 int txcnt;
1591
1592 if (rocket_paranoia_check(info, "rp_wait_until_sent"))
1593 return;
1594
1595 cp = &info->channel;
1596
1597 orig_jiffies = jiffies;
1598#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
Jiri Slaby68562b72008-02-07 00:16:33 -08001599 printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...\n", timeout,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 jiffies);
Jiri Slaby68562b72008-02-07 00:16:33 -08001601 printk(KERN_INFO "cps=%d...\n", info->cps);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602#endif
Alan Cox978e5952008-04-30 00:53:59 -07001603 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 while (1) {
1605 txcnt = sGetTxCnt(cp);
1606 if (!txcnt) {
1607 if (sGetChanStatusLo(cp) & TXSHRMT)
1608 break;
1609 check_time = (HZ / info->cps) / 5;
1610 } else {
1611 check_time = HZ * txcnt / info->cps;
1612 }
1613 if (timeout) {
1614 exit_time = orig_jiffies + timeout - jiffies;
1615 if (exit_time <= 0)
1616 break;
1617 if (exit_time < check_time)
1618 check_time = exit_time;
1619 }
1620 if (check_time == 0)
1621 check_time = 1;
1622#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
Jiri Slaby68562b72008-02-07 00:16:33 -08001623 printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...\n", txcnt,
1624 jiffies, check_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625#endif
1626 msleep_interruptible(jiffies_to_msecs(check_time));
1627 if (signal_pending(current))
1628 break;
1629 }
Milind Arun Choudharycc0a8fb2007-05-08 00:30:52 -07001630 __set_current_state(TASK_RUNNING);
Alan Cox978e5952008-04-30 00:53:59 -07001631 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
1633 printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
1634#endif
1635}
1636
1637/*
1638 * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
1639 */
1640static void rp_hangup(struct tty_struct *tty)
1641{
1642 CHANNEL_t *cp;
1643 struct r_port *info = (struct r_port *) tty->driver_data;
1644
1645 if (rocket_paranoia_check(info, "rp_hangup"))
1646 return;
1647
1648#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
Jiri Slaby68562b72008-02-07 00:16:33 -08001649 printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650#endif
1651 rp_flush_buffer(tty);
1652 if (info->flags & ROCKET_CLOSING)
1653 return;
Alan Coxe60a1082008-07-16 21:56:18 +01001654 if (info->port.count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 atomic_dec(&rp_num_ports_open);
1656 clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1657
Alan Coxe60a1082008-07-16 21:56:18 +01001658 info->port.count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 info->flags &= ~ROCKET_NORMAL_ACTIVE;
Alan Coxe60a1082008-07-16 21:56:18 +01001660 info->port.tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
1662 cp = &info->channel;
1663 sDisRxFIFO(cp);
1664 sDisTransmit(cp);
1665 sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
1666 sDisCTSFlowCtl(cp);
1667 sDisTxSoftFlowCtl(cp);
1668 sClrTxXOFF(cp);
1669 info->flags &= ~ROCKET_INITIALIZED;
1670
Alan Coxe60a1082008-07-16 21:56:18 +01001671 wake_up_interruptible(&info->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672}
1673
1674/*
1675 * Exception handler - write char routine. The RocketPort driver uses a
1676 * double-buffering strategy, with the twist that if the in-memory CPU
1677 * buffer is empty, and there's space in the transmit FIFO, the
1678 * writing routines will write directly to transmit FIFO.
1679 * Write buffer and counters protected by spinlocks
1680 */
Alan Coxbbbbb962008-04-30 00:54:05 -07001681static int rp_put_char(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682{
1683 struct r_port *info = (struct r_port *) tty->driver_data;
1684 CHANNEL_t *cp;
1685 unsigned long flags;
1686
1687 if (rocket_paranoia_check(info, "rp_put_char"))
Alan Coxbbbbb962008-04-30 00:54:05 -07001688 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
Matthias Kaehlcke69f545e2007-05-08 00:32:00 -07001690 /*
1691 * Grab the port write mutex, locking out other processes that try to
1692 * write to this port
1693 */
1694 mutex_lock(&info->write_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
1696#ifdef ROCKET_DEBUG_WRITE
Jiri Slaby68562b72008-02-07 00:16:33 -08001697 printk(KERN_INFO "rp_put_char %c...\n", ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698#endif
1699
1700 spin_lock_irqsave(&info->slock, flags);
1701 cp = &info->channel;
1702
1703 if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
1704 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1705
1706 if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
1707 info->xmit_buf[info->xmit_head++] = ch;
1708 info->xmit_head &= XMIT_BUF_SIZE - 1;
1709 info->xmit_cnt++;
1710 set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1711 } else {
1712 sOutB(sGetTxRxDataIO(cp), ch);
1713 info->xmit_fifo_room--;
1714 }
1715 spin_unlock_irqrestore(&info->slock, flags);
Matthias Kaehlcke69f545e2007-05-08 00:32:00 -07001716 mutex_unlock(&info->write_mtx);
Alan Coxbbbbb962008-04-30 00:54:05 -07001717 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718}
1719
1720/*
1721 * Exception handler - write routine, called when user app writes to the device.
Matthias Kaehlcke69f545e2007-05-08 00:32:00 -07001722 * A per port write mutex is used to protect from another process writing to
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 * this port at the same time. This other process could be running on the other CPU
1724 * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out).
1725 * Spinlocks protect the info xmit members.
1726 */
1727static int rp_write(struct tty_struct *tty,
1728 const unsigned char *buf, int count)
1729{
1730 struct r_port *info = (struct r_port *) tty->driver_data;
1731 CHANNEL_t *cp;
1732 const unsigned char *b;
1733 int c, retval = 0;
1734 unsigned long flags;
1735
1736 if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
1737 return 0;
1738
Satyam Sharma1e3e8d92007-07-15 23:40:07 -07001739 if (mutex_lock_interruptible(&info->write_mtx))
1740 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
1742#ifdef ROCKET_DEBUG_WRITE
Jiri Slaby68562b72008-02-07 00:16:33 -08001743 printk(KERN_INFO "rp_write %d chars...\n", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744#endif
1745 cp = &info->channel;
1746
1747 if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count)
1748 info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1749
1750 /*
1751 * If the write queue for the port is empty, and there is FIFO space, stuff bytes
1752 * into FIFO. Use the write queue for temp storage.
1753 */
1754 if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
1755 c = min(count, info->xmit_fifo_room);
1756 b = buf;
1757
1758 /* Push data into FIFO, 2 bytes at a time */
1759 sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2);
1760
1761 /* If there is a byte remaining, write it */
1762 if (c & 1)
1763 sOutB(sGetTxRxDataIO(cp), b[c - 1]);
1764
1765 retval += c;
1766 buf += c;
1767 count -= c;
1768
1769 spin_lock_irqsave(&info->slock, flags);
1770 info->xmit_fifo_room -= c;
1771 spin_unlock_irqrestore(&info->slock, flags);
1772 }
1773
1774 /* If count is zero, we wrote it all and are done */
1775 if (!count)
1776 goto end;
1777
1778 /* Write remaining data into the port's xmit_buf */
1779 while (1) {
Alan Coxe60a1082008-07-16 21:56:18 +01001780 if (!info->port.tty) /* Seemingly obligatory check... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 goto end;
Harvey Harrison709107f2008-04-30 00:53:51 -07001782 c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
1783 c = min(c, XMIT_BUF_SIZE - info->xmit_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 if (c <= 0)
1785 break;
1786
1787 b = buf;
1788 memcpy(info->xmit_buf + info->xmit_head, b, c);
1789
1790 spin_lock_irqsave(&info->slock, flags);
1791 info->xmit_head =
1792 (info->xmit_head + c) & (XMIT_BUF_SIZE - 1);
1793 info->xmit_cnt += c;
1794 spin_unlock_irqrestore(&info->slock, flags);
1795
1796 buf += c;
1797 count -= c;
1798 retval += c;
1799 }
1800
1801 if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
1802 set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
1803
1804end:
1805 if (info->xmit_cnt < WAKEUP_CHARS) {
1806 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807#ifdef ROCKETPORT_HAVE_POLL_WAIT
1808 wake_up_interruptible(&tty->poll_wait);
1809#endif
1810 }
Matthias Kaehlcke69f545e2007-05-08 00:32:00 -07001811 mutex_unlock(&info->write_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 return retval;
1813}
1814
1815/*
1816 * Return the number of characters that can be sent. We estimate
1817 * only using the in-memory transmit buffer only, and ignore the
1818 * potential space in the transmit FIFO.
1819 */
1820static int rp_write_room(struct tty_struct *tty)
1821{
1822 struct r_port *info = (struct r_port *) tty->driver_data;
1823 int ret;
1824
1825 if (rocket_paranoia_check(info, "rp_write_room"))
1826 return 0;
1827
1828 ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
1829 if (ret < 0)
1830 ret = 0;
1831#ifdef ROCKET_DEBUG_WRITE
Jiri Slaby68562b72008-02-07 00:16:33 -08001832 printk(KERN_INFO "rp_write_room returns %d...\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833#endif
1834 return ret;
1835}
1836
1837/*
1838 * Return the number of characters in the buffer. Again, this only
1839 * counts those characters in the in-memory transmit buffer.
1840 */
1841static int rp_chars_in_buffer(struct tty_struct *tty)
1842{
1843 struct r_port *info = (struct r_port *) tty->driver_data;
1844 CHANNEL_t *cp;
1845
1846 if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
1847 return 0;
1848
1849 cp = &info->channel;
1850
1851#ifdef ROCKET_DEBUG_WRITE
Jiri Slaby68562b72008-02-07 00:16:33 -08001852 printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853#endif
1854 return info->xmit_cnt;
1855}
1856
1857/*
1858 * Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the
1859 * r_port struct for the port. Note that spinlock are used to protect info members,
1860 * do not call this function if the spinlock is already held.
1861 */
1862static void rp_flush_buffer(struct tty_struct *tty)
1863{
1864 struct r_port *info = (struct r_port *) tty->driver_data;
1865 CHANNEL_t *cp;
1866 unsigned long flags;
1867
1868 if (rocket_paranoia_check(info, "rp_flush_buffer"))
1869 return;
1870
1871 spin_lock_irqsave(&info->slock, flags);
1872 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1873 spin_unlock_irqrestore(&info->slock, flags);
1874
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875#ifdef ROCKETPORT_HAVE_POLL_WAIT
1876 wake_up_interruptible(&tty->poll_wait);
1877#endif
1878 tty_wakeup(tty);
1879
1880 cp = &info->channel;
1881 sFlushTxFIFO(cp);
1882}
1883
1884#ifdef CONFIG_PCI
1885
Jiri Slaby8d5916d2007-05-08 00:27:05 -07001886static struct pci_device_id __devinitdata rocket_pci_ids[] = {
1887 { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
1888 { }
1889};
1890MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
1891
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892/*
1893 * Called when a PCI card is found. Retrieves and stores model information,
1894 * init's aiopic and serial port hardware.
1895 * Inputs: i is the board number (0-n)
1896 */
Adrian Bunkf15313b2005-06-25 14:59:05 -07001897static __init int register_PCI(int i, struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898{
1899 int num_aiops, aiop, max_num_aiops, num_chan, chan;
1900 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1901 char *str, *board_type;
1902 CONTROLLER_t *ctlp;
1903
1904 int fast_clock = 0;
1905 int altChanRingIndicator = 0;
1906 int ports_per_aiop = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 WordIO_t ConfigIO = 0;
1908 ByteIO_t UPCIRingInd = 0;
1909
1910 if (!dev || pci_enable_device(dev))
1911 return 0;
1912
1913 rcktpt_io_addr[i] = pci_resource_start(dev, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914
1915 rcktpt_type[i] = ROCKET_TYPE_NORMAL;
1916 rocketModel[i].loadrm2 = 0;
1917 rocketModel[i].startingPortNumber = nextLineNumber;
1918
1919 /* Depending on the model, set up some config variables */
1920 switch (dev->device) {
1921 case PCI_DEVICE_ID_RP4QUAD:
1922 str = "Quadcable";
1923 max_num_aiops = 1;
1924 ports_per_aiop = 4;
1925 rocketModel[i].model = MODEL_RP4QUAD;
1926 strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable");
1927 rocketModel[i].numPorts = 4;
1928 break;
1929 case PCI_DEVICE_ID_RP8OCTA:
1930 str = "Octacable";
1931 max_num_aiops = 1;
1932 rocketModel[i].model = MODEL_RP8OCTA;
1933 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
1934 rocketModel[i].numPorts = 8;
1935 break;
1936 case PCI_DEVICE_ID_URP8OCTA:
1937 str = "Octacable";
1938 max_num_aiops = 1;
1939 rocketModel[i].model = MODEL_UPCI_RP8OCTA;
1940 strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
1941 rocketModel[i].numPorts = 8;
1942 break;
1943 case PCI_DEVICE_ID_RP8INTF:
1944 str = "8";
1945 max_num_aiops = 1;
1946 rocketModel[i].model = MODEL_RP8INTF;
1947 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
1948 rocketModel[i].numPorts = 8;
1949 break;
1950 case PCI_DEVICE_ID_URP8INTF:
1951 str = "8";
1952 max_num_aiops = 1;
1953 rocketModel[i].model = MODEL_UPCI_RP8INTF;
1954 strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
1955 rocketModel[i].numPorts = 8;
1956 break;
1957 case PCI_DEVICE_ID_RP8J:
1958 str = "8J";
1959 max_num_aiops = 1;
1960 rocketModel[i].model = MODEL_RP8J;
1961 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
1962 rocketModel[i].numPorts = 8;
1963 break;
1964 case PCI_DEVICE_ID_RP4J:
1965 str = "4J";
1966 max_num_aiops = 1;
1967 ports_per_aiop = 4;
1968 rocketModel[i].model = MODEL_RP4J;
1969 strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors");
1970 rocketModel[i].numPorts = 4;
1971 break;
1972 case PCI_DEVICE_ID_RP8SNI:
1973 str = "8 (DB78 Custom)";
1974 max_num_aiops = 1;
1975 rocketModel[i].model = MODEL_RP8SNI;
1976 strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
1977 rocketModel[i].numPorts = 8;
1978 break;
1979 case PCI_DEVICE_ID_RP16SNI:
1980 str = "16 (DB78 Custom)";
1981 max_num_aiops = 2;
1982 rocketModel[i].model = MODEL_RP16SNI;
1983 strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
1984 rocketModel[i].numPorts = 16;
1985 break;
1986 case PCI_DEVICE_ID_RP16INTF:
1987 str = "16";
1988 max_num_aiops = 2;
1989 rocketModel[i].model = MODEL_RP16INTF;
1990 strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
1991 rocketModel[i].numPorts = 16;
1992 break;
1993 case PCI_DEVICE_ID_URP16INTF:
1994 str = "16";
1995 max_num_aiops = 2;
1996 rocketModel[i].model = MODEL_UPCI_RP16INTF;
1997 strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
1998 rocketModel[i].numPorts = 16;
1999 break;
2000 case PCI_DEVICE_ID_CRP16INTF:
2001 str = "16";
2002 max_num_aiops = 2;
2003 rocketModel[i].model = MODEL_CPCI_RP16INTF;
2004 strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
2005 rocketModel[i].numPorts = 16;
2006 break;
2007 case PCI_DEVICE_ID_RP32INTF:
2008 str = "32";
2009 max_num_aiops = 4;
2010 rocketModel[i].model = MODEL_RP32INTF;
2011 strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
2012 rocketModel[i].numPorts = 32;
2013 break;
2014 case PCI_DEVICE_ID_URP32INTF:
2015 str = "32";
2016 max_num_aiops = 4;
2017 rocketModel[i].model = MODEL_UPCI_RP32INTF;
2018 strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
2019 rocketModel[i].numPorts = 32;
2020 break;
2021 case PCI_DEVICE_ID_RPP4:
2022 str = "Plus Quadcable";
2023 max_num_aiops = 1;
2024 ports_per_aiop = 4;
2025 altChanRingIndicator++;
2026 fast_clock++;
2027 rocketModel[i].model = MODEL_RPP4;
2028 strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port");
2029 rocketModel[i].numPorts = 4;
2030 break;
2031 case PCI_DEVICE_ID_RPP8:
2032 str = "Plus Octacable";
2033 max_num_aiops = 2;
2034 ports_per_aiop = 4;
2035 altChanRingIndicator++;
2036 fast_clock++;
2037 rocketModel[i].model = MODEL_RPP8;
2038 strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port");
2039 rocketModel[i].numPorts = 8;
2040 break;
2041 case PCI_DEVICE_ID_RP2_232:
2042 str = "Plus 2 (RS-232)";
2043 max_num_aiops = 1;
2044 ports_per_aiop = 2;
2045 altChanRingIndicator++;
2046 fast_clock++;
2047 rocketModel[i].model = MODEL_RP2_232;
2048 strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232");
2049 rocketModel[i].numPorts = 2;
2050 break;
2051 case PCI_DEVICE_ID_RP2_422:
2052 str = "Plus 2 (RS-422)";
2053 max_num_aiops = 1;
2054 ports_per_aiop = 2;
2055 altChanRingIndicator++;
2056 fast_clock++;
2057 rocketModel[i].model = MODEL_RP2_422;
2058 strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422");
2059 rocketModel[i].numPorts = 2;
2060 break;
2061 case PCI_DEVICE_ID_RP6M:
2062
2063 max_num_aiops = 1;
2064 ports_per_aiop = 6;
2065 str = "6-port";
2066
Jiri Slaby57fedc72007-10-18 03:06:28 -07002067 /* If revision is 1, the rocketmodem flash must be loaded.
2068 * If it is 2 it is a "socketed" version. */
2069 if (dev->revision == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 rcktpt_type[i] = ROCKET_TYPE_MODEMII;
2071 rocketModel[i].loadrm2 = 1;
2072 } else {
2073 rcktpt_type[i] = ROCKET_TYPE_MODEM;
2074 }
2075
2076 rocketModel[i].model = MODEL_RP6M;
2077 strcpy(rocketModel[i].modelString, "RocketModem 6 port");
2078 rocketModel[i].numPorts = 6;
2079 break;
2080 case PCI_DEVICE_ID_RP4M:
2081 max_num_aiops = 1;
2082 ports_per_aiop = 4;
2083 str = "4-port";
Jiri Slaby57fedc72007-10-18 03:06:28 -07002084 if (dev->revision == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 rcktpt_type[i] = ROCKET_TYPE_MODEMII;
2086 rocketModel[i].loadrm2 = 1;
2087 } else {
2088 rcktpt_type[i] = ROCKET_TYPE_MODEM;
2089 }
2090
2091 rocketModel[i].model = MODEL_RP4M;
2092 strcpy(rocketModel[i].modelString, "RocketModem 4 port");
2093 rocketModel[i].numPorts = 4;
2094 break;
2095 default:
2096 str = "(unknown/unsupported)";
2097 max_num_aiops = 0;
2098 break;
2099 }
2100
2101 /*
2102 * Check for UPCI boards.
2103 */
2104
2105 switch (dev->device) {
2106 case PCI_DEVICE_ID_URP32INTF:
2107 case PCI_DEVICE_ID_URP8INTF:
2108 case PCI_DEVICE_ID_URP16INTF:
2109 case PCI_DEVICE_ID_CRP16INTF:
2110 case PCI_DEVICE_ID_URP8OCTA:
2111 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2112 ConfigIO = pci_resource_start(dev, 1);
2113 if (dev->device == PCI_DEVICE_ID_URP8OCTA) {
2114 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2115
2116 /*
2117 * Check for octa or quad cable.
2118 */
2119 if (!
2120 (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
2121 PCI_GPIO_CTRL_8PORT)) {
2122 str = "Quadcable";
2123 ports_per_aiop = 4;
2124 rocketModel[i].numPorts = 4;
2125 }
2126 }
2127 break;
2128 case PCI_DEVICE_ID_UPCI_RM3_8PORT:
2129 str = "8 ports";
2130 max_num_aiops = 1;
2131 rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
2132 strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
2133 rocketModel[i].numPorts = 8;
2134 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2135 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2136 ConfigIO = pci_resource_start(dev, 1);
2137 rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
2138 break;
2139 case PCI_DEVICE_ID_UPCI_RM3_4PORT:
2140 str = "4 ports";
2141 max_num_aiops = 1;
2142 rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
2143 strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
2144 rocketModel[i].numPorts = 4;
2145 rcktpt_io_addr[i] = pci_resource_start(dev, 2);
2146 UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
2147 ConfigIO = pci_resource_start(dev, 1);
2148 rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
2149 break;
2150 default:
2151 break;
2152 }
2153
2154 switch (rcktpt_type[i]) {
2155 case ROCKET_TYPE_MODEM:
2156 board_type = "RocketModem";
2157 break;
2158 case ROCKET_TYPE_MODEMII:
2159 board_type = "RocketModem II";
2160 break;
2161 case ROCKET_TYPE_MODEMIII:
2162 board_type = "RocketModem III";
2163 break;
2164 default:
2165 board_type = "RocketPort";
2166 break;
2167 }
2168
2169 if (fast_clock) {
2170 sClockPrescale = 0x12; /* mod 2 (divide by 3) */
2171 rp_baud_base[i] = 921600;
2172 } else {
2173 /*
2174 * If support_low_speed is set, use the slow clock
2175 * prescale, which supports 50 bps
2176 */
2177 if (support_low_speed) {
2178 /* mod 9 (divide by 10) prescale */
2179 sClockPrescale = 0x19;
2180 rp_baud_base[i] = 230400;
2181 } else {
2182 /* mod 4 (devide by 5) prescale */
2183 sClockPrescale = 0x14;
2184 rp_baud_base[i] = 460800;
2185 }
2186 }
2187
2188 for (aiop = 0; aiop < max_num_aiops; aiop++)
2189 aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
2190 ctlp = sCtlNumToCtlPtr(i);
2191 num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd);
2192 for (aiop = 0; aiop < max_num_aiops; aiop++)
2193 ctlp->AiopNumChan[aiop] = ports_per_aiop;
2194
Jiri Slaby68562b72008-02-07 00:16:33 -08002195 dev_info(&dev->dev, "comtrol PCI controller #%d found at "
2196 "address %04lx, %d AIOP(s) (%s), creating ttyR%d - %ld\n",
2197 i, rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString,
2198 rocketModel[i].startingPortNumber,
2199 rocketModel[i].startingPortNumber + rocketModel[i].numPorts-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
2201 if (num_aiops <= 0) {
2202 rcktpt_io_addr[i] = 0;
2203 return (0);
2204 }
2205 is_PCI[i] = 1;
2206
2207 /* Reset the AIOPIC, init the serial ports */
2208 for (aiop = 0; aiop < num_aiops; aiop++) {
2209 sResetAiopByNum(ctlp, aiop);
2210 num_chan = ports_per_aiop;
2211 for (chan = 0; chan < num_chan; chan++)
2212 init_r_port(i, aiop, chan, dev);
2213 }
2214
2215 /* Rocket modems must be reset */
2216 if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
2217 (rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
2218 (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
2219 num_chan = ports_per_aiop;
2220 for (chan = 0; chan < num_chan; chan++)
2221 sPCIModemReset(ctlp, chan, 1);
Jiri Slaby48a67f52008-02-07 00:16:32 -08002222 msleep(500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 for (chan = 0; chan < num_chan; chan++)
2224 sPCIModemReset(ctlp, chan, 0);
Jiri Slaby48a67f52008-02-07 00:16:32 -08002225 msleep(500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 rmSpeakerReset(ctlp, rocketModel[i].model);
2227 }
2228 return (1);
2229}
2230
2231/*
2232 * Probes for PCI cards, inits them if found
2233 * Input: board_found = number of ISA boards already found, or the
2234 * starting board number
2235 * Returns: Number of PCI boards found
2236 */
2237static int __init init_PCI(int boards_found)
2238{
2239 struct pci_dev *dev = NULL;
2240 int count = 0;
2241
2242 /* Work through the PCI device list, pulling out ours */
Alan Cox606d0992006-12-08 02:38:45 -08002243 while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 if (register_PCI(count + boards_found, dev))
2245 count++;
2246 }
2247 return (count);
2248}
2249
2250#endif /* CONFIG_PCI */
2251
2252/*
2253 * Probes for ISA cards
2254 * Input: i = the board number to look for
2255 * Returns: 1 if board found, 0 else
2256 */
2257static int __init init_ISA(int i)
2258{
2259 int num_aiops, num_chan = 0, total_num_chan = 0;
2260 int aiop, chan;
2261 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
2262 CONTROLLER_t *ctlp;
2263 char *type_string;
2264
2265 /* If io_addr is zero, no board configured */
2266 if (rcktpt_io_addr[i] == 0)
2267 return (0);
2268
2269 /* Reserve the IO region */
2270 if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) {
Jiri Slaby68562b72008-02-07 00:16:33 -08002271 printk(KERN_ERR "Unable to reserve IO region for configured "
2272 "ISA RocketPort at address 0x%lx, board not "
2273 "installed...\n", rcktpt_io_addr[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 rcktpt_io_addr[i] = 0;
2275 return (0);
2276 }
2277
2278 ctlp = sCtlNumToCtlPtr(i);
2279
2280 ctlp->boardType = rcktpt_type[i];
2281
2282 switch (rcktpt_type[i]) {
2283 case ROCKET_TYPE_PC104:
2284 type_string = "(PC104)";
2285 break;
2286 case ROCKET_TYPE_MODEM:
2287 type_string = "(RocketModem)";
2288 break;
2289 case ROCKET_TYPE_MODEMII:
2290 type_string = "(RocketModem II)";
2291 break;
2292 default:
2293 type_string = "";
2294 break;
2295 }
2296
2297 /*
2298 * If support_low_speed is set, use the slow clock prescale,
2299 * which supports 50 bps
2300 */
2301 if (support_low_speed) {
2302 sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */
2303 rp_baud_base[i] = 230400;
2304 } else {
2305 sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */
2306 rp_baud_base[i] = 460800;
2307 }
2308
2309 for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
2310 aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400);
2311
2312 num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
2313
2314 if (ctlp->boardType == ROCKET_TYPE_PC104) {
2315 sEnAiop(ctlp, 2); /* only one AIOPIC, but these */
2316 sEnAiop(ctlp, 3); /* CSels used for other stuff */
2317 }
2318
2319 /* If something went wrong initing the AIOP's release the ISA IO memory */
2320 if (num_aiops <= 0) {
2321 release_region(rcktpt_io_addr[i], 64);
2322 rcktpt_io_addr[i] = 0;
2323 return (0);
2324 }
2325
2326 rocketModel[i].startingPortNumber = nextLineNumber;
2327
2328 for (aiop = 0; aiop < num_aiops; aiop++) {
2329 sResetAiopByNum(ctlp, aiop);
2330 sEnAiop(ctlp, aiop);
2331 num_chan = sGetAiopNumChan(ctlp, aiop);
2332 total_num_chan += num_chan;
2333 for (chan = 0; chan < num_chan; chan++)
2334 init_r_port(i, aiop, chan, NULL);
2335 }
2336 is_PCI[i] = 0;
2337 if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) {
2338 num_chan = sGetAiopNumChan(ctlp, 0);
2339 total_num_chan = num_chan;
2340 for (chan = 0; chan < num_chan; chan++)
2341 sModemReset(ctlp, chan, 1);
Jiri Slaby48a67f52008-02-07 00:16:32 -08002342 msleep(500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 for (chan = 0; chan < num_chan; chan++)
2344 sModemReset(ctlp, chan, 0);
Jiri Slaby48a67f52008-02-07 00:16:32 -08002345 msleep(500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 strcpy(rocketModel[i].modelString, "RocketModem ISA");
2347 } else {
2348 strcpy(rocketModel[i].modelString, "RocketPort ISA");
2349 }
2350 rocketModel[i].numPorts = total_num_chan;
2351 rocketModel[i].model = MODEL_ISA;
2352
2353 printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n",
2354 i, rcktpt_io_addr[i], num_aiops, type_string);
2355
2356 printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
2357 rocketModel[i].modelString,
2358 rocketModel[i].startingPortNumber,
2359 rocketModel[i].startingPortNumber +
2360 rocketModel[i].numPorts - 1);
2361
2362 return (1);
2363}
2364
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002365static const struct tty_operations rocket_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 .open = rp_open,
2367 .close = rp_close,
2368 .write = rp_write,
2369 .put_char = rp_put_char,
2370 .write_room = rp_write_room,
2371 .chars_in_buffer = rp_chars_in_buffer,
2372 .flush_buffer = rp_flush_buffer,
2373 .ioctl = rp_ioctl,
2374 .throttle = rp_throttle,
2375 .unthrottle = rp_unthrottle,
2376 .set_termios = rp_set_termios,
2377 .stop = rp_stop,
2378 .start = rp_start,
2379 .hangup = rp_hangup,
2380 .break_ctl = rp_break,
2381 .send_xchar = rp_send_xchar,
2382 .wait_until_sent = rp_wait_until_sent,
2383 .tiocmget = rp_tiocmget,
2384 .tiocmset = rp_tiocmset,
2385};
2386
Alan Cox31f35932009-01-02 13:45:05 +00002387static const struct tty_port_operations rocket_port_ops = {
2388 .carrier_raised = carrier_raised,
Alan Cox5d951fb2009-01-02 13:45:19 +00002389 .raise_dtr_rts = raise_dtr_rts,
Alan Cox31f35932009-01-02 13:45:05 +00002390};
2391
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392/*
2393 * The module "startup" routine; it's run when the module is loaded.
2394 */
Bjorn Helgaasd269cdd2005-10-30 15:03:14 -08002395static int __init rp_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396{
Jiri Slaby4384a3f2007-10-18 03:06:28 -07002397 int ret = -ENOMEM, pci_boards_found, isa_boards_found, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398
2399 printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
2400 ROCKET_VERSION, ROCKET_DATE);
2401
2402 rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
2403 if (!rocket_driver)
Jiri Slaby4384a3f2007-10-18 03:06:28 -07002404 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
2406 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 * If board 1 is non-zero, there is at least one ISA configured. If controller is
2408 * zero, use the default controller IO address of board1 + 0x40.
2409 */
2410 if (board1) {
2411 if (controller == 0)
2412 controller = board1 + 0x40;
2413 } else {
2414 controller = 0; /* Used as a flag, meaning no ISA boards */
2415 }
2416
2417 /* If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
2418 if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
Jiri Slaby4384a3f2007-10-18 03:06:28 -07002419 printk(KERN_ERR "Unable to reserve IO region for first "
2420 "configured ISA RocketPort controller 0x%lx. "
2421 "Driver exiting\n", controller);
2422 ret = -EBUSY;
2423 goto err_tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 }
2425
2426 /* Store ISA variable retrieved from command line or .conf file. */
2427 rcktpt_io_addr[0] = board1;
2428 rcktpt_io_addr[1] = board2;
2429 rcktpt_io_addr[2] = board3;
2430 rcktpt_io_addr[3] = board4;
2431
2432 rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2433 rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0];
2434 rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2435 rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1];
2436 rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2437 rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2];
2438 rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
2439 rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3];
2440
2441 /*
2442 * Set up the tty driver structure and then register this
2443 * driver with the tty layer.
2444 */
2445
2446 rocket_driver->owner = THIS_MODULE;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07002447 rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 rocket_driver->name = "ttyR";
2449 rocket_driver->driver_name = "Comtrol RocketPort";
2450 rocket_driver->major = TTY_ROCKET_MAJOR;
2451 rocket_driver->minor_start = 0;
2452 rocket_driver->type = TTY_DRIVER_TYPE_SERIAL;
2453 rocket_driver->subtype = SERIAL_TYPE_NORMAL;
2454 rocket_driver->init_termios = tty_std_termios;
2455 rocket_driver->init_termios.c_cflag =
2456 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Alan Cox606d0992006-12-08 02:38:45 -08002457 rocket_driver->init_termios.c_ispeed = 9600;
2458 rocket_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459#ifdef ROCKET_SOFT_FLOW
Jiri Slabyac6aec22007-10-18 03:06:26 -07002460 rocket_driver->flags |= TTY_DRIVER_REAL_RAW;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461#endif
2462 tty_set_operations(rocket_driver, &rocket_ops);
2463
Jiri Slaby4384a3f2007-10-18 03:06:28 -07002464 ret = tty_register_driver(rocket_driver);
2465 if (ret < 0) {
2466 printk(KERN_ERR "Couldn't install tty RocketPort driver\n");
2467 goto err_tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 }
2469
2470#ifdef ROCKET_DEBUG_OPEN
2471 printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major);
2472#endif
2473
2474 /*
2475 * OK, let's probe each of the controllers looking for boards. Any boards found
2476 * will be initialized here.
2477 */
2478 isa_boards_found = 0;
2479 pci_boards_found = 0;
2480
2481 for (i = 0; i < NUM_BOARDS; i++) {
2482 if (init_ISA(i))
2483 isa_boards_found++;
2484 }
2485
2486#ifdef CONFIG_PCI
2487 if (isa_boards_found < NUM_BOARDS)
2488 pci_boards_found = init_PCI(isa_boards_found);
2489#endif
2490
2491 max_board = pci_boards_found + isa_boards_found;
2492
2493 if (max_board == 0) {
Jiri Slaby4384a3f2007-10-18 03:06:28 -07002494 printk(KERN_ERR "No rocketport ports found; unloading driver\n");
2495 ret = -ENXIO;
2496 goto err_ttyu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 }
2498
2499 return 0;
Jiri Slaby4384a3f2007-10-18 03:06:28 -07002500err_ttyu:
2501 tty_unregister_driver(rocket_driver);
2502err_tty:
2503 put_tty_driver(rocket_driver);
2504err:
2505 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506}
2507
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
2509static void rp_cleanup_module(void)
2510{
2511 int retval;
2512 int i;
2513
2514 del_timer_sync(&rocket_timer);
2515
2516 retval = tty_unregister_driver(rocket_driver);
2517 if (retval)
Jiri Slaby68562b72008-02-07 00:16:33 -08002518 printk(KERN_ERR "Error %d while trying to unregister "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 "rocketport driver\n", -retval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520
Jesper Juhl735d5662005-11-07 01:01:29 -08002521 for (i = 0; i < MAX_RP_PORTS; i++)
Jiri Slabyac6aec22007-10-18 03:06:26 -07002522 if (rp_table[i]) {
2523 tty_unregister_device(rocket_driver, i);
2524 kfree(rp_table[i]);
2525 }
2526
2527 put_tty_driver(rocket_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
2529 for (i = 0; i < NUM_BOARDS; i++) {
2530 if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
2531 continue;
2532 release_region(rcktpt_io_addr[i], 64);
2533 }
2534 if (controller)
2535 release_region(controller, 4);
2536}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538/***************************************************************************
2539Function: sInitController
2540Purpose: Initialization of controller global registers and controller
2541 structure.
2542Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
2543 IRQNum,Frequency,PeriodicOnly)
2544 CONTROLLER_T *CtlP; Ptr to controller structure
2545 int CtlNum; Controller number
2546 ByteIO_t MudbacIO; Mudbac base I/O address.
2547 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
2548 This list must be in the order the AIOPs will be found on the
2549 controller. Once an AIOP in the list is not found, it is
2550 assumed that there are no more AIOPs on the controller.
2551 int AiopIOListSize; Number of addresses in AiopIOList
2552 int IRQNum; Interrupt Request number. Can be any of the following:
2553 0: Disable global interrupts
2554 3: IRQ 3
2555 4: IRQ 4
2556 5: IRQ 5
2557 9: IRQ 9
2558 10: IRQ 10
2559 11: IRQ 11
2560 12: IRQ 12
2561 15: IRQ 15
2562 Byte_t Frequency: A flag identifying the frequency
2563 of the periodic interrupt, can be any one of the following:
2564 FREQ_DIS - periodic interrupt disabled
2565 FREQ_137HZ - 137 Hertz
2566 FREQ_69HZ - 69 Hertz
2567 FREQ_34HZ - 34 Hertz
2568 FREQ_17HZ - 17 Hertz
2569 FREQ_9HZ - 9 Hertz
2570 FREQ_4HZ - 4 Hertz
2571 If IRQNum is set to 0 the Frequency parameter is
2572 overidden, it is forced to a value of FREQ_DIS.
Adrian Bunkf15313b2005-06-25 14:59:05 -07002573 int PeriodicOnly: 1 if all interrupts except the periodic
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 interrupt are to be blocked.
Adrian Bunkf15313b2005-06-25 14:59:05 -07002575 0 is both the periodic interrupt and
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 other channel interrupts are allowed.
2577 If IRQNum is set to 0 the PeriodicOnly parameter is
Adrian Bunkf15313b2005-06-25 14:59:05 -07002578 overidden, it is forced to a value of 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
2580 initialization failed.
2581
2582Comments:
2583 If periodic interrupts are to be disabled but AIOP interrupts
Adrian Bunkf15313b2005-06-25 14:59:05 -07002584 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585
2586 If interrupts are to be completely disabled set IRQNum to 0.
2587
Adrian Bunkf15313b2005-06-25 14:59:05 -07002588 Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 invalid combination.
2590
2591 This function performs initialization of global interrupt modes,
2592 but it does not actually enable global interrupts. To enable
2593 and disable global interrupts use functions sEnGlobalInt() and
2594 sDisGlobalInt(). Enabling of global interrupts is normally not
2595 done until all other initializations are complete.
2596
2597 Even if interrupts are globally enabled, they must also be
2598 individually enabled for each channel that is to generate
2599 interrupts.
2600
2601Warnings: No range checking on any of the parameters is done.
2602
2603 No context switches are allowed while executing this function.
2604
2605 After this function all AIOPs on the controller are disabled,
2606 they can be enabled with sEnAiop().
2607*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002608static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
2609 ByteIO_t * AiopIOList, int AiopIOListSize,
2610 int IRQNum, Byte_t Frequency, int PeriodicOnly)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611{
2612 int i;
2613 ByteIO_t io;
2614 int done;
2615
2616 CtlP->AiopIntrBits = aiop_intr_bits;
2617 CtlP->AltChanRingIndicator = 0;
2618 CtlP->CtlNum = CtlNum;
2619 CtlP->CtlID = CTLID_0001; /* controller release 1 */
2620 CtlP->BusType = isISA;
2621 CtlP->MBaseIO = MudbacIO;
2622 CtlP->MReg1IO = MudbacIO + 1;
2623 CtlP->MReg2IO = MudbacIO + 2;
2624 CtlP->MReg3IO = MudbacIO + 3;
2625#if 1
2626 CtlP->MReg2 = 0; /* interrupt disable */
2627 CtlP->MReg3 = 0; /* no periodic interrupts */
2628#else
2629 if (sIRQMap[IRQNum] == 0) { /* interrupts globally disabled */
2630 CtlP->MReg2 = 0; /* interrupt disable */
2631 CtlP->MReg3 = 0; /* no periodic interrupts */
2632 } else {
2633 CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
2634 CtlP->MReg3 = Frequency; /* set frequency */
2635 if (PeriodicOnly) { /* periodic interrupt only */
2636 CtlP->MReg3 |= PERIODIC_ONLY;
2637 }
2638 }
2639#endif
2640 sOutB(CtlP->MReg2IO, CtlP->MReg2);
2641 sOutB(CtlP->MReg3IO, CtlP->MReg3);
2642 sControllerEOI(CtlP); /* clear EOI if warm init */
2643 /* Init AIOPs */
2644 CtlP->NumAiop = 0;
2645 for (i = done = 0; i < AiopIOListSize; i++) {
2646 io = AiopIOList[i];
2647 CtlP->AiopIO[i] = (WordIO_t) io;
2648 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2649 sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03)); /* AIOP index */
2650 sOutB(MudbacIO, (Byte_t) (io >> 6)); /* set up AIOP I/O in MUDBAC */
2651 if (done)
2652 continue;
2653 sEnAiop(CtlP, i); /* enable the AIOP */
2654 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
2655 if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
2656 done = 1; /* done looking for AIOPs */
2657 else {
2658 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
2659 sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
2660 sOutB(io + _INDX_DATA, sClockPrescale);
2661 CtlP->NumAiop++; /* bump count of AIOPs */
2662 }
2663 sDisAiop(CtlP, i); /* disable AIOP */
2664 }
2665
2666 if (CtlP->NumAiop == 0)
2667 return (-1);
2668 else
2669 return (CtlP->NumAiop);
2670}
2671
2672/***************************************************************************
2673Function: sPCIInitController
2674Purpose: Initialization of controller global registers and controller
2675 structure.
2676Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
2677 IRQNum,Frequency,PeriodicOnly)
2678 CONTROLLER_T *CtlP; Ptr to controller structure
2679 int CtlNum; Controller number
2680 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
2681 This list must be in the order the AIOPs will be found on the
2682 controller. Once an AIOP in the list is not found, it is
2683 assumed that there are no more AIOPs on the controller.
2684 int AiopIOListSize; Number of addresses in AiopIOList
2685 int IRQNum; Interrupt Request number. Can be any of the following:
2686 0: Disable global interrupts
2687 3: IRQ 3
2688 4: IRQ 4
2689 5: IRQ 5
2690 9: IRQ 9
2691 10: IRQ 10
2692 11: IRQ 11
2693 12: IRQ 12
2694 15: IRQ 15
2695 Byte_t Frequency: A flag identifying the frequency
2696 of the periodic interrupt, can be any one of the following:
2697 FREQ_DIS - periodic interrupt disabled
2698 FREQ_137HZ - 137 Hertz
2699 FREQ_69HZ - 69 Hertz
2700 FREQ_34HZ - 34 Hertz
2701 FREQ_17HZ - 17 Hertz
2702 FREQ_9HZ - 9 Hertz
2703 FREQ_4HZ - 4 Hertz
2704 If IRQNum is set to 0 the Frequency parameter is
2705 overidden, it is forced to a value of FREQ_DIS.
Adrian Bunkf15313b2005-06-25 14:59:05 -07002706 int PeriodicOnly: 1 if all interrupts except the periodic
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 interrupt are to be blocked.
Adrian Bunkf15313b2005-06-25 14:59:05 -07002708 0 is both the periodic interrupt and
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 other channel interrupts are allowed.
2710 If IRQNum is set to 0 the PeriodicOnly parameter is
Adrian Bunkf15313b2005-06-25 14:59:05 -07002711 overidden, it is forced to a value of 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
2713 initialization failed.
2714
2715Comments:
2716 If periodic interrupts are to be disabled but AIOP interrupts
Adrian Bunkf15313b2005-06-25 14:59:05 -07002717 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718
2719 If interrupts are to be completely disabled set IRQNum to 0.
2720
Adrian Bunkf15313b2005-06-25 14:59:05 -07002721 Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 invalid combination.
2723
2724 This function performs initialization of global interrupt modes,
2725 but it does not actually enable global interrupts. To enable
2726 and disable global interrupts use functions sEnGlobalInt() and
2727 sDisGlobalInt(). Enabling of global interrupts is normally not
2728 done until all other initializations are complete.
2729
2730 Even if interrupts are globally enabled, they must also be
2731 individually enabled for each channel that is to generate
2732 interrupts.
2733
2734Warnings: No range checking on any of the parameters is done.
2735
2736 No context switches are allowed while executing this function.
2737
2738 After this function all AIOPs on the controller are disabled,
2739 they can be enabled with sEnAiop().
2740*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002741static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
2742 ByteIO_t * AiopIOList, int AiopIOListSize,
2743 WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
2744 int PeriodicOnly, int altChanRingIndicator,
2745 int UPCIRingInd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746{
2747 int i;
2748 ByteIO_t io;
2749
2750 CtlP->AltChanRingIndicator = altChanRingIndicator;
2751 CtlP->UPCIRingInd = UPCIRingInd;
2752 CtlP->CtlNum = CtlNum;
2753 CtlP->CtlID = CTLID_0001; /* controller release 1 */
2754 CtlP->BusType = isPCI; /* controller release 1 */
2755
2756 if (ConfigIO) {
2757 CtlP->isUPCI = 1;
2758 CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
2759 CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
2760 CtlP->AiopIntrBits = upci_aiop_intr_bits;
2761 } else {
2762 CtlP->isUPCI = 0;
2763 CtlP->PCIIO =
2764 (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
2765 CtlP->AiopIntrBits = aiop_intr_bits;
2766 }
2767
2768 sPCIControllerEOI(CtlP); /* clear EOI if warm init */
2769 /* Init AIOPs */
2770 CtlP->NumAiop = 0;
2771 for (i = 0; i < AiopIOListSize; i++) {
2772 io = AiopIOList[i];
2773 CtlP->AiopIO[i] = (WordIO_t) io;
2774 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
2775
2776 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
2777 if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
2778 break; /* done looking for AIOPs */
2779
2780 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
2781 sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
2782 sOutB(io + _INDX_DATA, sClockPrescale);
2783 CtlP->NumAiop++; /* bump count of AIOPs */
2784 }
2785
2786 if (CtlP->NumAiop == 0)
2787 return (-1);
2788 else
2789 return (CtlP->NumAiop);
2790}
2791
2792/***************************************************************************
2793Function: sReadAiopID
2794Purpose: Read the AIOP idenfication number directly from an AIOP.
2795Call: sReadAiopID(io)
2796 ByteIO_t io: AIOP base I/O address
2797Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
2798 is replace by an identifying number.
2799 Flag AIOPID_NULL if no valid AIOP is found
2800Warnings: No context switches are allowed while executing this function.
2801
2802*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002803static int sReadAiopID(ByteIO_t io)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804{
2805 Byte_t AiopID; /* ID byte from AIOP */
2806
2807 sOutB(io + _CMD_REG, RESET_ALL); /* reset AIOP */
2808 sOutB(io + _CMD_REG, 0x0);
2809 AiopID = sInW(io + _CHN_STAT0) & 0x07;
2810 if (AiopID == 0x06)
2811 return (1);
2812 else /* AIOP does not exist */
2813 return (-1);
2814}
2815
2816/***************************************************************************
2817Function: sReadAiopNumChan
2818Purpose: Read the number of channels available in an AIOP directly from
2819 an AIOP.
2820Call: sReadAiopNumChan(io)
2821 WordIO_t io: AIOP base I/O address
2822Return: int: The number of channels available
2823Comments: The number of channels is determined by write/reads from identical
2824 offsets within the SRAM address spaces for channels 0 and 4.
2825 If the channel 4 space is mirrored to channel 0 it is a 4 channel
2826 AIOP, otherwise it is an 8 channel.
2827Warnings: No context switches are allowed while executing this function.
2828*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002829static int sReadAiopNumChan(WordIO_t io)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830{
2831 Word_t x;
2832 static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
2833
2834 /* write to chan 0 SRAM */
Al Viro457fb602008-03-19 16:27:48 +00002835 out32((DWordIO_t) io + _INDX_ADDR, R);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */
2837 x = sInW(io + _INDX_DATA);
2838 sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */
2839 if (x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
2840 return (8);
2841 else
2842 return (4);
2843}
2844
2845/***************************************************************************
2846Function: sInitChan
2847Purpose: Initialization of a channel and channel structure
2848Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
2849 CONTROLLER_T *CtlP; Ptr to controller structure
2850 CHANNEL_T *ChP; Ptr to channel structure
2851 int AiopNum; AIOP number within controller
2852 int ChanNum; Channel number within AIOP
Adrian Bunkf15313b2005-06-25 14:59:05 -07002853Return: int: 1 if initialization succeeded, 0 if it fails because channel
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 number exceeds number of channels available in AIOP.
2855Comments: This function must be called before a channel can be used.
2856Warnings: No range checking on any of the parameters is done.
2857
2858 No context switches are allowed while executing this function.
2859*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07002860static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
2861 int ChanNum)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862{
2863 int i;
2864 WordIO_t AiopIO;
2865 WordIO_t ChIOOff;
2866 Byte_t *ChR;
2867 Word_t ChOff;
2868 static Byte_t R[4];
2869 int brd9600;
2870
2871 if (ChanNum >= CtlP->AiopNumChan[AiopNum])
Adrian Bunkf15313b2005-06-25 14:59:05 -07002872 return 0; /* exceeds num chans in AIOP */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873
2874 /* Channel, AIOP, and controller identifiers */
2875 ChP->CtlP = CtlP;
2876 ChP->ChanID = CtlP->AiopID[AiopNum];
2877 ChP->AiopNum = AiopNum;
2878 ChP->ChanNum = ChanNum;
2879
2880 /* Global direct addresses */
2881 AiopIO = CtlP->AiopIO[AiopNum];
2882 ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG;
2883 ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN;
2884 ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK;
2885 ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR;
2886 ChP->IndexData = AiopIO + _INDX_DATA;
2887
2888 /* Channel direct addresses */
2889 ChIOOff = AiopIO + ChP->ChanNum * 2;
2890 ChP->TxRxData = ChIOOff + _TD0;
2891 ChP->ChanStat = ChIOOff + _CHN_STAT0;
2892 ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
2893 ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0;
2894
2895 /* Initialize the channel from the RData array */
2896 for (i = 0; i < RDATASIZE; i += 4) {
2897 R[0] = RData[i];
2898 R[1] = RData[i + 1] + 0x10 * ChanNum;
2899 R[2] = RData[i + 2];
2900 R[3] = RData[i + 3];
Al Viro457fb602008-03-19 16:27:48 +00002901 out32(ChP->IndexAddr, R);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 }
2903
2904 ChR = ChP->R;
2905 for (i = 0; i < RREGDATASIZE; i += 4) {
2906 ChR[i] = RRegData[i];
2907 ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum;
2908 ChR[i + 2] = RRegData[i + 2];
2909 ChR[i + 3] = RRegData[i + 3];
2910 }
2911
2912 /* Indexed registers */
2913 ChOff = (Word_t) ChanNum *0x1000;
2914
2915 if (sClockPrescale == 0x14)
2916 brd9600 = 47;
2917 else
2918 brd9600 = 23;
2919
2920 ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD);
2921 ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
2922 ChP->BaudDiv[2] = (Byte_t) brd9600;
2923 ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
Al Viro457fb602008-03-19 16:27:48 +00002924 out32(ChP->IndexAddr, ChP->BaudDiv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
2926 ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
2927 ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
2928 ChP->TxControl[2] = 0;
2929 ChP->TxControl[3] = 0;
Al Viro457fb602008-03-19 16:27:48 +00002930 out32(ChP->IndexAddr, ChP->TxControl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931
2932 ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
2933 ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
2934 ChP->RxControl[2] = 0;
2935 ChP->RxControl[3] = 0;
Al Viro457fb602008-03-19 16:27:48 +00002936 out32(ChP->IndexAddr, ChP->RxControl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937
2938 ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
2939 ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
2940 ChP->TxEnables[2] = 0;
2941 ChP->TxEnables[3] = 0;
Al Viro457fb602008-03-19 16:27:48 +00002942 out32(ChP->IndexAddr, ChP->TxEnables);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943
2944 ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
2945 ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
2946 ChP->TxCompare[2] = 0;
2947 ChP->TxCompare[3] = 0;
Al Viro457fb602008-03-19 16:27:48 +00002948 out32(ChP->IndexAddr, ChP->TxCompare);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949
2950 ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
2951 ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
2952 ChP->TxReplace1[2] = 0;
2953 ChP->TxReplace1[3] = 0;
Al Viro457fb602008-03-19 16:27:48 +00002954 out32(ChP->IndexAddr, ChP->TxReplace1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955
2956 ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
2957 ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
2958 ChP->TxReplace2[2] = 0;
2959 ChP->TxReplace2[3] = 0;
Al Viro457fb602008-03-19 16:27:48 +00002960 out32(ChP->IndexAddr, ChP->TxReplace2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961
2962 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
2963 ChP->TxFIFO = ChOff + _TX_FIFO;
2964
2965 sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
2966 sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Tx FIFO count */
2967 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
2968 sOutW(ChP->IndexData, 0);
2969 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
2970 ChP->RxFIFO = ChOff + _RX_FIFO;
2971
2972 sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
2973 sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Rx FIFO count */
2974 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
2975 sOutW(ChP->IndexData, 0);
2976 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
2977 sOutW(ChP->IndexData, 0);
2978 ChP->TxPrioCnt = ChOff + _TXP_CNT;
2979 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt);
2980 sOutB(ChP->IndexData, 0);
2981 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
2982 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr);
2983 sOutB(ChP->IndexData, 0);
2984 ChP->TxPrioBuf = ChOff + _TXP_BUF;
2985 sEnRxProcessor(ChP); /* start the Rx processor */
2986
Adrian Bunkf15313b2005-06-25 14:59:05 -07002987 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988}
2989
2990/***************************************************************************
2991Function: sStopRxProcessor
2992Purpose: Stop the receive processor from processing a channel.
2993Call: sStopRxProcessor(ChP)
2994 CHANNEL_T *ChP; Ptr to channel structure
2995
2996Comments: The receive processor can be started again with sStartRxProcessor().
2997 This function causes the receive processor to skip over the
2998 stopped channel. It does not stop it from processing other channels.
2999
3000Warnings: No context switches are allowed while executing this function.
3001
3002 Do not leave the receive processor stopped for more than one
3003 character time.
3004
3005 After calling this function a delay of 4 uS is required to ensure
3006 that the receive processor is no longer processing this channel.
3007*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003008static void sStopRxProcessor(CHANNEL_T * ChP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009{
3010 Byte_t R[4];
3011
3012 R[0] = ChP->R[0];
3013 R[1] = ChP->R[1];
3014 R[2] = 0x0a;
3015 R[3] = ChP->R[3];
Al Viro457fb602008-03-19 16:27:48 +00003016 out32(ChP->IndexAddr, R);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017}
3018
3019/***************************************************************************
3020Function: sFlushRxFIFO
3021Purpose: Flush the Rx FIFO
3022Call: sFlushRxFIFO(ChP)
3023 CHANNEL_T *ChP; Ptr to channel structure
3024Return: void
3025Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
3026 while it is being flushed the receive processor is stopped
3027 and the transmitter is disabled. After these operations a
3028 4 uS delay is done before clearing the pointers to allow
3029 the receive processor to stop. These items are handled inside
3030 this function.
3031Warnings: No context switches are allowed while executing this function.
3032*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003033static void sFlushRxFIFO(CHANNEL_T * ChP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034{
3035 int i;
3036 Byte_t Ch; /* channel number within AIOP */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003037 int RxFIFOEnabled; /* 1 if Rx FIFO enabled */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038
3039 if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
3040 return; /* don't need to flush */
3041
Adrian Bunkf15313b2005-06-25 14:59:05 -07003042 RxFIFOEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003044 RxFIFOEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 sDisRxFIFO(ChP); /* disable it */
3046 for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */
3047 sInB(ChP->IntChan); /* depends on bus i/o timing */
3048 }
3049 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
3050 Ch = (Byte_t) sGetChanNum(ChP);
3051 sOutB(ChP->Cmd, Ch | RESRXFCNT); /* apply reset Rx FIFO count */
3052 sOutB(ChP->Cmd, Ch); /* remove reset Rx FIFO count */
3053 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
3054 sOutW(ChP->IndexData, 0);
3055 sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
3056 sOutW(ChP->IndexData, 0);
3057 if (RxFIFOEnabled)
3058 sEnRxFIFO(ChP); /* enable Rx FIFO */
3059}
3060
3061/***************************************************************************
3062Function: sFlushTxFIFO
3063Purpose: Flush the Tx FIFO
3064Call: sFlushTxFIFO(ChP)
3065 CHANNEL_T *ChP; Ptr to channel structure
3066Return: void
3067Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
3068 while it is being flushed the receive processor is stopped
3069 and the transmitter is disabled. After these operations a
3070 4 uS delay is done before clearing the pointers to allow
3071 the receive processor to stop. These items are handled inside
3072 this function.
3073Warnings: No context switches are allowed while executing this function.
3074*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003075static void sFlushTxFIFO(CHANNEL_T * ChP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076{
3077 int i;
3078 Byte_t Ch; /* channel number within AIOP */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003079 int TxEnabled; /* 1 if transmitter enabled */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080
3081 if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
3082 return; /* don't need to flush */
3083
Adrian Bunkf15313b2005-06-25 14:59:05 -07003084 TxEnabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 if (ChP->TxControl[3] & TX_ENABLE) {
Adrian Bunkf15313b2005-06-25 14:59:05 -07003086 TxEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 sDisTransmit(ChP); /* disable transmitter */
3088 }
3089 sStopRxProcessor(ChP); /* stop Rx processor */
3090 for (i = 0; i < 4000 / 200; i++) /* delay 4 uS to allow proc to stop */
3091 sInB(ChP->IntChan); /* depends on bus i/o timing */
3092 Ch = (Byte_t) sGetChanNum(ChP);
3093 sOutB(ChP->Cmd, Ch | RESTXFCNT); /* apply reset Tx FIFO count */
3094 sOutB(ChP->Cmd, Ch); /* remove reset Tx FIFO count */
3095 sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
3096 sOutW(ChP->IndexData, 0);
3097 if (TxEnabled)
3098 sEnTransmit(ChP); /* enable transmitter */
3099 sStartRxProcessor(ChP); /* restart Rx processor */
3100}
3101
3102/***************************************************************************
3103Function: sWriteTxPrioByte
3104Purpose: Write a byte of priority transmit data to a channel
3105Call: sWriteTxPrioByte(ChP,Data)
3106 CHANNEL_T *ChP; Ptr to channel structure
3107 Byte_t Data; The transmit data byte
3108
3109Return: int: 1 if the bytes is successfully written, otherwise 0.
3110
3111Comments: The priority byte is transmitted before any data in the Tx FIFO.
3112
3113Warnings: No context switches are allowed while executing this function.
3114*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003115static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116{
3117 Byte_t DWBuf[4]; /* buffer for double word writes */
3118 Word_t *WordPtr; /* must be far because Win SS != DS */
3119 register DWordIO_t IndexAddr;
3120
3121 if (sGetTxCnt(ChP) > 1) { /* write it to Tx priority buffer */
3122 IndexAddr = ChP->IndexAddr;
3123 sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt); /* get priority buffer status */
3124 if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND) /* priority buffer busy */
3125 return (0); /* nothing sent */
3126
3127 WordPtr = (Word_t *) (&DWBuf[0]);
3128 *WordPtr = ChP->TxPrioBuf; /* data byte address */
3129
3130 DWBuf[2] = Data; /* data byte value */
Al Viro457fb602008-03-19 16:27:48 +00003131 out32(IndexAddr, DWBuf); /* write it out */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132
3133 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
3134
3135 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
3136 DWBuf[3] = 0; /* priority buffer pointer */
Al Viro457fb602008-03-19 16:27:48 +00003137 out32(IndexAddr, DWBuf); /* write it out */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 } else { /* write it to Tx FIFO */
3139
3140 sWriteTxByte(sGetTxRxDataIO(ChP), Data);
3141 }
3142 return (1); /* 1 byte sent */
3143}
3144
3145/***************************************************************************
3146Function: sEnInterrupts
3147Purpose: Enable one or more interrupts for a channel
3148Call: sEnInterrupts(ChP,Flags)
3149 CHANNEL_T *ChP; Ptr to channel structure
3150 Word_t Flags: Interrupt enable flags, can be any combination
3151 of the following flags:
3152 TXINT_EN: Interrupt on Tx FIFO empty
3153 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
3154 sSetRxTrigger())
3155 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
3156 MCINT_EN: Interrupt on modem input change
3157 CHANINT_EN: Allow channel interrupt signal to the AIOP's
3158 Interrupt Channel Register.
3159Return: void
3160Comments: If an interrupt enable flag is set in Flags, that interrupt will be
3161 enabled. If an interrupt enable flag is not set in Flags, that
3162 interrupt will not be changed. Interrupts can be disabled with
3163 function sDisInterrupts().
3164
3165 This function sets the appropriate bit for the channel in the AIOP's
3166 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
3167 this channel's bit to be set in the AIOP's Interrupt Channel Register.
3168
3169 Interrupts must also be globally enabled before channel interrupts
3170 will be passed on to the host. This is done with function
3171 sEnGlobalInt().
3172
3173 In some cases it may be desirable to disable interrupts globally but
3174 enable channel interrupts. This would allow the global interrupt
3175 status register to be used to determine which AIOPs need service.
3176*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003177static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178{
3179 Byte_t Mask; /* Interrupt Mask Register */
3180
3181 ChP->RxControl[2] |=
3182 ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
3183
Al Viro457fb602008-03-19 16:27:48 +00003184 out32(ChP->IndexAddr, ChP->RxControl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185
3186 ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
3187
Al Viro457fb602008-03-19 16:27:48 +00003188 out32(ChP->IndexAddr, ChP->TxControl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189
3190 if (Flags & CHANINT_EN) {
3191 Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
3192 sOutB(ChP->IntMask, Mask);
3193 }
3194}
3195
3196/***************************************************************************
3197Function: sDisInterrupts
3198Purpose: Disable one or more interrupts for a channel
3199Call: sDisInterrupts(ChP,Flags)
3200 CHANNEL_T *ChP; Ptr to channel structure
3201 Word_t Flags: Interrupt flags, can be any combination
3202 of the following flags:
3203 TXINT_EN: Interrupt on Tx FIFO empty
3204 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
3205 sSetRxTrigger())
3206 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
3207 MCINT_EN: Interrupt on modem input change
3208 CHANINT_EN: Disable channel interrupt signal to the
3209 AIOP's Interrupt Channel Register.
3210Return: void
3211Comments: If an interrupt flag is set in Flags, that interrupt will be
3212 disabled. If an interrupt flag is not set in Flags, that
3213 interrupt will not be changed. Interrupts can be enabled with
3214 function sEnInterrupts().
3215
3216 This function clears the appropriate bit for the channel in the AIOP's
3217 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
3218 this channel's bit from being set in the AIOP's Interrupt Channel
3219 Register.
3220*/
Adrian Bunkf15313b2005-06-25 14:59:05 -07003221static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222{
3223 Byte_t Mask; /* Interrupt Mask Register */
3224
3225 ChP->RxControl[2] &=
3226 ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
Al Viro457fb602008-03-19 16:27:48 +00003227 out32(ChP->IndexAddr, ChP->RxControl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
Al Viro457fb602008-03-19 16:27:48 +00003229 out32(ChP->IndexAddr, ChP->TxControl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
3231 if (Flags & CHANINT_EN) {
3232 Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
3233 sOutB(ChP->IntMask, Mask);
3234 }
3235}
3236
Adrian Bunkf15313b2005-06-25 14:59:05 -07003237static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238{
3239 sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
3240}
3241
3242/*
3243 * Not an official SSCI function, but how to reset RocketModems.
3244 * ISA bus version
3245 */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003246static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247{
3248 ByteIO_t addr;
3249 Byte_t val;
3250
3251 addr = CtlP->AiopIO[0] + 0x400;
3252 val = sInB(CtlP->MReg3IO);
3253 /* if AIOP[1] is not enabled, enable it */
3254 if ((val & 2) == 0) {
3255 val = sInB(CtlP->MReg2IO);
3256 sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03));
3257 sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6));
3258 }
3259
3260 sEnAiop(CtlP, 1);
3261 if (!on)
3262 addr += 8;
3263 sOutB(addr + chan, 0); /* apply or remove reset */
3264 sDisAiop(CtlP, 1);
3265}
3266
3267/*
3268 * Not an official SSCI function, but how to reset RocketModems.
3269 * PCI bus version
3270 */
Adrian Bunkf15313b2005-06-25 14:59:05 -07003271static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272{
3273 ByteIO_t addr;
3274
3275 addr = CtlP->AiopIO[0] + 0x40; /* 2nd AIOP */
3276 if (!on)
3277 addr += 8;
3278 sOutB(addr + chan, 0); /* apply or remove reset */
3279}
3280
3281/* Resets the speaker controller on RocketModem II and III devices */
3282static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
3283{
3284 ByteIO_t addr;
3285
3286 /* RocketModem II speaker control is at the 8th port location of offset 0x40 */
3287 if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
3288 addr = CtlP->AiopIO[0] + 0x4F;
3289 sOutB(addr, 0);
3290 }
3291
3292 /* RocketModem III speaker control is at the 1st port location of offset 0x80 */
3293 if ((model == MODEL_UPCI_RM3_8PORT)
3294 || (model == MODEL_UPCI_RM3_4PORT)) {
3295 addr = CtlP->AiopIO[0] + 0x88;
3296 sOutB(addr, 0);
3297 }
3298}
3299
3300/* Returns the line number given the controller (board), aiop and channel number */
3301static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
3302{
3303 return lineNumbers[(ctrl << 5) | (aiop << 3) | ch];
3304}
3305
3306/*
3307 * Stores the line number associated with a given controller (board), aiop
3308 * and channel number.
3309 * Returns: The line number assigned
3310 */
3311static unsigned char SetLineNumber(int ctrl, int aiop, int ch)
3312{
3313 lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++;
3314 return (nextLineNumber - 1);
3315}