[parisc-linux-cvs] [Patch] Serial Mux updates.

Ryan Bradetich rbradetich@uswest.net
14 Nov 2002 23:41:57 -0700


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

This Serial mux updates handles multiple mux cards, and recognizes the
difference between 8 and 16 port muxes.  Work still needs to be done
to fix the ttyBxx numbering, but this is a serial core issue.

- Ryan




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

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.7
diff -u -p -r1.7 mux.c
--- drivers/serial/mux.c	8 Nov 2002 16:17:24 -0000	1.7
+++ drivers/serial/mux.c	15 Nov 2002 06:36:18 -0000
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/console.h>
+#include <linux/slab.h>
 #include <asm/io.h>
=20
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -32,34 +33,35 @@
=20
 #include <linux/serial_core.h>
=20
-#define MUX_NR 1
-
 #define MUX_OFFSET 0x800
 #define MUX_LINE_OFFSET 0x80
=20
 #define MUX_FIFO_SIZE 255
-#define MUX_MIN_FREE_SIZE 32
-
-#define MUX_FIFO_DRAIN_DELAY 1
-#define MUX_POLL_DELAY (30 * HZ / 1000)=20
+#define MUX_POLL_DELAY (30 * HZ / 1000)
=20
-#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
=20
 #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)
=20
+#define UART_NR 8
+struct mux_card {
+	struct uart_port ports[UART_NR];
+	struct uart_driver drv;
+	struct mux_card *next;
+};
+
+static struct mux_card mux_card_head =3D {
+	.next =3D NULL,
+};
=20
-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)
+#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8
=20
 /**
  * mux_tx_empty - Check if the transmitter fifo is empty.
@@ -191,8 +193,8 @@ static void mux_write(struct uart_port *
 	if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 		uart_write_wakeup(port);
=20
-	if (uart_circ_empty(xmit))
-		mux_stop_tx(port, 0);
+        if (uart_circ_empty(xmit))
+                mux_stop_tx(port, 0);
 }
=20
 /**
@@ -205,8 +207,8 @@ 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;
+	__u32 start_count =3D port->icount.rx;
=20
 	while(1) {
 		data =3D __raw_readl((unsigned long)port->membase
@@ -295,7 +297,7 @@ static const char *mux_type(struct uart_
 }
=20
 /**
- * release_port - Release memory and IO regions.
+ * mux_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
@@ -358,10 +360,19 @@ static int mux_verify_port(struct uart_p
  */
 static void mux_poll(unsigned long unused)
 { =20
-	struct uart_port *port =3D &mux_ports[0];
+	int i;
+	struct mux_card *card =3D &mux_card_head;
+
+	while(card) {
+		for(i =3D 0; i < UART_NR; ++i) {
+			if(!card->ports[i].info)
+				continue;
=20
-	mux_read(port);
-	mux_write(port);
+			mux_read(&card->ports[i]);
+			mux_write(&card->ports[i]);
+		}
+		card =3D card->next;
+	}
 	mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
 }
=20
@@ -396,20 +407,6 @@ static struct uart_ops mux_pops =3D {
 	.verify_port =3D		mux_verify_port,
 };
=20
-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%d",
-#endif
-	.major =3D		MUX_MAJOR,
-	.minor =3D		0,
-	.nr =3D			MUX_NR,=20
-	.cons =3D			MUX_CONSOLE,
-};
-
 /**
  * mux_probe - Determine if the Serial Mux should claim this device.
  * @dev: The parisc device.
@@ -419,36 +416,77 @@ static struct uart_driver mux_reg =3D {
  */
 static int __init mux_probe(struct parisc_device *dev)
 {
-	int i, ret;
-	struct uart_port *port =3D &mux_ports[0];
+	int i, j, ret, ports, port_cnt =3D 0;
+	u8 iodc_data[8];
+	unsigned long bytecnt;
+	struct uart_port *port;
+	struct mux_card *card =3D &mux_card_head;
+
+	ret =3D pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 8);
+	if(ret !=3D PDC_OK) {
+		printk(KERN_ERR "Serial mux: Unable to read IODC.\n");
+		return 1;
+	}
+
+	ports =3D GET_MUX_PORTS(iodc_data);
+ 	printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.2\n",
+		ports);
+
+	if(!card->drv.nr) {
+		init_timer(&mux_timer);
+		mux_timer.function =3D mux_poll;
+	} else {
+		port_cnt +=3D UART_NR;
+		while(card->next) {
+			card =3D card->next;
+			port_cnt +=3D UART_NR;
+		}=20
+	}
=20
-	init_timer(&mux_timer);
-	mux_timer.function =3D mux_poll;
+	for(i =3D 0; i < ports / UART_NR; ++i) {
+		if(card->drv.nr) {
+			card->next =3D kmalloc(sizeof(struct mux_card), GFP_KERNEL);
+			if(!card->next) {
+				printk(KERN_ERR "Serial mux: Unable to allocate memory.\n");
+				return 1;
+			}
+			memset(card->next, '\0', sizeof(struct mux_card));
+			card =3D card->next;
+		}
=20
-	printk(KERN_INFO "Serial mux driver Revision: 0.1\n");
+		card->drv.owner =3D THIS_MODULE;
+		card->drv.driver_name =3D "ttyB";
+		card->drv.dev_name =3D "ttyB%d";
+		card->drv.major =3D MUX_MAJOR;
+		card->drv.minor =3D port_cnt;
+		card->drv.nr =3D UART_NR;
+		card->drv.cons =3D MUX_CONSOLE;
+
+		ret =3D uart_register_driver(&card->drv);
+		if(ret) {
+			printk(KERN_ERR "Serial mux: Unable to register driver.\n");
+			return 1;
+		}
=20
-	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 0;
-		port->mapbase	=3D dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
-		port->membase	=3D ioremap(port->mapbase, MUX_LINE_OFFSET);
-		port->iotype	=3D SERIAL_IO_MEM;
-		port->type	=3D PORT_MUX;
-		port->irq	=3D SERIAL_IRQ_NONE;
-		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;
+		for(j =3D 0; j < UART_NR; ++j) {
+			port =3D &card->ports[j];
=20
-		uart_add_one_port(&mux_reg, port);
+			port->iobase	=3D 0;
+			port->mapbase	=3D dev->hpa + MUX_OFFSET + (j * MUX_LINE_OFFSET);
+			port->membase	=3D ioremap(port->mapbase, MUX_LINE_OFFSET);
+			port->iotype	=3D SERIAL_IO_MEM;
+			port->type	=3D PORT_MUX;
+			port->irq	=3D SERIAL_IRQ_NONE;
+			port->uartclk	=3D 0;
+			port->fifosize	=3D MUX_FIFO_SIZE;
+			port->ops	=3D &mux_pops;
+			port->flags	=3D UPF_BOOT_AUTOCONF;
+			port->line	=3D j;
+			ret =3D uart_add_one_port(&card->drv, port);
+			BUG_ON(ret);
+		}
+		port_cnt +=3D UART_NR;
 	}
-
 	return 0;
 }
=20
@@ -460,7 +498,7 @@ static struct parisc_device_id mux_tbl[]
 MODULE_DEVICE_TABLE(parisc, mux_tbl);
=20
 static struct parisc_driver mux_driver =3D {
-	.name     =3D "Serial MUX driver",
+	.name     =3D "Serial MUX",
 	.id_table =3D mux_tbl,
 	.probe    =3D mux_probe,
 };
@@ -483,16 +521,19 @@ static int __init mux_init(void)
 static void __exit mux_exit(void)
 {
 	int i;
+	struct mux_card *card =3D &mux_card_head;
=20
-	for (i =3D 0; i < MUX_NR; i++) {
-		uart_remove_one_port(&mux_reg, &mux_ports[i]);
+	for (i =3D 0; i < UART_NR; i++) {
+		uart_remove_one_port(&card->drv, &card->ports[i]);
 	}
=20
-	uart_unregister_driver(&mux_reg);
+	uart_unregister_driver(&card->drv);
 }
=20
 module_init(mux_init);
 module_exit(mux_exit);
+
+EXPORT_NO_SYMBOLS;
=20
 MODULE_AUTHOR("Ryan Bradetich");
 MODULE_DESCRIPTION("Serial MUX driver");

--=-J3pV26VNbQ8S2RTpx/ME--