Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/drivers/serial/jsm/Makefile b/drivers/serial/jsm/Makefile
new file mode 100644
index 0000000..e46b6e0
--- /dev/null
+++ b/drivers/serial/jsm/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Jasmine adapter
+#
+
+obj-$(CONFIG_SERIAL_JSM) += jsm.o
+
+jsm-objs :=    jsm_driver.o jsm_neo.o jsm_tty.o
+
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
new file mode 100644
index 0000000..b12ee02
--- /dev/null
+++ b/drivers/serial/jsm/jsm.h
@@ -0,0 +1,437 @@
+/************************************************************************
+ * Copyright 2003 Digi International (www.digi.com)
+ *
+ * Copyright (C) 2004 IBM Corporation. All rights reserved.
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ *
+ * Contact Information:
+ * Scott H Kilau <Scott_Kilau@digi.com>
+ * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ *
+ ***********************************************************************/
+
+#ifndef __JSM_DRIVER_H
+#define __JSM_DRIVER_H
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/types.h>	/* To pick up the varions Linux types */
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+/*
+ * Debugging levels can be set using debug insmod variable
+ * They can also be compiled out completely.
+ */
+enum {
+	DBG_INIT	= 0x01,
+	DBG_BASIC	= 0x02,
+	DBG_CORE	= 0x04,
+	DBG_OPEN	= 0x08,
+	DBG_CLOSE	= 0x10,
+	DBG_READ	= 0x20,
+	DBG_WRITE	= 0x40,
+	DBG_IOCTL	= 0x80,
+	DBG_PROC	= 0x100,
+	DBG_PARAM	= 0x200,
+	DBG_PSCAN	= 0x400,
+	DBG_EVENT	= 0x800,
+	DBG_DRAIN	= 0x1000,
+	DBG_MSIGS	= 0x2000,
+	DBG_MGMT	= 0x4000,
+	DBG_INTR	= 0x8000,
+	DBG_CARR	= 0x10000,
+};
+
+#define jsm_printk(nlevel, klevel, pdev, fmt, args...)	\
+	if ((DBG_##nlevel & jsm_debug))			\
+	dev_printk(KERN_##klevel, pdev->dev, fmt, ## args)
+
+#define MAXPORTS	8
+#define MAX_STOPS_SENT	5
+
+/* Board type definitions */
+
+#define T_NEO		0000
+#define T_CLASSIC	0001
+#define T_PCIBUS	0400
+
+/* Board State Definitions */
+
+#define BD_RUNNING	0x0
+#define BD_REASON	0x7f
+#define BD_NOTFOUND	0x1
+#define BD_NOIOPORT	0x2
+#define BD_NOMEM	0x3
+#define BD_NOBIOS	0x4
+#define BD_NOFEP	0x5
+#define BD_FAILED	0x6
+#define BD_ALLOCATED	0x7
+#define BD_TRIBOOT	0x8
+#define BD_BADKME	0x80
+
+
+/* 4 extra for alignment play space */
+#define WRITEBUFLEN	((4096) + 4)
+#define MYFLIPLEN	N_TTY_BUF_SIZE
+
+#define JSM_VERSION	"jsm: 1.1-1-INKERNEL"
+#define JSM_PARTNUM	"40002438_A-INKERNEL"
+
+/*
+ * All the possible states the driver can be while being loaded.
+ */
+enum {
+	DRIVER_INITIALIZED = 0,
+	DRIVER_READY
+};
+
+/*
+ * All the possible states the board can be while booting up.
+ */
+enum {
+	BOARD_FAILED = 0,
+	BOARD_FOUND,
+	BOARD_READY
+};
+
+struct board_id {
+	u8 *name;
+	u32 maxports;
+};
+
+struct jsm_board;
+struct jsm_channel;
+
+/************************************************************************
+ * Per board operations structure					*
+ ************************************************************************/
+struct board_ops {
+	irqreturn_t (*intr) (int irq, void *voidbrd, struct pt_regs *regs);
+	void (*uart_init) (struct jsm_channel *ch);
+	void (*uart_off) (struct jsm_channel *ch);
+	void (*param) (struct jsm_channel *ch);
+	void (*assert_modem_signals) (struct jsm_channel *ch);
+	void (*flush_uart_write) (struct jsm_channel *ch);
+	void (*flush_uart_read) (struct jsm_channel *ch);
+	void (*disable_receiver) (struct jsm_channel *ch);
+	void (*enable_receiver) (struct jsm_channel *ch);
+	void (*send_break) (struct jsm_channel *ch);
+	void (*clear_break) (struct jsm_channel *ch, int);
+	void (*send_start_character) (struct jsm_channel *ch);
+	void (*send_stop_character) (struct jsm_channel *ch);
+	void (*copy_data_from_queue_to_uart) (struct jsm_channel *ch);
+	u32 (*get_uart_bytes_left) (struct jsm_channel *ch);
+	void (*send_immediate_char) (struct jsm_channel *ch, unsigned char);
+};
+
+
+/*
+ *	Per-board information
+ */
+struct jsm_board
+{
+	int		boardnum;	/* Board number: 0-32 */
+
+	int		type;		/* Type of board */
+	char		*name;		/* Product Name */
+	u8		rev;		/* PCI revision ID */
+	struct pci_dev	*pci_dev;
+	u32		maxports;	/* MAX ports this board can handle */
+
+	spinlock_t	bd_lock;	/* Used to protect board */
+
+	spinlock_t	bd_intr_lock;	/* Used to protect the poller tasklet and
+					 * the interrupt routine from each other.
+					 */
+
+	u32		state;		/* State of card. */
+	wait_queue_head_t state_wait;	/* Place to sleep on for state change */
+
+	u32		nasync;		/* Number of ports on card */
+
+	u32		irq;		/* Interrupt request number */
+	u64		intr_count;	/* Count of interrupts */
+
+	u64		membase;	/* Start of base memory of the card */
+	u64		membase_end;	/* End of base memory of the card */
+
+	u8	__iomem *re_map_membase;/* Remapped memory of the card */
+
+	u64		iobase;		/* Start of io base of the card */
+	u64		iobase_end;	/* End of io base of the card */
+
+	u32		bd_uart_offset;	/* Space between each UART */
+
+	struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */
+	char		*flipbuf;	/* Our flip buffer, alloced if board is found */
+
+	u16		dpatype;	/* The board "type", as defined by DPA */
+	u16		dpastatus;	/* The board "status", as defined by DPA */
+
+	u32		bd_dividend;	/* Board/UARTs specific dividend */
+
+	struct board_ops *bd_ops;
+
+	struct list_head jsm_board_entry;
+};
+
+/************************************************************************
+ * Device flag definitions for ch_flags.
+ ************************************************************************/
+#define CH_PRON		0x0001		/* Printer on string		*/
+#define CH_STOP		0x0002		/* Output is stopped		*/
+#define CH_STOPI	0x0004		/* Input is stopped		*/
+#define CH_CD		0x0008		/* Carrier is present		*/
+#define CH_FCAR		0x0010		/* Carrier forced on		*/
+#define CH_HANGUP	0x0020		/* Hangup received		*/
+
+#define CH_RECEIVER_OFF	0x0040		/* Receiver is off		*/
+#define CH_OPENING	0x0080		/* Port in fragile open state	*/
+#define CH_CLOSING	0x0100		/* Port in fragile close state	*/
+#define CH_FIFO_ENABLED 0x0200		/* Port has FIFOs enabled	*/
+#define CH_TX_FIFO_EMPTY 0x0400		/* TX Fifo is completely empty	*/
+#define CH_TX_FIFO_LWM	0x0800		/* TX Fifo is below Low Water	*/
+#define CH_BREAK_SENDING 0x1000		/* Break is being sent		*/
+#define CH_LOOPBACK 0x2000		/* Channel is in lookback mode	*/
+#define CH_FLIPBUF_IN_USE 0x4000	/* Channel's flipbuf is in use	*/
+#define CH_BAUD0	0x08000		/* Used for checking B0 transitions */
+
+/* Our Read/Error/Write queue sizes */
+#define RQUEUEMASK	0x1FFF		/* 8 K - 1 */
+#define EQUEUEMASK	0x1FFF		/* 8 K - 1 */
+#define WQUEUEMASK	0x0FFF		/* 4 K - 1 */
+#define RQUEUESIZE	(RQUEUEMASK + 1)
+#define EQUEUESIZE	RQUEUESIZE
+#define WQUEUESIZE	(WQUEUEMASK + 1)
+
+
+/************************************************************************
+ * Channel information structure.
+ ************************************************************************/
+struct jsm_channel {
+	struct uart_port uart_port;
+	struct jsm_board	*ch_bd;		/* Board structure pointer	*/
+
+	spinlock_t	ch_lock;	/* provide for serialization */
+	wait_queue_head_t ch_flags_wait;
+
+	u32		ch_portnum;	/* Port number, 0 offset.	*/
+	u32		ch_open_count;	/* open count			*/
+	u32		ch_flags;	/* Channel flags		*/
+
+	u64		ch_close_delay;	/* How long we should drop RTS/DTR for */
+
+	u64		ch_cpstime;	/* Time for CPS calculations	*/
+
+	tcflag_t	ch_c_iflag;	/* channel iflags		*/
+	tcflag_t	ch_c_cflag;	/* channel cflags		*/
+	tcflag_t	ch_c_oflag;	/* channel oflags		*/
+	tcflag_t	ch_c_lflag;	/* channel lflags		*/
+	u8		ch_stopc;	/* Stop character		*/
+	u8		ch_startc;	/* Start character		*/
+
+	u32		ch_old_baud;	/* Cache of the current baud */
+	u32		ch_custom_speed;/* Custom baud, if set */
+
+	u32		ch_wopen;	/* Waiting for open process cnt */
+
+	u8		ch_mostat;	/* FEP output modem status	*/
+	u8		ch_mistat;	/* FEP input modem status	*/
+
+	struct neo_uart_struct __iomem *ch_neo_uart;	/* Pointer to the "mapped" UART struct */
+	u8		ch_cached_lsr;	/* Cached value of the LSR register */
+
+	u8		*ch_rqueue;	/* Our read queue buffer - malloc'ed */
+	u16		ch_r_head;	/* Head location of the read queue */
+	u16		ch_r_tail;	/* Tail location of the read queue */
+
+	u8		*ch_equeue;	/* Our error queue buffer - malloc'ed */
+	u16		ch_e_head;	/* Head location of the error queue */
+	u16		ch_e_tail;	/* Tail location of the error queue */
+
+	u8		*ch_wqueue;	/* Our write queue buffer - malloc'ed */
+	u16		ch_w_head;	/* Head location of the write queue */
+	u16		ch_w_tail;	/* Tail location of the write queue */
+
+	u64		ch_rxcount;	/* total of data received so far */
+	u64		ch_txcount;	/* total of data transmitted so far */
+
+	u8		ch_r_tlevel;	/* Receive Trigger level */
+	u8		ch_t_tlevel;	/* Transmit Trigger level */
+
+	u8		ch_r_watermark;	/* Receive Watermark */
+
+
+	u32		ch_stops_sent;	/* How many times I have sent a stop character
+					 * to try to stop the other guy sending.
+					 */
+	u64		ch_err_parity;	/* Count of parity errors on channel */
+	u64		ch_err_frame;	/* Count of framing errors on channel */
+	u64		ch_err_break;	/* Count of breaks on channel */
+	u64		ch_err_overrun; /* Count of overruns on channel */
+
+	u64		ch_xon_sends;	/* Count of xons transmitted */
+	u64		ch_xoff_sends;	/* Count of xoffs transmitted */
+};
+
+
+/************************************************************************
+ * Per channel/port NEO UART structure					*
+ ************************************************************************
+ *		Base Structure Entries Usage Meanings to Host		*
+ *									*
+ *	W = read write		R = read only				*
+ *			U = Unused.					*
+ ************************************************************************/
+
+struct neo_uart_struct {
+	 u8 txrx;		/* WR	RHR/THR - Holding Reg */
+	 u8 ier;		/* WR	IER - Interrupt Enable Reg */
+	 u8 isr_fcr;		/* WR	ISR/FCR - Interrupt Status Reg/Fifo Control Reg */
+	 u8 lcr;		/* WR	LCR - Line Control Reg */
+	 u8 mcr;		/* WR	MCR - Modem Control Reg */
+	 u8 lsr;		/* WR	LSR - Line Status Reg */
+	 u8 msr;		/* WR	MSR - Modem Status Reg */
+	 u8 spr;		/* WR	SPR - Scratch Pad Reg */
+	 u8 fctr;		/* WR	FCTR - Feature Control Reg */
+	 u8 efr;		/* WR	EFR - Enhanced Function Reg */
+	 u8 tfifo;		/* WR	TXCNT/TXTRG - Transmit FIFO Reg */
+	 u8 rfifo;		/* WR	RXCNT/RXTRG - Recieve FIFO Reg */
+	 u8 xoffchar1;	/* WR	XOFF 1 - XOff Character 1 Reg */
+	 u8 xoffchar2;	/* WR	XOFF 2 - XOff Character 2 Reg */
+	 u8 xonchar1;	/* WR	XON 1 - Xon Character 1 Reg */
+	 u8 xonchar2;	/* WR	XON 2 - XOn Character 2 Reg */
+
+	 u8 reserved1[0x2ff - 0x200]; /* U	Reserved by Exar */
+	 u8 txrxburst[64];	/* RW	64 bytes of RX/TX FIFO Data */
+	 u8 reserved2[0x37f - 0x340]; /* U	Reserved by Exar */
+	 u8 rxburst_with_errors[64];	/* R	64 bytes of RX FIFO Data + LSR */
+};
+
+/* Where to read the extended interrupt register (32bits instead of 8bits) */
+#define	UART_17158_POLL_ADDR_OFFSET	0x80
+
+/*
+ * These are the redefinitions for the FCTR on the XR17C158, since
+ * Exar made them different than their earlier design. (XR16C854)
+ */
+
+/* These are only applicable when table D is selected */
+#define UART_17158_FCTR_RTS_NODELAY	0x00
+#define UART_17158_FCTR_RTS_4DELAY	0x01
+#define UART_17158_FCTR_RTS_6DELAY	0x02
+#define UART_17158_FCTR_RTS_8DELAY	0x03
+#define UART_17158_FCTR_RTS_12DELAY	0x12
+#define UART_17158_FCTR_RTS_16DELAY	0x05
+#define UART_17158_FCTR_RTS_20DELAY	0x13
+#define UART_17158_FCTR_RTS_24DELAY	0x06
+#define UART_17158_FCTR_RTS_28DELAY	0x14
+#define UART_17158_FCTR_RTS_32DELAY	0x07
+#define UART_17158_FCTR_RTS_36DELAY	0x16
+#define UART_17158_FCTR_RTS_40DELAY	0x08
+#define UART_17158_FCTR_RTS_44DELAY	0x09
+#define UART_17158_FCTR_RTS_48DELAY	0x10
+#define UART_17158_FCTR_RTS_52DELAY	0x11
+
+#define UART_17158_FCTR_RTS_IRDA	0x10
+#define UART_17158_FCTR_RS485		0x20
+#define UART_17158_FCTR_TRGA		0x00
+#define UART_17158_FCTR_TRGB		0x40
+#define UART_17158_FCTR_TRGC		0x80
+#define UART_17158_FCTR_TRGD		0xC0
+
+/* 17158 trigger table selects.. */
+#define UART_17158_FCTR_BIT6		0x40
+#define UART_17158_FCTR_BIT7		0x80
+
+/* 17158 TX/RX memmapped buffer offsets */
+#define UART_17158_RX_FIFOSIZE		64
+#define UART_17158_TX_FIFOSIZE		64
+
+/* 17158 Extended IIR's */
+#define UART_17158_IIR_RDI_TIMEOUT	0x0C	/* Receiver data TIMEOUT */
+#define UART_17158_IIR_XONXOFF		0x10	/* Received an XON/XOFF char */
+#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20	/* CTS/DSR or RTS/DTR state change */
+#define UART_17158_IIR_FIFO_ENABLED	0xC0	/* 16550 FIFOs are Enabled */
+
+/*
+ * These are the extended interrupts that get sent
+ * back to us from the UART's 32bit interrupt register
+ */
+#define UART_17158_RX_LINE_STATUS	0x1	/* RX Ready */
+#define UART_17158_RXRDY_TIMEOUT	0x2	/* RX Ready Timeout */
+#define UART_17158_TXRDY		0x3	/* TX Ready */
+#define UART_17158_MSR			0x4	/* Modem State Change */
+#define UART_17158_TX_AND_FIFO_CLR	0x40	/* Transmitter Holding Reg Empty */
+#define UART_17158_RX_FIFO_DATA_ERROR	0x80	/* UART detected an RX FIFO Data error */
+
+/*
+ * These are the EXTENDED definitions for the 17C158's Interrupt
+ * Enable Register.
+ */
+#define UART_17158_EFR_ECB	0x10	/* Enhanced control bit */
+#define UART_17158_EFR_IXON	0x2	/* Receiver compares Xon1/Xoff1 */
+#define UART_17158_EFR_IXOFF	0x8	/* Transmit Xon1/Xoff1 */
+#define UART_17158_EFR_RTSDTR	0x40	/* Auto RTS/DTR Flow Control Enable */
+#define UART_17158_EFR_CTSDSR	0x80	/* Auto CTS/DSR Flow COntrol Enable */
+
+#define UART_17158_XOFF_DETECT	0x1	/* Indicates whether chip saw an incoming XOFF char */
+#define UART_17158_XON_DETECT	0x2	/* Indicates whether chip saw an incoming XON char */
+
+#define UART_17158_IER_RSVD1	0x10	/* Reserved by Exar */
+#define UART_17158_IER_XOFF	0x20	/* Xoff Interrupt Enable */
+#define UART_17158_IER_RTSDTR	0x40	/* Output Interrupt Enable */
+#define UART_17158_IER_CTSDSR	0x80	/* Input Interrupt Enable */
+
+#define PCI_DEVICE_NEO_2DB9_PCI_NAME		"Neo 2 - DB9 Universal PCI"
+#define PCI_DEVICE_NEO_2DB9PRI_PCI_NAME		"Neo 2 - DB9 Universal PCI - Powered Ring Indicator"
+#define PCI_DEVICE_NEO_2RJ45_PCI_NAME		"Neo 2 - RJ45 Universal PCI"
+#define PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME	"Neo 2 - RJ45 Universal PCI - Powered Ring Indicator"
+
+/*
+ * Our Global Variables.
+ */
+extern struct	uart_driver jsm_uart_driver;
+extern struct	board_ops jsm_neo_ops;
+extern int	jsm_debug;
+extern int	jsm_rawreadok;
+
+extern int	jsm_driver_state;	/* The state of the driver	*/
+extern char	*jsm_driver_state_text[];/* Array of driver state text */
+
+extern spinlock_t jsm_board_head_lock;
+extern struct list_head jsm_board_head;
+
+/*************************************************************************
+ *
+ * Prototypes for non-static functions used in more than one module
+ *
+ *************************************************************************/
+int jsm_tty_write(struct uart_port *port);
+int jsm_tty_init(struct jsm_board *);
+int jsm_uart_port_init(struct jsm_board *);
+int jsm_remove_uart_port(struct jsm_board *);
+void jsm_input(struct jsm_channel *ch);
+void jsm_carrier(struct jsm_channel *ch);
+void jsm_check_queue_flow_control(struct jsm_channel *ch);
+
+void jsm_create_driver_sysfiles(struct device_driver *);
+void jsm_remove_driver_sysfiles(struct device_driver *);
+
+#endif
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
new file mode 100644
index 0000000..d4847d4
--- /dev/null
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -0,0 +1,404 @@
+/************************************************************************
+ * Copyright 2003 Digi International (www.digi.com)
+ *
+ * Copyright (C) 2004 IBM Corporation. All rights reserved.
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ *
+ * Contact Information:
+ * Scott H Kilau <Scott_Kilau@digi.com>
+ * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ *
+ ***********************************************************************/
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+
+#include "jsm.h"
+
+MODULE_AUTHOR("Digi International, http://www.digi.com");
+MODULE_DESCRIPTION("Driver for the Digi International Neo PCI based product line");
+MODULE_SUPPORTED_DEVICE("jsm");
+
+#define JSM_DRIVER_NAME "jsm"
+#define NR_PORTS	32
+#define JSM_MINOR_START	0
+
+struct uart_driver jsm_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= JSM_DRIVER_NAME,
+	.dev_name	= "ttyn",
+	.major		= 253,
+	.minor		= JSM_MINOR_START,
+	.nr		= NR_PORTS,
+	.cons		= NULL,
+};
+
+int jsm_debug;
+int jsm_rawreadok;
+module_param(jsm_debug, int, 0);
+module_param(jsm_rawreadok, int, 0);
+MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
+MODULE_PARM_DESC(jsm_rawreadok, "Bypass flip buffers on input");
+
+/*
+ * Globals
+ */
+int		jsm_driver_state = DRIVER_INITIALIZED;
+spinlock_t	jsm_board_head_lock = SPIN_LOCK_UNLOCKED;
+LIST_HEAD(jsm_board_head);
+
+static struct pci_device_id jsm_pci_tbl[] = {
+	{ PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9),	0,	0,	0 },
+	{ PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9PRI),	0,	0,	1 },
+	{ PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45),	0,	0,	2 },
+	{ PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI),	0,	0,	3 },
+	{ 0,}						/* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
+
+static struct board_id jsm_Ids[] = {
+	{ PCI_DEVICE_NEO_2DB9_PCI_NAME,		2 },
+	{ PCI_DEVICE_NEO_2DB9PRI_PCI_NAME,	2 },
+	{ PCI_DEVICE_NEO_2RJ45_PCI_NAME,	2 },
+	{ PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME,	2 },
+	{ NULL,					0 }
+};
+
+char *jsm_driver_state_text[] = {
+	"Driver Initialized",
+	"Driver Ready."
+};
+
+static int jsm_finalize_board_init(struct jsm_board *brd)
+{
+	int rc = 0;
+
+	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+
+	if (brd->irq) {
+		rc = request_irq(brd->irq, brd->bd_ops->intr, SA_INTERRUPT|SA_SHIRQ, "JSM", brd);
+
+		if (rc) {
+			printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq);
+			brd->state = BOARD_FAILED;
+			brd->dpastatus = BD_NOFEP;
+			rc = -ENODEV;
+		} else
+			jsm_printk(INIT, INFO, &brd->pci_dev,
+				"Requested and received usage of IRQ %d\n", brd->irq);
+	}
+	return rc;
+}
+
+/*
+ * jsm_found_board()
+ *
+ * A board has been found, init it.
+ */
+static int jsm_found_board(struct pci_dev *pdev, int id)
+{
+	struct jsm_board *brd;
+	int i = 0;
+	int rc = 0;
+	struct list_head *tmp;
+	struct jsm_board *cur_board_entry;
+	unsigned long lock_flags;
+	int adapter_count = 0;
+	int retval;
+
+	brd = kmalloc(sizeof(struct jsm_board), GFP_KERNEL);
+	if (!brd) {
+		dev_err(&pdev->dev, "memory allocation for board structure failed\n");
+		return -ENOMEM;
+	}
+	memset(brd, 0, sizeof(struct jsm_board));
+
+	spin_lock_irqsave(&jsm_board_head_lock, lock_flags);
+	list_for_each(tmp, &jsm_board_head) {
+		cur_board_entry =
+			list_entry(tmp, struct jsm_board,
+				jsm_board_entry);
+		if (cur_board_entry->boardnum != adapter_count) {
+			break;
+		}
+		adapter_count++;
+	}
+
+	list_add_tail(&brd->jsm_board_entry, &jsm_board_head);
+	spin_unlock_irqrestore(&jsm_board_head_lock, lock_flags);
+
+	/* store the info for the board we've found */
+	brd->boardnum = adapter_count;
+	brd->pci_dev = pdev;
+	brd->name = jsm_Ids[id].name;
+	brd->maxports = jsm_Ids[id].maxports;
+	brd->dpastatus = BD_NOFEP;
+	init_waitqueue_head(&brd->state_wait);
+
+	spin_lock_init(&brd->bd_lock);
+	spin_lock_init(&brd->bd_intr_lock);
+
+	brd->state = BOARD_FOUND;
+
+	for (i = 0; i < brd->maxports; i++)
+		brd->channels[i] = NULL;
+
+	/* store which revision we have */
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+
+	brd->irq = pdev->irq;
+
+	switch(brd->pci_dev->device) {
+
+	case PCI_DEVICE_ID_NEO_2DB9:
+	case PCI_DEVICE_ID_NEO_2DB9PRI:
+	case PCI_DEVICE_ID_NEO_2RJ45:
+	case PCI_DEVICE_ID_NEO_2RJ45PRI:
+
+		/*
+		 * This chip is set up 100% when we get to it.
+		 * No need to enable global interrupts or anything.
+		 */
+		brd->dpatype = T_NEO | T_PCIBUS;
+
+		jsm_printk(INIT, INFO, &brd->pci_dev,
+			"jsm_found_board - NEO adapter\n");
+
+		/* get the PCI Base Address Registers */
+		brd->membase	= pci_resource_start(pdev, 0);
+		brd->membase_end = pci_resource_end(pdev, 0);
+
+		if (brd->membase & 1)
+			brd->membase &= ~3;
+		else
+			brd->membase &= ~15;
+
+		/* Assign the board_ops struct */
+		brd->bd_ops = &jsm_neo_ops;
+
+		brd->bd_uart_offset = 0x200;
+		brd->bd_dividend = 921600;
+
+		brd->re_map_membase = ioremap(brd->membase, 0x1000);
+		jsm_printk(INIT, INFO, &brd->pci_dev,
+			"remapped mem: 0x%p\n", brd->re_map_membase);
+		if (!brd->re_map_membase) {
+			kfree(brd);
+			dev_err(&pdev->dev, "card has no PCI Memory resources, failing board.\n");
+			return -ENOMEM;
+		}
+		break;
+
+	default:
+		dev_err(&pdev->dev, "Did not find any compatible Neo or Classic PCI boards in system.\n");
+		kfree(brd);
+		return -ENXIO;
+	}
+
+	/*
+	 * Do tty device initialization.
+	 */
+	rc = jsm_finalize_board_init(brd);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "Can't finalize board init (%d)\n", rc);
+		brd->state = BOARD_FAILED;
+		retval = -ENXIO;
+		goto failed0;
+	}
+
+	rc = jsm_tty_init(brd);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "Can't init tty devices (%d)\n", rc);
+		brd->state = BOARD_FAILED;
+		retval = -ENXIO;
+		goto failed1;
+	}
+
+	rc = jsm_uart_port_init(brd);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "Can't init uart port (%d)\n", rc);
+		brd->state = BOARD_FAILED;
+		retval = -ENXIO;
+		goto failed1;
+	}
+
+	brd->state = BOARD_READY;
+	brd->dpastatus = BD_RUNNING;
+
+	/* Log the information about the board */
+	dev_info(&pdev->dev, "board %d: %s (rev %d), irq %d\n",adapter_count, brd->name, brd->rev, brd->irq);
+
+	/*
+	 * allocate flip buffer for board.
+	 *
+	 * Okay to malloc with GFP_KERNEL, we are not at interrupt
+	 * context, and there are no locks held.
+	 */
+	brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
+	if (!brd->flipbuf) {
+		dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
+		brd->state = BOARD_FAILED;
+		retval = -ENOMEM;
+		goto failed1;
+	}
+	memset(brd->flipbuf, 0, MYFLIPLEN);
+
+	jsm_create_driver_sysfiles(pdev->dev.driver);
+
+	wake_up_interruptible(&brd->state_wait);
+	return 0;
+failed1:
+	free_irq(brd->irq, brd);
+failed0:
+	kfree(brd);
+	iounmap(brd->re_map_membase);
+	return retval;
+}
+
+/* returns count (>= 0), or negative on error */
+static int jsm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int rc;
+
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		dev_err(&pdev->dev, "Device enable FAILED\n");
+		return rc;
+	}
+
+	if ((rc = pci_request_regions(pdev, "jsm"))) {
+	dev_err(&pdev->dev, "pci_request_region FAILED\n");
+		pci_disable_device(pdev);
+		return rc;
+	}
+
+	if ((rc = jsm_found_board(pdev, ent->driver_data))) {
+		dev_err(&pdev->dev, "jsm_found_board FAILED\n");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+	 	return rc;
+	}
+	return rc;
+}
+
+
+/*
+ * jsm_cleanup_board()
+ *
+ * Free all the memory associated with a board
+ */
+static void jsm_cleanup_board(struct jsm_board *brd)
+{
+	int i = 0;
+
+	free_irq(brd->irq, brd);
+	iounmap(brd->re_map_membase);
+
+	/* Free all allocated channels structs */
+	for (i = 0; i < brd->maxports; i++) {
+		if (brd->channels[i]) {
+			if (brd->channels[i]->ch_rqueue)
+				kfree(brd->channels[i]->ch_rqueue);
+			if (brd->channels[i]->ch_equeue)
+				kfree(brd->channels[i]->ch_equeue);
+			if (brd->channels[i]->ch_wqueue)
+				kfree(brd->channels[i]->ch_wqueue);
+			kfree(brd->channels[i]);
+		}
+	}
+
+	pci_release_regions(brd->pci_dev);
+	pci_disable_device(brd->pci_dev);
+	kfree(brd->flipbuf);
+	kfree(brd);
+}
+
+static void jsm_remove_one(struct pci_dev *dev)
+{
+	unsigned long lock_flags;
+	struct list_head *tmp;
+	struct jsm_board *brd;
+
+	spin_lock_irqsave(&jsm_board_head_lock, lock_flags);
+	list_for_each(tmp, &jsm_board_head) {
+		brd = list_entry(tmp, struct jsm_board,
+					jsm_board_entry);
+		if ( brd != NULL && brd->pci_dev == dev) {
+			jsm_remove_uart_port(brd);
+			jsm_cleanup_board(brd);
+			list_del(&brd->jsm_board_entry);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&jsm_board_head_lock, lock_flags);
+	return;
+}
+
+struct pci_driver jsm_driver = {
+	.name		= "jsm",
+	.probe		= jsm_init_one,
+	.id_table	= jsm_pci_tbl,
+	.remove		= __devexit_p(jsm_remove_one),
+};
+
+/*
+ * jsm_init_module()
+ *
+ * Module load.  This is where it all starts.
+ */
+static int __init jsm_init_module(void)
+{
+	int rc = 0;
+
+	printk(KERN_INFO "%s, Digi International Part Number %s\n",
+			JSM_VERSION, JSM_VERSION);
+
+	/*
+	 * Initialize global stuff
+	 */
+
+	rc = uart_register_driver(&jsm_uart_driver);
+	if (rc < 0) {
+		return rc;
+	}
+
+	rc = pci_register_driver(&jsm_driver);
+	if (rc < 0) {
+		uart_unregister_driver(&jsm_uart_driver);
+		return rc;
+	}
+	jsm_driver_state = DRIVER_READY;
+
+	return rc;
+}
+
+module_init(jsm_init_module);
+
+/*
+ * jsm_exit_module()
+ *
+ * Module unload.  This is where it all ends.
+ */
+static void __exit jsm_exit_module(void)
+{
+	jsm_remove_driver_sysfiles(&jsm_driver.driver);
+
+	pci_unregister_driver(&jsm_driver);
+
+	uart_unregister_driver(&jsm_uart_driver);
+}
+module_exit(jsm_exit_module);
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
new file mode 100644
index 0000000..9b79c1f
--- /dev/null
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -0,0 +1,1427 @@
+/************************************************************************
+ * Copyright 2003 Digi International (www.digi.com)
+ *
+ * Copyright (C) 2004 IBM Corporation. All rights reserved.
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ *
+ * Contact Information:
+ * Scott H Kilau <Scott_Kilau@digi.com>
+ * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ *
+ ***********************************************************************/
+#include <linux/delay.h>	/* For udelay */
+#include <linux/serial_reg.h>	/* For the various UART offsets */
+#include <linux/tty.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "jsm.h"		/* Driver main header file */
+
+static u32 jsm_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+/*
+ * This function allows calls to ensure that all outstanding
+ * PCI writes have been completed, by doing a PCI read against
+ * a non-destructive, read-only location on the Neo card.
+ *
+ * In this case, we are reading the DVID (Read-only Device Identification)
+ * value of the Neo card.
+ */
+static inline void neo_pci_posting_flush(struct jsm_board *bd)
+{
+      readb(bd->re_map_membase + 0x8D);
+}
+
+static void neo_set_cts_flow_control(struct jsm_channel *ch)
+{
+	u8 ier = readb(&ch->ch_neo_uart->ier);
+	u8 efr = readb(&ch->ch_neo_uart->efr);
+
+	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
+
+	/* Turn on auto CTS flow control */
+	ier |= (UART_17158_IER_CTSDSR);
+	efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR);
+
+	/* Turn off auto Xon flow control */
+	efr &= ~(UART_17158_EFR_IXON);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	/* Turn on table D, with 8 char hi/low watermarks */
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
+
+	/* Feed the UART our trigger levels */
+	writeb(8, &ch->ch_neo_uart->tfifo);
+	ch->ch_t_tlevel = 8;
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static void neo_set_rts_flow_control(struct jsm_channel *ch)
+{
+	u8 ier = readb(&ch->ch_neo_uart->ier);
+	u8 efr = readb(&ch->ch_neo_uart->efr);
+
+	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
+
+	/* Turn on auto RTS flow control */
+	ier |= (UART_17158_IER_RTSDTR);
+	efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR);
+
+	/* Turn off auto Xoff flow control */
+	ier &= ~(UART_17158_IER_XOFF);
+	efr &= ~(UART_17158_EFR_IXOFF);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
+	ch->ch_r_watermark = 4;
+
+	writeb(56, &ch->ch_neo_uart->rfifo);
+	ch->ch_r_tlevel = 56;
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+
+	/*
+	 * From the Neo UART spec sheet:
+	 * The auto RTS/DTR function must be started by asserting
+	 * RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after
+	 * it is enabled.
+	 */
+	ch->ch_mostat |= (UART_MCR_RTS);
+}
+
+
+static void neo_set_ixon_flow_control(struct jsm_channel *ch)
+{
+	u8 ier = readb(&ch->ch_neo_uart->ier);
+	u8 efr = readb(&ch->ch_neo_uart->efr);
+
+	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
+
+	/* Turn off auto CTS flow control */
+	ier &= ~(UART_17158_IER_CTSDSR);
+	efr &= ~(UART_17158_EFR_CTSDSR);
+
+	/* Turn on auto Xon flow control */
+	efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+	ch->ch_r_watermark = 4;
+
+	writeb(32, &ch->ch_neo_uart->rfifo);
+	ch->ch_r_tlevel = 32;
+
+	/* Tell UART what start/stop chars it should be looking for */
+	writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+	writeb(0, &ch->ch_neo_uart->xonchar2);
+
+	writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+	writeb(0, &ch->ch_neo_uart->xoffchar2);
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static void neo_set_ixoff_flow_control(struct jsm_channel *ch)
+{
+	u8 ier = readb(&ch->ch_neo_uart->ier);
+	u8 efr = readb(&ch->ch_neo_uart->efr);
+
+	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
+
+	/* Turn off auto RTS flow control */
+	ier &= ~(UART_17158_IER_RTSDTR);
+	efr &= ~(UART_17158_EFR_RTSDTR);
+
+	/* Turn on auto Xoff flow control */
+	ier |= (UART_17158_IER_XOFF);
+	efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	/* Turn on table D, with 8 char hi/low watermarks */
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+	writeb(8, &ch->ch_neo_uart->tfifo);
+	ch->ch_t_tlevel = 8;
+
+	/* Tell UART what start/stop chars it should be looking for */
+	writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+	writeb(0, &ch->ch_neo_uart->xonchar2);
+
+	writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+	writeb(0, &ch->ch_neo_uart->xoffchar2);
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static void neo_set_no_input_flow_control(struct jsm_channel *ch)
+{
+	u8 ier = readb(&ch->ch_neo_uart->ier);
+	u8 efr = readb(&ch->ch_neo_uart->efr);
+
+	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
+
+	/* Turn off auto RTS flow control */
+	ier &= ~(UART_17158_IER_RTSDTR);
+	efr &= ~(UART_17158_EFR_RTSDTR);
+
+	/* Turn off auto Xoff flow control */
+	ier &= ~(UART_17158_IER_XOFF);
+	if (ch->ch_c_iflag & IXON)
+		efr &= ~(UART_17158_EFR_IXOFF);
+	else
+		efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	/* Turn on table D, with 8 char hi/low watermarks */
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+	ch->ch_r_watermark = 0;
+
+	writeb(16, &ch->ch_neo_uart->tfifo);
+	ch->ch_t_tlevel = 16;
+
+	writeb(16, &ch->ch_neo_uart->rfifo);
+	ch->ch_r_tlevel = 16;
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static void neo_set_no_output_flow_control(struct jsm_channel *ch)
+{
+	u8 ier = readb(&ch->ch_neo_uart->ier);
+	u8 efr = readb(&ch->ch_neo_uart->efr);
+
+	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
+
+	/* Turn off auto CTS flow control */
+	ier &= ~(UART_17158_IER_CTSDSR);
+	efr &= ~(UART_17158_EFR_CTSDSR);
+
+	/* Turn off auto Xon flow control */
+	if (ch->ch_c_iflag & IXOFF)
+		efr &= ~(UART_17158_EFR_IXON);
+	else
+		efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON);
+
+	/* Why? Becuz Exar's spec says we have to zero it out before setting it */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Turn on UART enhanced bits */
+	writeb(efr, &ch->ch_neo_uart->efr);
+
+	/* Turn on table D, with 8 char hi/low watermarks */
+	writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+	ch->ch_r_watermark = 0;
+
+	writeb(16, &ch->ch_neo_uart->tfifo);
+	ch->ch_t_tlevel = 16;
+
+	writeb(16, &ch->ch_neo_uart->rfifo);
+	ch->ch_r_tlevel = 16;
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static inline void neo_set_new_start_stop_chars(struct jsm_channel *ch)
+{
+
+	/* if hardware flow control is set, then skip this whole thing */
+	if (ch->ch_c_cflag & CRTSCTS)
+		return;
+
+	jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "start\n");
+
+	/* Tell UART what start/stop chars it should be looking for */
+	writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+	writeb(0, &ch->ch_neo_uart->xonchar2);
+
+	writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+	writeb(0, &ch->ch_neo_uart->xoffchar2);
+}
+
+static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
+{
+	int qleft = 0;
+	u8 linestatus = 0;
+	u8 error_mask = 0;
+	int n = 0;
+	int total = 0;
+	u16 head;
+	u16 tail;
+
+	if (!ch)
+		return;
+
+	/* cache head and tail of queue */
+	head = ch->ch_r_head & RQUEUEMASK;
+	tail = ch->ch_r_tail & RQUEUEMASK;
+
+	/* Get our cached LSR */
+	linestatus = ch->ch_cached_lsr;
+	ch->ch_cached_lsr = 0;
+
+	/* Store how much space we have left in the queue */
+	if ((qleft = tail - head - 1) < 0)
+		qleft += RQUEUEMASK + 1;
+
+	/*
+	 * If the UART is not in FIFO mode, force the FIFO copy to
+	 * NOT be run, by setting total to 0.
+	 *
+	 * On the other hand, if the UART IS in FIFO mode, then ask
+	 * the UART to give us an approximation of data it has RX'ed.
+	 */
+	if (!(ch->ch_flags & CH_FIFO_ENABLED))
+		total = 0;
+	else {
+		total = readb(&ch->ch_neo_uart->rfifo);
+
+		/*
+		 * EXAR chip bug - RX FIFO COUNT - Fudge factor.
+		 *
+		 * This resolves a problem/bug with the Exar chip that sometimes
+		 * returns a bogus value in the rfifo register.
+		 * The count can be any where from 0-3 bytes "off".
+		 * Bizarre, but true.
+		 */
+		total -= 3;
+	}
+
+	/*
+	 * Finally, bound the copy to make sure we don't overflow
+	 * our own queue...
+	 * The byte by byte copy loop below this loop this will
+	 * deal with the queue overflow possibility.
+	 */
+	total = min(total, qleft);
+
+	while (total > 0) {
+		/*
+		 * Grab the linestatus register, we need to check
+		 * to see if there are any errors in the FIFO.
+		 */
+		linestatus = readb(&ch->ch_neo_uart->lsr);
+
+		/*
+		 * Break out if there is a FIFO error somewhere.
+		 * This will allow us to go byte by byte down below,
+		 * finding the exact location of the error.
+		 */
+		if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
+			break;
+
+		/* Make sure we don't go over the end of our queue */
+		n = min(((u32) total), (RQUEUESIZE - (u32) head));
+
+		/*
+		 * Cut down n even further if needed, this is to fix
+		 * a problem with memcpy_fromio() with the Neo on the
+		 * IBM pSeries platform.
+		 * 15 bytes max appears to be the magic number.
+		 */
+		n = min((u32) n, (u32) 12);
+
+		/*
+		 * Since we are grabbing the linestatus register, which
+		 * will reset some bits after our read, we need to ensure
+		 * we don't miss our TX FIFO emptys.
+		 */
+		if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR))
+			ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+
+		linestatus = 0;
+
+		/* Copy data from uart to the queue */
+		memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n);
+		/*
+		 * Since RX_FIFO_DATA_ERROR was 0, we are guarenteed
+		 * that all the data currently in the FIFO is free of
+		 * breaks and parity/frame/orun errors.
+		 */
+		memset(ch->ch_equeue + head, 0, n);
+
+		/* Add to and flip head if needed */
+		head = (head + n) & RQUEUEMASK;
+		total -= n;
+		qleft -= n;
+		ch->ch_rxcount += n;
+	}
+
+	/*
+	 * Create a mask to determine whether we should
+	 * insert the character (if any) into our queue.
+	 */
+	if (ch->ch_c_iflag & IGNBRK)
+		error_mask |= UART_LSR_BI;
+
+	/*
+	 * Now cleanup any leftover bytes still in the UART.
+	 * Also deal with any possible queue overflow here as well.
+	 */
+	while (1) {
+
+		/*
+		 * Its possible we have a linestatus from the loop above
+		 * this, so we "OR" on any extra bits.
+		 */
+		linestatus |= readb(&ch->ch_neo_uart->lsr);
+
+		/*
+		 * If the chip tells us there is no more data pending to
+		 * be read, we can then leave.
+		 * But before we do, cache the linestatus, just in case.
+		 */
+		if (!(linestatus & UART_LSR_DR)) {
+			ch->ch_cached_lsr = linestatus;
+			break;
+		}
+
+		/* No need to store this bit */
+		linestatus &= ~UART_LSR_DR;
+
+		/*
+		 * Since we are grabbing the linestatus register, which
+		 * will reset some bits after our read, we need to ensure
+		 * we don't miss our TX FIFO emptys.
+		 */
+		if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
+			linestatus &= ~(UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR);
+			ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		}
+
+		/*
+		 * Discard character if we are ignoring the error mask.
+		 */
+		if (linestatus & error_mask) {
+			u8 discard;
+			linestatus = 0;
+			memcpy_fromio(&discard, &ch->ch_neo_uart->txrxburst, 1);
+			continue;
+		}
+
+		/*
+		 * If our queue is full, we have no choice but to drop some data.
+		 * The assumption is that HWFLOW or SWFLOW should have stopped
+		 * things way way before we got to this point.
+		 *
+		 * I decided that I wanted to ditch the oldest data first,
+		 * I hope thats okay with everyone? Yes? Good.
+		 */
+		while (qleft < 1) {
+			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+				"Queue full, dropping DATA:%x LSR:%x\n",
+				ch->ch_rqueue[tail], ch->ch_equeue[tail]);
+
+			ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK;
+			ch->ch_err_overrun++;
+			qleft++;
+		}
+
+		memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1);
+		ch->ch_equeue[head] = (u8) linestatus;
+
+		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+				"DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]);
+
+		/* Ditch any remaining linestatus value. */
+		linestatus = 0;
+
+		/* Add to and flip head if needed */
+		head = (head + 1) & RQUEUEMASK;
+
+		qleft--;
+		ch->ch_rxcount++;
+	}
+
+	/*
+	 * Write new final heads to channel structure.
+	 */
+	ch->ch_r_head = head & RQUEUEMASK;
+	ch->ch_e_head = head & EQUEUEMASK;
+	jsm_input(ch);
+}
+
+static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
+{
+	u16 head;
+	u16 tail;
+	int n;
+	int s;
+	int qlen;
+	u32 len_written = 0;
+
+	if (!ch)
+		return;
+
+	/* No data to write to the UART */
+	if (ch->ch_w_tail == ch->ch_w_head)
+		return;
+
+	/* If port is "stopped", don't send any data to the UART */
+	if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING))
+		return;
+	/*
+	 * If FIFOs are disabled. Send data directly to txrx register
+	 */
+	if (!(ch->ch_flags & CH_FIFO_ENABLED)) {
+		u8 lsrbits = readb(&ch->ch_neo_uart->lsr);
+
+		ch->ch_cached_lsr |= lsrbits;
+		if (ch->ch_cached_lsr & UART_LSR_THRE) {
+			ch->ch_cached_lsr &= ~(UART_LSR_THRE);
+
+			writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx);
+			jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
+					"Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]);
+			ch->ch_w_tail++;
+			ch->ch_w_tail &= WQUEUEMASK;
+			ch->ch_txcount++;
+		}
+		return;
+	}
+
+	/*
+	 * We have to do it this way, because of the EXAR TXFIFO count bug.
+	 */
+	if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
+		return;
+
+	len_written = 0;
+	n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
+
+	/* cache head and tail of queue */
+	head = ch->ch_w_head & WQUEUEMASK;
+	tail = ch->ch_w_tail & WQUEUEMASK;
+	qlen = (head - tail) & WQUEUEMASK;
+
+	/* Find minimum of the FIFO space, versus queue length */
+	n = min(n, qlen);
+
+	while (n > 0) {
+
+		s = ((head >= tail) ? head : WQUEUESIZE) - tail;
+		s = min(s, n);
+
+		if (s <= 0)
+			break;
+
+		memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);
+		/* Add and flip queue if needed */
+		tail = (tail + s) & WQUEUEMASK;
+		n -= s;
+		ch->ch_txcount += s;
+		len_written += s;
+	}
+
+	/* Update the final tail */
+	ch->ch_w_tail = tail & WQUEUEMASK;
+
+	if (len_written >= ch->ch_t_tlevel)
+		ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+
+	if (!jsm_tty_write(&ch->uart_port))
+		uart_write_wakeup(&ch->uart_port);
+}
+
+static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
+{
+	u8 msignals = signals;
+
+	jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
+			"neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals);
+
+	if (!ch)
+		return;
+
+	/* Scrub off lower bits. They signify delta's, which I don't care about */
+	msignals &= 0xf0;
+
+	if (msignals & UART_MSR_DCD)
+		ch->ch_mistat |= UART_MSR_DCD;
+	else
+		ch->ch_mistat &= ~UART_MSR_DCD;
+
+	if (msignals & UART_MSR_DSR)
+		ch->ch_mistat |= UART_MSR_DSR;
+	else
+		ch->ch_mistat &= ~UART_MSR_DSR;
+
+	if (msignals & UART_MSR_RI)
+		ch->ch_mistat |= UART_MSR_RI;
+	else
+		ch->ch_mistat &= ~UART_MSR_RI;
+
+	if (msignals & UART_MSR_CTS)
+		ch->ch_mistat |= UART_MSR_CTS;
+	else
+		ch->ch_mistat &= ~UART_MSR_CTS;
+
+	jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
+			"Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
+		ch->ch_portnum,
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
+		!!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD));
+}
+
+/* Make the UART raise any of the output signals we want up */
+static void neo_assert_modem_signals(struct jsm_channel *ch)
+{
+	u8 out;
+
+	if (!ch)
+		return;
+
+	out = ch->ch_mostat;
+
+	writeb(out, &ch->ch_neo_uart->mcr);
+
+	/* flush write operation */
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+/*
+ * Flush the WRITE FIFO on the Neo.
+ *
+ * NOTE: Channel lock MUST be held before calling this function!
+ */
+static void neo_flush_uart_write(struct jsm_channel *ch)
+{
+	u8 tmp = 0;
+	int i = 0;
+
+	if (!ch)
+		return;
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
+
+	for (i = 0; i < 10; i++) {
+
+		/* Check to see if the UART feels it completely flushed the FIFO. */
+		tmp = readb(&ch->ch_neo_uart->isr_fcr);
+		if (tmp & 4) {
+			jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
+					"Still flushing TX UART... i: %d\n", i);
+			udelay(10);
+		}
+		else
+			break;
+	}
+
+	ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+}
+
+
+/*
+ * Flush the READ FIFO on the Neo.
+ *
+ * NOTE: Channel lock MUST be held before calling this function!
+ */
+static void neo_flush_uart_read(struct jsm_channel *ch)
+{
+	u8 tmp = 0;
+	int i = 0;
+
+	if (!ch)
+		return;
+
+	writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_neo_uart->isr_fcr);
+
+	for (i = 0; i < 10; i++) {
+
+		/* Check to see if the UART feels it completely flushed the FIFO. */
+		tmp = readb(&ch->ch_neo_uart->isr_fcr);
+		if (tmp & 2) {
+			jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
+					"Still flushing RX UART... i: %d\n", i);
+			udelay(10);
+		}
+		else
+			break;
+	}
+}
+
+/*
+ * No locks are assumed to be held when calling this function.
+ */
+void neo_clear_break(struct jsm_channel *ch, int force)
+{
+	unsigned long lock_flags;
+
+	spin_lock_irqsave(&ch->ch_lock, lock_flags);
+
+	/* Turn break off, and unset some variables */
+	if (ch->ch_flags & CH_BREAK_SENDING) {
+		u8 temp = readb(&ch->ch_neo_uart->lcr);
+		writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
+
+		ch->ch_flags &= ~(CH_BREAK_SENDING);
+		jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
+				"clear break Finishing UART_LCR_SBC! finished: %lx\n", jiffies);
+
+		/* flush write operation */
+		neo_pci_posting_flush(ch->ch_bd);
+	}
+	spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+}
+
+/*
+ * Parse the ISR register.
+ */
+static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
+{
+	struct jsm_channel *ch;
+	u8 isr;
+	u8 cause;
+	unsigned long lock_flags;
+
+	if (!brd)
+		return;
+
+	if (port > brd->maxports)
+		return;
+
+	ch = brd->channels[port];
+	if (!ch)
+		return;
+
+	/* Here we try to figure out what caused the interrupt to happen */
+	while (1) {
+
+		isr = readb(&ch->ch_neo_uart->isr_fcr);
+
+		/* Bail if no pending interrupt */
+		if (isr & UART_IIR_NO_INT)
+			break;
+
+		/*
+		 * Yank off the upper 2 bits, which just show that the FIFO's are enabled.
+		 */
+		isr &= ~(UART_17158_IIR_FIFO_ENABLED);
+
+		jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+				"%s:%d isr: %x\n", __FILE__, __LINE__, isr);
+
+		if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
+			/* Read data from uart -> queue */
+			neo_copy_data_from_uart_to_queue(ch);
+
+			/* Call our tty layer to enforce queue flow control if needed. */
+			spin_lock_irqsave(&ch->ch_lock, lock_flags);
+			jsm_check_queue_flow_control(ch);
+			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+		}
+
+		if (isr & UART_IIR_THRI) {
+			/* Transfer data (if any) from Write Queue -> UART. */
+			spin_lock_irqsave(&ch->ch_lock, lock_flags);
+			ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+			neo_copy_data_from_queue_to_uart(ch);
+		}
+
+		if (isr & UART_17158_IIR_XONXOFF) {
+			cause = readb(&ch->ch_neo_uart->xoffchar1);
+
+			jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+					"Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause);
+
+			/*
+			 * Since the UART detected either an XON or
+			 * XOFF match, we need to figure out which
+			 * one it was, so we can suspend or resume data flow.
+			 */
+			spin_lock_irqsave(&ch->ch_lock, lock_flags);
+			if (cause == UART_17158_XON_DETECT) {
+				/* Is output stopped right now, if so, resume it */
+				if (brd->channels[port]->ch_flags & CH_STOP) {
+					ch->ch_flags &= ~(CH_STOP);
+				}
+				jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+						"Port %d. XON detected in incoming data\n", port);
+			}
+			else if (cause == UART_17158_XOFF_DETECT) {
+				if (!(brd->channels[port]->ch_flags & CH_STOP)) {
+					ch->ch_flags |= CH_STOP;
+					jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+							"Setting CH_STOP\n");
+				}
+				jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+						"Port: %d. XOFF detected in incoming data\n", port);
+			}
+			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+		}
+
+		if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) {
+			/*
+			 * If we get here, this means the hardware is doing auto flow control.
+			 * Check to see whether RTS/DTR or CTS/DSR caused this interrupt.
+			 */
+			cause = readb(&ch->ch_neo_uart->mcr);
+
+			/* Which pin is doing auto flow? RTS or DTR? */
+			spin_lock_irqsave(&ch->ch_lock, lock_flags);
+			if ((cause & 0x4) == 0) {
+				if (cause & UART_MCR_RTS)
+					ch->ch_mostat |= UART_MCR_RTS;
+				else
+					ch->ch_mostat &= ~(UART_MCR_RTS);
+			} else {
+				if (cause & UART_MCR_DTR)
+					ch->ch_mostat |= UART_MCR_DTR;
+				else
+					ch->ch_mostat &= ~(UART_MCR_DTR);
+			}
+			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+		}
+
+		/* Parse any modem signal changes */
+		jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+				"MOD_STAT: sending to parse_modem_sigs\n");
+		neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
+	}
+}
+
+static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
+{
+	struct jsm_channel *ch;
+	int linestatus;
+	unsigned long lock_flags;
+
+	if (!brd)
+		return;
+
+	if (port > brd->maxports)
+		return;
+
+	ch = brd->channels[port];
+	if (!ch)
+		return;
+
+	linestatus = readb(&ch->ch_neo_uart->lsr);
+
+	jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+			"%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus);
+
+	ch->ch_cached_lsr |= linestatus;
+
+	if (ch->ch_cached_lsr & UART_LSR_DR) {
+		/* Read data from uart -> queue */
+		neo_copy_data_from_uart_to_queue(ch);
+		spin_lock_irqsave(&ch->ch_lock, lock_flags);
+		jsm_check_queue_flow_control(ch);
+		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+	}
+
+	/*
+	 * This is a special flag. It indicates that at least 1
+	 * RX error (parity, framing, or break) has happened.
+	 * Mark this in our struct, which will tell me that I have
+	 *to do the special RX+LSR read for this FIFO load.
+	 */
+	if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
+		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+			"%s:%d Port: %d Got an RX error, need to parse LSR\n",
+			__FILE__, __LINE__, port);
+
+	/*
+	 * The next 3 tests should *NOT* happen, as the above test
+	 * should encapsulate all 3... At least, thats what Exar says.
+	 */
+
+	if (linestatus & UART_LSR_PE) {
+		ch->ch_err_parity++;
+		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+			"%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port);
+	}
+
+	if (linestatus & UART_LSR_FE) {
+		ch->ch_err_frame++;
+		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+			"%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port);
+	}
+
+	if (linestatus & UART_LSR_BI) {
+		ch->ch_err_break++;
+		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+			"%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port);
+	}
+
+	if (linestatus & UART_LSR_OE) {
+		/*
+		 * Rx Oruns. Exar says that an orun will NOT corrupt
+		 * the FIFO. It will just replace the holding register
+		 * with this new data byte. So basically just ignore this.
+		 * Probably we should eventually have an orun stat in our driver...
+		 */
+		ch->ch_err_overrun++;
+		jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+			"%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port);
+	}
+
+	if (linestatus & UART_LSR_THRE) {
+		spin_lock_irqsave(&ch->ch_lock, lock_flags);
+		ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+		/* Transfer data (if any) from Write Queue -> UART. */
+		neo_copy_data_from_queue_to_uart(ch);
+	}
+	else if (linestatus & UART_17158_TX_AND_FIFO_CLR) {
+		spin_lock_irqsave(&ch->ch_lock, lock_flags);
+		ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+		/* Transfer data (if any) from Write Queue -> UART. */
+		neo_copy_data_from_queue_to_uart(ch);
+	}
+}
+
+/*
+ * neo_param()
+ * Send any/all changes to the line to the UART.
+ */
+static void neo_param(struct jsm_channel *ch)
+{
+	u8 lcr = 0;
+	u8 uart_lcr = 0;
+	u8 ier = 0;
+	u32 baud = 9600;
+	int quot = 0;
+	struct jsm_board *bd;
+
+	bd = ch->ch_bd;
+	if (!bd)
+		return;
+
+	/*
+	 * If baud rate is zero, flush queues, and set mval to drop DTR.
+	 */
+	if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+		ch->ch_r_head = ch->ch_r_tail = 0;
+		ch->ch_e_head = ch->ch_e_tail = 0;
+		ch->ch_w_head = ch->ch_w_tail = 0;
+
+		neo_flush_uart_write(ch);
+		neo_flush_uart_read(ch);
+
+		ch->ch_flags |= (CH_BAUD0);
+		ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
+		neo_assert_modem_signals(ch);
+		ch->ch_old_baud = 0;
+		return;
+
+	} else if (ch->ch_custom_speed) {
+			baud = ch->ch_custom_speed;
+			if (ch->ch_flags & CH_BAUD0)
+				ch->ch_flags &= ~(CH_BAUD0);
+		} else {
+			int iindex = 0;
+			int jindex = 0;
+
+			const u64 bauds[4][16] = {
+				{
+					0,	50,	75,	110,
+					134,	150,	200,	300,
+					600,	1200,	1800,	2400,
+					4800,	9600,	19200,	38400 },
+				{
+					0,	57600,	115200, 230400,
+					460800, 150,	200,	921600,
+					600,	1200,	1800,	2400,
+					4800,	9600,	19200,	38400 },
+				{
+					0,	57600,	76800, 115200,
+					131657, 153600, 230400, 460800,
+					921600, 1200,	1800,	2400,
+					4800,	9600,	19200,	38400 },
+				{
+					0,	57600,	115200, 230400,
+					460800, 150,	200,	921600,
+					600,	1200,	1800,	2400,
+					4800,	9600,	19200,	38400 }
+			};
+
+			baud = C_BAUD(ch->uart_port.info->tty) & 0xff;
+
+			if (ch->ch_c_cflag & CBAUDEX)
+				iindex = 1;
+
+			jindex = baud;
+
+			if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16))
+				baud = bauds[iindex][jindex];
+			else {
+				jsm_printk(IOCTL, DEBUG, &ch->ch_bd->pci_dev,
+					"baud indices were out of range (%d)(%d)",
+				iindex, jindex);
+				baud = 0;
+			}
+
+			if (baud == 0)
+				baud = 9600;
+
+			if (ch->ch_flags & CH_BAUD0)
+				ch->ch_flags &= ~(CH_BAUD0);
+		}
+
+	if (ch->ch_c_cflag & PARENB)
+		lcr |= UART_LCR_PARITY;
+
+	if (!(ch->ch_c_cflag & PARODD))
+		lcr |= UART_LCR_EPAR;
+
+	/*
+	 * Not all platforms support mark/space parity,
+	 * so this will hide behind an ifdef.
+	 */
+#ifdef CMSPAR
+	if (ch->ch_c_cflag & CMSPAR)
+		lcr |= UART_LCR_SPAR;
+#endif
+
+	if (ch->ch_c_cflag & CSTOPB)
+		lcr |= UART_LCR_STOP;
+
+	switch (ch->ch_c_cflag & CSIZE) {
+		case CS5:
+			lcr |= UART_LCR_WLEN5;
+			break;
+		case CS6:
+			lcr |= UART_LCR_WLEN6;
+			break;
+		case CS7:
+			lcr |= UART_LCR_WLEN7;
+			break;
+		case CS8:
+		default:
+			lcr |= UART_LCR_WLEN8;
+		break;
+	}
+
+	ier = readb(&ch->ch_neo_uart->ier);
+	uart_lcr = readb(&ch->ch_neo_uart->lcr);
+
+	if (baud == 0)
+		baud = 9600;
+
+	quot = ch->ch_bd->bd_dividend / baud;
+
+	if (quot != 0) {
+		ch->ch_old_baud = baud;
+		writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);
+		writeb((quot & 0xff), &ch->ch_neo_uart->txrx);
+		writeb((quot >> 8), &ch->ch_neo_uart->ier);
+		writeb(lcr, &ch->ch_neo_uart->lcr);
+	}
+
+	if (uart_lcr != lcr)
+		writeb(lcr, &ch->ch_neo_uart->lcr);
+
+	if (ch->ch_c_cflag & CREAD)
+		ier |= (UART_IER_RDI | UART_IER_RLSI);
+
+	ier |= (UART_IER_THRI | UART_IER_MSI);
+
+	writeb(ier, &ch->ch_neo_uart->ier);
+
+	/* Set new start/stop chars */
+	neo_set_new_start_stop_chars(ch);
+
+	if (ch->ch_c_cflag & CRTSCTS)
+		neo_set_cts_flow_control(ch);
+	else if (ch->ch_c_iflag & IXON) {
+		/* If start/stop is set to disable, then we should disable flow control */
+		if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))
+			neo_set_no_output_flow_control(ch);
+		else
+			neo_set_ixon_flow_control(ch);
+	}
+	else
+		neo_set_no_output_flow_control(ch);
+
+	if (ch->ch_c_cflag & CRTSCTS)
+		neo_set_rts_flow_control(ch);
+	else if (ch->ch_c_iflag & IXOFF) {
+		/* If start/stop is set to disable, then we should disable flow control */
+		if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))
+			neo_set_no_input_flow_control(ch);
+		else
+			neo_set_ixoff_flow_control(ch);
+	}
+	else
+		neo_set_no_input_flow_control(ch);
+	/*
+	 * Adjust the RX FIFO Trigger level if baud is less than 9600.
+	 * Not exactly elegant, but this is needed because of the Exar chip's
+	 * delay on firing off the RX FIFO interrupt on slower baud rates.
+	 */
+	if (baud < 9600) {
+		writeb(1, &ch->ch_neo_uart->rfifo);
+		ch->ch_r_tlevel = 1;
+	}
+
+	neo_assert_modem_signals(ch);
+
+	/* Get current status of the modem signals now */
+	neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
+	return;
+}
+
+/*
+ * jsm_neo_intr()
+ *
+ * Neo specific interrupt handler.
+ */
+static irqreturn_t neo_intr(int irq, void *voidbrd, struct pt_regs *regs)
+{
+	struct jsm_board *brd = (struct jsm_board *) voidbrd;
+	struct jsm_channel *ch;
+	int port = 0;
+	int type = 0;
+	int current_port;
+	u32 tmp;
+	u32 uart_poll;
+	unsigned long lock_flags;
+	unsigned long lock_flags2;
+	int outofloop_count = 0;
+
+	brd->intr_count++;
+
+	/* Lock out the slow poller from running on this board. */
+	spin_lock_irqsave(&brd->bd_intr_lock, lock_flags);
+
+	/*
+	 * Read in "extended" IRQ information from the 32bit Neo register.
+	 * Bits 0-7: What port triggered the interrupt.
+	 * Bits 8-31: Each 3bits indicate what type of interrupt occurred.
+	 */
+	uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
+
+	jsm_printk(INTR, INFO, &brd->pci_dev,
+		"%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll);
+
+	if (!uart_poll) {
+		jsm_printk(INTR, INFO, &brd->pci_dev,
+			"Kernel interrupted to me, but no pending interrupts...\n");
+		spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
+		return IRQ_NONE;
+	}
+
+	/* At this point, we have at least SOMETHING to service, dig further... */
+
+	current_port = 0;
+
+	/* Loop on each port */
+	while (((uart_poll & 0xff) != 0) && (outofloop_count < 0xff)){
+
+		tmp = uart_poll;
+		outofloop_count++;
+
+		/* Check current port to see if it has interrupt pending */
+		if ((tmp & jsm_offset_table[current_port]) != 0) {
+			port = current_port;
+			type = tmp >> (8 + (port * 3));
+			type &= 0x7;
+		} else {
+			current_port++;
+			continue;
+		}
+
+		jsm_printk(INTR, INFO, &brd->pci_dev,
+		"%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type);
+
+		/* Remove this port + type from uart_poll */
+		uart_poll &= ~(jsm_offset_table[port]);
+
+		if (!type) {
+			/* If no type, just ignore it, and move onto next port */
+			jsm_printk(INTR, ERR, &brd->pci_dev,
+				"Interrupt with no type! port: %d\n", port);
+			continue;
+		}
+
+		/* Switch on type of interrupt we have */
+		switch (type) {
+
+		case UART_17158_RXRDY_TIMEOUT:
+			/*
+			 * RXRDY Time-out is cleared by reading data in the
+			* RX FIFO until it falls below the trigger level.
+			 */
+
+			/* Verify the port is in range. */
+			if (port > brd->nasync)
+				continue;
+
+			ch = brd->channels[port];
+			neo_copy_data_from_uart_to_queue(ch);
+
+			/* Call our tty layer to enforce queue flow control if needed. */
+			spin_lock_irqsave(&ch->ch_lock, lock_flags2);
+			jsm_check_queue_flow_control(ch);
+			spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
+
+			continue;
+
+		case UART_17158_RX_LINE_STATUS:
+			/*
+			 * RXRDY and RX LINE Status (logic OR of LSR[4:1])
+			 */
+			neo_parse_lsr(brd, port);
+			continue;
+
+		case UART_17158_TXRDY:
+			/*
+			 * TXRDY interrupt clears after reading ISR register for the UART channel.
+			 */
+
+			/*
+			 * Yes, this is odd...
+			 * Why would I check EVERY possibility of type of
+			 * interrupt, when we know its TXRDY???
+			 * Becuz for some reason, even tho we got triggered for TXRDY,
+			 * it seems to be occassionally wrong. Instead of TX, which
+			 * it should be, I was getting things like RXDY too. Weird.
+			 */
+			neo_parse_isr(brd, port);
+			continue;
+
+		case UART_17158_MSR:
+			/*
+			 * MSR or flow control was seen.
+			 */
+			neo_parse_isr(brd, port);
+			continue;
+
+		default:
+			/*
+			 * The UART triggered us with a bogus interrupt type.
+			 * It appears the Exar chip, when REALLY bogged down, will throw
+			 * these once and awhile.
+			 * Its harmless, just ignore it and move on.
+			 */
+			jsm_printk(INTR, ERR, &brd->pci_dev,
+				"%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type);
+			continue;
+		}
+	}
+
+	spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
+
+	jsm_printk(INTR, INFO, &brd->pci_dev, "finish.\n");
+	return IRQ_HANDLED;
+}
+
+/*
+ * Neo specific way of turning off the receiver.
+ * Used as a way to enforce queue flow control when in
+ * hardware flow control mode.
+ */
+static void neo_disable_receiver(struct jsm_channel *ch)
+{
+	u8 tmp = readb(&ch->ch_neo_uart->ier);
+	tmp &= ~(UART_IER_RDI);
+	writeb(tmp, &ch->ch_neo_uart->ier);
+
+	/* flush write operation */
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+/*
+ * Neo specific way of turning on the receiver.
+ * Used as a way to un-enforce queue flow control when in
+ * hardware flow control mode.
+ */
+static void neo_enable_receiver(struct jsm_channel *ch)
+{
+	u8 tmp = readb(&ch->ch_neo_uart->ier);
+	tmp |= (UART_IER_RDI);
+	writeb(tmp, &ch->ch_neo_uart->ier);
+
+	/* flush write operation */
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+static void neo_send_start_character(struct jsm_channel *ch)
+{
+	if (!ch)
+		return;
+
+	if (ch->ch_startc != __DISABLED_CHAR) {
+		ch->ch_xon_sends++;
+		writeb(ch->ch_startc, &ch->ch_neo_uart->txrx);
+
+		/* flush write operation */
+		neo_pci_posting_flush(ch->ch_bd);
+	}
+}
+
+static void neo_send_stop_character(struct jsm_channel *ch)
+{
+	if (!ch)
+		return;
+
+	if (ch->ch_stopc != __DISABLED_CHAR) {
+		ch->ch_xoff_sends++;
+		writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx);
+
+		/* flush write operation */
+		neo_pci_posting_flush(ch->ch_bd);
+	}
+}
+
+/*
+ * neo_uart_init
+ */
+static void neo_uart_init(struct jsm_channel *ch)
+{
+	writeb(0, &ch->ch_neo_uart->ier);
+	writeb(0, &ch->ch_neo_uart->efr);
+	writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr);
+
+	/* Clear out UART and FIFO */
+	readb(&ch->ch_neo_uart->txrx);
+	writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
+	readb(&ch->ch_neo_uart->lsr);
+	readb(&ch->ch_neo_uart->msr);
+
+	ch->ch_flags |= CH_FIFO_ENABLED;
+
+	/* Assert any signals we want up */
+	writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);
+}
+
+/*
+ * Make the UART completely turn off.
+ */
+static void neo_uart_off(struct jsm_channel *ch)
+{
+	/* Turn off UART enhanced bits */
+	writeb(0, &ch->ch_neo_uart->efr);
+
+	/* Stop all interrupts from occurring. */
+	writeb(0, &ch->ch_neo_uart->ier);
+}
+
+static u32 neo_get_uart_bytes_left(struct jsm_channel *ch)
+{
+	u8 left = 0;
+	u8 lsr = readb(&ch->ch_neo_uart->lsr);
+
+	/* We must cache the LSR as some of the bits get reset once read... */
+	ch->ch_cached_lsr |= lsr;
+
+	/* Determine whether the Transmitter is empty or not */
+	if (!(lsr & UART_LSR_TEMT))
+		left = 1;
+	else {
+		ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+		left = 0;
+	}
+
+	return left;
+}
+
+/* Channel lock MUST be held by the calling function! */
+static void neo_send_break(struct jsm_channel *ch)
+{
+	/*
+	 * Set the time we should stop sending the break.
+	 * If we are already sending a break, toss away the existing
+	 * time to stop, and use this new value instead.
+	 */
+
+	/* Tell the UART to start sending the break */
+	if (!(ch->ch_flags & CH_BREAK_SENDING)) {
+		u8 temp = readb(&ch->ch_neo_uart->lcr);
+		writeb((temp | UART_LCR_SBC), &ch->ch_neo_uart->lcr);
+		ch->ch_flags |= (CH_BREAK_SENDING);
+
+		/* flush write operation */
+		neo_pci_posting_flush(ch->ch_bd);
+	}
+}
+
+/*
+ * neo_send_immediate_char.
+ *
+ * Sends a specific character as soon as possible to the UART,
+ * jumping over any bytes that might be in the write queue.
+ *
+ * The channel lock MUST be held by the calling function.
+ */
+static void neo_send_immediate_char(struct jsm_channel *ch, unsigned char c)
+{
+	if (!ch)
+		return;
+
+	writeb(c, &ch->ch_neo_uart->txrx);
+
+	/* flush write operation */
+	neo_pci_posting_flush(ch->ch_bd);
+}
+
+struct board_ops jsm_neo_ops = {
+	.intr				= neo_intr,
+	.uart_init			= neo_uart_init,
+	.uart_off			= neo_uart_off,
+	.param				= neo_param,
+	.assert_modem_signals		= neo_assert_modem_signals,
+	.flush_uart_write		= neo_flush_uart_write,
+	.flush_uart_read		= neo_flush_uart_read,
+	.disable_receiver		= neo_disable_receiver,
+	.enable_receiver		= neo_enable_receiver,
+	.send_break			= neo_send_break,
+	.clear_break			= neo_clear_break,
+	.send_start_character		= neo_send_start_character,
+	.send_stop_character		= neo_send_stop_character,
+	.copy_data_from_queue_to_uart	= neo_copy_data_from_queue_to_uart,
+	.get_uart_bytes_left		= neo_get_uart_bytes_left,
+	.send_immediate_char		= neo_send_immediate_char
+};
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
new file mode 100644
index 0000000..7fb7cc0
--- /dev/null
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -0,0 +1,1038 @@
+/************************************************************************
+ * Copyright 2003 Digi International (www.digi.com)
+ *
+ * Copyright (C) 2004 IBM Corporation. All rights reserved.
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ *
+ * Contact Information:
+ * Scott H Kilau <Scott_Kilau@digi.com>
+ * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ *
+ ***********************************************************************/
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h>	/* For udelay */
+#include <linux/pci.h>
+
+#include "jsm.h"
+
+static inline int jsm_get_mstat(struct jsm_channel *ch)
+{
+	unsigned char mstat;
+	unsigned result;
+
+	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "start\n");
+
+	mstat = (ch->ch_mostat | ch->ch_mistat);
+
+	result = 0;
+
+	if (mstat & UART_MCR_DTR)
+		result |= TIOCM_DTR;
+	if (mstat & UART_MCR_RTS)
+		result |= TIOCM_RTS;
+	if (mstat & UART_MSR_CTS)
+		result |= TIOCM_CTS;
+	if (mstat & UART_MSR_DSR)
+		result |= TIOCM_DSR;
+	if (mstat & UART_MSR_RI)
+		result |= TIOCM_RI;
+	if (mstat & UART_MSR_DCD)
+		result |= TIOCM_CD;
+
+	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
+	return result;
+}
+
+static unsigned int jsm_tty_tx_empty(struct uart_port *port)
+{
+	return TIOCSER_TEMT;
+}
+
+/*
+ * Return modem signals to ld.
+ */
+static unsigned int jsm_tty_get_mctrl(struct uart_port *port)
+{
+	int result;
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+	result = jsm_get_mstat(channel);
+
+	if (result < 0)
+		return -ENXIO;
+
+	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+
+	return result;
+}
+
+/*
+ * jsm_set_modem_info()
+ *
+ * Set modem signals, called by ld.
+ */
+static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+	if (mctrl & TIOCM_RTS)
+		channel->ch_mostat |= UART_MCR_RTS;
+	else
+		channel->ch_mostat &= ~UART_MCR_RTS;
+
+	if (mctrl & TIOCM_DTR)
+		channel->ch_mostat |= UART_MCR_DTR;
+	else
+		channel->ch_mostat &= ~UART_MCR_DTR;
+
+	channel->ch_bd->bd_ops->assert_modem_signals(channel);
+
+	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+	udelay(10);
+}
+
+static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+	channel->ch_flags &= ~(CH_STOP);
+	jsm_tty_write(port);
+
+	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+}
+
+static void jsm_tty_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+	channel->ch_flags |= (CH_STOP);
+
+	jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+}
+
+static void jsm_tty_send_xchar(struct uart_port *port, char ch)
+{
+	unsigned long lock_flags;
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	spin_lock_irqsave(&port->lock, lock_flags);
+	if (ch == port->info->tty->termios->c_cc[VSTART])
+		channel->ch_bd->bd_ops->send_start_character(channel);
+
+	if (ch == port->info->tty->termios->c_cc[VSTOP])
+		channel->ch_bd->bd_ops->send_stop_character(channel);
+	spin_unlock_irqrestore(&port->lock, lock_flags);
+}
+
+static void jsm_tty_stop_rx(struct uart_port *port)
+{
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	channel->ch_bd->bd_ops->disable_receiver(channel);
+}
+
+static void jsm_tty_break(struct uart_port *port, int break_state)
+{
+	unsigned long lock_flags;
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	spin_lock_irqsave(&port->lock, lock_flags);
+	if (break_state == -1)
+		channel->ch_bd->bd_ops->send_break(channel);
+	else
+		channel->ch_bd->bd_ops->clear_break(channel, 0);
+
+	spin_unlock_irqrestore(&port->lock, lock_flags);
+}
+
+static int jsm_tty_open(struct uart_port *port)
+{
+	struct jsm_board *brd;
+	int rc = 0;
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	/* Get board pointer from our array of majors we have allocated */
+	brd = channel->ch_bd;
+
+	/*
+	 * Allocate channel buffers for read/write/error.
+	 * Set flag, so we don't get trounced on.
+	 */
+	channel->ch_flags |= (CH_OPENING);
+
+	/* Drop locks, as malloc with GFP_KERNEL can sleep */
+
+	if (!channel->ch_rqueue) {
+		channel->ch_rqueue = (u8 *) kmalloc(RQUEUESIZE, GFP_KERNEL);
+		if (!channel->ch_rqueue) {
+			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
+				"unable to allocate read queue buf");
+			return -ENOMEM;
+		}
+		memset(channel->ch_rqueue, 0, RQUEUESIZE);
+	}
+	if (!channel->ch_equeue) {
+		channel->ch_equeue = (u8 *) kmalloc(EQUEUESIZE, GFP_KERNEL);
+		if (!channel->ch_equeue) {
+			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
+				"unable to allocate error queue buf");
+			return -ENOMEM;
+		}
+		memset(channel->ch_equeue, 0, EQUEUESIZE);
+	}
+	if (!channel->ch_wqueue) {
+		channel->ch_wqueue = (u8 *) kmalloc(WQUEUESIZE, GFP_KERNEL);
+		if (!channel->ch_wqueue) {
+			jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
+				"unable to allocate write queue buf");
+			return -ENOMEM;
+		}
+		memset(channel->ch_wqueue, 0, WQUEUESIZE);
+	}
+
+	channel->ch_flags &= ~(CH_OPENING);
+	/*
+	 * Initialize if neither terminal is open.
+	 */
+	jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev,
+		"jsm_open: initializing channel in open...\n");
+
+	/*
+	 * Flush input queues.
+	 */
+	channel->ch_r_head = channel->ch_r_tail = 0;
+	channel->ch_e_head = channel->ch_e_tail = 0;
+	channel->ch_w_head = channel->ch_w_tail = 0;
+
+	brd->bd_ops->flush_uart_write(channel);
+	brd->bd_ops->flush_uart_read(channel);
+
+	channel->ch_flags = 0;
+	channel->ch_cached_lsr = 0;
+	channel->ch_stops_sent = 0;
+
+	channel->ch_c_cflag	= port->info->tty->termios->c_cflag;
+	channel->ch_c_iflag	= port->info->tty->termios->c_iflag;
+	channel->ch_c_oflag	= port->info->tty->termios->c_oflag;
+	channel->ch_c_lflag	= port->info->tty->termios->c_lflag;
+	channel->ch_startc = port->info->tty->termios->c_cc[VSTART];
+	channel->ch_stopc = port->info->tty->termios->c_cc[VSTOP];
+
+	/* Tell UART to init itself */
+	brd->bd_ops->uart_init(channel);
+
+	/*
+	 * Run param in case we changed anything
+	 */
+	brd->bd_ops->param(channel);
+
+	jsm_carrier(channel);
+
+	channel->ch_open_count++;
+
+	jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev, "finish\n");
+	return rc;
+}
+
+static void jsm_tty_close(struct uart_port *port)
+{
+	struct jsm_board *bd;
+	struct termios *ts;
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+	bd = channel->ch_bd;
+	ts = channel->uart_port.info->tty->termios;
+
+	channel->ch_flags &= ~(CH_STOPI);
+
+	channel->ch_open_count--;
+
+	/*
+	 * If we have HUPCL set, lower DTR and RTS
+	 */
+	if (channel->ch_c_cflag & HUPCL) {
+		jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev,
+			"Close. HUPCL set, dropping DTR/RTS\n");
+
+		/* Drop RTS/DTR */
+		channel->ch_mostat &= ~(UART_MCR_DTR | UART_MCR_RTS);
+		bd->bd_ops->assert_modem_signals(channel);
+	}
+
+	channel->ch_old_baud = 0;
+
+	/* Turn off UART interrupts for this port */
+	channel->ch_bd->bd_ops->uart_off(channel);
+
+	jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "finish\n");
+}
+
+static void jsm_tty_set_termios(struct uart_port *port,
+				 struct termios *termios,
+				 struct termios *old_termios)
+{
+	unsigned long lock_flags;
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	spin_lock_irqsave(&port->lock, lock_flags);
+	channel->ch_c_cflag	= termios->c_cflag;
+	channel->ch_c_iflag	= termios->c_iflag;
+	channel->ch_c_oflag	= termios->c_oflag;
+	channel->ch_c_lflag	= termios->c_lflag;
+	channel->ch_startc	= termios->c_cc[VSTART];
+	channel->ch_stopc	= termios->c_cc[VSTOP];
+
+	channel->ch_bd->bd_ops->param(channel);
+	jsm_carrier(channel);
+	spin_unlock_irqrestore(&port->lock, lock_flags);
+}
+
+static const char *jsm_tty_type(struct uart_port *port)
+{
+	return "jsm";
+}
+
+static void jsm_tty_release_port(struct uart_port *port)
+{
+}
+
+static int jsm_tty_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void jsm_config_port(struct uart_port *port, int flags)
+{
+	port->type = PORT_JSM;
+}
+
+static struct uart_ops jsm_ops = {
+	.tx_empty	= jsm_tty_tx_empty,
+	.set_mctrl	= jsm_tty_set_mctrl,
+	.get_mctrl	= jsm_tty_get_mctrl,
+	.stop_tx	= jsm_tty_stop_tx,
+	.start_tx	= jsm_tty_start_tx,
+	.send_xchar	= jsm_tty_send_xchar,
+	.stop_rx	= jsm_tty_stop_rx,
+	.break_ctl	= jsm_tty_break,
+	.startup	= jsm_tty_open,
+	.shutdown	= jsm_tty_close,
+	.set_termios	= jsm_tty_set_termios,
+	.type		= jsm_tty_type,
+	.release_port	= jsm_tty_release_port,
+	.request_port	= jsm_tty_request_port,
+	.config_port	= jsm_config_port,
+};
+
+/*
+ * jsm_tty_init()
+ *
+ * Init the tty subsystem.  Called once per board after board has been
+ * downloaded and init'ed.
+ */
+int jsm_tty_init(struct jsm_board *brd)
+{
+	int i;
+	void __iomem *vaddr;
+	struct jsm_channel *ch;
+
+	if (!brd)
+		return -ENXIO;
+
+	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+
+	/*
+	 * Initialize board structure elements.
+	 */
+
+	brd->nasync = brd->maxports;
+
+	/*
+	 * Allocate channel memory that might not have been allocated
+	 * when the driver was first loaded.
+	 */
+	for (i = 0; i < brd->nasync; i++) {
+		if (!brd->channels[i]) {
+
+			/*
+			 * Okay to malloc with GFP_KERNEL, we are not at
+			 * interrupt context, and there are no locks held.
+			 */
+			brd->channels[i] = kmalloc(sizeof(struct jsm_channel), GFP_KERNEL);
+			if (!brd->channels[i]) {
+				jsm_printk(CORE, ERR, &brd->pci_dev,
+					"%s:%d Unable to allocate memory for channel struct\n",
+							 __FILE__, __LINE__);
+			}
+			memset(brd->channels[i], 0, sizeof(struct jsm_channel));
+		}
+	}
+
+	ch = brd->channels[0];
+	vaddr = brd->re_map_membase;
+
+	/* Set up channel variables */
+	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
+		if (!brd->channels[i])
+			continue;
+
+		spin_lock_init(&ch->ch_lock);
+
+		if (brd->bd_uart_offset == 0x200)
+			ch->ch_neo_uart =  vaddr + (brd->bd_uart_offset * i);
+
+		ch->ch_bd = brd;
+		ch->ch_portnum = i;
+
+		/* .25 second delay */
+		ch->ch_close_delay = 250;
+
+		init_waitqueue_head(&ch->ch_flags_wait);
+	}
+
+	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+	return 0;
+}
+
+int jsm_uart_port_init(struct jsm_board *brd)
+{
+	int i;
+	struct jsm_channel *ch;
+
+	if (!brd)
+		return -ENXIO;
+
+	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+
+	/*
+	 * Initialize board structure elements.
+	 */
+
+	brd->nasync = brd->maxports;
+
+	/* Set up channel variables */
+	for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
+		if (!brd->channels[i])
+			continue;
+
+		brd->channels[i]->uart_port.irq = brd->irq;
+		brd->channels[i]->uart_port.type = PORT_JSM;
+		brd->channels[i]->uart_port.iotype = UPIO_MEM;
+		brd->channels[i]->uart_port.membase = brd->re_map_membase;
+		brd->channels[i]->uart_port.fifosize = 16;
+		brd->channels[i]->uart_port.ops = &jsm_ops;
+		brd->channels[i]->uart_port.line = brd->channels[i]->ch_portnum + brd->boardnum * 2;
+		if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port))
+			printk(KERN_INFO "Added device failed\n");
+		else
+			printk(KERN_INFO "Added device \n");
+	}
+
+	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+	return 0;
+}
+
+int jsm_remove_uart_port(struct jsm_board *brd)
+{
+	int i;
+	struct jsm_channel *ch;
+
+	if (!brd)
+		return -ENXIO;
+
+	jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+
+	/*
+	 * Initialize board structure elements.
+	 */
+
+	brd->nasync = brd->maxports;
+
+	/* Set up channel variables */
+	for (i = 0; i < brd->nasync; i++) {
+
+		if (!brd->channels[i])
+			continue;
+
+		ch = brd->channels[i];
+
+		uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port);
+	}
+
+	jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+	return 0;
+}
+
+void jsm_input(struct jsm_channel *ch)
+{
+	struct jsm_board *bd;
+	struct tty_struct *tp;
+	u32 rmask;
+	u16 head;
+	u16 tail;
+	int data_len;
+	unsigned long lock_flags;
+	int flip_len;
+	int len = 0;
+	int n = 0;
+	char *buf = NULL;
+	char *buf2 = NULL;
+	int s = 0;
+	int i = 0;
+
+	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
+
+	if (!ch)
+		return;
+
+	tp = ch->uart_port.info->tty;
+
+	bd = ch->ch_bd;
+	if(!bd)
+		return;
+
+	spin_lock_irqsave(&ch->ch_lock, lock_flags);
+
+	/*
+	 *Figure the number of characters in the buffer.
+	 *Exit immediately if none.
+	 */
+
+	rmask = RQUEUEMASK;
+
+	head = ch->ch_r_head & rmask;
+	tail = ch->ch_r_tail & rmask;
+
+	data_len = (head - tail) & rmask;
+	if (data_len == 0) {
+		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+		return;
+	}
+
+	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
+
+	/*
+	 *If the device is not open, or CREAD is off, flush
+	 *input data and return immediately.
+	 */
+	if (!tp ||
+		!(tp->termios->c_cflag & CREAD) ) {
+
+		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+			"input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
+		ch->ch_r_head = tail;
+
+		/* Force queue flow control to be released, if needed */
+		jsm_check_queue_flow_control(ch);
+
+		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+		return;
+	}
+
+	/*
+	 * If we are throttled, simply don't read any data.
+	 */
+	if (ch->ch_flags & CH_STOPI) {
+		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+			"Port %d throttled, not reading any data. head: %x tail: %x\n",
+			ch->ch_portnum, head, tail);
+		return;
+	}
+
+	jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start 2\n");
+
+	/*
+	 * If the rxbuf is empty and we are not throttled, put as much
+	 * as we can directly into the linux TTY flip buffer.
+	 * The jsm_rawreadok case takes advantage of carnal knowledge that
+	 * the char_buf and the flag_buf are next to each other and
+	 * are each of (2 * TTY_FLIPBUF_SIZE) size.
+	 *
+	 * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf
+	 *actually still uses the flag buffer, so you can't
+	 *use it for input data
+	 */
+	if (jsm_rawreadok) {
+		if (tp->real_raw)
+			flip_len = MYFLIPLEN;
+		else
+			flip_len = 2 * TTY_FLIPBUF_SIZE;
+	} else
+		flip_len = TTY_FLIPBUF_SIZE - tp->flip.count;
+
+	len = min(data_len, flip_len);
+	len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);
+
+	if (len <= 0) {
+		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
+		return;
+	}
+
+	/*
+	 * If we're bypassing flip buffers on rx, we can blast it
+	 * right into the beginning of the buffer.
+	 */
+	if (jsm_rawreadok) {
+		if (tp->real_raw) {
+			if (ch->ch_flags & CH_FLIPBUF_IN_USE) {
+				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+					"JSM - FLIPBUF in use. delaying input\n");
+				spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+				return;
+			}
+			ch->ch_flags |= CH_FLIPBUF_IN_USE;
+			buf = ch->ch_bd->flipbuf;
+			buf2 = NULL;
+		} else {
+			buf = tp->flip.char_buf;
+			buf2 = tp->flip.flag_buf;
+		}
+	} else {
+		buf = tp->flip.char_buf_ptr;
+		buf2 = tp->flip.flag_buf_ptr;
+	}
+
+	n = len;
+
+	/*
+	 * n now contains the most amount of data we can copy,
+	 * bounded either by the flip buffer size or the amount
+	 * of data the card actually has pending...
+	 */
+	while (n) {
+		s = ((head >= tail) ? head : RQUEUESIZE) - tail;
+		s = min(s, n);
+
+		if (s <= 0)
+			break;
+
+		memcpy(buf, ch->ch_rqueue + tail, s);
+
+		/* buf2 is only set when port isn't raw */
+		if (buf2)
+			memcpy(buf2, ch->ch_equeue + tail, s);
+
+		tail += s;
+		buf += s;
+		if (buf2)
+			buf2 += s;
+		n -= s;
+		/* Flip queue if needed */
+		tail &= rmask;
+	}
+
+	/*
+	 * In high performance mode, we don't have to update
+	 * flag_buf or any of the counts or pointers into flip buf.
+	 */
+	if (!jsm_rawreadok) {
+		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+			for (i = 0; i < len; i++) {
+				/*
+				 * Give the Linux ld the flags in the
+				 * format it likes.
+				 */
+				if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
+					tp->flip.flag_buf_ptr[i] = TTY_BREAK;
+				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
+					tp->flip.flag_buf_ptr[i] = TTY_PARITY;
+				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
+					tp->flip.flag_buf_ptr[i] = TTY_FRAME;
+				else
+					tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
+			}
+		} else {
+			memset(tp->flip.flag_buf_ptr, 0, len);
+		}
+
+		tp->flip.char_buf_ptr += len;
+		tp->flip.flag_buf_ptr += len;
+		tp->flip.count += len;
+	}
+	else if (!tp->real_raw) {
+		if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+			for (i = 0; i < len; i++) {
+				/*
+				 * Give the Linux ld the flags in the
+				 * format it likes.
+				 */
+				if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
+					tp->flip.flag_buf_ptr[i] = TTY_BREAK;
+				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
+					tp->flip.flag_buf_ptr[i] = TTY_PARITY;
+				else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
+					tp->flip.flag_buf_ptr[i] = TTY_FRAME;
+				else
+					tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
+			}
+		} else
+			memset(tp->flip.flag_buf, 0, len);
+	}
+
+	/*
+	 * If we're doing raw reads, jam it right into the
+	 * line disc bypassing the flip buffers.
+	 */
+	if (jsm_rawreadok) {
+		if (tp->real_raw) {
+			ch->ch_r_tail = tail & rmask;
+			ch->ch_e_tail = tail & rmask;
+
+			jsm_check_queue_flow_control(ch);
+
+			/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
+
+			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+				"jsm_input. %d real_raw len:%d calling receive_buf for board %d\n",
+				__LINE__, len, ch->ch_bd->boardnum);
+			tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
+
+			/* Allow use of channel flip buffer again */
+			spin_lock_irqsave(&ch->ch_lock, lock_flags);
+			ch->ch_flags &= ~CH_FLIPBUF_IN_USE;
+			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+		} else {
+			ch->ch_r_tail = tail & rmask;
+			ch->ch_e_tail = tail & rmask;
+
+			jsm_check_queue_flow_control(ch);
+
+			/* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
+			spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+				"jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n",
+				__LINE__, len, ch->ch_bd->boardnum);
+
+			tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len);
+		}
+	} else {
+		ch->ch_r_tail = tail & rmask;
+		ch->ch_e_tail = tail & rmask;
+
+		jsm_check_queue_flow_control(ch);
+
+		spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+		jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+			"jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__);
+		tty_schedule_flip(tp);
+	}
+
+	jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
+}
+
+void jsm_carrier(struct jsm_channel *ch)
+{
+	struct jsm_board *bd;
+
+	int virt_carrier = 0;
+	int phys_carrier = 0;
+
+	jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev, "start\n");
+	if (!ch)
+		return;
+
+	bd = ch->ch_bd;
+
+	if (!bd)
+		return;
+
+	if (ch->ch_mistat & UART_MSR_DCD) {
+		jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+			"mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
+		phys_carrier = 1;
+	}
+
+	if (ch->ch_c_cflag & CLOCAL)
+		virt_carrier = 1;
+
+	jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+		"DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier);
+
+	/*
+	 * Test for a VIRTUAL carrier transition to HIGH.
+	 */
+	if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
+
+		/*
+		 * When carrier rises, wake any threads waiting
+		 * for carrier in the open routine.
+		 */
+
+		jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+			"carrier: virt DCD rose\n");
+
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 * Test for a PHYSICAL carrier transition to HIGH.
+	 */
+	if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
+
+		/*
+		 * When carrier rises, wake any threads waiting
+		 * for carrier in the open routine.
+		 */
+
+		jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+			"carrier: physical DCD rose\n");
+
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 *  Test for a PHYSICAL transition to low, so long as we aren't
+	 *  currently ignoring physical transitions (which is what "virtual
+	 *  carrier" indicates).
+	 *
+	 *  The transition of the virtual carrier to low really doesn't
+	 *  matter... it really only means "ignore carrier state", not
+	 *  "make pretend that carrier is there".
+	 */
+	if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0)
+			&& (phys_carrier == 0)) {
+		/*
+		 *	When carrier drops:
+		 *
+		 *	Drop carrier on all open units.
+		 *
+		 *	Flush queues, waking up any task waiting in the
+		 *	line discipline.
+		 *
+		 *	Send a hangup to the control terminal.
+		 *
+		 *	Enable all select calls.
+		 */
+		if (waitqueue_active(&(ch->ch_flags_wait)))
+			wake_up_interruptible(&ch->ch_flags_wait);
+	}
+
+	/*
+	 *  Make sure that our cached values reflect the current reality.
+	 */
+	if (virt_carrier == 1)
+		ch->ch_flags |= CH_FCAR;
+	else
+		ch->ch_flags &= ~CH_FCAR;
+
+	if (phys_carrier == 1)
+		ch->ch_flags |= CH_CD;
+	else
+		ch->ch_flags &= ~CH_CD;
+}
+
+
+void jsm_check_queue_flow_control(struct jsm_channel *ch)
+{
+	int qleft = 0;
+
+	/* Store how much space we have left in the queue */
+	if ((qleft = ch->ch_r_tail - ch->ch_r_head - 1) < 0)
+		qleft += RQUEUEMASK + 1;
+
+	/*
+	 * Check to see if we should enforce flow control on our queue because
+	 * the ld (or user) isn't reading data out of our queue fast enuf.
+	 *
+	 * NOTE: This is done based on what the current flow control of the
+	 * port is set for.
+	 *
+	 * 1) HWFLOW (RTS) - Turn off the UART's Receive interrupt.
+	 *	This will cause the UART's FIFO to back up, and force
+	 *	the RTS signal to be dropped.
+	 * 2) SWFLOW (IXOFF) - Keep trying to send a stop character to
+	 *	the other side, in hopes it will stop sending data to us.
+	 * 3) NONE - Nothing we can do.  We will simply drop any extra data
+	 *	that gets sent into us when the queue fills up.
+	 */
+	if (qleft < 256) {
+		/* HWFLOW */
+		if (ch->ch_c_cflag & CRTSCTS) {
+			if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
+				ch->ch_bd->bd_ops->disable_receiver(ch);
+				ch->ch_flags |= (CH_RECEIVER_OFF);
+				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+					"Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
+					qleft);
+			}
+		}
+		/* SWFLOW */
+		else if (ch->ch_c_iflag & IXOFF) {
+			if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
+				ch->ch_bd->bd_ops->send_stop_character(ch);
+				ch->ch_stops_sent++;
+				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+					"Sending stop char! Times sent: %x\n", ch->ch_stops_sent);
+			}
+		}
+	}
+
+	/*
+	 * Check to see if we should unenforce flow control because
+	 * ld (or user) finally read enuf data out of our queue.
+	 *
+	 * NOTE: This is done based on what the current flow control of the
+	 * port is set for.
+	 *
+	 * 1) HWFLOW (RTS) - Turn back on the UART's Receive interrupt.
+	 *	This will cause the UART's FIFO to raise RTS back up,
+	 *	which will allow the other side to start sending data again.
+	 * 2) SWFLOW (IXOFF) - Send a start character to
+	 *	the other side, so it will start sending data to us again.
+	 * 3) NONE - Do nothing. Since we didn't do anything to turn off the
+	 *	other side, we don't need to do anything now.
+	 */
+	if (qleft > (RQUEUESIZE / 2)) {
+		/* HWFLOW */
+		if (ch->ch_c_cflag & CRTSCTS) {
+			if (ch->ch_flags & CH_RECEIVER_OFF) {
+				ch->ch_bd->bd_ops->enable_receiver(ch);
+				ch->ch_flags &= ~(CH_RECEIVER_OFF);
+				jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+					"Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
+					qleft);
+			}
+		}
+		/* SWFLOW */
+		else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
+			ch->ch_stops_sent = 0;
+			ch->ch_bd->bd_ops->send_start_character(ch);
+			jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "Sending start char!\n");
+		}
+	}
+}
+
+/*
+ * jsm_tty_write()
+ *
+ * Take data from the user or kernel and send it out to the FEP.
+ * In here exists all the Transparent Print magic as well.
+ */
+int jsm_tty_write(struct uart_port *port)
+{
+	int bufcount = 0, n = 0;
+	int data_count = 0,data_count1 =0;
+	u16 head;
+	u16 tail;
+	u16 tmask;
+	u32 remain;
+	int temp_tail = port->info->xmit.tail;
+	struct jsm_channel *channel = (struct jsm_channel *)port;
+
+	tmask = WQUEUEMASK;
+	head = (channel->ch_w_head) & tmask;
+	tail = (channel->ch_w_tail) & tmask;
+
+	if ((bufcount = tail - head - 1) < 0)
+		bufcount += WQUEUESIZE;
+
+	n = bufcount;
+
+	n = min(n, 56);
+	remain = WQUEUESIZE - head;
+
+	data_count = 0;
+	if (n >= remain) {
+		n -= remain;
+		while ((port->info->xmit.head != temp_tail) &&
+		(data_count < remain)) {
+			channel->ch_wqueue[head++] =
+			port->info->xmit.buf[temp_tail];
+
+			temp_tail++;
+			temp_tail &= (UART_XMIT_SIZE - 1);
+			data_count++;
+		}
+		if (data_count == remain) head = 0;
+	}
+
+	data_count1 = 0;
+	if (n > 0) {
+		remain = n;
+		while ((port->info->xmit.head != temp_tail) &&
+			(data_count1 < remain)) {
+			channel->ch_wqueue[head++] =
+				port->info->xmit.buf[temp_tail];
+
+			temp_tail++;
+			temp_tail &= (UART_XMIT_SIZE - 1);
+			data_count1++;
+
+		}
+	}
+
+	port->info->xmit.tail = temp_tail;
+
+	data_count += data_count1;
+	if (data_count) {
+		head &= tmask;
+		channel->ch_w_head = head;
+	}
+
+	if (data_count) {
+		channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel);
+	}
+
+	return data_count;
+}
+
+static ssize_t jsm_driver_version_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", JSM_VERSION);
+}
+static DRIVER_ATTR(version, S_IRUSR, jsm_driver_version_show, NULL);
+
+static ssize_t jsm_driver_state_show(struct device_driver *ddp, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", jsm_driver_state_text[jsm_driver_state]);
+}
+static DRIVER_ATTR(state, S_IRUSR, jsm_driver_state_show, NULL);
+
+void jsm_create_driver_sysfiles(struct device_driver *driverfs)
+{
+	driver_create_file(driverfs, &driver_attr_version);
+	driver_create_file(driverfs, &driver_attr_state);
+}
+
+void jsm_remove_driver_sysfiles(struct device_driver *driverfs)
+{
+	driver_remove_file(driverfs, &driver_attr_version);
+	driver_remove_file(driverfs, &driver_attr_state);
+}