[parisc-linux-cvs] [PATCH] First pass for the Serial Mux

Ryan Bradetich rbradetich@uswest.net
04 Nov 2002 21:51:39 -0700


--=-3WXjfD0Fca6IFD7NCecJ
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

I have committed the first pass for the Serial Mux ported to the new
serial core.  Input/Output currently works, but the driver still needs
lots of cleanups.

- Ryan




--=-3WXjfD0Fca6IFD7NCecJ
Content-Disposition: attachment; filename=mux.diff
Content-Transfer-Encoding: quoted-printable
Content-Type: text/x-patch; name=mux.diff; charset=ISO-8859-1

Index: Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/linux-2.5/Makefile,v
retrieving revision 1.27
diff -u -p -r1.27 Makefile
--- Makefile	4 Nov 2002 16:41:36 -0000	1.27
+++ Makefile	5 Nov 2002 04:37:26 -0000
@@ -1,7 +1,7 @@
 VERSION =3D 2
 PATCHLEVEL =3D 5
 SUBLEVEL =3D 45
-EXTRAVERSION =3D -pa6
+EXTRAVERSION =3D -pa7
=20
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
Index: arch/parisc/kernel/pdc_cons.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/pdc_cons.c,v
retrieving revision 1.6
diff -u -p -r1.6 pdc_cons.c
--- arch/parisc/kernel/pdc_cons.c	31 Oct 2002 06:07:33 -0000	1.6
+++ arch/parisc/kernel/pdc_cons.c	5 Nov 2002 04:37:26 -0000
@@ -52,15 +52,12 @@ static int pdc_console_setup(struct cons
 	return 0;
 }
=20
-#ifdef CONFIG_PDC_CONSOLE
+#if defined(CONFIG_PDC_CONSOLE) || defined(CONFIG_SERIAL_MUX)
+#define PDC_CONSOLE_DEVICE pdc_console_device
 static kdev_t pdc_console_device (struct console *c)
 {
         return mk_kdev(PDCCONS_MAJOR, 0);
 }
-#endif
-
-#ifdef CONFIG_PDC_CONSOLE
-#define PDC_CONSOLE_DEVICE pdc_console_device
 #else
 #define PDC_CONSOLE_DEVICE NULL
 #endif
@@ -95,7 +92,7 @@ static void pdc_console_init_force(void)
=20
 void __init pdc_console_init(void)
 {
-#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE)
+#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE) || defined(=
CONFIG_SERIAL_MUX)
 	pdc_console_init_force();
 #endif
 #ifdef EARLY_BOOTUP_DEBUG
Index: drivers/serial/Kconfig
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/linux-2.5/drivers/serial/Kconfig,v
retrieving revision 1.2
diff -u -p -r1.2 Kconfig
--- drivers/serial/Kconfig	31 Oct 2002 23:30:15 -0000	1.2
+++ drivers/serial/Kconfig	5 Nov 2002 04:37:26 -0000
@@ -317,9 +317,32 @@ config SERIAL_SUNSU
 	  mouse on (PCI) UltraSPARC systems.  Say Y or M if you want to be able
 	  to these serial ports.
=20
+config SERIAL_MUX
+	bool "Serial MUX support"
+	depends on PARISC
+	default y
+	help
+	  Saying Y here will enable the hardware MUX serial driver for
+	  the Nova and K class systems.  The hardware MUX is not 8250/16550=20
+	  compatable therefore the /dev/ttyB0 device is shared between the=20
+	  Serial MUX and the PDC software console.  The following steps=20
+	  need to be completed to use the Serial MUX:
+
+	    1. create the device entry (mknod /dev/ttyB0 c 60 0)
+	    2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
+	    3. Add device ttyB0 to /etc/securetty (if you want to log on as
+		 root on this console.)
+	    4. Change the kernel command console parameter to: console=3DttyB0
+
+config SERIAL_MUX_CONSOLE
+        bool
+        depends on SERIAL_MUX
+        default y
+
 config PDC_CONSOLE
 	bool "PDC software console support"
-	depends on PARISC
+	depends on PARISC && !SERIAL_MUX
+	default n
 	help
 	  Saying Y here will enable the software based PDC console to be=20
 	  used as the system console.  This is useful for machines in=20
Index: drivers/serial/Makefile
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/linux-2.5/drivers/serial/Makefile,v
retrieving revision 1.5
diff -u -p -r1.5 Makefile
--- drivers/serial/Makefile	21 Oct 2002 03:45:50 -0000	1.5
+++ drivers/serial/Makefile	5 Nov 2002 04:37:26 -0000
@@ -24,5 +24,6 @@ obj-$(CONFIG_SERIAL_SUNCORE) +=3D suncore.
 obj-$(CONFIG_SERIAL_SUNZILOG) +=3D sunzilog.o
 obj-$(CONFIG_SERIAL_SUNSU) +=3D sunsu.o
 obj-$(CONFIG_SERIAL_SUNSAB) +=3D sunsab.o
+obj-$(CONFIG_SERIAL_MUX) +=3D mux.o
=20
 include $(TOPDIR)/Rules.make
Index: drivers/serial/core.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/linux-2.5/drivers/serial/core.c,v
retrieving revision 1.5
diff -u -p -r1.5 core.c
--- drivers/serial/core.c	2 Nov 2002 22:48:54 -0000	1.5
+++ drivers/serial/core.c	5 Nov 2002 04:37:27 -0000
@@ -522,7 +522,7 @@ static void uart_flush_buffer(struct tty
 	unsigned long flags;
=20
 	DPRINTK("uart_flush_buffer(%d) called\n",
-	        MINOR(tty->device) - tty->driver.minor_start);
+	        minor(tty->device) - tty->driver.minor_start);
=20
 	spin_lock_irqsave(&info->port->lock, flags);
 	uart_circ_clear(&info->xmit);
Index: drivers/serial/mux.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: drivers/serial/mux.c
diff -N drivers/serial/mux.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drivers/serial/mux.c	5 Nov 2002 04:37:27 -0000
@@ -0,0 +1,452 @@
+/*
+** mux.c:
+**      MUX console for the NOVA and K-Class systems.
+**
+**	(c) Copyright 2002 Ryan Bradetich
+**	(c) Copyright 2002 Hewlett-Packard Company
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This Driver currently only supports the console (port 0) on the MUX.
+** Additional work will be needed on this driver to enable the full
+** functionality of the MUX.
+**
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#define MUX_NR 1
+
+#define MUX_OFFSET 0x800
+#define MUX_LINE_OFFSET 0x80
+
+#define MUX_FIFO_SIZE 255
+#define MUX_MIN_FREE_SIZE 32
+
+#define MUX_FIFO_DRAIN_DELAY 1
+/* #define MUX_POLL_DELAY (30 * HZ / 1000) */
+#define MUX_POLL_DELAY HZ
+
+#define IO_COMMAND_REG_OFFSET 0x30
+#define IO_STATUS_REG_OFFSET 0x34
+#define IO_DATA_REG_OFFSET 0x3c
+#define IO_DCOUNT_REG_OFFSET 0x40
+#define IO_UCOUNT_REG_OFFSET 0x44
+#define IO_FIFOS_REG_OFFSET 0x48
+
+#define MUX_EOFIFO(status) ((status & 0xF000) =3D=3D 0xF000)
+#define MUX_STATUS(status) ((status & 0xF000) =3D=3D 0x8000)
+#define MUX_BREAK(status) ((status & 0xF000) =3D=3D 0x2000)
+
+
+static struct uart_port mux_ports[MUX_NR];
+static struct timer_list mux_timer;
+
+#define UART_PUT_CHAR(p, c) __raw_writel((c), (unsigned long)(p)->membase =
+ IO_DATA_REG_OFFSET)
+
+
+/**
+ * mux_tx_empty - Check if the transmitter fifo is empty.
+ * @port: Ptr to the uart_port.
+ *
+ * This function test if the transmitter fifo for the port
+ * described by 'port' is empty.  If it is empty, this function
+ * should return TIOCSER_TEMT, otherwise return 0.
+ */
+static unsigned int mux_tx_empty(struct uart_port *port)
+{
+	unsigned int cnt =3D __raw_readl((unsigned long)port->membase=20
+				+ IO_DCOUNT_REG_OFFSET);
+
+	return cnt ? 0 : TIOCSER_TEMT;
+}=20
+
+/**
+ * mux_set_mctrl - Set the current state of the modem control inputs.
+ * @ports: Ptr to the uart_port.
+ * @mctrl: Modem control bits.
+ *
+ * The Serial MUX does not support CTS, DCD or DSR so this function
+ * is ignored.
+ */
+static void mux_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+/**
+ * mux_get_mctrl - Returns the current state of modem control inputs.
+ * @port: Ptr to the uart_port.
+ *
+ * The Serial MUX does not support CTS, DCD or DSR so these lines are
+ * treated as permanently active.
+ */
+static unsigned int mux_get_mctrl(struct uart_port *port)
+{=20
+	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+}
+
+static void mux_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+}
+
+static void mux_stop_rx(struct uart_port *port)
+{
+}
+
+static void mux_enable_ms(struct uart_port *port)
+{
+}
+
+static void mux_break_ctl(struct uart_port *port, int break_state)
+{
+}
+/**
+ * mux_write - Write chars to the mux fifo.
+ * @port: Ptr to the uart_port.
+ *
+ * This function writes all the data from the uart buffer to
+ * the mux fifo.
+ */
+static void mux_write(struct uart_port *port)
+{
+	int count;
+	struct circ_buf *xmit =3D &port->info->xmit;
+
+	if(port->x_char) {
+		UART_PUT_CHAR(port, port->x_char);
+		port->icount.tx++;
+		port->x_char =3D 0;
+		return;
+	}
+
+	if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		mux_stop_tx(port, 0);
+		return;
+	}
+
+	count =3D port->fifosize >> 1;
+	do {
+		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+		xmit->tail =3D (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+		if(uart_circ_empty(xmit))
+			break;
+
+	} while(--count > 0);
+
+	if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_event(port, EVT_WRITE_WAKEUP);
+
+	if (uart_circ_empty(xmit))
+		mux_stop_tx(port, 0);
+}
+
+/**
+ * mux_read - Read chars from the mux fifo.
+ * @port: Ptr to the uart_port.
+ *
+ * This reads all available data from the mux's fifo and pushes
+ * the data to the tty layer.
+ */
+static void mux_read(struct uart_port *port)
+{
+        int data;
+        struct tty_struct *tty =3D port->info->tty;
+
+        while(1) {
+                data =3D __raw_readl((unsigned long)port->membase
+                                   + IO_DATA_REG_OFFSET);
+
+                if (MUX_STATUS(data))
+                        continue;
+
+                if (MUX_EOFIFO(data))
+                        break;
+
+                if (tty->flip.count >=3D TTY_FLIPBUF_SIZE)
+                        continue;
+
+                *tty->flip.char_buf_ptr =3D data & 0xffu;
+                *tty->flip.flag_buf_ptr =3D TTY_NORMAL;
+		port->icount.rx++;
+
+                tty->flip.flag_buf_ptr++;
+                tty->flip.char_buf_ptr++;
+                tty->flip.count++;
+        }
+
+        tty_flip_buffer_push(tty);
+}
+
+static int mux_startup(struct uart_port *port)
+{
+	mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
+	return 0;
+}
+
+static void mux_shutdown(struct uart_port *port)
+{
+}
+
+static void
+mux_change_speed(struct uart_port *port, unsigned int cflag,
+                 unsigned int iflag, unsigned int quot)
+{
+}
+
+static const char *mux_type(struct uart_port *port)
+{
+	return "Serial Mux";
+}
+
+static void mux_release_port(struct uart_port *port)
+{
+}
+
+static int mux_request_port(struct uart_port *port)
+{
+	return request_mem_region(port->mapbase, MUX_LINE_OFFSET, "Serial Mux")
+		!=3D NULL ? 0 : -EBUSY;
+}
+
+static void mux_config_port(struct uart_port *port, int flags)
+{
+	port->type =3D PORT_MUX;
+}
+
+/**
+ * mux_verify_port -=20
+ * @port: Ptr to the uart_port.
+ * @ser:=20
+ *
+ * Verify the new serial port information contained within serinfo is
+ * suitable for this port type.
+ */
+static int mux_verify_port(struct uart_port *port, struct serial_struct *s=
er)
+{
+	if(port->membase =3D=3D NULL)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * mux_drv_poll - Mux poll function.  =20
+ * @unused: Unused variable
+ *
+ * This function periodically polls the Serial MUX to check for new data.
+ */
+static void mux_poll(unsigned long unused)
+{ =20
+	struct uart_port *port =3D &mux_ports[0];
+
+	mux_read(port);
+	mux_write(port);
+	mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
+}
+
+
+static struct uart_ops mux_pops =3D {
+        .tx_empty       =3D mux_tx_empty,
+        .set_mctrl      =3D mux_set_mctrl,
+        .get_mctrl      =3D mux_get_mctrl,
+        .stop_tx        =3D mux_stop_tx,
+        .start_tx       =3D mux_start_tx,
+        .stop_rx        =3D mux_stop_rx,
+        .enable_ms      =3D mux_enable_ms,
+        .break_ctl      =3D mux_break_ctl,
+        .startup        =3D mux_startup,
+        .shutdown       =3D mux_shutdown,
+        .change_speed   =3D mux_change_speed,
+        .type           =3D mux_type,
+        .release_port   =3D mux_release_port,
+        .request_port   =3D mux_request_port,
+        .config_port    =3D mux_config_port,
+        .verify_port    =3D mux_verify_port,
+};
+
+#if 0
+static void
+mux_console_write(struct console *co, const char *s, unsigned int count)
+{
+	printk("[%s] %s(): %d\n", __FILE__, __FUNCTION__, __LINE__);
+}
+
+static kdev_t mux_console_device(struct console *co)
+{
+	printk("[%s] %s(): %d\n", __FILE__, __FUNCTION__, __LINE__);
+	return mk_kdev(PDCCONS_MAJOR, 0 + co->index);
+}
+
+static void __init
+mux_console_get_options(struct uart_port *port, int *baud,=20
+			int *parity, int *bits)
+{
+	printk("[%s] %s(): %d\n", __FILE__, __FUNCTION__, __LINE__);
+}
+
+static int __init mux_console_setup(struct console *co, char *options)
+{
+        struct uart_port *port;
+        int baud =3D 9600;
+        int bits =3D 8;
+        int parity =3D 'n';
+        int flow =3D 'n';
+
+	printk("[%s] %s(): %d\n", __FILE__, __FUNCTION__, __LINE__);
+        /*
+         * Check whether an invalid uart number has been specified, and
+         * if so, search for the first available port that does have
+         * console support.
+         */
+        if (co->index >=3D MUX_NR)
+                co->index =3D 0;
+
+	port =3D &mux_ports[0];
+
+        if (options)
+                uart_parse_options(options, &baud, &parity, &bits, &flow);
+        else
+                mux_console_get_options(port, &baud, &parity, &bits);
+
+        return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct console mux_console =3D {
+        .name	=3D "ttyB",
+        .write	=3D mux_console_write,
+        .device	=3D mux_console_device,
+        .setup	=3D mux_console_setup,
+        .flags	=3D CON_PRINTBUFFER,
+        .index	=3D -1,
+};
+
+void __init mux_console_init(void)
+{
+	printk("[%s] %s(): %d\n", __FILE__, __FUNCTION__, __LINE__);
+	register_console(&mux_console);
+}
+#endif
+
+static struct uart_driver mux_reg =3D {
+	.owner                  =3D THIS_MODULE,
+	.driver_name            =3D "ttyB",
+#ifdef CONFIG_DEVFS_FS
+	.dev_name               =3D "ttyB%d",
+#else
+	.dev_name               =3D "ttyB",
+#endif
+	.major                  =3D PDCCONS_MAJOR,
+	.minor                  =3D 0,
+	.nr                     =3D MUX_NR,=20
+	.cons                   =3D NULL,
+};
+
+/**
+ * mux_probe - Determine if the Serial Mux should claim this device.
+ * @dev: The parisc device.
+ *
+ * Deterimine if the Serial Mux should claim this chip (return 0)
+ * or not (return 1).
+ */
+static int __init mux_probe(struct parisc_device *dev)
+{
+        int i, ret;
+	struct uart_port *port =3D &mux_ports[0];
+
+        init_timer(&mux_timer);
+        mux_timer.function =3D mux_poll;
+
+        printk(KERN_INFO "Serial mux driver Revision: 0.1\n");
+
+        ret =3D uart_register_driver(&mux_reg);
+	if(ret)
+		return ret;
+
+	for (i =3D 0; i < MUX_NR; i++) {
+		port =3D &mux_ports[i];
+
+	        port->iobase   =3D dev->hpa + MUX_OFFSET;
+	        port->mapbase  =3D dev->hpa + MUX_OFFSET;
+		port->membase  =3D (void *)(dev->hpa + MUX_OFFSET);
+		port->iotype   =3D SERIAL_IO_MEM;
+		port->type     =3D PORT_MUX;
+		port->irq      =3D 0;
+		port->uartclk  =3D 0;
+		port->fifosize =3D MUX_FIFO_SIZE;
+		port->ops      =3D &mux_pops;
+		port->flags    =3D UPF_BOOT_AUTOCONF;
+		port->line     =3D 0;
+
+		uart_add_one_port(&mux_reg, port);
+        }
+
+        return 0;
+}
+
+static struct parisc_device_id mux_tbl[] =3D {
+        { HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D },
+        { 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, mux_tbl);
+
+static struct parisc_driver mux_driver =3D {
+        name:           "Serial MUX driver",
+        id_table:       mux_tbl,
+        probe:          mux_probe,
+};
+
+/**
+ * mux_init - Serial MUX initalization procedure.
+ *
+ * Register the Serial MUX driver.
+ */
+static int __init mux_init(void)
+{
+        return register_parisc_driver(&mux_driver);
+}
+
+/**
+ * mux_exit - Serial MUX cleanup procedure.
+ *
+ * Unregister the Serial MUX driver from the tty layer.
+ */
+static void __exit mux_exit(void)
+{
+        int i;
+
+        for(i =3D 0; i < MUX_NR; i++) {
+                uart_remove_one_port(&mux_reg, &mux_ports[i]);
+        }
+
+        uart_unregister_driver(&mux_reg);
+}
+
+module_init(mux_init);
+module_exit(mux_exit);
+
+MODULE_AUTHOR("Ryan Bradetich");
+MODULE_DESCRIPTION("Serial MUX driver");
+MODULE_LICENSE("GPL");
Index: include/linux/serial_core.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/linux-2.5/include/linux/serial_core.h,v
retrieving revision 1.4
diff -u -p -r1.4 serial_core.h
--- include/linux/serial_core.h	21 Oct 2002 03:46:12 -0000	1.4
+++ include/linux/serial_core.h	5 Nov 2002 04:37:27 -0000
@@ -55,6 +55,9 @@
 #define PORT_SUNZILOG	38
 #define PORT_SUNSAB	39
=20
+/* Parisc type numbers. */
+#define PORT_MUX        40
+
 #ifdef __KERNEL__
=20
 #include <linux/config.h>

--=-3WXjfD0Fca6IFD7NCecJ--