[parisc-linux-cvs] [PATCH] Serial Mux update for 2.5

Ryan Bradetich rbradetich@uswest.net
07 Nov 2002 21:57:19 -0700


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

The following changes were made:
	* Serial Mux is not dependant upon the 8250/16550 core anymore.
	* Added kerneldoc
	* sysrq now works.
	* Fixed a null ptr dereference.
	* Modified the serial core to cosmeticly handle polling drivers.
		[ Patch sent upstream to rmk for inclusion also.]


This driver still needs work for handling multiple serial ports, but it
works great for just the serial console.

--=-RliPMp65VWn23zroi6Oh
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.33
diff -u -p -r1.33 Makefile
--- Makefile	7 Nov 2002 17:48:16 -0000	1.33
+++ Makefile	8 Nov 2002 04:45:39 -0000
@@ -1,7 +1,7 @@
 VERSION =3D 2
 PATCHLEVEL =3D 5
 SUBLEVEL =3D 46
-EXTRAVERSION =3D -pa3
+EXTRAVERSION =3D -pa4
=20
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
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.3
diff -u -p -r1.3 Kconfig
--- drivers/serial/Kconfig	5 Nov 2002 04:46:58 -0000	1.3
+++ drivers/serial/Kconfig	8 Nov 2002 04:45:39 -0000
@@ -365,12 +365,12 @@ config SERIAL_SUNSAB
=20
 config SERIAL_CORE
 	tristate
-	default m if SERIAL_AMBA!=3Dy && SERIAL_CLPS711X!=3Dy && SERIAL_21285!=3D=
y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=3Dy=
 && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && (SERIAL_AMBA=3Dm || SERIAL_CLP=
S711X=3Dm || SERIAL_21285=3Dm || SERIAL_8250=3Dm)
-	default y if SERIAL_AMBA=3Dy || SERIAL_CLPS711X=3Dy || SERIAL_21285=3Dy |=
| SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=3Dy || SER=
IAL_ROCKETPORT || SERIAL_SUNCORE
+	default m if SERIAL_AMBA!=3Dy && SERIAL_CLPS711X!=3Dy && SERIAL_21285!=3D=
y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=3Dy=
 && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && (SERIAL_AMBA=3Dm || SERIAL_CLP=
S711X=3Dm || SERIAL_21285=3Dm || SERIAL_8250=3Dm) && SERIAL_MUX!=3Dy
+	default y if SERIAL_AMBA=3Dy || SERIAL_CLPS711X=3Dy || SERIAL_21285=3Dy |=
| SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=3Dy || SER=
IAL_ROCKETPORT || SERIAL_SUNCORE || SERIAL_MUX=3Dy
=20
 config SERIAL_CORE_CONSOLE
 	bool
-	depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285=
_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00=
_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_SUNCORE
+	depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285=
_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00=
_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_SUNCORE || SERIAL_MUX
 	default y
=20
 endmenu
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.7
diff -u -p -r1.7 core.c
--- drivers/serial/core.c	5 Nov 2002 18:10:41 -0000	1.7
+++ drivers/serial/core.c	8 Nov 2002 04:45:40 -0000
@@ -255,7 +255,8 @@ static void uart_shutdown(struct uart_in
 	/*
 	 * Ensure that the IRQ handler isn't running on another CPU.
 	 */
-	synchronize_irq(port->irq);
+	if(port->irq !=3D SERIAL_IRQ_NONE)
+		synchronize_irq(port->irq);
=20
 	/*
 	 * Free the transmit buffer page.
@@ -1996,7 +1997,12 @@ uart_report_port(struct uart_driver *drv
 		printk("MMIO 0x%lx", port->mapbase);
 		break;
 	}
-	printk(" (irq =3D %d) is a %s\n", port->irq, uart_type(port));
+
+	if(port->irq =3D=3D SERIAL_IRQ_NONE) {
+		printk(" (polling) is a %s\n", uart_type(port));
+	} else {
+		printk(" (irq =3D %d) is a %s\n", port->irq, uart_type(port));
+	}
 }
=20
 static void
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: /var/cvs/linux-2.5/drivers/serial/mux.c,v
retrieving revision 1.3
diff -u -p -r1.3 mux.c
--- drivers/serial/mux.c	5 Nov 2002 20:07:04 -0000	1.3
+++ drivers/serial/mux.c	8 Nov 2002 04:45:40 -0000
@@ -41,7 +41,7 @@
 #define MUX_MIN_FREE_SIZE 32
=20
 #define MUX_FIFO_DRAIN_DELAY 1
-#define MUX_POLL_DELAY (300 * HZ / 1000)=20
+#define MUX_POLL_DELAY (30 * HZ / 1000)=20
=20
 #define IO_COMMAND_REG_OFFSET 0x30
 #define IO_STATUS_REG_OFFSET 0x34
@@ -59,7 +59,7 @@ static struct uart_port mux_ports[MUX_NR
 static struct timer_list mux_timer;
=20
 #define UART_PUT_CHAR(p, c) __raw_writel((c), (unsigned long)(p)->membase =
+ IO_DATA_REG_OFFSET)
-
+#define UART_GET_FIFO_CNT(p) __raw_readl((unsigned long)(p)->membase + IO_=
DCOUNT_REG_OFFSET)
=20
 /**
  * mux_tx_empty - Check if the transmitter fifo is empty.
@@ -101,25 +101,59 @@ static unsigned int mux_get_mctrl(struct
 	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
 }
=20
+/**
+ * mux_stop_tx - Stop transmitting characters.
+ * @port: Ptr to the uart_port.
+ * @tty_stop: tty layer issue this command?
+ *
+ * The Serial MUX does not support this function.
+ */
 static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop)
 {
 }
=20
+/**
+ * mux_start_tx - Start transmitting characters.
+ * @port: Ptr to the uart_port.
+ * @tty_start: tty layer issue this command?
+ *
+ * The Serial Mux does not support this function.
+ */
 static void mux_start_tx(struct uart_port *port, unsigned int tty_start)
 {
 }
=20
+/**
+ * mux_stop_rx - Stop receiving characters.
+ * @port: Ptr to the uart_port.
+ *
+ * The Serial Mux does not support this function.
+ */
 static void mux_stop_rx(struct uart_port *port)
 {
 }
=20
+/**
+ * mux_enable_ms - Enable modum status interrupts.
+ * @port: Ptr to the uart_port.
+ *
+ * The Serial Mux does not support this function.
+ */
 static void mux_enable_ms(struct uart_port *port)
 {
 }
=20
+/**
+ * mux_break_ctl - Control the transmitssion of a break signal.
+ * @port: Ptr to the uart_port.
+ * @break_state: Raise/Lower the break signal.
+ *
+ * The Serial Mux does not support this function.
+ */
 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.
@@ -144,7 +178,7 @@ static void mux_write(struct uart_port *
 		return;
 	}
=20
-	count =3D port->fifosize >> 1;
+	count =3D (port->fifosize >> 1) - UART_GET_FIFO_CNT(port);
 	do {
 		UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
 		xmit->tail =3D (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -171,6 +205,7 @@ static void mux_write(struct uart_port *
 static void mux_read(struct uart_port *port)
 {
         int data;
+	__u32 start_count =3D port->icount.rx;
         struct tty_struct *tty =3D port->info->tty;
=20
         while(1) {
@@ -190,54 +225,119 @@ static void mux_read(struct uart_port *p
                 *tty->flip.flag_buf_ptr =3D TTY_NORMAL;
 		port->icount.rx++;
=20
+		if(MUX_BREAK(data)) {
+			port->icount.brk++;
+			if(uart_handle_break(port))
+				continue;
+		}
+
+                if(uart_handle_sysrq_char(port, data & 0xffu, NULL))
+                        continue;
+
                 tty->flip.flag_buf_ptr++;
                 tty->flip.char_buf_ptr++;
                 tty->flip.count++;
         }
-
-        tty_flip_buffer_push(tty);
+=09
+	if(start_count !=3D port->icount.rx) {
+        	tty_flip_buffer_push(tty);
+	}
 }
=20
+/**
+ * mux_startup - Initialize the port.
+ * @port: Ptr to the uart_port.
+ *
+ * Grab any resources needed for this port and start the
+ * mux timer.
+ */
 static int mux_startup(struct uart_port *port)
 {
 	mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
 	return 0;
 }
=20
+/**
+ * mux_shutdown - Disable the port.
+ * @port: Ptr to the uart_port.
+ *
+ * Release any resources needed for the port.
+ */
 static void mux_shutdown(struct uart_port *port)
 {
 }
=20
+/**
+ * mux_change_speed - Chane port parameters.
+ * @port: Ptr to the uart_port.
+ * @cflag: character flags.
+ * @iflag: interrupt flags.
+ * @quot:=20
+ *
+ * The Serial Mux does not support this function.
+ */
 static void
 mux_change_speed(struct uart_port *port, unsigned int cflag,
                  unsigned int iflag, unsigned int quot)
 {
 }
=20
+/**
+ * mux_type - Describe the port.
+ * @port: Ptr to the uart_port.
+ *
+ * Return a pointer to a string constant describing the
+ * specified port.
+ */
 static const char *mux_type(struct uart_port *port)
 {
-	return "Serial Mux";
+	return "Mux";
 }
=20
+/**
+ * release_port - Release memory and IO regions.
+ * @port: Ptr to the uart_port.
+ *=20
+ * Release any memory and IO region resources currently in use by
+ * the port.
+ */
 static void mux_release_port(struct uart_port *port)
 {
 }
=20
+/**
+ * mux_request_port - Request memory and IO regions.
+ * @port: Ptr to the uart_port.
+ *
+ * Request any memory and IO region resources required by the port.
+ * If any fail, no resources should be registered when this function
+ * returns, and it should return -EBUSY on failure.
+ */
 static int mux_request_port(struct uart_port *port)
 {
-	return request_mem_region(port->mapbase, MUX_LINE_OFFSET, "Serial Mux")
-		!=3D NULL ? 0 : -EBUSY;
+	return 0;
 }
=20
-static void mux_config_port(struct uart_port *port, int flags)
+/**
+ * mux_config_port - Perform port autoconfiguration.
+ * @port: Ptr to the uart_port.
+ * @type: Bitmask of required configurations.
+ *
+ * Perform any autoconfiguration steps for the port.  This functino is
+ * called if the UPF_BOOT_AUTOCONF flag is specified for the port.
+ * [Note: This is required for now because of a bug in the Serial core.
+ *  rmk has already submitted a patch to linus, should be available for
+ *  2.5.47.]
+ */
+static void mux_config_port(struct uart_port *port, int type)
 {
 	port->type =3D PORT_MUX;
 }
=20
 /**
- * mux_verify_port -=20
+ * mux_verify_port - Verify the port information.
  * @port: Ptr to the uart_port.
- * @ser:=20
+ * @ser: Ptr to the serial information.
  *
  * Verify the new serial port information contained within serinfo is
  * suitable for this port type.
@@ -266,6 +366,13 @@ static void mux_poll(unsigned long unuse
 }
=20
=20
+static struct console mux_console =3D {
+        .name           =3D "ttyB",
+        .flags          =3D CON_PRINTBUFFER,
+        .index          =3D 0,
+};
+
+
 static struct uart_ops mux_pops =3D {
         .tx_empty       =3D mux_tx_empty,
         .set_mctrl      =3D mux_set_mctrl,
@@ -285,69 +392,6 @@ static struct uart_ops mux_pops =3D {
         .verify_port    =3D mux_verify_port,
 };
=20
-#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",
@@ -359,7 +403,7 @@ static struct uart_driver mux_reg =3D {
 	.major                  =3D PDCCONS_MAJOR,
 	.minor                  =3D 0,
 	.nr                     =3D MUX_NR,=20
-	.cons                   =3D NULL,
+	.cons                   =3D &mux_console,
 };
=20
 /**
@@ -387,11 +431,11 @@ static int __init mux_probe(struct paris
 		port =3D &mux_ports[i];
=20
 	        port->iobase   =3D dev->hpa + MUX_OFFSET;
-	        port->mapbase  =3D dev->hpa + MUX_OFFSET;
 		port->membase  =3D (void *)(dev->hpa + MUX_OFFSET);
+		port->mapbase  =3D dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
 		port->iotype   =3D SERIAL_IO_MEM;
 		port->type     =3D PORT_MUX;
-		port->irq      =3D 0;
+		port->irq      =3D SERIAL_IRQ_NONE;
 		port->uartclk  =3D 0;
 		port->fifosize =3D MUX_FIFO_SIZE;
 		port->ops      =3D &mux_pops;
@@ -412,9 +456,9 @@ static struct parisc_device_id mux_tbl[]
 MODULE_DEVICE_TABLE(parisc, mux_tbl);
=20
 static struct parisc_driver mux_driver =3D {
-        name:           "Serial MUX driver",
-        id_table:       mux_tbl,
-        probe:          mux_probe,
+        .name     =3D "Serial MUX driver",
+        .id_table =3D mux_tbl,
+        .probe    =3D mux_probe,
 };
=20
 /**
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.6
diff -u -p -r1.6 serial_core.h
--- include/linux/serial_core.h	5 Nov 2002 18:11:04 -0000	1.6
+++ include/linux/serial_core.h	8 Nov 2002 04:45:40 -0000
@@ -58,6 +58,10 @@
 /* Parisc type numbers. */
 #define PORT_MUX        40
=20
+
+
+#define SERIAL_IRQ_NONE -1
+
 #ifdef __KERNEL__
=20
 #include <linux/config.h>

--=-RliPMp65VWn23zroi6Oh--