1 |
1275 |
phoenix |
/*
|
2 |
|
|
* linux/drivers/char/serial.c
|
3 |
|
|
*
|
4 |
|
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
5 |
|
|
* Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997,
|
6 |
|
|
* 1998, 1999 Theodore Ts'o
|
7 |
|
|
*
|
8 |
|
|
* Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now
|
9 |
|
|
* much more extensible to support other serial cards based on the
|
10 |
|
|
* 16450/16550A UART's. Added support for the AST FourPort and the
|
11 |
|
|
* Accent Async board.
|
12 |
|
|
*
|
13 |
|
|
* set_serial_info fixed to set the flags, custom divisor, and uart
|
14 |
|
|
* type fields. Fix suggested by Michael K. Johnson 12/12/92.
|
15 |
|
|
*
|
16 |
|
|
* 11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk>
|
17 |
|
|
*
|
18 |
|
|
* 03/96: Modularised by Angelo Haritsis <ah@doc.ic.ac.uk>
|
19 |
|
|
*
|
20 |
|
|
* rs_set_termios fixed to look also for changes of the input
|
21 |
|
|
* flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK.
|
22 |
|
|
* Bernd Anhäupl 05/17/96.
|
23 |
|
|
*
|
24 |
|
|
* 1/97: Extended dumb serial ports are a config option now.
|
25 |
|
|
* Saves 4k. Michael A. Griffith <grif@acm.org>
|
26 |
|
|
*
|
27 |
|
|
* 8/97: Fix bug in rs_set_termios with RTS
|
28 |
|
|
* Stanislav V. Voronyi <stas@uanet.kharkov.ua>
|
29 |
|
|
*
|
30 |
|
|
* 3/98: Change the IRQ detection, use of probe_irq_o*(),
|
31 |
|
|
* suppress TIOCSERGWILD and TIOCSERSWILD
|
32 |
|
|
* Etienne Lorrain <etienne.lorrain@ibm.net>
|
33 |
|
|
*
|
34 |
|
|
* 4/98: Added changes to support the ARM architecture proposed by
|
35 |
|
|
* Russell King
|
36 |
|
|
*
|
37 |
|
|
* 5/99: Updated to include support for the XR16C850 and ST16C654
|
38 |
|
|
* uarts. Stuart MacDonald <stuartm@connecttech.com>
|
39 |
|
|
*
|
40 |
|
|
* 8/99: Generalized PCI support added. Theodore Ts'o
|
41 |
|
|
*
|
42 |
|
|
* 3/00: Rid circular buffer of redundant xmit_cnt. Fix a
|
43 |
|
|
* few races on freeing buffers too.
|
44 |
|
|
* Alan Modra <alan@linuxcare.com>
|
45 |
|
|
*
|
46 |
|
|
* 5/00: Support for the RSA-DV II/S card added.
|
47 |
|
|
* Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
|
48 |
|
|
*
|
49 |
|
|
* 6/00: Remove old-style timer, use timer_list
|
50 |
|
|
* Andrew Morton <andrewm@uow.edu.au>
|
51 |
|
|
*
|
52 |
|
|
* 7/00: Support Timedia/Sunix/Exsys PCI cards
|
53 |
|
|
*
|
54 |
|
|
* 7/00: fix some returns on failure not using MOD_DEC_USE_COUNT.
|
55 |
|
|
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
56 |
|
|
*
|
57 |
|
|
* 10/00: add in optional software flow control for serial console.
|
58 |
|
|
* Kanoj Sarcar <kanoj@sgi.com> (Modified by Theodore Ts'o)
|
59 |
|
|
*
|
60 |
|
|
* 02/02: Fix for AMD Elan bug in transmit irq routine, by
|
61 |
|
|
* Christer Weinigel <wingel@hog.ctrl-c.liu.se>,
|
62 |
|
|
* Robert Schwebel <robert@schwebel.de>,
|
63 |
|
|
* Juergen Beisert <jbeisert@eurodsn.de>,
|
64 |
|
|
* Theodore Ts'o <tytso@mit.edu>
|
65 |
|
|
*/
|
66 |
|
|
|
67 |
|
|
static char *serial_version = "5.05c";
|
68 |
|
|
static char *serial_revdate = "2001-07-08";
|
69 |
|
|
|
70 |
|
|
/*
|
71 |
|
|
* Serial driver configuration section. Here are the various options:
|
72 |
|
|
*
|
73 |
|
|
* CONFIG_HUB6
|
74 |
|
|
* Enables support for the venerable Bell Technologies
|
75 |
|
|
* HUB6 card.
|
76 |
|
|
*
|
77 |
|
|
* CONFIG_SERIAL_MANY_PORTS
|
78 |
|
|
* Enables support for ports beyond the standard, stupid
|
79 |
|
|
* COM 1/2/3/4.
|
80 |
|
|
*
|
81 |
|
|
* CONFIG_SERIAL_MULTIPORT
|
82 |
|
|
* Enables support for special multiport board support.
|
83 |
|
|
*
|
84 |
|
|
* CONFIG_SERIAL_SHARE_IRQ
|
85 |
|
|
* Enables support for multiple serial ports on one IRQ
|
86 |
|
|
*
|
87 |
|
|
* CONFIG_SERIAL_DETECT_IRQ
|
88 |
|
|
* Enable the autodetection of IRQ on standart ports
|
89 |
|
|
*
|
90 |
|
|
* SERIAL_PARANOIA_CHECK
|
91 |
|
|
* Check the magic number for the async_structure where
|
92 |
|
|
* ever possible.
|
93 |
|
|
*
|
94 |
|
|
* CONFIG_SERIAL_ACPI
|
95 |
|
|
* Enable support for serial console port and serial
|
96 |
|
|
* debug port as defined by the SPCR and DBGP tables in
|
97 |
|
|
* ACPI 2.0.
|
98 |
|
|
*/
|
99 |
|
|
|
100 |
|
|
#include <linux/config.h>
|
101 |
|
|
#include <linux/version.h>
|
102 |
|
|
|
103 |
|
|
#undef SERIAL_PARANOIA_CHECK
|
104 |
|
|
#define CONFIG_SERIAL_NOPAUSE_IO
|
105 |
|
|
#define SERIAL_DO_RESTART
|
106 |
|
|
|
107 |
|
|
#if 0
|
108 |
|
|
/* These defines are normally controlled by the autoconf.h */
|
109 |
|
|
#define CONFIG_SERIAL_MANY_PORTS
|
110 |
|
|
#define CONFIG_SERIAL_SHARE_IRQ
|
111 |
|
|
#define CONFIG_SERIAL_DETECT_IRQ
|
112 |
|
|
#define CONFIG_SERIAL_MULTIPORT
|
113 |
|
|
#define CONFIG_HUB6
|
114 |
|
|
#endif
|
115 |
|
|
|
116 |
|
|
#ifdef CONFIG_PCI
|
117 |
|
|
#define ENABLE_SERIAL_PCI
|
118 |
|
|
#ifndef CONFIG_SERIAL_SHARE_IRQ
|
119 |
|
|
#define CONFIG_SERIAL_SHARE_IRQ
|
120 |
|
|
#endif
|
121 |
|
|
#ifndef CONFIG_SERIAL_MANY_PORTS
|
122 |
|
|
#define CONFIG_SERIAL_MANY_PORTS
|
123 |
|
|
#endif
|
124 |
|
|
#endif
|
125 |
|
|
|
126 |
|
|
#ifdef CONFIG_SERIAL_ACPI
|
127 |
|
|
#define ENABLE_SERIAL_ACPI
|
128 |
|
|
#endif
|
129 |
|
|
|
130 |
|
|
#if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
|
131 |
|
|
#ifndef ENABLE_SERIAL_PNP
|
132 |
|
|
#define ENABLE_SERIAL_PNP
|
133 |
|
|
#endif
|
134 |
|
|
#endif
|
135 |
|
|
|
136 |
|
|
/* Set of debugging defines */
|
137 |
|
|
|
138 |
|
|
#undef SERIAL_DEBUG_INTR
|
139 |
|
|
#undef SERIAL_DEBUG_OPEN
|
140 |
|
|
#undef SERIAL_DEBUG_FLOW
|
141 |
|
|
#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
|
142 |
|
|
#undef SERIAL_DEBUG_PCI
|
143 |
|
|
#undef SERIAL_DEBUG_AUTOCONF
|
144 |
|
|
|
145 |
|
|
/* Sanity checks */
|
146 |
|
|
|
147 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
148 |
|
|
#ifndef CONFIG_SERIAL_SHARE_IRQ
|
149 |
|
|
#define CONFIG_SERIAL_SHARE_IRQ
|
150 |
|
|
#endif
|
151 |
|
|
#endif
|
152 |
|
|
|
153 |
|
|
#ifdef CONFIG_HUB6
|
154 |
|
|
#ifndef CONFIG_SERIAL_MANY_PORTS
|
155 |
|
|
#define CONFIG_SERIAL_MANY_PORTS
|
156 |
|
|
#endif
|
157 |
|
|
#ifndef CONFIG_SERIAL_SHARE_IRQ
|
158 |
|
|
#define CONFIG_SERIAL_SHARE_IRQ
|
159 |
|
|
#endif
|
160 |
|
|
#endif
|
161 |
|
|
|
162 |
|
|
#ifdef MODULE
|
163 |
|
|
#undef CONFIG_SERIAL_CONSOLE
|
164 |
|
|
#endif
|
165 |
|
|
|
166 |
|
|
#define CONFIG_SERIAL_RSA
|
167 |
|
|
|
168 |
|
|
#define RS_STROBE_TIME (10*HZ)
|
169 |
|
|
#define RS_ISR_PASS_LIMIT 256
|
170 |
|
|
|
171 |
|
|
#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
|
172 |
|
|
#define SERIAL_INLINE
|
173 |
|
|
#endif
|
174 |
|
|
|
175 |
|
|
/*
|
176 |
|
|
* End of serial driver configuration section.
|
177 |
|
|
*/
|
178 |
|
|
|
179 |
|
|
#include <linux/module.h>
|
180 |
|
|
|
181 |
|
|
#include <linux/types.h>
|
182 |
|
|
#ifdef LOCAL_HEADERS
|
183 |
|
|
#include "serial_local.h"
|
184 |
|
|
#else
|
185 |
|
|
#include <linux/serial.h>
|
186 |
|
|
#include <linux/serialP.h>
|
187 |
|
|
#include <linux/serial_reg.h>
|
188 |
|
|
#include <asm/serial.h>
|
189 |
|
|
#define LOCAL_VERSTRING ""
|
190 |
|
|
#endif
|
191 |
|
|
|
192 |
|
|
#include <linux/errno.h>
|
193 |
|
|
#include <linux/signal.h>
|
194 |
|
|
#include <linux/sched.h>
|
195 |
|
|
#include <linux/timer.h>
|
196 |
|
|
#include <linux/interrupt.h>
|
197 |
|
|
#include <linux/tty.h>
|
198 |
|
|
#include <linux/tty_flip.h>
|
199 |
|
|
#include <linux/major.h>
|
200 |
|
|
#include <linux/string.h>
|
201 |
|
|
#include <linux/fcntl.h>
|
202 |
|
|
#include <linux/ptrace.h>
|
203 |
|
|
#include <linux/ioport.h>
|
204 |
|
|
#include <linux/mm.h>
|
205 |
|
|
#include <linux/slab.h>
|
206 |
|
|
#if (LINUX_VERSION_CODE >= 131343)
|
207 |
|
|
#include <linux/init.h>
|
208 |
|
|
#endif
|
209 |
|
|
#if (LINUX_VERSION_CODE >= 131336)
|
210 |
|
|
#include <asm/uaccess.h>
|
211 |
|
|
#endif
|
212 |
|
|
#include <linux/delay.h>
|
213 |
|
|
#ifdef CONFIG_SERIAL_CONSOLE
|
214 |
|
|
#include <linux/console.h>
|
215 |
|
|
#endif
|
216 |
|
|
#ifdef ENABLE_SERIAL_PCI
|
217 |
|
|
#include <linux/pci.h>
|
218 |
|
|
#endif
|
219 |
|
|
#ifdef ENABLE_SERIAL_PNP
|
220 |
|
|
#include <linux/isapnp.h>
|
221 |
|
|
#endif
|
222 |
|
|
#ifdef CONFIG_MAGIC_SYSRQ
|
223 |
|
|
#include <linux/sysrq.h>
|
224 |
|
|
#endif
|
225 |
|
|
|
226 |
|
|
/*
|
227 |
|
|
* All of the compatibilty code so we can compile serial.c against
|
228 |
|
|
* older kernels is hidden in serial_compat.h
|
229 |
|
|
*/
|
230 |
|
|
#if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */
|
231 |
|
|
#include "serial_compat.h"
|
232 |
|
|
#endif
|
233 |
|
|
|
234 |
|
|
#include <asm/system.h>
|
235 |
|
|
#include <asm/io.h>
|
236 |
|
|
#include <asm/irq.h>
|
237 |
|
|
#include <asm/bitops.h>
|
238 |
|
|
|
239 |
|
|
#if defined(CONFIG_MAC_SERIAL)
|
240 |
|
|
#define SERIAL_DEV_OFFSET ((_machine == _MACH_prep || _machine == _MACH_chrp) ? 0 : 2)
|
241 |
|
|
#else
|
242 |
|
|
#define SERIAL_DEV_OFFSET 0
|
243 |
|
|
#endif
|
244 |
|
|
|
245 |
|
|
#ifdef SERIAL_INLINE
|
246 |
|
|
#define _INLINE_ inline
|
247 |
|
|
#else
|
248 |
|
|
#define _INLINE_
|
249 |
|
|
#endif
|
250 |
|
|
|
251 |
|
|
static char *serial_name = "Serial driver";
|
252 |
|
|
|
253 |
|
|
static DECLARE_TASK_QUEUE(tq_serial);
|
254 |
|
|
|
255 |
|
|
static struct tty_driver serial_driver, callout_driver;
|
256 |
|
|
static int serial_refcount;
|
257 |
|
|
|
258 |
|
|
static struct timer_list serial_timer;
|
259 |
|
|
|
260 |
|
|
/* serial subtype definitions */
|
261 |
|
|
#ifndef SERIAL_TYPE_NORMAL
|
262 |
|
|
#define SERIAL_TYPE_NORMAL 1
|
263 |
|
|
#define SERIAL_TYPE_CALLOUT 2
|
264 |
|
|
#endif
|
265 |
|
|
|
266 |
|
|
/* number of characters left in xmit buffer before we ask for more */
|
267 |
|
|
#define WAKEUP_CHARS 256
|
268 |
|
|
|
269 |
|
|
/*
|
270 |
|
|
* IRQ_timeout - How long the timeout should be for each IRQ
|
271 |
|
|
* should be after the IRQ has been active.
|
272 |
|
|
*/
|
273 |
|
|
|
274 |
|
|
static struct async_struct *IRQ_ports[NR_IRQS];
|
275 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
276 |
|
|
static struct rs_multiport_struct rs_multiport[NR_IRQS];
|
277 |
|
|
#endif
|
278 |
|
|
static int IRQ_timeout[NR_IRQS];
|
279 |
|
|
#ifdef CONFIG_SERIAL_CONSOLE
|
280 |
|
|
static struct console sercons;
|
281 |
|
|
static int lsr_break_flag;
|
282 |
|
|
#endif
|
283 |
|
|
#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
284 |
|
|
static unsigned long break_pressed; /* break, really ... */
|
285 |
|
|
#endif
|
286 |
|
|
|
287 |
|
|
static unsigned detect_uart_irq (struct serial_state * state);
|
288 |
|
|
static void autoconfig(struct serial_state * state);
|
289 |
|
|
static void change_speed(struct async_struct *info, struct termios *old);
|
290 |
|
|
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
|
291 |
|
|
|
292 |
|
|
/*
|
293 |
|
|
* Here we define the default xmit fifo size used for each type of
|
294 |
|
|
* UART
|
295 |
|
|
*/
|
296 |
|
|
static struct serial_uart_config uart_config[] = {
|
297 |
|
|
{ "unknown", 1, 0 },
|
298 |
|
|
{ "8250", 1, 0 },
|
299 |
|
|
{ "16450", 1, 0 },
|
300 |
|
|
{ "16550", 1, 0 },
|
301 |
|
|
{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
|
302 |
|
|
{ "cirrus", 1, 0 }, /* usurped by cyclades.c */
|
303 |
|
|
{ "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
|
304 |
|
|
{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |
|
305 |
|
|
UART_STARTECH },
|
306 |
|
|
{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
|
307 |
|
|
{ "Startech", 1, 0}, /* usurped by cyclades.c */
|
308 |
|
|
{ "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO},
|
309 |
|
|
{ "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO |
|
310 |
|
|
UART_STARTECH },
|
311 |
|
|
{ "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO |
|
312 |
|
|
UART_STARTECH },
|
313 |
|
|
{ "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO },
|
314 |
|
|
{ 0, 0}
|
315 |
|
|
};
|
316 |
|
|
|
317 |
|
|
#if defined(CONFIG_SERIAL_RSA) && defined(MODULE)
|
318 |
|
|
|
319 |
|
|
#define PORT_RSA_MAX 4
|
320 |
|
|
static int probe_rsa[PORT_RSA_MAX];
|
321 |
|
|
static int force_rsa[PORT_RSA_MAX];
|
322 |
|
|
|
323 |
|
|
MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
|
324 |
|
|
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
|
325 |
|
|
MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
|
326 |
|
|
MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");
|
327 |
|
|
#endif /* CONFIG_SERIAL_RSA */
|
328 |
|
|
|
329 |
|
|
struct serial_state rs_table[RS_TABLE_SIZE] = {
|
330 |
|
|
SERIAL_PORT_DFNS /* Defined in serial.h */
|
331 |
|
|
};
|
332 |
|
|
|
333 |
|
|
#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
|
334 |
|
|
int serial_nr_ports = NR_PORTS;
|
335 |
|
|
|
336 |
|
|
#if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP))
|
337 |
|
|
#define NR_PCI_BOARDS 8
|
338 |
|
|
|
339 |
|
|
static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS];
|
340 |
|
|
|
341 |
|
|
#ifndef IS_PCI_REGION_IOPORT
|
342 |
|
|
#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \
|
343 |
|
|
IORESOURCE_IO)
|
344 |
|
|
#endif
|
345 |
|
|
#ifndef IS_PCI_REGION_IOMEM
|
346 |
|
|
#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \
|
347 |
|
|
IORESOURCE_MEM)
|
348 |
|
|
#endif
|
349 |
|
|
#ifndef PCI_IRQ_RESOURCE
|
350 |
|
|
#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)
|
351 |
|
|
#endif
|
352 |
|
|
#ifndef pci_get_subvendor
|
353 |
|
|
#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)
|
354 |
|
|
#define pci_get_subdevice(dev) ((dev)->subsystem_device)
|
355 |
|
|
#endif
|
356 |
|
|
#endif /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */
|
357 |
|
|
|
358 |
|
|
#ifndef PREPARE_FUNC
|
359 |
|
|
#define PREPARE_FUNC(dev) (dev->prepare)
|
360 |
|
|
#define ACTIVATE_FUNC(dev) (dev->activate)
|
361 |
|
|
#define DEACTIVATE_FUNC(dev) (dev->deactivate)
|
362 |
|
|
#endif
|
363 |
|
|
|
364 |
|
|
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
|
365 |
|
|
|
366 |
|
|
static struct tty_struct *serial_table[NR_PORTS];
|
367 |
|
|
static struct termios *serial_termios[NR_PORTS];
|
368 |
|
|
static struct termios *serial_termios_locked[NR_PORTS];
|
369 |
|
|
|
370 |
|
|
|
371 |
|
|
#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
|
372 |
|
|
#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
|
373 |
|
|
kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s)
|
374 |
|
|
#else
|
375 |
|
|
#define DBG_CNT(s)
|
376 |
|
|
#endif
|
377 |
|
|
|
378 |
|
|
/*
|
379 |
|
|
* tmp_buf is used as a temporary buffer by serial_write. We need to
|
380 |
|
|
* lock it in case the copy_from_user blocks while swapping in a page,
|
381 |
|
|
* and some other program tries to do a serial write at the same time.
|
382 |
|
|
* Since the lock will only come under contention when the system is
|
383 |
|
|
* swapping and available memory is low, it makes sense to share one
|
384 |
|
|
* buffer across all the serial ports, since it significantly saves
|
385 |
|
|
* memory if large numbers of serial ports are open.
|
386 |
|
|
*/
|
387 |
|
|
static unsigned char *tmp_buf;
|
388 |
|
|
#ifdef DECLARE_MUTEX
|
389 |
|
|
static DECLARE_MUTEX(tmp_buf_sem);
|
390 |
|
|
#else
|
391 |
|
|
static struct semaphore tmp_buf_sem = MUTEX;
|
392 |
|
|
#endif
|
393 |
|
|
|
394 |
|
|
|
395 |
|
|
static inline int serial_paranoia_check(struct async_struct *info,
|
396 |
|
|
kdev_t device, const char *routine)
|
397 |
|
|
{
|
398 |
|
|
#ifdef SERIAL_PARANOIA_CHECK
|
399 |
|
|
static const char *badmagic =
|
400 |
|
|
"Warning: bad magic number for serial struct (%s) in %s\n";
|
401 |
|
|
static const char *badinfo =
|
402 |
|
|
"Warning: null async_struct for (%s) in %s\n";
|
403 |
|
|
|
404 |
|
|
if (!info) {
|
405 |
|
|
printk(badinfo, kdevname(device), routine);
|
406 |
|
|
return 1;
|
407 |
|
|
}
|
408 |
|
|
if (info->magic != SERIAL_MAGIC) {
|
409 |
|
|
printk(badmagic, kdevname(device), routine);
|
410 |
|
|
return 1;
|
411 |
|
|
}
|
412 |
|
|
#endif
|
413 |
|
|
return 0;
|
414 |
|
|
}
|
415 |
|
|
|
416 |
|
|
static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset)
|
417 |
|
|
{
|
418 |
|
|
switch (info->io_type) {
|
419 |
|
|
#ifdef CONFIG_HUB6
|
420 |
|
|
case SERIAL_IO_HUB6:
|
421 |
|
|
outb(info->hub6 - 1 + offset, info->port);
|
422 |
|
|
return inb(info->port+1);
|
423 |
|
|
#endif
|
424 |
|
|
case SERIAL_IO_MEM:
|
425 |
|
|
return readb((unsigned long) info->iomem_base +
|
426 |
|
|
(offset<<info->iomem_reg_shift));
|
427 |
|
|
default:
|
428 |
|
|
return inb(info->port + offset);
|
429 |
|
|
}
|
430 |
|
|
}
|
431 |
|
|
|
432 |
|
|
static _INLINE_ void serial_out(struct async_struct *info, int offset,
|
433 |
|
|
int value)
|
434 |
|
|
{
|
435 |
|
|
switch (info->io_type) {
|
436 |
|
|
#ifdef CONFIG_HUB6
|
437 |
|
|
case SERIAL_IO_HUB6:
|
438 |
|
|
outb(info->hub6 - 1 + offset, info->port);
|
439 |
|
|
outb(value, info->port+1);
|
440 |
|
|
break;
|
441 |
|
|
#endif
|
442 |
|
|
case SERIAL_IO_MEM:
|
443 |
|
|
writeb(value, (unsigned long) info->iomem_base +
|
444 |
|
|
(offset<<info->iomem_reg_shift));
|
445 |
|
|
break;
|
446 |
|
|
default:
|
447 |
|
|
outb(value, info->port+offset);
|
448 |
|
|
}
|
449 |
|
|
}
|
450 |
|
|
|
451 |
|
|
/*
|
452 |
|
|
* We used to support using pause I/O for certain machines. We
|
453 |
|
|
* haven't supported this for a while, but just in case it's badly
|
454 |
|
|
* needed for certain old 386 machines, I've left these #define's
|
455 |
|
|
* in....
|
456 |
|
|
*/
|
457 |
|
|
#define serial_inp(info, offset) serial_in(info, offset)
|
458 |
|
|
#define serial_outp(info, offset, value) serial_out(info, offset, value)
|
459 |
|
|
|
460 |
|
|
|
461 |
|
|
/*
|
462 |
|
|
* For the 16C950
|
463 |
|
|
*/
|
464 |
|
|
void serial_icr_write(struct async_struct *info, int offset, int value)
|
465 |
|
|
{
|
466 |
|
|
serial_out(info, UART_SCR, offset);
|
467 |
|
|
serial_out(info, UART_ICR, value);
|
468 |
|
|
}
|
469 |
|
|
|
470 |
|
|
unsigned int serial_icr_read(struct async_struct *info, int offset)
|
471 |
|
|
{
|
472 |
|
|
int value;
|
473 |
|
|
|
474 |
|
|
serial_icr_write(info, UART_ACR, info->ACR | UART_ACR_ICRRD);
|
475 |
|
|
serial_out(info, UART_SCR, offset);
|
476 |
|
|
value = serial_in(info, UART_ICR);
|
477 |
|
|
serial_icr_write(info, UART_ACR, info->ACR);
|
478 |
|
|
return value;
|
479 |
|
|
}
|
480 |
|
|
|
481 |
|
|
/*
|
482 |
|
|
* ------------------------------------------------------------
|
483 |
|
|
* rs_stop() and rs_start()
|
484 |
|
|
*
|
485 |
|
|
* This routines are called before setting or resetting tty->stopped.
|
486 |
|
|
* They enable or disable transmitter interrupts, as necessary.
|
487 |
|
|
* ------------------------------------------------------------
|
488 |
|
|
*/
|
489 |
|
|
static void rs_stop(struct tty_struct *tty)
|
490 |
|
|
{
|
491 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
492 |
|
|
unsigned long flags;
|
493 |
|
|
|
494 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_stop"))
|
495 |
|
|
return;
|
496 |
|
|
|
497 |
|
|
save_flags(flags); cli();
|
498 |
|
|
if (info->IER & UART_IER_THRI) {
|
499 |
|
|
info->IER &= ~UART_IER_THRI;
|
500 |
|
|
serial_out(info, UART_IER, info->IER);
|
501 |
|
|
}
|
502 |
|
|
if (info->state->type == PORT_16C950) {
|
503 |
|
|
info->ACR |= UART_ACR_TXDIS;
|
504 |
|
|
serial_icr_write(info, UART_ACR, info->ACR);
|
505 |
|
|
}
|
506 |
|
|
restore_flags(flags);
|
507 |
|
|
}
|
508 |
|
|
|
509 |
|
|
static void rs_start(struct tty_struct *tty)
|
510 |
|
|
{
|
511 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
512 |
|
|
unsigned long flags;
|
513 |
|
|
|
514 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_start"))
|
515 |
|
|
return;
|
516 |
|
|
|
517 |
|
|
save_flags(flags); cli();
|
518 |
|
|
if (info->xmit.head != info->xmit.tail
|
519 |
|
|
&& info->xmit.buf
|
520 |
|
|
&& !(info->IER & UART_IER_THRI)) {
|
521 |
|
|
info->IER |= UART_IER_THRI;
|
522 |
|
|
serial_out(info, UART_IER, info->IER);
|
523 |
|
|
}
|
524 |
|
|
if (info->state->type == PORT_16C950) {
|
525 |
|
|
info->ACR &= ~UART_ACR_TXDIS;
|
526 |
|
|
serial_icr_write(info, UART_ACR, info->ACR);
|
527 |
|
|
}
|
528 |
|
|
restore_flags(flags);
|
529 |
|
|
}
|
530 |
|
|
|
531 |
|
|
/*
|
532 |
|
|
* ----------------------------------------------------------------------
|
533 |
|
|
*
|
534 |
|
|
* Here starts the interrupt handling routines. All of the following
|
535 |
|
|
* subroutines are declared as inline and are folded into
|
536 |
|
|
* rs_interrupt(). They were separated out for readability's sake.
|
537 |
|
|
*
|
538 |
|
|
* Note: rs_interrupt() is a "fast" interrupt, which means that it
|
539 |
|
|
* runs with interrupts turned off. People who may want to modify
|
540 |
|
|
* rs_interrupt() should try to keep the interrupt handler as fast as
|
541 |
|
|
* possible. After you are done making modifications, it is not a bad
|
542 |
|
|
* idea to do:
|
543 |
|
|
*
|
544 |
|
|
* gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
|
545 |
|
|
*
|
546 |
|
|
* and look at the resulting assemble code in serial.s.
|
547 |
|
|
*
|
548 |
|
|
* - Ted Ts'o (tytso@mit.edu), 7-Mar-93
|
549 |
|
|
* -----------------------------------------------------------------------
|
550 |
|
|
*/
|
551 |
|
|
|
552 |
|
|
/*
|
553 |
|
|
* This routine is used by the interrupt handler to schedule
|
554 |
|
|
* processing in the software interrupt portion of the driver.
|
555 |
|
|
*/
|
556 |
|
|
static _INLINE_ void rs_sched_event(struct async_struct *info,
|
557 |
|
|
int event)
|
558 |
|
|
{
|
559 |
|
|
info->event |= 1 << event;
|
560 |
|
|
queue_task(&info->tqueue, &tq_serial);
|
561 |
|
|
mark_bh(SERIAL_BH);
|
562 |
|
|
}
|
563 |
|
|
|
564 |
|
|
static _INLINE_ void receive_chars(struct async_struct *info,
|
565 |
|
|
int *status, struct pt_regs * regs)
|
566 |
|
|
{
|
567 |
|
|
struct tty_struct *tty = info->tty;
|
568 |
|
|
unsigned char ch;
|
569 |
|
|
struct async_icount *icount;
|
570 |
|
|
int max_count = 256;
|
571 |
|
|
|
572 |
|
|
icount = &info->state->icount;
|
573 |
|
|
do {
|
574 |
|
|
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
|
575 |
|
|
tty->flip.tqueue.routine((void *) tty);
|
576 |
|
|
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
577 |
|
|
return; // if TTY_DONT_FLIP is set
|
578 |
|
|
}
|
579 |
|
|
ch = serial_inp(info, UART_RX);
|
580 |
|
|
*tty->flip.char_buf_ptr = ch;
|
581 |
|
|
icount->rx++;
|
582 |
|
|
|
583 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
584 |
|
|
printk("DR%02x:%02x...", ch, *status);
|
585 |
|
|
#endif
|
586 |
|
|
*tty->flip.flag_buf_ptr = 0;
|
587 |
|
|
if (*status & (UART_LSR_BI | UART_LSR_PE |
|
588 |
|
|
UART_LSR_FE | UART_LSR_OE)) {
|
589 |
|
|
/*
|
590 |
|
|
* For statistics only
|
591 |
|
|
*/
|
592 |
|
|
if (*status & UART_LSR_BI) {
|
593 |
|
|
*status &= ~(UART_LSR_FE | UART_LSR_PE);
|
594 |
|
|
icount->brk++;
|
595 |
|
|
/*
|
596 |
|
|
* We do the SysRQ and SAK checking
|
597 |
|
|
* here because otherwise the break
|
598 |
|
|
* may get masked by ignore_status_mask
|
599 |
|
|
* or read_status_mask.
|
600 |
|
|
*/
|
601 |
|
|
#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
602 |
|
|
if (info->line == sercons.index) {
|
603 |
|
|
if (!break_pressed) {
|
604 |
|
|
break_pressed = jiffies;
|
605 |
|
|
goto ignore_char;
|
606 |
|
|
}
|
607 |
|
|
break_pressed = 0;
|
608 |
|
|
}
|
609 |
|
|
#endif
|
610 |
|
|
if (info->flags & ASYNC_SAK)
|
611 |
|
|
do_SAK(tty);
|
612 |
|
|
} else if (*status & UART_LSR_PE)
|
613 |
|
|
icount->parity++;
|
614 |
|
|
else if (*status & UART_LSR_FE)
|
615 |
|
|
icount->frame++;
|
616 |
|
|
if (*status & UART_LSR_OE)
|
617 |
|
|
icount->overrun++;
|
618 |
|
|
|
619 |
|
|
/*
|
620 |
|
|
* Mask off conditions which should be ignored.
|
621 |
|
|
*/
|
622 |
|
|
*status &= info->read_status_mask;
|
623 |
|
|
|
624 |
|
|
#ifdef CONFIG_SERIAL_CONSOLE
|
625 |
|
|
if (info->line == sercons.index) {
|
626 |
|
|
/* Recover the break flag from console xmit */
|
627 |
|
|
*status |= lsr_break_flag;
|
628 |
|
|
lsr_break_flag = 0;
|
629 |
|
|
}
|
630 |
|
|
#endif
|
631 |
|
|
if (*status & (UART_LSR_BI)) {
|
632 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
633 |
|
|
printk("handling break....");
|
634 |
|
|
#endif
|
635 |
|
|
*tty->flip.flag_buf_ptr = TTY_BREAK;
|
636 |
|
|
} else if (*status & UART_LSR_PE)
|
637 |
|
|
*tty->flip.flag_buf_ptr = TTY_PARITY;
|
638 |
|
|
else if (*status & UART_LSR_FE)
|
639 |
|
|
*tty->flip.flag_buf_ptr = TTY_FRAME;
|
640 |
|
|
}
|
641 |
|
|
#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
642 |
|
|
if (break_pressed && info->line == sercons.index) {
|
643 |
|
|
if (ch != 0 &&
|
644 |
|
|
time_before(jiffies, break_pressed + HZ*5)) {
|
645 |
|
|
handle_sysrq(ch, regs, NULL, NULL);
|
646 |
|
|
break_pressed = 0;
|
647 |
|
|
goto ignore_char;
|
648 |
|
|
}
|
649 |
|
|
break_pressed = 0;
|
650 |
|
|
}
|
651 |
|
|
#endif
|
652 |
|
|
if ((*status & info->ignore_status_mask) == 0) {
|
653 |
|
|
tty->flip.flag_buf_ptr++;
|
654 |
|
|
tty->flip.char_buf_ptr++;
|
655 |
|
|
tty->flip.count++;
|
656 |
|
|
}
|
657 |
|
|
if ((*status & UART_LSR_OE) &&
|
658 |
|
|
(tty->flip.count < TTY_FLIPBUF_SIZE)) {
|
659 |
|
|
/*
|
660 |
|
|
* Overrun is special, since it's reported
|
661 |
|
|
* immediately, and doesn't affect the current
|
662 |
|
|
* character
|
663 |
|
|
*/
|
664 |
|
|
*tty->flip.flag_buf_ptr = TTY_OVERRUN;
|
665 |
|
|
tty->flip.count++;
|
666 |
|
|
tty->flip.flag_buf_ptr++;
|
667 |
|
|
tty->flip.char_buf_ptr++;
|
668 |
|
|
}
|
669 |
|
|
#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
670 |
|
|
ignore_char:
|
671 |
|
|
#endif
|
672 |
|
|
*status = serial_inp(info, UART_LSR);
|
673 |
|
|
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
|
674 |
|
|
#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
|
675 |
|
|
tty_flip_buffer_push(tty);
|
676 |
|
|
#else
|
677 |
|
|
queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
|
678 |
|
|
#endif
|
679 |
|
|
}
|
680 |
|
|
|
681 |
|
|
static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
|
682 |
|
|
{
|
683 |
|
|
int count;
|
684 |
|
|
|
685 |
|
|
if (info->x_char) {
|
686 |
|
|
serial_outp(info, UART_TX, info->x_char);
|
687 |
|
|
info->state->icount.tx++;
|
688 |
|
|
info->x_char = 0;
|
689 |
|
|
if (intr_done)
|
690 |
|
|
*intr_done = 0;
|
691 |
|
|
return;
|
692 |
|
|
}
|
693 |
|
|
if (info->xmit.head == info->xmit.tail
|
694 |
|
|
|| info->tty->stopped
|
695 |
|
|
|| info->tty->hw_stopped) {
|
696 |
|
|
info->IER &= ~UART_IER_THRI;
|
697 |
|
|
serial_out(info, UART_IER, info->IER);
|
698 |
|
|
return;
|
699 |
|
|
}
|
700 |
|
|
|
701 |
|
|
count = info->xmit_fifo_size;
|
702 |
|
|
do {
|
703 |
|
|
serial_out(info, UART_TX, info->xmit.buf[info->xmit.tail]);
|
704 |
|
|
info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1);
|
705 |
|
|
info->state->icount.tx++;
|
706 |
|
|
if (info->xmit.head == info->xmit.tail)
|
707 |
|
|
break;
|
708 |
|
|
} while (--count > 0);
|
709 |
|
|
|
710 |
|
|
if (CIRC_CNT(info->xmit.head,
|
711 |
|
|
info->xmit.tail,
|
712 |
|
|
SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
|
713 |
|
|
rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
|
714 |
|
|
|
715 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
716 |
|
|
printk("THRE...");
|
717 |
|
|
#endif
|
718 |
|
|
if (intr_done)
|
719 |
|
|
*intr_done = 0;
|
720 |
|
|
|
721 |
|
|
if (info->xmit.head == info->xmit.tail) {
|
722 |
|
|
info->IER &= ~UART_IER_THRI;
|
723 |
|
|
serial_out(info, UART_IER, info->IER);
|
724 |
|
|
}
|
725 |
|
|
}
|
726 |
|
|
|
727 |
|
|
static _INLINE_ void check_modem_status(struct async_struct *info)
|
728 |
|
|
{
|
729 |
|
|
int status;
|
730 |
|
|
struct async_icount *icount;
|
731 |
|
|
|
732 |
|
|
status = serial_in(info, UART_MSR);
|
733 |
|
|
|
734 |
|
|
if (status & UART_MSR_ANY_DELTA) {
|
735 |
|
|
icount = &info->state->icount;
|
736 |
|
|
/* update input line counters */
|
737 |
|
|
if (status & UART_MSR_TERI)
|
738 |
|
|
icount->rng++;
|
739 |
|
|
if (status & UART_MSR_DDSR)
|
740 |
|
|
icount->dsr++;
|
741 |
|
|
if (status & UART_MSR_DDCD) {
|
742 |
|
|
icount->dcd++;
|
743 |
|
|
#ifdef CONFIG_HARD_PPS
|
744 |
|
|
if ((info->flags & ASYNC_HARDPPS_CD) &&
|
745 |
|
|
(status & UART_MSR_DCD))
|
746 |
|
|
hardpps();
|
747 |
|
|
#endif
|
748 |
|
|
}
|
749 |
|
|
if (status & UART_MSR_DCTS)
|
750 |
|
|
icount->cts++;
|
751 |
|
|
wake_up_interruptible(&info->delta_msr_wait);
|
752 |
|
|
}
|
753 |
|
|
|
754 |
|
|
if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
|
755 |
|
|
#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
|
756 |
|
|
printk("ttys%d CD now %s...", info->line,
|
757 |
|
|
(status & UART_MSR_DCD) ? "on" : "off");
|
758 |
|
|
#endif
|
759 |
|
|
if (status & UART_MSR_DCD)
|
760 |
|
|
wake_up_interruptible(&info->open_wait);
|
761 |
|
|
else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
|
762 |
|
|
(info->flags & ASYNC_CALLOUT_NOHUP))) {
|
763 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
764 |
|
|
printk("doing serial hangup...");
|
765 |
|
|
#endif
|
766 |
|
|
if (info->tty)
|
767 |
|
|
tty_hangup(info->tty);
|
768 |
|
|
}
|
769 |
|
|
}
|
770 |
|
|
if (info->flags & ASYNC_CTS_FLOW) {
|
771 |
|
|
if (info->tty->hw_stopped) {
|
772 |
|
|
if (status & UART_MSR_CTS) {
|
773 |
|
|
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
|
774 |
|
|
printk("CTS tx start...");
|
775 |
|
|
#endif
|
776 |
|
|
info->tty->hw_stopped = 0;
|
777 |
|
|
info->IER |= UART_IER_THRI;
|
778 |
|
|
serial_out(info, UART_IER, info->IER);
|
779 |
|
|
rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
|
780 |
|
|
return;
|
781 |
|
|
}
|
782 |
|
|
} else {
|
783 |
|
|
if (!(status & UART_MSR_CTS)) {
|
784 |
|
|
#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
|
785 |
|
|
printk("CTS tx stop...");
|
786 |
|
|
#endif
|
787 |
|
|
info->tty->hw_stopped = 1;
|
788 |
|
|
info->IER &= ~UART_IER_THRI;
|
789 |
|
|
serial_out(info, UART_IER, info->IER);
|
790 |
|
|
}
|
791 |
|
|
}
|
792 |
|
|
}
|
793 |
|
|
}
|
794 |
|
|
|
795 |
|
|
#ifdef CONFIG_SERIAL_SHARE_IRQ
|
796 |
|
|
/*
|
797 |
|
|
* This is the serial driver's generic interrupt routine
|
798 |
|
|
*/
|
799 |
|
|
static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
|
800 |
|
|
{
|
801 |
|
|
int status, iir;
|
802 |
|
|
struct async_struct * info;
|
803 |
|
|
int pass_counter = 0;
|
804 |
|
|
struct async_struct *end_mark = 0;
|
805 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
806 |
|
|
int first_multi = 0;
|
807 |
|
|
struct rs_multiport_struct *multi;
|
808 |
|
|
#endif
|
809 |
|
|
|
810 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
811 |
|
|
printk("rs_interrupt(%d)...", irq);
|
812 |
|
|
#endif
|
813 |
|
|
|
814 |
|
|
info = IRQ_ports[irq];
|
815 |
|
|
if (!info)
|
816 |
|
|
return;
|
817 |
|
|
|
818 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
819 |
|
|
multi = &rs_multiport[irq];
|
820 |
|
|
if (multi->port_monitor)
|
821 |
|
|
first_multi = inb(multi->port_monitor);
|
822 |
|
|
#endif
|
823 |
|
|
|
824 |
|
|
do {
|
825 |
|
|
if (!info->tty ||
|
826 |
|
|
((iir=serial_in(info, UART_IIR)) & UART_IIR_NO_INT)) {
|
827 |
|
|
if (!end_mark)
|
828 |
|
|
end_mark = info;
|
829 |
|
|
goto next;
|
830 |
|
|
}
|
831 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
832 |
|
|
printk("IIR = %x...", serial_in(info, UART_IIR));
|
833 |
|
|
#endif
|
834 |
|
|
end_mark = 0;
|
835 |
|
|
|
836 |
|
|
info->last_active = jiffies;
|
837 |
|
|
|
838 |
|
|
status = serial_inp(info, UART_LSR);
|
839 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
840 |
|
|
printk("status = %x...", status);
|
841 |
|
|
#endif
|
842 |
|
|
if (status & UART_LSR_DR)
|
843 |
|
|
receive_chars(info, &status, regs);
|
844 |
|
|
check_modem_status(info);
|
845 |
|
|
#ifdef CONFIG_MELAN
|
846 |
|
|
if ((status & UART_LSR_THRE) ||
|
847 |
|
|
/* for buggy ELAN processors */
|
848 |
|
|
((iir & UART_IIR_ID) == UART_IIR_THRI))
|
849 |
|
|
transmit_chars(info, 0);
|
850 |
|
|
#else
|
851 |
|
|
if (status & UART_LSR_THRE)
|
852 |
|
|
transmit_chars(info, 0);
|
853 |
|
|
#endif
|
854 |
|
|
|
855 |
|
|
next:
|
856 |
|
|
info = info->next_port;
|
857 |
|
|
if (!info) {
|
858 |
|
|
info = IRQ_ports[irq];
|
859 |
|
|
if (pass_counter++ > RS_ISR_PASS_LIMIT) {
|
860 |
|
|
#if 0
|
861 |
|
|
printk("rs loop break\n");
|
862 |
|
|
#endif
|
863 |
|
|
break; /* Prevent infinite loops */
|
864 |
|
|
}
|
865 |
|
|
continue;
|
866 |
|
|
}
|
867 |
|
|
} while (end_mark != info);
|
868 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
869 |
|
|
if (multi->port_monitor)
|
870 |
|
|
printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n",
|
871 |
|
|
info->state->irq, first_multi,
|
872 |
|
|
inb(multi->port_monitor));
|
873 |
|
|
#endif
|
874 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
875 |
|
|
printk("end.\n");
|
876 |
|
|
#endif
|
877 |
|
|
}
|
878 |
|
|
#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */
|
879 |
|
|
|
880 |
|
|
|
881 |
|
|
/*
|
882 |
|
|
* This is the serial driver's interrupt routine for a single port
|
883 |
|
|
*/
|
884 |
|
|
static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
|
885 |
|
|
{
|
886 |
|
|
int status, iir;
|
887 |
|
|
int pass_counter = 0;
|
888 |
|
|
struct async_struct * info;
|
889 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
890 |
|
|
int first_multi = 0;
|
891 |
|
|
struct rs_multiport_struct *multi;
|
892 |
|
|
#endif
|
893 |
|
|
|
894 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
895 |
|
|
printk("rs_interrupt_single(%d)...", irq);
|
896 |
|
|
#endif
|
897 |
|
|
|
898 |
|
|
info = IRQ_ports[irq];
|
899 |
|
|
if (!info || !info->tty)
|
900 |
|
|
return;
|
901 |
|
|
|
902 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
903 |
|
|
multi = &rs_multiport[irq];
|
904 |
|
|
if (multi->port_monitor)
|
905 |
|
|
first_multi = inb(multi->port_monitor);
|
906 |
|
|
#endif
|
907 |
|
|
|
908 |
|
|
iir = serial_in(info, UART_IIR);
|
909 |
|
|
do {
|
910 |
|
|
status = serial_inp(info, UART_LSR);
|
911 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
912 |
|
|
printk("status = %x...", status);
|
913 |
|
|
#endif
|
914 |
|
|
if (status & UART_LSR_DR)
|
915 |
|
|
receive_chars(info, &status, regs);
|
916 |
|
|
check_modem_status(info);
|
917 |
|
|
#ifdef CONFIG_MELAN
|
918 |
|
|
if ((status & UART_LSR_THRE) ||
|
919 |
|
|
/* For buggy ELAN processors */
|
920 |
|
|
((iir & UART_IIR_ID) == UART_IIR_THRI))
|
921 |
|
|
transmit_chars(info, 0);
|
922 |
|
|
#else
|
923 |
|
|
if (status & UART_LSR_THRE)
|
924 |
|
|
transmit_chars(info, 0);
|
925 |
|
|
#endif
|
926 |
|
|
if (pass_counter++ > RS_ISR_PASS_LIMIT) {
|
927 |
|
|
#if SERIAL_DEBUG_INTR
|
928 |
|
|
printk("rs_single loop break.\n");
|
929 |
|
|
#endif
|
930 |
|
|
break;
|
931 |
|
|
}
|
932 |
|
|
iir = serial_in(info, UART_IIR);
|
933 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
934 |
|
|
printk("IIR = %x...", iir);
|
935 |
|
|
#endif
|
936 |
|
|
} while ((iir & UART_IIR_NO_INT) == 0);
|
937 |
|
|
info->last_active = jiffies;
|
938 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
939 |
|
|
if (multi->port_monitor)
|
940 |
|
|
printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n",
|
941 |
|
|
info->state->irq, first_multi,
|
942 |
|
|
inb(multi->port_monitor));
|
943 |
|
|
#endif
|
944 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
945 |
|
|
printk("end.\n");
|
946 |
|
|
#endif
|
947 |
|
|
}
|
948 |
|
|
|
949 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
950 |
|
|
/*
|
951 |
|
|
* This is the serial driver's for multiport boards
|
952 |
|
|
*/
|
953 |
|
|
static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs)
|
954 |
|
|
{
|
955 |
|
|
int status;
|
956 |
|
|
struct async_struct * info;
|
957 |
|
|
int pass_counter = 0;
|
958 |
|
|
int first_multi= 0;
|
959 |
|
|
struct rs_multiport_struct *multi;
|
960 |
|
|
|
961 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
962 |
|
|
printk("rs_interrupt_multi(%d)...", irq);
|
963 |
|
|
#endif
|
964 |
|
|
|
965 |
|
|
info = IRQ_ports[irq];
|
966 |
|
|
if (!info)
|
967 |
|
|
return;
|
968 |
|
|
multi = &rs_multiport[irq];
|
969 |
|
|
if (!multi->port1) {
|
970 |
|
|
/* Should never happen */
|
971 |
|
|
printk("rs_interrupt_multi: NULL port1!\n");
|
972 |
|
|
return;
|
973 |
|
|
}
|
974 |
|
|
if (multi->port_monitor)
|
975 |
|
|
first_multi = inb(multi->port_monitor);
|
976 |
|
|
|
977 |
|
|
while (1) {
|
978 |
|
|
if (!info->tty ||
|
979 |
|
|
(serial_in(info, UART_IIR) & UART_IIR_NO_INT))
|
980 |
|
|
goto next;
|
981 |
|
|
|
982 |
|
|
info->last_active = jiffies;
|
983 |
|
|
|
984 |
|
|
status = serial_inp(info, UART_LSR);
|
985 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
986 |
|
|
printk("status = %x...", status);
|
987 |
|
|
#endif
|
988 |
|
|
if (status & UART_LSR_DR)
|
989 |
|
|
receive_chars(info, &status, regs);
|
990 |
|
|
check_modem_status(info);
|
991 |
|
|
if (status & UART_LSR_THRE)
|
992 |
|
|
transmit_chars(info, 0);
|
993 |
|
|
|
994 |
|
|
next:
|
995 |
|
|
info = info->next_port;
|
996 |
|
|
if (info)
|
997 |
|
|
continue;
|
998 |
|
|
|
999 |
|
|
info = IRQ_ports[irq];
|
1000 |
|
|
/*
|
1001 |
|
|
* The user was a bonehead, and misconfigured their
|
1002 |
|
|
* multiport info. Rather than lock up the kernel
|
1003 |
|
|
* in an infinite loop, if we loop too many times,
|
1004 |
|
|
* print a message and break out of the loop.
|
1005 |
|
|
*/
|
1006 |
|
|
if (pass_counter++ > RS_ISR_PASS_LIMIT) {
|
1007 |
|
|
printk("Misconfigured multiport serial info "
|
1008 |
|
|
"for irq %d. Breaking out irq loop\n", irq);
|
1009 |
|
|
break;
|
1010 |
|
|
}
|
1011 |
|
|
if (multi->port_monitor)
|
1012 |
|
|
printk("rs port monitor irq %d: 0x%x, 0x%x\n",
|
1013 |
|
|
info->state->irq, first_multi,
|
1014 |
|
|
inb(multi->port_monitor));
|
1015 |
|
|
if ((inb(multi->port1) & multi->mask1) != multi->match1)
|
1016 |
|
|
continue;
|
1017 |
|
|
if (!multi->port2)
|
1018 |
|
|
break;
|
1019 |
|
|
if ((inb(multi->port2) & multi->mask2) != multi->match2)
|
1020 |
|
|
continue;
|
1021 |
|
|
if (!multi->port3)
|
1022 |
|
|
break;
|
1023 |
|
|
if ((inb(multi->port3) & multi->mask3) != multi->match3)
|
1024 |
|
|
continue;
|
1025 |
|
|
if (!multi->port4)
|
1026 |
|
|
break;
|
1027 |
|
|
if ((inb(multi->port4) & multi->mask4) != multi->match4)
|
1028 |
|
|
continue;
|
1029 |
|
|
break;
|
1030 |
|
|
}
|
1031 |
|
|
#ifdef SERIAL_DEBUG_INTR
|
1032 |
|
|
printk("end.\n");
|
1033 |
|
|
#endif
|
1034 |
|
|
}
|
1035 |
|
|
#endif
|
1036 |
|
|
|
1037 |
|
|
/*
|
1038 |
|
|
* -------------------------------------------------------------------
|
1039 |
|
|
* Here ends the serial interrupt routines.
|
1040 |
|
|
* -------------------------------------------------------------------
|
1041 |
|
|
*/
|
1042 |
|
|
|
1043 |
|
|
/*
|
1044 |
|
|
* This routine is used to handle the "bottom half" processing for the
|
1045 |
|
|
* serial driver, known also the "software interrupt" processing.
|
1046 |
|
|
* This processing is done at the kernel interrupt level, after the
|
1047 |
|
|
* rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
|
1048 |
|
|
* is where time-consuming activities which can not be done in the
|
1049 |
|
|
* interrupt driver proper are done; the interrupt driver schedules
|
1050 |
|
|
* them using rs_sched_event(), and they get done here.
|
1051 |
|
|
*/
|
1052 |
|
|
static void do_serial_bh(void)
|
1053 |
|
|
{
|
1054 |
|
|
run_task_queue(&tq_serial);
|
1055 |
|
|
}
|
1056 |
|
|
|
1057 |
|
|
static void do_softint(void *private_)
|
1058 |
|
|
{
|
1059 |
|
|
struct async_struct *info = (struct async_struct *) private_;
|
1060 |
|
|
struct tty_struct *tty;
|
1061 |
|
|
|
1062 |
|
|
tty = info->tty;
|
1063 |
|
|
if (!tty)
|
1064 |
|
|
return;
|
1065 |
|
|
|
1066 |
|
|
if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
|
1067 |
|
|
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
|
1068 |
|
|
tty->ldisc.write_wakeup)
|
1069 |
|
|
(tty->ldisc.write_wakeup)(tty);
|
1070 |
|
|
wake_up_interruptible(&tty->write_wait);
|
1071 |
|
|
#ifdef SERIAL_HAVE_POLL_WAIT
|
1072 |
|
|
wake_up_interruptible(&tty->poll_wait);
|
1073 |
|
|
#endif
|
1074 |
|
|
}
|
1075 |
|
|
}
|
1076 |
|
|
|
1077 |
|
|
/*
|
1078 |
|
|
* This subroutine is called when the RS_TIMER goes off. It is used
|
1079 |
|
|
* by the serial driver to handle ports that do not have an interrupt
|
1080 |
|
|
* (irq=0). This doesn't work very well for 16450's, but gives barely
|
1081 |
|
|
* passable results for a 16550A. (Although at the expense of much
|
1082 |
|
|
* CPU overhead).
|
1083 |
|
|
*/
|
1084 |
|
|
static void rs_timer(unsigned long dummy)
|
1085 |
|
|
{
|
1086 |
|
|
static unsigned long last_strobe;
|
1087 |
|
|
struct async_struct *info;
|
1088 |
|
|
unsigned int i;
|
1089 |
|
|
unsigned long flags;
|
1090 |
|
|
|
1091 |
|
|
if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
|
1092 |
|
|
for (i=0; i < NR_IRQS; i++) {
|
1093 |
|
|
info = IRQ_ports[i];
|
1094 |
|
|
if (!info)
|
1095 |
|
|
continue;
|
1096 |
|
|
save_flags(flags); cli();
|
1097 |
|
|
#ifdef CONFIG_SERIAL_SHARE_IRQ
|
1098 |
|
|
if (info->next_port) {
|
1099 |
|
|
do {
|
1100 |
|
|
serial_out(info, UART_IER, 0);
|
1101 |
|
|
info->IER |= UART_IER_THRI;
|
1102 |
|
|
serial_out(info, UART_IER, info->IER);
|
1103 |
|
|
info = info->next_port;
|
1104 |
|
|
} while (info);
|
1105 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
1106 |
|
|
if (rs_multiport[i].port1)
|
1107 |
|
|
rs_interrupt_multi(i, NULL, NULL);
|
1108 |
|
|
else
|
1109 |
|
|
#endif
|
1110 |
|
|
rs_interrupt(i, NULL, NULL);
|
1111 |
|
|
} else
|
1112 |
|
|
#endif /* CONFIG_SERIAL_SHARE_IRQ */
|
1113 |
|
|
rs_interrupt_single(i, NULL, NULL);
|
1114 |
|
|
restore_flags(flags);
|
1115 |
|
|
}
|
1116 |
|
|
}
|
1117 |
|
|
last_strobe = jiffies;
|
1118 |
|
|
mod_timer(&serial_timer, jiffies + RS_STROBE_TIME);
|
1119 |
|
|
|
1120 |
|
|
if (IRQ_ports[0]) {
|
1121 |
|
|
save_flags(flags); cli();
|
1122 |
|
|
#ifdef CONFIG_SERIAL_SHARE_IRQ
|
1123 |
|
|
rs_interrupt(0, NULL, NULL);
|
1124 |
|
|
#else
|
1125 |
|
|
rs_interrupt_single(0, NULL, NULL);
|
1126 |
|
|
#endif
|
1127 |
|
|
restore_flags(flags);
|
1128 |
|
|
|
1129 |
|
|
mod_timer(&serial_timer, jiffies + IRQ_timeout[0]);
|
1130 |
|
|
}
|
1131 |
|
|
}
|
1132 |
|
|
|
1133 |
|
|
/*
|
1134 |
|
|
* ---------------------------------------------------------------
|
1135 |
|
|
* Low level utility subroutines for the serial driver: routines to
|
1136 |
|
|
* figure out the appropriate timeout for an interrupt chain, routines
|
1137 |
|
|
* to initialize and startup a serial port, and routines to shutdown a
|
1138 |
|
|
* serial port. Useful stuff like that.
|
1139 |
|
|
* ---------------------------------------------------------------
|
1140 |
|
|
*/
|
1141 |
|
|
|
1142 |
|
|
/*
|
1143 |
|
|
* This routine figures out the correct timeout for a particular IRQ.
|
1144 |
|
|
* It uses the smallest timeout of all of the serial ports in a
|
1145 |
|
|
* particular interrupt chain. Now only used for IRQ 0....
|
1146 |
|
|
*/
|
1147 |
|
|
static void figure_IRQ_timeout(int irq)
|
1148 |
|
|
{
|
1149 |
|
|
struct async_struct *info;
|
1150 |
|
|
int timeout = 60*HZ; /* 60 seconds === a long time :-) */
|
1151 |
|
|
|
1152 |
|
|
info = IRQ_ports[irq];
|
1153 |
|
|
if (!info) {
|
1154 |
|
|
IRQ_timeout[irq] = 60*HZ;
|
1155 |
|
|
return;
|
1156 |
|
|
}
|
1157 |
|
|
while (info) {
|
1158 |
|
|
if (info->timeout < timeout)
|
1159 |
|
|
timeout = info->timeout;
|
1160 |
|
|
info = info->next_port;
|
1161 |
|
|
}
|
1162 |
|
|
if (!irq)
|
1163 |
|
|
timeout = timeout / 2;
|
1164 |
|
|
IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1;
|
1165 |
|
|
}
|
1166 |
|
|
|
1167 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
1168 |
|
|
/* Attempts to turn on the RSA FIFO. Returns zero on failure */
|
1169 |
|
|
static int enable_rsa(struct async_struct *info)
|
1170 |
|
|
{
|
1171 |
|
|
unsigned char mode;
|
1172 |
|
|
int result;
|
1173 |
|
|
unsigned long flags;
|
1174 |
|
|
|
1175 |
|
|
save_flags(flags); cli();
|
1176 |
|
|
mode = serial_inp(info, UART_RSA_MSR);
|
1177 |
|
|
result = mode & UART_RSA_MSR_FIFO;
|
1178 |
|
|
|
1179 |
|
|
if (!result) {
|
1180 |
|
|
serial_outp(info, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
|
1181 |
|
|
mode = serial_inp(info, UART_RSA_MSR);
|
1182 |
|
|
result = mode & UART_RSA_MSR_FIFO;
|
1183 |
|
|
}
|
1184 |
|
|
|
1185 |
|
|
restore_flags(flags);
|
1186 |
|
|
return result;
|
1187 |
|
|
}
|
1188 |
|
|
|
1189 |
|
|
/* Attempts to turn off the RSA FIFO. Returns zero on failure */
|
1190 |
|
|
static int disable_rsa(struct async_struct *info)
|
1191 |
|
|
{
|
1192 |
|
|
unsigned char mode;
|
1193 |
|
|
int result;
|
1194 |
|
|
unsigned long flags;
|
1195 |
|
|
|
1196 |
|
|
save_flags(flags); cli();
|
1197 |
|
|
mode = serial_inp(info, UART_RSA_MSR);
|
1198 |
|
|
result = !(mode & UART_RSA_MSR_FIFO);
|
1199 |
|
|
|
1200 |
|
|
if (!result) {
|
1201 |
|
|
serial_outp(info, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
|
1202 |
|
|
mode = serial_inp(info, UART_RSA_MSR);
|
1203 |
|
|
result = !(mode & UART_RSA_MSR_FIFO);
|
1204 |
|
|
}
|
1205 |
|
|
|
1206 |
|
|
restore_flags(flags);
|
1207 |
|
|
return result;
|
1208 |
|
|
}
|
1209 |
|
|
#endif /* CONFIG_SERIAL_RSA */
|
1210 |
|
|
|
1211 |
|
|
static int startup(struct async_struct * info)
|
1212 |
|
|
{
|
1213 |
|
|
unsigned long flags;
|
1214 |
|
|
int retval=0;
|
1215 |
|
|
void (*handler)(int, void *, struct pt_regs *);
|
1216 |
|
|
struct serial_state *state= info->state;
|
1217 |
|
|
unsigned long page;
|
1218 |
|
|
#ifdef CONFIG_SERIAL_MANY_PORTS
|
1219 |
|
|
unsigned short ICP;
|
1220 |
|
|
#endif
|
1221 |
|
|
|
1222 |
|
|
page = get_zeroed_page(GFP_KERNEL);
|
1223 |
|
|
if (!page)
|
1224 |
|
|
return -ENOMEM;
|
1225 |
|
|
|
1226 |
|
|
save_flags(flags); cli();
|
1227 |
|
|
|
1228 |
|
|
if (info->flags & ASYNC_INITIALIZED) {
|
1229 |
|
|
free_page(page);
|
1230 |
|
|
goto errout;
|
1231 |
|
|
}
|
1232 |
|
|
|
1233 |
|
|
if (!CONFIGURED_SERIAL_PORT(state) || !state->type) {
|
1234 |
|
|
if (info->tty)
|
1235 |
|
|
set_bit(TTY_IO_ERROR, &info->tty->flags);
|
1236 |
|
|
free_page(page);
|
1237 |
|
|
goto errout;
|
1238 |
|
|
}
|
1239 |
|
|
if (info->xmit.buf)
|
1240 |
|
|
free_page(page);
|
1241 |
|
|
else
|
1242 |
|
|
info->xmit.buf = (unsigned char *) page;
|
1243 |
|
|
|
1244 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
1245 |
|
|
printk("starting up ttys%d (irq %d)...", info->line, state->irq);
|
1246 |
|
|
#endif
|
1247 |
|
|
|
1248 |
|
|
if (uart_config[state->type].flags & UART_STARTECH) {
|
1249 |
|
|
/* Wake up UART */
|
1250 |
|
|
serial_outp(info, UART_LCR, 0xBF);
|
1251 |
|
|
serial_outp(info, UART_EFR, UART_EFR_ECB);
|
1252 |
|
|
/*
|
1253 |
|
|
* Turn off LCR == 0xBF so we actually set the IER
|
1254 |
|
|
* register on the XR16C850
|
1255 |
|
|
*/
|
1256 |
|
|
serial_outp(info, UART_LCR, 0);
|
1257 |
|
|
serial_outp(info, UART_IER, 0);
|
1258 |
|
|
/*
|
1259 |
|
|
* Now reset LCR so we can turn off the ECB bit
|
1260 |
|
|
*/
|
1261 |
|
|
serial_outp(info, UART_LCR, 0xBF);
|
1262 |
|
|
serial_outp(info, UART_EFR, 0);
|
1263 |
|
|
/*
|
1264 |
|
|
* For a XR16C850, we need to set the trigger levels
|
1265 |
|
|
*/
|
1266 |
|
|
if (state->type == PORT_16850) {
|
1267 |
|
|
serial_outp(info, UART_FCTR, UART_FCTR_TRGD |
|
1268 |
|
|
UART_FCTR_RX);
|
1269 |
|
|
serial_outp(info, UART_TRG, UART_TRG_96);
|
1270 |
|
|
serial_outp(info, UART_FCTR, UART_FCTR_TRGD |
|
1271 |
|
|
UART_FCTR_TX);
|
1272 |
|
|
serial_outp(info, UART_TRG, UART_TRG_96);
|
1273 |
|
|
}
|
1274 |
|
|
serial_outp(info, UART_LCR, 0);
|
1275 |
|
|
}
|
1276 |
|
|
|
1277 |
|
|
if (state->type == PORT_16750) {
|
1278 |
|
|
/* Wake up UART */
|
1279 |
|
|
serial_outp(info, UART_IER, 0);
|
1280 |
|
|
}
|
1281 |
|
|
|
1282 |
|
|
if (state->type == PORT_16C950) {
|
1283 |
|
|
/* Wake up and initialize UART */
|
1284 |
|
|
info->ACR = 0;
|
1285 |
|
|
serial_outp(info, UART_LCR, 0xBF);
|
1286 |
|
|
serial_outp(info, UART_EFR, UART_EFR_ECB);
|
1287 |
|
|
serial_outp(info, UART_IER, 0);
|
1288 |
|
|
serial_outp(info, UART_LCR, 0);
|
1289 |
|
|
serial_icr_write(info, UART_CSR, 0); /* Reset the UART */
|
1290 |
|
|
serial_outp(info, UART_LCR, 0xBF);
|
1291 |
|
|
serial_outp(info, UART_EFR, UART_EFR_ECB);
|
1292 |
|
|
serial_outp(info, UART_LCR, 0);
|
1293 |
|
|
}
|
1294 |
|
|
|
1295 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
1296 |
|
|
/*
|
1297 |
|
|
* If this is an RSA port, see if we can kick it up to the
|
1298 |
|
|
* higher speed clock.
|
1299 |
|
|
*/
|
1300 |
|
|
if (state->type == PORT_RSA) {
|
1301 |
|
|
if (state->baud_base != SERIAL_RSA_BAUD_BASE &&
|
1302 |
|
|
enable_rsa(info))
|
1303 |
|
|
state->baud_base = SERIAL_RSA_BAUD_BASE;
|
1304 |
|
|
if (state->baud_base == SERIAL_RSA_BAUD_BASE)
|
1305 |
|
|
serial_outp(info, UART_RSA_FRR, 0);
|
1306 |
|
|
}
|
1307 |
|
|
#endif
|
1308 |
|
|
|
1309 |
|
|
/*
|
1310 |
|
|
* Clear the FIFO buffers and disable them
|
1311 |
|
|
* (they will be reenabled in change_speed())
|
1312 |
|
|
*/
|
1313 |
|
|
if (uart_config[state->type].flags & UART_CLEAR_FIFO) {
|
1314 |
|
|
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
|
1315 |
|
|
serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
|
1316 |
|
|
UART_FCR_CLEAR_RCVR |
|
1317 |
|
|
UART_FCR_CLEAR_XMIT));
|
1318 |
|
|
serial_outp(info, UART_FCR, 0);
|
1319 |
|
|
}
|
1320 |
|
|
|
1321 |
|
|
/*
|
1322 |
|
|
* Clear the interrupt registers.
|
1323 |
|
|
*/
|
1324 |
|
|
(void) serial_inp(info, UART_LSR);
|
1325 |
|
|
(void) serial_inp(info, UART_RX);
|
1326 |
|
|
(void) serial_inp(info, UART_IIR);
|
1327 |
|
|
(void) serial_inp(info, UART_MSR);
|
1328 |
|
|
|
1329 |
|
|
/*
|
1330 |
|
|
* At this point there's no way the LSR could still be 0xFF;
|
1331 |
|
|
* if it is, then bail out, because there's likely no UART
|
1332 |
|
|
* here.
|
1333 |
|
|
*/
|
1334 |
|
|
if (!(info->flags & ASYNC_BUGGY_UART) &&
|
1335 |
|
|
(serial_inp(info, UART_LSR) == 0xff)) {
|
1336 |
|
|
printk("ttyS%d: LSR safety check engaged!\n", state->line);
|
1337 |
|
|
if (capable(CAP_SYS_ADMIN)) {
|
1338 |
|
|
if (info->tty)
|
1339 |
|
|
set_bit(TTY_IO_ERROR, &info->tty->flags);
|
1340 |
|
|
} else
|
1341 |
|
|
retval = -ENODEV;
|
1342 |
|
|
goto errout;
|
1343 |
|
|
}
|
1344 |
|
|
|
1345 |
|
|
/*
|
1346 |
|
|
* Allocate the IRQ if necessary
|
1347 |
|
|
*/
|
1348 |
|
|
if (state->irq && (!IRQ_ports[state->irq] ||
|
1349 |
|
|
!IRQ_ports[state->irq]->next_port)) {
|
1350 |
|
|
if (IRQ_ports[state->irq]) {
|
1351 |
|
|
#ifdef CONFIG_SERIAL_SHARE_IRQ
|
1352 |
|
|
free_irq(state->irq, &IRQ_ports[state->irq]);
|
1353 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
1354 |
|
|
if (rs_multiport[state->irq].port1)
|
1355 |
|
|
handler = rs_interrupt_multi;
|
1356 |
|
|
else
|
1357 |
|
|
#endif
|
1358 |
|
|
handler = rs_interrupt;
|
1359 |
|
|
#else
|
1360 |
|
|
retval = -EBUSY;
|
1361 |
|
|
goto errout;
|
1362 |
|
|
#endif /* CONFIG_SERIAL_SHARE_IRQ */
|
1363 |
|
|
} else
|
1364 |
|
|
handler = rs_interrupt_single;
|
1365 |
|
|
|
1366 |
|
|
retval = request_irq(state->irq, handler, SA_SHIRQ,
|
1367 |
|
|
"serial", &IRQ_ports[state->irq]);
|
1368 |
|
|
if (retval) {
|
1369 |
|
|
if (capable(CAP_SYS_ADMIN)) {
|
1370 |
|
|
if (info->tty)
|
1371 |
|
|
set_bit(TTY_IO_ERROR,
|
1372 |
|
|
&info->tty->flags);
|
1373 |
|
|
retval = 0;
|
1374 |
|
|
}
|
1375 |
|
|
goto errout;
|
1376 |
|
|
}
|
1377 |
|
|
}
|
1378 |
|
|
|
1379 |
|
|
/*
|
1380 |
|
|
* Insert serial port into IRQ chain.
|
1381 |
|
|
*/
|
1382 |
|
|
info->prev_port = 0;
|
1383 |
|
|
info->next_port = IRQ_ports[state->irq];
|
1384 |
|
|
if (info->next_port)
|
1385 |
|
|
info->next_port->prev_port = info;
|
1386 |
|
|
IRQ_ports[state->irq] = info;
|
1387 |
|
|
figure_IRQ_timeout(state->irq);
|
1388 |
|
|
|
1389 |
|
|
/*
|
1390 |
|
|
* Now, initialize the UART
|
1391 |
|
|
*/
|
1392 |
|
|
serial_outp(info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */
|
1393 |
|
|
|
1394 |
|
|
info->MCR = 0;
|
1395 |
|
|
if (info->tty->termios->c_cflag & CBAUD)
|
1396 |
|
|
info->MCR = UART_MCR_DTR | UART_MCR_RTS;
|
1397 |
|
|
#ifdef CONFIG_SERIAL_MANY_PORTS
|
1398 |
|
|
if (info->flags & ASYNC_FOURPORT) {
|
1399 |
|
|
if (state->irq == 0)
|
1400 |
|
|
info->MCR |= UART_MCR_OUT1;
|
1401 |
|
|
} else
|
1402 |
|
|
#endif
|
1403 |
|
|
{
|
1404 |
|
|
if (state->irq != 0)
|
1405 |
|
|
info->MCR |= UART_MCR_OUT2;
|
1406 |
|
|
}
|
1407 |
|
|
info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */
|
1408 |
|
|
serial_outp(info, UART_MCR, info->MCR);
|
1409 |
|
|
|
1410 |
|
|
/*
|
1411 |
|
|
* Finally, enable interrupts
|
1412 |
|
|
*/
|
1413 |
|
|
info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
|
1414 |
|
|
serial_outp(info, UART_IER, info->IER); /* enable interrupts */
|
1415 |
|
|
|
1416 |
|
|
#ifdef CONFIG_SERIAL_MANY_PORTS
|
1417 |
|
|
if (info->flags & ASYNC_FOURPORT) {
|
1418 |
|
|
/* Enable interrupts on the AST Fourport board */
|
1419 |
|
|
ICP = (info->port & 0xFE0) | 0x01F;
|
1420 |
|
|
outb_p(0x80, ICP);
|
1421 |
|
|
(void) inb_p(ICP);
|
1422 |
|
|
}
|
1423 |
|
|
#endif
|
1424 |
|
|
|
1425 |
|
|
/*
|
1426 |
|
|
* And clear the interrupt registers again for luck.
|
1427 |
|
|
*/
|
1428 |
|
|
(void)serial_inp(info, UART_LSR);
|
1429 |
|
|
(void)serial_inp(info, UART_RX);
|
1430 |
|
|
(void)serial_inp(info, UART_IIR);
|
1431 |
|
|
(void)serial_inp(info, UART_MSR);
|
1432 |
|
|
|
1433 |
|
|
if (info->tty)
|
1434 |
|
|
clear_bit(TTY_IO_ERROR, &info->tty->flags);
|
1435 |
|
|
info->xmit.head = info->xmit.tail = 0;
|
1436 |
|
|
|
1437 |
|
|
/*
|
1438 |
|
|
* Set up serial timers...
|
1439 |
|
|
*/
|
1440 |
|
|
mod_timer(&serial_timer, jiffies + 2*HZ/100);
|
1441 |
|
|
|
1442 |
|
|
/*
|
1443 |
|
|
* Set up the tty->alt_speed kludge
|
1444 |
|
|
*/
|
1445 |
|
|
#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
|
1446 |
|
|
if (info->tty) {
|
1447 |
|
|
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
|
1448 |
|
|
info->tty->alt_speed = 57600;
|
1449 |
|
|
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
|
1450 |
|
|
info->tty->alt_speed = 115200;
|
1451 |
|
|
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
|
1452 |
|
|
info->tty->alt_speed = 230400;
|
1453 |
|
|
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
|
1454 |
|
|
info->tty->alt_speed = 460800;
|
1455 |
|
|
}
|
1456 |
|
|
#endif
|
1457 |
|
|
|
1458 |
|
|
/*
|
1459 |
|
|
* and set the speed of the serial port
|
1460 |
|
|
*/
|
1461 |
|
|
change_speed(info, 0);
|
1462 |
|
|
|
1463 |
|
|
info->flags |= ASYNC_INITIALIZED;
|
1464 |
|
|
restore_flags(flags);
|
1465 |
|
|
return 0;
|
1466 |
|
|
|
1467 |
|
|
errout:
|
1468 |
|
|
restore_flags(flags);
|
1469 |
|
|
return retval;
|
1470 |
|
|
}
|
1471 |
|
|
|
1472 |
|
|
/*
|
1473 |
|
|
* This routine will shutdown a serial port; interrupts are disabled, and
|
1474 |
|
|
* DTR is dropped if the hangup on close termio flag is on.
|
1475 |
|
|
*/
|
1476 |
|
|
static void shutdown(struct async_struct * info)
|
1477 |
|
|
{
|
1478 |
|
|
unsigned long flags;
|
1479 |
|
|
struct serial_state *state;
|
1480 |
|
|
int retval;
|
1481 |
|
|
|
1482 |
|
|
if (!(info->flags & ASYNC_INITIALIZED))
|
1483 |
|
|
return;
|
1484 |
|
|
|
1485 |
|
|
state = info->state;
|
1486 |
|
|
|
1487 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
1488 |
|
|
printk("Shutting down serial port %d (irq %d)....", info->line,
|
1489 |
|
|
state->irq);
|
1490 |
|
|
#endif
|
1491 |
|
|
|
1492 |
|
|
save_flags(flags); cli(); /* Disable interrupts */
|
1493 |
|
|
|
1494 |
|
|
/*
|
1495 |
|
|
* clear delta_msr_wait queue to avoid mem leaks: we may free the irq
|
1496 |
|
|
* here so the queue might never be waken up
|
1497 |
|
|
*/
|
1498 |
|
|
wake_up_interruptible(&info->delta_msr_wait);
|
1499 |
|
|
|
1500 |
|
|
/*
|
1501 |
|
|
* First unlink the serial port from the IRQ chain...
|
1502 |
|
|
*/
|
1503 |
|
|
if (info->next_port)
|
1504 |
|
|
info->next_port->prev_port = info->prev_port;
|
1505 |
|
|
if (info->prev_port)
|
1506 |
|
|
info->prev_port->next_port = info->next_port;
|
1507 |
|
|
else
|
1508 |
|
|
IRQ_ports[state->irq] = info->next_port;
|
1509 |
|
|
figure_IRQ_timeout(state->irq);
|
1510 |
|
|
|
1511 |
|
|
/*
|
1512 |
|
|
* Free the IRQ, if necessary
|
1513 |
|
|
*/
|
1514 |
|
|
if (state->irq && (!IRQ_ports[state->irq] ||
|
1515 |
|
|
!IRQ_ports[state->irq]->next_port)) {
|
1516 |
|
|
if (IRQ_ports[state->irq]) {
|
1517 |
|
|
free_irq(state->irq, &IRQ_ports[state->irq]);
|
1518 |
|
|
retval = request_irq(state->irq, rs_interrupt_single,
|
1519 |
|
|
SA_SHIRQ, "serial",
|
1520 |
|
|
&IRQ_ports[state->irq]);
|
1521 |
|
|
|
1522 |
|
|
if (retval)
|
1523 |
|
|
printk("serial shutdown: request_irq: error %d"
|
1524 |
|
|
" Couldn't reacquire IRQ.\n", retval);
|
1525 |
|
|
} else
|
1526 |
|
|
free_irq(state->irq, &IRQ_ports[state->irq]);
|
1527 |
|
|
}
|
1528 |
|
|
|
1529 |
|
|
if (info->xmit.buf) {
|
1530 |
|
|
unsigned long pg = (unsigned long) info->xmit.buf;
|
1531 |
|
|
info->xmit.buf = 0;
|
1532 |
|
|
free_page(pg);
|
1533 |
|
|
}
|
1534 |
|
|
|
1535 |
|
|
info->IER = 0;
|
1536 |
|
|
serial_outp(info, UART_IER, 0x00); /* disable all intrs */
|
1537 |
|
|
#ifdef CONFIG_SERIAL_MANY_PORTS
|
1538 |
|
|
if (info->flags & ASYNC_FOURPORT) {
|
1539 |
|
|
/* reset interrupts on the AST Fourport board */
|
1540 |
|
|
(void) inb((info->port & 0xFE0) | 0x01F);
|
1541 |
|
|
info->MCR |= UART_MCR_OUT1;
|
1542 |
|
|
} else
|
1543 |
|
|
#endif
|
1544 |
|
|
info->MCR &= ~UART_MCR_OUT2;
|
1545 |
|
|
info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */
|
1546 |
|
|
|
1547 |
|
|
/* disable break condition */
|
1548 |
|
|
serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
|
1549 |
|
|
|
1550 |
|
|
if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
|
1551 |
|
|
info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
|
1552 |
|
|
serial_outp(info, UART_MCR, info->MCR);
|
1553 |
|
|
|
1554 |
|
|
/* disable FIFO's */
|
1555 |
|
|
serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
|
1556 |
|
|
UART_FCR_CLEAR_RCVR |
|
1557 |
|
|
UART_FCR_CLEAR_XMIT));
|
1558 |
|
|
serial_outp(info, UART_FCR, 0);
|
1559 |
|
|
|
1560 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
1561 |
|
|
/*
|
1562 |
|
|
* Reset the RSA board back to 115kbps compat mode.
|
1563 |
|
|
*/
|
1564 |
|
|
if ((state->type == PORT_RSA) &&
|
1565 |
|
|
(state->baud_base == SERIAL_RSA_BAUD_BASE &&
|
1566 |
|
|
disable_rsa(info)))
|
1567 |
|
|
state->baud_base = SERIAL_RSA_BAUD_BASE_LO;
|
1568 |
|
|
#endif
|
1569 |
|
|
|
1570 |
|
|
|
1571 |
|
|
(void)serial_in(info, UART_RX); /* read data port to reset things */
|
1572 |
|
|
|
1573 |
|
|
if (info->tty)
|
1574 |
|
|
set_bit(TTY_IO_ERROR, &info->tty->flags);
|
1575 |
|
|
|
1576 |
|
|
if (uart_config[info->state->type].flags & UART_STARTECH) {
|
1577 |
|
|
/* Arrange to enter sleep mode */
|
1578 |
|
|
serial_outp(info, UART_LCR, 0xBF);
|
1579 |
|
|
serial_outp(info, UART_EFR, UART_EFR_ECB);
|
1580 |
|
|
serial_outp(info, UART_LCR, 0);
|
1581 |
|
|
serial_outp(info, UART_IER, UART_IERX_SLEEP);
|
1582 |
|
|
serial_outp(info, UART_LCR, 0xBF);
|
1583 |
|
|
serial_outp(info, UART_EFR, 0);
|
1584 |
|
|
serial_outp(info, UART_LCR, 0);
|
1585 |
|
|
}
|
1586 |
|
|
if (info->state->type == PORT_16750) {
|
1587 |
|
|
/* Arrange to enter sleep mode */
|
1588 |
|
|
serial_outp(info, UART_IER, UART_IERX_SLEEP);
|
1589 |
|
|
}
|
1590 |
|
|
info->flags &= ~ASYNC_INITIALIZED;
|
1591 |
|
|
restore_flags(flags);
|
1592 |
|
|
}
|
1593 |
|
|
|
1594 |
|
|
#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
|
1595 |
|
|
static int baud_table[] = {
|
1596 |
|
|
0, 50, 75, 110, 134, 150, 200, 300,
|
1597 |
|
|
600, 1200, 1800, 2400, 4800, 9600, 19200,
|
1598 |
|
|
38400, 57600, 115200, 230400, 460800, 0 };
|
1599 |
|
|
|
1600 |
|
|
static int tty_get_baud_rate(struct tty_struct *tty)
|
1601 |
|
|
{
|
1602 |
|
|
struct async_struct * info = (struct async_struct *)tty->driver_data;
|
1603 |
|
|
unsigned int cflag, i;
|
1604 |
|
|
|
1605 |
|
|
cflag = tty->termios->c_cflag;
|
1606 |
|
|
|
1607 |
|
|
i = cflag & CBAUD;
|
1608 |
|
|
if (i & CBAUDEX) {
|
1609 |
|
|
i &= ~CBAUDEX;
|
1610 |
|
|
if (i < 1 || i > 2)
|
1611 |
|
|
tty->termios->c_cflag &= ~CBAUDEX;
|
1612 |
|
|
else
|
1613 |
|
|
i += 15;
|
1614 |
|
|
}
|
1615 |
|
|
if (i == 15) {
|
1616 |
|
|
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
|
1617 |
|
|
i += 1;
|
1618 |
|
|
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
|
1619 |
|
|
i += 2;
|
1620 |
|
|
}
|
1621 |
|
|
return baud_table[i];
|
1622 |
|
|
}
|
1623 |
|
|
#endif
|
1624 |
|
|
|
1625 |
|
|
/*
|
1626 |
|
|
* This routine is called to set the UART divisor registers to match
|
1627 |
|
|
* the specified baud rate for a serial port.
|
1628 |
|
|
*/
|
1629 |
|
|
static void change_speed(struct async_struct *info,
|
1630 |
|
|
struct termios *old_termios)
|
1631 |
|
|
{
|
1632 |
|
|
int quot = 0, baud_base, baud;
|
1633 |
|
|
unsigned cflag, cval, fcr = 0;
|
1634 |
|
|
int bits;
|
1635 |
|
|
unsigned long flags;
|
1636 |
|
|
|
1637 |
|
|
if (!info->tty || !info->tty->termios)
|
1638 |
|
|
return;
|
1639 |
|
|
cflag = info->tty->termios->c_cflag;
|
1640 |
|
|
if (!CONFIGURED_SERIAL_PORT(info))
|
1641 |
|
|
return;
|
1642 |
|
|
|
1643 |
|
|
/* byte size and parity */
|
1644 |
|
|
switch (cflag & CSIZE) {
|
1645 |
|
|
case CS5: cval = 0x00; bits = 7; break;
|
1646 |
|
|
case CS6: cval = 0x01; bits = 8; break;
|
1647 |
|
|
case CS7: cval = 0x02; bits = 9; break;
|
1648 |
|
|
case CS8: cval = 0x03; bits = 10; break;
|
1649 |
|
|
/* Never happens, but GCC is too dumb to figure it out */
|
1650 |
|
|
default: cval = 0x00; bits = 7; break;
|
1651 |
|
|
}
|
1652 |
|
|
if (cflag & CSTOPB) {
|
1653 |
|
|
cval |= 0x04;
|
1654 |
|
|
bits++;
|
1655 |
|
|
}
|
1656 |
|
|
if (cflag & PARENB) {
|
1657 |
|
|
cval |= UART_LCR_PARITY;
|
1658 |
|
|
bits++;
|
1659 |
|
|
}
|
1660 |
|
|
if (!(cflag & PARODD))
|
1661 |
|
|
cval |= UART_LCR_EPAR;
|
1662 |
|
|
#ifdef CMSPAR
|
1663 |
|
|
if (cflag & CMSPAR)
|
1664 |
|
|
cval |= UART_LCR_SPAR;
|
1665 |
|
|
#endif
|
1666 |
|
|
|
1667 |
|
|
/* Determine divisor based on baud rate */
|
1668 |
|
|
baud = tty_get_baud_rate(info->tty);
|
1669 |
|
|
if (!baud)
|
1670 |
|
|
baud = 9600; /* B0 transition handled in rs_set_termios */
|
1671 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
1672 |
|
|
if ((info->state->type == PORT_RSA) &&
|
1673 |
|
|
(info->state->baud_base != SERIAL_RSA_BAUD_BASE) &&
|
1674 |
|
|
enable_rsa(info))
|
1675 |
|
|
info->state->baud_base = SERIAL_RSA_BAUD_BASE;
|
1676 |
|
|
#endif
|
1677 |
|
|
baud_base = info->state->baud_base;
|
1678 |
|
|
if (info->state->type == PORT_16C950) {
|
1679 |
|
|
if (baud <= baud_base)
|
1680 |
|
|
serial_icr_write(info, UART_TCR, 0);
|
1681 |
|
|
else if (baud <= 2*baud_base) {
|
1682 |
|
|
serial_icr_write(info, UART_TCR, 0x8);
|
1683 |
|
|
baud_base = baud_base * 2;
|
1684 |
|
|
} else if (baud <= 4*baud_base) {
|
1685 |
|
|
serial_icr_write(info, UART_TCR, 0x4);
|
1686 |
|
|
baud_base = baud_base * 4;
|
1687 |
|
|
} else
|
1688 |
|
|
serial_icr_write(info, UART_TCR, 0);
|
1689 |
|
|
}
|
1690 |
|
|
if (baud == 38400 &&
|
1691 |
|
|
((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
|
1692 |
|
|
quot = info->state->custom_divisor;
|
1693 |
|
|
else {
|
1694 |
|
|
if (baud == 134)
|
1695 |
|
|
/* Special case since 134 is really 134.5 */
|
1696 |
|
|
quot = (2*baud_base / 269);
|
1697 |
|
|
else if (baud)
|
1698 |
|
|
quot = baud_base / baud;
|
1699 |
|
|
}
|
1700 |
|
|
/* If the quotient is zero refuse the change */
|
1701 |
|
|
if (!quot && old_termios) {
|
1702 |
|
|
info->tty->termios->c_cflag &= ~CBAUD;
|
1703 |
|
|
info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
|
1704 |
|
|
baud = tty_get_baud_rate(info->tty);
|
1705 |
|
|
if (!baud)
|
1706 |
|
|
baud = 9600;
|
1707 |
|
|
if (baud == 38400 &&
|
1708 |
|
|
((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
|
1709 |
|
|
quot = info->state->custom_divisor;
|
1710 |
|
|
else {
|
1711 |
|
|
if (baud == 134)
|
1712 |
|
|
/* Special case since 134 is really 134.5 */
|
1713 |
|
|
quot = (2*baud_base / 269);
|
1714 |
|
|
else if (baud)
|
1715 |
|
|
quot = baud_base / baud;
|
1716 |
|
|
}
|
1717 |
|
|
}
|
1718 |
|
|
/* As a last resort, if the quotient is zero, default to 9600 bps */
|
1719 |
|
|
if (!quot)
|
1720 |
|
|
quot = baud_base / 9600;
|
1721 |
|
|
/*
|
1722 |
|
|
* Work around a bug in the Oxford Semiconductor 952 rev B
|
1723 |
|
|
* chip which causes it to seriously miscalculate baud rates
|
1724 |
|
|
* when DLL is 0.
|
1725 |
|
|
*/
|
1726 |
|
|
if (((quot & 0xFF) == 0) && (info->state->type == PORT_16C950) &&
|
1727 |
|
|
(info->state->revision == 0x5201))
|
1728 |
|
|
quot++;
|
1729 |
|
|
|
1730 |
|
|
info->quot = quot;
|
1731 |
|
|
info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
|
1732 |
|
|
info->timeout += HZ/50; /* Add .02 seconds of slop */
|
1733 |
|
|
|
1734 |
|
|
/* Set up FIFO's */
|
1735 |
|
|
if (uart_config[info->state->type].flags & UART_USE_FIFO) {
|
1736 |
|
|
if ((info->state->baud_base / quot) < 2400)
|
1737 |
|
|
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
|
1738 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
1739 |
|
|
else if (info->state->type == PORT_RSA)
|
1740 |
|
|
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
|
1741 |
|
|
#endif
|
1742 |
|
|
else
|
1743 |
|
|
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
|
1744 |
|
|
}
|
1745 |
|
|
if (info->state->type == PORT_16750)
|
1746 |
|
|
fcr |= UART_FCR7_64BYTE;
|
1747 |
|
|
|
1748 |
|
|
/* CTS flow control flag and modem status interrupts */
|
1749 |
|
|
info->IER &= ~UART_IER_MSI;
|
1750 |
|
|
if (info->flags & ASYNC_HARDPPS_CD)
|
1751 |
|
|
info->IER |= UART_IER_MSI;
|
1752 |
|
|
if (cflag & CRTSCTS) {
|
1753 |
|
|
info->flags |= ASYNC_CTS_FLOW;
|
1754 |
|
|
info->IER |= UART_IER_MSI;
|
1755 |
|
|
} else
|
1756 |
|
|
info->flags &= ~ASYNC_CTS_FLOW;
|
1757 |
|
|
if (cflag & CLOCAL)
|
1758 |
|
|
info->flags &= ~ASYNC_CHECK_CD;
|
1759 |
|
|
else {
|
1760 |
|
|
info->flags |= ASYNC_CHECK_CD;
|
1761 |
|
|
info->IER |= UART_IER_MSI;
|
1762 |
|
|
}
|
1763 |
|
|
serial_out(info, UART_IER, info->IER);
|
1764 |
|
|
|
1765 |
|
|
/*
|
1766 |
|
|
* Set up parity check flag
|
1767 |
|
|
*/
|
1768 |
|
|
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
|
1769 |
|
|
|
1770 |
|
|
info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
|
1771 |
|
|
if (I_INPCK(info->tty))
|
1772 |
|
|
info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
|
1773 |
|
|
if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
|
1774 |
|
|
info->read_status_mask |= UART_LSR_BI;
|
1775 |
|
|
|
1776 |
|
|
/*
|
1777 |
|
|
* Characters to ignore
|
1778 |
|
|
*/
|
1779 |
|
|
info->ignore_status_mask = 0;
|
1780 |
|
|
if (I_IGNPAR(info->tty))
|
1781 |
|
|
info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
|
1782 |
|
|
if (I_IGNBRK(info->tty)) {
|
1783 |
|
|
info->ignore_status_mask |= UART_LSR_BI;
|
1784 |
|
|
/*
|
1785 |
|
|
* If we're ignore parity and break indicators, ignore
|
1786 |
|
|
* overruns too. (For real raw support).
|
1787 |
|
|
*/
|
1788 |
|
|
if (I_IGNPAR(info->tty))
|
1789 |
|
|
info->ignore_status_mask |= UART_LSR_OE;
|
1790 |
|
|
}
|
1791 |
|
|
/*
|
1792 |
|
|
* !!! ignore all characters if CREAD is not set
|
1793 |
|
|
*/
|
1794 |
|
|
if ((cflag & CREAD) == 0)
|
1795 |
|
|
info->ignore_status_mask |= UART_LSR_DR;
|
1796 |
|
|
save_flags(flags); cli();
|
1797 |
|
|
if (uart_config[info->state->type].flags & UART_STARTECH) {
|
1798 |
|
|
serial_outp(info, UART_LCR, 0xBF);
|
1799 |
|
|
serial_outp(info, UART_EFR,
|
1800 |
|
|
(cflag & CRTSCTS) ? UART_EFR_CTS : 0);
|
1801 |
|
|
}
|
1802 |
|
|
serial_outp(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
|
1803 |
|
|
serial_outp(info, UART_DLL, quot & 0xff); /* LS of divisor */
|
1804 |
|
|
serial_outp(info, UART_DLM, quot >> 8); /* MS of divisor */
|
1805 |
|
|
if (info->state->type == PORT_16750)
|
1806 |
|
|
serial_outp(info, UART_FCR, fcr); /* set fcr */
|
1807 |
|
|
serial_outp(info, UART_LCR, cval); /* reset DLAB */
|
1808 |
|
|
info->LCR = cval; /* Save LCR */
|
1809 |
|
|
if (info->state->type != PORT_16750) {
|
1810 |
|
|
if (fcr & UART_FCR_ENABLE_FIFO) {
|
1811 |
|
|
/* emulated UARTs (Lucent Venus 167x) need two steps */
|
1812 |
|
|
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
|
1813 |
|
|
}
|
1814 |
|
|
serial_outp(info, UART_FCR, fcr); /* set fcr */
|
1815 |
|
|
}
|
1816 |
|
|
restore_flags(flags);
|
1817 |
|
|
}
|
1818 |
|
|
|
1819 |
|
|
static void rs_put_char(struct tty_struct *tty, unsigned char ch)
|
1820 |
|
|
{
|
1821 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
1822 |
|
|
unsigned long flags;
|
1823 |
|
|
|
1824 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_put_char"))
|
1825 |
|
|
return;
|
1826 |
|
|
|
1827 |
|
|
if (!tty || !info->xmit.buf)
|
1828 |
|
|
return;
|
1829 |
|
|
|
1830 |
|
|
save_flags(flags); cli();
|
1831 |
|
|
if (CIRC_SPACE(info->xmit.head,
|
1832 |
|
|
info->xmit.tail,
|
1833 |
|
|
SERIAL_XMIT_SIZE) == 0) {
|
1834 |
|
|
restore_flags(flags);
|
1835 |
|
|
return;
|
1836 |
|
|
}
|
1837 |
|
|
|
1838 |
|
|
info->xmit.buf[info->xmit.head] = ch;
|
1839 |
|
|
info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
|
1840 |
|
|
restore_flags(flags);
|
1841 |
|
|
}
|
1842 |
|
|
|
1843 |
|
|
static void rs_flush_chars(struct tty_struct *tty)
|
1844 |
|
|
{
|
1845 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
1846 |
|
|
unsigned long flags;
|
1847 |
|
|
|
1848 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
|
1849 |
|
|
return;
|
1850 |
|
|
|
1851 |
|
|
if (info->xmit.head == info->xmit.tail
|
1852 |
|
|
|| tty->stopped
|
1853 |
|
|
|| tty->hw_stopped
|
1854 |
|
|
|| !info->xmit.buf)
|
1855 |
|
|
return;
|
1856 |
|
|
|
1857 |
|
|
save_flags(flags); cli();
|
1858 |
|
|
info->IER |= UART_IER_THRI;
|
1859 |
|
|
serial_out(info, UART_IER, info->IER);
|
1860 |
|
|
restore_flags(flags);
|
1861 |
|
|
}
|
1862 |
|
|
|
1863 |
|
|
static int rs_write(struct tty_struct * tty, int from_user,
|
1864 |
|
|
const unsigned char *buf, int count)
|
1865 |
|
|
{
|
1866 |
|
|
int c, ret = 0;
|
1867 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
1868 |
|
|
unsigned long flags;
|
1869 |
|
|
|
1870 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_write"))
|
1871 |
|
|
return 0;
|
1872 |
|
|
|
1873 |
|
|
if (!tty || !info->xmit.buf || !tmp_buf)
|
1874 |
|
|
return 0;
|
1875 |
|
|
|
1876 |
|
|
save_flags(flags);
|
1877 |
|
|
if (from_user) {
|
1878 |
|
|
down(&tmp_buf_sem);
|
1879 |
|
|
while (1) {
|
1880 |
|
|
int c1;
|
1881 |
|
|
c = CIRC_SPACE_TO_END(info->xmit.head,
|
1882 |
|
|
info->xmit.tail,
|
1883 |
|
|
SERIAL_XMIT_SIZE);
|
1884 |
|
|
if (count < c)
|
1885 |
|
|
c = count;
|
1886 |
|
|
if (c <= 0)
|
1887 |
|
|
break;
|
1888 |
|
|
|
1889 |
|
|
c -= copy_from_user(tmp_buf, buf, c);
|
1890 |
|
|
if (!c) {
|
1891 |
|
|
if (!ret)
|
1892 |
|
|
ret = -EFAULT;
|
1893 |
|
|
break;
|
1894 |
|
|
}
|
1895 |
|
|
cli();
|
1896 |
|
|
c1 = CIRC_SPACE_TO_END(info->xmit.head,
|
1897 |
|
|
info->xmit.tail,
|
1898 |
|
|
SERIAL_XMIT_SIZE);
|
1899 |
|
|
if (c1 < c)
|
1900 |
|
|
c = c1;
|
1901 |
|
|
memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
|
1902 |
|
|
info->xmit.head = ((info->xmit.head + c) &
|
1903 |
|
|
(SERIAL_XMIT_SIZE-1));
|
1904 |
|
|
restore_flags(flags);
|
1905 |
|
|
buf += c;
|
1906 |
|
|
count -= c;
|
1907 |
|
|
ret += c;
|
1908 |
|
|
}
|
1909 |
|
|
up(&tmp_buf_sem);
|
1910 |
|
|
} else {
|
1911 |
|
|
cli();
|
1912 |
|
|
while (1) {
|
1913 |
|
|
c = CIRC_SPACE_TO_END(info->xmit.head,
|
1914 |
|
|
info->xmit.tail,
|
1915 |
|
|
SERIAL_XMIT_SIZE);
|
1916 |
|
|
if (count < c)
|
1917 |
|
|
c = count;
|
1918 |
|
|
if (c <= 0) {
|
1919 |
|
|
break;
|
1920 |
|
|
}
|
1921 |
|
|
memcpy(info->xmit.buf + info->xmit.head, buf, c);
|
1922 |
|
|
info->xmit.head = ((info->xmit.head + c) &
|
1923 |
|
|
(SERIAL_XMIT_SIZE-1));
|
1924 |
|
|
buf += c;
|
1925 |
|
|
count -= c;
|
1926 |
|
|
ret += c;
|
1927 |
|
|
}
|
1928 |
|
|
restore_flags(flags);
|
1929 |
|
|
}
|
1930 |
|
|
if (info->xmit.head != info->xmit.tail
|
1931 |
|
|
&& !tty->stopped
|
1932 |
|
|
&& !tty->hw_stopped
|
1933 |
|
|
&& !(info->IER & UART_IER_THRI)) {
|
1934 |
|
|
info->IER |= UART_IER_THRI;
|
1935 |
|
|
serial_out(info, UART_IER, info->IER);
|
1936 |
|
|
}
|
1937 |
|
|
return ret;
|
1938 |
|
|
}
|
1939 |
|
|
|
1940 |
|
|
static int rs_write_room(struct tty_struct *tty)
|
1941 |
|
|
{
|
1942 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
1943 |
|
|
|
1944 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_write_room"))
|
1945 |
|
|
return 0;
|
1946 |
|
|
return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
|
1947 |
|
|
}
|
1948 |
|
|
|
1949 |
|
|
static int rs_chars_in_buffer(struct tty_struct *tty)
|
1950 |
|
|
{
|
1951 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
1952 |
|
|
|
1953 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
|
1954 |
|
|
return 0;
|
1955 |
|
|
return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
|
1956 |
|
|
}
|
1957 |
|
|
|
1958 |
|
|
static void rs_flush_buffer(struct tty_struct *tty)
|
1959 |
|
|
{
|
1960 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
1961 |
|
|
unsigned long flags;
|
1962 |
|
|
|
1963 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
|
1964 |
|
|
return;
|
1965 |
|
|
save_flags(flags); cli();
|
1966 |
|
|
info->xmit.head = info->xmit.tail = 0;
|
1967 |
|
|
restore_flags(flags);
|
1968 |
|
|
wake_up_interruptible(&tty->write_wait);
|
1969 |
|
|
#ifdef SERIAL_HAVE_POLL_WAIT
|
1970 |
|
|
wake_up_interruptible(&tty->poll_wait);
|
1971 |
|
|
#endif
|
1972 |
|
|
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
|
1973 |
|
|
tty->ldisc.write_wakeup)
|
1974 |
|
|
(tty->ldisc.write_wakeup)(tty);
|
1975 |
|
|
}
|
1976 |
|
|
|
1977 |
|
|
/*
|
1978 |
|
|
* This function is used to send a high-priority XON/XOFF character to
|
1979 |
|
|
* the device
|
1980 |
|
|
*/
|
1981 |
|
|
static void rs_send_xchar(struct tty_struct *tty, char ch)
|
1982 |
|
|
{
|
1983 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
1984 |
|
|
|
1985 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_send_char"))
|
1986 |
|
|
return;
|
1987 |
|
|
|
1988 |
|
|
info->x_char = ch;
|
1989 |
|
|
if (ch) {
|
1990 |
|
|
/* Make sure transmit interrupts are on */
|
1991 |
|
|
info->IER |= UART_IER_THRI;
|
1992 |
|
|
serial_out(info, UART_IER, info->IER);
|
1993 |
|
|
}
|
1994 |
|
|
}
|
1995 |
|
|
|
1996 |
|
|
/*
|
1997 |
|
|
* ------------------------------------------------------------
|
1998 |
|
|
* rs_throttle()
|
1999 |
|
|
*
|
2000 |
|
|
* This routine is called by the upper-layer tty layer to signal that
|
2001 |
|
|
* incoming characters should be throttled.
|
2002 |
|
|
* ------------------------------------------------------------
|
2003 |
|
|
*/
|
2004 |
|
|
static void rs_throttle(struct tty_struct * tty)
|
2005 |
|
|
{
|
2006 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
2007 |
|
|
unsigned long flags;
|
2008 |
|
|
#ifdef SERIAL_DEBUG_THROTTLE
|
2009 |
|
|
char buf[64];
|
2010 |
|
|
|
2011 |
|
|
printk("throttle %s: %d....\n", tty_name(tty, buf),
|
2012 |
|
|
tty->ldisc.chars_in_buffer(tty));
|
2013 |
|
|
#endif
|
2014 |
|
|
|
2015 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_throttle"))
|
2016 |
|
|
return;
|
2017 |
|
|
|
2018 |
|
|
if (I_IXOFF(tty))
|
2019 |
|
|
rs_send_xchar(tty, STOP_CHAR(tty));
|
2020 |
|
|
|
2021 |
|
|
if (tty->termios->c_cflag & CRTSCTS)
|
2022 |
|
|
info->MCR &= ~UART_MCR_RTS;
|
2023 |
|
|
|
2024 |
|
|
save_flags(flags); cli();
|
2025 |
|
|
serial_out(info, UART_MCR, info->MCR);
|
2026 |
|
|
restore_flags(flags);
|
2027 |
|
|
}
|
2028 |
|
|
|
2029 |
|
|
static void rs_unthrottle(struct tty_struct * tty)
|
2030 |
|
|
{
|
2031 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
2032 |
|
|
unsigned long flags;
|
2033 |
|
|
#ifdef SERIAL_DEBUG_THROTTLE
|
2034 |
|
|
char buf[64];
|
2035 |
|
|
|
2036 |
|
|
printk("unthrottle %s: %d....\n", tty_name(tty, buf),
|
2037 |
|
|
tty->ldisc.chars_in_buffer(tty));
|
2038 |
|
|
#endif
|
2039 |
|
|
|
2040 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
|
2041 |
|
|
return;
|
2042 |
|
|
|
2043 |
|
|
if (I_IXOFF(tty)) {
|
2044 |
|
|
if (info->x_char)
|
2045 |
|
|
info->x_char = 0;
|
2046 |
|
|
else
|
2047 |
|
|
rs_send_xchar(tty, START_CHAR(tty));
|
2048 |
|
|
}
|
2049 |
|
|
if (tty->termios->c_cflag & CRTSCTS)
|
2050 |
|
|
info->MCR |= UART_MCR_RTS;
|
2051 |
|
|
save_flags(flags); cli();
|
2052 |
|
|
serial_out(info, UART_MCR, info->MCR);
|
2053 |
|
|
restore_flags(flags);
|
2054 |
|
|
}
|
2055 |
|
|
|
2056 |
|
|
/*
|
2057 |
|
|
* ------------------------------------------------------------
|
2058 |
|
|
* rs_ioctl() and friends
|
2059 |
|
|
* ------------------------------------------------------------
|
2060 |
|
|
*/
|
2061 |
|
|
|
2062 |
|
|
static int get_serial_info(struct async_struct * info,
|
2063 |
|
|
struct serial_struct * retinfo)
|
2064 |
|
|
{
|
2065 |
|
|
struct serial_struct tmp;
|
2066 |
|
|
struct serial_state *state = info->state;
|
2067 |
|
|
|
2068 |
|
|
if (!retinfo)
|
2069 |
|
|
return -EFAULT;
|
2070 |
|
|
memset(&tmp, 0, sizeof(tmp));
|
2071 |
|
|
tmp.type = state->type;
|
2072 |
|
|
tmp.line = state->line;
|
2073 |
|
|
tmp.port = state->port;
|
2074 |
|
|
if (HIGH_BITS_OFFSET)
|
2075 |
|
|
tmp.port_high = state->port >> HIGH_BITS_OFFSET;
|
2076 |
|
|
else
|
2077 |
|
|
tmp.port_high = 0;
|
2078 |
|
|
tmp.irq = state->irq;
|
2079 |
|
|
tmp.flags = state->flags;
|
2080 |
|
|
tmp.xmit_fifo_size = state->xmit_fifo_size;
|
2081 |
|
|
tmp.baud_base = state->baud_base;
|
2082 |
|
|
tmp.close_delay = state->close_delay;
|
2083 |
|
|
tmp.closing_wait = state->closing_wait;
|
2084 |
|
|
tmp.custom_divisor = state->custom_divisor;
|
2085 |
|
|
tmp.hub6 = state->hub6;
|
2086 |
|
|
tmp.io_type = state->io_type;
|
2087 |
|
|
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
|
2088 |
|
|
return -EFAULT;
|
2089 |
|
|
return 0;
|
2090 |
|
|
}
|
2091 |
|
|
|
2092 |
|
|
static int set_serial_info(struct async_struct * info,
|
2093 |
|
|
struct serial_struct * new_info)
|
2094 |
|
|
{
|
2095 |
|
|
struct serial_struct new_serial;
|
2096 |
|
|
struct serial_state old_state, *state;
|
2097 |
|
|
unsigned int i,change_irq,change_port;
|
2098 |
|
|
int retval = 0;
|
2099 |
|
|
unsigned long new_port;
|
2100 |
|
|
|
2101 |
|
|
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
|
2102 |
|
|
return -EFAULT;
|
2103 |
|
|
state = info->state;
|
2104 |
|
|
old_state = *state;
|
2105 |
|
|
|
2106 |
|
|
new_port = new_serial.port;
|
2107 |
|
|
if (HIGH_BITS_OFFSET)
|
2108 |
|
|
new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
|
2109 |
|
|
|
2110 |
|
|
change_irq = new_serial.irq != state->irq;
|
2111 |
|
|
change_port = (new_port != ((int) state->port)) ||
|
2112 |
|
|
(new_serial.hub6 != state->hub6);
|
2113 |
|
|
|
2114 |
|
|
if (!capable(CAP_SYS_ADMIN)) {
|
2115 |
|
|
if (change_irq || change_port ||
|
2116 |
|
|
(new_serial.baud_base != state->baud_base) ||
|
2117 |
|
|
(new_serial.type != state->type) ||
|
2118 |
|
|
(new_serial.close_delay != state->close_delay) ||
|
2119 |
|
|
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
|
2120 |
|
|
((new_serial.flags & ~ASYNC_USR_MASK) !=
|
2121 |
|
|
(state->flags & ~ASYNC_USR_MASK)))
|
2122 |
|
|
return -EPERM;
|
2123 |
|
|
state->flags = ((state->flags & ~ASYNC_USR_MASK) |
|
2124 |
|
|
(new_serial.flags & ASYNC_USR_MASK));
|
2125 |
|
|
info->flags = ((info->flags & ~ASYNC_USR_MASK) |
|
2126 |
|
|
(new_serial.flags & ASYNC_USR_MASK));
|
2127 |
|
|
state->custom_divisor = new_serial.custom_divisor;
|
2128 |
|
|
goto check_and_exit;
|
2129 |
|
|
}
|
2130 |
|
|
|
2131 |
|
|
new_serial.irq = irq_cannonicalize(new_serial.irq);
|
2132 |
|
|
|
2133 |
|
|
if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
|
2134 |
|
|
(new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) ||
|
2135 |
|
|
(new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) ||
|
2136 |
|
|
(new_serial.type == PORT_STARTECH)) {
|
2137 |
|
|
return -EINVAL;
|
2138 |
|
|
}
|
2139 |
|
|
|
2140 |
|
|
if ((new_serial.type != state->type) ||
|
2141 |
|
|
(new_serial.xmit_fifo_size <= 0))
|
2142 |
|
|
new_serial.xmit_fifo_size =
|
2143 |
|
|
uart_config[new_serial.type].dfl_xmit_fifo_size;
|
2144 |
|
|
|
2145 |
|
|
/* Make sure address is not already in use */
|
2146 |
|
|
if (new_serial.type) {
|
2147 |
|
|
for (i = 0 ; i < NR_PORTS; i++)
|
2148 |
|
|
if ((state != &rs_table[i]) &&
|
2149 |
|
|
(rs_table[i].io_type == SERIAL_IO_PORT) &&
|
2150 |
|
|
(rs_table[i].port == new_port) &&
|
2151 |
|
|
rs_table[i].type)
|
2152 |
|
|
return -EADDRINUSE;
|
2153 |
|
|
}
|
2154 |
|
|
|
2155 |
|
|
if ((change_port || change_irq) && (state->count > 1))
|
2156 |
|
|
return -EBUSY;
|
2157 |
|
|
|
2158 |
|
|
/*
|
2159 |
|
|
* OK, past this point, all the error checking has been done.
|
2160 |
|
|
* At this point, we start making changes.....
|
2161 |
|
|
*/
|
2162 |
|
|
|
2163 |
|
|
state->baud_base = new_serial.baud_base;
|
2164 |
|
|
state->flags = ((state->flags & ~ASYNC_FLAGS) |
|
2165 |
|
|
(new_serial.flags & ASYNC_FLAGS));
|
2166 |
|
|
info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
|
2167 |
|
|
(info->flags & ASYNC_INTERNAL_FLAGS));
|
2168 |
|
|
state->custom_divisor = new_serial.custom_divisor;
|
2169 |
|
|
state->close_delay = new_serial.close_delay * HZ/100;
|
2170 |
|
|
state->closing_wait = new_serial.closing_wait * HZ/100;
|
2171 |
|
|
#if (LINUX_VERSION_CODE > 0x20100)
|
2172 |
|
|
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
2173 |
|
|
#endif
|
2174 |
|
|
info->xmit_fifo_size = state->xmit_fifo_size =
|
2175 |
|
|
new_serial.xmit_fifo_size;
|
2176 |
|
|
|
2177 |
|
|
if ((state->type != PORT_UNKNOWN) && state->port) {
|
2178 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
2179 |
|
|
if (old_state.type == PORT_RSA)
|
2180 |
|
|
release_region(state->port + UART_RSA_BASE, 16);
|
2181 |
|
|
else
|
2182 |
|
|
#endif
|
2183 |
|
|
release_region(state->port,8);
|
2184 |
|
|
}
|
2185 |
|
|
state->type = new_serial.type;
|
2186 |
|
|
if (change_port || change_irq) {
|
2187 |
|
|
/*
|
2188 |
|
|
* We need to shutdown the serial port at the old
|
2189 |
|
|
* port/irq combination.
|
2190 |
|
|
*/
|
2191 |
|
|
shutdown(info);
|
2192 |
|
|
state->irq = new_serial.irq;
|
2193 |
|
|
info->port = state->port = new_port;
|
2194 |
|
|
info->hub6 = state->hub6 = new_serial.hub6;
|
2195 |
|
|
if (info->hub6)
|
2196 |
|
|
info->io_type = state->io_type = SERIAL_IO_HUB6;
|
2197 |
|
|
else if (info->io_type == SERIAL_IO_HUB6)
|
2198 |
|
|
info->io_type = state->io_type = SERIAL_IO_PORT;
|
2199 |
|
|
}
|
2200 |
|
|
if ((state->type != PORT_UNKNOWN) && state->port) {
|
2201 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
2202 |
|
|
if (state->type == PORT_RSA)
|
2203 |
|
|
request_region(state->port + UART_RSA_BASE,
|
2204 |
|
|
16, "serial_rsa(set)");
|
2205 |
|
|
else
|
2206 |
|
|
#endif
|
2207 |
|
|
request_region(state->port,8,"serial(set)");
|
2208 |
|
|
}
|
2209 |
|
|
|
2210 |
|
|
|
2211 |
|
|
check_and_exit:
|
2212 |
|
|
if ((!state->port && !state->iomem_base) || !state->type)
|
2213 |
|
|
return 0;
|
2214 |
|
|
if (info->flags & ASYNC_INITIALIZED) {
|
2215 |
|
|
if (((old_state.flags & ASYNC_SPD_MASK) !=
|
2216 |
|
|
(state->flags & ASYNC_SPD_MASK)) ||
|
2217 |
|
|
(old_state.custom_divisor != state->custom_divisor)) {
|
2218 |
|
|
#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
|
2219 |
|
|
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
|
2220 |
|
|
info->tty->alt_speed = 57600;
|
2221 |
|
|
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
|
2222 |
|
|
info->tty->alt_speed = 115200;
|
2223 |
|
|
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
|
2224 |
|
|
info->tty->alt_speed = 230400;
|
2225 |
|
|
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
|
2226 |
|
|
info->tty->alt_speed = 460800;
|
2227 |
|
|
#endif
|
2228 |
|
|
change_speed(info, 0);
|
2229 |
|
|
}
|
2230 |
|
|
} else
|
2231 |
|
|
retval = startup(info);
|
2232 |
|
|
return retval;
|
2233 |
|
|
}
|
2234 |
|
|
|
2235 |
|
|
|
2236 |
|
|
/*
|
2237 |
|
|
* get_lsr_info - get line status register info
|
2238 |
|
|
*
|
2239 |
|
|
* Purpose: Let user call ioctl() to get info when the UART physically
|
2240 |
|
|
* is emptied. On bus types like RS485, the transmitter must
|
2241 |
|
|
* release the bus after transmitting. This must be done when
|
2242 |
|
|
* the transmit shift register is empty, not be done when the
|
2243 |
|
|
* transmit holding register is empty. This functionality
|
2244 |
|
|
* allows an RS485 driver to be written in user space.
|
2245 |
|
|
*/
|
2246 |
|
|
static int get_lsr_info(struct async_struct * info, unsigned int *value)
|
2247 |
|
|
{
|
2248 |
|
|
unsigned char status;
|
2249 |
|
|
unsigned int result;
|
2250 |
|
|
unsigned long flags;
|
2251 |
|
|
|
2252 |
|
|
save_flags(flags); cli();
|
2253 |
|
|
status = serial_in(info, UART_LSR);
|
2254 |
|
|
restore_flags(flags);
|
2255 |
|
|
result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
|
2256 |
|
|
|
2257 |
|
|
/*
|
2258 |
|
|
* If we're about to load something into the transmit
|
2259 |
|
|
* register, we'll pretend the transmitter isn't empty to
|
2260 |
|
|
* avoid a race condition (depending on when the transmit
|
2261 |
|
|
* interrupt happens).
|
2262 |
|
|
*/
|
2263 |
|
|
if (info->x_char ||
|
2264 |
|
|
((CIRC_CNT(info->xmit.head, info->xmit.tail,
|
2265 |
|
|
SERIAL_XMIT_SIZE) > 0) &&
|
2266 |
|
|
!info->tty->stopped && !info->tty->hw_stopped))
|
2267 |
|
|
result &= ~TIOCSER_TEMT;
|
2268 |
|
|
|
2269 |
|
|
if (copy_to_user(value, &result, sizeof(int)))
|
2270 |
|
|
return -EFAULT;
|
2271 |
|
|
return 0;
|
2272 |
|
|
}
|
2273 |
|
|
|
2274 |
|
|
|
2275 |
|
|
static int get_modem_info(struct async_struct * info, unsigned int *value)
|
2276 |
|
|
{
|
2277 |
|
|
unsigned char control, status;
|
2278 |
|
|
unsigned int result;
|
2279 |
|
|
unsigned long flags;
|
2280 |
|
|
|
2281 |
|
|
control = info->MCR;
|
2282 |
|
|
save_flags(flags); cli();
|
2283 |
|
|
status = serial_in(info, UART_MSR);
|
2284 |
|
|
restore_flags(flags);
|
2285 |
|
|
result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
|
2286 |
|
|
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
|
2287 |
|
|
#ifdef TIOCM_OUT1
|
2288 |
|
|
| ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
|
2289 |
|
|
| ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
|
2290 |
|
|
#endif
|
2291 |
|
|
| ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
|
2292 |
|
|
| ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
|
2293 |
|
|
| ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
|
2294 |
|
|
| ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
|
2295 |
|
|
|
2296 |
|
|
if (copy_to_user(value, &result, sizeof(int)))
|
2297 |
|
|
return -EFAULT;
|
2298 |
|
|
return 0;
|
2299 |
|
|
}
|
2300 |
|
|
|
2301 |
|
|
static int set_modem_info(struct async_struct * info, unsigned int cmd,
|
2302 |
|
|
unsigned int *value)
|
2303 |
|
|
{
|
2304 |
|
|
unsigned int arg;
|
2305 |
|
|
unsigned long flags;
|
2306 |
|
|
|
2307 |
|
|
if (copy_from_user(&arg, value, sizeof(int)))
|
2308 |
|
|
return -EFAULT;
|
2309 |
|
|
|
2310 |
|
|
switch (cmd) {
|
2311 |
|
|
case TIOCMBIS:
|
2312 |
|
|
if (arg & TIOCM_RTS)
|
2313 |
|
|
info->MCR |= UART_MCR_RTS;
|
2314 |
|
|
if (arg & TIOCM_DTR)
|
2315 |
|
|
info->MCR |= UART_MCR_DTR;
|
2316 |
|
|
#ifdef TIOCM_OUT1
|
2317 |
|
|
if (arg & TIOCM_OUT1)
|
2318 |
|
|
info->MCR |= UART_MCR_OUT1;
|
2319 |
|
|
if (arg & TIOCM_OUT2)
|
2320 |
|
|
info->MCR |= UART_MCR_OUT2;
|
2321 |
|
|
#endif
|
2322 |
|
|
if (arg & TIOCM_LOOP)
|
2323 |
|
|
info->MCR |= UART_MCR_LOOP;
|
2324 |
|
|
break;
|
2325 |
|
|
case TIOCMBIC:
|
2326 |
|
|
if (arg & TIOCM_RTS)
|
2327 |
|
|
info->MCR &= ~UART_MCR_RTS;
|
2328 |
|
|
if (arg & TIOCM_DTR)
|
2329 |
|
|
info->MCR &= ~UART_MCR_DTR;
|
2330 |
|
|
#ifdef TIOCM_OUT1
|
2331 |
|
|
if (arg & TIOCM_OUT1)
|
2332 |
|
|
info->MCR &= ~UART_MCR_OUT1;
|
2333 |
|
|
if (arg & TIOCM_OUT2)
|
2334 |
|
|
info->MCR &= ~UART_MCR_OUT2;
|
2335 |
|
|
#endif
|
2336 |
|
|
if (arg & TIOCM_LOOP)
|
2337 |
|
|
info->MCR &= ~UART_MCR_LOOP;
|
2338 |
|
|
break;
|
2339 |
|
|
case TIOCMSET:
|
2340 |
|
|
info->MCR = ((info->MCR & ~(UART_MCR_RTS |
|
2341 |
|
|
#ifdef TIOCM_OUT1
|
2342 |
|
|
UART_MCR_OUT1 |
|
2343 |
|
|
UART_MCR_OUT2 |
|
2344 |
|
|
#endif
|
2345 |
|
|
UART_MCR_LOOP |
|
2346 |
|
|
UART_MCR_DTR))
|
2347 |
|
|
| ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
|
2348 |
|
|
#ifdef TIOCM_OUT1
|
2349 |
|
|
| ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
|
2350 |
|
|
| ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
|
2351 |
|
|
#endif
|
2352 |
|
|
| ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0)
|
2353 |
|
|
| ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
|
2354 |
|
|
break;
|
2355 |
|
|
default:
|
2356 |
|
|
return -EINVAL;
|
2357 |
|
|
}
|
2358 |
|
|
save_flags(flags); cli();
|
2359 |
|
|
info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */
|
2360 |
|
|
serial_out(info, UART_MCR, info->MCR);
|
2361 |
|
|
restore_flags(flags);
|
2362 |
|
|
return 0;
|
2363 |
|
|
}
|
2364 |
|
|
|
2365 |
|
|
static int do_autoconfig(struct async_struct * info)
|
2366 |
|
|
{
|
2367 |
|
|
int irq, retval;
|
2368 |
|
|
|
2369 |
|
|
if (!capable(CAP_SYS_ADMIN))
|
2370 |
|
|
return -EPERM;
|
2371 |
|
|
|
2372 |
|
|
if (info->state->count > 1)
|
2373 |
|
|
return -EBUSY;
|
2374 |
|
|
|
2375 |
|
|
shutdown(info);
|
2376 |
|
|
|
2377 |
|
|
autoconfig(info->state);
|
2378 |
|
|
if ((info->state->flags & ASYNC_AUTO_IRQ) &&
|
2379 |
|
|
(info->state->port != 0 || info->state->iomem_base != 0) &&
|
2380 |
|
|
(info->state->type != PORT_UNKNOWN)) {
|
2381 |
|
|
irq = detect_uart_irq(info->state);
|
2382 |
|
|
if (irq > 0)
|
2383 |
|
|
info->state->irq = irq;
|
2384 |
|
|
}
|
2385 |
|
|
|
2386 |
|
|
retval = startup(info);
|
2387 |
|
|
if (retval)
|
2388 |
|
|
return retval;
|
2389 |
|
|
return 0;
|
2390 |
|
|
}
|
2391 |
|
|
|
2392 |
|
|
/*
|
2393 |
|
|
* rs_break() --- routine which turns the break handling on or off
|
2394 |
|
|
*/
|
2395 |
|
|
#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
|
2396 |
|
|
static void send_break( struct async_struct * info, int duration)
|
2397 |
|
|
{
|
2398 |
|
|
if (!CONFIGURED_SERIAL_PORT(info))
|
2399 |
|
|
return;
|
2400 |
|
|
current->state = TASK_INTERRUPTIBLE;
|
2401 |
|
|
current->timeout = jiffies + duration;
|
2402 |
|
|
cli();
|
2403 |
|
|
info->LCR |= UART_LCR_SBC;
|
2404 |
|
|
serial_out(info, UART_LCR, info->LCR);
|
2405 |
|
|
schedule();
|
2406 |
|
|
info->LCR &= ~UART_LCR_SBC;
|
2407 |
|
|
serial_out(info, UART_LCR, info->LCR);
|
2408 |
|
|
sti();
|
2409 |
|
|
}
|
2410 |
|
|
#else
|
2411 |
|
|
static void rs_break(struct tty_struct *tty, int break_state)
|
2412 |
|
|
{
|
2413 |
|
|
struct async_struct * info = (struct async_struct *)tty->driver_data;
|
2414 |
|
|
unsigned long flags;
|
2415 |
|
|
|
2416 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_break"))
|
2417 |
|
|
return;
|
2418 |
|
|
|
2419 |
|
|
if (!CONFIGURED_SERIAL_PORT(info))
|
2420 |
|
|
return;
|
2421 |
|
|
save_flags(flags); cli();
|
2422 |
|
|
if (break_state == -1)
|
2423 |
|
|
info->LCR |= UART_LCR_SBC;
|
2424 |
|
|
else
|
2425 |
|
|
info->LCR &= ~UART_LCR_SBC;
|
2426 |
|
|
serial_out(info, UART_LCR, info->LCR);
|
2427 |
|
|
restore_flags(flags);
|
2428 |
|
|
}
|
2429 |
|
|
#endif
|
2430 |
|
|
|
2431 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
2432 |
|
|
static int get_multiport_struct(struct async_struct * info,
|
2433 |
|
|
struct serial_multiport_struct *retinfo)
|
2434 |
|
|
{
|
2435 |
|
|
struct serial_multiport_struct ret;
|
2436 |
|
|
struct rs_multiport_struct *multi;
|
2437 |
|
|
|
2438 |
|
|
multi = &rs_multiport[info->state->irq];
|
2439 |
|
|
|
2440 |
|
|
ret.port_monitor = multi->port_monitor;
|
2441 |
|
|
|
2442 |
|
|
ret.port1 = multi->port1;
|
2443 |
|
|
ret.mask1 = multi->mask1;
|
2444 |
|
|
ret.match1 = multi->match1;
|
2445 |
|
|
|
2446 |
|
|
ret.port2 = multi->port2;
|
2447 |
|
|
ret.mask2 = multi->mask2;
|
2448 |
|
|
ret.match2 = multi->match2;
|
2449 |
|
|
|
2450 |
|
|
ret.port3 = multi->port3;
|
2451 |
|
|
ret.mask3 = multi->mask3;
|
2452 |
|
|
ret.match3 = multi->match3;
|
2453 |
|
|
|
2454 |
|
|
ret.port4 = multi->port4;
|
2455 |
|
|
ret.mask4 = multi->mask4;
|
2456 |
|
|
ret.match4 = multi->match4;
|
2457 |
|
|
|
2458 |
|
|
ret.irq = info->state->irq;
|
2459 |
|
|
|
2460 |
|
|
if (copy_to_user(retinfo,&ret,sizeof(*retinfo)))
|
2461 |
|
|
return -EFAULT;
|
2462 |
|
|
return 0;
|
2463 |
|
|
}
|
2464 |
|
|
|
2465 |
|
|
static int set_multiport_struct(struct async_struct * info,
|
2466 |
|
|
struct serial_multiport_struct *in_multi)
|
2467 |
|
|
{
|
2468 |
|
|
struct serial_multiport_struct new_multi;
|
2469 |
|
|
struct rs_multiport_struct *multi;
|
2470 |
|
|
struct serial_state *state;
|
2471 |
|
|
int was_multi, now_multi;
|
2472 |
|
|
int retval;
|
2473 |
|
|
void (*handler)(int, void *, struct pt_regs *);
|
2474 |
|
|
|
2475 |
|
|
if (!capable(CAP_SYS_ADMIN))
|
2476 |
|
|
return -EPERM;
|
2477 |
|
|
state = info->state;
|
2478 |
|
|
|
2479 |
|
|
if (copy_from_user(&new_multi, in_multi,
|
2480 |
|
|
sizeof(struct serial_multiport_struct)))
|
2481 |
|
|
return -EFAULT;
|
2482 |
|
|
|
2483 |
|
|
if (new_multi.irq != state->irq || state->irq == 0 ||
|
2484 |
|
|
!IRQ_ports[state->irq])
|
2485 |
|
|
return -EINVAL;
|
2486 |
|
|
|
2487 |
|
|
multi = &rs_multiport[state->irq];
|
2488 |
|
|
was_multi = (multi->port1 != 0);
|
2489 |
|
|
|
2490 |
|
|
multi->port_monitor = new_multi.port_monitor;
|
2491 |
|
|
|
2492 |
|
|
if (multi->port1)
|
2493 |
|
|
release_region(multi->port1,1);
|
2494 |
|
|
multi->port1 = new_multi.port1;
|
2495 |
|
|
multi->mask1 = new_multi.mask1;
|
2496 |
|
|
multi->match1 = new_multi.match1;
|
2497 |
|
|
if (multi->port1)
|
2498 |
|
|
request_region(multi->port1,1,"serial(multiport1)");
|
2499 |
|
|
|
2500 |
|
|
if (multi->port2)
|
2501 |
|
|
release_region(multi->port2,1);
|
2502 |
|
|
multi->port2 = new_multi.port2;
|
2503 |
|
|
multi->mask2 = new_multi.mask2;
|
2504 |
|
|
multi->match2 = new_multi.match2;
|
2505 |
|
|
if (multi->port2)
|
2506 |
|
|
request_region(multi->port2,1,"serial(multiport2)");
|
2507 |
|
|
|
2508 |
|
|
if (multi->port3)
|
2509 |
|
|
release_region(multi->port3,1);
|
2510 |
|
|
multi->port3 = new_multi.port3;
|
2511 |
|
|
multi->mask3 = new_multi.mask3;
|
2512 |
|
|
multi->match3 = new_multi.match3;
|
2513 |
|
|
if (multi->port3)
|
2514 |
|
|
request_region(multi->port3,1,"serial(multiport3)");
|
2515 |
|
|
|
2516 |
|
|
if (multi->port4)
|
2517 |
|
|
release_region(multi->port4,1);
|
2518 |
|
|
multi->port4 = new_multi.port4;
|
2519 |
|
|
multi->mask4 = new_multi.mask4;
|
2520 |
|
|
multi->match4 = new_multi.match4;
|
2521 |
|
|
if (multi->port4)
|
2522 |
|
|
request_region(multi->port4,1,"serial(multiport4)");
|
2523 |
|
|
|
2524 |
|
|
now_multi = (multi->port1 != 0);
|
2525 |
|
|
|
2526 |
|
|
if (IRQ_ports[state->irq]->next_port &&
|
2527 |
|
|
(was_multi != now_multi)) {
|
2528 |
|
|
free_irq(state->irq, &IRQ_ports[state->irq]);
|
2529 |
|
|
if (now_multi)
|
2530 |
|
|
handler = rs_interrupt_multi;
|
2531 |
|
|
else
|
2532 |
|
|
handler = rs_interrupt;
|
2533 |
|
|
|
2534 |
|
|
retval = request_irq(state->irq, handler, SA_SHIRQ,
|
2535 |
|
|
"serial", &IRQ_ports[state->irq]);
|
2536 |
|
|
if (retval) {
|
2537 |
|
|
printk("Couldn't reallocate serial interrupt "
|
2538 |
|
|
"driver!!\n");
|
2539 |
|
|
}
|
2540 |
|
|
}
|
2541 |
|
|
return 0;
|
2542 |
|
|
}
|
2543 |
|
|
#endif
|
2544 |
|
|
|
2545 |
|
|
static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
2546 |
|
|
unsigned int cmd, unsigned long arg)
|
2547 |
|
|
{
|
2548 |
|
|
struct async_struct * info = (struct async_struct *)tty->driver_data;
|
2549 |
|
|
struct async_icount cprev, cnow; /* kernel counter temps */
|
2550 |
|
|
struct serial_icounter_struct icount;
|
2551 |
|
|
unsigned long flags;
|
2552 |
|
|
#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
|
2553 |
|
|
int retval, tmp;
|
2554 |
|
|
#endif
|
2555 |
|
|
|
2556 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
|
2557 |
|
|
return -ENODEV;
|
2558 |
|
|
|
2559 |
|
|
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
2560 |
|
|
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
|
2561 |
|
|
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
2562 |
|
|
if (tty->flags & (1 << TTY_IO_ERROR))
|
2563 |
|
|
return -EIO;
|
2564 |
|
|
}
|
2565 |
|
|
|
2566 |
|
|
switch (cmd) {
|
2567 |
|
|
#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
|
2568 |
|
|
case TCSBRK: /* SVID version: non-zero arg --> no break */
|
2569 |
|
|
retval = tty_check_change(tty);
|
2570 |
|
|
if (retval)
|
2571 |
|
|
return retval;
|
2572 |
|
|
tty_wait_until_sent(tty, 0);
|
2573 |
|
|
if (signal_pending(current))
|
2574 |
|
|
return -EINTR;
|
2575 |
|
|
if (!arg) {
|
2576 |
|
|
send_break(info, HZ/4); /* 1/4 second */
|
2577 |
|
|
if (signal_pending(current))
|
2578 |
|
|
return -EINTR;
|
2579 |
|
|
}
|
2580 |
|
|
return 0;
|
2581 |
|
|
case TCSBRKP: /* support for POSIX tcsendbreak() */
|
2582 |
|
|
retval = tty_check_change(tty);
|
2583 |
|
|
if (retval)
|
2584 |
|
|
return retval;
|
2585 |
|
|
tty_wait_until_sent(tty, 0);
|
2586 |
|
|
if (signal_pending(current))
|
2587 |
|
|
return -EINTR;
|
2588 |
|
|
send_break(info, arg ? arg*(HZ/10) : HZ/4);
|
2589 |
|
|
if (signal_pending(current))
|
2590 |
|
|
return -EINTR;
|
2591 |
|
|
return 0;
|
2592 |
|
|
case TIOCGSOFTCAR:
|
2593 |
|
|
tmp = C_CLOCAL(tty) ? 1 : 0;
|
2594 |
|
|
if (copy_to_user((void *)arg, &tmp, sizeof(int)))
|
2595 |
|
|
return -EFAULT;
|
2596 |
|
|
return 0;
|
2597 |
|
|
case TIOCSSOFTCAR:
|
2598 |
|
|
if (copy_from_user(&tmp, (void *)arg, sizeof(int)))
|
2599 |
|
|
return -EFAULT;
|
2600 |
|
|
|
2601 |
|
|
tty->termios->c_cflag =
|
2602 |
|
|
((tty->termios->c_cflag & ~CLOCAL) |
|
2603 |
|
|
(tmp ? CLOCAL : 0));
|
2604 |
|
|
return 0;
|
2605 |
|
|
#endif
|
2606 |
|
|
case TIOCMGET:
|
2607 |
|
|
return get_modem_info(info, (unsigned int *) arg);
|
2608 |
|
|
case TIOCMBIS:
|
2609 |
|
|
case TIOCMBIC:
|
2610 |
|
|
case TIOCMSET:
|
2611 |
|
|
return set_modem_info(info, cmd, (unsigned int *) arg);
|
2612 |
|
|
case TIOCGSERIAL:
|
2613 |
|
|
return get_serial_info(info,
|
2614 |
|
|
(struct serial_struct *) arg);
|
2615 |
|
|
case TIOCSSERIAL:
|
2616 |
|
|
return set_serial_info(info,
|
2617 |
|
|
(struct serial_struct *) arg);
|
2618 |
|
|
case TIOCSERCONFIG:
|
2619 |
|
|
return do_autoconfig(info);
|
2620 |
|
|
|
2621 |
|
|
case TIOCSERGETLSR: /* Get line status register */
|
2622 |
|
|
return get_lsr_info(info, (unsigned int *) arg);
|
2623 |
|
|
|
2624 |
|
|
case TIOCSERGSTRUCT:
|
2625 |
|
|
if (copy_to_user((struct async_struct *) arg,
|
2626 |
|
|
info, sizeof(struct async_struct)))
|
2627 |
|
|
return -EFAULT;
|
2628 |
|
|
return 0;
|
2629 |
|
|
|
2630 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
2631 |
|
|
case TIOCSERGETMULTI:
|
2632 |
|
|
return get_multiport_struct(info,
|
2633 |
|
|
(struct serial_multiport_struct *) arg);
|
2634 |
|
|
case TIOCSERSETMULTI:
|
2635 |
|
|
return set_multiport_struct(info,
|
2636 |
|
|
(struct serial_multiport_struct *) arg);
|
2637 |
|
|
#endif
|
2638 |
|
|
|
2639 |
|
|
/*
|
2640 |
|
|
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
|
2641 |
|
|
* - mask passed in arg for lines of interest
|
2642 |
|
|
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
|
2643 |
|
|
* Caller should use TIOCGICOUNT to see which one it was
|
2644 |
|
|
*/
|
2645 |
|
|
case TIOCMIWAIT:
|
2646 |
|
|
save_flags(flags); cli();
|
2647 |
|
|
/* note the counters on entry */
|
2648 |
|
|
cprev = info->state->icount;
|
2649 |
|
|
restore_flags(flags);
|
2650 |
|
|
/* Force modem status interrupts on */
|
2651 |
|
|
info->IER |= UART_IER_MSI;
|
2652 |
|
|
serial_out(info, UART_IER, info->IER);
|
2653 |
|
|
while (1) {
|
2654 |
|
|
interruptible_sleep_on(&info->delta_msr_wait);
|
2655 |
|
|
/* see if a signal did it */
|
2656 |
|
|
if (signal_pending(current))
|
2657 |
|
|
return -ERESTARTSYS;
|
2658 |
|
|
save_flags(flags); cli();
|
2659 |
|
|
cnow = info->state->icount; /* atomic copy */
|
2660 |
|
|
restore_flags(flags);
|
2661 |
|
|
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
|
2662 |
|
|
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
|
2663 |
|
|
return -EIO; /* no change => error */
|
2664 |
|
|
if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
|
2665 |
|
|
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
|
2666 |
|
|
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
|
2667 |
|
|
((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
|
2668 |
|
|
return 0;
|
2669 |
|
|
}
|
2670 |
|
|
cprev = cnow;
|
2671 |
|
|
}
|
2672 |
|
|
/* NOTREACHED */
|
2673 |
|
|
|
2674 |
|
|
/*
|
2675 |
|
|
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
2676 |
|
|
* Return: write counters to the user passed counter struct
|
2677 |
|
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
2678 |
|
|
* RI where only 0->1 is counted.
|
2679 |
|
|
*/
|
2680 |
|
|
case TIOCGICOUNT:
|
2681 |
|
|
save_flags(flags); cli();
|
2682 |
|
|
cnow = info->state->icount;
|
2683 |
|
|
restore_flags(flags);
|
2684 |
|
|
icount.cts = cnow.cts;
|
2685 |
|
|
icount.dsr = cnow.dsr;
|
2686 |
|
|
icount.rng = cnow.rng;
|
2687 |
|
|
icount.dcd = cnow.dcd;
|
2688 |
|
|
icount.rx = cnow.rx;
|
2689 |
|
|
icount.tx = cnow.tx;
|
2690 |
|
|
icount.frame = cnow.frame;
|
2691 |
|
|
icount.overrun = cnow.overrun;
|
2692 |
|
|
icount.parity = cnow.parity;
|
2693 |
|
|
icount.brk = cnow.brk;
|
2694 |
|
|
icount.buf_overrun = cnow.buf_overrun;
|
2695 |
|
|
|
2696 |
|
|
if (copy_to_user((void *)arg, &icount, sizeof(icount)))
|
2697 |
|
|
return -EFAULT;
|
2698 |
|
|
return 0;
|
2699 |
|
|
case TIOCSERGWILD:
|
2700 |
|
|
case TIOCSERSWILD:
|
2701 |
|
|
/* "setserial -W" is called in Debian boot */
|
2702 |
|
|
printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
|
2703 |
|
|
return 0;
|
2704 |
|
|
|
2705 |
|
|
default:
|
2706 |
|
|
return -ENOIOCTLCMD;
|
2707 |
|
|
}
|
2708 |
|
|
return 0;
|
2709 |
|
|
}
|
2710 |
|
|
|
2711 |
|
|
static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
|
2712 |
|
|
{
|
2713 |
|
|
struct async_struct *info = (struct async_struct *)tty->driver_data;
|
2714 |
|
|
unsigned long flags;
|
2715 |
|
|
unsigned int cflag = tty->termios->c_cflag;
|
2716 |
|
|
|
2717 |
|
|
if ( (cflag == old_termios->c_cflag)
|
2718 |
|
|
&& ( RELEVANT_IFLAG(tty->termios->c_iflag)
|
2719 |
|
|
== RELEVANT_IFLAG(old_termios->c_iflag)))
|
2720 |
|
|
return;
|
2721 |
|
|
|
2722 |
|
|
change_speed(info, old_termios);
|
2723 |
|
|
|
2724 |
|
|
/* Handle transition to B0 status */
|
2725 |
|
|
if ((old_termios->c_cflag & CBAUD) &&
|
2726 |
|
|
!(cflag & CBAUD)) {
|
2727 |
|
|
info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
|
2728 |
|
|
save_flags(flags); cli();
|
2729 |
|
|
serial_out(info, UART_MCR, info->MCR);
|
2730 |
|
|
restore_flags(flags);
|
2731 |
|
|
}
|
2732 |
|
|
|
2733 |
|
|
/* Handle transition away from B0 status */
|
2734 |
|
|
if (!(old_termios->c_cflag & CBAUD) &&
|
2735 |
|
|
(cflag & CBAUD)) {
|
2736 |
|
|
info->MCR |= UART_MCR_DTR;
|
2737 |
|
|
if (!(tty->termios->c_cflag & CRTSCTS) ||
|
2738 |
|
|
!test_bit(TTY_THROTTLED, &tty->flags)) {
|
2739 |
|
|
info->MCR |= UART_MCR_RTS;
|
2740 |
|
|
}
|
2741 |
|
|
save_flags(flags); cli();
|
2742 |
|
|
serial_out(info, UART_MCR, info->MCR);
|
2743 |
|
|
restore_flags(flags);
|
2744 |
|
|
}
|
2745 |
|
|
|
2746 |
|
|
/* Handle turning off CRTSCTS */
|
2747 |
|
|
if ((old_termios->c_cflag & CRTSCTS) &&
|
2748 |
|
|
!(tty->termios->c_cflag & CRTSCTS)) {
|
2749 |
|
|
tty->hw_stopped = 0;
|
2750 |
|
|
rs_start(tty);
|
2751 |
|
|
}
|
2752 |
|
|
|
2753 |
|
|
#if 0
|
2754 |
|
|
/*
|
2755 |
|
|
* No need to wake up processes in open wait, since they
|
2756 |
|
|
* sample the CLOCAL flag once, and don't recheck it.
|
2757 |
|
|
* XXX It's not clear whether the current behavior is correct
|
2758 |
|
|
* or not. Hence, this may change.....
|
2759 |
|
|
*/
|
2760 |
|
|
if (!(old_termios->c_cflag & CLOCAL) &&
|
2761 |
|
|
(tty->termios->c_cflag & CLOCAL))
|
2762 |
|
|
wake_up_interruptible(&info->open_wait);
|
2763 |
|
|
#endif
|
2764 |
|
|
}
|
2765 |
|
|
|
2766 |
|
|
/*
|
2767 |
|
|
* ------------------------------------------------------------
|
2768 |
|
|
* rs_close()
|
2769 |
|
|
*
|
2770 |
|
|
* This routine is called when the serial port gets closed. First, we
|
2771 |
|
|
* wait for the last remaining data to be sent. Then, we unlink its
|
2772 |
|
|
* async structure from the interrupt chain if necessary, and we free
|
2773 |
|
|
* that IRQ if nothing is left in the chain.
|
2774 |
|
|
* ------------------------------------------------------------
|
2775 |
|
|
*/
|
2776 |
|
|
static void rs_close(struct tty_struct *tty, struct file * filp)
|
2777 |
|
|
{
|
2778 |
|
|
struct async_struct * info = (struct async_struct *)tty->driver_data;
|
2779 |
|
|
struct serial_state *state;
|
2780 |
|
|
unsigned long flags;
|
2781 |
|
|
|
2782 |
|
|
if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
|
2783 |
|
|
return;
|
2784 |
|
|
|
2785 |
|
|
state = info->state;
|
2786 |
|
|
|
2787 |
|
|
save_flags(flags); cli();
|
2788 |
|
|
|
2789 |
|
|
if (tty_hung_up_p(filp)) {
|
2790 |
|
|
DBG_CNT("before DEC-hung");
|
2791 |
|
|
MOD_DEC_USE_COUNT;
|
2792 |
|
|
restore_flags(flags);
|
2793 |
|
|
return;
|
2794 |
|
|
}
|
2795 |
|
|
|
2796 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
2797 |
|
|
printk("rs_close ttys%d, count = %d\n", info->line, state->count);
|
2798 |
|
|
#endif
|
2799 |
|
|
if ((tty->count == 1) && (state->count != 1)) {
|
2800 |
|
|
/*
|
2801 |
|
|
* Uh, oh. tty->count is 1, which means that the tty
|
2802 |
|
|
* structure will be freed. state->count should always
|
2803 |
|
|
* be one in these conditions. If it's greater than
|
2804 |
|
|
* one, we've got real problems, since it means the
|
2805 |
|
|
* serial port won't be shutdown.
|
2806 |
|
|
*/
|
2807 |
|
|
printk("rs_close: bad serial port count; tty->count is 1, "
|
2808 |
|
|
"state->count is %d\n", state->count);
|
2809 |
|
|
state->count = 1;
|
2810 |
|
|
}
|
2811 |
|
|
if (--state->count < 0) {
|
2812 |
|
|
printk("rs_close: bad serial port count for ttys%d: %d\n",
|
2813 |
|
|
info->line, state->count);
|
2814 |
|
|
state->count = 0;
|
2815 |
|
|
}
|
2816 |
|
|
if (state->count) {
|
2817 |
|
|
DBG_CNT("before DEC-2");
|
2818 |
|
|
MOD_DEC_USE_COUNT;
|
2819 |
|
|
restore_flags(flags);
|
2820 |
|
|
return;
|
2821 |
|
|
}
|
2822 |
|
|
info->flags |= ASYNC_CLOSING;
|
2823 |
|
|
restore_flags(flags);
|
2824 |
|
|
/*
|
2825 |
|
|
* Save the termios structure, since this port may have
|
2826 |
|
|
* separate termios for callout and dialin.
|
2827 |
|
|
*/
|
2828 |
|
|
if (info->flags & ASYNC_NORMAL_ACTIVE)
|
2829 |
|
|
info->state->normal_termios = *tty->termios;
|
2830 |
|
|
if (info->flags & ASYNC_CALLOUT_ACTIVE)
|
2831 |
|
|
info->state->callout_termios = *tty->termios;
|
2832 |
|
|
/*
|
2833 |
|
|
* Now we wait for the transmit buffer to clear; and we notify
|
2834 |
|
|
* the line discipline to only process XON/XOFF characters.
|
2835 |
|
|
*/
|
2836 |
|
|
tty->closing = 1;
|
2837 |
|
|
if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
|
2838 |
|
|
tty_wait_until_sent(tty, info->closing_wait);
|
2839 |
|
|
/*
|
2840 |
|
|
* At this point we stop accepting input. To do this, we
|
2841 |
|
|
* disable the receive line status interrupts, and tell the
|
2842 |
|
|
* interrupt driver to stop checking the data ready bit in the
|
2843 |
|
|
* line status register.
|
2844 |
|
|
*/
|
2845 |
|
|
info->IER &= ~UART_IER_RLSI;
|
2846 |
|
|
info->read_status_mask &= ~UART_LSR_DR;
|
2847 |
|
|
if (info->flags & ASYNC_INITIALIZED) {
|
2848 |
|
|
serial_out(info, UART_IER, info->IER);
|
2849 |
|
|
/*
|
2850 |
|
|
* Before we drop DTR, make sure the UART transmitter
|
2851 |
|
|
* has completely drained; this is especially
|
2852 |
|
|
* important if there is a transmit FIFO!
|
2853 |
|
|
*/
|
2854 |
|
|
rs_wait_until_sent(tty, info->timeout);
|
2855 |
|
|
}
|
2856 |
|
|
shutdown(info);
|
2857 |
|
|
if (tty->driver.flush_buffer)
|
2858 |
|
|
tty->driver.flush_buffer(tty);
|
2859 |
|
|
if (tty->ldisc.flush_buffer)
|
2860 |
|
|
tty->ldisc.flush_buffer(tty);
|
2861 |
|
|
tty->closing = 0;
|
2862 |
|
|
info->event = 0;
|
2863 |
|
|
info->tty = 0;
|
2864 |
|
|
if (info->blocked_open) {
|
2865 |
|
|
if (info->close_delay) {
|
2866 |
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
2867 |
|
|
schedule_timeout(info->close_delay);
|
2868 |
|
|
}
|
2869 |
|
|
wake_up_interruptible(&info->open_wait);
|
2870 |
|
|
}
|
2871 |
|
|
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
|
2872 |
|
|
ASYNC_CLOSING);
|
2873 |
|
|
wake_up_interruptible(&info->close_wait);
|
2874 |
|
|
MOD_DEC_USE_COUNT;
|
2875 |
|
|
}
|
2876 |
|
|
|
2877 |
|
|
/*
|
2878 |
|
|
* rs_wait_until_sent() --- wait until the transmitter is empty
|
2879 |
|
|
*/
|
2880 |
|
|
static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
|
2881 |
|
|
{
|
2882 |
|
|
struct async_struct * info = (struct async_struct *)tty->driver_data;
|
2883 |
|
|
unsigned long orig_jiffies, char_time;
|
2884 |
|
|
int lsr;
|
2885 |
|
|
|
2886 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
|
2887 |
|
|
return;
|
2888 |
|
|
|
2889 |
|
|
if (info->state->type == PORT_UNKNOWN)
|
2890 |
|
|
return;
|
2891 |
|
|
|
2892 |
|
|
if (info->xmit_fifo_size == 0)
|
2893 |
|
|
return; /* Just in case.... */
|
2894 |
|
|
|
2895 |
|
|
orig_jiffies = jiffies;
|
2896 |
|
|
/*
|
2897 |
|
|
* Set the check interval to be 1/5 of the estimated time to
|
2898 |
|
|
* send a single character, and make it at least 1. The check
|
2899 |
|
|
* interval should also be less than the timeout.
|
2900 |
|
|
*
|
2901 |
|
|
* Note: we have to use pretty tight timings here to satisfy
|
2902 |
|
|
* the NIST-PCTS.
|
2903 |
|
|
*/
|
2904 |
|
|
char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
|
2905 |
|
|
char_time = char_time / 5;
|
2906 |
|
|
if (char_time == 0)
|
2907 |
|
|
char_time = 1;
|
2908 |
|
|
if (timeout && timeout < char_time)
|
2909 |
|
|
char_time = timeout;
|
2910 |
|
|
/*
|
2911 |
|
|
* If the transmitter hasn't cleared in twice the approximate
|
2912 |
|
|
* amount of time to send the entire FIFO, it probably won't
|
2913 |
|
|
* ever clear. This assumes the UART isn't doing flow
|
2914 |
|
|
* control, which is currently the case. Hence, if it ever
|
2915 |
|
|
* takes longer than info->timeout, this is probably due to a
|
2916 |
|
|
* UART bug of some kind. So, we clamp the timeout parameter at
|
2917 |
|
|
* 2*info->timeout.
|
2918 |
|
|
*/
|
2919 |
|
|
if (!timeout || timeout > 2*info->timeout)
|
2920 |
|
|
timeout = 2*info->timeout;
|
2921 |
|
|
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
|
2922 |
|
|
printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
|
2923 |
|
|
printk("jiff=%lu...", jiffies);
|
2924 |
|
|
#endif
|
2925 |
|
|
while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) {
|
2926 |
|
|
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
|
2927 |
|
|
printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
|
2928 |
|
|
#endif
|
2929 |
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
2930 |
|
|
schedule_timeout(char_time);
|
2931 |
|
|
if (signal_pending(current))
|
2932 |
|
|
break;
|
2933 |
|
|
if (timeout && time_after(jiffies, orig_jiffies + timeout))
|
2934 |
|
|
break;
|
2935 |
|
|
}
|
2936 |
|
|
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
|
2937 |
|
|
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
|
2938 |
|
|
#endif
|
2939 |
|
|
}
|
2940 |
|
|
|
2941 |
|
|
/*
|
2942 |
|
|
* rs_hangup() --- called by tty_hangup() when a hangup is signaled.
|
2943 |
|
|
*/
|
2944 |
|
|
static void rs_hangup(struct tty_struct *tty)
|
2945 |
|
|
{
|
2946 |
|
|
struct async_struct * info = (struct async_struct *)tty->driver_data;
|
2947 |
|
|
struct serial_state *state = info->state;
|
2948 |
|
|
|
2949 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_hangup"))
|
2950 |
|
|
return;
|
2951 |
|
|
|
2952 |
|
|
state = info->state;
|
2953 |
|
|
|
2954 |
|
|
rs_flush_buffer(tty);
|
2955 |
|
|
if (info->flags & ASYNC_CLOSING)
|
2956 |
|
|
return;
|
2957 |
|
|
shutdown(info);
|
2958 |
|
|
info->event = 0;
|
2959 |
|
|
state->count = 0;
|
2960 |
|
|
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
|
2961 |
|
|
info->tty = 0;
|
2962 |
|
|
wake_up_interruptible(&info->open_wait);
|
2963 |
|
|
}
|
2964 |
|
|
|
2965 |
|
|
/*
|
2966 |
|
|
* ------------------------------------------------------------
|
2967 |
|
|
* rs_open() and friends
|
2968 |
|
|
* ------------------------------------------------------------
|
2969 |
|
|
*/
|
2970 |
|
|
static int block_til_ready(struct tty_struct *tty, struct file * filp,
|
2971 |
|
|
struct async_struct *info)
|
2972 |
|
|
{
|
2973 |
|
|
DECLARE_WAITQUEUE(wait, current);
|
2974 |
|
|
struct serial_state *state = info->state;
|
2975 |
|
|
int retval;
|
2976 |
|
|
int do_clocal = 0, extra_count = 0;
|
2977 |
|
|
unsigned long flags;
|
2978 |
|
|
|
2979 |
|
|
/*
|
2980 |
|
|
* If the device is in the middle of being closed, then block
|
2981 |
|
|
* until it's done, and then try again.
|
2982 |
|
|
*/
|
2983 |
|
|
if (tty_hung_up_p(filp) ||
|
2984 |
|
|
(info->flags & ASYNC_CLOSING)) {
|
2985 |
|
|
if (info->flags & ASYNC_CLOSING)
|
2986 |
|
|
interruptible_sleep_on(&info->close_wait);
|
2987 |
|
|
#ifdef SERIAL_DO_RESTART
|
2988 |
|
|
return ((info->flags & ASYNC_HUP_NOTIFY) ?
|
2989 |
|
|
-EAGAIN : -ERESTARTSYS);
|
2990 |
|
|
#else
|
2991 |
|
|
return -EAGAIN;
|
2992 |
|
|
#endif
|
2993 |
|
|
}
|
2994 |
|
|
|
2995 |
|
|
/*
|
2996 |
|
|
* If this is a callout device, then just make sure the normal
|
2997 |
|
|
* device isn't being used.
|
2998 |
|
|
*/
|
2999 |
|
|
if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
|
3000 |
|
|
if (info->flags & ASYNC_NORMAL_ACTIVE)
|
3001 |
|
|
return -EBUSY;
|
3002 |
|
|
if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
|
3003 |
|
|
(info->flags & ASYNC_SESSION_LOCKOUT) &&
|
3004 |
|
|
(info->session != current->session))
|
3005 |
|
|
return -EBUSY;
|
3006 |
|
|
if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
|
3007 |
|
|
(info->flags & ASYNC_PGRP_LOCKOUT) &&
|
3008 |
|
|
(info->pgrp != current->pgrp))
|
3009 |
|
|
return -EBUSY;
|
3010 |
|
|
info->flags |= ASYNC_CALLOUT_ACTIVE;
|
3011 |
|
|
return 0;
|
3012 |
|
|
}
|
3013 |
|
|
|
3014 |
|
|
/*
|
3015 |
|
|
* If non-blocking mode is set, or the port is not enabled,
|
3016 |
|
|
* then make the check up front and then exit.
|
3017 |
|
|
*/
|
3018 |
|
|
if ((filp->f_flags & O_NONBLOCK) ||
|
3019 |
|
|
(tty->flags & (1 << TTY_IO_ERROR))) {
|
3020 |
|
|
if (info->flags & ASYNC_CALLOUT_ACTIVE)
|
3021 |
|
|
return -EBUSY;
|
3022 |
|
|
info->flags |= ASYNC_NORMAL_ACTIVE;
|
3023 |
|
|
return 0;
|
3024 |
|
|
}
|
3025 |
|
|
|
3026 |
|
|
if (info->flags & ASYNC_CALLOUT_ACTIVE) {
|
3027 |
|
|
if (state->normal_termios.c_cflag & CLOCAL)
|
3028 |
|
|
do_clocal = 1;
|
3029 |
|
|
} else {
|
3030 |
|
|
if (tty->termios->c_cflag & CLOCAL)
|
3031 |
|
|
do_clocal = 1;
|
3032 |
|
|
}
|
3033 |
|
|
|
3034 |
|
|
/*
|
3035 |
|
|
* Block waiting for the carrier detect and the line to become
|
3036 |
|
|
* free (i.e., not in use by the callout). While we are in
|
3037 |
|
|
* this loop, state->count is dropped by one, so that
|
3038 |
|
|
* rs_close() knows when to free things. We restore it upon
|
3039 |
|
|
* exit, either normal or abnormal.
|
3040 |
|
|
*/
|
3041 |
|
|
retval = 0;
|
3042 |
|
|
add_wait_queue(&info->open_wait, &wait);
|
3043 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
3044 |
|
|
printk("block_til_ready before block: ttys%d, count = %d\n",
|
3045 |
|
|
state->line, state->count);
|
3046 |
|
|
#endif
|
3047 |
|
|
save_flags(flags); cli();
|
3048 |
|
|
if (!tty_hung_up_p(filp)) {
|
3049 |
|
|
extra_count = 1;
|
3050 |
|
|
state->count--;
|
3051 |
|
|
}
|
3052 |
|
|
restore_flags(flags);
|
3053 |
|
|
info->blocked_open++;
|
3054 |
|
|
while (1) {
|
3055 |
|
|
save_flags(flags); cli();
|
3056 |
|
|
if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
|
3057 |
|
|
(tty->termios->c_cflag & CBAUD))
|
3058 |
|
|
serial_out(info, UART_MCR,
|
3059 |
|
|
serial_inp(info, UART_MCR) |
|
3060 |
|
|
(UART_MCR_DTR | UART_MCR_RTS));
|
3061 |
|
|
restore_flags(flags);
|
3062 |
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
3063 |
|
|
if (tty_hung_up_p(filp) ||
|
3064 |
|
|
!(info->flags & ASYNC_INITIALIZED)) {
|
3065 |
|
|
#ifdef SERIAL_DO_RESTART
|
3066 |
|
|
if (info->flags & ASYNC_HUP_NOTIFY)
|
3067 |
|
|
retval = -EAGAIN;
|
3068 |
|
|
else
|
3069 |
|
|
retval = -ERESTARTSYS;
|
3070 |
|
|
#else
|
3071 |
|
|
retval = -EAGAIN;
|
3072 |
|
|
#endif
|
3073 |
|
|
break;
|
3074 |
|
|
}
|
3075 |
|
|
if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
|
3076 |
|
|
!(info->flags & ASYNC_CLOSING) &&
|
3077 |
|
|
(do_clocal || (serial_in(info, UART_MSR) &
|
3078 |
|
|
UART_MSR_DCD)))
|
3079 |
|
|
break;
|
3080 |
|
|
if (signal_pending(current)) {
|
3081 |
|
|
retval = -ERESTARTSYS;
|
3082 |
|
|
break;
|
3083 |
|
|
}
|
3084 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
3085 |
|
|
printk("block_til_ready blocking: ttys%d, count = %d\n",
|
3086 |
|
|
info->line, state->count);
|
3087 |
|
|
#endif
|
3088 |
|
|
schedule();
|
3089 |
|
|
}
|
3090 |
|
|
set_current_state(TASK_RUNNING);
|
3091 |
|
|
remove_wait_queue(&info->open_wait, &wait);
|
3092 |
|
|
if (extra_count)
|
3093 |
|
|
state->count++;
|
3094 |
|
|
info->blocked_open--;
|
3095 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
3096 |
|
|
printk("block_til_ready after blocking: ttys%d, count = %d\n",
|
3097 |
|
|
info->line, state->count);
|
3098 |
|
|
#endif
|
3099 |
|
|
if (retval)
|
3100 |
|
|
return retval;
|
3101 |
|
|
info->flags |= ASYNC_NORMAL_ACTIVE;
|
3102 |
|
|
return 0;
|
3103 |
|
|
}
|
3104 |
|
|
|
3105 |
|
|
static int get_async_struct(int line, struct async_struct **ret_info)
|
3106 |
|
|
{
|
3107 |
|
|
struct async_struct *info;
|
3108 |
|
|
struct serial_state *sstate;
|
3109 |
|
|
|
3110 |
|
|
sstate = rs_table + line;
|
3111 |
|
|
sstate->count++;
|
3112 |
|
|
if (sstate->info) {
|
3113 |
|
|
*ret_info = sstate->info;
|
3114 |
|
|
return 0;
|
3115 |
|
|
}
|
3116 |
|
|
info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
|
3117 |
|
|
if (!info) {
|
3118 |
|
|
sstate->count--;
|
3119 |
|
|
return -ENOMEM;
|
3120 |
|
|
}
|
3121 |
|
|
memset(info, 0, sizeof(struct async_struct));
|
3122 |
|
|
init_waitqueue_head(&info->open_wait);
|
3123 |
|
|
init_waitqueue_head(&info->close_wait);
|
3124 |
|
|
init_waitqueue_head(&info->delta_msr_wait);
|
3125 |
|
|
info->magic = SERIAL_MAGIC;
|
3126 |
|
|
info->port = sstate->port;
|
3127 |
|
|
info->flags = sstate->flags;
|
3128 |
|
|
info->io_type = sstate->io_type;
|
3129 |
|
|
info->iomem_base = sstate->iomem_base;
|
3130 |
|
|
info->iomem_reg_shift = sstate->iomem_reg_shift;
|
3131 |
|
|
info->xmit_fifo_size = sstate->xmit_fifo_size;
|
3132 |
|
|
info->line = line;
|
3133 |
|
|
info->tqueue.routine = do_softint;
|
3134 |
|
|
info->tqueue.data = info;
|
3135 |
|
|
info->state = sstate;
|
3136 |
|
|
if (sstate->info) {
|
3137 |
|
|
kfree(info);
|
3138 |
|
|
*ret_info = sstate->info;
|
3139 |
|
|
return 0;
|
3140 |
|
|
}
|
3141 |
|
|
*ret_info = sstate->info = info;
|
3142 |
|
|
return 0;
|
3143 |
|
|
}
|
3144 |
|
|
|
3145 |
|
|
/*
|
3146 |
|
|
* This routine is called whenever a serial port is opened. It
|
3147 |
|
|
* enables interrupts for a serial port, linking in its async structure into
|
3148 |
|
|
* the IRQ chain. It also performs the serial-specific
|
3149 |
|
|
* initialization for the tty structure.
|
3150 |
|
|
*
|
3151 |
|
|
* Note that on failure, we don't decrement the module use count - the tty
|
3152 |
|
|
* later will call rs_close, which will decrement it for us as long as
|
3153 |
|
|
* tty->driver_data is set non-NULL. --rmk
|
3154 |
|
|
*/
|
3155 |
|
|
static int rs_open(struct tty_struct *tty, struct file * filp)
|
3156 |
|
|
{
|
3157 |
|
|
struct async_struct *info;
|
3158 |
|
|
int retval, line;
|
3159 |
|
|
unsigned long page;
|
3160 |
|
|
|
3161 |
|
|
MOD_INC_USE_COUNT;
|
3162 |
|
|
line = MINOR(tty->device) - tty->driver.minor_start;
|
3163 |
|
|
if ((line < 0) || (line >= NR_PORTS)) {
|
3164 |
|
|
MOD_DEC_USE_COUNT;
|
3165 |
|
|
return -ENODEV;
|
3166 |
|
|
}
|
3167 |
|
|
retval = get_async_struct(line, &info);
|
3168 |
|
|
if (retval) {
|
3169 |
|
|
MOD_DEC_USE_COUNT;
|
3170 |
|
|
return retval;
|
3171 |
|
|
}
|
3172 |
|
|
tty->driver_data = info;
|
3173 |
|
|
info->tty = tty;
|
3174 |
|
|
if (serial_paranoia_check(info, tty->device, "rs_open"))
|
3175 |
|
|
return -ENODEV;
|
3176 |
|
|
|
3177 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
3178 |
|
|
printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
|
3179 |
|
|
info->state->count);
|
3180 |
|
|
#endif
|
3181 |
|
|
#if (LINUX_VERSION_CODE > 0x20100)
|
3182 |
|
|
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
3183 |
|
|
#endif
|
3184 |
|
|
|
3185 |
|
|
/*
|
3186 |
|
|
* This relies on lock_kernel() stuff so wants tidying for 2.5
|
3187 |
|
|
*/
|
3188 |
|
|
if (!tmp_buf) {
|
3189 |
|
|
page = get_zeroed_page(GFP_KERNEL);
|
3190 |
|
|
if (!page)
|
3191 |
|
|
return -ENOMEM;
|
3192 |
|
|
if (tmp_buf)
|
3193 |
|
|
free_page(page);
|
3194 |
|
|
else
|
3195 |
|
|
tmp_buf = (unsigned char *) page;
|
3196 |
|
|
}
|
3197 |
|
|
|
3198 |
|
|
/*
|
3199 |
|
|
* If the port is the middle of closing, bail out now
|
3200 |
|
|
*/
|
3201 |
|
|
if (tty_hung_up_p(filp) ||
|
3202 |
|
|
(info->flags & ASYNC_CLOSING)) {
|
3203 |
|
|
if (info->flags & ASYNC_CLOSING)
|
3204 |
|
|
interruptible_sleep_on(&info->close_wait);
|
3205 |
|
|
#ifdef SERIAL_DO_RESTART
|
3206 |
|
|
return ((info->flags & ASYNC_HUP_NOTIFY) ?
|
3207 |
|
|
-EAGAIN : -ERESTARTSYS);
|
3208 |
|
|
#else
|
3209 |
|
|
return -EAGAIN;
|
3210 |
|
|
#endif
|
3211 |
|
|
}
|
3212 |
|
|
|
3213 |
|
|
/*
|
3214 |
|
|
* Start up serial port
|
3215 |
|
|
*/
|
3216 |
|
|
retval = startup(info);
|
3217 |
|
|
if (retval)
|
3218 |
|
|
return retval;
|
3219 |
|
|
|
3220 |
|
|
retval = block_til_ready(tty, filp, info);
|
3221 |
|
|
if (retval) {
|
3222 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
3223 |
|
|
printk("rs_open returning after block_til_ready with %d\n",
|
3224 |
|
|
retval);
|
3225 |
|
|
#endif
|
3226 |
|
|
return retval;
|
3227 |
|
|
}
|
3228 |
|
|
|
3229 |
|
|
if ((info->state->count == 1) &&
|
3230 |
|
|
(info->flags & ASYNC_SPLIT_TERMIOS)) {
|
3231 |
|
|
if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
|
3232 |
|
|
*tty->termios = info->state->normal_termios;
|
3233 |
|
|
else
|
3234 |
|
|
*tty->termios = info->state->callout_termios;
|
3235 |
|
|
change_speed(info, 0);
|
3236 |
|
|
}
|
3237 |
|
|
#ifdef CONFIG_SERIAL_CONSOLE
|
3238 |
|
|
if (sercons.cflag && sercons.index == line) {
|
3239 |
|
|
tty->termios->c_cflag = sercons.cflag;
|
3240 |
|
|
sercons.cflag = 0;
|
3241 |
|
|
change_speed(info, 0);
|
3242 |
|
|
}
|
3243 |
|
|
#endif
|
3244 |
|
|
info->session = current->session;
|
3245 |
|
|
info->pgrp = current->pgrp;
|
3246 |
|
|
|
3247 |
|
|
#ifdef SERIAL_DEBUG_OPEN
|
3248 |
|
|
printk("rs_open ttys%d successful...", info->line);
|
3249 |
|
|
#endif
|
3250 |
|
|
return 0;
|
3251 |
|
|
}
|
3252 |
|
|
|
3253 |
|
|
/*
|
3254 |
|
|
* /proc fs routines....
|
3255 |
|
|
*/
|
3256 |
|
|
|
3257 |
|
|
static inline int line_info(char *buf, struct serial_state *state)
|
3258 |
|
|
{
|
3259 |
|
|
struct async_struct *info = state->info, scr_info;
|
3260 |
|
|
char stat_buf[30], control, status;
|
3261 |
|
|
int ret;
|
3262 |
|
|
unsigned long flags;
|
3263 |
|
|
|
3264 |
|
|
/*
|
3265 |
|
|
* Return zero characters for ports not claimed by driver.
|
3266 |
|
|
*/
|
3267 |
|
|
if (state->type == PORT_UNKNOWN) {
|
3268 |
|
|
return 0; /* ignore unused ports */
|
3269 |
|
|
}
|
3270 |
|
|
|
3271 |
|
|
ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d",
|
3272 |
|
|
state->line, uart_config[state->type].name,
|
3273 |
|
|
(state->port ? state->port : (long)state->iomem_base),
|
3274 |
|
|
state->irq);
|
3275 |
|
|
|
3276 |
|
|
/*
|
3277 |
|
|
* Figure out the current RS-232 lines
|
3278 |
|
|
*/
|
3279 |
|
|
if (!info) {
|
3280 |
|
|
info = &scr_info; /* This is just for serial_{in,out} */
|
3281 |
|
|
|
3282 |
|
|
info->magic = SERIAL_MAGIC;
|
3283 |
|
|
info->port = state->port;
|
3284 |
|
|
info->flags = state->flags;
|
3285 |
|
|
info->hub6 = state->hub6;
|
3286 |
|
|
info->io_type = state->io_type;
|
3287 |
|
|
info->iomem_base = state->iomem_base;
|
3288 |
|
|
info->iomem_reg_shift = state->iomem_reg_shift;
|
3289 |
|
|
info->quot = 0;
|
3290 |
|
|
info->tty = 0;
|
3291 |
|
|
}
|
3292 |
|
|
save_flags(flags); cli();
|
3293 |
|
|
status = serial_in(info, UART_MSR);
|
3294 |
|
|
control = info != &scr_info ? info->MCR : serial_in(info, UART_MCR);
|
3295 |
|
|
restore_flags(flags);
|
3296 |
|
|
|
3297 |
|
|
stat_buf[0] = 0;
|
3298 |
|
|
stat_buf[1] = 0;
|
3299 |
|
|
if (control & UART_MCR_RTS)
|
3300 |
|
|
strcat(stat_buf, "|RTS");
|
3301 |
|
|
if (status & UART_MSR_CTS)
|
3302 |
|
|
strcat(stat_buf, "|CTS");
|
3303 |
|
|
if (control & UART_MCR_DTR)
|
3304 |
|
|
strcat(stat_buf, "|DTR");
|
3305 |
|
|
if (status & UART_MSR_DSR)
|
3306 |
|
|
strcat(stat_buf, "|DSR");
|
3307 |
|
|
if (status & UART_MSR_DCD)
|
3308 |
|
|
strcat(stat_buf, "|CD");
|
3309 |
|
|
if (status & UART_MSR_RI)
|
3310 |
|
|
strcat(stat_buf, "|RI");
|
3311 |
|
|
|
3312 |
|
|
if (info->quot) {
|
3313 |
|
|
ret += sprintf(buf+ret, " baud:%d",
|
3314 |
|
|
state->baud_base / info->quot);
|
3315 |
|
|
}
|
3316 |
|
|
|
3317 |
|
|
ret += sprintf(buf+ret, " tx:%d rx:%d",
|
3318 |
|
|
state->icount.tx, state->icount.rx);
|
3319 |
|
|
|
3320 |
|
|
if (state->icount.frame)
|
3321 |
|
|
ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
|
3322 |
|
|
|
3323 |
|
|
if (state->icount.parity)
|
3324 |
|
|
ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
|
3325 |
|
|
|
3326 |
|
|
if (state->icount.brk)
|
3327 |
|
|
ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
|
3328 |
|
|
|
3329 |
|
|
if (state->icount.overrun)
|
3330 |
|
|
ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
|
3331 |
|
|
|
3332 |
|
|
/*
|
3333 |
|
|
* Last thing is the RS-232 status lines
|
3334 |
|
|
*/
|
3335 |
|
|
ret += sprintf(buf+ret, " %s\n", stat_buf+1);
|
3336 |
|
|
return ret;
|
3337 |
|
|
}
|
3338 |
|
|
|
3339 |
|
|
static int rs_read_proc(char *page, char **start, off_t off, int count,
|
3340 |
|
|
int *eof, void *data)
|
3341 |
|
|
{
|
3342 |
|
|
int i, len = 0, l;
|
3343 |
|
|
off_t begin = 0;
|
3344 |
|
|
|
3345 |
|
|
len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n",
|
3346 |
|
|
serial_version, LOCAL_VERSTRING, serial_revdate);
|
3347 |
|
|
for (i = 0; i < NR_PORTS && len < 4000; i++) {
|
3348 |
|
|
l = line_info(page + len, &rs_table[i]);
|
3349 |
|
|
len += l;
|
3350 |
|
|
if (len+begin > off+count)
|
3351 |
|
|
goto done;
|
3352 |
|
|
if (len+begin < off) {
|
3353 |
|
|
begin += len;
|
3354 |
|
|
len = 0;
|
3355 |
|
|
}
|
3356 |
|
|
}
|
3357 |
|
|
*eof = 1;
|
3358 |
|
|
done:
|
3359 |
|
|
if (off >= len+begin)
|
3360 |
|
|
return 0;
|
3361 |
|
|
*start = page + (off-begin);
|
3362 |
|
|
return ((count < begin+len-off) ? count : begin+len-off);
|
3363 |
|
|
}
|
3364 |
|
|
|
3365 |
|
|
/*
|
3366 |
|
|
* ---------------------------------------------------------------------
|
3367 |
|
|
* rs_init() and friends
|
3368 |
|
|
*
|
3369 |
|
|
* rs_init() is called at boot-time to initialize the serial driver.
|
3370 |
|
|
* ---------------------------------------------------------------------
|
3371 |
|
|
*/
|
3372 |
|
|
|
3373 |
|
|
/*
|
3374 |
|
|
* This routine prints out the appropriate serial driver version
|
3375 |
|
|
* number, and identifies which options were configured into this
|
3376 |
|
|
* driver.
|
3377 |
|
|
*/
|
3378 |
|
|
static char serial_options[] __initdata =
|
3379 |
|
|
#ifdef CONFIG_HUB6
|
3380 |
|
|
" HUB-6"
|
3381 |
|
|
#define SERIAL_OPT
|
3382 |
|
|
#endif
|
3383 |
|
|
#ifdef CONFIG_SERIAL_MANY_PORTS
|
3384 |
|
|
" MANY_PORTS"
|
3385 |
|
|
#define SERIAL_OPT
|
3386 |
|
|
#endif
|
3387 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
3388 |
|
|
" MULTIPORT"
|
3389 |
|
|
#define SERIAL_OPT
|
3390 |
|
|
#endif
|
3391 |
|
|
#ifdef CONFIG_SERIAL_SHARE_IRQ
|
3392 |
|
|
" SHARE_IRQ"
|
3393 |
|
|
#define SERIAL_OPT
|
3394 |
|
|
#endif
|
3395 |
|
|
#ifdef CONFIG_SERIAL_DETECT_IRQ
|
3396 |
|
|
" DETECT_IRQ"
|
3397 |
|
|
#define SERIAL_OPT
|
3398 |
|
|
#endif
|
3399 |
|
|
#ifdef ENABLE_SERIAL_PCI
|
3400 |
|
|
" SERIAL_PCI"
|
3401 |
|
|
#define SERIAL_OPT
|
3402 |
|
|
#endif
|
3403 |
|
|
#ifdef ENABLE_SERIAL_PNP
|
3404 |
|
|
" ISAPNP"
|
3405 |
|
|
#define SERIAL_OPT
|
3406 |
|
|
#endif
|
3407 |
|
|
#ifdef ENABLE_SERIAL_ACPI
|
3408 |
|
|
" SERIAL_ACPI"
|
3409 |
|
|
#define SERIAL_OPT
|
3410 |
|
|
#endif
|
3411 |
|
|
#ifdef SERIAL_OPT
|
3412 |
|
|
" enabled\n";
|
3413 |
|
|
#else
|
3414 |
|
|
" no serial options enabled\n";
|
3415 |
|
|
#endif
|
3416 |
|
|
#undef SERIAL_OPT
|
3417 |
|
|
|
3418 |
|
|
static _INLINE_ void show_serial_version(void)
|
3419 |
|
|
{
|
3420 |
|
|
printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name,
|
3421 |
|
|
serial_version, LOCAL_VERSTRING, serial_revdate,
|
3422 |
|
|
serial_options);
|
3423 |
|
|
}
|
3424 |
|
|
|
3425 |
|
|
/*
|
3426 |
|
|
* This routine detect the IRQ of a serial port by clearing OUT2 when
|
3427 |
|
|
* no UART interrupt are requested (IER = 0) (*GPL*). This seems to work at
|
3428 |
|
|
* each time, as long as no other device permanently request the IRQ.
|
3429 |
|
|
* If no IRQ is detected, or multiple IRQ appear, this function returns 0.
|
3430 |
|
|
* The variable "state" and the field "state->port" should not be null.
|
3431 |
|
|
*/
|
3432 |
|
|
static unsigned detect_uart_irq (struct serial_state * state)
|
3433 |
|
|
{
|
3434 |
|
|
int irq;
|
3435 |
|
|
unsigned long irqs;
|
3436 |
|
|
unsigned char save_mcr, save_ier;
|
3437 |
|
|
struct async_struct scr_info; /* serial_{in,out} because HUB6 */
|
3438 |
|
|
|
3439 |
|
|
#ifdef CONFIG_SERIAL_MANY_PORTS
|
3440 |
|
|
unsigned char save_ICP=0; /* no warning */
|
3441 |
|
|
unsigned short ICP=0;
|
3442 |
|
|
|
3443 |
|
|
if (state->flags & ASYNC_FOURPORT) {
|
3444 |
|
|
ICP = (state->port & 0xFE0) | 0x01F;
|
3445 |
|
|
save_ICP = inb_p(ICP);
|
3446 |
|
|
outb_p(0x80, ICP);
|
3447 |
|
|
(void) inb_p(ICP);
|
3448 |
|
|
}
|
3449 |
|
|
#endif
|
3450 |
|
|
scr_info.magic = SERIAL_MAGIC;
|
3451 |
|
|
scr_info.state = state;
|
3452 |
|
|
scr_info.port = state->port;
|
3453 |
|
|
scr_info.flags = state->flags;
|
3454 |
|
|
#ifdef CONFIG_HUB6
|
3455 |
|
|
scr_info.hub6 = state->hub6;
|
3456 |
|
|
#endif
|
3457 |
|
|
scr_info.io_type = state->io_type;
|
3458 |
|
|
scr_info.iomem_base = state->iomem_base;
|
3459 |
|
|
scr_info.iomem_reg_shift = state->iomem_reg_shift;
|
3460 |
|
|
|
3461 |
|
|
/* forget possible initially masked and pending IRQ */
|
3462 |
|
|
probe_irq_off(probe_irq_on());
|
3463 |
|
|
save_mcr = serial_inp(&scr_info, UART_MCR);
|
3464 |
|
|
save_ier = serial_inp(&scr_info, UART_IER);
|
3465 |
|
|
serial_outp(&scr_info, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
|
3466 |
|
|
|
3467 |
|
|
irqs = probe_irq_on();
|
3468 |
|
|
serial_outp(&scr_info, UART_MCR, 0);
|
3469 |
|
|
udelay (10);
|
3470 |
|
|
if (state->flags & ASYNC_FOURPORT) {
|
3471 |
|
|
serial_outp(&scr_info, UART_MCR,
|
3472 |
|
|
UART_MCR_DTR | UART_MCR_RTS);
|
3473 |
|
|
} else {
|
3474 |
|
|
serial_outp(&scr_info, UART_MCR,
|
3475 |
|
|
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
|
3476 |
|
|
}
|
3477 |
|
|
serial_outp(&scr_info, UART_IER, 0x0f); /* enable all intrs */
|
3478 |
|
|
(void)serial_inp(&scr_info, UART_LSR);
|
3479 |
|
|
(void)serial_inp(&scr_info, UART_RX);
|
3480 |
|
|
(void)serial_inp(&scr_info, UART_IIR);
|
3481 |
|
|
(void)serial_inp(&scr_info, UART_MSR);
|
3482 |
|
|
serial_outp(&scr_info, UART_TX, 0xFF);
|
3483 |
|
|
udelay (20);
|
3484 |
|
|
irq = probe_irq_off(irqs);
|
3485 |
|
|
|
3486 |
|
|
serial_outp(&scr_info, UART_MCR, save_mcr);
|
3487 |
|
|
serial_outp(&scr_info, UART_IER, save_ier);
|
3488 |
|
|
#ifdef CONFIG_SERIAL_MANY_PORTS
|
3489 |
|
|
if (state->flags & ASYNC_FOURPORT)
|
3490 |
|
|
outb_p(save_ICP, ICP);
|
3491 |
|
|
#endif
|
3492 |
|
|
return (irq > 0)? irq : 0;
|
3493 |
|
|
}
|
3494 |
|
|
|
3495 |
|
|
/*
|
3496 |
|
|
* This is a quickie test to see how big the FIFO is.
|
3497 |
|
|
* It doesn't work at all the time, more's the pity.
|
3498 |
|
|
*/
|
3499 |
|
|
static int size_fifo(struct async_struct *info)
|
3500 |
|
|
{
|
3501 |
|
|
unsigned char old_fcr, old_mcr, old_dll, old_dlm;
|
3502 |
|
|
int count;
|
3503 |
|
|
|
3504 |
|
|
old_fcr = serial_inp(info, UART_FCR);
|
3505 |
|
|
old_mcr = serial_inp(info, UART_MCR);
|
3506 |
|
|
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO |
|
3507 |
|
|
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
|
3508 |
|
|
serial_outp(info, UART_MCR, UART_MCR_LOOP);
|
3509 |
|
|
serial_outp(info, UART_LCR, UART_LCR_DLAB);
|
3510 |
|
|
old_dll = serial_inp(info, UART_DLL);
|
3511 |
|
|
old_dlm = serial_inp(info, UART_DLM);
|
3512 |
|
|
serial_outp(info, UART_DLL, 0x01);
|
3513 |
|
|
serial_outp(info, UART_DLM, 0x00);
|
3514 |
|
|
serial_outp(info, UART_LCR, 0x03);
|
3515 |
|
|
for (count = 0; count < 256; count++)
|
3516 |
|
|
serial_outp(info, UART_TX, count);
|
3517 |
|
|
mdelay(20);
|
3518 |
|
|
for (count = 0; (serial_inp(info, UART_LSR) & UART_LSR_DR) &&
|
3519 |
|
|
(count < 256); count++)
|
3520 |
|
|
serial_inp(info, UART_RX);
|
3521 |
|
|
serial_outp(info, UART_FCR, old_fcr);
|
3522 |
|
|
serial_outp(info, UART_MCR, old_mcr);
|
3523 |
|
|
serial_outp(info, UART_LCR, UART_LCR_DLAB);
|
3524 |
|
|
serial_outp(info, UART_DLL, old_dll);
|
3525 |
|
|
serial_outp(info, UART_DLM, old_dlm);
|
3526 |
|
|
|
3527 |
|
|
return count;
|
3528 |
|
|
}
|
3529 |
|
|
|
3530 |
|
|
/*
|
3531 |
|
|
* This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
|
3532 |
|
|
* When this function is called we know it is at least a StarTech
|
3533 |
|
|
* 16650 V2, but it might be one of several StarTech UARTs, or one of
|
3534 |
|
|
* its clones. (We treat the broken original StarTech 16650 V1 as a
|
3535 |
|
|
* 16550, and why not? Startech doesn't seem to even acknowledge its
|
3536 |
|
|
* existence.)
|
3537 |
|
|
*
|
3538 |
|
|
* What evil have men's minds wrought...
|
3539 |
|
|
*/
|
3540 |
|
|
static void autoconfig_startech_uarts(struct async_struct *info,
|
3541 |
|
|
struct serial_state *state,
|
3542 |
|
|
unsigned long flags)
|
3543 |
|
|
{
|
3544 |
|
|
unsigned char scratch, scratch2, scratch3, scratch4;
|
3545 |
|
|
|
3546 |
|
|
/*
|
3547 |
|
|
* First we check to see if it's an Oxford Semiconductor UART.
|
3548 |
|
|
*
|
3549 |
|
|
* If we have to do this here because some non-National
|
3550 |
|
|
* Semiconductor clone chips lock up if you try writing to the
|
3551 |
|
|
* LSR register (which serial_icr_read does)
|
3552 |
|
|
*/
|
3553 |
|
|
if (state->type == PORT_16550A) {
|
3554 |
|
|
/*
|
3555 |
|
|
* EFR [4] must be set else this test fails
|
3556 |
|
|
*
|
3557 |
|
|
* This shouldn't be necessary, but Mike Hudson
|
3558 |
|
|
* (Exoray@isys.ca) claims that it's needed for 952
|
3559 |
|
|
* dual UART's (which are not recommended for new designs).
|
3560 |
|
|
*/
|
3561 |
|
|
info->ACR = 0;
|
3562 |
|
|
serial_out(info, UART_LCR, 0xBF);
|
3563 |
|
|
serial_out(info, UART_EFR, 0x10);
|
3564 |
|
|
serial_out(info, UART_LCR, 0x00);
|
3565 |
|
|
/* Check for Oxford Semiconductor 16C950 */
|
3566 |
|
|
scratch = serial_icr_read(info, UART_ID1);
|
3567 |
|
|
scratch2 = serial_icr_read(info, UART_ID2);
|
3568 |
|
|
scratch3 = serial_icr_read(info, UART_ID3);
|
3569 |
|
|
|
3570 |
|
|
if (scratch == 0x16 && scratch2 == 0xC9 &&
|
3571 |
|
|
(scratch3 == 0x50 || scratch3 == 0x52 ||
|
3572 |
|
|
scratch3 == 0x54)) {
|
3573 |
|
|
state->type = PORT_16C950;
|
3574 |
|
|
state->revision = serial_icr_read(info, UART_REV) |
|
3575 |
|
|
(scratch3 << 8);
|
3576 |
|
|
return;
|
3577 |
|
|
}
|
3578 |
|
|
}
|
3579 |
|
|
|
3580 |
|
|
/*
|
3581 |
|
|
* We check for a XR16C850 by setting DLL and DLM to 0, and
|
3582 |
|
|
* then reading back DLL and DLM. If DLM reads back 0x10,
|
3583 |
|
|
* then the UART is a XR16C850 and the DLL contains the chip
|
3584 |
|
|
* revision. If DLM reads back 0x14, then the UART is a
|
3585 |
|
|
* XR16C854.
|
3586 |
|
|
*
|
3587 |
|
|
*/
|
3588 |
|
|
|
3589 |
|
|
/* Save the DLL and DLM */
|
3590 |
|
|
|
3591 |
|
|
serial_outp(info, UART_LCR, UART_LCR_DLAB);
|
3592 |
|
|
scratch3 = serial_inp(info, UART_DLL);
|
3593 |
|
|
scratch4 = serial_inp(info, UART_DLM);
|
3594 |
|
|
|
3595 |
|
|
serial_outp(info, UART_DLL, 0);
|
3596 |
|
|
serial_outp(info, UART_DLM, 0);
|
3597 |
|
|
scratch2 = serial_inp(info, UART_DLL);
|
3598 |
|
|
scratch = serial_inp(info, UART_DLM);
|
3599 |
|
|
serial_outp(info, UART_LCR, 0);
|
3600 |
|
|
|
3601 |
|
|
if (scratch == 0x10 || scratch == 0x14) {
|
3602 |
|
|
if (scratch == 0x10)
|
3603 |
|
|
state->revision = scratch2;
|
3604 |
|
|
state->type = PORT_16850;
|
3605 |
|
|
return;
|
3606 |
|
|
}
|
3607 |
|
|
|
3608 |
|
|
/* Restore the DLL and DLM */
|
3609 |
|
|
|
3610 |
|
|
serial_outp(info, UART_LCR, UART_LCR_DLAB);
|
3611 |
|
|
serial_outp(info, UART_DLL, scratch3);
|
3612 |
|
|
serial_outp(info, UART_DLM, scratch4);
|
3613 |
|
|
serial_outp(info, UART_LCR, 0);
|
3614 |
|
|
/*
|
3615 |
|
|
* We distinguish between the '654 and the '650 by counting
|
3616 |
|
|
* how many bytes are in the FIFO. I'm using this for now,
|
3617 |
|
|
* since that's the technique that was sent to me in the
|
3618 |
|
|
* serial driver update, but I'm not convinced this works.
|
3619 |
|
|
* I've had problems doing this in the past. -TYT
|
3620 |
|
|
*/
|
3621 |
|
|
if (size_fifo(info) == 64)
|
3622 |
|
|
state->type = PORT_16654;
|
3623 |
|
|
else
|
3624 |
|
|
state->type = PORT_16650V2;
|
3625 |
|
|
}
|
3626 |
|
|
|
3627 |
|
|
/*
|
3628 |
|
|
* This routine is called by rs_init() to initialize a specific serial
|
3629 |
|
|
* port. It determines what type of UART chip this serial port is
|
3630 |
|
|
* using: 8250, 16450, 16550, 16550A. The important question is
|
3631 |
|
|
* whether or not this UART is a 16550A or not, since this will
|
3632 |
|
|
* determine whether or not we can use its FIFO features or not.
|
3633 |
|
|
*/
|
3634 |
|
|
static void autoconfig(struct serial_state * state)
|
3635 |
|
|
{
|
3636 |
|
|
unsigned char status1, status2, scratch, scratch2, scratch3;
|
3637 |
|
|
unsigned char save_lcr, save_mcr;
|
3638 |
|
|
struct async_struct *info, scr_info;
|
3639 |
|
|
unsigned long flags;
|
3640 |
|
|
|
3641 |
|
|
state->type = PORT_UNKNOWN;
|
3642 |
|
|
|
3643 |
|
|
#ifdef SERIAL_DEBUG_AUTOCONF
|
3644 |
|
|
printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line,
|
3645 |
|
|
state->port, (unsigned) state->iomem_base);
|
3646 |
|
|
#endif
|
3647 |
|
|
|
3648 |
|
|
if (!CONFIGURED_SERIAL_PORT(state))
|
3649 |
|
|
return;
|
3650 |
|
|
|
3651 |
|
|
info = &scr_info; /* This is just for serial_{in,out} */
|
3652 |
|
|
|
3653 |
|
|
info->magic = SERIAL_MAGIC;
|
3654 |
|
|
info->state = state;
|
3655 |
|
|
info->port = state->port;
|
3656 |
|
|
info->flags = state->flags;
|
3657 |
|
|
#ifdef CONFIG_HUB6
|
3658 |
|
|
info->hub6 = state->hub6;
|
3659 |
|
|
#endif
|
3660 |
|
|
info->io_type = state->io_type;
|
3661 |
|
|
info->iomem_base = state->iomem_base;
|
3662 |
|
|
info->iomem_reg_shift = state->iomem_reg_shift;
|
3663 |
|
|
|
3664 |
|
|
save_flags(flags); cli();
|
3665 |
|
|
|
3666 |
|
|
if (!(state->flags & ASYNC_BUGGY_UART) &&
|
3667 |
|
|
!state->iomem_base) {
|
3668 |
|
|
/*
|
3669 |
|
|
* Do a simple existence test first; if we fail this,
|
3670 |
|
|
* there's no point trying anything else.
|
3671 |
|
|
*
|
3672 |
|
|
* 0x80 is used as a nonsense port to prevent against
|
3673 |
|
|
* false positives due to ISA bus float. The
|
3674 |
|
|
* assumption is that 0x80 is a non-existent port;
|
3675 |
|
|
* which should be safe since include/asm/io.h also
|
3676 |
|
|
* makes this assumption.
|
3677 |
|
|
*/
|
3678 |
|
|
scratch = serial_inp(info, UART_IER);
|
3679 |
|
|
serial_outp(info, UART_IER, 0);
|
3680 |
|
|
#ifdef __i386__
|
3681 |
|
|
outb(0xff, 0x080);
|
3682 |
|
|
#endif
|
3683 |
|
|
scratch2 = serial_inp(info, UART_IER);
|
3684 |
|
|
serial_outp(info, UART_IER, 0x0F);
|
3685 |
|
|
#ifdef __i386__
|
3686 |
|
|
outb(0, 0x080);
|
3687 |
|
|
#endif
|
3688 |
|
|
scratch3 = serial_inp(info, UART_IER);
|
3689 |
|
|
serial_outp(info, UART_IER, scratch);
|
3690 |
|
|
if (scratch2 || scratch3 != 0x0F) {
|
3691 |
|
|
#ifdef SERIAL_DEBUG_AUTOCONF
|
3692 |
|
|
printk("serial: ttyS%d: simple autoconfig failed "
|
3693 |
|
|
"(%02x, %02x)\n", state->line,
|
3694 |
|
|
scratch2, scratch3);
|
3695 |
|
|
#endif
|
3696 |
|
|
restore_flags(flags);
|
3697 |
|
|
return; /* We failed; there's nothing here */
|
3698 |
|
|
}
|
3699 |
|
|
}
|
3700 |
|
|
|
3701 |
|
|
save_mcr = serial_in(info, UART_MCR);
|
3702 |
|
|
save_lcr = serial_in(info, UART_LCR);
|
3703 |
|
|
|
3704 |
|
|
/*
|
3705 |
|
|
* Check to see if a UART is really there. Certain broken
|
3706 |
|
|
* internal modems based on the Rockwell chipset fail this
|
3707 |
|
|
* test, because they apparently don't implement the loopback
|
3708 |
|
|
* test mode. So this test is skipped on the COM 1 through
|
3709 |
|
|
* COM 4 ports. This *should* be safe, since no board
|
3710 |
|
|
* manufacturer would be stupid enough to design a board
|
3711 |
|
|
* that conflicts with COM 1-4 --- we hope!
|
3712 |
|
|
*/
|
3713 |
|
|
if (!(state->flags & ASYNC_SKIP_TEST)) {
|
3714 |
|
|
serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A);
|
3715 |
|
|
status1 = serial_inp(info, UART_MSR) & 0xF0;
|
3716 |
|
|
serial_outp(info, UART_MCR, save_mcr);
|
3717 |
|
|
if (status1 != 0x90) {
|
3718 |
|
|
#ifdef SERIAL_DEBUG_AUTOCONF
|
3719 |
|
|
printk("serial: ttyS%d: no UART loopback failed\n",
|
3720 |
|
|
state->line);
|
3721 |
|
|
#endif
|
3722 |
|
|
restore_flags(flags);
|
3723 |
|
|
return;
|
3724 |
|
|
}
|
3725 |
|
|
}
|
3726 |
|
|
serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */
|
3727 |
|
|
serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */
|
3728 |
|
|
serial_outp(info, UART_LCR, 0);
|
3729 |
|
|
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
|
3730 |
|
|
scratch = serial_in(info, UART_IIR) >> 6;
|
3731 |
|
|
switch (scratch) {
|
3732 |
|
|
case 0:
|
3733 |
|
|
state->type = PORT_16450;
|
3734 |
|
|
break;
|
3735 |
|
|
case 1:
|
3736 |
|
|
state->type = PORT_UNKNOWN;
|
3737 |
|
|
break;
|
3738 |
|
|
case 2:
|
3739 |
|
|
state->type = PORT_16550;
|
3740 |
|
|
break;
|
3741 |
|
|
case 3:
|
3742 |
|
|
state->type = PORT_16550A;
|
3743 |
|
|
break;
|
3744 |
|
|
}
|
3745 |
|
|
if (state->type == PORT_16550A) {
|
3746 |
|
|
/* Check for Startech UART's */
|
3747 |
|
|
serial_outp(info, UART_LCR, UART_LCR_DLAB);
|
3748 |
|
|
if (serial_in(info, UART_EFR) == 0) {
|
3749 |
|
|
serial_outp(info, UART_EFR, 0xA8);
|
3750 |
|
|
if (serial_in(info, UART_EFR) == 0) {
|
3751 |
|
|
/* We are a NS16552D/Motorola
|
3752 |
|
|
* 8xxx DUART, stop. */
|
3753 |
|
|
goto out;
|
3754 |
|
|
}
|
3755 |
|
|
state->type = PORT_16650;
|
3756 |
|
|
serial_outp(info, UART_EFR, 0);
|
3757 |
|
|
} else {
|
3758 |
|
|
serial_outp(info, UART_LCR, 0xBF);
|
3759 |
|
|
if (serial_in(info, UART_EFR) == 0)
|
3760 |
|
|
autoconfig_startech_uarts(info, state, flags);
|
3761 |
|
|
}
|
3762 |
|
|
}
|
3763 |
|
|
if (state->type == PORT_16550A) {
|
3764 |
|
|
/* Check for TI 16750 */
|
3765 |
|
|
serial_outp(info, UART_LCR, save_lcr | UART_LCR_DLAB);
|
3766 |
|
|
serial_outp(info, UART_FCR,
|
3767 |
|
|
UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
|
3768 |
|
|
scratch = serial_in(info, UART_IIR) >> 5;
|
3769 |
|
|
if (scratch == 7) {
|
3770 |
|
|
/*
|
3771 |
|
|
* If this is a 16750, and not a cheap UART
|
3772 |
|
|
* clone, then it should only go into 64 byte
|
3773 |
|
|
* mode if the UART_FCR7_64BYTE bit was set
|
3774 |
|
|
* while UART_LCR_DLAB was latched.
|
3775 |
|
|
*/
|
3776 |
|
|
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
|
3777 |
|
|
serial_outp(info, UART_LCR, 0);
|
3778 |
|
|
serial_outp(info, UART_FCR,
|
3779 |
|
|
UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
|
3780 |
|
|
scratch = serial_in(info, UART_IIR) >> 5;
|
3781 |
|
|
if (scratch == 6)
|
3782 |
|
|
state->type = PORT_16750;
|
3783 |
|
|
}
|
3784 |
|
|
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
|
3785 |
|
|
}
|
3786 |
|
|
#if defined(CONFIG_SERIAL_RSA) && defined(MODULE)
|
3787 |
|
|
if (state->type == PORT_16550A) {
|
3788 |
|
|
int i;
|
3789 |
|
|
|
3790 |
|
|
for (i = 0 ; i < PORT_RSA_MAX ; ++i) {
|
3791 |
|
|
if (!probe_rsa[i] && !force_rsa[i])
|
3792 |
|
|
break;
|
3793 |
|
|
if (((probe_rsa[i] != state->port) ||
|
3794 |
|
|
check_region(state->port + UART_RSA_BASE, 16)) &&
|
3795 |
|
|
(force_rsa[i] != state->port))
|
3796 |
|
|
continue;
|
3797 |
|
|
if (!enable_rsa(info))
|
3798 |
|
|
continue;
|
3799 |
|
|
state->type = PORT_RSA;
|
3800 |
|
|
state->baud_base = SERIAL_RSA_BAUD_BASE;
|
3801 |
|
|
break;
|
3802 |
|
|
}
|
3803 |
|
|
}
|
3804 |
|
|
#endif
|
3805 |
|
|
out:
|
3806 |
|
|
serial_outp(info, UART_LCR, save_lcr);
|
3807 |
|
|
if (state->type == PORT_16450) {
|
3808 |
|
|
scratch = serial_in(info, UART_SCR);
|
3809 |
|
|
serial_outp(info, UART_SCR, 0xa5);
|
3810 |
|
|
status1 = serial_in(info, UART_SCR);
|
3811 |
|
|
serial_outp(info, UART_SCR, 0x5a);
|
3812 |
|
|
status2 = serial_in(info, UART_SCR);
|
3813 |
|
|
serial_outp(info, UART_SCR, scratch);
|
3814 |
|
|
|
3815 |
|
|
if ((status1 != 0xa5) || (status2 != 0x5a))
|
3816 |
|
|
state->type = PORT_8250;
|
3817 |
|
|
}
|
3818 |
|
|
state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size;
|
3819 |
|
|
|
3820 |
|
|
if (state->type == PORT_UNKNOWN) {
|
3821 |
|
|
restore_flags(flags);
|
3822 |
|
|
return;
|
3823 |
|
|
}
|
3824 |
|
|
|
3825 |
|
|
if (info->port) {
|
3826 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
3827 |
|
|
if (state->type == PORT_RSA)
|
3828 |
|
|
request_region(info->port + UART_RSA_BASE, 16,
|
3829 |
|
|
"serial_rsa(auto)");
|
3830 |
|
|
else
|
3831 |
|
|
#endif
|
3832 |
|
|
request_region(info->port,8,"serial(auto)");
|
3833 |
|
|
}
|
3834 |
|
|
|
3835 |
|
|
/*
|
3836 |
|
|
* Reset the UART.
|
3837 |
|
|
*/
|
3838 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
3839 |
|
|
if (state->type == PORT_RSA)
|
3840 |
|
|
serial_outp(info, UART_RSA_FRR, 0);
|
3841 |
|
|
#endif
|
3842 |
|
|
serial_outp(info, UART_MCR, save_mcr);
|
3843 |
|
|
serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
|
3844 |
|
|
UART_FCR_CLEAR_RCVR |
|
3845 |
|
|
UART_FCR_CLEAR_XMIT));
|
3846 |
|
|
serial_outp(info, UART_FCR, 0);
|
3847 |
|
|
(void)serial_in(info, UART_RX);
|
3848 |
|
|
serial_outp(info, UART_IER, 0);
|
3849 |
|
|
|
3850 |
|
|
restore_flags(flags);
|
3851 |
|
|
}
|
3852 |
|
|
|
3853 |
|
|
int register_serial(struct serial_struct *req);
|
3854 |
|
|
void unregister_serial(int line);
|
3855 |
|
|
|
3856 |
|
|
#if (LINUX_VERSION_CODE > 0x20100)
|
3857 |
|
|
EXPORT_SYMBOL(register_serial);
|
3858 |
|
|
EXPORT_SYMBOL(unregister_serial);
|
3859 |
|
|
#else
|
3860 |
|
|
static struct symbol_table serial_syms = {
|
3861 |
|
|
#include <linux/symtab_begin.h>
|
3862 |
|
|
X(register_serial),
|
3863 |
|
|
X(unregister_serial),
|
3864 |
|
|
#include <linux/symtab_end.h>
|
3865 |
|
|
};
|
3866 |
|
|
#endif
|
3867 |
|
|
|
3868 |
|
|
|
3869 |
|
|
#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)
|
3870 |
|
|
|
3871 |
|
|
static void __devinit printk_pnp_dev_id(unsigned short vendor,
|
3872 |
|
|
unsigned short device)
|
3873 |
|
|
{
|
3874 |
|
|
printk("%c%c%c%x%x%x%x",
|
3875 |
|
|
'A' + ((vendor >> 2) & 0x3f) - 1,
|
3876 |
|
|
'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
|
3877 |
|
|
'A' + ((vendor >> 8) & 0x1f) - 1,
|
3878 |
|
|
(device >> 4) & 0x0f,
|
3879 |
|
|
device & 0x0f,
|
3880 |
|
|
(device >> 12) & 0x0f,
|
3881 |
|
|
(device >> 8) & 0x0f);
|
3882 |
|
|
}
|
3883 |
|
|
|
3884 |
|
|
static _INLINE_ int get_pci_port(struct pci_dev *dev,
|
3885 |
|
|
struct pci_board *board,
|
3886 |
|
|
struct serial_struct *req,
|
3887 |
|
|
int idx)
|
3888 |
|
|
{
|
3889 |
|
|
unsigned long port;
|
3890 |
|
|
int base_idx;
|
3891 |
|
|
int max_port;
|
3892 |
|
|
int offset;
|
3893 |
|
|
|
3894 |
|
|
base_idx = SPCI_FL_GET_BASE(board->flags);
|
3895 |
|
|
if (board->flags & SPCI_FL_BASE_TABLE)
|
3896 |
|
|
base_idx += idx;
|
3897 |
|
|
|
3898 |
|
|
if (board->flags & SPCI_FL_REGION_SZ_CAP) {
|
3899 |
|
|
max_port = pci_resource_len(dev, base_idx) / 8;
|
3900 |
|
|
if (idx >= max_port)
|
3901 |
|
|
return 1;
|
3902 |
|
|
}
|
3903 |
|
|
|
3904 |
|
|
offset = board->first_uart_offset;
|
3905 |
|
|
|
3906 |
|
|
/* Timedia/SUNIX uses a mixture of BARs and offsets */
|
3907 |
|
|
/* Ugh, this is ugly as all hell --- TYT */
|
3908 |
|
|
if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */
|
3909 |
|
|
switch(idx) {
|
3910 |
|
|
case 0: base_idx=0;
|
3911 |
|
|
break;
|
3912 |
|
|
case 1: base_idx=0; offset=8;
|
3913 |
|
|
break;
|
3914 |
|
|
case 2: base_idx=1;
|
3915 |
|
|
break;
|
3916 |
|
|
case 3: base_idx=1; offset=8;
|
3917 |
|
|
break;
|
3918 |
|
|
case 4: /* BAR 2*/
|
3919 |
|
|
case 5: /* BAR 3 */
|
3920 |
|
|
case 6: /* BAR 4*/
|
3921 |
|
|
case 7: base_idx=idx-2; /* BAR 5*/
|
3922 |
|
|
}
|
3923 |
|
|
|
3924 |
|
|
/* Some Titan cards are also a little weird */
|
3925 |
|
|
if (dev->vendor == PCI_VENDOR_ID_TITAN &&
|
3926 |
|
|
(dev->device == PCI_DEVICE_ID_TITAN_400L ||
|
3927 |
|
|
dev->device == PCI_DEVICE_ID_TITAN_800L)) {
|
3928 |
|
|
switch (idx) {
|
3929 |
|
|
case 0: base_idx = 1;
|
3930 |
|
|
break;
|
3931 |
|
|
case 1: base_idx = 2;
|
3932 |
|
|
break;
|
3933 |
|
|
default:
|
3934 |
|
|
base_idx = 4;
|
3935 |
|
|
offset = 8 * (idx - 2);
|
3936 |
|
|
}
|
3937 |
|
|
|
3938 |
|
|
}
|
3939 |
|
|
|
3940 |
|
|
/* HP's Diva chip puts the 4th/5th serial port further out, and
|
3941 |
|
|
* some serial ports are supposed to be hidden on certain models.
|
3942 |
|
|
*/
|
3943 |
|
|
if (dev->vendor == PCI_VENDOR_ID_HP &&
|
3944 |
|
|
dev->device == PCI_DEVICE_ID_HP_SAS) {
|
3945 |
|
|
switch (dev->subsystem_device) {
|
3946 |
|
|
case 0x104B: /* Maestro */
|
3947 |
|
|
if (idx == 3) idx++;
|
3948 |
|
|
break;
|
3949 |
|
|
case 0x1282: /* Everest / Longs Peak */
|
3950 |
|
|
if (idx > 0) idx++;
|
3951 |
|
|
if (idx > 2) idx++;
|
3952 |
|
|
break;
|
3953 |
|
|
}
|
3954 |
|
|
if (idx > 2) {
|
3955 |
|
|
offset = 0x18;
|
3956 |
|
|
}
|
3957 |
|
|
}
|
3958 |
|
|
|
3959 |
|
|
port = pci_resource_start(dev, base_idx) + offset;
|
3960 |
|
|
|
3961 |
|
|
if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
|
3962 |
|
|
port += idx * (board->uart_offset ? board->uart_offset : 8);
|
3963 |
|
|
|
3964 |
|
|
if (IS_PCI_REGION_IOPORT(dev, base_idx)) {
|
3965 |
|
|
req->port = port;
|
3966 |
|
|
if (HIGH_BITS_OFFSET)
|
3967 |
|
|
req->port_high = port >> HIGH_BITS_OFFSET;
|
3968 |
|
|
else
|
3969 |
|
|
req->port_high = 0;
|
3970 |
|
|
return 0;
|
3971 |
|
|
}
|
3972 |
|
|
req->io_type = SERIAL_IO_MEM;
|
3973 |
|
|
req->iomem_base = ioremap(port, board->uart_offset);
|
3974 |
|
|
req->iomem_reg_shift = board->reg_shift;
|
3975 |
|
|
req->port = 0;
|
3976 |
|
|
return 0;
|
3977 |
|
|
}
|
3978 |
|
|
|
3979 |
|
|
static _INLINE_ int get_pci_irq(struct pci_dev *dev,
|
3980 |
|
|
struct pci_board *board,
|
3981 |
|
|
int idx)
|
3982 |
|
|
{
|
3983 |
|
|
int base_idx;
|
3984 |
|
|
|
3985 |
|
|
if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
|
3986 |
|
|
return dev->irq;
|
3987 |
|
|
|
3988 |
|
|
base_idx = SPCI_FL_GET_IRQBASE(board->flags);
|
3989 |
|
|
if (board->flags & SPCI_FL_IRQ_TABLE)
|
3990 |
|
|
base_idx += idx;
|
3991 |
|
|
|
3992 |
|
|
return PCI_IRQ_RESOURCE(dev, base_idx);
|
3993 |
|
|
}
|
3994 |
|
|
|
3995 |
|
|
/*
|
3996 |
|
|
* Common enabler code shared by both PCI and ISAPNP probes
|
3997 |
|
|
*/
|
3998 |
|
|
static void __devinit start_pci_pnp_board(struct pci_dev *dev,
|
3999 |
|
|
struct pci_board *board)
|
4000 |
|
|
{
|
4001 |
|
|
int k, line;
|
4002 |
|
|
struct serial_struct serial_req;
|
4003 |
|
|
int base_baud;
|
4004 |
|
|
|
4005 |
|
|
if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) {
|
4006 |
|
|
printk("serial: PNP device '");
|
4007 |
|
|
printk_pnp_dev_id(dev->vendor, dev->device);
|
4008 |
|
|
printk("' prepare failed\n");
|
4009 |
|
|
return;
|
4010 |
|
|
}
|
4011 |
|
|
|
4012 |
|
|
if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) {
|
4013 |
|
|
printk("serial: PNP device '");
|
4014 |
|
|
printk_pnp_dev_id(dev->vendor, dev->device);
|
4015 |
|
|
printk("' activate failed\n");
|
4016 |
|
|
return;
|
4017 |
|
|
}
|
4018 |
|
|
|
4019 |
|
|
/*
|
4020 |
|
|
* Run the initialization function, if any
|
4021 |
|
|
*/
|
4022 |
|
|
if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0))
|
4023 |
|
|
return;
|
4024 |
|
|
|
4025 |
|
|
/*
|
4026 |
|
|
* Register the serial board in the array if we need to
|
4027 |
|
|
* shutdown the board on a module unload or card removal
|
4028 |
|
|
*/
|
4029 |
|
|
if (DEACTIVATE_FUNC(dev) || board->init_fn) {
|
4030 |
|
|
for (k=0; k < NR_PCI_BOARDS; k++)
|
4031 |
|
|
if (serial_pci_board[k].dev == 0)
|
4032 |
|
|
break;
|
4033 |
|
|
if (k >= NR_PCI_BOARDS)
|
4034 |
|
|
return;
|
4035 |
|
|
serial_pci_board[k].board = *board;
|
4036 |
|
|
serial_pci_board[k].dev = dev;
|
4037 |
|
|
}
|
4038 |
|
|
|
4039 |
|
|
base_baud = board->base_baud;
|
4040 |
|
|
if (!base_baud)
|
4041 |
|
|
base_baud = BASE_BAUD;
|
4042 |
|
|
memset(&serial_req, 0, sizeof(serial_req));
|
4043 |
|
|
|
4044 |
|
|
for (k=0; k < board->num_ports; k++) {
|
4045 |
|
|
serial_req.irq = get_pci_irq(dev, board, k);
|
4046 |
|
|
if (get_pci_port(dev, board, &serial_req, k))
|
4047 |
|
|
break;
|
4048 |
|
|
serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
|
4049 |
|
|
#ifdef SERIAL_DEBUG_PCI
|
4050 |
|
|
printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
|
4051 |
|
|
serial_req.port, serial_req.irq, serial_req.io_type);
|
4052 |
|
|
#endif
|
4053 |
|
|
line = register_serial(&serial_req);
|
4054 |
|
|
if (line < 0)
|
4055 |
|
|
break;
|
4056 |
|
|
rs_table[line].baud_base = base_baud;
|
4057 |
|
|
rs_table[line].dev = dev;
|
4058 |
|
|
}
|
4059 |
|
|
}
|
4060 |
|
|
#endif /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */
|
4061 |
|
|
|
4062 |
|
|
#ifdef ENABLE_SERIAL_PCI
|
4063 |
|
|
/*
|
4064 |
|
|
* Some PCI serial cards using the PLX 9050 PCI interface chip require
|
4065 |
|
|
* that the card interrupt be explicitly enabled or disabled. This
|
4066 |
|
|
* seems to be mainly needed on card using the PLX which also use I/O
|
4067 |
|
|
* mapped memory.
|
4068 |
|
|
*/
|
4069 |
|
|
static int __devinit
|
4070 |
|
|
pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable)
|
4071 |
|
|
{
|
4072 |
|
|
u8 data, *p, irq_config;
|
4073 |
|
|
int pci_config;
|
4074 |
|
|
|
4075 |
|
|
irq_config = 0x41;
|
4076 |
|
|
pci_config = PCI_COMMAND_MEMORY;
|
4077 |
|
|
if (dev->vendor == PCI_VENDOR_ID_PANACOM)
|
4078 |
|
|
irq_config = 0x43;
|
4079 |
|
|
if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
|
4080 |
|
|
(dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
|
4081 |
|
|
/*
|
4082 |
|
|
* As the megawolf cards have the int pins active
|
4083 |
|
|
* high, and have 2 UART chips, both ints must be
|
4084 |
|
|
* enabled on the 9050. Also, the UARTS are set in
|
4085 |
|
|
* 16450 mode by default, so we have to enable the
|
4086 |
|
|
* 16C950 'enhanced' mode so that we can use the deep
|
4087 |
|
|
* FIFOs
|
4088 |
|
|
*/
|
4089 |
|
|
irq_config = 0x5b;
|
4090 |
|
|
pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
|
4091 |
|
|
}
|
4092 |
|
|
|
4093 |
|
|
pci_read_config_byte(dev, PCI_COMMAND, &data);
|
4094 |
|
|
|
4095 |
|
|
if (enable)
|
4096 |
|
|
pci_write_config_byte(dev, PCI_COMMAND,
|
4097 |
|
|
data | pci_config);
|
4098 |
|
|
|
4099 |
|
|
/* enable/disable interrupts */
|
4100 |
|
|
p = ioremap(pci_resource_start(dev, 0), 0x80);
|
4101 |
|
|
writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c);
|
4102 |
|
|
iounmap(p);
|
4103 |
|
|
|
4104 |
|
|
if (!enable)
|
4105 |
|
|
pci_write_config_byte(dev, PCI_COMMAND,
|
4106 |
|
|
data & ~pci_config);
|
4107 |
|
|
return 0;
|
4108 |
|
|
}
|
4109 |
|
|
|
4110 |
|
|
|
4111 |
|
|
/*
|
4112 |
|
|
* SIIG serial cards have an PCI interface chip which also controls
|
4113 |
|
|
* the UART clocking frequency. Each UART can be clocked independently
|
4114 |
|
|
* (except cards equiped with 4 UARTs) and initial clocking settings
|
4115 |
|
|
* are stored in the EEPROM chip. It can cause problems because this
|
4116 |
|
|
* version of serial driver doesn't support differently clocked UART's
|
4117 |
|
|
* on single PCI card. To prevent this, initialization functions set
|
4118 |
|
|
* high frequency clocking for all UART's on given card. It is safe (I
|
4119 |
|
|
* hope) because it doesn't touch EEPROM settings to prevent conflicts
|
4120 |
|
|
* with other OSes (like M$ DOS).
|
4121 |
|
|
*
|
4122 |
|
|
* SIIG support added by Andrey Panin <pazke@mail.tp.ru>, 10/1999
|
4123 |
|
|
*
|
4124 |
|
|
* There is two family of SIIG serial cards with different PCI
|
4125 |
|
|
* interface chip and different configuration methods:
|
4126 |
|
|
* - 10x cards have control registers in IO and/or memory space;
|
4127 |
|
|
* - 20x cards have control registers in standard PCI configuration space.
|
4128 |
|
|
*
|
4129 |
|
|
* SIIG initialization functions exported for use by parport_serial.c module.
|
4130 |
|
|
*/
|
4131 |
|
|
|
4132 |
|
|
#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
|
4133 |
|
|
#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
|
4134 |
|
|
|
4135 |
|
|
int __devinit
|
4136 |
|
|
pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
|
4137 |
|
|
{
|
4138 |
|
|
u16 data, *p;
|
4139 |
|
|
|
4140 |
|
|
if (!enable) return 0;
|
4141 |
|
|
|
4142 |
|
|
p = ioremap(pci_resource_start(dev, 0), 0x80);
|
4143 |
|
|
|
4144 |
|
|
switch (dev->device & 0xfff8) {
|
4145 |
|
|
case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
|
4146 |
|
|
data = 0xffdf;
|
4147 |
|
|
break;
|
4148 |
|
|
case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
|
4149 |
|
|
data = 0xf7ff;
|
4150 |
|
|
break;
|
4151 |
|
|
default: /* 1S1P, 4S */
|
4152 |
|
|
data = 0xfffb;
|
4153 |
|
|
break;
|
4154 |
|
|
}
|
4155 |
|
|
|
4156 |
|
|
writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
|
4157 |
|
|
iounmap(p);
|
4158 |
|
|
return 0;
|
4159 |
|
|
}
|
4160 |
|
|
EXPORT_SYMBOL(pci_siig10x_fn);
|
4161 |
|
|
|
4162 |
|
|
#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
|
4163 |
|
|
#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
|
4164 |
|
|
|
4165 |
|
|
int __devinit
|
4166 |
|
|
pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
|
4167 |
|
|
{
|
4168 |
|
|
u8 data;
|
4169 |
|
|
|
4170 |
|
|
if (!enable) return 0;
|
4171 |
|
|
|
4172 |
|
|
/* Change clock frequency for the first UART. */
|
4173 |
|
|
pci_read_config_byte(dev, 0x6f, &data);
|
4174 |
|
|
pci_write_config_byte(dev, 0x6f, data & 0xef);
|
4175 |
|
|
|
4176 |
|
|
/* If this card has 2 UART, we have to do the same with second UART. */
|
4177 |
|
|
if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
|
4178 |
|
|
((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
|
4179 |
|
|
pci_read_config_byte(dev, 0x73, &data);
|
4180 |
|
|
pci_write_config_byte(dev, 0x73, data & 0xef);
|
4181 |
|
|
}
|
4182 |
|
|
return 0;
|
4183 |
|
|
}
|
4184 |
|
|
EXPORT_SYMBOL(pci_siig20x_fn);
|
4185 |
|
|
|
4186 |
|
|
/* Added for EKF Intel i960 serial boards */
|
4187 |
|
|
static int __devinit
|
4188 |
|
|
pci_inteli960ni_fn(struct pci_dev *dev,
|
4189 |
|
|
struct pci_board *board,
|
4190 |
|
|
int enable)
|
4191 |
|
|
{
|
4192 |
|
|
unsigned long oldval;
|
4193 |
|
|
|
4194 |
|
|
if (!(pci_get_subdevice(dev) & 0x1000))
|
4195 |
|
|
return(-1);
|
4196 |
|
|
|
4197 |
|
|
if (!enable) /* is there something to deinit? */
|
4198 |
|
|
return(0);
|
4199 |
|
|
|
4200 |
|
|
#ifdef SERIAL_DEBUG_PCI
|
4201 |
|
|
printk(KERN_DEBUG " Subsystem ID %lx (intel 960)\n",
|
4202 |
|
|
(unsigned long) board->subdevice);
|
4203 |
|
|
#endif
|
4204 |
|
|
/* is firmware started? */
|
4205 |
|
|
pci_read_config_dword(dev, 0x44, (void*) &oldval);
|
4206 |
|
|
if (oldval == 0x00001000L) { /* RESET value */
|
4207 |
|
|
printk(KERN_DEBUG "Local i960 firmware missing");
|
4208 |
|
|
return(-1);
|
4209 |
|
|
}
|
4210 |
|
|
return(0);
|
4211 |
|
|
}
|
4212 |
|
|
|
4213 |
|
|
/*
|
4214 |
|
|
* Timedia has an explosion of boards, and to avoid the PCI table from
|
4215 |
|
|
* growing *huge*, we use this function to collapse some 70 entries
|
4216 |
|
|
* in the PCI table into one, for sanity's and compactness's sake.
|
4217 |
|
|
*/
|
4218 |
|
|
static unsigned short timedia_single_port[] = {
|
4219 |
|
|
0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 };
|
4220 |
|
|
static unsigned short timedia_dual_port[] = {
|
4221 |
|
|
0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
|
4222 |
|
|
0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
|
4223 |
|
|
0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
|
4224 |
|
|
0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
|
4225 |
|
|
0xD079, 0 };
|
4226 |
|
|
static unsigned short timedia_quad_port[] = {
|
4227 |
|
|
0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
|
4228 |
|
|
0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
|
4229 |
|
|
0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
|
4230 |
|
|
0xB157, 0 };
|
4231 |
|
|
static unsigned short timedia_eight_port[] = {
|
4232 |
|
|
0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
|
4233 |
|
|
0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 };
|
4234 |
|
|
static struct timedia_struct {
|
4235 |
|
|
int num;
|
4236 |
|
|
unsigned short *ids;
|
4237 |
|
|
} timedia_data[] = {
|
4238 |
|
|
{ 1, timedia_single_port },
|
4239 |
|
|
{ 2, timedia_dual_port },
|
4240 |
|
|
{ 4, timedia_quad_port },
|
4241 |
|
|
{ 8, timedia_eight_port },
|
4242 |
|
|
{ 0, 0 }
|
4243 |
|
|
};
|
4244 |
|
|
|
4245 |
|
|
static int __devinit
|
4246 |
|
|
pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable)
|
4247 |
|
|
{
|
4248 |
|
|
int i, j;
|
4249 |
|
|
unsigned short *ids;
|
4250 |
|
|
|
4251 |
|
|
if (!enable)
|
4252 |
|
|
return 0;
|
4253 |
|
|
|
4254 |
|
|
for (i=0; timedia_data[i].num; i++) {
|
4255 |
|
|
ids = timedia_data[i].ids;
|
4256 |
|
|
for (j=0; ids[j]; j++) {
|
4257 |
|
|
if (pci_get_subdevice(dev) == ids[j]) {
|
4258 |
|
|
board->num_ports = timedia_data[i].num;
|
4259 |
|
|
return 0;
|
4260 |
|
|
}
|
4261 |
|
|
}
|
4262 |
|
|
}
|
4263 |
|
|
return 0;
|
4264 |
|
|
}
|
4265 |
|
|
|
4266 |
|
|
/*
|
4267 |
|
|
* HP's Remote Management Console. The Diva chip came in several
|
4268 |
|
|
* different versions. N-class, L2000 and A500 have two Diva chips, each
|
4269 |
|
|
* with 3 UARTs (the third UART on the second chip is unused). Superdome
|
4270 |
|
|
* and Keystone have one Diva chip with 3 UARTs. Some later machines have
|
4271 |
|
|
* one Diva chip, but it has been expanded to 5 UARTs.
|
4272 |
|
|
*/
|
4273 |
|
|
static int __devinit
|
4274 |
|
|
pci_hp_diva(struct pci_dev *dev, struct pci_board *board, int enable)
|
4275 |
|
|
{
|
4276 |
|
|
if (!enable)
|
4277 |
|
|
return 0;
|
4278 |
|
|
|
4279 |
|
|
switch (dev->subsystem_device) {
|
4280 |
|
|
case 0x1049: /* Prelude Diva 1 */
|
4281 |
|
|
case 0x1223: /* Superdome */
|
4282 |
|
|
case 0x1226: /* Keystone */
|
4283 |
|
|
case 0x1282: /* Everest / Longs Peak */
|
4284 |
|
|
board->num_ports = 3;
|
4285 |
|
|
break;
|
4286 |
|
|
case 0x104A: /* Prelude Diva 2 */
|
4287 |
|
|
board->num_ports = 2;
|
4288 |
|
|
break;
|
4289 |
|
|
case 0x104B: /* Maestro */
|
4290 |
|
|
board->num_ports = 4;
|
4291 |
|
|
break;
|
4292 |
|
|
case 0x1227: /* Powerbar */
|
4293 |
|
|
board->num_ports = 1;
|
4294 |
|
|
break;
|
4295 |
|
|
}
|
4296 |
|
|
|
4297 |
|
|
return 0;
|
4298 |
|
|
}
|
4299 |
|
|
|
4300 |
|
|
static int __devinit
|
4301 |
|
|
pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable)
|
4302 |
|
|
{
|
4303 |
|
|
__set_current_state(TASK_UNINTERRUPTIBLE);
|
4304 |
|
|
schedule_timeout(HZ/10);
|
4305 |
|
|
return 0;
|
4306 |
|
|
}
|
4307 |
|
|
|
4308 |
|
|
/*
|
4309 |
|
|
* This is the configuration table for all of the PCI serial boards
|
4310 |
|
|
* which we support. It is directly indexed by the pci_board_num_t enum
|
4311 |
|
|
* value, which is encoded in the pci_device_id PCI probe table's
|
4312 |
|
|
* driver_data member.
|
4313 |
|
|
*/
|
4314 |
|
|
enum pci_board_num_t {
|
4315 |
|
|
pbn_b0_1_115200,
|
4316 |
|
|
pbn_default = 0,
|
4317 |
|
|
|
4318 |
|
|
pbn_b0_2_115200,
|
4319 |
|
|
pbn_b0_4_115200,
|
4320 |
|
|
|
4321 |
|
|
pbn_b0_1_921600,
|
4322 |
|
|
pbn_b0_2_921600,
|
4323 |
|
|
pbn_b0_4_921600,
|
4324 |
|
|
|
4325 |
|
|
pbn_b0_bt_1_115200,
|
4326 |
|
|
pbn_b0_bt_2_115200,
|
4327 |
|
|
pbn_b0_bt_1_460800,
|
4328 |
|
|
pbn_b0_bt_2_460800,
|
4329 |
|
|
pbn_b0_bt_2_921600,
|
4330 |
|
|
|
4331 |
|
|
pbn_b1_1_115200,
|
4332 |
|
|
pbn_b1_2_115200,
|
4333 |
|
|
pbn_b1_4_115200,
|
4334 |
|
|
pbn_b1_8_115200,
|
4335 |
|
|
|
4336 |
|
|
pbn_b1_2_921600,
|
4337 |
|
|
pbn_b1_4_921600,
|
4338 |
|
|
pbn_b1_8_921600,
|
4339 |
|
|
|
4340 |
|
|
pbn_b1_2_1382400,
|
4341 |
|
|
pbn_b1_4_1382400,
|
4342 |
|
|
pbn_b1_8_1382400,
|
4343 |
|
|
|
4344 |
|
|
pbn_b2_1_115200,
|
4345 |
|
|
pbn_b2_8_115200,
|
4346 |
|
|
pbn_b2_4_460800,
|
4347 |
|
|
pbn_b2_8_460800,
|
4348 |
|
|
pbn_b2_16_460800,
|
4349 |
|
|
pbn_b2_4_921600,
|
4350 |
|
|
pbn_b2_8_921600,
|
4351 |
|
|
|
4352 |
|
|
pbn_b2_bt_1_115200,
|
4353 |
|
|
pbn_b2_bt_2_115200,
|
4354 |
|
|
pbn_b2_bt_4_115200,
|
4355 |
|
|
pbn_b2_bt_2_921600,
|
4356 |
|
|
|
4357 |
|
|
pbn_panacom,
|
4358 |
|
|
pbn_panacom2,
|
4359 |
|
|
pbn_panacom4,
|
4360 |
|
|
pbn_plx_romulus,
|
4361 |
|
|
pbn_oxsemi,
|
4362 |
|
|
pbn_timedia,
|
4363 |
|
|
pbn_intel_i960,
|
4364 |
|
|
pbn_sgi_ioc3,
|
4365 |
|
|
pbn_hp_diva,
|
4366 |
|
|
#ifdef CONFIG_DDB5074
|
4367 |
|
|
pbn_nec_nile4,
|
4368 |
|
|
#endif
|
4369 |
|
|
|
4370 |
|
|
pbn_dci_pccom4,
|
4371 |
|
|
pbn_dci_pccom8,
|
4372 |
|
|
|
4373 |
|
|
pbn_xircom_combo,
|
4374 |
|
|
|
4375 |
|
|
pbn_siig10x_0,
|
4376 |
|
|
pbn_siig10x_1,
|
4377 |
|
|
pbn_siig10x_2,
|
4378 |
|
|
pbn_siig10x_4,
|
4379 |
|
|
pbn_siig20x_0,
|
4380 |
|
|
pbn_siig20x_2,
|
4381 |
|
|
pbn_siig20x_4,
|
4382 |
|
|
|
4383 |
|
|
pbn_computone_4,
|
4384 |
|
|
pbn_computone_6,
|
4385 |
|
|
pbn_computone_8,
|
4386 |
|
|
};
|
4387 |
|
|
|
4388 |
|
|
static struct pci_board pci_boards[] __devinitdata = {
|
4389 |
|
|
/*
|
4390 |
|
|
* PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
|
4391 |
|
|
* Offset to get to next UART's registers,
|
4392 |
|
|
* Register shift to use for memory-mapped I/O,
|
4393 |
|
|
* Initialization function, first UART offset
|
4394 |
|
|
*/
|
4395 |
|
|
|
4396 |
|
|
/* Generic serial board, pbn_b0_1_115200, pbn_default */
|
4397 |
|
|
{ SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200,
|
4398 |
|
|
pbn_default */
|
4399 |
|
|
|
4400 |
|
|
{ SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */
|
4401 |
|
|
{ SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */
|
4402 |
|
|
|
4403 |
|
|
{ SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */
|
4404 |
|
|
{ SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */
|
4405 |
|
|
{ SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */
|
4406 |
|
|
|
4407 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */
|
4408 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */
|
4409 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */
|
4410 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */
|
4411 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b0_bt_2_921600 */
|
4412 |
|
|
|
4413 |
|
|
{ SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */
|
4414 |
|
|
{ SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */
|
4415 |
|
|
{ SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */
|
4416 |
|
|
{ SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */
|
4417 |
|
|
|
4418 |
|
|
{ SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */
|
4419 |
|
|
{ SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */
|
4420 |
|
|
{ SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */
|
4421 |
|
|
|
4422 |
|
|
{ SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */
|
4423 |
|
|
{ SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */
|
4424 |
|
|
{ SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */
|
4425 |
|
|
|
4426 |
|
|
{ SPCI_FL_BASE2, 1, 115200 }, /* pbn_b2_1_115200 */
|
4427 |
|
|
{ SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */
|
4428 |
|
|
{ SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */
|
4429 |
|
|
{ SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */
|
4430 |
|
|
{ SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */
|
4431 |
|
|
{ SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */
|
4432 |
|
|
{ SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */
|
4433 |
|
|
|
4434 |
|
|
{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */
|
4435 |
|
|
{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */
|
4436 |
|
|
{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */
|
4437 |
|
|
{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */
|
4438 |
|
|
|
4439 |
|
|
{ SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */
|
4440 |
|
|
0x400, 7, pci_plx9050_fn },
|
4441 |
|
|
{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */
|
4442 |
|
|
0x400, 7, pci_plx9050_fn },
|
4443 |
|
|
{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */
|
4444 |
|
|
0x400, 7, pci_plx9050_fn },
|
4445 |
|
|
{ SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */
|
4446 |
|
|
0x20, 2, pci_plx9050_fn, 0x03 },
|
4447 |
|
|
/* This board uses the size of PCI Base region 0 to
|
4448 |
|
|
* signal now many ports are available */
|
4449 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */
|
4450 |
|
|
{ SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */
|
4451 |
|
|
0, 0, pci_timedia_fn },
|
4452 |
|
|
/* EKF addition for i960 Boards form EKF with serial port */
|
4453 |
|
|
{ SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */
|
4454 |
|
|
8<<2, 2, pci_inteli960ni_fn, 0x10000},
|
4455 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */
|
4456 |
|
|
1, 458333, 0, 0, 0, 0x20178 },
|
4457 |
|
|
{ SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0}, /* pbn_hp_diva */
|
4458 |
|
|
#ifdef CONFIG_DDB5074
|
4459 |
|
|
/*
|
4460 |
|
|
* NEC Vrc-5074 (Nile 4) builtin UART.
|
4461 |
|
|
* Conditionally compiled in since this is a motherboard device.
|
4462 |
|
|
*/
|
4463 |
|
|
{ SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */
|
4464 |
|
|
64, 3, NULL, 0x300 },
|
4465 |
|
|
#endif
|
4466 |
|
|
|
4467 |
|
|
{SPCI_FL_BASE3, 4, 115200, 8}, /* pbn_dci_pccom4 */
|
4468 |
|
|
{SPCI_FL_BASE3, 8, 115200, 8}, /* pbn_dci_pccom8 */
|
4469 |
|
|
|
4470 |
|
|
{ SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */
|
4471 |
|
|
0, 0, pci_xircom_fn },
|
4472 |
|
|
|
4473 |
|
|
{ SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */
|
4474 |
|
|
0, 0, pci_siig10x_fn },
|
4475 |
|
|
{ SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */
|
4476 |
|
|
0, 0, pci_siig10x_fn },
|
4477 |
|
|
{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */
|
4478 |
|
|
0, 0, pci_siig10x_fn },
|
4479 |
|
|
{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */
|
4480 |
|
|
0, 0, pci_siig10x_fn },
|
4481 |
|
|
{ SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */
|
4482 |
|
|
0, 0, pci_siig20x_fn },
|
4483 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */
|
4484 |
|
|
0, 0, pci_siig20x_fn },
|
4485 |
|
|
{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */
|
4486 |
|
|
0, 0, pci_siig20x_fn },
|
4487 |
|
|
|
4488 |
|
|
{ SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */
|
4489 |
|
|
0x40, 2, NULL, 0x200 },
|
4490 |
|
|
{ SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */
|
4491 |
|
|
0x40, 2, NULL, 0x200 },
|
4492 |
|
|
{ SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */
|
4493 |
|
|
0x40, 2, NULL, 0x200 },
|
4494 |
|
|
};
|
4495 |
|
|
|
4496 |
|
|
/*
|
4497 |
|
|
* Given a complete unknown PCI device, try to use some heuristics to
|
4498 |
|
|
* guess what the configuration might be, based on the pitiful PCI
|
4499 |
|
|
* serial specs. Returns 0 on success, 1 on failure.
|
4500 |
|
|
*/
|
4501 |
|
|
static int __devinit serial_pci_guess_board(struct pci_dev *dev,
|
4502 |
|
|
struct pci_board *board)
|
4503 |
|
|
{
|
4504 |
|
|
int num_iomem = 0, num_port = 0, first_port = -1;
|
4505 |
|
|
int i;
|
4506 |
|
|
|
4507 |
|
|
/*
|
4508 |
|
|
* If it is not a communications device or the programming
|
4509 |
|
|
* interface is greater than 6, give up.
|
4510 |
|
|
*
|
4511 |
|
|
* (Should we try to make guesses for multiport serial devices
|
4512 |
|
|
* later?)
|
4513 |
|
|
*/
|
4514 |
|
|
if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
|
4515 |
|
|
((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
|
4516 |
|
|
(dev->class & 0xff) > 6)
|
4517 |
|
|
return 1;
|
4518 |
|
|
|
4519 |
|
|
for (i=0; i < 6; i++) {
|
4520 |
|
|
if (IS_PCI_REGION_IOPORT(dev, i)) {
|
4521 |
|
|
num_port++;
|
4522 |
|
|
if (first_port == -1)
|
4523 |
|
|
first_port = i;
|
4524 |
|
|
}
|
4525 |
|
|
if (IS_PCI_REGION_IOMEM(dev, i))
|
4526 |
|
|
num_iomem++;
|
4527 |
|
|
}
|
4528 |
|
|
|
4529 |
|
|
/*
|
4530 |
|
|
* If there is 1 or 0 iomem regions, and exactly one port, use
|
4531 |
|
|
* it.
|
4532 |
|
|
*/
|
4533 |
|
|
if (num_iomem <= 1 && num_port == 1) {
|
4534 |
|
|
board->flags = first_port;
|
4535 |
|
|
return 0;
|
4536 |
|
|
}
|
4537 |
|
|
return 1;
|
4538 |
|
|
}
|
4539 |
|
|
|
4540 |
|
|
static int __devinit serial_init_one(struct pci_dev *dev,
|
4541 |
|
|
const struct pci_device_id *ent)
|
4542 |
|
|
{
|
4543 |
|
|
struct pci_board *board, tmp;
|
4544 |
|
|
int rc;
|
4545 |
|
|
|
4546 |
|
|
board = &pci_boards[ent->driver_data];
|
4547 |
|
|
|
4548 |
|
|
rc = pci_enable_device(dev);
|
4549 |
|
|
if (rc) return rc;
|
4550 |
|
|
|
4551 |
|
|
if (ent->driver_data == pbn_default &&
|
4552 |
|
|
serial_pci_guess_board(dev, board))
|
4553 |
|
|
return -ENODEV;
|
4554 |
|
|
else if (serial_pci_guess_board(dev, &tmp) == 0) {
|
4555 |
|
|
printk(KERN_INFO "Redundant entry in serial pci_table. "
|
4556 |
|
|
"Please send the output of\n"
|
4557 |
|
|
"lspci -vv, this message (%04x,%04x,%04x,%04x)\n"
|
4558 |
|
|
"and the manufacturer and name of "
|
4559 |
|
|
"serial board or modem board\n"
|
4560 |
|
|
"to serial-pci-info@lists.sourceforge.net.\n",
|
4561 |
|
|
dev->vendor, dev->device,
|
4562 |
|
|
pci_get_subvendor(dev), pci_get_subdevice(dev));
|
4563 |
|
|
}
|
4564 |
|
|
|
4565 |
|
|
start_pci_pnp_board(dev, board);
|
4566 |
|
|
|
4567 |
|
|
return 0;
|
4568 |
|
|
}
|
4569 |
|
|
|
4570 |
|
|
static void __devexit serial_remove_one(struct pci_dev *dev)
|
4571 |
|
|
{
|
4572 |
|
|
int i;
|
4573 |
|
|
|
4574 |
|
|
/*
|
4575 |
|
|
* Iterate through all of the ports finding those that belong
|
4576 |
|
|
* to this PCI device.
|
4577 |
|
|
*/
|
4578 |
|
|
for(i = 0; i < NR_PORTS; i++) {
|
4579 |
|
|
if (rs_table[i].dev != dev)
|
4580 |
|
|
continue;
|
4581 |
|
|
unregister_serial(i);
|
4582 |
|
|
rs_table[i].dev = 0;
|
4583 |
|
|
}
|
4584 |
|
|
/*
|
4585 |
|
|
* Now execute any board-specific shutdown procedure
|
4586 |
|
|
*/
|
4587 |
|
|
for (i=0; i < NR_PCI_BOARDS; i++) {
|
4588 |
|
|
struct pci_board_inst *brd = &serial_pci_board[i];
|
4589 |
|
|
|
4590 |
|
|
if (serial_pci_board[i].dev != dev)
|
4591 |
|
|
continue;
|
4592 |
|
|
if (brd->board.init_fn)
|
4593 |
|
|
(brd->board.init_fn)(brd->dev, &brd->board, 0);
|
4594 |
|
|
if (DEACTIVATE_FUNC(brd->dev))
|
4595 |
|
|
(DEACTIVATE_FUNC(brd->dev))(brd->dev);
|
4596 |
|
|
serial_pci_board[i].dev = 0;
|
4597 |
|
|
}
|
4598 |
|
|
}
|
4599 |
|
|
|
4600 |
|
|
|
4601 |
|
|
static struct pci_device_id serial_pci_tbl[] __devinitdata = {
|
4602 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
|
4603 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4604 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
|
4605 |
|
|
pbn_b1_8_1382400 },
|
4606 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
|
4607 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4608 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
|
4609 |
|
|
pbn_b1_4_1382400 },
|
4610 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
|
4611 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4612 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
|
4613 |
|
|
pbn_b1_2_1382400 },
|
4614 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4615 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4616 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
|
4617 |
|
|
pbn_b1_8_1382400 },
|
4618 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4619 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4620 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
|
4621 |
|
|
pbn_b1_4_1382400 },
|
4622 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4623 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4624 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
|
4625 |
|
|
pbn_b1_2_1382400 },
|
4626 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4627 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4628 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
|
4629 |
|
|
pbn_b1_8_921600 },
|
4630 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4631 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4632 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
|
4633 |
|
|
pbn_b1_8_921600 },
|
4634 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4635 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4636 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
|
4637 |
|
|
pbn_b1_4_921600 },
|
4638 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4639 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4640 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
|
4641 |
|
|
pbn_b1_4_921600 },
|
4642 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4643 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4644 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
|
4645 |
|
|
pbn_b1_2_921600 },
|
4646 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4647 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4648 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
|
4649 |
|
|
pbn_b1_8_921600 },
|
4650 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4651 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4652 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
|
4653 |
|
|
pbn_b1_8_921600 },
|
4654 |
|
|
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
|
4655 |
|
|
PCI_SUBVENDOR_ID_CONNECT_TECH,
|
4656 |
|
|
PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
|
4657 |
|
|
pbn_b1_4_921600 },
|
4658 |
|
|
|
4659 |
|
|
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
|
4660 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4661 |
|
|
pbn_b2_bt_1_115200 },
|
4662 |
|
|
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
|
4663 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4664 |
|
|
pbn_b2_bt_2_115200 },
|
4665 |
|
|
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
|
4666 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4667 |
|
|
pbn_b2_bt_4_115200 },
|
4668 |
|
|
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
|
4669 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4670 |
|
|
pbn_b2_bt_2_115200 },
|
4671 |
|
|
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
|
4672 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4673 |
|
|
pbn_b2_bt_4_115200 },
|
4674 |
|
|
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
|
4675 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4676 |
|
|
pbn_b2_8_115200 },
|
4677 |
|
|
|
4678 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
|
4679 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4680 |
|
|
pbn_b2_bt_2_115200 },
|
4681 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
|
4682 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4683 |
|
|
pbn_b2_bt_2_921600 },
|
4684 |
|
|
/* VScom SPCOM800, from sl@s.pl */
|
4685 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
|
4686 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4687 |
|
|
pbn_b2_8_921600 },
|
4688 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
|
4689 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4690 |
|
|
pbn_b2_4_921600 },
|
4691 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
4692 |
|
|
PCI_SUBVENDOR_ID_KEYSPAN,
|
4693 |
|
|
PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
|
4694 |
|
|
pbn_panacom },
|
4695 |
|
|
{ PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
|
4696 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4697 |
|
|
pbn_panacom4 },
|
4698 |
|
|
{ PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
|
4699 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4700 |
|
|
pbn_panacom2 },
|
4701 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
4702 |
|
|
PCI_SUBVENDOR_ID_CHASE_PCIFAST,
|
4703 |
|
|
PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0,
|
4704 |
|
|
pbn_b2_4_460800 },
|
4705 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
4706 |
|
|
PCI_SUBVENDOR_ID_CHASE_PCIFAST,
|
4707 |
|
|
PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0,
|
4708 |
|
|
pbn_b2_8_460800 },
|
4709 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
4710 |
|
|
PCI_SUBVENDOR_ID_CHASE_PCIFAST,
|
4711 |
|
|
PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0,
|
4712 |
|
|
pbn_b2_16_460800 },
|
4713 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
4714 |
|
|
PCI_SUBVENDOR_ID_CHASE_PCIFAST,
|
4715 |
|
|
PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0,
|
4716 |
|
|
pbn_b2_16_460800 },
|
4717 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
4718 |
|
|
PCI_SUBVENDOR_ID_CHASE_PCIRAS,
|
4719 |
|
|
PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0,
|
4720 |
|
|
pbn_b2_4_460800 },
|
4721 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
4722 |
|
|
PCI_SUBVENDOR_ID_CHASE_PCIRAS,
|
4723 |
|
|
PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
|
4724 |
|
|
pbn_b2_8_460800 },
|
4725 |
|
|
/* Megawolf Romulus PCI Serial Card, from Mike Hudson */
|
4726 |
|
|
/* (Exoray@isys.ca) */
|
4727 |
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
|
4728 |
|
|
0x10b5, 0x106a, 0, 0,
|
4729 |
|
|
pbn_plx_romulus },
|
4730 |
|
|
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
|
4731 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4732 |
|
|
pbn_b1_4_115200 },
|
4733 |
|
|
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
|
4734 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4735 |
|
|
pbn_b1_2_115200 },
|
4736 |
|
|
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
|
4737 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4738 |
|
|
pbn_b1_8_115200 },
|
4739 |
|
|
{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
|
4740 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4741 |
|
|
pbn_b1_8_115200 },
|
4742 |
|
|
{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
|
4743 |
|
|
PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0,
|
4744 |
|
|
pbn_b0_4_921600 },
|
4745 |
|
|
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
|
4746 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4747 |
|
|
pbn_b0_4_115200 },
|
4748 |
|
|
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
|
4749 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4750 |
|
|
pbn_b0_bt_2_921600 },
|
4751 |
|
|
|
4752 |
|
|
/* Digitan DS560-558, from jimd@esoft.com */
|
4753 |
|
|
{ PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
|
4754 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4755 |
|
|
pbn_b1_1_115200 },
|
4756 |
|
|
|
4757 |
|
|
/* 3Com US Robotics 56k Voice Internal PCI model 5610 */
|
4758 |
|
|
{ PCI_VENDOR_ID_USR, 0x1008,
|
4759 |
|
|
PCI_ANY_ID, PCI_ANY_ID, },
|
4760 |
|
|
|
4761 |
|
|
/* Titan Electronic cards */
|
4762 |
|
|
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
|
4763 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4764 |
|
|
pbn_b0_1_921600 },
|
4765 |
|
|
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
|
4766 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4767 |
|
|
pbn_b0_2_921600 },
|
4768 |
|
|
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
|
4769 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4770 |
|
|
pbn_b0_4_921600 },
|
4771 |
|
|
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
|
4772 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4773 |
|
|
pbn_b0_4_921600 },
|
4774 |
|
|
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
|
4775 |
|
|
PCI_ANY_ID, PCI_ANY_ID,
|
4776 |
|
|
SPCI_FL_BASE1, 1, 921600 },
|
4777 |
|
|
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
|
4778 |
|
|
PCI_ANY_ID, PCI_ANY_ID,
|
4779 |
|
|
SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
|
4780 |
|
|
/* The 400L and 800L have a custom hack in get_pci_port */
|
4781 |
|
|
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
|
4782 |
|
|
PCI_ANY_ID, PCI_ANY_ID,
|
4783 |
|
|
SPCI_FL_BASE_TABLE, 4, 921600 },
|
4784 |
|
|
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
|
4785 |
|
|
PCI_ANY_ID, PCI_ANY_ID,
|
4786 |
|
|
SPCI_FL_BASE_TABLE, 8, 921600 },
|
4787 |
|
|
|
4788 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
|
4789 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4790 |
|
|
pbn_siig10x_0 },
|
4791 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
|
4792 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4793 |
|
|
pbn_siig10x_0 },
|
4794 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
|
4795 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4796 |
|
|
pbn_siig10x_0 },
|
4797 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
|
4798 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4799 |
|
|
pbn_siig10x_2 },
|
4800 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
|
4801 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4802 |
|
|
pbn_siig10x_2 },
|
4803 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
|
4804 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4805 |
|
|
pbn_siig10x_2 },
|
4806 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
|
4807 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4808 |
|
|
pbn_siig10x_4 },
|
4809 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
|
4810 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4811 |
|
|
pbn_siig10x_4 },
|
4812 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
|
4813 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4814 |
|
|
pbn_siig10x_4 },
|
4815 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
|
4816 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4817 |
|
|
pbn_siig20x_0 },
|
4818 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
|
4819 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4820 |
|
|
pbn_siig20x_0 },
|
4821 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
|
4822 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4823 |
|
|
pbn_siig20x_0 },
|
4824 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
|
4825 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4826 |
|
|
pbn_siig20x_2 },
|
4827 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
|
4828 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4829 |
|
|
pbn_siig20x_2 },
|
4830 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
|
4831 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4832 |
|
|
pbn_siig20x_2 },
|
4833 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
|
4834 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4835 |
|
|
pbn_siig20x_4 },
|
4836 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
|
4837 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4838 |
|
|
pbn_siig20x_4 },
|
4839 |
|
|
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
|
4840 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4841 |
|
|
pbn_siig20x_4 },
|
4842 |
|
|
|
4843 |
|
|
/* Computone devices submitted by Doug McNash dmcnash@computone.com */
|
4844 |
|
|
{ PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
|
4845 |
|
|
PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
|
4846 |
|
|
0, 0, pbn_computone_4 },
|
4847 |
|
|
{ PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
|
4848 |
|
|
PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
|
4849 |
|
|
0, 0, pbn_computone_8 },
|
4850 |
|
|
{ PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
|
4851 |
|
|
PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
|
4852 |
|
|
0, 0, pbn_computone_6 },
|
4853 |
|
|
|
4854 |
|
|
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
|
4855 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi },
|
4856 |
|
|
{ PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
|
4857 |
|
|
PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia },
|
4858 |
|
|
|
4859 |
|
|
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
|
4860 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4861 |
|
|
pbn_b0_bt_2_115200 },
|
4862 |
|
|
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
|
4863 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4864 |
|
|
pbn_b0_bt_2_115200 },
|
4865 |
|
|
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
|
4866 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4867 |
|
|
pbn_b0_bt_2_115200 },
|
4868 |
|
|
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
|
4869 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4870 |
|
|
pbn_b0_bt_2_460800 },
|
4871 |
|
|
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
|
4872 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4873 |
|
|
pbn_b0_bt_2_460800 },
|
4874 |
|
|
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
|
4875 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4876 |
|
|
pbn_b0_bt_2_460800 },
|
4877 |
|
|
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
|
4878 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4879 |
|
|
pbn_b0_bt_1_115200 },
|
4880 |
|
|
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
|
4881 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4882 |
|
|
pbn_b0_bt_1_460800 },
|
4883 |
|
|
|
4884 |
|
|
/* RAStel 2 port modem, gerg@moreton.com.au */
|
4885 |
|
|
{ PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
|
4886 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4887 |
|
|
pbn_b2_bt_2_115200 },
|
4888 |
|
|
|
4889 |
|
|
/* EKF addition for i960 Boards form EKF with serial port */
|
4890 |
|
|
{ PCI_VENDOR_ID_INTEL, 0x1960,
|
4891 |
|
|
0xE4BF, PCI_ANY_ID, 0, 0,
|
4892 |
|
|
pbn_intel_i960 },
|
4893 |
|
|
|
4894 |
|
|
/* Xircom Cardbus/Ethernet combos */
|
4895 |
|
|
{ PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
|
4896 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4897 |
|
|
pbn_xircom_combo },
|
4898 |
|
|
|
4899 |
|
|
/*
|
4900 |
|
|
* Untested PCI modems, sent in from various folks...
|
4901 |
|
|
*/
|
4902 |
|
|
|
4903 |
|
|
/* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
|
4904 |
|
|
{ PCI_VENDOR_ID_ROCKWELL, 0x1004,
|
4905 |
|
|
0x1048, 0x1500, 0, 0,
|
4906 |
|
|
pbn_b1_1_115200 },
|
4907 |
|
|
|
4908 |
|
|
{ PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
|
4909 |
|
|
0xFF00, 0, 0, 0,
|
4910 |
|
|
pbn_sgi_ioc3 },
|
4911 |
|
|
|
4912 |
|
|
/* HP Diva card */
|
4913 |
|
|
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_SAS,
|
4914 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4915 |
|
|
pbn_hp_diva },
|
4916 |
|
|
{ PCI_VENDOR_ID_HP, 0x1290,
|
4917 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4918 |
|
|
pbn_b2_1_115200 },
|
4919 |
|
|
|
4920 |
|
|
#ifdef CONFIG_DDB5074
|
4921 |
|
|
/*
|
4922 |
|
|
* NEC Vrc-5074 (Nile 4) builtin UART.
|
4923 |
|
|
* Conditionally compiled in since this is a motherboard device.
|
4924 |
|
|
*/
|
4925 |
|
|
{ PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4,
|
4926 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4927 |
|
|
pbn_nec_nile4 },
|
4928 |
|
|
#endif
|
4929 |
|
|
|
4930 |
|
|
{ PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
|
4931 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4932 |
|
|
pbn_dci_pccom4 },
|
4933 |
|
|
{ PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
|
4934 |
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
4935 |
|
|
pbn_dci_pccom8 },
|
4936 |
|
|
|
4937 |
|
|
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
4938 |
|
|
PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, },
|
4939 |
|
|
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
4940 |
|
|
PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, },
|
4941 |
|
|
{ 0, }
|
4942 |
|
|
};
|
4943 |
|
|
|
4944 |
|
|
MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
|
4945 |
|
|
|
4946 |
|
|
static struct pci_driver serial_pci_driver = {
|
4947 |
|
|
name: "serial",
|
4948 |
|
|
probe: serial_init_one,
|
4949 |
|
|
remove: __devexit_p(serial_remove_one),
|
4950 |
|
|
id_table: serial_pci_tbl,
|
4951 |
|
|
};
|
4952 |
|
|
|
4953 |
|
|
|
4954 |
|
|
/*
|
4955 |
|
|
* Query PCI space for known serial boards
|
4956 |
|
|
* If found, add them to the PCI device space in rs_table[]
|
4957 |
|
|
*
|
4958 |
|
|
* Accept a maximum of eight boards
|
4959 |
|
|
*
|
4960 |
|
|
*/
|
4961 |
|
|
static void __devinit probe_serial_pci(void)
|
4962 |
|
|
{
|
4963 |
|
|
#ifdef SERIAL_DEBUG_PCI
|
4964 |
|
|
printk(KERN_DEBUG "Entered probe_serial_pci()\n");
|
4965 |
|
|
#endif
|
4966 |
|
|
|
4967 |
|
|
/* Register call PCI serial devices. Null out
|
4968 |
|
|
* the driver name upon failure, as a signal
|
4969 |
|
|
* not to attempt to unregister the driver later
|
4970 |
|
|
*/
|
4971 |
|
|
if (pci_module_init (&serial_pci_driver) != 0)
|
4972 |
|
|
serial_pci_driver.name = "";
|
4973 |
|
|
|
4974 |
|
|
#ifdef SERIAL_DEBUG_PCI
|
4975 |
|
|
printk(KERN_DEBUG "Leaving probe_serial_pci() (probe finished)\n");
|
4976 |
|
|
#endif
|
4977 |
|
|
return;
|
4978 |
|
|
}
|
4979 |
|
|
|
4980 |
|
|
#endif /* ENABLE_SERIAL_PCI */
|
4981 |
|
|
|
4982 |
|
|
#ifdef ENABLE_SERIAL_PNP
|
4983 |
|
|
|
4984 |
|
|
struct pnp_board {
|
4985 |
|
|
unsigned short vendor;
|
4986 |
|
|
unsigned short device;
|
4987 |
|
|
};
|
4988 |
|
|
|
4989 |
|
|
static struct pnp_board pnp_devices[] __devinitdata = {
|
4990 |
|
|
/* Archtek America Corp. */
|
4991 |
|
|
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
4992 |
|
|
{ ISAPNP_VENDOR('A', 'A', 'C'), ISAPNP_DEVICE(0x000F) },
|
4993 |
|
|
/* Anchor Datacomm BV */
|
4994 |
|
|
/* SXPro 144 External Data Fax Modem Plug & Play */
|
4995 |
|
|
{ ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0001) },
|
4996 |
|
|
/* SXPro 288 External Data Fax Modem Plug & Play */
|
4997 |
|
|
{ ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0002) },
|
4998 |
|
|
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
4999 |
|
|
{ ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021) },
|
5000 |
|
|
/* AZT3005 PnP SOUND DEVICE */
|
5001 |
|
|
{ ISAPNP_VENDOR('A', 'Z', 'T'), ISAPNP_DEVICE(0x4001) },
|
5002 |
|
|
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
5003 |
|
|
{ ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) },
|
5004 |
|
|
/* Boca Research */
|
5005 |
|
|
/* Boca Complete Ofc Communicator 14.4 Data-FAX */
|
5006 |
|
|
{ ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) },
|
5007 |
|
|
/* Boca Research 33,600 ACF Modem */
|
5008 |
|
|
{ ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400) },
|
5009 |
|
|
/* Boca 33.6 Kbps Internal FD34FSVD */
|
5010 |
|
|
{ ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x3400) },
|
5011 |
|
|
/* Boca 33.6 Kbps Internal FD34FSVD */
|
5012 |
|
|
{ ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) },
|
5013 |
|
|
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
5014 |
|
|
{ ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) },
|
5015 |
|
|
/* Computer Peripherals Inc */
|
5016 |
|
|
/* EuroViVa CommCenter-33.6 SP PnP */
|
5017 |
|
|
{ ISAPNP_VENDOR('C', 'P', 'I'), ISAPNP_DEVICE(0x4050) },
|
5018 |
|
|
/* Creative Labs */
|
5019 |
|
|
/* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
|
5020 |
|
|
{ ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3001) },
|
5021 |
|
|
/* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
|
5022 |
|
|
{ ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3011) },
|
5023 |
|
|
/* Creative */
|
5024 |
|
|
/* Creative Modem Blaster Flash56 DI5601-1 */
|
5025 |
|
|
{ ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x1032) },
|
5026 |
|
|
/* Creative Modem Blaster V.90 DI5660 */
|
5027 |
|
|
{ ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x2001) },
|
5028 |
|
|
/* FUJITSU */
|
5029 |
|
|
/* Fujitsu 33600 PnP-I2 R Plug & Play */
|
5030 |
|
|
{ ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0202) },
|
5031 |
|
|
/* Fujitsu FMV-FX431 Plug & Play */
|
5032 |
|
|
{ ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0205) },
|
5033 |
|
|
/* Fujitsu 33600 PnP-I4 R Plug & Play */
|
5034 |
|
|
{ ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0206) },
|
5035 |
|
|
/* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
|
5036 |
|
|
{ ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0209) },
|
5037 |
|
|
/* Archtek America Corp. */
|
5038 |
|
|
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
5039 |
|
|
{ ISAPNP_VENDOR('G', 'V', 'C'), ISAPNP_DEVICE(0x000F) },
|
5040 |
|
|
/* Hayes */
|
5041 |
|
|
/* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
|
5042 |
|
|
{ ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x0001) },
|
5043 |
|
|
/* Hayes Optima 336 V.34 + FAX + Voice PnP */
|
5044 |
|
|
{ ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000C) },
|
5045 |
|
|
/* Hayes Optima 336B V.34 + FAX + Voice PnP */
|
5046 |
|
|
{ ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000D) },
|
5047 |
|
|
/* Hayes Accura 56K Ext Fax Modem PnP */
|
5048 |
|
|
{ ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5670) },
|
5049 |
|
|
/* Hayes Accura 56K Ext Fax Modem PnP */
|
5050 |
|
|
{ ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5674) },
|
5051 |
|
|
/* Hayes Accura 56K Fax Modem PnP */
|
5052 |
|
|
{ ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5675) },
|
5053 |
|
|
/* Hayes 288, V.34 + FAX */
|
5054 |
|
|
{ ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF000) },
|
5055 |
|
|
/* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
|
5056 |
|
|
{ ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF001) },
|
5057 |
|
|
/* IBM */
|
5058 |
|
|
/* IBM Thinkpad 701 Internal Modem Voice */
|
5059 |
|
|
{ ISAPNP_VENDOR('I', 'B', 'M'), ISAPNP_DEVICE(0x0033) },
|
5060 |
|
|
/* Intertex */
|
5061 |
|
|
/* Intertex 28k8 33k6 Voice EXT PnP */
|
5062 |
|
|
{ ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC801) },
|
5063 |
|
|
/* Intertex 33k6 56k Voice EXT PnP */
|
5064 |
|
|
{ ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC901) },
|
5065 |
|
|
/* Intertex 28k8 33k6 Voice SP EXT PnP */
|
5066 |
|
|
{ ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD801) },
|
5067 |
|
|
/* Intertex 33k6 56k Voice SP EXT PnP */
|
5068 |
|
|
{ ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD901) },
|
5069 |
|
|
/* Intertex 28k8 33k6 Voice SP INT PnP */
|
5070 |
|
|
{ ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF401) },
|
5071 |
|
|
/* Intertex 28k8 33k6 Voice SP EXT PnP */
|
5072 |
|
|
{ ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF801) },
|
5073 |
|
|
/* Intertex 33k6 56k Voice SP EXT PnP */
|
5074 |
|
|
{ ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF901) },
|
5075 |
|
|
/* Kortex International */
|
5076 |
|
|
/* KORTEX 28800 Externe PnP */
|
5077 |
|
|
{ ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0x4522) },
|
5078 |
|
|
/* KXPro 33.6 Vocal ASVD PnP */
|
5079 |
|
|
{ ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0xF661) },
|
5080 |
|
|
/* Lasat */
|
5081 |
|
|
/* LASAT Internet 33600 PnP */
|
5082 |
|
|
{ ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4040) },
|
5083 |
|
|
/* Lasat Safire 560 PnP */
|
5084 |
|
|
{ ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4540) },
|
5085 |
|
|
/* Lasat Safire 336 PnP */
|
5086 |
|
|
{ ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x5440) },
|
5087 |
|
|
/* Microcom, Inc. */
|
5088 |
|
|
/* Microcom TravelPorte FAST V.34 Plug & Play */
|
5089 |
|
|
{ ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x281) },
|
5090 |
|
|
/* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
|
5091 |
|
|
{ ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0336) },
|
5092 |
|
|
/* Microcom DeskPorte FAST EP 28.8 Plug & Play */
|
5093 |
|
|
{ ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0339) },
|
5094 |
|
|
/* Microcom DeskPorte 28.8P Plug & Play */
|
5095 |
|
|
{ ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0342) },
|
5096 |
|
|
/* Microcom DeskPorte FAST ES 28.8 Plug & Play */
|
5097 |
|
|
{ ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0500) },
|
5098 |
|
|
/* Microcom DeskPorte FAST ES 28.8 Plug & Play */
|
5099 |
|
|
{ ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0501) },
|
5100 |
|
|
/* Microcom DeskPorte 28.8S Internal Plug & Play */
|
5101 |
|
|
{ ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0502) },
|
5102 |
|
|
/* Motorola */
|
5103 |
|
|
/* Motorola BitSURFR Plug & Play */
|
5104 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1105) },
|
5105 |
|
|
/* Motorola TA210 Plug & Play */
|
5106 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1111) },
|
5107 |
|
|
/* Motorola HMTA 200 (ISDN) Plug & Play */
|
5108 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1114) },
|
5109 |
|
|
/* Motorola BitSURFR Plug & Play */
|
5110 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1115) },
|
5111 |
|
|
/* Motorola Lifestyle 28.8 Internal */
|
5112 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1190) },
|
5113 |
|
|
/* Motorola V.3400 Plug & Play */
|
5114 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1501) },
|
5115 |
|
|
/* Motorola Lifestyle 28.8 V.34 Plug & Play */
|
5116 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1502) },
|
5117 |
|
|
/* Motorola Power 28.8 V.34 Plug & Play */
|
5118 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1505) },
|
5119 |
|
|
/* Motorola ModemSURFR External 28.8 Plug & Play */
|
5120 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1509) },
|
5121 |
|
|
/* Motorola Premier 33.6 Desktop Plug & Play */
|
5122 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150A) },
|
5123 |
|
|
/* Motorola VoiceSURFR 56K External PnP */
|
5124 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150F) },
|
5125 |
|
|
/* Motorola ModemSURFR 56K External PnP */
|
5126 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1510) },
|
5127 |
|
|
/* Motorola ModemSURFR 56K Internal PnP */
|
5128 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1550) },
|
5129 |
|
|
/* Motorola ModemSURFR Internal 28.8 Plug & Play */
|
5130 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1560) },
|
5131 |
|
|
/* Motorola Premier 33.6 Internal Plug & Play */
|
5132 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1580) },
|
5133 |
|
|
/* Motorola OnlineSURFR 28.8 Internal Plug & Play */
|
5134 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15B0) },
|
5135 |
|
|
/* Motorola VoiceSURFR 56K Internal PnP */
|
5136 |
|
|
{ ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0) },
|
5137 |
|
|
/* Com 1 */
|
5138 |
|
|
/* Deskline K56 Phone System PnP */
|
5139 |
|
|
{ ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00A1) },
|
5140 |
|
|
/* PC Rider K56 Phone System PnP */
|
5141 |
|
|
{ ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00F2) },
|
5142 |
|
|
/* Pace 56 Voice Internal Plug & Play Modem */
|
5143 |
|
|
{ ISAPNP_VENDOR('P', 'M', 'C'), ISAPNP_DEVICE(0x2430) },
|
5144 |
|
|
/* Generic */
|
5145 |
|
|
/* Generic standard PC COM port */
|
5146 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0500) },
|
5147 |
|
|
/* Generic 16550A-compatible COM port */
|
5148 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501) },
|
5149 |
|
|
/* Compaq 14400 Modem */
|
5150 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000) },
|
5151 |
|
|
/* Compaq 2400/9600 Modem */
|
5152 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC001) },
|
5153 |
|
|
/* Dial-Up Networking Serial Cable between 2 PCs */
|
5154 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC031) },
|
5155 |
|
|
/* Dial-Up Networking Parallel Cable between 2 PCs */
|
5156 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC032) },
|
5157 |
|
|
/* Standard 9600 bps Modem */
|
5158 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC100) },
|
5159 |
|
|
/* Standard 14400 bps Modem */
|
5160 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC101) },
|
5161 |
|
|
/* Standard 28800 bps Modem*/
|
5162 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC102) },
|
5163 |
|
|
/* Standard Modem*/
|
5164 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC103) },
|
5165 |
|
|
/* Standard 9600 bps Modem*/
|
5166 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC104) },
|
5167 |
|
|
/* Standard 14400 bps Modem*/
|
5168 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC105) },
|
5169 |
|
|
/* Standard 28800 bps Modem*/
|
5170 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC106) },
|
5171 |
|
|
/* Standard Modem */
|
5172 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC107) },
|
5173 |
|
|
/* Standard 9600 bps Modem */
|
5174 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC108) },
|
5175 |
|
|
/* Standard 14400 bps Modem */
|
5176 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC109) },
|
5177 |
|
|
/* Standard 28800 bps Modem */
|
5178 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10A) },
|
5179 |
|
|
/* Standard Modem */
|
5180 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10B) },
|
5181 |
|
|
/* Standard 9600 bps Modem */
|
5182 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10C) },
|
5183 |
|
|
/* Standard 14400 bps Modem */
|
5184 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10D) },
|
5185 |
|
|
/* Standard 28800 bps Modem */
|
5186 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10E) },
|
5187 |
|
|
/* Standard Modem */
|
5188 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10F) },
|
5189 |
|
|
/* Standard PCMCIA Card Modem */
|
5190 |
|
|
{ ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x2000) },
|
5191 |
|
|
/* Rockwell */
|
5192 |
|
|
/* Modular Technology */
|
5193 |
|
|
/* Rockwell 33.6 DPF Internal PnP */
|
5194 |
|
|
/* Modular Technology 33.6 Internal PnP */
|
5195 |
|
|
{ ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0030) },
|
5196 |
|
|
/* Kortex International */
|
5197 |
|
|
/* KORTEX 14400 Externe PnP */
|
5198 |
|
|
{ ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0100) },
|
5199 |
|
|
/* Viking Components, Inc */
|
5200 |
|
|
/* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
|
5201 |
|
|
{ ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x4920) },
|
5202 |
|
|
/* Rockwell */
|
5203 |
|
|
/* British Telecom */
|
5204 |
|
|
/* Modular Technology */
|
5205 |
|
|
/* Rockwell 33.6 DPF External PnP */
|
5206 |
|
|
/* BT Prologue 33.6 External PnP */
|
5207 |
|
|
/* Modular Technology 33.6 External PnP */
|
5208 |
|
|
{ ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x00A0) },
|
5209 |
|
|
/* Viking 56K FAX INT */
|
5210 |
|
|
{ ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x0262) },
|
5211 |
|
|
/* SupraExpress 28.8 Data/Fax PnP modem */
|
5212 |
|
|
{ ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1310) },
|
5213 |
|
|
/* SupraExpress 33.6 Data/Fax PnP modem */
|
5214 |
|
|
{ ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1421) },
|
5215 |
|
|
/* SupraExpress 33.6 Data/Fax PnP modem */
|
5216 |
|
|
{ ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1590) },
|
5217 |
|
|
/* SupraExpress 33.6 Data/Fax PnP modem */
|
5218 |
|
|
{ ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1760) },
|
5219 |
|
|
/* Phoebe Micro */
|
5220 |
|
|
/* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
|
5221 |
|
|
{ ISAPNP_VENDOR('T', 'E', 'X'), ISAPNP_DEVICE(0x0011) },
|
5222 |
|
|
/* Archtek America Corp. */
|
5223 |
|
|
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
5224 |
|
|
{ ISAPNP_VENDOR('U', 'A', 'C'), ISAPNP_DEVICE(0x000F) },
|
5225 |
|
|
/* 3Com Corp. */
|
5226 |
|
|
/* Gateway Telepath IIvi 33.6 */
|
5227 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0000) },
|
5228 |
|
|
/* Sportster Vi 14.4 PnP FAX Voicemail */
|
5229 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0004) },
|
5230 |
|
|
/* U.S. Robotics 33.6K Voice INT PnP */
|
5231 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0006) },
|
5232 |
|
|
/* U.S. Robotics 33.6K Voice EXT PnP */
|
5233 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0007) },
|
5234 |
|
|
/* U.S. Robotics 33.6K Voice INT PnP */
|
5235 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2002) },
|
5236 |
|
|
/* U.S. Robotics 56K Voice INT PnP */
|
5237 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2070) },
|
5238 |
|
|
/* U.S. Robotics 56K Voice EXT PnP */
|
5239 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2080) },
|
5240 |
|
|
/* U.S. Robotics 56K FAX INT */
|
5241 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031) },
|
5242 |
|
|
/* U.S. Robotics 56K Voice INT PnP */
|
5243 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3070) },
|
5244 |
|
|
/* U.S. Robotics 56K Voice EXT PnP */
|
5245 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3080) },
|
5246 |
|
|
/* U.S. Robotics 56K Voice INT PnP */
|
5247 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3090) },
|
5248 |
|
|
/* U.S. Robotics 56K Message */
|
5249 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9100) },
|
5250 |
|
|
/* U.S. Robotics 56K FAX EXT PnP*/
|
5251 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9160) },
|
5252 |
|
|
/* U.S. Robotics 56K FAX INT PnP*/
|
5253 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9170) },
|
5254 |
|
|
/* U.S. Robotics 56K Voice EXT PnP*/
|
5255 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9180) },
|
5256 |
|
|
/* U.S. Robotics 56K Voice INT PnP*/
|
5257 |
|
|
{ ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9190) },
|
5258 |
|
|
{ 0, }
|
5259 |
|
|
};
|
5260 |
|
|
|
5261 |
|
|
static inline void avoid_irq_share(struct pci_dev *dev)
|
5262 |
|
|
{
|
5263 |
|
|
int i, map = 0x1FF8;
|
5264 |
|
|
struct serial_state *state = rs_table;
|
5265 |
|
|
struct isapnp_irq *irq;
|
5266 |
|
|
struct isapnp_resources *res = dev->sysdata;
|
5267 |
|
|
|
5268 |
|
|
for (i = 0; i < NR_PORTS; i++) {
|
5269 |
|
|
if (state->type != PORT_UNKNOWN)
|
5270 |
|
|
clear_bit(state->irq, &map);
|
5271 |
|
|
state++;
|
5272 |
|
|
}
|
5273 |
|
|
|
5274 |
|
|
for ( ; res; res = res->alt)
|
5275 |
|
|
for(irq = res->irq; irq; irq = irq->next)
|
5276 |
|
|
irq->map = map;
|
5277 |
|
|
}
|
5278 |
|
|
|
5279 |
|
|
static char *modem_names[] __devinitdata = {
|
5280 |
|
|
"MODEM", "Modem", "modem", "FAX", "Fax", "fax",
|
5281 |
|
|
"56K", "56k", "K56", "33.6", "28.8", "14.4",
|
5282 |
|
|
"33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
|
5283 |
|
|
"33600", "28800", "14400", "V.90", "V.34", "V.32", 0
|
5284 |
|
|
};
|
5285 |
|
|
|
5286 |
|
|
static int __devinit check_name(char *name)
|
5287 |
|
|
{
|
5288 |
|
|
char **tmp = modem_names;
|
5289 |
|
|
|
5290 |
|
|
while (*tmp) {
|
5291 |
|
|
if (strstr(name, *tmp))
|
5292 |
|
|
return 1;
|
5293 |
|
|
tmp++;
|
5294 |
|
|
}
|
5295 |
|
|
return 0;
|
5296 |
|
|
}
|
5297 |
|
|
|
5298 |
|
|
static inline int check_compatible_id(struct pci_dev *dev)
|
5299 |
|
|
{
|
5300 |
|
|
int i;
|
5301 |
|
|
for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++)
|
5302 |
|
|
if ((dev->vendor_compatible[i] ==
|
5303 |
|
|
ISAPNP_VENDOR('P', 'N', 'P')) &&
|
5304 |
|
|
(swab16(dev->device_compatible[i]) >= 0xc000) &&
|
5305 |
|
|
(swab16(dev->device_compatible[i]) <= 0xdfff))
|
5306 |
|
|
return 0;
|
5307 |
|
|
return 1;
|
5308 |
|
|
}
|
5309 |
|
|
|
5310 |
|
|
/*
|
5311 |
|
|
* Given a complete unknown ISA PnP device, try to use some heuristics to
|
5312 |
|
|
* detect modems. Currently use such heuristic set:
|
5313 |
|
|
* - dev->name or dev->bus->name must contain "modem" substring;
|
5314 |
|
|
* - device must have only one IO region (8 byte long) with base adress
|
5315 |
|
|
* 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
|
5316 |
|
|
*
|
5317 |
|
|
* Such detection looks very ugly, but can detect at least some of numerous
|
5318 |
|
|
* ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[]
|
5319 |
|
|
* table.
|
5320 |
|
|
*/
|
5321 |
|
|
static int _INLINE_ serial_pnp_guess_board(struct pci_dev *dev,
|
5322 |
|
|
struct pci_board *board)
|
5323 |
|
|
{
|
5324 |
|
|
struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
|
5325 |
|
|
struct isapnp_resources *resa;
|
5326 |
|
|
|
5327 |
|
|
if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
|
5328 |
|
|
!(check_compatible_id(dev)))
|
5329 |
|
|
return 1;
|
5330 |
|
|
|
5331 |
|
|
if (!res || res->next)
|
5332 |
|
|
return 1;
|
5333 |
|
|
|
5334 |
|
|
for (resa = res->alt; resa; resa = resa->alt) {
|
5335 |
|
|
struct isapnp_port *port;
|
5336 |
|
|
for (port = res->port; port; port = port->next)
|
5337 |
|
|
if ((port->size == 8) &&
|
5338 |
|
|
((port->min == 0x2f8) ||
|
5339 |
|
|
(port->min == 0x3f8) ||
|
5340 |
|
|
(port->min == 0x2e8) ||
|
5341 |
|
|
(port->min == 0x3e8)))
|
5342 |
|
|
return 0;
|
5343 |
|
|
}
|
5344 |
|
|
|
5345 |
|
|
return 1;
|
5346 |
|
|
}
|
5347 |
|
|
|
5348 |
|
|
static void __devinit probe_serial_pnp(void)
|
5349 |
|
|
{
|
5350 |
|
|
struct pci_dev *dev = NULL;
|
5351 |
|
|
struct pnp_board *pnp_board;
|
5352 |
|
|
struct pci_board board;
|
5353 |
|
|
|
5354 |
|
|
#ifdef SERIAL_DEBUG_PNP
|
5355 |
|
|
printk("Entered probe_serial_pnp()\n");
|
5356 |
|
|
#endif
|
5357 |
|
|
if (!isapnp_present()) {
|
5358 |
|
|
#ifdef SERIAL_DEBUG_PNP
|
5359 |
|
|
printk("Leaving probe_serial_pnp() (no isapnp)\n");
|
5360 |
|
|
#endif
|
5361 |
|
|
return;
|
5362 |
|
|
}
|
5363 |
|
|
|
5364 |
|
|
isapnp_for_each_dev(dev) {
|
5365 |
|
|
if (dev->active)
|
5366 |
|
|
continue;
|
5367 |
|
|
|
5368 |
|
|
memset(&board, 0, sizeof(board));
|
5369 |
|
|
board.flags = SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT;
|
5370 |
|
|
board.num_ports = 1;
|
5371 |
|
|
board.base_baud = 115200;
|
5372 |
|
|
|
5373 |
|
|
for (pnp_board = pnp_devices; pnp_board->vendor; pnp_board++)
|
5374 |
|
|
if ((dev->vendor == pnp_board->vendor) &&
|
5375 |
|
|
(dev->device == pnp_board->device))
|
5376 |
|
|
break;
|
5377 |
|
|
|
5378 |
|
|
if (pnp_board->vendor) {
|
5379 |
|
|
/* Special case that's more efficient to hardcode */
|
5380 |
|
|
if ((pnp_board->vendor == ISAPNP_VENDOR('A', 'K', 'Y') &&
|
5381 |
|
|
pnp_board->device == ISAPNP_DEVICE(0x1021)))
|
5382 |
|
|
board.flags |= SPCI_FL_NO_SHIRQ;
|
5383 |
|
|
} else {
|
5384 |
|
|
if (serial_pnp_guess_board(dev, &board))
|
5385 |
|
|
continue;
|
5386 |
|
|
}
|
5387 |
|
|
|
5388 |
|
|
if (board.flags & SPCI_FL_NO_SHIRQ)
|
5389 |
|
|
avoid_irq_share(dev);
|
5390 |
|
|
start_pci_pnp_board(dev, &board);
|
5391 |
|
|
}
|
5392 |
|
|
|
5393 |
|
|
#ifdef SERIAL_DEBUG_PNP
|
5394 |
|
|
printk("Leaving probe_serial_pnp() (probe finished)\n");
|
5395 |
|
|
#endif
|
5396 |
|
|
return;
|
5397 |
|
|
}
|
5398 |
|
|
|
5399 |
|
|
#endif /* ENABLE_SERIAL_PNP */
|
5400 |
|
|
|
5401 |
|
|
/*
|
5402 |
|
|
* The serial driver boot-time initialization code!
|
5403 |
|
|
*/
|
5404 |
|
|
static int __init rs_init(void)
|
5405 |
|
|
{
|
5406 |
|
|
int i;
|
5407 |
|
|
struct serial_state * state;
|
5408 |
|
|
|
5409 |
|
|
init_bh(SERIAL_BH, do_serial_bh);
|
5410 |
|
|
init_timer(&serial_timer);
|
5411 |
|
|
serial_timer.function = rs_timer;
|
5412 |
|
|
mod_timer(&serial_timer, jiffies + RS_STROBE_TIME);
|
5413 |
|
|
|
5414 |
|
|
for (i = 0; i < NR_IRQS; i++) {
|
5415 |
|
|
IRQ_ports[i] = 0;
|
5416 |
|
|
IRQ_timeout[i] = 0;
|
5417 |
|
|
#ifdef CONFIG_SERIAL_MULTIPORT
|
5418 |
|
|
memset(&rs_multiport[i], 0,
|
5419 |
|
|
sizeof(struct rs_multiport_struct));
|
5420 |
|
|
#endif
|
5421 |
|
|
}
|
5422 |
|
|
#ifdef CONFIG_SERIAL_CONSOLE
|
5423 |
|
|
/*
|
5424 |
|
|
* The interrupt of the serial console port
|
5425 |
|
|
* can't be shared.
|
5426 |
|
|
*/
|
5427 |
|
|
if (sercons.flags & CON_CONSDEV) {
|
5428 |
|
|
for(i = 0; i < NR_PORTS; i++)
|
5429 |
|
|
if (i != sercons.index &&
|
5430 |
|
|
rs_table[i].irq == rs_table[sercons.index].irq)
|
5431 |
|
|
rs_table[i].irq = 0;
|
5432 |
|
|
}
|
5433 |
|
|
#endif
|
5434 |
|
|
show_serial_version();
|
5435 |
|
|
|
5436 |
|
|
/* Initialize the tty_driver structure */
|
5437 |
|
|
|
5438 |
|
|
memset(&serial_driver, 0, sizeof(struct tty_driver));
|
5439 |
|
|
serial_driver.magic = TTY_DRIVER_MAGIC;
|
5440 |
|
|
#if (LINUX_VERSION_CODE > 0x20100)
|
5441 |
|
|
serial_driver.driver_name = "serial";
|
5442 |
|
|
#endif
|
5443 |
|
|
#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
|
5444 |
|
|
serial_driver.name = "tts/%d";
|
5445 |
|
|
#else
|
5446 |
|
|
serial_driver.name = "ttyS";
|
5447 |
|
|
#endif
|
5448 |
|
|
serial_driver.major = TTY_MAJOR;
|
5449 |
|
|
serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET;
|
5450 |
|
|
serial_driver.name_base = SERIAL_DEV_OFFSET;
|
5451 |
|
|
serial_driver.num = NR_PORTS;
|
5452 |
|
|
serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
|
5453 |
|
|
serial_driver.subtype = SERIAL_TYPE_NORMAL;
|
5454 |
|
|
serial_driver.init_termios = tty_std_termios;
|
5455 |
|
|
serial_driver.init_termios.c_cflag =
|
5456 |
|
|
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
5457 |
|
|
serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
|
5458 |
|
|
serial_driver.refcount = &serial_refcount;
|
5459 |
|
|
serial_driver.table = serial_table;
|
5460 |
|
|
serial_driver.termios = serial_termios;
|
5461 |
|
|
serial_driver.termios_locked = serial_termios_locked;
|
5462 |
|
|
|
5463 |
|
|
serial_driver.open = rs_open;
|
5464 |
|
|
serial_driver.close = rs_close;
|
5465 |
|
|
serial_driver.write = rs_write;
|
5466 |
|
|
serial_driver.put_char = rs_put_char;
|
5467 |
|
|
serial_driver.flush_chars = rs_flush_chars;
|
5468 |
|
|
serial_driver.write_room = rs_write_room;
|
5469 |
|
|
serial_driver.chars_in_buffer = rs_chars_in_buffer;
|
5470 |
|
|
serial_driver.flush_buffer = rs_flush_buffer;
|
5471 |
|
|
serial_driver.ioctl = rs_ioctl;
|
5472 |
|
|
serial_driver.throttle = rs_throttle;
|
5473 |
|
|
serial_driver.unthrottle = rs_unthrottle;
|
5474 |
|
|
serial_driver.set_termios = rs_set_termios;
|
5475 |
|
|
serial_driver.stop = rs_stop;
|
5476 |
|
|
serial_driver.start = rs_start;
|
5477 |
|
|
serial_driver.hangup = rs_hangup;
|
5478 |
|
|
#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
|
5479 |
|
|
serial_driver.break_ctl = rs_break;
|
5480 |
|
|
#endif
|
5481 |
|
|
#if (LINUX_VERSION_CODE >= 131343)
|
5482 |
|
|
serial_driver.send_xchar = rs_send_xchar;
|
5483 |
|
|
serial_driver.wait_until_sent = rs_wait_until_sent;
|
5484 |
|
|
serial_driver.read_proc = rs_read_proc;
|
5485 |
|
|
#endif
|
5486 |
|
|
|
5487 |
|
|
/*
|
5488 |
|
|
* The callout device is just like normal device except for
|
5489 |
|
|
* major number and the subtype code.
|
5490 |
|
|
*/
|
5491 |
|
|
callout_driver = serial_driver;
|
5492 |
|
|
#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
|
5493 |
|
|
callout_driver.name = "cua/%d";
|
5494 |
|
|
#else
|
5495 |
|
|
callout_driver.name = "cua";
|
5496 |
|
|
#endif
|
5497 |
|
|
callout_driver.major = TTYAUX_MAJOR;
|
5498 |
|
|
callout_driver.subtype = SERIAL_TYPE_CALLOUT;
|
5499 |
|
|
#if (LINUX_VERSION_CODE >= 131343)
|
5500 |
|
|
callout_driver.read_proc = 0;
|
5501 |
|
|
callout_driver.proc_entry = 0;
|
5502 |
|
|
#endif
|
5503 |
|
|
|
5504 |
|
|
if (tty_register_driver(&serial_driver))
|
5505 |
|
|
panic("Couldn't register serial driver\n");
|
5506 |
|
|
if (tty_register_driver(&callout_driver))
|
5507 |
|
|
panic("Couldn't register callout driver\n");
|
5508 |
|
|
|
5509 |
|
|
for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
|
5510 |
|
|
state->magic = SSTATE_MAGIC;
|
5511 |
|
|
state->line = i;
|
5512 |
|
|
state->type = PORT_UNKNOWN;
|
5513 |
|
|
state->custom_divisor = 0;
|
5514 |
|
|
state->close_delay = 5*HZ/10;
|
5515 |
|
|
state->closing_wait = 30*HZ;
|
5516 |
|
|
state->callout_termios = callout_driver.init_termios;
|
5517 |
|
|
state->normal_termios = serial_driver.init_termios;
|
5518 |
|
|
state->icount.cts = state->icount.dsr =
|
5519 |
|
|
state->icount.rng = state->icount.dcd = 0;
|
5520 |
|
|
state->icount.rx = state->icount.tx = 0;
|
5521 |
|
|
state->icount.frame = state->icount.parity = 0;
|
5522 |
|
|
state->icount.overrun = state->icount.brk = 0;
|
5523 |
|
|
state->irq = irq_cannonicalize(state->irq);
|
5524 |
|
|
if (state->hub6)
|
5525 |
|
|
state->io_type = SERIAL_IO_HUB6;
|
5526 |
|
|
if (state->port && check_region(state->port,8))
|
5527 |
|
|
continue;
|
5528 |
|
|
#ifdef CONFIG_MCA
|
5529 |
|
|
if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus)
|
5530 |
|
|
continue;
|
5531 |
|
|
#endif
|
5532 |
|
|
if (state->flags & ASYNC_BOOT_AUTOCONF)
|
5533 |
|
|
autoconfig(state);
|
5534 |
|
|
}
|
5535 |
|
|
for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
|
5536 |
|
|
if (state->type == PORT_UNKNOWN)
|
5537 |
|
|
continue;
|
5538 |
|
|
if ( (state->flags & ASYNC_BOOT_AUTOCONF)
|
5539 |
|
|
&& (state->flags & ASYNC_AUTO_IRQ)
|
5540 |
|
|
&& (state->port != 0 || state->iomem_base != 0))
|
5541 |
|
|
state->irq = detect_uart_irq(state);
|
5542 |
|
|
if (state->io_type == SERIAL_IO_MEM) {
|
5543 |
|
|
printk(KERN_INFO"ttyS%02d%s at 0x%p (irq = %d) is a %s\n",
|
5544 |
|
|
state->line + SERIAL_DEV_OFFSET,
|
5545 |
|
|
(state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
|
5546 |
|
|
state->iomem_base, state->irq,
|
5547 |
|
|
uart_config[state->type].name);
|
5548 |
|
|
}
|
5549 |
|
|
else {
|
5550 |
|
|
printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n",
|
5551 |
|
|
state->line + SERIAL_DEV_OFFSET,
|
5552 |
|
|
(state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
|
5553 |
|
|
state->port, state->irq,
|
5554 |
|
|
uart_config[state->type].name);
|
5555 |
|
|
}
|
5556 |
|
|
tty_register_devfs(&serial_driver, 0,
|
5557 |
|
|
serial_driver.minor_start + state->line);
|
5558 |
|
|
tty_register_devfs(&callout_driver, 0,
|
5559 |
|
|
callout_driver.minor_start + state->line);
|
5560 |
|
|
}
|
5561 |
|
|
#ifdef ENABLE_SERIAL_PCI
|
5562 |
|
|
probe_serial_pci();
|
5563 |
|
|
#endif
|
5564 |
|
|
#ifdef ENABLE_SERIAL_PNP
|
5565 |
|
|
probe_serial_pnp();
|
5566 |
|
|
#endif
|
5567 |
|
|
return 0;
|
5568 |
|
|
}
|
5569 |
|
|
|
5570 |
|
|
/*
|
5571 |
|
|
* This is for use by architectures that know their serial console
|
5572 |
|
|
* attributes only at run time. Not to be invoked after rs_init().
|
5573 |
|
|
*/
|
5574 |
|
|
int __init early_serial_setup(struct serial_struct *req)
|
5575 |
|
|
{
|
5576 |
|
|
int i = req->line;
|
5577 |
|
|
|
5578 |
|
|
if (i >= NR_IRQS)
|
5579 |
|
|
return(-ENOENT);
|
5580 |
|
|
rs_table[i].magic = 0;
|
5581 |
|
|
rs_table[i].baud_base = req->baud_base;
|
5582 |
|
|
rs_table[i].port = req->port;
|
5583 |
|
|
if (HIGH_BITS_OFFSET)
|
5584 |
|
|
rs_table[i].port += (unsigned long) req->port_high <<
|
5585 |
|
|
HIGH_BITS_OFFSET;
|
5586 |
|
|
rs_table[i].irq = req->irq;
|
5587 |
|
|
rs_table[i].flags = req->flags;
|
5588 |
|
|
rs_table[i].close_delay = req->close_delay;
|
5589 |
|
|
rs_table[i].io_type = req->io_type;
|
5590 |
|
|
rs_table[i].hub6 = req->hub6;
|
5591 |
|
|
rs_table[i].iomem_base = req->iomem_base;
|
5592 |
|
|
rs_table[i].iomem_reg_shift = req->iomem_reg_shift;
|
5593 |
|
|
rs_table[i].type = req->type;
|
5594 |
|
|
rs_table[i].xmit_fifo_size = req->xmit_fifo_size;
|
5595 |
|
|
rs_table[i].custom_divisor = req->custom_divisor;
|
5596 |
|
|
rs_table[i].closing_wait = req->closing_wait;
|
5597 |
|
|
return(0);
|
5598 |
|
|
}
|
5599 |
|
|
|
5600 |
|
|
/*
|
5601 |
|
|
* register_serial and unregister_serial allows for 16x50 serial ports to be
|
5602 |
|
|
* configured at run-time, to support PCMCIA modems.
|
5603 |
|
|
*/
|
5604 |
|
|
|
5605 |
|
|
/**
|
5606 |
|
|
* register_serial - configure a 16x50 serial port at runtime
|
5607 |
|
|
* @req: request structure
|
5608 |
|
|
*
|
5609 |
|
|
* Configure the serial port specified by the request. If the
|
5610 |
|
|
* port exists and is in use an error is returned. If the port
|
5611 |
|
|
* is not currently in the table it is added.
|
5612 |
|
|
*
|
5613 |
|
|
* The port is then probed and if neccessary the IRQ is autodetected
|
5614 |
|
|
* If this fails an error is returned.
|
5615 |
|
|
*
|
5616 |
|
|
* On success the port is ready to use and the line number is returned.
|
5617 |
|
|
*/
|
5618 |
|
|
|
5619 |
|
|
int register_serial(struct serial_struct *req)
|
5620 |
|
|
{
|
5621 |
|
|
int i;
|
5622 |
|
|
unsigned long flags;
|
5623 |
|
|
struct serial_state *state;
|
5624 |
|
|
struct async_struct *info;
|
5625 |
|
|
unsigned long port;
|
5626 |
|
|
|
5627 |
|
|
port = req->port;
|
5628 |
|
|
if (HIGH_BITS_OFFSET)
|
5629 |
|
|
port += (unsigned long) req->port_high << HIGH_BITS_OFFSET;
|
5630 |
|
|
|
5631 |
|
|
save_flags(flags); cli();
|
5632 |
|
|
for (i = 0; i < NR_PORTS; i++) {
|
5633 |
|
|
if ((rs_table[i].port == port) &&
|
5634 |
|
|
(rs_table[i].iomem_base == req->iomem_base))
|
5635 |
|
|
break;
|
5636 |
|
|
}
|
5637 |
|
|
#ifdef __i386__
|
5638 |
|
|
if (i == NR_PORTS) {
|
5639 |
|
|
for (i = 4; i < NR_PORTS; i++)
|
5640 |
|
|
if ((rs_table[i].type == PORT_UNKNOWN) &&
|
5641 |
|
|
(rs_table[i].count == 0))
|
5642 |
|
|
break;
|
5643 |
|
|
}
|
5644 |
|
|
#endif
|
5645 |
|
|
if (i == NR_PORTS) {
|
5646 |
|
|
for (i = 0; i < NR_PORTS; i++)
|
5647 |
|
|
if ((rs_table[i].type == PORT_UNKNOWN) &&
|
5648 |
|
|
(rs_table[i].count == 0))
|
5649 |
|
|
break;
|
5650 |
|
|
}
|
5651 |
|
|
if (i == NR_PORTS) {
|
5652 |
|
|
restore_flags(flags);
|
5653 |
|
|
return -1;
|
5654 |
|
|
}
|
5655 |
|
|
state = &rs_table[i];
|
5656 |
|
|
if (rs_table[i].count) {
|
5657 |
|
|
restore_flags(flags);
|
5658 |
|
|
printk("Couldn't configure serial #%d (port=%ld,irq=%d): "
|
5659 |
|
|
"device already open\n", i, port, req->irq);
|
5660 |
|
|
return -1;
|
5661 |
|
|
}
|
5662 |
|
|
state->irq = req->irq;
|
5663 |
|
|
state->port = port;
|
5664 |
|
|
state->flags = req->flags;
|
5665 |
|
|
state->io_type = req->io_type;
|
5666 |
|
|
state->iomem_base = req->iomem_base;
|
5667 |
|
|
state->iomem_reg_shift = req->iomem_reg_shift;
|
5668 |
|
|
if (req->baud_base)
|
5669 |
|
|
state->baud_base = req->baud_base;
|
5670 |
|
|
if ((info = state->info) != NULL) {
|
5671 |
|
|
info->port = port;
|
5672 |
|
|
info->flags = req->flags;
|
5673 |
|
|
info->io_type = req->io_type;
|
5674 |
|
|
info->iomem_base = req->iomem_base;
|
5675 |
|
|
info->iomem_reg_shift = req->iomem_reg_shift;
|
5676 |
|
|
}
|
5677 |
|
|
autoconfig(state);
|
5678 |
|
|
if (state->type == PORT_UNKNOWN) {
|
5679 |
|
|
restore_flags(flags);
|
5680 |
|
|
printk("register_serial(): autoconfig failed\n");
|
5681 |
|
|
return -1;
|
5682 |
|
|
}
|
5683 |
|
|
restore_flags(flags);
|
5684 |
|
|
|
5685 |
|
|
if ((state->flags & ASYNC_AUTO_IRQ) && CONFIGURED_SERIAL_PORT(state))
|
5686 |
|
|
state->irq = detect_uart_irq(state);
|
5687 |
|
|
|
5688 |
|
|
printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n",
|
5689 |
|
|
state->line + SERIAL_DEV_OFFSET,
|
5690 |
|
|
state->iomem_base ? "iomem" : "port",
|
5691 |
|
|
state->iomem_base ? (unsigned long)state->iomem_base :
|
5692 |
|
|
state->port, state->irq, uart_config[state->type].name);
|
5693 |
|
|
tty_register_devfs(&serial_driver, 0,
|
5694 |
|
|
serial_driver.minor_start + state->line);
|
5695 |
|
|
tty_register_devfs(&callout_driver, 0,
|
5696 |
|
|
callout_driver.minor_start + state->line);
|
5697 |
|
|
return state->line + SERIAL_DEV_OFFSET;
|
5698 |
|
|
}
|
5699 |
|
|
|
5700 |
|
|
/**
|
5701 |
|
|
* unregister_serial - deconfigure a 16x50 serial port
|
5702 |
|
|
* @line: line to deconfigure
|
5703 |
|
|
*
|
5704 |
|
|
* The port specified is deconfigured and its resources are freed. Any
|
5705 |
|
|
* user of the port is disconnected as if carrier was dropped. Line is
|
5706 |
|
|
* the port number returned by register_serial().
|
5707 |
|
|
*/
|
5708 |
|
|
|
5709 |
|
|
void unregister_serial(int line)
|
5710 |
|
|
{
|
5711 |
|
|
unsigned long flags;
|
5712 |
|
|
struct serial_state *state = &rs_table[line];
|
5713 |
|
|
|
5714 |
|
|
save_flags(flags); cli();
|
5715 |
|
|
if (state->info && state->info->tty)
|
5716 |
|
|
tty_hangup(state->info->tty);
|
5717 |
|
|
state->type = PORT_UNKNOWN;
|
5718 |
|
|
printk(KERN_INFO "ttyS%02d unloaded\n", state->line);
|
5719 |
|
|
/* These will be hidden, because they are devices that will no longer
|
5720 |
|
|
* be available to the system. (ie, PCMCIA modems, once ejected)
|
5721 |
|
|
*/
|
5722 |
|
|
tty_unregister_devfs(&serial_driver,
|
5723 |
|
|
serial_driver.minor_start + state->line);
|
5724 |
|
|
tty_unregister_devfs(&callout_driver,
|
5725 |
|
|
callout_driver.minor_start + state->line);
|
5726 |
|
|
restore_flags(flags);
|
5727 |
|
|
}
|
5728 |
|
|
|
5729 |
|
|
static void __exit rs_fini(void)
|
5730 |
|
|
{
|
5731 |
|
|
unsigned long flags;
|
5732 |
|
|
int e1, e2;
|
5733 |
|
|
int i;
|
5734 |
|
|
struct async_struct *info;
|
5735 |
|
|
|
5736 |
|
|
/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
|
5737 |
|
|
del_timer_sync(&serial_timer);
|
5738 |
|
|
save_flags(flags); cli();
|
5739 |
|
|
remove_bh(SERIAL_BH);
|
5740 |
|
|
if ((e1 = tty_unregister_driver(&serial_driver)))
|
5741 |
|
|
printk("serial: failed to unregister serial driver (%d)\n",
|
5742 |
|
|
e1);
|
5743 |
|
|
if ((e2 = tty_unregister_driver(&callout_driver)))
|
5744 |
|
|
printk("serial: failed to unregister callout driver (%d)\n",
|
5745 |
|
|
e2);
|
5746 |
|
|
restore_flags(flags);
|
5747 |
|
|
|
5748 |
|
|
for (i = 0; i < NR_PORTS; i++) {
|
5749 |
|
|
if ((info = rs_table[i].info)) {
|
5750 |
|
|
rs_table[i].info = NULL;
|
5751 |
|
|
kfree(info);
|
5752 |
|
|
}
|
5753 |
|
|
if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) {
|
5754 |
|
|
#ifdef CONFIG_SERIAL_RSA
|
5755 |
|
|
if (rs_table[i].type == PORT_RSA)
|
5756 |
|
|
release_region(rs_table[i].port +
|
5757 |
|
|
UART_RSA_BASE, 16);
|
5758 |
|
|
else
|
5759 |
|
|
#endif
|
5760 |
|
|
release_region(rs_table[i].port, 8);
|
5761 |
|
|
}
|
5762 |
|
|
#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)
|
5763 |
|
|
if (rs_table[i].iomem_base)
|
5764 |
|
|
iounmap(rs_table[i].iomem_base);
|
5765 |
|
|
#endif
|
5766 |
|
|
}
|
5767 |
|
|
#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)
|
5768 |
|
|
for (i=0; i < NR_PCI_BOARDS; i++) {
|
5769 |
|
|
struct pci_board_inst *brd = &serial_pci_board[i];
|
5770 |
|
|
|
5771 |
|
|
if (serial_pci_board[i].dev == 0)
|
5772 |
|
|
continue;
|
5773 |
|
|
if (brd->board.init_fn)
|
5774 |
|
|
(brd->board.init_fn)(brd->dev, &brd->board, 0);
|
5775 |
|
|
if (DEACTIVATE_FUNC(brd->dev))
|
5776 |
|
|
(DEACTIVATE_FUNC(brd->dev))(brd->dev);
|
5777 |
|
|
}
|
5778 |
|
|
#endif
|
5779 |
|
|
if (tmp_buf) {
|
5780 |
|
|
unsigned long pg = (unsigned long) tmp_buf;
|
5781 |
|
|
tmp_buf = NULL;
|
5782 |
|
|
free_page(pg);
|
5783 |
|
|
}
|
5784 |
|
|
|
5785 |
|
|
#ifdef ENABLE_SERIAL_PCI
|
5786 |
|
|
if (serial_pci_driver.name[0])
|
5787 |
|
|
pci_unregister_driver (&serial_pci_driver);
|
5788 |
|
|
#endif
|
5789 |
|
|
}
|
5790 |
|
|
|
5791 |
|
|
module_init(rs_init);
|
5792 |
|
|
module_exit(rs_fini);
|
5793 |
|
|
MODULE_DESCRIPTION("Standard/generic (dumb) serial driver");
|
5794 |
|
|
MODULE_AUTHOR("Theodore Ts'o <tytso@mit.edu>");
|
5795 |
|
|
MODULE_LICENSE("GPL");
|
5796 |
|
|
|
5797 |
|
|
|
5798 |
|
|
/*
|
5799 |
|
|
* ------------------------------------------------------------
|
5800 |
|
|
* Serial console driver
|
5801 |
|
|
* ------------------------------------------------------------
|
5802 |
|
|
*/
|
5803 |
|
|
#ifdef CONFIG_SERIAL_CONSOLE
|
5804 |
|
|
|
5805 |
|
|
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
5806 |
|
|
|
5807 |
|
|
static struct async_struct async_sercons;
|
5808 |
|
|
|
5809 |
|
|
/*
|
5810 |
|
|
* Wait for transmitter & holding register to empty
|
5811 |
|
|
*/
|
5812 |
|
|
static inline void wait_for_xmitr(struct async_struct *info)
|
5813 |
|
|
{
|
5814 |
|
|
unsigned int status, tmout = 1000000;
|
5815 |
|
|
|
5816 |
|
|
do {
|
5817 |
|
|
status = serial_in(info, UART_LSR);
|
5818 |
|
|
|
5819 |
|
|
if (status & UART_LSR_BI)
|
5820 |
|
|
lsr_break_flag = UART_LSR_BI;
|
5821 |
|
|
|
5822 |
|
|
if (--tmout == 0)
|
5823 |
|
|
break;
|
5824 |
|
|
} while((status & BOTH_EMPTY) != BOTH_EMPTY);
|
5825 |
|
|
|
5826 |
|
|
/* Wait for flow control if necessary */
|
5827 |
|
|
if (info->flags & ASYNC_CONS_FLOW) {
|
5828 |
|
|
tmout = 1000000;
|
5829 |
|
|
while (--tmout &&
|
5830 |
|
|
((serial_in(info, UART_MSR) & UART_MSR_CTS) == 0));
|
5831 |
|
|
}
|
5832 |
|
|
}
|
5833 |
|
|
|
5834 |
|
|
|
5835 |
|
|
/*
|
5836 |
|
|
* Print a string to the serial port trying not to disturb
|
5837 |
|
|
* any possible real use of the port...
|
5838 |
|
|
*
|
5839 |
|
|
* The console must be locked when we get here.
|
5840 |
|
|
*/
|
5841 |
|
|
static void serial_console_write(struct console *co, const char *s,
|
5842 |
|
|
unsigned count)
|
5843 |
|
|
{
|
5844 |
|
|
static struct async_struct *info = &async_sercons;
|
5845 |
|
|
int ier;
|
5846 |
|
|
unsigned i;
|
5847 |
|
|
|
5848 |
|
|
/*
|
5849 |
|
|
* First save the IER then disable the interrupts
|
5850 |
|
|
*/
|
5851 |
|
|
ier = serial_in(info, UART_IER);
|
5852 |
|
|
serial_out(info, UART_IER, 0x00);
|
5853 |
|
|
|
5854 |
|
|
/*
|
5855 |
|
|
* Now, do each character
|
5856 |
|
|
*/
|
5857 |
|
|
for (i = 0; i < count; i++, s++) {
|
5858 |
|
|
wait_for_xmitr(info);
|
5859 |
|
|
|
5860 |
|
|
/*
|
5861 |
|
|
* Send the character out.
|
5862 |
|
|
* If a LF, also do CR...
|
5863 |
|
|
*/
|
5864 |
|
|
serial_out(info, UART_TX, *s);
|
5865 |
|
|
if (*s == 10) {
|
5866 |
|
|
wait_for_xmitr(info);
|
5867 |
|
|
serial_out(info, UART_TX, 13);
|
5868 |
|
|
}
|
5869 |
|
|
}
|
5870 |
|
|
|
5871 |
|
|
/*
|
5872 |
|
|
* Finally, Wait for transmitter & holding register to empty
|
5873 |
|
|
* and restore the IER
|
5874 |
|
|
*/
|
5875 |
|
|
wait_for_xmitr(info);
|
5876 |
|
|
serial_out(info, UART_IER, ier);
|
5877 |
|
|
}
|
5878 |
|
|
|
5879 |
|
|
static kdev_t serial_console_device(struct console *c)
|
5880 |
|
|
{
|
5881 |
|
|
return MKDEV(TTY_MAJOR, 64 + c->index);
|
5882 |
|
|
}
|
5883 |
|
|
|
5884 |
|
|
/*
|
5885 |
|
|
* Setup initial baud/bits/parity/flow control. We do two things here:
|
5886 |
|
|
* - construct a cflag setting for the first rs_open()
|
5887 |
|
|
* - initialize the serial port
|
5888 |
|
|
* Return non-zero if we didn't find a serial port.
|
5889 |
|
|
*/
|
5890 |
|
|
static int __init serial_console_setup(struct console *co, char *options)
|
5891 |
|
|
{
|
5892 |
|
|
static struct async_struct *info;
|
5893 |
|
|
struct serial_state *state;
|
5894 |
|
|
unsigned cval;
|
5895 |
|
|
int baud = 9600;
|
5896 |
|
|
int bits = 8;
|
5897 |
|
|
int parity = 'n';
|
5898 |
|
|
int doflow = 0;
|
5899 |
|
|
int cflag = CREAD | HUPCL | CLOCAL;
|
5900 |
|
|
int quot = 0;
|
5901 |
|
|
char *s;
|
5902 |
|
|
|
5903 |
|
|
if (options) {
|
5904 |
|
|
baud = simple_strtoul(options, NULL, 10);
|
5905 |
|
|
s = options;
|
5906 |
|
|
while(*s >= '0' && *s <= '9')
|
5907 |
|
|
s++;
|
5908 |
|
|
if (*s) parity = *s++;
|
5909 |
|
|
if (*s) bits = *s++ - '0';
|
5910 |
|
|
if (*s) doflow = (*s++ == 'r');
|
5911 |
|
|
}
|
5912 |
|
|
|
5913 |
|
|
/*
|
5914 |
|
|
* Now construct a cflag setting.
|
5915 |
|
|
*/
|
5916 |
|
|
switch(baud) {
|
5917 |
|
|
case 1200:
|
5918 |
|
|
cflag |= B1200;
|
5919 |
|
|
break;
|
5920 |
|
|
case 2400:
|
5921 |
|
|
cflag |= B2400;
|
5922 |
|
|
break;
|
5923 |
|
|
case 4800:
|
5924 |
|
|
cflag |= B4800;
|
5925 |
|
|
break;
|
5926 |
|
|
case 19200:
|
5927 |
|
|
cflag |= B19200;
|
5928 |
|
|
break;
|
5929 |
|
|
case 38400:
|
5930 |
|
|
cflag |= B38400;
|
5931 |
|
|
break;
|
5932 |
|
|
case 57600:
|
5933 |
|
|
cflag |= B57600;
|
5934 |
|
|
break;
|
5935 |
|
|
case 115200:
|
5936 |
|
|
cflag |= B115200;
|
5937 |
|
|
break;
|
5938 |
|
|
case 9600:
|
5939 |
|
|
default:
|
5940 |
|
|
cflag |= B9600;
|
5941 |
|
|
/*
|
5942 |
|
|
* Set this to a sane value to prevent a divide error
|
5943 |
|
|
*/
|
5944 |
|
|
baud = 9600;
|
5945 |
|
|
break;
|
5946 |
|
|
}
|
5947 |
|
|
switch(bits) {
|
5948 |
|
|
case 7:
|
5949 |
|
|
cflag |= CS7;
|
5950 |
|
|
break;
|
5951 |
|
|
default:
|
5952 |
|
|
case 8:
|
5953 |
|
|
cflag |= CS8;
|
5954 |
|
|
break;
|
5955 |
|
|
}
|
5956 |
|
|
switch(parity) {
|
5957 |
|
|
case 'o': case 'O':
|
5958 |
|
|
cflag |= PARODD;
|
5959 |
|
|
break;
|
5960 |
|
|
case 'e': case 'E':
|
5961 |
|
|
cflag |= PARENB;
|
5962 |
|
|
break;
|
5963 |
|
|
}
|
5964 |
|
|
co->cflag = cflag;
|
5965 |
|
|
|
5966 |
|
|
/*
|
5967 |
|
|
* Divisor, bytesize and parity
|
5968 |
|
|
*/
|
5969 |
|
|
state = rs_table + co->index;
|
5970 |
|
|
if (doflow)
|
5971 |
|
|
state->flags |= ASYNC_CONS_FLOW;
|
5972 |
|
|
info = &async_sercons;
|
5973 |
|
|
info->magic = SERIAL_MAGIC;
|
5974 |
|
|
info->state = state;
|
5975 |
|
|
info->port = state->port;
|
5976 |
|
|
info->flags = state->flags;
|
5977 |
|
|
#ifdef CONFIG_HUB6
|
5978 |
|
|
info->hub6 = state->hub6;
|
5979 |
|
|
#endif
|
5980 |
|
|
info->io_type = state->io_type;
|
5981 |
|
|
info->iomem_base = state->iomem_base;
|
5982 |
|
|
info->iomem_reg_shift = state->iomem_reg_shift;
|
5983 |
|
|
quot = state->baud_base / baud;
|
5984 |
|
|
cval = cflag & (CSIZE | CSTOPB);
|
5985 |
|
|
#if defined(__powerpc__) || defined(__alpha__)
|
5986 |
|
|
cval >>= 8;
|
5987 |
|
|
#else /* !__powerpc__ && !__alpha__ */
|
5988 |
|
|
cval >>= 4;
|
5989 |
|
|
#endif /* !__powerpc__ && !__alpha__ */
|
5990 |
|
|
if (cflag & PARENB)
|
5991 |
|
|
cval |= UART_LCR_PARITY;
|
5992 |
|
|
if (!(cflag & PARODD))
|
5993 |
|
|
cval |= UART_LCR_EPAR;
|
5994 |
|
|
|
5995 |
|
|
/*
|
5996 |
|
|
* Disable UART interrupts, set DTR and RTS high
|
5997 |
|
|
* and set speed.
|
5998 |
|
|
*/
|
5999 |
|
|
serial_out(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
|
6000 |
|
|
serial_out(info, UART_DLL, quot & 0xff); /* LS of divisor */
|
6001 |
|
|
serial_out(info, UART_DLM, quot >> 8); /* MS of divisor */
|
6002 |
|
|
serial_out(info, UART_LCR, cval); /* reset DLAB */
|
6003 |
|
|
serial_out(info, UART_IER, 0);
|
6004 |
|
|
serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
|
6005 |
|
|
|
6006 |
|
|
/*
|
6007 |
|
|
* If we read 0xff from the LSR, there is no UART here.
|
6008 |
|
|
*/
|
6009 |
|
|
if (serial_in(info, UART_LSR) == 0xff)
|
6010 |
|
|
return -1;
|
6011 |
|
|
|
6012 |
|
|
return 0;
|
6013 |
|
|
}
|
6014 |
|
|
|
6015 |
|
|
static struct console sercons = {
|
6016 |
|
|
name: "ttyS",
|
6017 |
|
|
write: serial_console_write,
|
6018 |
|
|
device: serial_console_device,
|
6019 |
|
|
setup: serial_console_setup,
|
6020 |
|
|
flags: CON_PRINTBUFFER,
|
6021 |
|
|
index: -1,
|
6022 |
|
|
};
|
6023 |
|
|
|
6024 |
|
|
/*
|
6025 |
|
|
* Register console.
|
6026 |
|
|
*/
|
6027 |
|
|
void __init serial_console_init(void)
|
6028 |
|
|
{
|
6029 |
|
|
register_console(&sercons);
|
6030 |
|
|
}
|
6031 |
|
|
#endif
|
6032 |
|
|
|
6033 |
|
|
/*
|
6034 |
|
|
Local variables:
|
6035 |
|
|
compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c"
|
6036 |
|
|
End:
|
6037 |
|
|
*/
|