[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--