diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-01-13 15:10:18 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-01-13 15:10:18 -0500 |
commit | ab4382d27412e7e3e7c936e8d50d8888dfac3df8 (patch) | |
tree | 51d96dea2431140358784b6b426715f37f74fd53 /drivers/tty/serial/mux.c | |
parent | 728674a7e466628df2aeec6d11a2ae1ef968fb67 (diff) |
tty: move drivers/serial/ to drivers/tty/serial/
The serial drivers are really just tty drivers, so move them to
drivers/tty/ to make things a bit neater overall.
This is part of the tty/serial driver movement proceedure as proposed by
Arnd Bergmann and approved by everyone involved a number of months ago.
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Rogier Wolff <R.E.Wolff@bitwizard.nl>
Cc: Michael H. Warfield <mhw@wittsend.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/tty/serial/mux.c')
-rw-r--r-- | drivers/tty/serial/mux.c | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c new file mode 100644 index 000000000000..9711e06a8374 --- /dev/null +++ b/drivers/tty/serial/mux.c | |||
@@ -0,0 +1,633 @@ | |||
1 | /* | ||
2 | ** mux.c: | ||
3 | ** serial driver for the Mux console found in some PA-RISC servers. | ||
4 | ** | ||
5 | ** (c) Copyright 2002 Ryan Bradetich | ||
6 | ** (c) Copyright 2002 Hewlett-Packard Company | ||
7 | ** | ||
8 | ** This program is free software; you can redistribute it and/or modify | ||
9 | ** it under the terms of the GNU General Public License as published by | ||
10 | ** the Free Software Foundation; either version 2 of the License, or | ||
11 | ** (at your option) any later version. | ||
12 | ** | ||
13 | ** This Driver currently only supports the console (port 0) on the MUX. | ||
14 | ** Additional work will be needed on this driver to enable the full | ||
15 | ** functionality of the MUX. | ||
16 | ** | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/tty.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/serial.h> | ||
24 | #include <linux/console.h> | ||
25 | #include <linux/delay.h> /* for udelay */ | ||
26 | #include <linux/device.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/parisc-device.h> | ||
30 | |||
31 | #ifdef CONFIG_MAGIC_SYSRQ | ||
32 | #include <linux/sysrq.h> | ||
33 | #define SUPPORT_SYSRQ | ||
34 | #endif | ||
35 | |||
36 | #include <linux/serial_core.h> | ||
37 | |||
38 | #define MUX_OFFSET 0x800 | ||
39 | #define MUX_LINE_OFFSET 0x80 | ||
40 | |||
41 | #define MUX_FIFO_SIZE 255 | ||
42 | #define MUX_POLL_DELAY (30 * HZ / 1000) | ||
43 | |||
44 | #define IO_DATA_REG_OFFSET 0x3c | ||
45 | #define IO_DCOUNT_REG_OFFSET 0x40 | ||
46 | |||
47 | #define MUX_EOFIFO(status) ((status & 0xF000) == 0xF000) | ||
48 | #define MUX_STATUS(status) ((status & 0xF000) == 0x8000) | ||
49 | #define MUX_BREAK(status) ((status & 0xF000) == 0x2000) | ||
50 | |||
51 | #define MUX_NR 256 | ||
52 | static unsigned int port_cnt __read_mostly; | ||
53 | struct mux_port { | ||
54 | struct uart_port port; | ||
55 | int enabled; | ||
56 | }; | ||
57 | static struct mux_port mux_ports[MUX_NR]; | ||
58 | |||
59 | static struct uart_driver mux_driver = { | ||
60 | .owner = THIS_MODULE, | ||
61 | .driver_name = "ttyB", | ||
62 | .dev_name = "ttyB", | ||
63 | .major = MUX_MAJOR, | ||
64 | .minor = 0, | ||
65 | .nr = MUX_NR, | ||
66 | }; | ||
67 | |||
68 | static struct timer_list mux_timer; | ||
69 | |||
70 | #define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET) | ||
71 | #define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET) | ||
72 | |||
73 | /** | ||
74 | * get_mux_port_count - Get the number of available ports on the Mux. | ||
75 | * @dev: The parisc device. | ||
76 | * | ||
77 | * This function is used to determine the number of ports the Mux | ||
78 | * supports. The IODC data reports the number of ports the Mux | ||
79 | * can support, but there are cases where not all the Mux ports | ||
80 | * are connected. This function can override the IODC and | ||
81 | * return the true port count. | ||
82 | */ | ||
83 | static int __init get_mux_port_count(struct parisc_device *dev) | ||
84 | { | ||
85 | int status; | ||
86 | u8 iodc_data[32]; | ||
87 | unsigned long bytecnt; | ||
88 | |||
89 | /* If this is the built-in Mux for the K-Class (Eole CAP/MUX), | ||
90 | * we only need to allocate resources for 1 port since the | ||
91 | * other 7 ports are not connected. | ||
92 | */ | ||
93 | if(dev->id.hversion == 0x15) | ||
94 | return 1; | ||
95 | |||
96 | status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32); | ||
97 | BUG_ON(status != PDC_OK); | ||
98 | |||
99 | /* Return the number of ports specified in the iodc data. */ | ||
100 | return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * mux_tx_empty - Check if the transmitter fifo is empty. | ||
105 | * @port: Ptr to the uart_port. | ||
106 | * | ||
107 | * This function test if the transmitter fifo for the port | ||
108 | * described by 'port' is empty. If it is empty, this function | ||
109 | * should return TIOCSER_TEMT, otherwise return 0. | ||
110 | */ | ||
111 | static unsigned int mux_tx_empty(struct uart_port *port) | ||
112 | { | ||
113 | return UART_GET_FIFO_CNT(port) ? 0 : TIOCSER_TEMT; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * mux_set_mctrl - Set the current state of the modem control inputs. | ||
118 | * @ports: Ptr to the uart_port. | ||
119 | * @mctrl: Modem control bits. | ||
120 | * | ||
121 | * The Serial MUX does not support CTS, DCD or DSR so this function | ||
122 | * is ignored. | ||
123 | */ | ||
124 | static void mux_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
125 | { | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * mux_get_mctrl - Returns the current state of modem control inputs. | ||
130 | * @port: Ptr to the uart_port. | ||
131 | * | ||
132 | * The Serial MUX does not support CTS, DCD or DSR so these lines are | ||
133 | * treated as permanently active. | ||
134 | */ | ||
135 | static unsigned int mux_get_mctrl(struct uart_port *port) | ||
136 | { | ||
137 | return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * mux_stop_tx - Stop transmitting characters. | ||
142 | * @port: Ptr to the uart_port. | ||
143 | * | ||
144 | * The Serial MUX does not support this function. | ||
145 | */ | ||
146 | static void mux_stop_tx(struct uart_port *port) | ||
147 | { | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * mux_start_tx - Start transmitting characters. | ||
152 | * @port: Ptr to the uart_port. | ||
153 | * | ||
154 | * The Serial Mux does not support this function. | ||
155 | */ | ||
156 | static void mux_start_tx(struct uart_port *port) | ||
157 | { | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * mux_stop_rx - Stop receiving characters. | ||
162 | * @port: Ptr to the uart_port. | ||
163 | * | ||
164 | * The Serial Mux does not support this function. | ||
165 | */ | ||
166 | static void mux_stop_rx(struct uart_port *port) | ||
167 | { | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * mux_enable_ms - Enable modum status interrupts. | ||
172 | * @port: Ptr to the uart_port. | ||
173 | * | ||
174 | * The Serial Mux does not support this function. | ||
175 | */ | ||
176 | static void mux_enable_ms(struct uart_port *port) | ||
177 | { | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * mux_break_ctl - Control the transmitssion of a break signal. | ||
182 | * @port: Ptr to the uart_port. | ||
183 | * @break_state: Raise/Lower the break signal. | ||
184 | * | ||
185 | * The Serial Mux does not support this function. | ||
186 | */ | ||
187 | static void mux_break_ctl(struct uart_port *port, int break_state) | ||
188 | { | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * mux_write - Write chars to the mux fifo. | ||
193 | * @port: Ptr to the uart_port. | ||
194 | * | ||
195 | * This function writes all the data from the uart buffer to | ||
196 | * the mux fifo. | ||
197 | */ | ||
198 | static void mux_write(struct uart_port *port) | ||
199 | { | ||
200 | int count; | ||
201 | struct circ_buf *xmit = &port->state->xmit; | ||
202 | |||
203 | if(port->x_char) { | ||
204 | UART_PUT_CHAR(port, port->x_char); | ||
205 | port->icount.tx++; | ||
206 | port->x_char = 0; | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | if(uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
211 | mux_stop_tx(port); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | count = (port->fifosize) - UART_GET_FIFO_CNT(port); | ||
216 | do { | ||
217 | UART_PUT_CHAR(port, xmit->buf[xmit->tail]); | ||
218 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
219 | port->icount.tx++; | ||
220 | if(uart_circ_empty(xmit)) | ||
221 | break; | ||
222 | |||
223 | } while(--count > 0); | ||
224 | |||
225 | while(UART_GET_FIFO_CNT(port)) | ||
226 | udelay(1); | ||
227 | |||
228 | if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
229 | uart_write_wakeup(port); | ||
230 | |||
231 | if (uart_circ_empty(xmit)) | ||
232 | mux_stop_tx(port); | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * mux_read - Read chars from the mux fifo. | ||
237 | * @port: Ptr to the uart_port. | ||
238 | * | ||
239 | * This reads all available data from the mux's fifo and pushes | ||
240 | * the data to the tty layer. | ||
241 | */ | ||
242 | static void mux_read(struct uart_port *port) | ||
243 | { | ||
244 | int data; | ||
245 | struct tty_struct *tty = port->state->port.tty; | ||
246 | __u32 start_count = port->icount.rx; | ||
247 | |||
248 | while(1) { | ||
249 | data = __raw_readl(port->membase + IO_DATA_REG_OFFSET); | ||
250 | |||
251 | if (MUX_STATUS(data)) | ||
252 | continue; | ||
253 | |||
254 | if (MUX_EOFIFO(data)) | ||
255 | break; | ||
256 | |||
257 | port->icount.rx++; | ||
258 | |||
259 | if (MUX_BREAK(data)) { | ||
260 | port->icount.brk++; | ||
261 | if(uart_handle_break(port)) | ||
262 | continue; | ||
263 | } | ||
264 | |||
265 | if (uart_handle_sysrq_char(port, data & 0xffu)) | ||
266 | continue; | ||
267 | |||
268 | tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL); | ||
269 | } | ||
270 | |||
271 | if (start_count != port->icount.rx) { | ||
272 | tty_flip_buffer_push(tty); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * mux_startup - Initialize the port. | ||
278 | * @port: Ptr to the uart_port. | ||
279 | * | ||
280 | * Grab any resources needed for this port and start the | ||
281 | * mux timer. | ||
282 | */ | ||
283 | static int mux_startup(struct uart_port *port) | ||
284 | { | ||
285 | mux_ports[port->line].enabled = 1; | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * mux_shutdown - Disable the port. | ||
291 | * @port: Ptr to the uart_port. | ||
292 | * | ||
293 | * Release any resources needed for the port. | ||
294 | */ | ||
295 | static void mux_shutdown(struct uart_port *port) | ||
296 | { | ||
297 | mux_ports[port->line].enabled = 0; | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * mux_set_termios - Chane port parameters. | ||
302 | * @port: Ptr to the uart_port. | ||
303 | * @termios: new termios settings. | ||
304 | * @old: old termios settings. | ||
305 | * | ||
306 | * The Serial Mux does not support this function. | ||
307 | */ | ||
308 | static void | ||
309 | mux_set_termios(struct uart_port *port, struct ktermios *termios, | ||
310 | struct ktermios *old) | ||
311 | { | ||
312 | } | ||
313 | |||
314 | /** | ||
315 | * mux_type - Describe the port. | ||
316 | * @port: Ptr to the uart_port. | ||
317 | * | ||
318 | * Return a pointer to a string constant describing the | ||
319 | * specified port. | ||
320 | */ | ||
321 | static const char *mux_type(struct uart_port *port) | ||
322 | { | ||
323 | return "Mux"; | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * mux_release_port - Release memory and IO regions. | ||
328 | * @port: Ptr to the uart_port. | ||
329 | * | ||
330 | * Release any memory and IO region resources currently in use by | ||
331 | * the port. | ||
332 | */ | ||
333 | static void mux_release_port(struct uart_port *port) | ||
334 | { | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * mux_request_port - Request memory and IO regions. | ||
339 | * @port: Ptr to the uart_port. | ||
340 | * | ||
341 | * Request any memory and IO region resources required by the port. | ||
342 | * If any fail, no resources should be registered when this function | ||
343 | * returns, and it should return -EBUSY on failure. | ||
344 | */ | ||
345 | static int mux_request_port(struct uart_port *port) | ||
346 | { | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | /** | ||
351 | * mux_config_port - Perform port autoconfiguration. | ||
352 | * @port: Ptr to the uart_port. | ||
353 | * @type: Bitmask of required configurations. | ||
354 | * | ||
355 | * Perform any autoconfiguration steps for the port. This function is | ||
356 | * called if the UPF_BOOT_AUTOCONF flag is specified for the port. | ||
357 | * [Note: This is required for now because of a bug in the Serial core. | ||
358 | * rmk has already submitted a patch to linus, should be available for | ||
359 | * 2.5.47.] | ||
360 | */ | ||
361 | static void mux_config_port(struct uart_port *port, int type) | ||
362 | { | ||
363 | port->type = PORT_MUX; | ||
364 | } | ||
365 | |||
366 | /** | ||
367 | * mux_verify_port - Verify the port information. | ||
368 | * @port: Ptr to the uart_port. | ||
369 | * @ser: Ptr to the serial information. | ||
370 | * | ||
371 | * Verify the new serial port information contained within serinfo is | ||
372 | * suitable for this port type. | ||
373 | */ | ||
374 | static int mux_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
375 | { | ||
376 | if(port->membase == NULL) | ||
377 | return -EINVAL; | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | /** | ||
383 | * mux_drv_poll - Mux poll function. | ||
384 | * @unused: Unused variable | ||
385 | * | ||
386 | * This function periodically polls the Serial MUX to check for new data. | ||
387 | */ | ||
388 | static void mux_poll(unsigned long unused) | ||
389 | { | ||
390 | int i; | ||
391 | |||
392 | for(i = 0; i < port_cnt; ++i) { | ||
393 | if(!mux_ports[i].enabled) | ||
394 | continue; | ||
395 | |||
396 | mux_read(&mux_ports[i].port); | ||
397 | mux_write(&mux_ports[i].port); | ||
398 | } | ||
399 | |||
400 | mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); | ||
401 | } | ||
402 | |||
403 | |||
404 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | ||
405 | static void mux_console_write(struct console *co, const char *s, unsigned count) | ||
406 | { | ||
407 | /* Wait until the FIFO drains. */ | ||
408 | while(UART_GET_FIFO_CNT(&mux_ports[0].port)) | ||
409 | udelay(1); | ||
410 | |||
411 | while(count--) { | ||
412 | if(*s == '\n') { | ||
413 | UART_PUT_CHAR(&mux_ports[0].port, '\r'); | ||
414 | } | ||
415 | UART_PUT_CHAR(&mux_ports[0].port, *s++); | ||
416 | } | ||
417 | |||
418 | } | ||
419 | |||
420 | static int mux_console_setup(struct console *co, char *options) | ||
421 | { | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | struct tty_driver *mux_console_device(struct console *co, int *index) | ||
426 | { | ||
427 | *index = co->index; | ||
428 | return mux_driver.tty_driver; | ||
429 | } | ||
430 | |||
431 | static struct console mux_console = { | ||
432 | .name = "ttyB", | ||
433 | .write = mux_console_write, | ||
434 | .device = mux_console_device, | ||
435 | .setup = mux_console_setup, | ||
436 | .flags = CON_ENABLED | CON_PRINTBUFFER, | ||
437 | .index = 0, | ||
438 | }; | ||
439 | |||
440 | #define MUX_CONSOLE &mux_console | ||
441 | #else | ||
442 | #define MUX_CONSOLE NULL | ||
443 | #endif | ||
444 | |||
445 | static struct uart_ops mux_pops = { | ||
446 | .tx_empty = mux_tx_empty, | ||
447 | .set_mctrl = mux_set_mctrl, | ||
448 | .get_mctrl = mux_get_mctrl, | ||
449 | .stop_tx = mux_stop_tx, | ||
450 | .start_tx = mux_start_tx, | ||
451 | .stop_rx = mux_stop_rx, | ||
452 | .enable_ms = mux_enable_ms, | ||
453 | .break_ctl = mux_break_ctl, | ||
454 | .startup = mux_startup, | ||
455 | .shutdown = mux_shutdown, | ||
456 | .set_termios = mux_set_termios, | ||
457 | .type = mux_type, | ||
458 | .release_port = mux_release_port, | ||
459 | .request_port = mux_request_port, | ||
460 | .config_port = mux_config_port, | ||
461 | .verify_port = mux_verify_port, | ||
462 | }; | ||
463 | |||
464 | /** | ||
465 | * mux_probe - Determine if the Serial Mux should claim this device. | ||
466 | * @dev: The parisc device. | ||
467 | * | ||
468 | * Deterimine if the Serial Mux should claim this chip (return 0) | ||
469 | * or not (return 1). | ||
470 | */ | ||
471 | static int __init mux_probe(struct parisc_device *dev) | ||
472 | { | ||
473 | int i, status; | ||
474 | |||
475 | int port_count = get_mux_port_count(dev); | ||
476 | printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.6\n", port_count); | ||
477 | |||
478 | dev_set_drvdata(&dev->dev, (void *)(long)port_count); | ||
479 | request_mem_region(dev->hpa.start + MUX_OFFSET, | ||
480 | port_count * MUX_LINE_OFFSET, "Mux"); | ||
481 | |||
482 | if(!port_cnt) { | ||
483 | mux_driver.cons = MUX_CONSOLE; | ||
484 | |||
485 | status = uart_register_driver(&mux_driver); | ||
486 | if(status) { | ||
487 | printk(KERN_ERR "Serial mux: Unable to register driver.\n"); | ||
488 | return 1; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | for(i = 0; i < port_count; ++i, ++port_cnt) { | ||
493 | struct uart_port *port = &mux_ports[port_cnt].port; | ||
494 | port->iobase = 0; | ||
495 | port->mapbase = dev->hpa.start + MUX_OFFSET + | ||
496 | (i * MUX_LINE_OFFSET); | ||
497 | port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); | ||
498 | port->iotype = UPIO_MEM; | ||
499 | port->type = PORT_MUX; | ||
500 | port->irq = NO_IRQ; | ||
501 | port->uartclk = 0; | ||
502 | port->fifosize = MUX_FIFO_SIZE; | ||
503 | port->ops = &mux_pops; | ||
504 | port->flags = UPF_BOOT_AUTOCONF; | ||
505 | port->line = port_cnt; | ||
506 | |||
507 | /* The port->timeout needs to match what is present in | ||
508 | * uart_wait_until_sent in serial_core.c. Otherwise | ||
509 | * the time spent in msleep_interruptable will be very | ||
510 | * long, causing the appearance of a console hang. | ||
511 | */ | ||
512 | port->timeout = HZ / 50; | ||
513 | spin_lock_init(&port->lock); | ||
514 | |||
515 | status = uart_add_one_port(&mux_driver, port); | ||
516 | BUG_ON(status); | ||
517 | } | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int __devexit mux_remove(struct parisc_device *dev) | ||
523 | { | ||
524 | int i, j; | ||
525 | int port_count = (long)dev_get_drvdata(&dev->dev); | ||
526 | |||
527 | /* Find Port 0 for this card in the mux_ports list. */ | ||
528 | for(i = 0; i < port_cnt; ++i) { | ||
529 | if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET) | ||
530 | break; | ||
531 | } | ||
532 | BUG_ON(i + port_count > port_cnt); | ||
533 | |||
534 | /* Release the resources associated with each port on the device. */ | ||
535 | for(j = 0; j < port_count; ++j, ++i) { | ||
536 | struct uart_port *port = &mux_ports[i].port; | ||
537 | |||
538 | uart_remove_one_port(&mux_driver, port); | ||
539 | if(port->membase) | ||
540 | iounmap(port->membase); | ||
541 | } | ||
542 | |||
543 | release_mem_region(dev->hpa.start + MUX_OFFSET, port_count * MUX_LINE_OFFSET); | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | /* Hack. This idea was taken from the 8250_gsc.c on how to properly order | ||
548 | * the serial port detection in the proper order. The idea is we always | ||
549 | * want the builtin mux to be detected before addin mux cards, so we | ||
550 | * specifically probe for the builtin mux cards first. | ||
551 | * | ||
552 | * This table only contains the parisc_device_id of known builtin mux | ||
553 | * devices. All other mux cards will be detected by the generic mux_tbl. | ||
554 | */ | ||
555 | static struct parisc_device_id builtin_mux_tbl[] = { | ||
556 | { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */ | ||
557 | { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */ | ||
558 | { 0, } | ||
559 | }; | ||
560 | |||
561 | static struct parisc_device_id mux_tbl[] = { | ||
562 | { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D }, | ||
563 | { 0, } | ||
564 | }; | ||
565 | |||
566 | MODULE_DEVICE_TABLE(parisc, builtin_mux_tbl); | ||
567 | MODULE_DEVICE_TABLE(parisc, mux_tbl); | ||
568 | |||
569 | static struct parisc_driver builtin_serial_mux_driver = { | ||
570 | .name = "builtin_serial_mux", | ||
571 | .id_table = builtin_mux_tbl, | ||
572 | .probe = mux_probe, | ||
573 | .remove = __devexit_p(mux_remove), | ||
574 | }; | ||
575 | |||
576 | static struct parisc_driver serial_mux_driver = { | ||
577 | .name = "serial_mux", | ||
578 | .id_table = mux_tbl, | ||
579 | .probe = mux_probe, | ||
580 | .remove = __devexit_p(mux_remove), | ||
581 | }; | ||
582 | |||
583 | /** | ||
584 | * mux_init - Serial MUX initialization procedure. | ||
585 | * | ||
586 | * Register the Serial MUX driver. | ||
587 | */ | ||
588 | static int __init mux_init(void) | ||
589 | { | ||
590 | register_parisc_driver(&builtin_serial_mux_driver); | ||
591 | register_parisc_driver(&serial_mux_driver); | ||
592 | |||
593 | if(port_cnt > 0) { | ||
594 | /* Start the Mux timer */ | ||
595 | init_timer(&mux_timer); | ||
596 | mux_timer.function = mux_poll; | ||
597 | mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); | ||
598 | |||
599 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | ||
600 | register_console(&mux_console); | ||
601 | #endif | ||
602 | } | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | /** | ||
608 | * mux_exit - Serial MUX cleanup procedure. | ||
609 | * | ||
610 | * Unregister the Serial MUX driver from the tty layer. | ||
611 | */ | ||
612 | static void __exit mux_exit(void) | ||
613 | { | ||
614 | /* Delete the Mux timer. */ | ||
615 | if(port_cnt > 0) { | ||
616 | del_timer(&mux_timer); | ||
617 | #ifdef CONFIG_SERIAL_MUX_CONSOLE | ||
618 | unregister_console(&mux_console); | ||
619 | #endif | ||
620 | } | ||
621 | |||
622 | unregister_parisc_driver(&builtin_serial_mux_driver); | ||
623 | unregister_parisc_driver(&serial_mux_driver); | ||
624 | uart_unregister_driver(&mux_driver); | ||
625 | } | ||
626 | |||
627 | module_init(mux_init); | ||
628 | module_exit(mux_exit); | ||
629 | |||
630 | MODULE_AUTHOR("Ryan Bradetich"); | ||
631 | MODULE_DESCRIPTION("Serial MUX driver"); | ||
632 | MODULE_LICENSE("GPL"); | ||
633 | MODULE_ALIAS_CHARDEV_MAJOR(MUX_MAJOR); | ||