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/char/rio/Makefile b/drivers/char/rio/Makefile
new file mode 100644
index 0000000..bce2bd1
--- /dev/null
+++ b/drivers/char/rio/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux rio-subsystem.
+#
+# (C) R.E.Wolff@BitWizard.nl 
+# 
+# This file is GPL. See other files for the full Blurb. I'm lazy today. 
+#
+
+obj-$(CONFIG_RIO) += rio.o
+
+rio-objs := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \
+            rioparam.o riopcicopy.o rioroute.o riotable.o riotty.o
diff --git a/drivers/char/rio/board.h b/drivers/char/rio/board.h
new file mode 100644
index 0000000..0b397e1
--- /dev/null
+++ b/drivers/char/rio/board.h
@@ -0,0 +1,143 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources. 
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: board.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:07
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)board.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_board_h__
+#define	__rio_board_h__
+
+#ifdef SCCS_LABELS
+static char *_board_h_sccs_ = "@(#)board.h	1.2";
+#endif
+
+/*
+** board.h contains the definitions for the *hardware* of the host cards.
+** It describes the memory overlay for the dual port RAM area.
+*/
+
+#define	DP_SRAM1_SIZE	0x7C00
+#define	DP_SRAM2_SIZE	0x0200
+#define	DP_SRAM3_SIZE	0x7000
+#define	DP_SCRATCH_SIZE	0x1000
+#define	DP_PARMMAP_ADDR	0x01FE	/* offset into SRAM2 */
+#define	DP_STARTUP_ADDR	0x01F8	/* offset into SRAM2 */
+
+/*
+**	The shape of the Host Control area, at offset 0x7C00, Write Only
+*/
+struct s_Ctrl
+{
+	BYTE	DpCtl;				/* 7C00 */
+	BYTE	Dp_Unused2_[127];
+	BYTE	DpIntSet;			/* 7C80 */
+	BYTE	Dp_Unused3_[127];
+	BYTE	DpTpuReset;			/* 7D00 */
+	BYTE	Dp_Unused4_[127];
+	BYTE	DpIntReset;			/* 7D80 */
+	BYTE	Dp_Unused5_[127];
+};
+
+/*
+** The PROM data area on the host (0x7C00), Read Only
+*/
+struct s_Prom
+{
+	WORD	DpSlxCode[2];
+	WORD	DpRev;
+	WORD	Dp_Unused6_;
+	WORD	DpUniq[4];
+	WORD	DpJahre;
+	WORD	DpWoche;
+	WORD	DpHwFeature[5];
+	WORD	DpOemId;
+	WORD	DpSiggy[16];
+};
+
+/*
+** Union of the Ctrl and Prom areas
+*/
+union u_CtrlProm	/* This is the control/PROM area (0x7C00) */
+{
+	struct s_Ctrl	DpCtrl;
+	struct s_Prom	DpProm;
+};
+
+/*
+** The top end of memory!
+*/
+struct s_ParmMapS		/* Area containing Parm Map Pointer */
+{
+	BYTE	Dp_Unused8_[DP_PARMMAP_ADDR];
+	WORD	DpParmMapAd;
+};
+
+struct s_StartUpS
+{
+	BYTE    Dp_Unused9_[DP_STARTUP_ADDR];
+	BYTE	Dp_LongJump[0x4];
+	BYTE	Dp_Unused10_[2];
+	BYTE	Dp_ShortJump[0x2];
+};
+
+union u_Sram2ParmMap	/* This is the top of memory (0x7E00-0x7FFF) */
+{
+	BYTE	DpSramMem[DP_SRAM2_SIZE];
+	struct s_ParmMapS DpParmMapS;
+	struct s_StartUpS DpStartUpS;
+};
+
+/*
+**	This is the DP RAM overlay.
+*/
+struct DpRam
+{
+    BYTE 		 DpSram1[DP_SRAM1_SIZE];     /* 0000 - 7BFF */
+    union u_CtrlProm     DpCtrlProm;                 /* 7C00 - 7DFF */
+    union u_Sram2ParmMap DpSram2ParmMap;             /* 7E00 - 7FFF */
+    BYTE		 DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */
+    BYTE		 DpSram3[DP_SRAM3_SIZE];     /* 9000 - FFFF */
+};
+
+#define	DpControl	DpCtrlProm.DpCtrl.DpCtl
+#define	DpSetInt	DpCtrlProm.DpCtrl.DpIntSet
+#define	DpResetTpu	DpCtrlProm.DpCtrl.DpTpuReset
+#define	DpResetInt	DpCtrlProm.DpCtrl.DpIntReset
+
+#define	DpSlx		DpCtrlProm.DpProm.DpSlxCode
+#define	DpRevision	DpCtrlProm.DpProm.DpRev
+#define	DpUnique	DpCtrlProm.DpProm.DpUniq
+#define	DpYear		DpCtrlProm.DpProm.DpJahre
+#define	DpWeek		DpCtrlProm.DpProm.DpWoche
+#define	DpSignature	DpCtrlProm.DpProm.DpSiggy
+
+#define	DpParmMapR	DpSram2ParmMap.DpParmMapS.DpParmMapAd
+#define	DpSram2		DpSram2ParmMap.DpSramMem
+
+#endif
diff --git a/drivers/char/rio/bootpkt.h b/drivers/char/rio/bootpkt.h
new file mode 100644
index 0000000..c329aeb
--- /dev/null
+++ b/drivers/char/rio/bootpkt.h
@@ -0,0 +1,62 @@
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******        B O O T    P A C K E T   H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _pkt_h
+#define _pkt_h 1
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h	1.1" ;
+#endif
+#endif
+
+    /*************************************************
+     * Overlayed onto the Data fields of a regular
+     * Packet
+     ************************************************/
+typedef struct BOOT_PKT BOOT_PKT ;
+struct BOOT_PKT {
+                    short     seq_num ;
+                    char      data[10] ;
+                } ;
+
+
+#endif
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/brates.h b/drivers/char/rio/brates.h
new file mode 100644
index 0000000..bd4fc84
--- /dev/null
+++ b/drivers/char/rio/brates.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+ *******                                                              *******
+ *******		BRATES.H				      *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    : 1 Nov 1990
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _brates_h
+#ifndef lint
+/* static char * _brates_h_sccs = "@(#)brates.h	1.4"; */
+#endif
+#define _brates_h 1
+/* List of baud rate defines. Most are borrowed from /usr/include/sys/termio.h
+*/
+#ifndef INKERNEL
+
+#define	B0	0x00
+#define	B50	0x01
+#define	B75	0x02
+#define	B110	0x03
+#define	B134	0x04
+#define	B150	0x05
+#define	B200	0x06
+#define	B300	0x07
+#define	B600	0x08
+#define	B1200	0x09
+#define	B1800	0x0a
+#define	B2400	0x0b
+#define	B4800	0x0c
+#define	B9600	0x0d
+#define	B19200	0x0e
+#define	B38400	0x0f
+
+#endif
+
+/*
+** The following baudrates may or may not be defined
+** on various UNIX systems.
+** If they are not then we define them.
+** If they are then we do not define them ;-)
+**
+** This is appalling that we use same definitions as UNIX
+** for our own download code as there is no garuntee that
+** B57600 will be defined as 0x11 by a UNIX system....
+** Arghhhhh!!!!!!!!!!!!!!
+*/
+#if !defined(B56000)
+#define	B56000	0x10
+#endif
+
+#if !defined(B57600)
+#define	B57600	0x11
+#endif
+
+#if !defined(B64000)
+#define	B64000	0x12
+#endif
+
+#if !defined(B115200)
+#define	B115200	0x13
+#endif
+
+
+#if !defined(B2000)
+#define B2000	0x14
+#endif
+
+
+#define MAX_RATE B2000
+
+struct    baud_rate            /* Tag for baud rates */
+{
+     /* short    host_rate,*/        /* As passed by the driver */
+     short    divisor,          /* The divisor */
+              prescaler;        /* The pre-scaler */
+};
+
+#endif
diff --git a/drivers/char/rio/chan.h b/drivers/char/rio/chan.h
new file mode 100644
index 0000000..5b30654
--- /dev/null
+++ b/drivers/char/rio/chan.h
@@ -0,0 +1,33 @@
+/*
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef _chan_h
+#define _chan_h
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_chan_h_sccs = "@(#)chan.h	1.1" ;
+#endif
+#endif
+
+#define Link0   0
+#define Link1   1
+#define Link2   2
+#define Link3   3
+
+#endif
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h
new file mode 100644
index 0000000..cf056a9
--- /dev/null
+++ b/drivers/char/rio/cirrus.h
@@ -0,0 +1,463 @@
+/****************************************************************************
+ *******                                                              *******
+ *******		CIRRUS.H				      *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    : 3 Aug 1990
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _cirrus_h
+#ifndef lint
+/* static char* _cirrus_h_sccs = "@(#)cirrus.h	1.16"; */
+#endif
+#define _cirrus_h 1
+
+#ifdef RTA
+#define	TO_UART	RX
+#define TO_DRIVER TX
+#endif
+
+#ifdef HOST
+#define	TO_UART	TX
+#define TO_DRIVER RX
+#endif
+#ifdef RTA
+/* Miscellaneous defines for CIRRUS addresses and related logic for
+   interrupts etc.
+*/
+#define	MAP(a)		((short *)(cirrus_base + (a)))
+#define outp(a,b)	(*MAP (a) =(b))
+#define inp(a)		((*MAP (a)) & 0xff)
+#define	CIRRUS_FIRST	(short*)0x7300
+#define	CIRRUS_SECOND	(short*)0x7200
+#define	CIRRUS_THIRD	(short*)0x7100
+#define	CIRRUS_FOURTH	(short*)0x7000
+#define	PORTS_ON_CIRRUS	4
+#define	CIRRUS_FIFO_SIZE	12
+#define	SPACE		0x20
+#define	TAB		0x09
+#define	LINE_FEED	0x0a
+#define	CARRIAGE_RETURN	0x0d
+#define	BACKSPACE	0x08
+#define	SPACES_IN_TABS	8
+#define	SEND_ESCAPE	0x00
+#define START_BREAK	0x81
+#define	TIMER_TICK	0x82
+#define STOP_BREAK	0x83
+#define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH)))
+#define txack1	((short *)0x7104) 
+#define rxack1	((short *)0x7102) 
+#define mdack1  ((short *)0x7106)
+#define txack2  ((short *)0x7006) 
+#define rxack2	((short *)0x7004) 
+#define mdack2  ((short *)0x7100) 
+#define int_latch       ((short *) 0x7800)
+#define int_status      ((short *) 0x7c00) 
+#define tx1_pending     0x20 
+#define rx1_pending     0x10 
+#define md1_pending     0x40 
+#define tx2_pending     0x02 
+#define rx2_pending     0x01 
+#define md2_pending     0x40 
+#define module1_bits	0x07
+#define module1_modern	0x08
+#define module2_bits	0x70
+#define module2_modern	0x80
+#define module_blank	0xf
+#define rs232_d25	0x0
+#define	rs232_rj45	0x1
+#define rs422_d25	0x3
+#define parallel	0x5
+
+#define	CLK0	0x00
+#define CLK1	0x01
+#define CLK2	0x02
+#define CLK3	0x03
+#define CLK4	0x04
+
+#define CIRRUS_REVC    0x42
+#define CIRRUS_REVE    0x44
+
+#define	TURNON	1
+#define TURNOFF 0
+
+/* The list of CIRRUS registers. 
+   NB. These registers are relative values on 8 bit boundaries whereas
+   on the RTA's the CIRRUS registers are on word boundaries. Use pointer
+   arithmetic (short *) to obtain the real addresses required */
+#define ccr	0x05	/* Channel Command Register     */
+#define ier	0x06	/* Interrupt Enable Register    */
+#define cor1	0x08	/* Channel Option Register 1    */
+#define cor2	0x09	/* Channel Option Register 2    */
+#define cor3	0x0a	/* Channel Option Register 3    */
+#define cor4	0x1e	/* Channel Option Register 4    */
+#define	cor5	0x1f	/* Channel Option Register 5	*/
+
+#define ccsr	0x0b	/* Channel Control Status Register */
+#define rdcr	0x0e	/* Receive Data Count Register  */
+#define tdcr	0x12	/* Transmit Data Count Register */
+#define mcor1	0x15	/* Modem Change Option Register 1 */
+#define mcor2	0x16	/* Modem Change Option Regsiter 2 */
+
+#define livr	0x18	/* Local Interrupt Vector Register */
+#define schr1	0x1a	/* Special Character Register 1 */
+#define schr2	0x1b	/* Special Character Register 2 */
+#define schr3	0x1c	/* Special Character Register 3 */
+#define schr4	0x1d	/* Special Character Register 4 */
+
+#define rtr	0x20    /* Receive Timer Register */
+#define rtpr	0x21	/* Receive Timeout Period Register */
+#define lnc	0x24	/* Lnext character */
+
+#define rivr	0x43	/* Receive Interrupt Vector Register    */
+#define tivr	0x42	/* Transmit Interrupt Vector Register   */
+#define mivr	0x41	/* Modem Interrupt Vector Register      */
+#define gfrcr	0x40	/* Global Firmware Revision code Reg    */
+#define ricr	0x44	/* Receive Interrupting Channel Reg     */
+#define ticr	0x45	/* Transmit Interrupting Channel Reg    */
+#define micr	0x46	/* Modem Interrupting Channel Register  */
+
+#define gcr	0x4b	/* Global configuration register*/
+#define misr    0x4c    /* Modem interrupt status register */
+
+#define rbusr	0x59
+#define tbusr	0x5a
+#define mbusr	0x5b
+
+#define eoir	0x60	/* End Of Interrupt Register */
+#define rdsr	0x62	/* Receive Data / Status Register */
+#define tdr	0x63	/* Transmit Data Register */
+#define svrr	0x67	/* Service Request Register */
+
+#define car	0x68	/* Channel Access Register */
+#define mir	0x69	/* Modem Interrupt Register */
+#define tir	0x6a	/* Transmit Interrupt Register */
+#define rir	0x6b	/* Receive Interrupt Register */
+#define msvr1	0x6c	/* Modem Signal Value Register 1 */
+#define msvr2	0x6d	/* Modem Signal Value Register 2*/
+#define psvr	0x6f	/* Printer Signal Value Register*/
+
+#define tbpr	0x72	/* Transmit Baud Rate Period Register */
+#define tcor	0x76	/* Transmit Clock Option Register */
+
+#define rbpr	0x78	/* Receive Baud Rate Period Register */
+#define rber	0x7a	/* Receive Baud Rate Extension Register */
+#define rcor	0x7c	/* Receive Clock Option Register*/
+#define ppr	0x7e	/* Prescalar Period Register    */
+
+/* Misc registers used for forcing the 1400 out of its reset woes */
+#define airl	0x6d
+#define airm	0x6e
+#define airh	0x6f
+#define btcr	0x66
+#define mtcr	0x6c
+#define tber	0x74
+
+#endif				/* #ifdef RTA */
+
+
+/* Bit fields for particular registers */
+
+/* GCR */
+#define GCR_SERIAL	0x00	/* Configure as serial channel */
+#define GCR_PARALLEL	0x80	/* Configure as parallel channel */
+
+/* RDSR - when status read from FIFO */
+#define	RDSR_BREAK		0x08	/* Break received */
+#define RDSR_TIMEOUT    	0x80    /* No new data timeout */
+#define RDSR_SC1  	  	0x10    /* Special char 1 (tx XON) matched */
+#define RDSR_SC2  	  	0x20    /* Special char 2 (tx XOFF) matched */
+#define RDSR_SC12_MASK	  	0x30    /* Mask for special chars 1 and 2 */
+
+/* PPR */
+#define PPR_DEFAULT	0x31	/* Default value - for a 25Mhz clock gives
+				   a timeout period of 1ms */
+
+/* LIVR */
+#define	LIVR_EXCEPTION	0x07	/* Receive exception interrupt */
+
+/* CCR */
+#define	CCR_RESET	0x80	/* Reset channel */
+#define	CCR_CHANGE	0x4e	/* COR's have changed - NB always change all
+				   COR's */
+#define	CCR_WFLUSH	0x82	/* Flush transmit FIFO and TSR / THR */
+
+#define	CCR_SENDSC1	0x21	/* Send special character one */
+#define CCR_SENDSC2	0x22	/* Send special character two */
+#define CCR_SENDSC3	0x23	/* Send special character three */
+#define CCR_SENDSC4	0x24	/* Send special character four */
+
+#define CCR_TENABLE	0x18	/* Enable transmitter */
+#define	CCR_TDISABLE	0x14	/* Disable transmitter */
+#define CCR_RENABLE	0x12	/* Enable receiver */
+#define CCR_RDISABLE	0x11	/* Disable receiver */
+
+#define	CCR_READY	0x00	/* CCR is ready for another command */
+
+/* CCSR */
+#define CCSR_TXENABLE	0x08	/* Transmitter enable */
+#define CCSR_RXENABLE	0x80	/* Receiver enable */
+#define CCSR_TXFLOWOFF	0x04	/* Transmit flow off */
+#define CCSR_TXFLOWON	0x02	/* Transmit flow on */
+
+/* SVRR */
+#define	SVRR_RECEIVE	0x01	/* Receive interrupt pending */
+#define	SVRR_TRANSMIT	0x02	/* Transmit interrupt pending */
+#define	SVRR_MODEM	0x04	/* Modem interrupt pending */
+
+/* CAR */
+#define CAR_PORTS	0x03	/* Bit fields for ports */
+
+/* IER */
+#define	IER_MODEM	0x80	/* Change in modem status */
+#define	IER_RECEIVE	0x10	/* Good data / data exception */
+#define IER_TRANSMITR	0x04	/* Transmit ready (FIFO empty) */
+#define	IER_TRANSMITE	0x02	/* Transmit empty */
+#define IER_TIMEOUT	0x01	/* Timeout on no data */
+
+#define	IER_DEFAULT	0x94	/* Default values */
+#define IER_PARALLEL    0x84    /* Default for Parallel */
+#define	IER_EMPTY	0x92	/* Transmitter empty rather than ready */
+
+/* COR1 - Driver only */
+#define	COR1_INPCK	0x10	/* Check parity of received characters */
+
+/* COR1 - driver and RTA */
+#define	COR1_ODD	0x80	/* Odd parity */
+#define COR1_EVEN	0x00	/* Even parity */
+#define	COR1_NOP	0x00	/* No parity */
+#define	COR1_FORCE	0x20	/* Force parity */
+#define	COR1_NORMAL	0x40	/* With parity */
+#define	COR1_1STOP	0x00	/* 1 stop bit */
+#define	COR1_15STOP	0x04	/* 1.5 stop bits */
+#define	COR1_2STOP	0x08	/* 2 stop bits */
+#define	COR1_5BITS	0x00	/* 5 data bits */
+#define	COR1_6BITS	0x01	/* 6 data bits */
+#define	COR1_7BITS	0x02	/* 7 data bits */
+#define	COR1_8BITS	0x03	/* 8 data bits */
+
+#define COR1_HOST       0xef    /* Safe host bits */
+
+/* RTA only */
+#define COR1_CINPCK     0x00    /* Check parity of received characters */
+#define COR1_CNINPCK    0x10    /* Don't check parity */
+
+/* COR2 bits for both RTA and driver use */
+#define	COR2_IXANY	0x80	/* IXANY - any character is XON */
+#define	COR2_IXON	0x40	/* IXON - enable tx soft flowcontrol */
+#define	COR2_RTSFLOW	0x02	/* Enable tx hardware flow control */
+
+/* Additional driver bits */
+#define	COR2_HUPCL	0x20	/* Hang up on close */
+#define	COR2_CTSFLOW	0x04	/* Enable rx hardware flow control */
+#define	COR2_IXOFF	0x01	/* Enable rx software flow control */
+#define COR2_DTRFLOW	0x08	/* Enable tx hardware flow control */
+
+/* RTA use only */
+#define COR2_ETC	0x20	/* Embedded transmit options */
+#define	COR2_LOCAL	0x10	/* Local loopback mode */
+#define	COR2_REMOTE	0x08	/* Remote loopback mode */
+#define	COR2_HOST	0xc2	/* Safe host bits */
+
+/* COR3 - RTA use only */
+#define	COR3_SCDRNG	0x80	/* Enable special char detect for range */
+#define	COR3_SCD34	0x40	/* Special character detect for SCHR's 3 + 4 */
+#define	COR3_FCT	0x20	/* Flow control transparency */
+#define	COR3_SCD12	0x10	/* Special character detect for SCHR's 1 + 2 */
+#define	COR3_FIFO12	0x0c	/* 12 chars for receive FIFO threshold */
+#define COR3_FIFO10     0x0a    /* 10 chars for receive FIFO threshold */
+#define COR3_FIFO8      0x08    /* 8 chars for receive FIFO threshold */
+#define COR3_FIFO6      0x06    /* 6 chars for receive FIFO threshold */
+
+#define COR3_THRESHOLD  COR3_FIFO8	/* MUST BE LESS THAN MCOR_THRESHOLD */
+
+#define	COR3_DEFAULT	(COR3_FCT | COR3_THRESHOLD)
+				/* Default bits for COR3 */
+
+/* COR4 driver and RTA use */
+#define	COR4_IGNCR	0x80	/* Throw away CR's on input */
+#define	COR4_ICRNL	0x40	/* Map CR -> NL on input */
+#define	COR4_INLCR	0x20	/* Map NL -> CR on input */
+#define	COR4_IGNBRK	0x10	/* Ignore Break */
+#define	COR4_NBRKINT	0x08	/* No interrupt on break (-BRKINT) */
+#define COR4_RAISEMOD	0x01	/* Raise modem output lines on non-zero baud */
+
+
+/* COR4 driver only */
+#define COR4_IGNPAR	0x04	/* IGNPAR (ignore characters with errors) */
+#define COR4_PARMRK	0x02	/* PARMRK */
+
+#define COR4_HOST	0xf8	/* Safe host bits */
+
+/* COR4 RTA only */
+#define COR4_CIGNPAR	0x02	/* Thrown away bad characters */
+#define COR4_CPARMRK	0x04	/* PARMRK characters */
+#define COR4_CNPARMRK	0x03	/* Don't PARMRK */
+
+/* COR5 driver and RTA use */
+#define	COR5_ISTRIP	0x80	/* Strip input chars to 7 bits */
+#define	COR5_LNE	0x40	/* Enable LNEXT processing */
+#define	COR5_CMOE	0x20	/* Match good and errored characters */
+#define	COR5_ONLCR	0x02	/* NL -> CR NL on output */
+#define	COR5_OCRNL	0x01	/* CR -> NL on output */
+
+/*
+** Spare bits - these are not used in the CIRRUS registers, so we use
+** them to set various other features.
+*/
+/*
+** tstop and tbusy indication
+*/
+#define	COR5_TSTATE_ON	0x08	/* Turn on monitoring of tbusy and tstop */
+#define	COR5_TSTATE_OFF	0x04	/* Turn off monitoring of tbusy and tstop */
+/*
+** TAB3
+*/
+#define	COR5_TAB3	0x10	/* TAB3 mode */
+
+#define	COR5_HOST	0xc3	/* Safe host bits */
+
+/* CCSR */
+#define	CCSR_TXFLOFF	0x04	/* Tx is xoffed */
+
+/* MSVR1 */
+/* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the
+   RTA. This is because otherwise DCD would get lost on the 1 parallel / 3
+   serial option.
+*/
+#define	MSVR1_CD	0x80	/* CD (DSR on Cirrus) */
+#define	MSVR1_RTS	0x40	/* RTS (CTS on Cirrus) */
+#define	MSVR1_RI	0x20	/* RI */
+#define	MSVR1_DTR	0x10	/* DTR (CD on Cirrus) */
+#define	MSVR1_CTS	0x01	/* CTS output pin (RTS on Cirrus) */
+/* Next two used to indicate state of tbusy and tstop to driver */
+#define	MSVR1_TSTOP	0x08	/* Set if port flow controlled */
+#define	MSVR1_TEMPTY	0x04	/* Set if port tx buffer empty */
+
+#define	MSVR1_HOST	0xf3	/* The bits the host wants */
+
+/* MSVR2 */
+#define	MSVR2_DSR	0x02	/* DSR output pin (DTR on Cirrus) */
+
+/* MCOR */
+#define	MCOR_CD	        0x80	/* CD (DSR on Cirrus) */
+#define	MCOR_RTS	0x40	/* RTS (CTS on Cirrus) */
+#define	MCOR_RI	        0x20	/* RI */
+#define	MCOR_DTR	0x10	/* DTR (CD on Cirrus) */
+
+#define MCOR_DEFAULT    (MCOR_CD | MCOR_RTS | MCOR_RI | MCOR_DTR)
+#define MCOR_FULLMODEM  MCOR_DEFAULT
+#define MCOR_RJ45       (MCOR_CD | MCOR_RTS | MCOR_DTR)
+#define MCOR_RESTRICTED (MCOR_CD | MCOR_RTS)
+
+/* More MCOR - H/W Handshake (flowcontrol) stuff */
+#define	MCOR_THRESH8	0x08	/* eight characters then we stop */
+#define	MCOR_THRESH9	0x09	/* nine characters then we stop */
+#define	MCOR_THRESH10	0x0A	/* ten characters then we stop */
+#define	MCOR_THRESH11	0x0B	/* eleven characters then we stop */
+
+#define	MCOR_THRESHBITS 0x0F	/* mask for ANDing out the above */
+
+#define	MCOR_THRESHOLD	MCOR_THRESH9 /* MUST BE GREATER THAN COR3_THRESHOLD */
+
+
+/* RTPR */
+#define RTPR_DEFAULT	0x02	/* Default */
+
+
+/* Defines for the subscripts of a CONFIG packet */
+#define	CONFIG_COR1	1	/* Option register 1 */
+#define	CONFIG_COR2	2	/* Option register 2 */
+#define	CONFIG_COR4	3	/* Option register 4 */
+#define	CONFIG_COR5	4	/* Option register 5 */
+#define	CONFIG_TXXON	5	/* Tx XON character */
+#define	CONFIG_TXXOFF	6	/* Tx XOFF character */
+#define	CONFIG_RXXON	7	/* Rx XON character */
+#define	CONFIG_RXXOFF	8	/* Rx XOFF character */
+#define CONFIG_LNEXT	9	/* LNEXT character */
+#define	CONFIG_TXBAUD	10	/* Tx baud rate */
+#define	CONFIG_RXBAUD	11	/* Rx baud rate */
+
+/* Port status stuff */
+#define	IDLE_CLOSED	0	/* Closed */
+#define IDLE_OPEN	1	/* Idle open */
+#define IDLE_BREAK	2	/* Idle on break */
+
+/* Subscript of MODEM STATUS packet */
+#define	MODEM_VALUE	3	/* Current values of handshake pins */
+/* Subscript of SBREAK packet */
+#define BREAK_LENGTH	1	/* Length of a break in slices of 0.01 seconds
+				   0 = stay on break until an EBREAK command
+				   is sent */
+
+
+#define	PRE_EMPTIVE	0x80	/* Pre-emptive bit in command field */
+
+/* Packet types going from Host to remote - with the exception of OPEN, MOPEN,
+   CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not
+   be used 
+*/
+#define	OPEN		0x00	/* Open a port */
+#define CONFIG		0x01	/* Configure a port */
+#define	MOPEN		0x02	/* Modem open (block for DCD) */
+#define	CLOSE		0x03	/* Close a port */
+#define	WFLUSH		(0x04 | PRE_EMPTIVE) /* Write flush */
+#define	RFLUSH		(0x05 | PRE_EMPTIVE) /* Read flush */
+#define	RESUME		(0x06 | PRE_EMPTIVE) /* Resume if xoffed */
+#define	SBREAK		0x07 	/* Start break */
+#define	EBREAK		0x08	/* End break */
+#define	SUSPEND		(0x09 | PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */
+#define FCLOSE          (0x0a | PRE_EMPTIVE) /* Force close */
+#define XPRINT          0x0b    /* Xprint packet */
+#define MBIS		(0x0c | PRE_EMPTIVE) /* Set modem lines */
+#define MBIC		(0x0d | PRE_EMPTIVE) /* Clear modem lines */
+#define MSET		(0x0e | PRE_EMPTIVE) /* Set modem lines */
+#define PCLOSE		0x0f	/* Pseudo close - Leaves rx/tx enabled */
+#define MGET		(0x10 | PRE_EMPTIVE) /* Force update of modem status */
+#define MEMDUMP		(0x11 | PRE_EMPTIVE) /* Send back mem from addr supplied */
+#define	READ_REGISTER	(0x12 | PRE_EMPTIVE) /* Read CD1400 register (debug) */
+
+/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
+   use data[4] / data[3] to indicate current state and modem status respectively
+*/ 
+
+#define	COMPLETE	(0x20 | PRE_EMPTIVE)
+				/* Command complete */
+#define BREAK_RECEIVED	(0x21 | PRE_EMPTIVE)
+				/* Break received */
+#define MODEM_STATUS	(0x22 | PRE_EMPTIVE)
+				/* Change in modem status */
+
+/* "Command" packet that could go either way - handshake wake-up */
+#define HANDSHAKE	(0x23 | PRE_EMPTIVE)
+				/* Wake-up to HOST / RTA */
+
+#endif
diff --git a/drivers/char/rio/cmd.h b/drivers/char/rio/cmd.h
new file mode 100644
index 0000000..c369eda
--- /dev/null
+++ b/drivers/char/rio/cmd.h
@@ -0,0 +1,84 @@
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******           C O M M A N D   P A C K E T   H E A D E R S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+
+#ifndef _cmd_h
+#define _cmd_h
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_cmd_h_sccs = "@(#)cmd.h	1.1" ;
+#endif
+#endif
+
+
+#define PRE_EMPTIVE_CMD         0x80
+#define INLINE_CMD              ~PRE_EMPTIVE_CMD
+
+#define CMD_IGNORE_PKT          ( (ushort) 0)
+#define CMD_STATUS_REQ          ( (ushort) 1)
+#define CMD_UNIT_STATUS_REQ     ( (ushort) 2)     /* Is this needed ??? */
+#define CMD_CONF_PORT           ( (ushort) 3)
+#define CMD_CONF_UNIT           ( (ushort) 4)
+#define CMD_ROUTE_MAP_REQ       ( (ushort) 5)
+#define CMD_FLUSH_TX            ( (ushort) 6)
+#define CMD_FLUSH_RX            ( (ushort) 7)
+#define CMD_PARTION_PORT        ( (ushort) 8)
+#define CMD_RESET_PORT          ( (ushort) 0x0a)
+#define CMD_BOOT_UNIT           ( (ushort) 0x0b)
+#define CMD_FOUND_UNIT          ( (ushort) 0x0c)
+#define CMD_ATTACHED_RTA_2      ( (ushort) 0x0d)
+#define CMD_PROVIDE_BOOT        ( (ushort) 0x0e)
+#define CMD_CIRRUS              ( (ushort) 0x0f)
+
+#define FORM_STATUS_PKT         ( (ushort) 1 )
+#define FORM_POLL_PKT           ( (ushort) 2 )
+#define FORM_LINK_STATUS_PKT    ( (ushort) 3 )
+
+
+#define CMD_DATA_PORT           ( (ushort) 1 )
+#define CMD_DATA                ( (ushort) 2 )
+
+#define CMD_TX_PART             ( (ushort) 2 )
+#define CMD_RX_PART             ( (ushort) 3 )
+#define CMD_RX_LIMIT            ( (ushort) 4 )
+
+#endif
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/cmdblk.h b/drivers/char/rio/cmdblk.h
new file mode 100644
index 0000000..2b8efbd
--- /dev/null
+++ b/drivers/char/rio/cmdblk.h
@@ -0,0 +1,60 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: cmdblk.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)cmdblk.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_cmdblk_h__
+#define __rio_cmdblk_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_cmdblk_h_sccs_ = "@(#)cmdblk.h	1.2";
+#endif
+#endif
+
+/*
+** the structure of a command block, used to queue commands destined for
+** a rup.
+*/
+
+struct CmdBlk
+{
+ struct CmdBlk *NextP;          /* Pointer to next command block */
+ struct	PKT     Packet;         /* A packet, to copy to the rup */
+    	                        /* The func to call to check if OK */
+    	int     (*PreFuncP)(int, struct CmdBlk *);
+    	int     PreArg;         /* The arg for the func */
+    	                        /* The func to call when completed */
+    	int     (*PostFuncP)(int, struct CmdBlk *);
+    	int     PostArg;        /* The arg for the func */
+};
+
+#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4))
+#endif
diff --git a/drivers/char/rio/cmdpkt.h b/drivers/char/rio/cmdpkt.h
new file mode 100644
index 0000000..46befd35
--- /dev/null
+++ b/drivers/char/rio/cmdpkt.h
@@ -0,0 +1,206 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: cmdpkt.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)cmdpkt.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifndef __rio_cmdpkt_h__
+#define __rio_cmdpkt_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_cmdpkt_h_sccs_ = "@(#)cmdpkt.h	1.2";
+#endif
+#endif
+
+/*
+** overlays for the data area of a packet. Used in both directions
+** (to build a packet to send, and to interpret a packet that arrives)
+** and is very inconvenient for MIPS, so they appear as two separate
+** structures - those used for modifying/reading packets on the card
+** and those for modifying/reading packets in real memory, which have an _M
+** suffix.
+*/
+
+#define	RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2)
+
+/*
+** The boot information packet looks like this:
+** This structure overlays a PktCmd->CmdData structure, and so starts
+** at Data[2] in the actual pkt!
+*/
+struct BootSequence
+{
+    WORD	NumPackets;
+    WORD	LoadBase;
+    WORD	CodeSize;
+};
+
+#define	BOOT_SEQUENCE_LEN	8
+
+struct SamTop
+{
+    BYTE Unit;
+    BYTE Link;
+};
+
+struct CmdHdr
+{
+    BYTE PcCommand;
+    union
+    {
+    BYTE PcPhbNum;
+    BYTE PcLinkNum;
+    BYTE PcIDNum;
+    } U0;
+};
+
+
+struct PktCmd
+{
+    union
+    {
+	struct 
+	{
+	    struct CmdHdr CmdHdr;
+	    struct BootSequence PcBootSequence;
+	} S1;
+	struct
+	{
+	    WORD PcSequence;
+	    BYTE PcBootData[RTA_BOOT_DATA_SIZE];
+	} S2;
+	struct
+	{
+	    WORD  __crud__;
+	    BYTE  PcUniqNum[4];	        /* this is really a uint. */
+	    BYTE  PcModuleTypes;  	/* what modules are fitted */
+	} S3;
+	struct
+	{
+	    struct CmdHdr CmdHdr;
+	    BYTE   __undefined__;
+	    BYTE   PcModemStatus;
+	    BYTE   PcPortStatus;
+	    BYTE   PcSubCommand;	/* commands like mem or register dump */
+	    WORD   PcSubAddr;		/* Address for command */
+	    BYTE   PcSubData[64];	/* Date area for command */
+	} S4;
+	struct
+	{
+	    struct CmdHdr CmdHdr;
+	    BYTE   PcCommandText[1];
+	    BYTE   __crud__[20];
+	    BYTE   PcIDNum2;		/* It had to go somewhere! */
+	} S5;
+	struct
+	{
+	    struct CmdHdr CmdHdr;
+	    struct SamTop    Topology[LINKS_PER_UNIT];
+	} S6;
+    } U1;
+};
+
+struct PktCmd_M
+{
+    union
+    {
+	struct 
+	{
+	    struct
+	    {
+    		uchar PcCommand;
+    		union
+    		{
+    		    uchar PcPhbNum;
+    		    uchar PcLinkNum;
+    		    uchar PcIDNum;
+    		} U0;
+	    } CmdHdr;
+	    struct
+	    {
+                ushort	NumPackets;
+                ushort	LoadBase;
+                ushort	CodeSize;
+            } PcBootSequence;
+	} S1;
+	struct
+	{
+	    ushort PcSequence;
+	    uchar PcBootData[RTA_BOOT_DATA_SIZE];
+	} S2;
+	struct
+	{
+	    ushort  __crud__;
+	    uchar  PcUniqNum[4];	        /* this is really a uint. */
+	    uchar  PcModuleTypes;  	/* what modules are fitted */
+	} S3;
+	struct
+	{
+	    ushort  __cmd_hdr__;
+	    uchar   __undefined__;
+	    uchar   PcModemStatus;
+	    uchar   PcPortStatus;
+	    uchar   PcSubCommand;
+	    ushort  PcSubAddr;
+	    uchar   PcSubData[64];
+	} S4;
+	struct
+	{
+	    ushort  __cmd_hdr__;
+	    uchar   PcCommandText[1];
+	    uchar   __crud__[20];
+	    uchar   PcIDNum2;		/* Tacked on end */
+	} S5;
+	struct
+	{
+	    ushort  __cmd_hdr__;
+	    struct Top Topology[LINKS_PER_UNIT];
+	} S6;
+    } U1;
+};
+
+#define Command		U1.S1.CmdHdr.PcCommand
+#define PhbNum		U1.S1.CmdHdr.U0.PcPhbNum
+#define IDNum		U1.S1.CmdHdr.U0.PcIDNum
+#define IDNum2		U1.S5.PcIDNum2
+#define LinkNum		U1.S1.CmdHdr.U0.PcLinkNum
+#define Sequence	U1.S2.PcSequence
+#define BootData	U1.S2.PcBootData
+#define BootSequence	U1.S1.PcBootSequence
+#define UniqNum		U1.S3.PcUniqNum
+#define ModemStatus	U1.S4.PcModemStatus
+#define PortStatus	U1.S4.PcPortStatus
+#define SubCommand	U1.S4.PcSubCommand
+#define SubAddr		U1.S4.PcSubAddr
+#define SubData		U1.S4.PcSubData
+#define CommandText	U1.S5.PcCommandText
+#define RouteTopology	U1.S6.Topology
+#define ModuleTypes	U1.S3.PcModuleTypes
+
+#endif
diff --git a/drivers/char/rio/control.h b/drivers/char/rio/control.h
new file mode 100644
index 0000000..1712f62
--- /dev/null
+++ b/drivers/char/rio/control.h
@@ -0,0 +1,62 @@
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******           C O N T R O L   P A C K E T   H E A D E R S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jon Brawn
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+
+#ifndef _control_h
+#define _control_h
+
+#ifndef lint
+/* static char *_rio_control_h_sccs = "@(#)control.h	1.4"; */
+#endif
+
+#define	CONTROL		'^'
+#define IFOAD		( CONTROL + 1 )
+#define	IDENTIFY	( CONTROL + 2 )
+#define	ZOMBIE		( CONTROL + 3 )
+#define	UFOAD		( CONTROL + 4 )
+#define IWAIT		( CONTROL + 5 )
+
+#define	IFOAD_MAGIC	0xF0AD		/* of course */
+#define	ZOMBIE_MAGIC	(~0xDEAD)	/* not dead -> zombie */
+#define	UFOAD_MAGIC	0xD1E		/* kill-your-neighbour */
+#define	IWAIT_MAGIC	0xB1DE		/* Bide your time */
+
+#endif
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h
new file mode 100644
index 0000000..62dba0e
--- /dev/null
+++ b/drivers/char/rio/daemon.h
@@ -0,0 +1,334 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: daemon.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)daemon.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_daemon_h__
+#define	__rio_daemon_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_daemon_h_sccs_ = "@(#)daemon.h	1.3";
+#endif
+#endif
+
+
+/*
+** structures used on /dev/rio
+*/
+
+struct Error
+{
+	uint	Error;
+	uint	Entry;
+	uint	Other;
+};
+
+struct DownLoad
+{
+	char	*DataP;
+	uint	Count;
+	uint	ProductCode;
+};
+
+/*
+** A few constants....
+*/
+#ifndef MAX_VERSION_LEN
+#define	MAX_VERSION_LEN	256
+#endif
+
+#ifndef MAX_XP_CTRL_LEN
+#define	MAX_XP_CTRL_LEN 16		/* ALSO IN PORT.H */
+#endif
+
+struct	PortSetup
+{
+	uint	From;	/* Set/Clear XP & IXANY Control from this port.... */
+	uint	To;	/* .... to this port */
+	uint	XpCps;			/* at this speed */
+	char	XpOn[MAX_XP_CTRL_LEN];	/* this is the start string */
+	char	XpOff[MAX_XP_CTRL_LEN];	/* this is the stop string */
+	uchar	IxAny;			/* enable/disable IXANY */
+	uchar	IxOn;			/* enable/disable IXON */
+	uchar	Lock;			/* lock port params */
+	uchar	Store;			/* store params across closes */
+	uchar	Drain;			/* close only when drained */
+};
+
+struct	LpbReq
+{
+	uint	Host;
+	uint	Link;
+	struct  LPB     *LpbP;
+};
+
+struct	RupReq
+{
+	uint	HostNum;
+	uint	RupNum;
+	struct  RUP 	*RupP;
+};
+
+struct	PortReq
+{
+	uint	SysPort;
+	struct  Port 	*PortP;
+};
+
+struct  StreamInfo
+{
+	uint	SysPort;
+#if 0
+	queue_t RQueue;
+	queue_t WQueue;
+#else
+	int RQueue;
+	int WQueue;
+#endif
+};
+
+struct	HostReq
+{
+	uint	HostNum;
+	struct  Host 	*HostP;
+};
+
+struct	HostDpRam
+{
+	uint	HostNum;
+	struct	DpRam	*DpRamP;
+};
+
+struct	DebugCtrl
+{
+	uint	SysPort;
+	uint	Debug;
+	uint	Wait;
+};
+
+struct	MapInfo
+{
+	uint	FirstPort;	/* 8 ports, starting from this (tty) number */
+	uint	RtaUnique;	/* reside on this RTA (unique number) */
+};
+
+struct	MapIn
+{
+	uint	NumEntries;		/* How many port sets are we mapping? */
+	struct  MapInfo	*MapInfoP;	/* Pointer to (user space) info */
+};
+
+struct  SendPack
+{
+        unsigned int	PortNum;
+	unsigned char	Len;
+	unsigned char	Data[PKT_MAX_DATA_LEN];
+};
+
+struct SpecialRupCmd
+{
+	struct	PKT		Packet;
+	unsigned short	Host;
+	unsigned short	RupNum;
+};
+
+struct	IdentifyRta
+{
+	ulong	RtaUnique;
+	uchar	ID;
+};
+
+struct	KillNeighbour
+{
+	ulong	UniqueNum;
+	uchar	Link;
+};
+
+struct rioVersion {
+    char        version[MAX_VERSION_LEN];
+    char        relid[MAX_VERSION_LEN];
+    int         buildLevel;
+    char        buildDate[MAX_VERSION_LEN];
+};
+
+
+/*
+**	RIOC commands are for the daemon type operations
+**
+** 09.12.1998 ARG - ESIL 0776 part fix
+** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a
+** #ifndef here first.
+** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now
+** allowed to be used by customers.
+*/
+#ifndef RIOC
+#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
+#endif
+
+/*
+** Boot stuff
+*/
+#define	RIO_GET_TABLE     (RIOC | 100)
+#define RIO_PUT_TABLE     (RIOC | 101)
+#define RIO_ASSIGN_RTA    (RIOC | 102)
+#define RIO_DELETE_RTA    (RIOC | 103)
+#define	RIO_HOST_FOAD	  (RIOC | 104)
+#define	RIO_QUICK_CHECK	  (RIOC | 105)
+#define RIO_SIGNALS_ON    (RIOC | 106)
+#define RIO_SIGNALS_OFF   (RIOC | 107)
+#define	RIO_CHANGE_NAME   (RIOC | 108)
+#define RIO_DOWNLOAD      (RIOC | 109)
+#define	RIO_GET_LOG	  (RIOC | 110)
+#define	RIO_SETUP_PORTS   (RIOC | 111)
+#define RIO_ALL_MODEM     (RIOC | 112)
+
+/*
+** card state, debug stuff
+*/
+#define	RIO_NUM_HOSTS	  (RIOC | 120)
+#define	RIO_HOST_LPB	  (RIOC | 121)
+#define	RIO_HOST_RUP	  (RIOC | 122)
+#define	RIO_HOST_PORT	  (RIOC | 123)
+#define	RIO_PARMS 	  (RIOC | 124)
+#define RIO_HOST_REQ	  (RIOC | 125)
+#define	RIO_READ_CONFIG	  (RIOC | 126)
+#define	RIO_SET_CONFIG	  (RIOC | 127)
+#define	RIO_VERSID	  (RIOC | 128)
+#define	RIO_FLAGS	  (RIOC | 129)
+#define	RIO_SETDEBUG	  (RIOC | 130)
+#define	RIO_GETDEBUG	  (RIOC | 131)
+#define	RIO_READ_LEVELS   (RIOC | 132)
+#define	RIO_SET_FAST_BUS  (RIOC | 133)
+#define	RIO_SET_SLOW_BUS  (RIOC | 134)
+#define	RIO_SET_BYTE_MODE (RIOC | 135)
+#define	RIO_SET_WORD_MODE (RIOC | 136)
+#define RIO_STREAM_INFO   (RIOC | 137)
+#define	RIO_START_POLLER  (RIOC | 138)
+#define	RIO_STOP_POLLER   (RIOC | 139)
+#define	RIO_LAST_ERROR    (RIOC | 140)
+#define	RIO_TICK	  (RIOC | 141)
+#define	RIO_TOCK	  (RIOC | 241)	/* I did this on purpose, you know. */
+#define	RIO_SEND_PACKET   (RIOC | 142)
+#define	RIO_SET_BUSY	  (RIOC | 143)
+#define	SPECIAL_RUP_CMD   (RIOC | 144)
+#define	RIO_FOAD_RTA      (RIOC | 145)
+#define	RIO_ZOMBIE_RTA    (RIOC | 146)
+#define RIO_IDENTIFY_RTA  (RIOC | 147)
+#define RIO_KILL_NEIGHBOUR (RIOC | 148)
+#define RIO_DEBUG_MEM     (RIOC | 149)
+/*
+** 150 - 167 used.....   See below
+*/
+#define RIO_GET_PORT_SETUP (RIOC | 168)
+#define RIO_RESUME        (RIOC | 169)
+#define	RIO_MESG	(RIOC | 170)
+#define	RIO_NO_MESG	(RIOC | 171)
+#define	RIO_WHAT_MESG	(RIOC | 172)
+#define RIO_HOST_DPRAM	(RIOC | 173)
+#define RIO_MAP_B50_TO_50	(RIOC | 174)
+#define RIO_MAP_B50_TO_57600	(RIOC | 175)
+#define RIO_MAP_B110_TO_110	(RIOC | 176)
+#define RIO_MAP_B110_TO_115200	(RIOC | 177)
+#define RIO_GET_PORT_PARAMS	(RIOC | 178)
+#define RIO_SET_PORT_PARAMS	(RIOC | 179)
+#define RIO_GET_PORT_TTY	(RIOC | 180)
+#define RIO_SET_PORT_TTY	(RIOC | 181)
+#define RIO_SYSLOG_ONLY	(RIOC | 182)
+#define RIO_SYSLOG_CONS	(RIOC | 183)
+#define RIO_CONS_ONLY	(RIOC | 184)
+#define RIO_BLOCK_OPENS	(RIOC | 185)
+
+/*
+** 02.03.1999 ARG - ESIL 0820 fix :
+** RIOBootMode is no longer use by the driver, so these ioctls
+** are now obsolete :
+**
+#define RIO_GET_BOOT_MODE	(RIOC | 186)
+#define RIO_SET_BOOT_MODE	(RIOC | 187)
+**
+*/
+
+#define RIO_MEM_DUMP	(RIOC | 189)
+#define RIO_READ_REGISTER	(RIOC | 190)
+#define RIO_GET_MODTYPE	(RIOC | 191)
+#define RIO_SET_TIMER	(RIOC | 192)
+#define RIO_READ_CHECK	(RIOC | 196)
+#define RIO_WAITING_FOR_RESTART	(RIOC | 197)
+#define RIO_BIND_RTA	(RIOC | 198)
+#define RIO_GET_BINDINGS	(RIOC | 199)
+#define RIO_PUT_BINDINGS	(RIOC | 200)
+
+#define	RIO_MAKE_DEV		(RIOC | 201)
+#define	RIO_MINOR		(RIOC | 202)
+
+#define	RIO_IDENTIFY_DRIVER	(RIOC | 203)
+#define	RIO_DISPLAY_HOST_CFG	(RIOC | 204)
+
+
+/*
+** MAKE_DEV / MINOR stuff
+*/
+#define	RIO_DEV_DIRECT		0x0000
+#define	RIO_DEV_MODEM		0x0200
+#define	RIO_DEV_XPRINT		0x0400
+#define	RIO_DEV_MASK		0x0600
+
+/*
+** port management, xprint stuff
+*/
+#define	rIOCN(N)	(RIOC|(N))
+#define	rIOCR(N,T)	(RIOC|(N))
+#define	rIOCW(N,T)	(RIOC|(N))
+
+#define	RIO_GET_XP_ON     rIOCR(150,char[16])	/* start xprint string */
+#define	RIO_SET_XP_ON     rIOCW(151,char[16])
+#define	RIO_GET_XP_OFF    rIOCR(152,char[16])	/* finish xprint string */
+#define	RIO_SET_XP_OFF    rIOCW(153,char[16])
+#define	RIO_GET_XP_CPS    rIOCR(154,int)	/* xprint CPS */
+#define	RIO_SET_XP_CPS    rIOCW(155,int)
+#define RIO_GET_IXANY     rIOCR(156,int)	/* ixany allowed? */
+#define RIO_SET_IXANY     rIOCW(157,int)
+#define RIO_SET_IXANY_ON  rIOCN(158)		/* allow ixany */
+#define RIO_SET_IXANY_OFF rIOCN(159)		/* disallow ixany */
+#define RIO_GET_MODEM     rIOCR(160,int)	/* port is modem/direct line? */
+#define RIO_SET_MODEM     rIOCW(161,int)
+#define RIO_SET_MODEM_ON  rIOCN(162)		/* port is a modem */
+#define RIO_SET_MODEM_OFF rIOCN(163)		/* port is direct */
+#define RIO_GET_IXON      rIOCR(164,int)	/* ixon allowed? */
+#define RIO_SET_IXON      rIOCW(165,int)
+#define RIO_SET_IXON_ON   rIOCN(166)		/* allow ixon */
+#define RIO_SET_IXON_OFF  rIOCN(167)		/* disallow ixon */
+
+#define RIO_GET_SIVIEW	  ((('s')<<8) | 106)	/* backwards compatible with SI */
+
+#define	RIO_IOCTL_UNKNOWN	-2
+
+#endif
diff --git a/drivers/char/rio/data.h b/drivers/char/rio/data.h
new file mode 100644
index 0000000..dabc2d1
--- /dev/null
+++ b/drivers/char/rio/data.h
@@ -0,0 +1,40 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: data.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)data.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_datadex__
+#define __rio_datadex__
+
+#ifndef lint
+static char *_data_h_sccs_ = "@(#)data.h	1.2";
+#endif
+
+#endif
diff --git a/drivers/char/rio/debug.h b/drivers/char/rio/debug.h
new file mode 100644
index 0000000..b6e0d09
--- /dev/null
+++ b/drivers/char/rio/debug.h
@@ -0,0 +1,39 @@
+/*
+** File:		debug.h
+**
+** Author:		David Dix
+**
+** Created:		12th March 1993
+**
+** Last modified:	93/04/27
+**
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _debug_h_
+#define _debug_h_
+
+
+#if defined(DCIRRUS)
+#define	DBPACKET(pkt, opt, str, chn) 	debug_packet((pkt), (opt), (str), (chn))
+#else
+#define	DBPACKET(pkt, opt, str, c)
+#endif	/* DCIRRUS */
+
+
+#endif	/* _debug_h_ */
diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h
new file mode 100644
index 0000000..2e7309e
--- /dev/null
+++ b/drivers/char/rio/defaults.h
@@ -0,0 +1,59 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******                     D E F A U L T S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_defaults_h_sccs = "@(#)defaults.h	1.1" ;
+#endif
+#endif
+
+
+#define MILLISECOND           (int) (1000/64)   /* 15.625 low ticks */
+#define SECOND                (int) 15625       /* Low priority ticks */
+
+#ifdef RTA
+#define RX_LIMIT       (ushort) 3
+#endif
+#ifdef HOST
+#define RX_LIMIT       (ushort) 1
+#endif
+
+#define LINK_TIMEOUT          (int) (POLL_PERIOD / 2)
+
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/eisa.h b/drivers/char/rio/eisa.h
new file mode 100644
index 0000000..59371b0
--- /dev/null
+++ b/drivers/char/rio/eisa.h
@@ -0,0 +1,104 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: eisa.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)eisa.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_eisa_h__
+#define __rio_eisa_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_eisa_h_sccs_ = "@(#)eisa.h	1.2";
+#endif
+#endif
+
+/*
+** things to do with the EISA bus
+*/
+
+#define RIO_EISA_STRING_ADDRESS 	0xfffd9	/* where EISA is stored */
+
+#define	RIO_MAX_EISA_SLOTS		16	/* how many EISA slots? */
+
+#define	RIO_EISA_IDENT			0x984D	/* Specialix */
+#define	RIO_EISA_PRODUCT_CODE		0x14	/* Code 14 */
+#define	RIO_EISA_ENABLE_BIT		0x01	/* To enable card */
+
+#define	EISA_MEMORY_BASE_LO		0xC00	/* A16-A23 */
+#define	EISA_MEMORY_BASE_HI		0xC01	/* A24-A31 */
+#define	EISA_INTERRUPT_VEC		0xC02	/* see below */
+#define	EISA_CONTROL_PORT		0xC02	/* see below */
+#define	EISA_INTERRUPT_RESET		0xC03	/* read to clear IRQ */
+
+#define	EISA_PRODUCT_IDENT_LO		0xC80	/* where RIO_EISA_IDENT is */
+#define	EISA_PRODUCT_IDENT_HI		0xC81
+#define	EISA_PRODUCT_NUMBER		0xC82   /* where PROD_CODE is */
+#define	EISA_REVISION_NUMBER		0xC83	/* revision (1dp) */
+#define	EISA_ENABLE			0xC84	/* set LSB to enable card */
+#define	EISA_UNIQUE_NUM_0		0xC88	/* vomit */
+#define	EISA_UNIQUE_NUM_1		0xC8A
+#define	EISA_UNIQUE_NUM_2		0xC90	/* bit strangely arranged */
+#define	EISA_UNIQUE_NUM_3		0xC92
+#define	EISA_MANUF_YEAR			0xC98	/* when */
+#define	EISA_MANUF_WEEK			0xC9A	/* more when */
+
+#define	EISA_TP_BOOT_FROM_RAM	0x01
+#define	EISA_TP_BOOT_FROM_LINK	0x00
+#define	EISA_TP_FAST_LINKS	0x02
+#define	EISA_TP_SLOW_LINKS	0x00
+#define	EISA_TP_BUS_ENABLE	0x04
+#define	EISA_TP_BUS_DISABLE	0x00
+#define	EISA_TP_RUN		0x08
+#define	EISA_TP_RESET		0x00
+#define	EISA_POLLED		0x00
+#define	EISA_IRQ_3		0x30
+#define	EISA_IRQ_4		0x40
+#define	EISA_IRQ_5		0x50
+#define	EISA_IRQ_6		0x60
+#define	EISA_IRQ_7		0x70
+#define	EISA_IRQ_9		0x90
+#define	EISA_IRQ_10		0xA0
+#define	EISA_IRQ_11		0xB0
+#define	EISA_IRQ_12		0xC0
+#define	EISA_IRQ_14		0xE0
+#define	EISA_IRQ_15		0xF0
+
+#define	EISA_INTERRUPT_MASK	0xF0
+#define	EISA_CONTROL_MASK	0x0F
+
+#define	RIO_EISA_DEFAULT_MODE	EISA_TP_SLOW_LINKS
+
+#define	RIOEisaToIvec(X)	(uchar )((uchar)((X) & EISA_INTERRUPT_MASK)>>4)
+
+#define	INBZ(z,x)	inb(((z)<<12) | (x))
+#define	OUTBZ(z,x,y)	outb((((z)<<12) | (x)), y)
+
+#endif /* __rio_eisa_h__ */
diff --git a/drivers/char/rio/enable.h b/drivers/char/rio/enable.h
new file mode 100644
index 0000000..8e9a419e
--- /dev/null
+++ b/drivers/char/rio/enable.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+ *******                                                              *******
+ *******               E N A B L E   H E A D E R S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_enable_h_sccs = "@(#)enable.h	1.1" ;
+#endif
+#endif
+
+
+#define ENABLE_LTT  TRUE
+#define ENABLE_LRT  TRUE
+
+
+/*********** end of file ***********/
+
+
diff --git a/drivers/char/rio/error.h b/drivers/char/rio/error.h
new file mode 100644
index 0000000..229438e
--- /dev/null
+++ b/drivers/char/rio/error.h
@@ -0,0 +1,85 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******     E R R O R  H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+/* static char *_rio_error_h_sccs = "@(#)error.h	1.3"; */
+#endif
+
+#define E_NO_ERROR                       ((ushort) 0)
+#define E_PROCESS_NOT_INIT               ((ushort) 1)
+#define E_LINK_TIMEOUT                   ((ushort) 2)
+#define E_NO_ROUTE                       ((ushort) 3)
+#define E_CONFUSED                       ((ushort) 4)
+#define E_HOME                           ((ushort) 5)
+#define E_CSUM_FAIL                      ((ushort) 6)
+#define E_DISCONNECTED                   ((ushort) 7)
+#define E_BAD_RUP                        ((ushort) 8)
+#define E_NO_VIRGIN                      ((ushort) 9)
+#define E_BOOT_RUP_BUSY                  ((ushort) 10)
+
+
+
+    /*************************************************
+     * Parsed to mem_halt()
+     ************************************************/
+#define E_CHANALLOC                      ((ushort) 0x80)
+#define E_POLL_ALLOC                     ((ushort) 0x81)
+#define E_LTTWAKE                        ((ushort) 0x82)
+#define E_LTT_ALLOC                      ((ushort) 0x83)
+#define E_LRT_ALLOC                      ((ushort) 0x84)
+#define E_CIRRUS                         ((ushort) 0x85)
+#define E_MONITOR                        ((ushort) 0x86)
+#define E_PHB_ALLOC                      ((ushort) 0x87)
+#define E_ARRAY_ALLOC                    ((ushort) 0x88)
+#define E_QBUF_ALLOC                     ((ushort) 0x89)
+#define E_PKT_ALLOC                      ((ushort) 0x8a)
+#define E_GET_TX_Q_BUF                   ((ushort) 0x8b)
+#define E_GET_RX_Q_BUF                   ((ushort) 0x8c)
+#define E_MEM_OUT                        ((ushort) 0x8d)
+#define E_MMU_INIT                       ((ushort) 0x8e)
+#define E_LTT_INIT                       ((ushort) 0x8f)
+#define E_LRT_INIT                       ((ushort) 0x90)
+#define E_LINK_RUN                       ((ushort) 0x91)
+#define E_MONITOR_ALLOC                  ((ushort) 0x92)
+#define E_MONITOR_INIT                   ((ushort) 0x93)
+#define E_POLL_INIT                      ((ushort) 0x94)
+
+
+/*********** end of file ***********/
+
+
+
diff --git a/drivers/char/rio/errors.h b/drivers/char/rio/errors.h
new file mode 100644
index 0000000..f920b9f
--- /dev/null
+++ b/drivers/char/rio/errors.h
@@ -0,0 +1,104 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: errors.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)errors.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_errors_h__
+#define	__rio_errors_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_errors_h_sccs_ = "@(#)errors.h	1.2";
+#endif
+#endif
+
+/*
+** error codes
+*/
+
+#define	NOTHING_WRONG_AT_ALL		0
+#define	BAD_CHARACTER_IN_NAME		1
+#define	TABLE_ENTRY_ISNT_PROPERLY_NULL	2
+#define	UNKNOWN_HOST_NUMBER		3
+#define	ZERO_RTA_ID			4
+#define	BAD_RTA_ID			5
+#define	DUPLICATED_RTA_ID		6
+#define	DUPLICATE_UNIQUE_NUMBER		7
+#define	BAD_TTY_NUMBER			8
+#define	TTY_NUMBER_IN_USE		9
+#define	NAME_USED_TWICE			10
+#define	HOST_ID_NOT_ZERO		11
+#define	BOOT_IN_PROGRESS		12
+#define	COPYIN_FAILED			13
+#define	HOST_FILE_TOO_LARGE		14
+#define	COPYOUT_FAILED			15
+#define	NOT_SUPER_USER			16
+#define	RIO_ALREADY_POLLING		17
+
+#define	ID_NUMBER_OUT_OF_RANGE		18
+#define PORT_NUMBER_OUT_OF_RANGE	19
+#define	HOST_NUMBER_OUT_OF_RANGE	20
+#define	RUP_NUMBER_OUT_OF_RANGE		21
+#define	TTY_NUMBER_OUT_OF_RANGE		22
+#define	LINK_NUMBER_OUT_OF_RANGE	23
+
+#define	HOST_NOT_RUNNING		24
+#define	IOCTL_COMMAND_UNKNOWN		25
+#define	RIO_SYSTEM_HALTED		26
+#define	WAIT_FOR_DRAIN_BROKEN		27
+#define	PORT_NOT_MAPPED_INTO_SYSTEM	28
+#define	EXCLUSIVE_USE_SET		29
+#define	WAIT_FOR_NOT_CLOSING_BROKEN	30
+#define	WAIT_FOR_PORT_TO_OPEN_BROKEN	31
+#define	WAIT_FOR_CARRIER_BROKEN		32
+#define	WAIT_FOR_NOT_IN_USE_BROKEN	33
+#define	WAIT_FOR_CAN_ADD_COMMAND_BROKEN	34
+#define	WAIT_FOR_ADD_COMMAND_BROKEN	35
+#define	WAIT_FOR_NOT_PARAM_BROKEN	36
+#define	WAIT_FOR_RETRY_BROKEN		37
+#define	HOST_HAS_ALREADY_BEEN_BOOTED	38
+#define	UNIT_IS_IN_USE			39
+#define	COULDNT_FIND_ENTRY		40
+#define	RTA_UNIQUE_NUMBER_ZERO		41
+#define	CLOSE_COMMAND_FAILED		42
+#define	WAIT_FOR_CLOSE_BROKEN		43
+#define	CPS_VALUE_OUT_OF_RANGE		44
+#define	ID_ALREADY_IN_USE		45
+#define	SIGNALS_ALREADY_SET		46
+#define	NOT_RECEIVING_PROCESS		47
+#define	RTA_NUMBER_WRONG		48
+#define NO_SUCH_PRODUCT			49
+#define	HOST_SYSPORT_BAD		50
+#define	ID_NOT_TENTATIVE		51
+#define XPRINT_CPS_OUT_OF_RANGE		52
+#define	NOT_ENOUGH_CORE_FOR_PCI_COPY	53
+
+
+#endif /* __rio_errors_h__ */
diff --git a/drivers/char/rio/formpkt.h b/drivers/char/rio/formpkt.h
new file mode 100644
index 0000000..a8b65ae
--- /dev/null
+++ b/drivers/char/rio/formpkt.h
@@ -0,0 +1,154 @@
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******         F O R M   P A C K E T   H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _formpkt_h
+#define _formpkt_h 1
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_formpkt_h_sccs = "@(#)formpkt.h	1.1" ;
+#endif
+#endif
+
+typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1 ;
+struct FORM_BOOT_PKT_1 {
+                           ushort pkt_number ;
+                           ushort pkt_total ;
+                           ushort boot_top ;
+                       } ;
+
+typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2 ;
+struct FORM_BOOT_PKT_2 {
+                           ushort pkt_number ;
+                           char   boot_data[10] ;
+                       } ;
+
+
+typedef struct FORM_ATTACH_RTA   FORM_ATTACH_RTA ;
+struct FORM_ATTACH_RTA  {
+                       char    cmd_code ;
+                       char    booter_serial[4] ;
+                       char    booter_link ;
+                       char    bootee_serial[4] ;
+                       char    bootee_link ;
+                   } ;
+
+
+typedef struct FORM_BOOT_ID   FORM_BOOT_ID ;
+struct FORM_BOOT_ID  {
+                       char    cmd_code ;
+                       char    bootee_serial[4] ;
+                       char    bootee_prod_id ;
+                       char    bootee_link ;
+                   } ;
+
+
+
+typedef struct FORM_ROUTE_1   FORM_ROUTE_1 ;
+struct FORM_ROUTE_1 {
+                        char     cmd_code ;
+                        char     pkt_number ;
+                        char     total_in_sequence ;
+                        char     unit_id ;
+                        char     host_unit_id ;
+                    } ;
+
+typedef struct FORM_ROUTE_2   FORM_ROUTE_2 ;
+struct FORM_ROUTE_2 {
+                        char   cmd_code ;
+                        char   pkt_number ;
+                        char   total_in_sequence ;
+                        char   route_data[9] ;
+                    } ;
+
+typedef struct FORM_ROUTE_REQ   FORM_ROUTE_REQ ;
+struct FORM_ROUTE_REQ {
+                          char   cmd_code ;
+                          char   pkt_number ;
+                          char   total_in_sequence ;
+                          char   route_data[10] ;
+                      } ;
+
+
+typedef struct FORM_ERROR   FORM_ERROR ;
+struct FORM_ERROR {
+                        char   cmd_code ;
+                        char   error_code ;
+
+                    } ;
+
+typedef struct FORM_STATUS   FORM_STATUS ;
+struct FORM_STATUS {
+                        char   cmd_code ;
+                        char   status_code ;
+                        char   last_packet_valid ;
+                        char   tx_buffer ;
+                        char   rx_buffer ;
+                        char   port_status ;
+                        char   phb_status ;
+                    } ;
+
+
+typedef struct FORM_LINK_STATUS   FORM_LINK_STATUS ;
+struct FORM_LINK_STATUS {
+                        char    cmd_code ;
+                        char    status_code ;
+                        char    link_number ;
+                        ushort  rx_errors ;
+                        ushort  tx_errors ;
+                        ushort  csum_errors ;
+                        ushort  disconnects ;
+                    } ;
+
+
+
+typedef struct FORM_PARTITION FORM_PARTITION ;
+struct FORM_PARTITION {
+                        char    cmd_code ;
+                        char    status_code ;
+                        char    port_number ;
+                        char    tx_max ;
+                        char    rx_max ;
+                        char    rx_limit ;
+                      } ;
+
+
+#endif
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
new file mode 100644
index 0000000..e8f3860
--- /dev/null
+++ b/drivers/char/rio/func.h
@@ -0,0 +1,154 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: func.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)func.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __func_h_def
+#define __func_h_def
+
+#include <linux/kdev_t.h>
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_func_h_sccs_ = "@(#)func.h	1.3";
+#endif
+#endif
+
+/* rioboot.c */
+int RIOBootCodeRTA(struct rio_info *, struct DownLoad *);
+int RIOBootCodeHOST(struct rio_info *, register struct DownLoad *);
+int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
+void msec_timeout(struct Host *);
+int RIOBootRup(struct rio_info *, uint, struct Host *, struct PKT *);
+int RIOBootOk(struct rio_info *,struct Host *, ulong);
+int RIORtaBound(struct rio_info *, uint); 
+void FillSlot(int, int, uint, struct Host *);
+
+/* riocmd.c */
+int RIOFoadRta(struct Host *, struct Map *);
+int RIOZombieRta(struct Host *, struct Map *);
+int RIOCommandRta(struct rio_info *, uint, int (* func)( struct Host *, 
+								struct Map *));
+int RIOIdentifyRta(struct rio_info *, caddr_t); 
+int RIOKillNeighbour(struct rio_info *, caddr_t);
+int RIOSuspendBootRta(struct Host *, int, int);
+int RIOFoadWakeup(struct rio_info *);
+struct CmdBlk * RIOGetCmdBlk(void);
+void RIOFreeCmdBlk(struct CmdBlk *);
+int RIOQueueCmdBlk(struct Host *, uint, struct CmdBlk *);
+void RIOPollHostCommands(struct rio_info *, struct Host *);
+int RIOWFlushMark(int, struct CmdBlk *);
+int RIORFlushEnable(int, struct CmdBlk *);
+int RIOUnUse(int, struct CmdBlk *);
+void ShowPacket(uint, struct PKT *);
+
+/* rioctrl.c */
+int copyin(int, caddr_t, int);
+int riocontrol(struct rio_info *, dev_t,int,caddr_t,int); 
+int RIOPreemptiveCmd(struct rio_info *,struct Port *,uchar);
+
+/* rioinit.c */
+void rioinit(struct rio_info *, struct RioHostInfo *);
+void RIOInitHosts(struct rio_info *, struct RioHostInfo *);
+void RIOISAinit(struct rio_info *,int);
+int RIODoAT(struct rio_info *, int, int);
+caddr_t RIOCheckForATCard(int);
+int RIOAssignAT(struct rio_info *, int, caddr_t, int);
+int RIOBoardTest(paddr_t, caddr_t, uchar, int);
+void RIOAllocDataStructs(struct rio_info *);
+void RIOSetupDataStructs(struct rio_info *);
+int RIODefaultName(struct rio_info *, struct Host *, uint);
+struct rioVersion * RIOVersid(void);
+int RIOMapin(paddr_t, int, caddr_t *);
+void RIOMapout(paddr_t, long, caddr_t);
+void RIOHostReset(uint, volatile struct DpRam *, uint);
+
+/* riointr.c */
+void RIOTxEnable(char *);
+void RIOServiceHost(struct rio_info *, struct Host *, int);
+int riotproc(struct rio_info *, register struct ttystatics *, int, int);
+
+/* rioparam.c */
+int RIOParam(struct Port *, int, int, int);
+int RIODelay(struct Port *PortP, int);
+int RIODelay_ni(struct Port *PortP, int);
+void ms_timeout(struct Port *);
+int can_add_transmit(struct PKT **, struct Port *);
+void add_transmit(struct Port *);
+void put_free_end(struct Host *, struct PKT *);
+int can_remove_receive(struct PKT **, struct Port *);
+void remove_receive(struct Port *);
+
+/* rioroute.c */
+int RIORouteRup(struct rio_info *, uint, struct Host *, struct PKT *);
+void RIOFixPhbs(struct rio_info *, struct Host *, uint); 
+uint GetUnitType(uint);
+int RIOSetChange(struct rio_info *);
+int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *);
+
+
+/* riotty.c */
+
+int riotopen(struct tty_struct * tty, struct file * filp);
+int riotclose(void  *ptr);
+int riotioctl(struct rio_info *, struct tty_struct *, register int, register caddr_t); 
+void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg);
+
+/* riotable.c */
+int RIONewTable(struct rio_info *);
+int RIOApel(struct rio_info *);
+int RIODeleteRta(struct rio_info *, struct Map *);
+int RIOAssignRta(struct rio_info *, struct Map *);
+int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *);
+int RIOChangeName(struct rio_info *, struct Map*);
+
+#if 0
+/* riodrvr.c */
+struct rio_info * rio_install(struct RioHostInfo *);
+int rio_uninstall(register struct rio_info *);
+int rio_open(struct rio_info *, int, struct file *);
+int rio_close(struct rio_info *, struct file *);
+int rio_read(struct rio_info *, struct file *, char *, int);
+int rio_write(struct rio_info *, struct file *	f, char *, int);
+int rio_ioctl(struct rio_info *, struct file *, int, char *);
+int rio_select(struct rio_info *, struct file *	f, int, struct sel *);
+int	rio_intr(char *);
+int rio_isr_thread(char  *);
+struct rio_info * rio_info_store( int cmd, struct rio_info * p);
+#endif
+
+extern int    rio_pcicopy(char *src, char *dst, int n);
+extern int rio_minor (struct tty_struct *tty);
+extern int rio_ismodem (struct tty_struct *tty);
+extern void rio_udelay (int usecs);
+
+extern void rio_start_card_running (struct Host * HostP);
+
+#endif	/* __func_h_def */
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
new file mode 100644
index 0000000..4c65963
--- /dev/null
+++ b/drivers/char/rio/host.h
@@ -0,0 +1,134 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: host.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)host.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_host_h__
+#define __rio_host_h__
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_host_h_sccs_ = "@(#)host.h	1.2";
+#endif
+#endif
+
+/*
+** the host structure - one per host card in the system.
+*/
+
+#define	MAX_EXTRA_UNITS	64
+
+/*
+**    Host data structure. This is used for the software equiv. of
+**    the host.
+*/
+struct    Host
+{
+    uchar             	    Type;      /* RIO_EISA, RIO_MCA, ... */
+    uchar             	    Ivec;      /* POLLED or ivec number */
+    uchar             	    Mode;      /* Control stuff */
+    uchar                   Slot;      /* Slot */
+    volatile caddr_t        Caddr;     /* KV address of DPRAM */
+    volatile struct DpRam  *CardP;     /* KV address of DPRAM, with overlay */
+    paddr_t          	    PaddrP;    /* Phys. address of DPRAM */
+    char                    Name[MAX_NAME_LEN];  /* The name of the host */
+    uint            	    UniqueNum; /* host unique number */
+    spinlock_t	            HostLock;  /* Lock structure for MPX */
+    /*struct pci_devinfo    PciDevInfo; *//* PCI Bus/Device/Function stuff */
+    /*struct lockb	    HostLock;  *//* Lock structure for MPX */
+    uint                    WorkToBeDone; /* set to true each interrupt */
+    uint                    InIntr;    /* Being serviced? */
+    uint                    IntSrvDone;/* host's interrupt has been serviced */
+    int			    (*Copy)( caddr_t, caddr_t, int ); /* copy func */
+    struct timer_list timer;
+    /*
+    **               I M P O R T A N T !
+    **
+    ** The rest of this data structure is cleared to zero after
+    ** a RIO_HOST_FOAD command.
+    */
+    
+    ulong                   Flags;     /* Whats going down */
+#define RC_WAITING            0
+#define RC_STARTUP            1
+#define RC_RUNNING            2
+#define RC_STUFFED            3
+#define RC_SOMETHING          4
+#define RC_SOMETHING_NEW      5
+#define RC_SOMETHING_ELSE     6
+#define RC_READY              7
+#define RUN_STATE             7
+/*
+** Boot mode applies to the way in which hosts in this system will
+** boot RTAs
+*/
+#define RC_BOOT_ALL           0x8	/* Boot all RTAs attached */
+#define RC_BOOT_OWN           0x10	/* Only boot RTAs bound to this system */
+#define RC_BOOT_NONE          0x20	/* Don't boot any RTAs (slave mode) */
+
+    struct Top		    Topology[LINKS_PER_UNIT]; /* one per link */
+    struct Map              Mapping[MAX_RUP];     /* Mappings for host */
+    struct PHB		    *PhbP;                /* Pointer to the PHB array */
+    ushort           	    *PhbNumP;             /* Ptr to Number of PHB's */
+    struct LPB 	            *LinkStrP ;           /* Link Structure Array */
+    struct RUP       	    *RupP;                /* Sixteen real rups here */
+    struct PARM_MAP  	    *ParmMapP;            /* points to the parmmap */
+    uint                    ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */
+    uint                    NumExtraBooted;       /* how many of the above */
+    /*
+    ** Twenty logical rups.
+    ** The first sixteen are the real Rup entries (above), the last four
+    ** are the link RUPs.
+    */
+    struct UnixRup	    UnixRups[MAX_RUP+LINKS_PER_UNIT];
+	int				timeout_id;	/* For calling 100 ms delays */
+	int				timeout_sem;/* For calling 100 ms delays */
+    long locks; /* long req'd for set_bit --RR */
+    char             	    ____end_marker____;
+};
+#define Control      CardP->DpControl
+#define SetInt       CardP->DpSetInt
+#define ResetTpu     CardP->DpResetTpu
+#define ResetInt     CardP->DpResetInt
+#define Signature    CardP->DpSignature
+#define Sram1        CardP->DpSram1
+#define Sram2        CardP->DpSram2
+#define Sram3        CardP->DpSram3
+#define Scratch      CardP->DpScratch
+#define __ParmMapR   CardP->DpParmMapR
+#define SLX          CardP->DpSlx
+#define Revision     CardP->DpRevision
+#define Unique       CardP->DpUnique
+#define Year         CardP->DpYear
+#define Week         CardP->DpWeek
+
+#define RIO_DUMBPARM 0x0860    /* what not to expect */
+
+#endif
diff --git a/drivers/char/rio/hosthw.h b/drivers/char/rio/hosthw.h
new file mode 100644
index 0000000..f6f31ec
--- /dev/null
+++ b/drivers/char/rio/hosthw.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                H O S T      H A R D W A R E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_hosthw_h_sccs = "@(#)hosthw.h	1.2" ;
+#endif
+#endif
+
+#define SET_OTHER_INTERRUPT  ( (volatile u_short *) 0x7c80 )
+#define SET_EISA_INTERRUPT  ( (volatile u_short *) 0x7ef0 )
+
+#define EISA_HOST    0x30
+#define AT_HOST      0xa0
+#define MCA_HOST     0xb0
+#define PCI_HOST     0xd0
+
+#define PRODUCT_MASK 0xf0
+
+
+/*********** end of file ***********/
+
+
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h
new file mode 100644
index 0000000..9722503
--- /dev/null
+++ b/drivers/char/rio/link.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L I N K
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _link_h
+#define _link_h 1
+
+#ifndef lint
+#ifdef SCCS_LABELS
+/* static char *_rio_link_h_sccs = "@(#)link.h	1.15"; */
+#endif
+#endif
+
+
+
+/*************************************************
+ * Define the Link Status stuff
+ ************************************************/
+#define LRT_ACTIVE         ((ushort) 0x01)
+#define LRT_SPARE1         ((ushort) 0x02)
+#define INTRO_RCVD         ((ushort) 0x04)
+#define FORCED_DISCONNECT  ((ushort) 0x08)
+#define LRT_SPARE2	   ((ushort) 0x80)
+
+#define TOP_OF_RTA_RAM     ((ushort) 0x7000)
+#define HOST_SERIAL_POINTER (unsigned char **) (TOP_OF_RTA_RAM - 2 * sizeof (ushort))
+
+/* Flags for ltt_status */
+#define  WAITING_ACK		(ushort) 0x0001
+#define  DATA_SENT		(ushort) 0x0002
+#define  WAITING_RUP		(ushort) 0x0004
+#define  WAITING_RETRY		(ushort) 0x0008
+#define  WAITING_TOPOLOGY	(ushort) 0x0010
+#define  SEND_SYNC		(ushort) 0x0020
+#define  FOAD_THIS_LINK		(ushort) 0x0040
+#define  REQUEST_SYNC		(ushort) 0x0080
+#define  REMOTE_DYING		(ushort) 0x0100
+#define  DIE_NOW		(ushort) 0x0200
+
+/* Boot request stuff */
+#define BOOT_REQUEST       ((ushort) 0)    /* Request for a boot */
+#define BOOT_ABORT         ((ushort) 1)    /* Abort a boot */
+#define BOOT_SEQUENCE      ((ushort) 2)    /* Packet with the number of packets
+                                              and load address */
+#define BOOT_COMPLETED     ((ushort) 3)    /* Boot completed */
+
+/* States that a link can be in */
+#define	LINK_DISCONNECTED  ((ushort) 0)    /* Disconnected */
+#define LINK_BOOT1         ((ushort) 1)    /* Trying to send 1st stage boot */
+#define LINK_BOOT2         ((ushort) 2)    /* Trying to send 2nd stage boot */
+#define LINK_BOOT2WAIT     ((ushort) 3)    /* Waiting for selftest results */
+#define LINK_BOOT3         ((ushort) 4)    /* Trying to send 3rd stage boots */
+#define LINK_SYNC          ((ushort) 5)    /* Syncing */
+
+#define LINK_INTRO         ((ushort) 10)    /* Introductory packet */
+#define LINK_SUPPLYID      ((ushort) 11)    /* Trying to supply an ID */
+#define LINK_TOPOLOGY      ((ushort) 12)    /* Send a topology update */
+#define LINK_REQUESTID     ((ushort) 13)    /* Waiting for an ID */
+#define LINK_CONNECTED     ((ushort) 14)    /* Connected */
+
+#define LINK_INTERCONNECT  ((ushort) 20)   /* Subnets interconnected */
+
+#define LINK_SPARE	   ((ushort) 40)
+
+/*
+** Set the default timeout for link communications.
+*/
+#define	LINKTIMEOUT		(400 * MILLISECOND)
+
+/*
+** LED stuff
+*/
+#if defined(RTA)
+#define LED_OFF            ((ushort) 0)    /* LED off */
+#define LED_RED            ((ushort) 1)    /* LED Red */
+#define LED_GREEN          ((ushort) 2)    /* LED Green */
+#define LED_ORANGE         ((ushort) 4)    /* LED Orange */
+#define LED_1TO8_OPEN      ((ushort) 1)    /* Port 1->8 LED on */
+#define LED_9TO16_OPEN     ((ushort) 2)    /* Port 9->16 LED on */
+#define LED_SET_COLOUR(colour)	(link->led = (colour))
+#define LED_OR_COLOUR(colour)	(link->led |= (colour))
+#define LED_TIMEOUT(time)    (link->led_timeout = RioTimePlus(RioTime(),(time)))
+#else
+#define LED_SET_COLOUR(colour)
+#define LED_OR_COLOUR(colour)
+#define LED_TIMEOUT(time)
+#endif /* RTA */
+
+struct LPB {
+               WORD          link_number ;       /* Link Number */
+               Channel_ptr   in_ch ;             /* Link In Channel */
+               Channel_ptr   out_ch ;            /* Link Out Channel */
+#ifdef RTA
+               uchar        stat_led ;          /* Port open leds */
+               uchar        led ;               /* True, light led! */
+#endif
+               BYTE attached_serial[4]; /* Attached serial number */
+               BYTE attached_host_serial[4];
+                                                 /* Serial number of Host who
+                                                    booted the other end */
+               WORD          descheduled ;       /* Currently Descheduled */
+               WORD          state;              /* Current state */
+               WORD          send_poll ;         /* Send a Poll Packet */
+               Process_ptr   ltt_p ;             /* Process Descriptor */
+               Process_ptr   lrt_p ;             /* Process Descriptor */
+               WORD          lrt_status ;        /* Current lrt status */
+               WORD          ltt_status ;        /* Current ltt status */
+               WORD          timeout ;           /* Timeout value */
+               WORD          topology;           /* Topology bits */
+               WORD          mon_ltt ;
+               WORD          mon_lrt ;
+               WORD          WaitNoBoot ;	 /* Secs to hold off booting */
+               PKT_ptr       add_packet_list;    /* Add packets to here */
+               PKT_ptr       remove_packet_list; /* Send packets from here */
+#ifdef RTA
+#ifdef DCIRRUS
+#define    QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1) 
+#else
+#define    QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1) 
+#endif
+               PKT_ptr_ptr   rd_add ;            /* Add a new Packet here */
+               Q_BUF_ptr     rd_add_qb;          /* Pointer to the add Q buf */
+               PKT_ptr_ptr   rd_add_st_qbb ;     /* Pointer to start of the Q's buf */
+               PKT_ptr_ptr   rd_add_end_qbb ;    /* Pointer to the end of the Q's buf */
+               PKT_ptr_ptr   rd_remove ;         /* Remove a Packet here */
+               Q_BUF_ptr     rd_remove_qb ;      /* Pointer to the remove Q buf */
+               PKT_ptr_ptr   rd_remove_st_qbb ;  /* Pointer to the start of the Q buf */
+               PKT_ptr_ptr   rd_remove_end_qbb ; /* Pointer to the end of the Q buf */
+               ushort        pkts_in_q ;         /* Packets in queue */
+#endif
+
+               Channel_ptr   lrt_fail_chan ;     /* Lrt's failure channel */
+               Channel_ptr   ltt_fail_chan ;     /* Ltt's failure channel */
+
+#if defined (HOST) || defined (INKERNEL)
+ /* RUP structure for HOST to driver communications */
+               struct RUP           rup ;              
+#endif
+               struct RUP           link_rup;           /* RUP for the link (POLL,
+                                                    topology etc.) */
+               WORD          attached_link ;     /* Number of attached link */
+               WORD          csum_errors ;       /* csum errors */
+               WORD          num_disconnects ;   /* number of disconnects */
+               WORD          num_sync_rcvd ;     /* # sync's received */
+               WORD          num_sync_rqst ;     /* # sync requests */
+               WORD          num_tx ;            /* Num pkts sent */
+               WORD          num_rx ;            /* Num pkts received */
+               WORD          module_attached;    /* Module tpyes of attached */
+               WORD          led_timeout;        /* LED timeout */
+               WORD          first_port;         /* First port to service */
+               WORD          last_port;          /* Last port to service */
+           } ;
+
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h
new file mode 100644
index 0000000..d53843a
--- /dev/null
+++ b/drivers/char/rio/linux_compat.h
@@ -0,0 +1,122 @@
+/*
+ * (C) 2000 R.E.Wolff@BitWizard.nl
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/interrupt.h>
+
+
+#define disable(oldspl) save_flags (oldspl)
+#define restore(oldspl) restore_flags (oldspl)
+
+#define sysbrk(x) kmalloc ((x),in_interrupt()? GFP_ATOMIC : GFP_KERNEL)
+#define sysfree(p,size) kfree ((p))
+
+#define WBYTE(p,v) writeb(v, &p)
+#define RBYTE(p)   readb (&p)
+#define WWORD(p,v) writew(v, &p)
+#define RWORD(p)   readw(&p)
+#define WINDW(p,v) writew(v, p)
+#define RINDW(p)   readw(p)
+
+#define DEBUG_ALL
+
+#define cprintf printk
+
+#ifdef __KERNEL__
+#define INKERNEL
+#endif
+
+struct ttystatics {
+  struct termios tm;
+};
+
+#define bzero(d, n)         memset((d), 0, (n))
+#define bcopy(src, dest, n) memcpy ((dest), (src), (n))
+
+#define SEM_SIGIGNORE 0x1234
+
+#ifdef DEBUG_SEM
+#define swait(a,b)      printk ("waiting:    " __FILE__ " line %d\n", __LINE__)
+#define ssignal(sem)    printk ("signalling: " __FILE__ " line %d\n", __LINE__)
+
+#define sreset(sem)     printk ("sreset:     " __FILE__ "\n")
+#define sem_init(sem,v) printk ("sreset:     " __FILE__ "\n")
+#endif
+
+
+#define getpid()    (current->pid)
+
+#define QSIZE SERIAL_XMIT_SIZE
+
+#define pseterr(errno) return (- errno)
+
+#define V_CBAUD CBAUD
+
+/* For one reason or another rioboot.c uses delay instead of RIODelay. */
+#define delay(x,y) RIODelay(NULL, y)
+
+extern int rio_debug;
+
+#define RIO_DEBUG_INIT         0x000001
+#define RIO_DEBUG_BOOT         0x000002
+#define RIO_DEBUG_CMD          0x000004
+#define RIO_DEBUG_CTRL         0x000008
+#define RIO_DEBUG_INTR         0x000010
+#define RIO_DEBUG_PARAM        0x000020
+#define RIO_DEBUG_ROUTE        0x000040
+#define RIO_DEBUG_TABLE        0x000080
+#define RIO_DEBUG_TTY          0x000100
+#define RIO_DEBUG_FLOW         0x000200
+#define RIO_DEBUG_MODEMSIGNALS 0x000400
+#define RIO_DEBUG_PROBE        0x000800
+#define RIO_DEBUG_CLEANUP      0x001000
+#define RIO_DEBUG_IFLOW        0x002000
+#define RIO_DEBUG_PFE          0x004000
+#define RIO_DEBUG_REC          0x008000
+#define RIO_DEBUG_SPINLOCK     0x010000
+#define RIO_DEBUG_DELAY        0x020000
+#define RIO_DEBUG_MOD_COUNT    0x040000
+
+/* Copied over from riowinif.h . This is ugly. The winif file declares
+also much other stuff which is incompatible with the headers from
+the older driver. The older driver includes "brates.h" which shadows
+the definitions from Linux, and is incompatible... */
+
+/* RxBaud and TxBaud definitions... */
+#define	RIO_B0			0x00			/* RTS / DTR signals dropped */
+#define	RIO_B50			0x01			/* 50 baud */
+#define	RIO_B75			0x02			/* 75 baud */
+#define	RIO_B110		0x03			/* 110 baud */
+#define	RIO_B134		0x04			/* 134.5 baud */
+#define	RIO_B150		0x05			/* 150 baud */
+#define	RIO_B200		0x06			/* 200 baud */
+#define	RIO_B300		0x07			/* 300 baud */
+#define	RIO_B600		0x08			/* 600 baud */
+#define	RIO_B1200		0x09			/* 1200 baud */
+#define	RIO_B1800		0x0A			/* 1800 baud */
+#define	RIO_B2400		0x0B			/* 2400 baud */
+#define	RIO_B4800		0x0C			/* 4800 baud */
+#define	RIO_B9600		0x0D			/* 9600 baud */
+#define	RIO_B19200		0x0E			/* 19200 baud */
+#define	RIO_B38400		0x0F			/* 38400 baud */
+#define	RIO_B56000		0x10			/* 56000 baud */
+#define	RIO_B57600		0x11			/* 57600 baud */
+#define	RIO_B64000		0x12			/* 64000 baud */
+#define	RIO_B115200		0x13			/* 115200 baud */
+#define	RIO_B2000		0x14			/* 2000 baud */
+
+
diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h
new file mode 100644
index 0000000..a4f7f1f
--- /dev/null
+++ b/drivers/char/rio/list.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L I S T                                 *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls.
+ Date    : 04-Nov-1990
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+ ***************************************************************************/
+
+#ifndef _list_h
+#define _list_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+static char *_rio_list_h_sccs = "@(#)list.h	1.9" ;
+#endif
+#endif
+
+#define PKT_IN_USE    0x1
+
+#ifdef INKERNEL
+
+#define ZERO_PTR (ushort) 0x8000
+#define	CaD	PortP->Caddr
+
+/*
+** We can add another packet to a transmit queue if the packet pointer pointed
+** to by the TxAdd pointer has PKT_IN_USE clear in its address.
+*/
+
+#ifndef linux
+#if defined( MIPS ) && !defined( MIPSEISA )
+/* May the shoes of the Devil dance on your grave for creating this */
+#define   can_add_transmit(PacketP,PortP) \
+          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \
+          & (PKT_IN_USE<<2)))
+
+#elif  defined(MIPSEISA) || defined(nx6000) || \
+       defined(drs6000)  || defined(UWsparc)
+
+#define   can_add_transmit(PacketP,PortP) \
+          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \
+	  & PKT_IN_USE))
+
+#else
+#define   can_add_transmit(PacketP,PortP) \
+          (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,*PortP->TxAdd)) \
+	  & PKT_IN_USE))
+#endif
+
+/*
+** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
+** and then move the TxAdd pointer along one position to point to the next
+** packet pointer. You must wrap the pointer from the end back to the start.
+*/
+#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
+#   define add_transmit(PortP)  \
+	WINDW(PortP->TxAdd,RINDW(PortP->TxAdd) | PKT_IN_USE);\
+	if (PortP->TxAdd == PortP->TxEnd)\
+	    PortP->TxAdd = PortP->TxStart;\
+	else\
+	    PortP->TxAdd++;\
+	WWORD(PortP->PhbP->tx_add , RIO_OFF(CaD,PortP->TxAdd));
+#elif defined(AIX)
+#   define add_transmit(PortP)  \
+	{\
+	    register ushort *TxAddP = (ushort *)RIO_PTR(Cad,PortP->TxAddO);\
+	    WINDW( TxAddP, RINDW( TxAddP ) | PKT_IN_USE );\
+	    if (PortP->TxAddO == PortP->TxEndO )\
+		PortP->TxAddO = PortP->TxStartO;\
+	    else\
+		PortP->TxAddO += sizeof(ushort);\
+	    WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->tx_add , PortP->TxAddO );\
+	}
+#else
+#   define add_transmit(PortP)  \
+	*PortP->TxAdd |= PKT_IN_USE;\
+	if (PortP->TxAdd == PortP->TxEnd)\
+	    PortP->TxAdd = PortP->TxStart;\
+	else\
+	    PortP->TxAdd++;\
+	PortP->PhbP->tx_add = RIO_OFF(CaD,PortP->TxAdd);
+#endif
+
+/*
+** can_remove_receive( PacketP, PortP ) returns non-zero if PKT_IN_USE is set
+** for the next packet on the queue. It will also set PacketP to point to the
+** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
+** then can_remove_receive() returns 0.
+*/
+#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
+#   define can_remove_receive(PacketP,PortP) \
+	((RINDW(PortP->RxRemove) & PKT_IN_USE) ? \
+	(PacketP=(struct PKT *)RIO_PTR(CaD,(RINDW(PortP->RxRemove) & ~PKT_IN_USE))):0)
+#elif defined(AIX)
+#   define can_remove_receive(PacketP,PortP) \
+	((RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & PKT_IN_USE) ? \
+	(PacketP=(struct PKT *)RIO_PTR(Cad,RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & ~PKT_IN_USE)):0)
+#else
+#   define can_remove_receive(PacketP,PortP) \
+	((*PortP->RxRemove & PKT_IN_USE) ? \
+	(PacketP=(struct PKT *)RIO_PTR(CaD,(*PortP->RxRemove & ~PKT_IN_USE))):0)
+#endif
+
+
+/*
+** Will God see it within his heart to forgive us for this thing that
+** we have created? To remove a packet from the receive queue you clear
+** its PKT_IN_USE bit, and then bump the pointers. Once the pointers
+** get to the end, they must be wrapped back to the start.
+*/
+#if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc)
+#   define remove_receive(PortP) \
+	WINDW(PortP->RxRemove, (RINDW(PortP->RxRemove) & ~PKT_IN_USE));\
+	if (PortP->RxRemove == PortP->RxEnd)\
+	    PortP->RxRemove = PortP->RxStart;\
+	else\
+	    PortP->RxRemove++;\
+	WWORD(PortP->PhbP->rx_remove , RIO_OFF(CaD,PortP->RxRemove));
+#elif defined(AIX)
+#   define remove_receive(PortP) \
+    {\
+        register ushort *RxRemoveP = (ushort *)RIO_PTR(Cad,PortP->RxRemoveO);\
+        WINDW( RxRemoveP, RINDW( RxRemoveP ) & ~PKT_IN_USE );\
+        if (PortP->RxRemoveO == PortP->RxEndO)\
+            PortP->RxRemoveO = PortP->RxStartO;\
+        else\
+            PortP->RxRemoveO += sizeof(ushort);\
+        WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->rx_remove, PortP->RxRemoveO );\
+    }
+#else
+#   define remove_receive(PortP) \
+	*PortP->RxRemove &= ~PKT_IN_USE;\
+	if (PortP->RxRemove == PortP->RxEnd)\
+	    PortP->RxRemove = PortP->RxStart;\
+	else\
+	    PortP->RxRemove++;\
+	PortP->PhbP->rx_remove = RIO_OFF(CaD,PortP->RxRemove);
+#endif
+#endif
+
+
+#else /* !IN_KERNEL */
+
+#define ZERO_PTR NULL
+
+
+#ifdef HOST
+/* #define can_remove_transmit(pkt,phb) ((((char*)pkt = (*(char**)(phb->tx_remove))-1) || 1)) && (*phb->u3.s2.tx_remove_ptr & PKT_IN_USE))   */
+#define remove_transmit(phb) *phb->u3.s2.tx_remove_ptr &= ~(ushort)PKT_IN_USE;\
+                             if (phb->tx_remove == phb->tx_end)\
+                                phb->tx_remove = phb->tx_start;\
+                             else\
+                                phb->tx_remove++;
+#define can_add_receive(phb) !(*phb->u4.s2.rx_add_ptr & PKT_IN_USE)
+#define add_receive(pkt,phb) *phb->rx_add = pkt;\
+                             *phb->u4.s2.rx_add_ptr |= PKT_IN_USE;\
+                             if (phb->rx_add == phb->rx_end)\
+                                phb->rx_add = phb->rx_start;\
+                             else\
+                                phb->rx_add++;
+#endif
+#endif
+
+#ifdef RTA
+#define splx(oldspl)    if ((oldspl) == 0) spl0()
+#endif
+
+#endif /* ifndef _list.h */
+/*********** end of file ***********/
diff --git a/drivers/char/rio/lrt.h b/drivers/char/rio/lrt.h
new file mode 100644
index 0000000..bbac8fa
--- /dev/null
+++ b/drivers/char/rio/lrt.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L R T
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_lrt_h_sccs = "@(#)lrt.h	1.1" ;
+#endif
+#endif
+
+
+#ifdef DCIRRUS
+#define LRT_STACK       (unsigned short) 600
+#else
+#define LRT_STACK        (ushort) 200
+#endif
+
+
+
+/*********** end of file ***********/
+
+
+
diff --git a/drivers/char/rio/ltt.h b/drivers/char/rio/ltt.h
new file mode 100644
index 0000000..f27dcec
--- /dev/null
+++ b/drivers/char/rio/ltt.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L T T
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_ltt_h_sccs = "@(#)ltt.h	1.1" ;
+#endif
+#endif
+
+#ifdef DCIRRUS
+#define LTT_STACK       (unsigned short)  600
+#else
+#define LTT_STACK       (ushort) 200
+#endif
+ 
+
+
+
+/*********** end of file ***********/
+
+
+
diff --git a/drivers/char/rio/lttwake.h b/drivers/char/rio/lttwake.h
new file mode 100644
index 0000000..fe17d0e
--- /dev/null
+++ b/drivers/char/rio/lttwake.h
@@ -0,0 +1,53 @@
+
+
+
+/****************************************************************************
+ *******                                                              *******
+ *******            L T T    W A K E U P    H E A D E R
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_lttwake_h_sccs = "@(#)lttwake.h	1.1" ;
+#endif
+#endif
+
+#define LTT_WAKEUP_STACK          500
+#define LTT_WAKEUP_INTERVAL       (int) (500 * MILLISECOND)
+
+
+/*********** end of file ***********/
+
+
+
diff --git a/drivers/char/rio/map.h b/drivers/char/rio/map.h
new file mode 100644
index 0000000..400645a1
--- /dev/null
+++ b/drivers/char/rio/map.h
@@ -0,0 +1,103 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: map.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:11
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)map.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_map_h__
+#define __rio_map_h__
+
+#ifdef SCCS_LABELS
+static char *_map_h_sccs_ = "@(#)map.h	1.2";
+#endif
+
+/*
+** mapping structure passed to and from the config.rio program to
+** determine the current topology of the world
+*/
+
+#define MAX_MAP_ENTRY 17
+#define	TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS)
+#define	MAX_NAME_LEN 32
+
+struct Map
+{
+	uint	HostUniqueNum;	        /* Supporting hosts unique number */
+	uint	RtaUniqueNum;	        /* Unique number */
+	/*
+	** The next two IDs must be swapped on big-endian architectures
+	** when using a v2.04 /etc/rio/config with a v3.00 driver (when
+	** upgrading for example).
+	*/
+	ushort	ID;			/* ID used in the subnet */
+	ushort	ID2;			/* ID of 2nd block of 8 for 16 port */
+	ulong	Flags;			/* Booted, ID Given, Disconnected */
+	ulong	SysPort;		/* First tty mapped to this port */
+	struct Top   Topology[LINKS_PER_UNIT];	/* ID connected to each link */
+	char	Name[MAX_NAME_LEN];        /* Cute name by which RTA is known */
+};
+
+/*
+** Flag values:
+*/
+#define	RTA_BOOTED		0x00000001
+#define RTA_NEWBOOT		0x00000010
+#define	MSG_DONE		0x00000020
+#define	RTA_INTERCONNECT	0x00000040
+#define	RTA16_SECOND_SLOT	0x00000080
+#define	BEEN_HERE		0x00000100
+#define SLOT_TENTATIVE		0x40000000
+#define SLOT_IN_USE		0x80000000
+
+/*
+** HostUniqueNum is the unique number from the host card that this RTA
+** is to be connected to.
+** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO
+** if the slot in the table is unused. If it is the same as the HostUniqueNum
+** then this slot represents a host card.
+** Flags contains current boot/route state info
+** SysPort is a value in the range 0-504, being the number of the first tty
+** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8.
+** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor
+** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256,
+** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511
+** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an
+** unused slot/unknown ID etc.
+** The Topology array contains the ID of the unit connected to each of the
+** four links on this unit. The entry will be 0xFFFF if NOTHING is connected
+** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link.
+** The Name field is a null-terminated string, upto 31 characters, containing
+** the 'cute' name that the sysadmin/users know the RTA by. It is permissible
+** for this string to contain any character in the range \040 to \176 inclusive.
+** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The
+** special character '%' IS allowable, and needs no special action.
+**
+*/
+
+#endif
diff --git a/drivers/char/rio/mca.h b/drivers/char/rio/mca.h
new file mode 100644
index 0000000..08a327e
--- /dev/null
+++ b/drivers/char/rio/mca.h
@@ -0,0 +1,73 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: mca.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:11
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)mca.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_mca_h__
+#define	__rio_mca_h__
+
+#ifdef SCCS_LABELS
+static char *_mca_h_sccs_ = "@(#)mca.h	1.2";
+#endif
+
+/*
+** Micro Channel stuff
+*/
+
+#define	McaMaxSlots	8
+#define McaSlotSelect	0x96
+#define	McaSlotEnable	0x08
+#define	McaIdLow	0x100
+#define	McaIdHigh	0x101
+#define	McaIrqEnable	0x102
+#define	McaMemory	0x103
+#define McaRIOId	0x6a5c
+#define	McaIrq9		0x00
+#define	McaIrq3		0x02
+#define	McaIrq4		0x04
+#define	McaIrq7		0x06
+#define	McaIrq10	0x08
+#define	McaIrq11	0x0A
+#define	McaIrq12	0x0C
+#define	McaIrq15	0x0E
+#define McaIrqMask	0x0E
+#define	McaCardEnable	0x01
+#define	McaAddress(X)	(((X)&0xFF)<<16)
+
+#define	McaTpFastLinks	        0x40
+#define	McaTpSlowLinks	        0x00
+#define	McaTpBootFromRam	0x01
+#define	McaTpBootFromLink	0x00
+#define	McaTpBusEnable		0x02
+#define	McaTpBusDisable		0x00
+
+#define	RIO_MCA_DEFAULT_MODE	SLOW_LINKS
+
+#endif	/* __rio_mca_h__ */
diff --git a/drivers/char/rio/mesg.h b/drivers/char/rio/mesg.h
new file mode 100644
index 0000000..9cf6c0b
--- /dev/null
+++ b/drivers/char/rio/mesg.h
@@ -0,0 +1,41 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: mesg.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)mesg.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_mesg_h__
+#define	__rio_mesg_h__
+
+#ifdef SCCS_LABELS
+static char *_mesg_h_sccs_ = "@(#)mesg.h	1.2";
+#endif
+
+
+#endif /* __rio_mesg_h__ */
diff --git a/drivers/char/rio/param.h b/drivers/char/rio/param.h
new file mode 100644
index 0000000..2dc30b9
--- /dev/null
+++ b/drivers/char/rio/param.h
@@ -0,0 +1,61 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: param.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)param.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_param_h__
+#define __rio_param_h__
+
+#ifdef SCCS_LABELS
+static char *_param_h_sccs_ = "@(#)param.h	1.2";
+#endif
+
+
+/*
+** the param command block, as used in OPEN and PARAM calls.
+*/
+
+struct phb_param
+{
+    BYTE    Cmd;        /* It is very important that these line up */
+    BYTE    Cor1;       /* with what is expected at the other end. */
+    BYTE    Cor2;       /* to confirm that you've got it right,    */
+    BYTE    Cor4;       /* check with cirrus/cirrus.h              */
+    BYTE    Cor5;
+    BYTE    TxXon;	/* Transmit X-On character */
+    BYTE    TxXoff;	/* Transmit X-Off character */
+    BYTE    RxXon;	/* Receive X-On character */
+    BYTE    RxXoff;	/* Receive X-Off character */
+    BYTE    LNext;	/* Literal-next character */
+    BYTE    TxBaud;	/* Transmit baudrate */
+    BYTE    RxBaud;	/* Receive baudrate */
+};
+
+#endif
diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h
new file mode 100644
index 0000000..46f99df
--- /dev/null
+++ b/drivers/char/rio/parmmap.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+ *******                                                              *******
+ *******               H O S T   M E M O R Y  M A P
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+6/4/1991   jonb		     Made changes to accommodate Mips R3230 bus
+ ***************************************************************************/
+
+#ifndef _parmap_h
+#define _parmap_h
+
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_parmmap_h_sccs = "@(#)parmmap.h	1.4"; */
+#endif
+#endif
+
+typedef struct PARM_MAP PARM_MAP ;
+
+struct PARM_MAP
+{
+PHB_ptr           phb_ptr ;              /* Pointer to the PHB array */
+WORD_ptr          phb_num_ptr ;          /* Ptr to Number of PHB's */
+FREE_LIST_ptr     free_list;             /* Free List pointer */
+FREE_LIST_ptr     free_list_end;         /* Free List End pointer */
+Q_BUF_ptr_ptr     q_free_list_ptr ;      /* Ptr to Q_BUF variable */
+BYTE_ptr          unit_id_ptr ;          /* Unit Id */
+LPB_ptr           link_str_ptr ;         /* Link Structure Array */
+BYTE_ptr          bootloader_1 ;         /* 1st Stage Boot Loader */
+BYTE_ptr          bootloader_2 ;         /* 2nd Stage Boot Loader */
+WORD_ptr          port_route_map_ptr ;   /* Port Route Map */
+ROUTE_STR_ptr     route_ptr ;            /* Unit Route Map */
+NUMBER_ptr        map_present ;          /* Route Map present */
+NUMBER            pkt_num ;               /* Total number of packets */
+NUMBER            q_num ;                 /* Total number of Q packets */
+WORD              buffers_per_port ;      /* Number of buffers per port */
+WORD              heap_size ;             /* Initial size of heap */
+WORD              heap_left ;             /* Current Heap left */
+WORD              error ;                 /* Error code */
+WORD              tx_max;                 /* Max number of tx pkts per phb */
+WORD              rx_max;                 /* Max number of rx pkts per phb */
+WORD              rx_limit;               /* For high / low watermarks */
+NUMBER            links ;                 /* Links to use */
+NUMBER            timer ;                 /* Interrupts per second */
+RUP_ptr           rups ;                 /* Pointer to the RUPs */
+WORD              max_phb ;              /* Mostly for debugging */
+WORD              living ;               /* Just increments!! */
+WORD              init_done ;            /* Initialisation over */
+WORD              booting_link ;
+WORD              idle_count ;           /* Idle time counter */
+WORD              busy_count ;           /* Busy counter */
+WORD              idle_control ;         /* Control Idle Process */
+#if defined(HOST) || defined(INKERNEL)
+WORD              tx_intr;               /* TX interrupt pending */
+WORD              rx_intr;               /* RX interrupt pending */
+WORD              rup_intr;              /* RUP interrupt pending */
+#endif
+#if defined(RTA)
+WORD		  dying_count;		/* Count of processes dead */
+#endif
+} ;
+
+#endif
+
+/*********** end of file ***********/
+
+
diff --git a/drivers/char/rio/pci.h b/drivers/char/rio/pci.h
new file mode 100644
index 0000000..dc635bd
--- /dev/null
+++ b/drivers/char/rio/pci.h
@@ -0,0 +1,76 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: pci.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)pci.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_pci_h__
+#define	__rio_pci_h__
+
+#ifdef SCCS_LABELS
+static char *_pci_h_sccs_ = "@(#)pci.h	1.2";
+#endif
+
+/*
+** PCI stuff
+*/
+
+#define	PCITpFastClock		0x80
+#define	PCITpSlowClock		0x00
+#define	PCITpFastLinks	        0x40
+#define	PCITpSlowLinks	        0x00
+#define	PCITpIntEnable		0x04
+#define	PCITpIntDisable		0x00
+#define	PCITpBusEnable		0x02
+#define	PCITpBusDisable		0x00
+#define	PCITpBootFromRam	0x01
+#define	PCITpBootFromLink	0x00
+
+#define	RIO_PCI_VENDOR		0x11CB
+#define	RIO_PCI_DEVICE		0x8000
+#define	RIO_PCI_BASE_CLASS	0x02
+#define	RIO_PCI_SUB_CLASS	0x80
+#define	RIO_PCI_PROG_IFACE	0x00
+
+#define RIO_PCI_RID		0x0008
+#define RIO_PCI_BADR0		0x0010
+#define RIO_PCI_INTLN		0x003C
+#define RIO_PCI_INTPIN		0x003D
+
+#define	RIO_PCI_MEM_SIZE	65536
+
+#define	RIO_PCI_TURBO_TP	0x80
+#define	RIO_PCI_FAST_LINKS	0x40
+#define	RIO_PCI_INT_ENABLE	0x04
+#define	RIO_PCI_TP_BUS_ENABLE	0x02
+#define	RIO_PCI_BOOT_FROM_RAM	0x01
+
+#define	RIO_PCI_DEFAULT_MODE	0x05
+
+#endif	/* __rio_pci_h__ */
diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h
new file mode 100644
index 0000000..e1483a0
--- /dev/null
+++ b/drivers/char/rio/phb.h
@@ -0,0 +1,293 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                 P H B     H E A D E R                        *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra, Jeremy Rolls
+ Date    : 
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _phb_h
+#define _phb_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_phb_h_sccs = "@(#)phb.h	1.12"; */
+#endif
+#endif
+
+
+ /*************************************************
+  * Set the LIMIT values.
+  ************************************************/
+#ifdef RTA
+#define RX_LIMIT       (ushort) 3
+#endif
+#ifdef HOST
+#define RX_LIMIT       (ushort) 1
+#endif
+
+
+/*************************************************
+ * Handshake asserted. Deasserted by the LTT(s)
+ ************************************************/
+#define PHB_HANDSHAKE_SET      ((ushort) 0x001) /* Set by LRT */
+
+#define PHB_HANDSHAKE_RESET     ((ushort) 0x002) /* Set by ISR / driver */
+
+#define PHB_HANDSHAKE_FLAGS     (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET)
+                                                /* Reset by ltt */
+
+
+/*************************************************
+ * Maximum number of PHB's
+ ************************************************/
+#if defined (HOST) || defined (INKERNEL)
+#define MAX_PHB               ((ushort) 128)  /* range 0-127 */
+#else
+#define MAX_PHB               ((ushort) 8)    /* range 0-7 */
+#endif
+
+/*************************************************
+ * Defines for the mode fields
+ ************************************************/
+#define TXPKT_INCOMPLETE        0x0001  /* Previous tx packet not completed */
+#define TXINTR_ENABLED          0x0002  /* Tx interrupt is enabled */
+#define TX_TAB3                 0x0004  /* TAB3 mode */
+#define TX_OCRNL                0x0008  /* OCRNL mode */
+#define TX_ONLCR                0x0010  /* ONLCR mode */
+#define TX_SENDSPACES           0x0020  /* Send n spaces command needs 
+                                           completing */
+#define TX_SENDNULL             0x0040  /* Escaping NULL needs completing */
+#define TX_SENDLF               0x0080  /* LF -> CR LF needs completing */
+#define TX_PARALLELBUG          0x0100  /* CD1400 LF -> CR LF bug on parallel
+                                           port */
+#define TX_HANGOVER             (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL)
+#define TX_DTRFLOW		0x0200	/* DTR tx flow control */
+#define	TX_DTRFLOWED		0x0400	/* DTR is low - don't allow more data
+					   into the FIFO */
+#define	TX_DATAINFIFO		0x0800	/* There is data in the FIFO */
+#define	TX_BUSY			0x1000	/* Data in FIFO, shift or holding regs */
+
+#define RX_SPARE	        0x0001   /* SPARE */
+#define RXINTR_ENABLED          0x0002   /* Rx interrupt enabled */
+#define RX_ICRNL                0x0008   /* ICRNL mode */
+#define RX_INLCR                0x0010   /* INLCR mode */
+#define RX_IGNCR                0x0020   /* IGNCR mode */
+#define RX_CTSFLOW              0x0040   /* CTSFLOW enabled */
+#define RX_IXOFF                0x0080   /* IXOFF enabled */
+#define RX_CTSFLOWED            0x0100   /* CTSFLOW and CTS dropped */
+#define RX_IXOFFED              0x0200   /* IXOFF and xoff sent */
+#define RX_BUFFERED		0x0400	 /* Try and pass on complete packets */
+
+#define PORT_ISOPEN             0x0001  /* Port open? */
+#define PORT_HUPCL              0x0002  /* Hangup on close? */
+#define PORT_MOPENPEND          0x0004  /* Modem open pending */
+#define PORT_ISPARALLEL         0x0008  /* Parallel port */
+#define PORT_BREAK              0x0010  /* Port on break */
+#define PORT_STATUSPEND		0x0020  /* Status packet pending */
+#define PORT_BREAKPEND          0x0040  /* Break packet pending */
+#define PORT_MODEMPEND          0x0080  /* Modem status packet pending */
+#define PORT_PARALLELBUG        0x0100  /* CD1400 LF -> CR LF bug on parallel
+                                           port */
+#define PORT_FULLMODEM          0x0200  /* Full modem signals */
+#define PORT_RJ45               0x0400  /* RJ45 connector - no RI signal */
+#define PORT_RESTRICTED         0x0600  /* Restricted connector - no RI / DTR */
+
+#define PORT_MODEMBITS          0x0600  /* Mask for modem fields */
+
+#define PORT_WCLOSE             0x0800  /* Waiting for close */
+#define	PORT_HANDSHAKEFIX	0x1000	/* Port has H/W flow control fix */
+#define	PORT_WASPCLOSED		0x2000	/* Port closed with PCLOSE */
+#define	DUMPMODE		0x4000	/* Dump RTA mem */
+#define	READ_REG		0x8000	/* Read CD1400 register */
+
+
+
+/**************************************************************************
+ * PHB Structure
+ * A  few words.
+ *
+ * Normally Packets are added to the end of the list and removed from
+ * the start. The pointer tx_add points to a SPACE to put a Packet.
+ * The pointer tx_remove points to the next Packet to remove
+ *************************************************************************/
+#ifndef INKERNEL
+#define src_unit     u2.s2.unit
+#define src_port     u2.s2.port
+#define dest_unit    u1.s1.unit
+#define dest_port    u1.s1.port
+#endif
+#ifdef HOST
+#define tx_start     u3.s1.tx_start_ptr_ptr
+#define tx_add       u3.s1.tx_add_ptr_ptr
+#define tx_end       u3.s1.tx_end_ptr_ptr
+#define tx_remove    u3.s1.tx_remove_ptr_ptr
+#define rx_start     u4.s1.rx_start_ptr_ptr
+#define rx_add       u4.s1.rx_add_ptr_ptr
+#define rx_end       u4.s1.rx_end_ptr_ptr
+#define rx_remove    u4.s1.rx_remove_ptr_ptr
+#endif
+typedef struct PHB PHB ;
+struct PHB {
+#ifdef RTA
+        ushort      port;
+#endif
+#ifdef INKERNEL
+        WORD      source;
+#else
+        union       
+        {
+            ushort source;              /* Complete source */
+            struct
+            {
+                unsigned char unit;     /* Source unit */
+                unsigned char port;     /* Source port */
+            } s2;
+        } u2;
+#endif
+        WORD      handshake ;
+        WORD      status ;
+        NUMBER       timeout ;           /* Maximum of 1.9 seconds */
+        WORD      link ;              /* Send down this link */
+#ifdef INKERNEL
+        WORD      destination;
+#else
+        union       
+        {
+            ushort destination;         /* Complete destination */
+            struct
+            {
+                unsigned char unit;     /* Destination unit */
+                unsigned char port;     /* Destination port */
+            } s1;
+        } u1;
+#endif
+#ifdef RTA
+        ushort      tx_pkts_added;
+        ushort      tx_pkts_removed;
+        Q_BUF_ptr   tx_q_start ;        /* Start of the Q list chain */
+        short       num_tx_q_bufs ;     /* Number of Q buffers in the chain */
+        PKT_ptr_ptr tx_add ;            /* Add a new Packet here */
+        Q_BUF_ptr   tx_add_qb;          /* Pointer to the add Q buf */
+        PKT_ptr_ptr tx_add_st_qbb ;     /* Pointer to start of the Q's buf */
+        PKT_ptr_ptr tx_add_end_qbb ;    /* Pointer to the end of the Q's buf */
+        PKT_ptr_ptr tx_remove ;         /* Remove a Packet here */
+        Q_BUF_ptr   tx_remove_qb ;      /* Pointer to the remove Q buf */
+        PKT_ptr_ptr tx_remove_st_qbb ;  /* Pointer to the start of the Q buf */
+        PKT_ptr_ptr tx_remove_end_qbb ; /* Pointer to the end of the Q buf */
+#endif
+#ifdef INKERNEL
+        PKT_ptr_ptr tx_start ;
+        PKT_ptr_ptr tx_end ;
+        PKT_ptr_ptr tx_add ;
+        PKT_ptr_ptr tx_remove ;
+#endif
+#ifdef HOST
+        union
+        {
+            struct
+            {
+                PKT_ptr_ptr tx_start_ptr_ptr;
+                PKT_ptr_ptr tx_end_ptr_ptr;
+                PKT_ptr_ptr tx_add_ptr_ptr;
+                PKT_ptr_ptr tx_remove_ptr_ptr;
+            } s1;
+            struct
+            {
+                ushort * tx_start_ptr;
+                ushort * tx_end_ptr;
+                ushort * tx_add_ptr;
+                ushort * tx_remove_ptr;
+            } s2;
+        } u3;
+#endif
+
+#ifdef  RTA
+        ushort      rx_pkts_added;
+        ushort      rx_pkts_removed;
+        Q_BUF_ptr   rx_q_start ;        /* Start of the Q list chain */
+        short       num_rx_q_bufs ;     /* Number of Q buffers in the chain */
+        PKT_ptr_ptr rx_add ;            /* Add a new Packet here */
+        Q_BUF_ptr   rx_add_qb ;         /* Pointer to the add Q buf */
+        PKT_ptr_ptr rx_add_st_qbb ;     /* Pointer to start of the Q's buf */
+        PKT_ptr_ptr rx_add_end_qbb ;    /* Pointer to the end of the Q's buf */
+        PKT_ptr_ptr rx_remove ;         /* Remove a Packet here */
+        Q_BUF_ptr   rx_remove_qb ;      /* Pointer to the remove Q buf */
+        PKT_ptr_ptr rx_remove_st_qbb ;  /* Pointer to the start of the Q buf */
+        PKT_ptr_ptr rx_remove_end_qbb ; /* Pointer to the end of the Q buf */
+#endif
+#ifdef INKERNEL
+        PKT_ptr_ptr rx_start ;
+        PKT_ptr_ptr rx_end ;
+        PKT_ptr_ptr rx_add ;
+        PKT_ptr_ptr rx_remove ;
+#endif
+#ifdef HOST
+        union
+        {
+            struct
+            {
+                PKT_ptr_ptr rx_start_ptr_ptr;
+                PKT_ptr_ptr rx_end_ptr_ptr;
+                PKT_ptr_ptr rx_add_ptr_ptr;
+                PKT_ptr_ptr rx_remove_ptr_ptr;
+            } s1;
+            struct
+            {
+                ushort * rx_start_ptr;
+                ushort * rx_end_ptr;
+                ushort * rx_add_ptr;
+                ushort * rx_remove_ptr;
+            } s2;
+        } u4;
+#endif
+
+#ifdef RTA                              /* some fields for the remotes */
+        ushort     flush_count;		/* Count of write flushes */
+        ushort     txmode;		/* Modes for tx */
+        ushort     rxmode;		/* Modes for rx */
+        ushort     portmode;		/* Generic modes */
+        ushort     column;		/* TAB3 column count */
+        ushort     tx_subscript;	/* (TX) Subscript into data field */
+        ushort     rx_subscript;	/* (RX) Subscript into data field */
+        PKT_ptr    rx_incomplete;	/* Hold an incomplete packet here */
+        ushort     modem_bits;		/* Modem bits to mask */
+	ushort	   lastModem;		/* Modem control lines. */
+        ushort     addr;		/* Address for sub commands */
+        ushort     MonitorTstate;	/* TRUE if monitoring tstop */
+#endif
+
+        } ;
+
+#endif
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h
new file mode 100644
index 0000000..66bb2ff
--- /dev/null
+++ b/drivers/char/rio/pkt.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+ *******                                                              *******
+ *******            P A C K E T   H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _pkt_h
+#define _pkt_h 1
+
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_pkt_h_sccs = "@(#)pkt.h	1.8"; */
+#endif
+#endif
+
+#define MAX_TTL         0xf
+#define PKT_CMD_BIT     ((ushort) 0x080)
+#define PKT_CMD_DATA    ((ushort) 0x080)
+
+#define PKT_ACK         ((ushort) 0x040)
+
+#define PKT_TGL         ((ushort) 0x020)
+
+#define PKT_LEN_MASK    ((ushort) 0x07f)
+
+#define DATA_WNDW       ((ushort) 0x10)
+#define PKT_TTL_MASK    ((ushort) 0x0f)
+
+#define PKT_MAX_DATA_LEN   72
+
+#define PKT_LENGTH         sizeof(struct PKT)
+#define SYNC_PKT_LENGTH    (PKT_LENGTH + 4)
+
+#define CONTROL_PKT_LEN_MASK PKT_LEN_MASK
+#define CONTROL_PKT_CMD_BIT  PKT_CMD_BIT
+#define CONTROL_PKT_ACK (PKT_ACK << 8)
+#define CONTROL_PKT_TGL (PKT_TGL << 8)
+#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8)
+#define CONTROL_DATA_WNDW  (DATA_WNDW << 8)
+
+struct PKT    {
+#ifdef INKERNEL
+                   BYTE    dest_unit ;    /* Destination Unit Id */
+                   BYTE    dest_port ;    /* Destination POrt */
+                   BYTE    src_unit ;     /* Source Unit Id */
+                   BYTE    src_port ;     /* Source POrt */
+#else
+                   union       
+                   {
+                       ushort destination;         /* Complete destination */
+                       struct
+                       {
+                           unsigned char unit;     /* Destination unit */
+                           unsigned char port;     /* Destination port */
+                       } s1;
+                   } u1;
+                   union       
+                   {
+                       ushort source;              /* Complete source */
+                       struct
+                       {
+                           unsigned char unit;     /* Source unit */
+                           unsigned char port;     /* Source port */
+                       } s2;
+                   } u2;
+#endif
+#ifdef INKERNEL
+                   BYTE len ;
+                   BYTE control;
+#else
+                   union
+                   {
+                        ushort      control;
+                        struct
+                        {
+                            unsigned char len;
+                            unsigned char control;
+                        } s3;
+                    } u3;
+#endif
+                   BYTE    data[PKT_MAX_DATA_LEN] ;     
+                                                   /* Actual data :-) */
+                   WORD  csum ;                  /* C-SUM */
+               } ;
+#endif
+
+/*********** end of file ***********/
+
+
diff --git a/drivers/char/rio/poll.h b/drivers/char/rio/poll.h
new file mode 100644
index 0000000..d9b8e98
--- /dev/null
+++ b/drivers/char/rio/poll.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      P O L L
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _poll_h
+#define _poll_h
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_poll_h_sccs = "@(#)poll.h	1.2" ;
+#endif
+#endif
+
+
+#ifdef HOST
+#define POLL_STACK            100
+#endif
+#ifdef RTA
+#define POLL_STACK            200
+#endif
+
+#define POLL_PERIOD           (int) SECOND
+
+/* The various poll commands */
+#define POLL_POLL             0            /* We are connected and happy.. */
+#define POLL_INTRO            1            /* Introduction packet */
+#define POLL_TOPOLOGY         2            /* Topology update */
+#define POLL_ASSIGN           3            /* ID assign */
+#define POLL_FOAD             4            /* F*** Off And Die */
+#define POLL_LMD	      5		   /* Let Me Die */
+#define POLL_DYB	      6		   /* Die You Ba***** */
+
+/* The way data fields are split up for POLL packets */
+#define POLL_HOST_SERIAL      2            /* Host who booted me */
+#define POLL_MY_SERIAL        6            /* My serial number */
+#define POLL_YOUR_ID          1            /* Your ID number */
+#define POLL_TOPOLOGY_FIELDS  2            /* Topology maps */
+
+#endif
+
+/*********** end of file ***********/
+
+
+
diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h
new file mode 100644
index 0000000..8506af0
--- /dev/null
+++ b/drivers/char/rio/port.h
@@ -0,0 +1,245 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: port.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)port.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_port_h__
+#define	__rio_port_h__
+
+#ifdef SCCS_LABELS
+static char *_port_h_sccs_ = "@(#)port.h	1.3";
+#endif
+
+
+#undef VPIX
+
+
+/*
+** the port data structure - one per port in the system
+*/
+
+#ifdef STATS
+struct RIOStats
+{
+	/*
+	** interrupt statistics
+	*/
+	uint	BreakIntCnt;
+	uint	ModemOffCnt;
+	uint	ModemOnCnt;
+	uint	RxIntCnt;
+	uint	TxIntCnt;
+	/*
+	** throughput statistics
+	*/
+	uint	RxCharCnt;
+	uint	RxPktCnt;
+	uint	RxSaveCnt;
+	uint	TxCharCnt;
+	uint	TxPktCnt;
+	/*
+	** driver entry statistics
+	*/
+	uint	CloseCnt;
+	uint	IoctlCnt;
+	uint	OpenCnt;
+	uint	ReadCnt;
+	uint	WriteCnt;
+	/*
+	** proc statistics
+	*/
+	uint	BlockCnt;
+	uint	OutputCnt;
+	uint	ResumeCnt;
+	uint	RflushCnt;
+	uint	SuspendCnt;
+	uint	TbreakCnt;
+	uint	TimeoutCnt;
+	uint	UnblockCnt;
+	uint	WflushCnt;
+	uint	WFBodgeCnt;
+};
+#endif
+
+/*
+**	Port data structure
+*/
+struct	Port
+{
+  struct gs_port gs; 
+  int				PortNum;	/* RIO port no., 0-511 */
+  struct Host	*HostP;
+  volatile caddr_t		Caddr;
+  ushort			HostPort;  /* Port number on host card */
+  uchar			RupNum;	/* Number of RUP for port */
+  uchar			ID2;	/* Second ID of RTA for port */
+  ulong			State;	/* FLAGS for open & xopen */
+#define	RIO_LOPEN	0x00001		/* Local open */
+#define	RIO_MOPEN	0x00002		/* Modem open */
+#define	RIO_WOPEN	0x00004		/* Waiting for open */
+#define	RIO_CLOSING	0x00008		/* The port is being close */
+#define	RIO_XPBUSY	0x00010		/* Transparent printer busy */
+#define	RIO_BREAKING	0x00020		/* Break in progress */
+#define	RIO_DIRECT	0x00040		/* Doing Direct output */
+#define	RIO_EXCLUSIVE	0x00080		/* Stream open for exclusive use */
+#define	RIO_NDELAY	0x00100		/* Stream is open FNDELAY */
+#define	RIO_CARR_ON	0x00200		/* Stream has carrier present */
+#define	RIO_XPWANTR	0x00400		/* Stream wanted by Xprint */
+#define	RIO_RBLK	0x00800		/* Stream is read-blocked */
+#define	RIO_BUSY	0x01000		/* Stream is BUSY for write */
+#define	RIO_TIMEOUT	0x02000		/* Stream timeout in progress */
+#define	RIO_TXSTOP	0x04000		/* Stream output is stopped */
+#define	RIO_WAITFLUSH	0x08000		/* Stream waiting for flush */
+#define	RIO_DYNOROD	0x10000		/* Drain failed */
+#define	RIO_DELETED	0x20000		/* RTA has been deleted */
+#define RIO_ISSCANCODE	0x40000		/* This line is in scancode mode */
+#define	RIO_USING_EUC	0x100000	/* Using extended Unix chars */
+#define	RIO_CAN_COOK	0x200000	/* This line can do cooking */
+#define RIO_TRIAD_MODE  0x400000        /* Enable TRIAD special ops. */
+#define RIO_TRIAD_BLOCK 0x800000        /* Next read will block */
+#define RIO_TRIAD_FUNC  0x1000000       /* Seen a function key coming in */
+#define RIO_THROTTLE_RX 0x2000000       /* RX needs to be throttled. */
+
+    ulong			Config;	/* FLAGS for NOREAD.... */
+#define	RIO_NOREAD	0x0001		/* Are not allowed to read port */
+#define	RIO_NOWRITE	0x0002		/* Are not allowed to write port */
+#define	RIO_NOXPRINT	0x0004		/* Are not allowed to xprint port */
+#define	RIO_NOMASK	0x0007		/* All not allowed things */
+#define RIO_IXANY	0x0008          /* Port is allowed ixany */
+#define	RIO_MODEM	0x0010		/* Stream is a modem device */
+#define	RIO_IXON	0x0020		/* Port is allowed ixon */
+#define RIO_WAITDRAIN	0x0040		/* Wait for port to completely drain */
+#define RIO_MAP_50_TO_50	0x0080	/* Map 50 baud to 50 baud */
+#define RIO_MAP_110_TO_110	0x0100	/* Map 110 baud to 110 baud */
+
+/*
+** 15.10.1998 ARG - ESIL 0761 prt fix
+** As LynxOS does not appear to support Hardware Flow Control .....
+** Define our own flow control flags in 'Config'.
+*/
+#define RIO_CTSFLOW	0x0200		/* RIO's own CTSFLOW flag */
+#define RIO_RTSFLOW	0x0400		/* RIO's own RTSFLOW flag */
+
+
+    struct PHB			*PhbP;	  /* pointer to PHB for port */
+    WORD                        *TxAdd;   /* Add packets here */
+    WORD                        *TxStart; /* Start of add array */
+    WORD                        *TxEnd;         /* End of add array */
+    WORD                        *RxRemove;      /* Remove packets here */
+    WORD                        *RxStart;       /* Start of remove array */
+    WORD                        *RxEnd;         /* End of remove array */
+    uint			RtaUniqueNum;	/* Unique number of RTA */
+    ushort			PortState;	/* status of port */
+    ushort			ModemState;	/* status of modem lines */
+    ulong			ModemLines;	/* Modem bits sent to RTA */
+    uchar			CookMode;	/* who expands CR/LF? */
+    uchar			ParamSem;	/* Prevent write during param */
+    uchar			Mapped;		/* if port mapped onto host */
+    uchar			SecondBlock;	/* if port belongs to 2nd block
+						   of 16 port RTA */
+    uchar			InUse;		/* how many pre-emptive cmds */
+    uchar			Lock;		/* if params locked */
+    uchar			Store;	/* if params stored across closes */
+    uchar			FirstOpen; /* TRUE if first time port opened */
+    uchar			FlushCmdBodge;	/* if doing a (non)flush */
+    uchar			MagicFlags;	/* require intr processing */
+#define	MAGIC_FLUSH	0x01	/* mirror of WflushFlag */
+#define	MAGIC_REBOOT	0x02	/* RTA re-booted, re-open ports */
+#define	MORE_OUTPUT_EYGOR 0x04	/* riotproc failed to empty clists */
+    uchar			WflushFlag;	/* 1 How many WFLUSHs active */
+/*
+** Transparent print stuff
+*/
+    struct Xprint
+    {
+#ifndef MAX_XP_CTRL_LEN
+#define MAX_XP_CTRL_LEN		16		/* ALSO IN DAEMON.H */
+#endif
+	uint			XpCps;
+	char			XpOn[MAX_XP_CTRL_LEN];
+	char			XpOff[MAX_XP_CTRL_LEN];
+	ushort			XpLen;		/* strlen(XpOn)+strlen(XpOff) */
+	uchar			XpActive;
+	uchar			XpLastTickOk;	/* TRUE if we can process */
+#define	XP_OPEN		00001
+#define	XP_RUNABLE	00002
+	struct ttystatics 		*XttyP;
+    } Xprint;
+#ifdef VPIX
+    v86_t			*StashP;
+    uint			IntMask;
+    struct termss 		VpixSs;
+    uchar			ModemStatusReg;	/* Modem status register */
+#endif
+    uchar			RxDataStart;
+    uchar			Cor2Copy;	/* copy of COR2 */
+    char			*Name;		/* points to the Rta's name */
+#ifdef STATS
+    struct RIOStats 		Stat;		/* ports statistics */
+#endif
+    char			*TxRingBuffer;
+    ushort			TxBufferIn;	/* New data arrives here */
+    ushort			TxBufferOut;	/* Intr removes data here */
+    ushort			OldTxBufferOut;	/* Indicates if draining */
+    int				TimeoutId;	/* Timeout ID */
+    uint			Debug;
+    uchar			WaitUntilBooted; /* True if open should block */
+    uint			statsGather;	/* True if gathering stats */
+    ulong			txchars;	/* Chars transmitted */
+    ulong			rxchars;	/* Chars received */
+    ulong			opens;		/* port open count */
+    ulong			closes;		/* port close count */
+    ulong			ioctls;		/* ioctl count */
+    uchar			LastRxTgl;	/* Last state of rx toggle bit */
+  spinlock_t				portSem;	/* Lock using this sem */
+	int				MonitorTstate;	/* Monitoring ? */
+	int				timeout_id;	/* For calling 100 ms delays */
+	int				timeout_sem;/* For calling 100 ms delays */
+	int				firstOpen;	/* First time open ? */
+	char *			p;			/* save the global struc here .. */
+};
+
+struct ModuleInfo
+{
+	char	*Name;
+	uint	Flags[4];	/* one per port on a module */
+};
+#endif
+
+/*
+** This struct is required because trying to grab an entire Port structure
+** runs into problems with differing struct sizes between driver and config.
+*/
+struct PortParams {
+	uint	Port;
+	ulong	Config;
+	ulong	State;
+	struct ttystatics	*TtyP;
+};
diff --git a/drivers/char/rio/proto.h b/drivers/char/rio/proto.h
new file mode 100644
index 0000000..ddff0ef
--- /dev/null
+++ b/drivers/char/rio/proto.h
@@ -0,0 +1,244 @@
+/*
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef	_prototypes_h
+#define _prototypes_h
+
+
+/*
+** boot.c
+*/
+void init_boot( char *p, short stage);
+
+/*
+** disconct.c
+*/
+void kill_boot ( LPB *link );
+void disconnected( LPB *link );
+short boot_3( LPB *link, PKT *pkt );
+short send_3_pkt( LPB *link, PKT *pkt);
+
+/*
+** error.c
+*/
+void du_error(void);
+
+/*
+** formpkt.c
+*/
+ushort sum_it( PKT *pkt ) ;
+void form_rup_pkt( RUP *form_rup, PKT *pkt );
+void form_poll_pkt ( int type, LPB *link, int node );
+void form_route_pkt ( int type, PKT *pkt, LPB *link );
+
+/*
+** idle.c
+*/
+void idle( Process *idle_p );
+
+/*
+** init.c
+*/
+void general_init(void);
+void mem_halt( int error);
+
+/*
+** linkinit.c
+*/
+void initlink( u_short number, LPB *link);
+void runlink( LPB *link);
+
+/*
+** list.c
+*/
+PKT *get_free_start(void);
+void put_free_start( PKT *pkt);
+
+#ifdef HOST
+int can_remove_transmit ( PKT **pkt, PKT *pointer );
+#endif
+
+#ifdef RTA
+int spl7 ( void );
+int spl0 ( void );
+Q_BUF *get_free_q( void );
+PKT *get_free_end(void);
+int add_end( PKT *pkt, PHB *phb, int type);
+unsigned short free_packets( PHB *phb, int type);
+int can_remove_start( PKT **pkt, PHB *phb, int type);
+int can_add_start( PHB *phb, int type);
+int can_add_end( PHB *phb, int type);
+void put_free_end( PKT *pkt);
+int remove_start( PKT **pkt, PHB *phb, int type);
+#endif
+
+/*
+** Lrt.c
+*/
+void lrt( Process *lrt_p, LPB *link );
+
+#ifdef RTA
+void set_led_red ( LPB *link );
+#endif
+
+/*
+** ltt.c
+*/
+void ltt( Process *ltt_p, LPB *link, PHB *phb_ptr[] );
+void send_poll ( LPB *link );
+void request_id ( LPB *link );
+void send_topology_update ( LPB *link );
+void send_topology ( LPB *link );
+void supply_id ( LPB *link );
+
+#ifdef RTA
+void redirect_queue ( LPB *link, ushort flush );
+int obtain_rup ( int rup_number, PKT **pkt_address, LPB *link );
+#endif
+
+#ifdef TESTING_PERF
+int consume_cpu( void );
+#endif
+
+/*
+** lttwake.c
+*/
+#ifdef HOST
+void ltt_wakeup( Process *ltt_wakeup_p );
+#endif
+
+/*
+** mapgen.c
+*/
+void generate_id_map( short mapping, ROUTE_STR route[] );
+void gen_map( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl );
+void adjust_ttl( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl);
+void init_sys_map(void);
+
+/*
+** mmu.c
+*/
+char *rio_malloc( unsigned int amount);
+char *rio_calloc( unsigned int num, unsigned int size);
+ERROR rio_mmu_init( uint total_mem );
+
+/*
+** partn.c
+*/
+void partition_tx( struct PHB *phb, u_short tx_size, u_short rx_size, u_short rx_limit);
+
+/*
+** poll.c
+*/
+void tx_poll( Process *tx_poll_p);
+
+/*
+** process.c
+*/
+int  get_proc_space( Process **pd, int **pws, int wssize);
+
+/*
+** readrom.c
+*/
+void read_serial_number(char *buf);
+
+/*
+** rio.c
+*/
+int main( void );
+
+/*
+** route.c
+*/
+void route_update ( PKT *pkt, LPB *link);
+
+/*
+** rtainit.c
+*/
+#if defined(RTA)
+void rta_init(ushort RtaType);
+#endif /* defined(RTA) */
+
+/*
+** rupboot.c
+*/
+void rup_boot( PKT *pkt, RUP *this_rup, LPB *link);
+
+#ifdef RTA
+void kill_your_neighbour( int link_to_kill );
+#endif
+
+/*
+** rupcmd.c
+*/
+void rup_command( PKT *pkt, struct RUP *this_rup, LPB *link);
+
+/*
+** ruperr.c
+*/
+void rup_error( PKT *pkt, RUP *this_rup, LPB *link );
+void illegal_cmd( PKT *src_pkt );
+
+/*
+** ruppoll.c
+*/
+void rup_poll( PKT *pkt, RUP *this_rup, LPB *link );
+
+/*
+** ruppower.c
+*/
+void rup_power( PKT *pkt, RUP *this_rup, LPB *link );
+
+/*
+** ruprm.c
+*/
+void rup_route_map( PKT *pkt, RUP *this_rup, LPB *link);
+
+/*
+** rupstat.c
+*/
+void rup_status( PKT *pkt, RUP *this_rup, LPB *link);
+
+/*
+** rupsync.c
+*/
+void rup_sync( PKT *pkt);
+
+/*
+** rxpkt.c
+*/
+ERROR  rx_pkt( PKT_ptr_ptr pkt_address, LPB *link);
+
+/*
+** sendsts.c
+*/
+void send_status( PKT *requesting_pkt, RUP *this_rup);
+
+/*
+** serial.c
+*/
+void assign_serial ( char *ser_in, char *ser_out);
+int cmp_serial ( char *ser_1, char *ser_2);
+
+/*
+** txpkt.c
+*/
+ERROR  tx_pkt( PKT *pkt, LPB *link);
+short send_sync( LPB *link);
+
+#endif	/* _prototypes_h */
diff --git a/drivers/char/rio/protsts.h b/drivers/char/rio/protsts.h
new file mode 100644
index 0000000..848111a
--- /dev/null
+++ b/drivers/char/rio/protsts.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+ *******                                                              *******
+ *******      P R O T O C O L    S T A T U S   S T R U C T U R E      *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _protsts_h
+#define _protsts_h 1
+
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_protsts_h_sccs = "@(#)protsts.h	1.4"; */
+#endif
+#endif
+
+/*************************************************
+ * ACK bit. Last Packet received OK. Set by
+ * rxpkt to indicate that the Packet has been
+ * received OK and that the LTT must set the ACK
+ * bit in the next outward bound Packet
+ * and re-set by LTT's after xmit.
+ *
+ * Gets shoved into rx_status
+ ************************************************/
+#define PHB_RX_LAST_PKT_ACKED    ((ushort) 0x080)
+
+/*******************************************************
+ * The Rx TOGGLE bit.
+ * Stuffed into rx_status by RXPKT
+ ******************************************************/
+#define PHB_RX_DATA_WNDW         ((ushort) 0x040)
+
+/*******************************************************
+ * The Rx TOGGLE bit. Matches the setting in PKT.H
+ * Stuffed into rx_status
+ ******************************************************/
+#define PHB_RX_TGL               ((ushort) 0x2000)
+
+
+/*************************************************
+ * This bit is set by the LRT to indicate that
+ * an ACK (packet) must be returned.
+ *
+ * Gets shoved into tx_status
+ ************************************************/
+#define PHB_TX_SEND_PKT_ACK      ((ushort) 0x08)
+
+/*************************************************
+ * Set by LTT to indicate that an ACK is required
+ *************************************************/
+#define PHB_TX_ACK_RQRD         ((ushort) 0x01)
+
+
+/*******************************************************
+ * The Tx TOGGLE bit.
+ * Stuffed into tx_status by RXPKT from the PKT WndW
+ * field. Looked by the LTT when the NEXT Packet
+ * is going to be sent.
+ ******************************************************/
+#define PHB_TX_DATA_WNDW         ((ushort) 0x04)
+
+
+/*******************************************************
+ * The Tx TOGGLE bit. Matches the setting in PKT.H
+ * Stuffed into tx_status
+ ******************************************************/
+#define PHB_TX_TGL               ((ushort) 0x02)
+
+/*******************************************************
+ * Request intr bit. Set when the queue has gone quiet
+ * and the PHB has requested an interrupt.
+ ******************************************************/
+#define PHB_TX_INTR             ((ushort) 0x100)
+
+/*******************************************************
+ * SET if the PHB cannot send any more data down the
+ * Link
+ ******************************************************/
+#define PHB_TX_HANDSHAKE         ((ushort) 0x010)
+
+
+#define RUP_SEND_WNDW		 ((ushort) 0x08) ;
+
+#endif
+
+/*********** end of file ***********/
+
+
diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h
new file mode 100644
index 0000000..1fce02f
--- /dev/null
+++ b/drivers/char/rio/qbuf.h
@@ -0,0 +1,67 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******       Q U E U E    B U F F E R   S T R U C T U R E S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _qbuf_h
+#define _qbuf_h 1
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_qbuf_h_sccs = "@(#)qbuf.h	1.1" ;
+#endif
+#endif
+
+
+
+#ifdef HOST
+#define PKTS_PER_BUFFER    1
+#else
+#define PKTS_PER_BUFFER    (220 / PKT_LENGTH)
+#endif
+
+typedef struct Q_BUF Q_BUF ;
+struct Q_BUF  {
+                  Q_BUF_ptr next ;
+                  Q_BUF_ptr prev ;
+                  PKT_ptr buf[PKTS_PER_BUFFER] ;
+              } ;
+
+
+#endif
+
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h
new file mode 100644
index 0000000..13a9931
--- /dev/null
+++ b/drivers/char/rio/rio.h
@@ -0,0 +1,294 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rio.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)rio.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_rio_h__
+#define	__rio_rio_h__
+
+#ifdef SCCS_LABELS
+static char *_rio_h_sccs_ = "@(#)rio.h	1.3";
+#endif
+
+/*
+** 30.09.1998 ARG -
+** Introduced driver version and host card type strings
+*/
+#define RIO_DRV_STR "Specialix RIO Driver"
+#define RIO_AT_HOST_STR "ISA"
+#define RIO_PCI_HOST_STR "PCI"
+
+
+/*
+** rio_info_store() commands (arbitary values) :
+*/
+#define RIO_INFO_PUT	0xA4B3C2D1
+#define RIO_INFO_GET	0xF1E2D3C4
+
+
+/*
+** anything that I couldn't cram in somewhere else
+*/
+/*
+#ifndef RIODEBUG
+#define debug
+#else
+#define debug rioprint
+#endif
+*/
+
+
+/*
+**	Maximum numbers of things
+*/
+#define	RIO_SLOTS	4	/* number of configuration slots */
+#define	RIO_HOSTS	4	/* number of hosts that can be found */
+#define	PORTS_PER_HOST	128	/* number of ports per host */
+#define	LINKS_PER_UNIT	4	/* number of links from a host */
+#define	RIO_PORTS	(PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */
+#define	RTAS_PER_HOST	(MAX_RUP) /* number of RTAs per host */
+#define	PORTS_PER_RTA	(PORTS_PER_HOST/RTAS_PER_HOST)	/* ports on a rta */
+#define	PORTS_PER_MODULE 4	/* number of ports on a plug-in module */
+				/* number of modules on an RTA */
+#define	MODULES_PER_RTA	 (PORTS_PER_RTA/PORTS_PER_MODULE)
+#define MAX_PRODUCT	16	/* numbr of different product codes */
+#define MAX_MODULE_TYPES 16	/* number of different types of module */
+
+#define RIO_CONTROL_DEV	128	/* minor number of host/control device */
+#define RIO_INVALID_MAJOR 0	/* test first host card's major no for validity */
+
+/*
+** number of RTAs that can be bound to a master
+*/
+#define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS)
+
+/*
+**	Unit types
+*/
+#define PC_RTA16	0x90000000
+#define PC_RTA8		0xe0000000
+#define TYPE_HOST	0
+#define TYPE_RTA8	1
+#define TYPE_RTA16	2
+
+/*
+**	Flag values returned by functions
+*/
+#define	RIO_FAIL	-1
+#define	RIO_SUCCESS	0
+#define	COPYFAIL	-1	/* copy[in|out] failed */
+
+/*
+** SysPort value for something that hasn't any ports
+*/
+#define	NO_PORT	0xFFFFFFFF
+
+/*
+** Unit ID Of all hosts
+*/
+#define	HOST_ID	0
+
+/*
+** Break bytes into nybles
+*/
+#define	LONYBLE(X)	((X) & 0xF)
+#define	HINYBLE(X)	(((X)>>4) & 0xF)
+
+/*
+** Flag values passed into some functions
+*/
+#define	DONT_SLEEP	0
+#define	OK_TO_SLEEP	1
+
+#define	DONT_PRINT	1
+#define	DO_PRINT	0
+
+#define PRINT_TO_LOG_CONS	0
+#define PRINT_TO_CONS	1
+#define PRINT_TO_LOG	2
+
+/*
+** Timeout has trouble with times of less than 3 ticks...
+*/
+#define	MIN_TIMEOUT	3
+
+/*
+**	Generally useful constants
+*/
+#define	HALF_A_SECOND		((HZ)>>1)
+#define	A_SECOND		(HZ)
+#define	HUNDRED_HZ		((HZ/100)?(HZ/100):1)
+#define	FIFTY_HZ		((HZ/50)?(HZ/50):1)
+#define	TWENTY_HZ		((HZ/20)?(HZ/20):1)
+#define	TEN_HZ			((HZ/10)?(HZ/10):1)
+#define	FIVE_HZ			((HZ/5)?(HZ/5):1)
+#define	HUNDRED_MS		TEN_HZ
+#define	FIFTY_MS		TWENTY_HZ
+#define	TWENTY_MS		FIFTY_HZ
+#define	TEN_MS			HUNDRED_HZ
+#define	TWO_SECONDS		((A_SECOND)*2)
+#define	FIVE_SECONDS		((A_SECOND)*5)
+#define	TEN_SECONDS		((A_SECOND)*10)
+#define	FIFTEEN_SECONDS		((A_SECOND)*15)
+#define	TWENTY_SECONDS		((A_SECOND)*20)
+#define	HALF_A_MINUTE		(A_MINUTE>>1)
+#define	A_MINUTE		(A_SECOND*60)
+#define	FIVE_MINUTES		(A_MINUTE*5)
+#define	QUARTER_HOUR		(A_MINUTE*15)
+#define	HALF_HOUR		(A_MINUTE*30)
+#define	HOUR			(A_MINUTE*60)
+
+#define	SIXTEEN_MEG		0x1000000
+#define	ONE_MEG			0x100000
+#define	SIXTY_FOUR_K		0x10000
+
+#define	RIO_AT_MEM_SIZE		SIXTY_FOUR_K
+#define	RIO_EISA_MEM_SIZE	SIXTY_FOUR_K
+#define	RIO_MCA_MEM_SIZE	SIXTY_FOUR_K
+
+#define	POLL_VECTOR		0x100
+
+#define	COOK_WELL		0
+#define	COOK_MEDIUM		1
+#define	COOK_RAW		2
+
+/*
+**	Pointer manipulation stuff
+**	RIO_PTR takes hostp->Caddr and the offset into the DP RAM area
+**	and produces a UNIX caddr_t (pointer) to the object
+**	RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and
+**	returns the offset into the DP RAM area.
+*/
+#define	RIO_PTR(C,O) (((caddr_t)(C))+(0xFFFF&(O)))
+#define	RIO_OFF(C,O) ((int)(O)-(int)(C))
+
+/*
+**	How to convert from various different device number formats:
+**	DEV is a dev number, as passed to open, close etc - NOT a minor
+**	number!
+**
+**	Note:	LynxOS only gives us 8 bits for the device minor number,
+**		so all this crap here to deal with 'modem' bits etc. is
+**		just a load of irrelevant old bunkum!
+**		This however does not stop us needing to define a value
+**		for RIO_MODEMOFFSET which is required by the 'riomkdev'
+**		utility in the New Config Utilities suite.
+*/
+/* 0-511: direct 512-1023: modem */
+#define	RIO_MODEMOFFSET		0x200	/* doesn't mean anything */
+#define	RIO_MODEM_MASK		0x1FF
+#define	RIO_MODEM_BIT		0x200
+#define	RIO_UNMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_MASK)
+#define	RIO_ISMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_BIT)
+#define RIO_PORT(DEV,FIRST_MAJ)	( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \
+					+ MINOR(DEV)
+
+#define	splrio	spltty
+
+#define	RIO_IPL	5
+#define	RIO_PRI	(PZERO+10)
+#define RIO_CLOSE_PRI	PZERO-1	/* uninterruptible sleeps for close */
+
+typedef struct DbInf
+{
+	uint	Flag;
+	char	Name[8];
+} DbInf;
+
+#ifndef TRUE
+#define	TRUE (1==1)
+#endif
+#ifndef FALSE
+#define	FALSE	(!TRUE)
+#endif
+
+#define CSUM(pkt_ptr)  (((ushort *)(pkt_ptr))[0] + ((ushort *)(pkt_ptr))[1] + \
+			((ushort *)(pkt_ptr))[2] + ((ushort *)(pkt_ptr))[3] + \
+			((ushort *)(pkt_ptr))[4] + ((ushort *)(pkt_ptr))[5] + \
+			((ushort *)(pkt_ptr))[6] + ((ushort *)(pkt_ptr))[7] + \
+			((ushort *)(pkt_ptr))[8] + ((ushort *)(pkt_ptr))[9] )
+
+/*
+** This happy little macro copies SIZE bytes of data from FROM to TO
+** quite well. SIZE must be a constant.
+*/
+#define CCOPY( FROM, TO, SIZE ) { *(struct s { char data[SIZE]; } *)(TO) = *(struct s *)(FROM); }
+
+/*
+** increment a buffer pointer modulo the size of the buffer...
+*/
+#define	BUMP( P, I )	((P) = (((P)+(I)) & RIOBufferMask))
+
+#define INIT_PACKET( PK, PP ) \
+{ \
+	*((uint *)PK)    = PP->PacketInfo; \
+}
+
+#define	RIO_LINK_ENABLE	0x80FF /* FF is a hack, mainly for Mips, to        */
+			       /* prevent a really stupid race condition.  */
+
+#define	NOT_INITIALISED	0
+#define	INITIALISED	1
+
+#define	NOT_POLLING	0
+#define	POLLING		1
+
+#define	NOT_CHANGED	0
+#define	CHANGED		1
+
+#define	NOT_INUSE	0
+
+#define	DISCONNECT	0
+#define	CONNECT		1
+
+
+/*
+** Machine types - these must NOT overlap with product codes 0-15
+*/
+#define	RIO_MIPS_R3230	31
+#define	RIO_MIPS_R4030	32
+
+#define	RIO_IO_UNKNOWN	-2
+
+#undef	MODERN
+#define	ERROR( E )	do { u.u_error = E; return OPENFAIL } while ( 0 )
+
+/* Defines for MPX line discipline routines */
+
+#define DIST_LINESW_OPEN	0x01
+#define DIST_LINESW_CLOSE	0x02
+#define DIST_LINESW_READ	0x04
+#define DIST_LINESW_WRITE	0x08
+#define DIST_LINESW_IOCTL	0x10
+#define DIST_LINESW_INPUT	0x20
+#define DIST_LINESW_OUTPUT	0x40
+#define DIST_LINESW_MDMINT	0x80
+
+#endif /* __rio_h__ */
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
new file mode 100644
index 0000000..a91ae27
--- /dev/null
+++ b/drivers/char/rio/rio_linux.c
@@ -0,0 +1,1380 @@
+
+/* rio_linux.c -- Linux driver for the Specialix RIO series cards. 
+ *
+ *
+ *   (C) 1999 R.E.Wolff@BitWizard.nl
+ *
+ * Specialix pays for the development and support of this driver.
+ * Please DO contact support@specialix.co.uk if you require
+ * support. But please read the documentation (rio.txt) first.
+ *
+ *
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be
+ *      useful, but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139,
+ *      USA.
+ *
+ * Revision history:
+ * $Log: rio.c,v $
+ * Revision 1.1  1999/07/11 10:13:54  wolff
+ * Initial revision
+ *
+ * */
+
+#include <linux/module.h>
+#include <linux/config.h> 
+#include <linux/kdev_t.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/serial.h>
+#include <linux/fcntl.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+
+#include <linux/generic_serial.h>
+#include <asm/uaccess.h>
+
+#if BITS_PER_LONG != 32
+#  error FIXME: this driver only works on 32-bit platforms
+#endif
+
+#include "linux_compat.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+#include "protsts.h"
+#include "rioboard.h"
+
+
+#include "rio_linux.h"
+
+/* I don't think that this driver can handle more than 512 ports on
+one machine.  Specialix specifies max 4 boards in one machine. I don't
+know why. If you want to try anyway you'll have to increase the number
+of boards in rio.h.  You'll have to allocate more majors if you need
+more than 512 ports.... */
+
+#ifndef RIO_NORMAL_MAJOR0
+/* This allows overriding on the compiler commandline, or in a "major.h" 
+   include or something like that */
+#define RIO_NORMAL_MAJOR0  154
+#define RIO_NORMAL_MAJOR1  156
+#endif
+
+#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
+#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
+#endif
+
+#ifndef RIO_WINDOW_LEN 
+#define RIO_WINDOW_LEN 0x10000
+#endif
+
+
+/* Configurable options: 
+   (Don't be too sure that it'll work if you toggle them) */
+
+/* Am I paranoid or not ? ;-) */
+#undef RIO_PARANOIA_CHECK
+
+
+/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000
+   Hz, but it is user configurable. I don't recommend going above 1000
+   Hz. The interrupt ratelimit might trigger if the interrupt is
+   shared with a very active other device. 
+   undef this if you want to disable the check....
+*/
+#define IRQ_RATE_LIMIT 200
+
+#if 0
+/* Not implemented */
+/* 
+ * The following defines are mostly for testing purposes. But if you need
+ * some nice reporting in your syslog, you can define them also.
+ */
+#define RIO_REPORT_FIFO
+#define RIO_REPORT_OVERRUN
+#endif 
+
+
+/* These constants are derived from SCO Source */
+static struct Conf
+RIOConf =
+{
+  /* locator */         "RIO Config here",
+  /* startuptime */     HZ*2,           /* how long to wait for card to run */
+  /* slowcook */        0,              /* TRUE -> always use line disc. */
+  /* intrpolltime */    1,              /* The frequency of OUR polls */
+  /* breakinterval */   25,             /* x10 mS XXX: units seem to be 1ms not 10! -- REW*/
+  /* timer */           10,             /* mS */
+  /* RtaLoadBase */     0x7000,
+  /* HostLoadBase */    0x7C00,
+  /* XpHz */            5,              /* number of Xprint hits per second */
+  /* XpCps */           120,            /* Xprint characters per second */
+  /* XpOn */            "\033d#",       /* start Xprint for a wyse 60 */
+  /* XpOff */           "\024",         /* end Xprint for a wyse 60 */
+  /* MaxXpCps */        2000,           /* highest Xprint speed */
+  /* MinXpCps */        10,             /* slowest Xprint speed */
+  /* SpinCmds */        1,              /* non-zero for mega fast boots */
+  /* First Addr */      0x0A0000,       /* First address to look at */
+  /* Last Addr */       0xFF0000,       /* Last address looked at */
+  /* BufferSize */      1024,           /* Bytes per port of buffering */
+  /* LowWater */        256,            /* how much data left before wakeup */
+  /* LineLength */      80,             /* how wide is the console? */
+  /* CmdTimeout */      HZ,             /* how long a close command may take */
+};
+
+
+
+
+/* Function prototypes */
+
+static void rio_disable_tx_interrupts (void * ptr); 
+static void rio_enable_tx_interrupts (void * ptr); 
+static void rio_disable_rx_interrupts (void * ptr); 
+static void rio_enable_rx_interrupts (void * ptr); 
+static int  rio_get_CD (void * ptr); 
+static void rio_shutdown_port (void * ptr);
+static int  rio_set_real_termios (void  *ptr);
+static void rio_hungup (void  *ptr);
+static void rio_close (void  *ptr);
+static int rio_chars_in_buffer (void * ptr);
+static int rio_fw_ioctl (struct inode *inode, struct file *filp,
+		         unsigned int cmd, unsigned long arg);
+static int rio_init_drivers(void);
+
+static void my_hd (void *addr, int len);
+
+static struct tty_driver *rio_driver, *rio_driver2;
+
+/* The name "p" is a bit non-descript. But that's what the rio-lynxos
+sources use all over the place. */
+struct rio_info *p;
+
+int rio_debug;
+
+
+/* You can have the driver poll your card. 
+    - Set rio_poll to 1 to poll every timer tick (10ms on Intel). 
+      This is used when the card cannot use an interrupt for some reason.
+*/
+static int rio_poll = 1;
+
+
+/* These are the only open spaces in my computer. Yours may have more
+   or less.... */
+static int rio_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000};
+
+#define NR_RIO_ADDRS (sizeof(rio_probe_addrs)/sizeof (int))
+
+
+/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
+   Some architectures may need more. -- Changed to LONG to
+   support up to 64 bits on 64bit architectures. -- REW 20/06/99 */
+long rio_irqmask = -1;
+
+MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>");
+MODULE_DESCRIPTION("RIO driver");
+MODULE_LICENSE("GPL");
+module_param(rio_poll, int, 0);
+module_param(rio_debug, int, 0644);
+module_param(rio_irqmask, long, 0);
+
+static struct real_driver rio_real_driver = {
+  rio_disable_tx_interrupts,
+  rio_enable_tx_interrupts,
+  rio_disable_rx_interrupts,
+  rio_enable_rx_interrupts,
+  rio_get_CD,
+  rio_shutdown_port, 
+  rio_set_real_termios, 
+  rio_chars_in_buffer,
+  rio_close,
+  rio_hungup,
+  NULL
+};
+
+/* 
+ *  Firmware loader driver specific routines
+ *
+ */
+
+static struct file_operations rio_fw_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= rio_fw_ioctl,
+};
+
+static struct miscdevice rio_fw_device = {
+	RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops
+};
+
+
+
+
+
+#ifdef RIO_PARANOIA_CHECK
+
+/* This doesn't work. Who's paranoid around here? Not me! */
+
+static inline int rio_paranoia_check(struct rio_port const * port,
+				    char *name, const char *routine)
+{
+
+  static const char *badmagic =
+    KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
+  static const char *badinfo =
+    KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
+ 
+  if (!port) {
+    printk (badinfo, name, routine);
+    return 1;
+  }
+  if (port->magic != RIO_MAGIC) {
+    printk (badmagic, name, routine);
+    return 1;
+  }
+
+  return 0;
+}
+#else
+#define rio_paranoia_check(a,b,c) 0
+#endif
+
+
+#ifdef DEBUG
+static void my_hd (void *ad, int len)
+{
+  int i, j, ch;
+  unsigned char *addr = ad;
+  
+  for (i=0;i<len;i+=16) {
+    rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i);
+    for (j=0;j<16;j++) {
+      rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":"");
+    }
+    for (j=0;j<16;j++) {
+      ch = addr[j+i];
+      rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+    }
+    rio_dprintk (RIO_DEBUG_PARAM, "\n");
+  }
+}
+#else
+#define my_hd(ad,len) do{/* nothing*/ } while (0)
+#endif
+
+
+/* Delay a number of jiffies, allowing a signal to interrupt */ 
+int RIODelay (struct Port *PortP, int njiffies)
+{
+  func_enter ();
+
+  rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);  
+  msleep_interruptible(jiffies_to_msecs(njiffies));
+  func_exit();
+
+  if (signal_pending(current))
+    return RIO_FAIL;
+  else
+    return !RIO_FAIL;
+}
+
+
+/* Delay a number of jiffies, disallowing a signal to interrupt */ 
+int RIODelay_ni (struct Port *PortP, int njiffies)
+{
+  func_enter ();
+
+  rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);  
+  msleep(jiffies_to_msecs(njiffies));
+  func_exit();
+  return !RIO_FAIL;
+}
+
+
+int rio_minor(struct tty_struct *tty)
+{
+	return tty->index + (tty->driver == rio_driver) ? 0 : 256;
+}
+
+
+int rio_ismodem(struct tty_struct *tty)
+{
+	return 1;
+}
+
+
+void rio_udelay (int usecs)
+{
+  udelay (usecs);
+}
+
+static int rio_set_real_termios (void *ptr)
+{
+  int rv, modem;
+  struct tty_struct *tty;
+  func_enter();
+
+  tty = ((struct Port *)ptr)->gs.tty;
+
+  modem = rio_ismodem(tty);
+
+  rv = RIOParam( (struct Port *) ptr, CONFIG, modem, 1);
+
+  func_exit ();
+
+  return rv;
+}
+
+
+static void rio_reset_interrupt (struct Host *HostP)
+{
+  func_enter();
+
+  switch( HostP->Type ) {
+  case RIO_AT:
+  case RIO_MCA:
+  case RIO_PCI:
+    WBYTE(HostP->ResetInt , 0xff);
+  }
+
+  func_exit();
+}
+
+
+static irqreturn_t rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
+{
+  struct Host *HostP;
+  func_enter ();
+
+  HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */
+  rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", 
+               irq, HostP->Ivec); 
+
+  /* AAargh! The order in which to do these things is essential and
+     not trivial. 
+     
+     - Rate limit goes before "recursive". Otherwise a series of
+       recursive calls will hang the machine in the interrupt routine. 
+
+     - hardware twiddling goes before "recursive". Otherwise when we
+       poll the card, and a recursive interrupt happens, we won't
+       ack the card, so it might keep on interrupting us. (especially
+       level sensitive interrupt systems like PCI).
+
+     - Rate limit goes before hardware twiddling. Otherwise we won't
+       catch a card that has gone bonkers.
+
+     - The "initialized" test goes after the hardware twiddling. Otherwise
+       the card will stick us in the interrupt routine again.
+
+     - The initialized test goes before recursive. 
+  */
+
+
+
+#ifdef IRQ_RATE_LIMIT
+  /* Aaargh! I'm ashamed. This costs more lines-of-code than the
+     actual interrupt routine!. (Well, used to when I wrote that comment) */
+  {
+    static int lastjif;
+    static int nintr=0;
+
+    if (lastjif == jiffies) {
+      if (++nintr > IRQ_RATE_LIMIT) {
+        free_irq (HostP->Ivec, ptr);
+        printk (KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n", 
+                HostP->Ivec);
+      }
+    } else {
+      lastjif = jiffies;
+      nintr = 0;
+    }
+  }
+#endif
+  rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n"); 
+  if (HostP->Ivec == irq) {
+    /* Tell the card we've noticed the interrupt. */
+    rio_reset_interrupt (HostP);
+  }
+
+  if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
+  	return IRQ_HANDLED;
+
+  if (test_and_set_bit (RIO_BOARD_INTR_LOCK, &HostP->locks)) {
+    printk (KERN_ERR "Recursive interrupt! (host %d/irq%d)\n", 
+            (int) ptr, HostP->Ivec);
+    return IRQ_HANDLED;
+  }
+
+  RIOServiceHost(p, HostP, irq);
+
+  rio_dprintk ( RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n", 
+                (int) ptr, HostP->Type);
+
+  clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks);
+  rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", 
+               irq, HostP->Ivec); 
+  func_exit ();
+  return IRQ_HANDLED;
+}
+
+
+static void rio_pollfunc (unsigned long data)
+{
+  func_enter ();
+
+  rio_interrupt (0, &p->RIOHosts[data], NULL);
+  p->RIOHosts[data].timer.expires = jiffies + rio_poll;
+  add_timer (&p->RIOHosts[data].timer);
+
+  func_exit ();
+}
+
+
+/* ********************************************************************** *
+ *                Here are the routines that actually                     *
+ *              interface with the generic_serial driver                  *
+ * ********************************************************************** */
+
+/* Ehhm. I don't know how to fiddle with interrupts on the Specialix 
+   cards. ....   Hmm. Ok I figured it out. You don't.  -- REW */
+
+static void rio_disable_tx_interrupts (void * ptr) 
+{
+  func_enter();
+
+  /*  port->gs.flags &= ~GS_TX_INTEN; */
+
+  func_exit();
+}
+
+
+static void rio_enable_tx_interrupts (void * ptr) 
+{
+  struct Port *PortP = ptr;
+  /* int hn; */
+
+  func_enter();
+
+  /* hn = PortP->HostP - p->RIOHosts;
+
+     rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
+     rio_interrupt (-1,(void *) hn, NULL); */
+
+  RIOTxEnable((char *) PortP);
+
+  /* 
+   * In general we cannot count on "tx empty" interrupts, although
+   * the interrupt routine seems to be able to tell the difference. 
+   */
+  PortP->gs.flags &= ~GS_TX_INTEN;
+
+  func_exit();
+}
+
+
+static void rio_disable_rx_interrupts (void * ptr) 
+{
+  func_enter();
+  func_exit();
+}
+
+static void rio_enable_rx_interrupts (void * ptr) 
+{
+  /*  struct rio_port *port = ptr; */
+  func_enter();
+  func_exit();
+}
+
+
+/* Jeez. Isn't this simple?  */
+static int rio_get_CD (void * ptr) 
+{
+  struct Port *PortP = ptr;
+  int rv;
+
+  func_enter();
+  rv = (PortP->ModemState & MSVR1_CD) != 0;
+
+  rio_dprintk (RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
+  
+  func_exit();  
+  return rv;
+}
+
+
+/* Jeez. Isn't this simple? Actually, we can sync with the actual port
+   by just pushing stuff into the queue going to the port... */
+static int rio_chars_in_buffer (void * ptr) 
+{
+  func_enter();
+
+  func_exit();  
+  return 0;
+}
+
+
+/* Nothing special here... */
+static void rio_shutdown_port (void * ptr) 
+{
+  struct Port *PortP;
+
+  func_enter();
+
+  PortP = (struct Port *)ptr;
+  PortP->gs.tty = NULL;
+#if 0
+  port->gs.flags &= ~ GS_ACTIVE;
+  if (!port->gs.tty) {
+    rio_dprintk (RIO_DBUG_TTY, "No tty.\n");
+    return;
+  }
+  if (!port->gs.tty->termios) {
+    rio_dprintk (RIO_DEBUG_TTY, "No termios.\n");
+    return;
+  }
+  if (port->gs.tty->termios->c_cflag & HUPCL) {
+    rio_setsignals (port, 0, 0);
+  }
+#endif
+
+  func_exit();
+}
+
+
+/* I haven't the foggiest why the decrement use count has to happen
+   here. The whole linux serial drivers stuff needs to be redesigned.
+   My guess is that this is a hack to minimize the impact of a bug
+   elsewhere. Thinking about it some more. (try it sometime) Try
+   running minicom on a serial port that is driven by a modularized
+   driver. Have the modem hangup. Then remove the driver module. Then
+   exit minicom.  I expect an "oops".  -- REW */
+static void rio_hungup (void *ptr)
+{
+  struct Port *PortP;
+
+  func_enter();
+  
+  PortP = (struct Port *)ptr;
+  PortP->gs.tty = NULL;
+
+  func_exit ();
+}
+
+
+/* The standard serial_close would become shorter if you'd wrap it like
+   this. 
+   rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;}
+ */
+static void rio_close (void *ptr)
+{
+  struct Port *PortP;
+
+  func_enter ();
+
+  PortP = (struct Port *)ptr;
+
+  riotclose (ptr);
+
+  if(PortP->gs.count) {
+    printk (KERN_ERR "WARNING port count:%d\n", PortP->gs.count);
+    PortP->gs.count = 0; 
+  }                
+
+  PortP->gs.tty = NULL;
+  func_exit ();
+}
+
+
+
+static int rio_fw_ioctl (struct inode *inode, struct file *filp,
+		         unsigned int cmd, unsigned long arg)
+{
+  int rc = 0;
+  func_enter();
+
+  /* The "dev" argument isn't used. */
+  rc = riocontrol (p, 0, cmd, (void *)arg, capable(CAP_SYS_ADMIN));
+
+  func_exit ();
+  return rc;
+}
+
+extern int RIOShortCommand(struct rio_info *p, struct Port *PortP,
+               int command, int len, int arg);
+
+static int rio_ioctl (struct tty_struct * tty, struct file * filp, 
+                     unsigned int cmd, unsigned long arg)
+{
+  int rc;
+  struct Port *PortP;
+  int ival;
+
+  func_enter();
+
+  PortP = (struct Port *)tty->driver_data;
+
+  rc  = 0;
+  switch (cmd) {
+#if 0
+  case TIOCGSOFTCAR:
+    rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+                  (unsigned int *) arg);
+    break;
+#endif
+  case TIOCSSOFTCAR:
+    if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
+      tty->termios->c_cflag =
+        (tty->termios->c_cflag & ~CLOCAL) |
+        (ival ? CLOCAL : 0);
+    }
+    break;
+  case TIOCGSERIAL:
+    rc = -EFAULT;
+    if (access_ok(VERIFY_WRITE, (void *) arg,
+                          sizeof(struct serial_struct)))
+      rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg);
+    break;
+  case TCSBRK:
+    if ( PortP->State & RIO_DELETED ) {
+      rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+      rc = -EIO;      
+    } else {
+      if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) {
+         rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+         rc = -EIO;
+      }          
+    }
+    break;
+  case TCSBRKP:
+    if ( PortP->State & RIO_DELETED ) {
+      rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+      rc = -EIO;      
+    } else {
+      int l;
+      l = arg?arg*100:250;
+      if (l > 255) l = 255;
+      if (RIOShortCommand(p, PortP, SBREAK, 2, arg?arg*100:250) == RIO_FAIL) {
+         rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+         rc = -EIO;
+      }          
+    }
+    break;
+  case TIOCSSERIAL:
+    rc = -EFAULT;
+    if (access_ok(VERIFY_READ, (void *) arg,
+                          sizeof(struct serial_struct)))
+      rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
+    break;
+#if 0
+  /*
+   * note: these IOCTLs no longer reach here.  Use
+   * tiocmset/tiocmget driver methods instead.  The
+   * #if 0 disablement predates this comment.
+   */
+  case TIOCMGET:
+    rc = -EFAULT;
+    if (access_ok(VERIFY_WRITE, (void *) arg,
+                          sizeof(unsigned int))) {
+      rc = 0;
+      ival = rio_getsignals(port);
+      put_user(ival, (unsigned int *) arg);
+    }
+    break;
+  case TIOCMBIS:
+    if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
+                           ((ival & TIOCM_RTS) ? 1 : -1));
+    }
+    break;
+  case TIOCMBIC:
+    if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
+                           ((ival & TIOCM_RTS) ? 0 : -1));
+    }
+    break;
+  case TIOCMSET:
+    if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
+                           ((ival & TIOCM_RTS) ? 1 : 0));
+    }
+    break;
+#endif
+  default:
+    rc = -ENOIOCTLCMD;
+    break;
+  }
+  func_exit();
+  return rc;
+}
+
+
+/* The throttle/unthrottle scheme for the Specialix card is different
+ * from other drivers and deserves some explanation. 
+ * The Specialix hardware takes care of XON/XOFF
+ * and CTS/RTS flow control itself.  This means that all we have to
+ * do when signalled by the upper tty layer to throttle/unthrottle is
+ * to make a note of it here.  When we come to read characters from the
+ * rx buffers on the card (rio_receive_chars()) we look to see if the
+ * upper layer can accept more (as noted here in rio_rx_throt[]). 
+ * If it can't we simply don't remove chars from the cards buffer. 
+ * When the tty layer can accept chars, we again note that here and when
+ * rio_receive_chars() is called it will remove them from the cards buffer.
+ * The card will notice that a ports buffer has drained below some low
+ * water mark and will unflow control the line itself, using whatever
+ * flow control scheme is in use for that port. -- Simon Allen
+ */
+
+static void rio_throttle (struct tty_struct * tty)
+{
+  struct Port *port = (struct Port *)tty->driver_data;
+  
+  func_enter();
+  /* If the port is using any type of input flow
+   * control then throttle the port.
+   */
+
+  if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) {
+    port->State |= RIO_THROTTLE_RX;
+  }
+
+  func_exit();
+}
+
+
+static void rio_unthrottle (struct tty_struct * tty)
+{
+  struct Port *port = (struct Port *)tty->driver_data;
+
+  func_enter();
+  /* Always unthrottle even if flow control is not enabled on
+   * this port in case we disabled flow control while the port
+   * was throttled
+   */
+
+  port->State &= ~RIO_THROTTLE_RX;
+
+  func_exit();
+  return;
+}
+
+
+
+
+
+/* ********************************************************************** *
+ *                    Here are the initialization routines.               *
+ * ********************************************************************** */
+
+
+static struct vpd_prom *get_VPD_PROM (struct Host *hp)
+{
+  static struct vpd_prom vpdp;
+  char *p;
+  int i;
+
+  func_enter();
+  rio_dprintk (RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", 
+              hp->Caddr + RIO_VPD_ROM);
+
+  p = (char *) &vpdp;
+  for (i=0;i< sizeof (struct vpd_prom);i++)
+    *p++ = readb (hp->Caddr+RIO_VPD_ROM + i*2);
+      /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
+
+  /* Terminate the identifier string. 
+     *** requires one extra byte in struct vpd_prom *** */
+  *p++=0; 
+
+  if (rio_debug & RIO_DEBUG_PROBE)
+    my_hd ((char *)&vpdp, 0x20);
+  
+  func_exit();
+
+  return &vpdp;
+}
+
+static struct tty_operations rio_ops = {
+	.open  = riotopen,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = rio_ioctl,
+	.throttle = rio_throttle,
+	.unthrottle = rio_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+};
+
+static int rio_init_drivers(void)
+{
+	int error = -ENOMEM;
+
+	rio_driver = alloc_tty_driver(256);
+	if (!rio_driver)
+		goto out;
+	rio_driver2 = alloc_tty_driver(256);
+	if (!rio_driver2)
+		goto out1;
+
+	func_enter();
+
+	rio_driver->owner = THIS_MODULE;
+	rio_driver->driver_name = "specialix_rio";
+	rio_driver->name = "ttySR";
+	rio_driver->major = RIO_NORMAL_MAJOR0;
+	rio_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	rio_driver->subtype = SERIAL_TYPE_NORMAL;
+	rio_driver->init_termios = tty_std_termios;
+	rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	rio_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(rio_driver, &rio_ops);
+
+	rio_driver2->owner = THIS_MODULE;
+	rio_driver2->driver_name = "specialix_rio";
+	rio_driver2->name = "ttySR";
+	rio_driver2->major = RIO_NORMAL_MAJOR1;
+	rio_driver2->type = TTY_DRIVER_TYPE_SERIAL;
+	rio_driver2->subtype = SERIAL_TYPE_NORMAL;
+	rio_driver2->init_termios = tty_std_termios;
+	rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	rio_driver2->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(rio_driver2, &rio_ops);
+
+	rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
+
+	if ((error = tty_register_driver(rio_driver)))
+		goto out2;
+	if ((error = tty_register_driver(rio_driver2)))
+		goto out3;
+	func_exit();
+	return 0;
+out3:
+	tty_unregister_driver(rio_driver);
+out2:
+	put_tty_driver(rio_driver2);
+out1:
+	put_tty_driver(rio_driver);
+out:
+	printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n",
+	     error);
+	return 1;
+}
+
+
+static void * ckmalloc (int size)
+{
+  void *p;
+
+  p = kmalloc(size, GFP_KERNEL);
+  if (p) 
+    memset(p, 0, size);
+  return p;
+}
+
+
+
+static int rio_init_datastructures (void)
+{
+  int i;
+  struct Port *port;
+  func_enter();
+
+  /* Many drivers statically allocate the maximum number of ports
+     There is no reason not to allocate them dynamically. Is there? -- REW */
+  /* However, the RIO driver allows users to configure their first
+     RTA as the ports numbered 504-511. We therefore need to allocate 
+     the whole range. :-(   -- REW */
+  
+#define RI_SZ   sizeof(struct rio_info)
+#define HOST_SZ sizeof(struct Host)
+#define PORT_SZ sizeof(struct Port *)
+#define TMIO_SZ sizeof(struct termios *)
+  rio_dprintk (RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n", 
+               RI_SZ, 
+               RIO_HOSTS * HOST_SZ,
+               RIO_PORTS * PORT_SZ,
+               RIO_PORTS * TMIO_SZ,
+               RIO_PORTS * TMIO_SZ);
+  
+  if (!(p                  = ckmalloc (              RI_SZ))) goto free0;
+  if (!(p->RIOHosts        = ckmalloc (RIO_HOSTS * HOST_SZ))) goto free1;
+  if (!(p->RIOPortp        = ckmalloc (RIO_PORTS * PORT_SZ))) goto free2;
+  p->RIOConf = RIOConf;
+  rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p\n", 
+               p, p->RIOHosts, p->RIOPortp);
+
+#if 1
+  for (i = 0; i < RIO_PORTS; i++) {
+    port = p->RIOPortp[i] = ckmalloc (sizeof (struct Port));
+    if (!port) {
+      goto free6;
+    }
+    rio_dprintk (RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
+    port->PortNum = i;
+    port->gs.magic = RIO_MAGIC;
+    port->gs.close_delay = HZ/2;
+    port->gs.closing_wait = 30 * HZ;
+    port->gs.rd = &rio_real_driver;
+    spin_lock_init(&port->portSem);
+    /*
+     * Initializing wait queue
+     */
+    init_waitqueue_head(&port->gs.open_wait);
+    init_waitqueue_head(&port->gs.close_wait);
+  }
+#else
+  /* We could postpone initializing them to when they are configured. */
+#endif
+
+
+  
+  if (rio_debug & RIO_DEBUG_INIT) {
+    my_hd (&rio_real_driver, sizeof (rio_real_driver));
+  }
+
+  
+  func_exit();
+  return 0;
+
+ free6:for (i--;i>=0;i--)
+        kfree (p->RIOPortp[i]);
+/*free5:
+ free4:
+ free3:*/kfree (p->RIOPortp);
+ free2:kfree (p->RIOHosts);
+ free1:
+  rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", 
+        	       p, p->RIOHosts, p->RIOPortp);
+  kfree(p);        	      
+ free0:
+  return -ENOMEM;
+}
+
+static void  __exit rio_release_drivers(void)
+{
+  func_enter();
+  tty_unregister_driver(rio_driver2);
+  tty_unregister_driver(rio_driver);
+  put_tty_driver(rio_driver2);
+  put_tty_driver(rio_driver);
+  func_exit();
+}
+
+
+#ifdef CONFIG_PCI
+ /* This was written for SX, but applies to RIO too...
+    (including bugs....)
+
+    There is another bit besides Bit 17. Turning that bit off
+    (on boards shipped with the fix in the eeprom) results in a 
+    hang on the next access to the card. 
+ */
+
+ /******************************************************** 
+ * Setting bit 17 in the CNTRL register of the PLX 9050  * 
+ * chip forces a retry on writes while a read is pending.*
+ * This is to prevent the card locking up on Intel Xeon  *
+ * multiprocessor systems with the NX chipset.    -- NV  *
+ ********************************************************/
+
+/* Newer cards are produced with this bit set from the configuration
+   EEprom.  As the bit is read/write for the CPU, we can fix it here,
+   if we detect that it isn't set correctly. -- REW */
+
+static void fix_rio_pci (struct pci_dev *pdev)
+{
+  unsigned int hwbase;
+  unsigned long rebase;
+  unsigned int t;
+
+#define CNTRL_REG_OFFSET        0x50
+#define CNTRL_REG_GOODVALUE     0x18260000
+
+  pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
+  hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
+  rebase =  (ulong) ioremap(hwbase, 0x80);
+  t = readl (rebase + CNTRL_REG_OFFSET);
+  if (t != CNTRL_REG_GOODVALUE) {
+    printk (KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", 
+            t, CNTRL_REG_GOODVALUE); 
+    writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);  
+  }
+  iounmap((char*) rebase);
+}
+#endif
+
+
+static int __init rio_init(void) 
+{
+  int found = 0;
+  int i;
+  struct Host *hp;
+  int retval;
+  struct vpd_prom *vpdp;
+  int okboard;
+
+#ifdef CONFIG_PCI
+  struct pci_dev *pdev = NULL;
+  unsigned int tint;
+  unsigned short tshort;
+#endif
+
+  func_enter();
+  rio_dprintk (RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", 
+	       rio_debug);
+
+  if (abs ((long) (&rio_debug) - rio_debug) < 0x10000) {
+    printk (KERN_WARNING "rio: rio_debug is an address, instead of a value. "
+            "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
+    rio_debug=-1;
+  }
+
+  if (misc_register(&rio_fw_device) < 0) {
+    printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
+    return -EIO;
+  }
+
+  retval = rio_init_datastructures ();
+  if (retval < 0) {
+    misc_deregister(&rio_fw_device);
+    return retval;
+  }
+
+#ifdef CONFIG_PCI
+    /* First look for the JET devices: */
+    while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
+                                    PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, 
+                                    pdev))) {
+       if (pci_enable_device(pdev)) continue;
+
+      /* Specialix has a whole bunch of cards with
+         0x2000 as the device ID. They say its because
+         the standard requires it. Stupid standard. */
+      /* It seems that reading a word doesn't work reliably on 2.0.
+         Also, reading a non-aligned dword doesn't work. So we read the
+         whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
+         ourselves */
+      /* I don't know why the define doesn't work, constant 0x2c does --REW */ 
+      pci_read_config_dword (pdev, 0x2c, &tint);
+      tshort = (tint >> 16) & 0xffff;
+      rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
+      if (tshort != 0x0100) {
+        rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", 
+                    tshort);
+        continue;
+      }
+      rio_dprintk (RIO_DEBUG_PROBE, "cp1\n");
+
+      pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
+
+      hp = &p->RIOHosts[p->RIONumHosts];
+      hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
+      hp->Ivec = pdev->irq;
+      if (((1 << hp->Ivec) & rio_irqmask) == 0)
+              hp->Ivec = 0;
+      hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->CardP	= (struct DpRam *) hp->Caddr;
+      hp->Type  = RIO_PCI;
+      hp->Copy  = rio_pcicopy; 
+      hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
+      spin_lock_init(&hp->HostLock);
+      rio_reset_interrupt (hp);
+      rio_start_card_running (hp);
+
+      rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
+                   (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
+                   p->RIOHosts[p->RIONumHosts].Caddr);
+      if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
+                        p->RIOHosts[p->RIONumHosts].Caddr, 
+                        RIO_PCI, 0 ) == RIO_SUCCESS) {
+              rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n");
+              WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+              p->RIOHosts[p->RIONumHosts].UniqueNum  =
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
+              rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+                           p->RIOHosts[p->RIONumHosts].UniqueNum);
+              
+              fix_rio_pci (pdev);
+              p->RIOLastPCISearch = RIO_SUCCESS;
+              p->RIONumHosts++;
+              found++;
+      } else {
+              iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
+      }
+    }
+    
+    /* Then look for the older PCI card.... : */
+
+  /* These older PCI cards have problems (only byte-mode access is
+     supported), which makes them a bit awkward to support. 
+     They also have problems sharing interrupts. Be careful. 
+     (The driver now refuses to share interrupts for these
+     cards. This should be sufficient).
+  */
+
+    /* Then look for the older RIO/PCI devices: */
+    while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
+                                    PCI_DEVICE_ID_SPECIALIX_RIO, 
+                                    pdev))) {
+       if (pci_enable_device(pdev)) continue;
+
+#ifdef CONFIG_RIO_OLDPCI
+      pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint);
+
+      hp = &p->RIOHosts[p->RIONumHosts];
+      hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
+      hp->Ivec = pdev->irq;
+      if (((1 << hp->Ivec) & rio_irqmask) == 0) 
+      	hp->Ivec = 0;
+      hp->Ivec |= 0x8000; /* Mark as non-sharable */
+      hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->CardP	= (struct DpRam *) hp->Caddr;
+      hp->Type  = RIO_PCI;
+      hp->Copy  = rio_pcicopy;
+      hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
+      spin_lock_init(&hp->HostLock);
+
+      rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
+      rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
+
+      rio_reset_interrupt (hp);
+      rio_start_card_running (hp);
+       rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
+                   (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
+                   p->RIOHosts[p->RIONumHosts].Caddr);
+      if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
+                        p->RIOHosts[p->RIONumHosts].Caddr, 
+                        RIO_PCI, 0 ) == RIO_SUCCESS) {
+        WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+        p->RIOHosts[p->RIONumHosts].UniqueNum  =
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
+          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
+        rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+                   p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+        p->RIOLastPCISearch = RIO_SUCCESS;
+        p->RIONumHosts++;
+        found++;
+      } else {
+        iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
+      }
+#else
+      printk (KERN_ERR "Found an older RIO PCI card, but the driver is not "
+              "compiled to support it.\n");
+#endif
+    }
+#endif /* PCI */
+
+  /* Now probe for ISA cards... */
+  for (i=0;i<NR_RIO_ADDRS;i++) {
+    hp = &p->RIOHosts[p->RIONumHosts];
+    hp->PaddrP = rio_probe_addrs[i];
+    /* There was something about the IRQs of these cards. 'Forget what.--REW */
+    hp->Ivec = 0;
+    hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+    hp->CardP = (struct DpRam *) hp->Caddr;
+    hp->Type = RIO_AT;
+    hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
+                             * -- YES! this is now a normal copy. Only the 
+                             * old PCI card uses the special PCI copy. 
+                             * Moreover, the ISA card will work with the 
+                             * special PCI copy anyway. -- REW */
+    hp->Mode = 0;
+    spin_lock_init(&hp->HostLock);
+
+    vpdp = get_VPD_PROM (hp);
+    rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n");
+    okboard = 0;
+    if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) ||
+        (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) ||
+        (strncmp (vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
+      /* Board is present... */
+      if (RIOBoardTest (hp->PaddrP, 
+                        hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) {
+        /* ... and feeling fine!!!! */
+        rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+                   p->RIOHosts[p->RIONumHosts].UniqueNum);
+        if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {        
+          rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n",
+                       p->RIONumHosts, 
+                       p->RIOHosts[p->RIONumHosts-1].UniqueNum);
+          okboard++;
+          found++;
+        }
+      }
+
+    if (!okboard)
+      iounmap ((char*) (hp->Caddr));
+    }
+  }
+
+
+  for (i=0;i<p->RIONumHosts;i++) {
+    hp = &p->RIOHosts[i];
+    if (hp->Ivec) {
+      int mode = SA_SHIRQ;
+      if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;}
+      rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode);
+      retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp);
+      rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
+      if (retval) {
+              printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
+              hp->Ivec = 0;
+      }
+      rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
+      if (hp->Ivec != 0){
+              rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); 
+              hp->Mode |= RIO_PCI_INT_ENABLE;
+      } else
+              hp->Mode &= !RIO_PCI_INT_ENABLE;
+      rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
+      rio_start_card_running (hp);
+    }
+    /* Init the timer "always" to make sure that it can safely be 
+       deleted when we unload... */
+
+    init_timer (&hp->timer);
+    if (!hp->Ivec) {
+      rio_dprintk (RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", 
+                   rio_poll);
+      hp->timer.data = i;
+      hp->timer.function = rio_pollfunc;
+      hp->timer.expires = jiffies + rio_poll;
+      add_timer (&hp->timer);
+    }
+  }
+
+  if (found) {
+    rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
+    rio_init_drivers ();
+  } else {
+    /* deregister the misc device we created earlier */
+    misc_deregister(&rio_fw_device);
+  }
+
+  func_exit();
+  return found?0:-EIO;
+}
+
+
+static void __exit rio_exit (void)
+{
+  int i; 
+  struct Host *hp;
+  
+  func_enter();
+
+  for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) {
+    RIOHostReset (hp->Type, hp->CardP, hp->Slot);
+    if (hp->Ivec) {
+      free_irq (hp->Ivec, hp);
+      rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
+    }
+    /* It is safe/allowed to del_timer a non-active timer */
+    del_timer (&hp->timer);
+  }
+
+  if (misc_deregister(&rio_fw_device) < 0) {
+    printk (KERN_INFO "rio: couldn't deregister control-device\n");
+  }
+
+
+  rio_dprintk (RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
+
+  rio_release_drivers ();
+
+  /* Release dynamically allocated memory */
+  kfree (p->RIOPortp);
+  kfree (p->RIOHosts);
+  kfree (p);
+
+  func_exit();
+}
+
+module_init(rio_init);
+module_exit(rio_exit);
+
+/*
+ * Anybody who knows why this doesn't work for me, please tell me -- REW.
+ * Snatched from scsi.c (fixed one spelling error):
+ * Overrides for Emacs so that we follow Linus' tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local Variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
+
diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h
new file mode 100644
index 0000000..1fba19d5
--- /dev/null
+++ b/drivers/char/rio/rio_linux.h
@@ -0,0 +1,187 @@
+
+/*
+ *  rio_linux.h
+ *
+ *  Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.nl
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  RIO serial driver.
+ *
+ *  Version 1.0 -- July, 1999. 
+ * 
+ */
+#include <linux/config.h>
+
+#define RIO_NBOARDS        4
+#define RIO_PORTSPERBOARD 128
+#define RIO_NPORTS        (RIO_NBOARDS * RIO_PORTSPERBOARD)
+
+#define MODEM_SUPPORT
+
+#ifdef __KERNEL__
+
+#define RIO_MAGIC 0x12345678
+
+
+struct vpd_prom {
+  unsigned short id;
+  char hwrev;
+  char hwass;
+  int uniqid;
+  char myear;
+  char mweek;
+  char hw_feature[5];
+  char oem_id;
+  char identifier[16];
+};
+
+
+#define RIO_DEBUG_ALL           0xffffffff
+
+#define O_OTHER(tty)    \
+      ((O_OLCUC(tty))  ||\
+      (O_ONLCR(tty))   ||\
+      (O_OCRNL(tty))   ||\
+      (O_ONOCR(tty))   ||\
+      (O_ONLRET(tty))  ||\
+      (O_OFILL(tty))   ||\
+      (O_OFDEL(tty))   ||\
+      (O_NLDLY(tty))   ||\
+      (O_CRDLY(tty))   ||\
+      (O_TABDLY(tty))  ||\
+      (O_BSDLY(tty))   ||\
+      (O_VTDLY(tty))   ||\
+      (O_FFDLY(tty)))
+
+/* Same for input. */
+#define I_OTHER(tty)    \
+      ((I_INLCR(tty))  ||\
+      (I_IGNCR(tty))   ||\
+      (I_ICRNL(tty))   ||\
+      (I_IUCLC(tty))   ||\
+      (L_ISIG(tty)))
+
+
+#endif /* __KERNEL__ */
+
+
+#define RIO_BOARD_INTR_LOCK  1
+
+
+#ifndef RIOCTL_MISC_MINOR 
+/* Allow others to gather this into "major.h" or something like that */
+#define RIOCTL_MISC_MINOR    169
+#endif
+
+
+/* Allow us to debug "in the field" without requiring clients to
+   recompile.... */
+#if 1
+#define rio_spin_lock_irqsave(sem, flags) do { \
+	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \
+	                                sem, __FILE__, __LINE__);\
+	spin_lock_irqsave(sem, flags);\
+	} while (0)
+
+#define rio_spin_unlock_irqrestore(sem, flags) do { \
+	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\
+	                                sem, __FILE__, __LINE__);\
+	spin_unlock_irqrestore(sem, flags);\
+	} while (0)
+
+#define rio_spin_lock(sem) do { \
+	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\
+	                                sem, __FILE__, __LINE__);\
+	spin_lock(sem);\
+	} while (0)
+
+#define rio_spin_unlock(sem) do { \
+	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\
+	                                sem, __FILE__, __LINE__);\
+	spin_unlock(sem);\
+	} while (0)
+#else
+#define rio_spin_lock_irqsave(sem, flags) \
+            spin_lock_irqsave(sem, flags)
+
+#define rio_spin_unlock_irqrestore(sem, flags) \
+            spin_unlock_irqrestore(sem, flags)
+
+#define rio_spin_lock(sem) \
+            spin_lock(sem) 
+
+#define rio_spin_unlock(sem) \
+            spin_unlock(sem) 
+
+#endif
+
+
+
+#ifdef CONFIG_RIO_OLDPCI
+static inline void *rio_memcpy_toio (void *dummy, void *dest, void *source, int n)
+{
+  char *dst = dest;
+  char *src = source;
+
+  while (n--) {
+    writeb (*src++, dst++);
+    (void) readb (dummy);
+  }
+
+  return dest;
+}
+
+
+static inline void *rio_memcpy_fromio (void *dest, void *source, int n)
+{
+  char *dst = dest;
+  char *src = source;
+
+  while (n--) 
+    *dst++ = readb (src++);
+
+  return dest;
+}
+
+#else
+#define rio_memcpy_toio(dummy,dest,source,n)   memcpy_toio(dest, source, n)
+#define rio_memcpy_fromio                      memcpy_fromio
+#endif
+
+#define DEBUG 1
+
+
+/* 
+   This driver can spew a whole lot of debugging output at you. If you
+   need maximum performance, you should disable the DEBUG define. To
+   aid in debugging in the field, I'm leaving the compile-time debug
+   features enabled, and disable them "runtime". That allows me to
+   instruct people with problems to enable debugging without requiring
+   them to recompile... 
+*/
+
+#ifdef DEBUG
+#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0)
+#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __FUNCTION__)
+#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  %s\n", __FUNCTION__)
+#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__FUNCTION__, port->line)
+#else
+#define rio_dprintk(f, str...) /* nothing */
+#define func_enter()
+#define func_exit()
+#define func_enter2()
+#endif
+
diff --git a/drivers/char/rio/rioboard.h b/drivers/char/rio/rioboard.h
new file mode 100644
index 0000000..cc6ac6a
--- /dev/null
+++ b/drivers/char/rio/rioboard.h
@@ -0,0 +1,281 @@
+/************************************************************************/
+/*									*/
+/*	Title		:	RIO Host Card Hardware Definitions	*/
+/*									*/
+/*	Author		:	N.P.Vassallo				*/
+/*									*/
+/*	Creation	:	26th April 1999				*/
+/*									*/
+/*	Version		:	1.0.0					*/
+/*									*/
+/*	Copyright	:	(c) Specialix International Ltd. 1999	*
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *									*/
+/*	Description	:	Prototypes, structures and definitions	*/
+/*				describing the RIO board hardware	*/
+/*									*/
+/************************************************************************/
+
+/* History...
+
+1.0.0	26/04/99 NPV	Creation.
+
+*/
+
+#ifndef	_rioboard_h				/* If RIOBOARD.H not already defined */
+#define	_rioboard_h    1
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   Hardware Control Registers   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* Hardware Registers... */
+
+#define	RIO_REG_BASE	0x7C00			/* Base of control registers */
+
+#define	RIO_CONFIG	RIO_REG_BASE + 0x0000	/* WRITE: Configuration Register */
+#define	RIO_INTSET	RIO_REG_BASE + 0x0080	/* WRITE: Interrupt Set */
+#define	RIO_RESET	RIO_REG_BASE + 0x0100	/* WRITE: Host Reset */
+#define	RIO_INTRESET	RIO_REG_BASE + 0x0180	/* WRITE: Interrupt Reset */
+
+#define	RIO_VPD_ROM	RIO_REG_BASE + 0x0000	/* READ: Vital Product Data ROM */
+#define	RIO_INTSTAT	RIO_REG_BASE + 0x0080	/* READ: Interrupt Status (Jet boards only) */
+#define	RIO_RESETSTAT	RIO_REG_BASE + 0x0100	/* READ: Reset Status (Jet boards only) */
+
+/* RIO_VPD_ROM definitions... */
+#define	VPD_SLX_ID1	0x00			/* READ: Specialix Identifier #1 */
+#define	VPD_SLX_ID2	0x01			/* READ: Specialix Identifier #2 */
+#define	VPD_HW_REV	0x02			/* READ: Hardware Revision */
+#define	VPD_HW_ASSEM	0x03			/* READ: Hardware Assembly Level */
+#define	VPD_UNIQUEID4	0x04			/* READ: Unique Identifier #4 */
+#define	VPD_UNIQUEID3	0x05			/* READ: Unique Identifier #3 */
+#define	VPD_UNIQUEID2	0x06			/* READ: Unique Identifier #2 */
+#define	VPD_UNIQUEID1	0x07			/* READ: Unique Identifier #1 */
+#define	VPD_MANU_YEAR	0x08			/* READ: Year Of Manufacture (0 = 1970) */
+#define	VPD_MANU_WEEK	0x09			/* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define	VPD_HWFEATURE1	0x0A			/* READ: Hardware Feature Byte 1 */
+#define	VPD_HWFEATURE2	0x0B			/* READ: Hardware Feature Byte 2 */
+#define	VPD_HWFEATURE3	0x0C			/* READ: Hardware Feature Byte 3 */
+#define	VPD_HWFEATURE4	0x0D			/* READ: Hardware Feature Byte 4 */
+#define	VPD_HWFEATURE5	0x0E			/* READ: Hardware Feature Byte 5 */
+#define	VPD_OEMID	0x0F			/* READ: OEM Identifier */
+#define	VPD_IDENT	0x10			/* READ: Identifier string (16 bytes) */
+#define	VPD_IDENT_LEN	0x10
+
+/* VPD ROM Definitions... */
+#define	SLX_ID1		0x4D
+#define	SLX_ID2		0x98
+
+#define	PRODUCT_ID(a)	((a>>4)&0xF)		/* Use to obtain Product ID from VPD_UNIQUEID1 */
+
+#define	ID_SX_ISA	0x2
+#define	ID_RIO_EISA	0x3
+#define	ID_SX_PCI	0x5
+#define	ID_SX_EISA	0x7
+#define	ID_RIO_RTA16	0x9
+#define	ID_RIO_ISA	0xA
+#define	ID_RIO_MCA	0xB
+#define	ID_RIO_SBUS	0xC
+#define	ID_RIO_PCI	0xD
+#define	ID_RIO_RTA8	0xE
+
+/* Transputer bootstrap definitions... */
+
+#define	BOOTLOADADDR		(0x8000 - 6)
+#define	BOOTINDICATE		(0x8000 - 2)
+
+/* Firmware load position... */
+
+#define	FIRMWARELOADADDR	0x7C00		/* Firmware is loaded _before_ this address */
+
+/*****************************************************************************
+*****************************                    *****************************
+*****************************   RIO (Rev1) ISA   *****************************
+*****************************                    *****************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_ISA_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_ISA_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_ISA_CFG_IRQMASK	0x30		/* Interrupt mask */
+#define	  RIO_ISA_CFG_IRQ12	0x10		/* Interrupt Level 12 */
+#define	  RIO_ISA_CFG_IRQ11	0x20		/* Interrupt Level 11 */
+#define	  RIO_ISA_CFG_IRQ9	0x30		/* Interrupt Level 9 */
+#define	RIO_ISA_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+#define	RIO_ISA_CFG_WAITSTATE0	0x80		/* 0 waitstates, else 1 */
+
+/*****************************************************************************
+*****************************                    *****************************
+*****************************   RIO (Rev2) ISA   *****************************
+*****************************                    *****************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA2_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_ISA2_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_ISA2_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_ISA2_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+#define	RIO_ISA2_CFG_16BIT	0x08		/* 16bit mode, else 8bit */
+#define	RIO_ISA2_CFG_IRQMASK	0x30		/* Interrupt mask */
+#define	  RIO_ISA2_CFG_IRQ15	0x00		/* Interrupt Level 15 */
+#define	  RIO_ISA2_CFG_IRQ12	0x10		/* Interrupt Level 12 */
+#define	  RIO_ISA2_CFG_IRQ11	0x20		/* Interrupt Level 11 */
+#define	  RIO_ISA2_CFG_IRQ9	0x30		/* Interrupt Level 9 */
+#define	RIO_ISA2_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+#define	RIO_ISA2_CFG_WAITSTATE0	0x80		/* 0 waitstates, else 1 */
+
+/*****************************************************************************
+*****************************                   ******************************
+*****************************   RIO (Jet) ISA   ******************************
+*****************************                   ******************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA3_IDENT	"JET HOST BY KEV#"
+
+#define	RIO_ISA3_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_ISA3_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+#define	RIO_ISA32_CFG_IRQMASK	0xF30		/* Interrupt mask */
+#define	  RIO_ISA3_CFG_IRQ15	0xF0		/* Interrupt Level 15 */
+#define	  RIO_ISA3_CFG_IRQ12	0xC0		/* Interrupt Level 12 */
+#define	  RIO_ISA3_CFG_IRQ11	0xB0		/* Interrupt Level 11 */
+#define	  RIO_ISA3_CFG_IRQ10	0xA0		/* Interrupt Level 10 */
+#define	  RIO_ISA3_CFG_IRQ9	0x90		/* Interrupt Level 9 */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   RIO MCA   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_MCA_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_MCA_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_MCA_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_MCA_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+
+/*****************************************************************************
+********************************              ********************************
+********************************   RIO EISA   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+/* EISA Configuration Space Definitions... */
+#define	EISA_PRODUCT_ID1	0xC80
+#define	EISA_PRODUCT_ID2	0xC81
+#define	EISA_PRODUCT_NUMBER	0xC82
+#define	EISA_REVISION_NUMBER	0xC83
+#define	EISA_CARD_ENABLE	0xC84
+#define	EISA_VPD_UNIQUEID4	0xC88		/* READ: Unique Identifier #4 */
+#define	EISA_VPD_UNIQUEID3	0xC8A		/* READ: Unique Identifier #3 */
+#define	EISA_VPD_UNIQUEID2	0xC90		/* READ: Unique Identifier #2 */
+#define	EISA_VPD_UNIQUEID1	0xC92		/* READ: Unique Identifier #1 */
+#define	EISA_VPD_MANU_YEAR	0xC98		/* READ: Year Of Manufacture (0 = 1970) */
+#define	EISA_VPD_MANU_WEEK	0xC9A		/* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define	EISA_MEM_ADDR_23_16	0xC00
+#define	EISA_MEM_ADDR_31_24	0xC01
+#define	EISA_RIO_CONFIG		0xC02		/* WRITE: Configuration Register */
+#define	EISA_RIO_INTSET		0xC03		/* WRITE: Interrupt Set */
+#define	EISA_RIO_INTRESET	0xC03		/* READ:  Interrupt Reset */
+
+/* Control Register Definitions... */
+#define	RIO_EISA_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_EISA_CFG_LINK20	0x02		/* 20Mbps link, else 10Mbps */
+#define	RIO_EISA_CFG_BUSENABLE	0x04		/* Enable processor bus */
+#define	RIO_EISA_CFG_PROCRUN	0x08		/* Processor running, else reset */
+#define	RIO_EISA_CFG_IRQMASK	0xF0		/* Interrupt mask */
+#define	  RIO_EISA_CFG_IRQ15	0xF0		/* Interrupt Level 15 */
+#define	  RIO_EISA_CFG_IRQ14	0xE0		/* Interrupt Level 14 */
+#define	  RIO_EISA_CFG_IRQ12	0xC0		/* Interrupt Level 12 */
+#define	  RIO_EISA_CFG_IRQ11	0xB0		/* Interrupt Level 11 */
+#define	  RIO_EISA_CFG_IRQ10	0xA0		/* Interrupt Level 10 */
+#define	  RIO_EISA_CFG_IRQ9	0x90		/* Interrupt Level 9 */
+#define	  RIO_EISA_CFG_IRQ7	0x70		/* Interrupt Level 7 */
+#define	  RIO_EISA_CFG_IRQ6	0x60		/* Interrupt Level 6 */
+#define	  RIO_EISA_CFG_IRQ5	0x50		/* Interrupt Level 5 */
+#define	  RIO_EISA_CFG_IRQ4	0x40		/* Interrupt Level 4 */
+#define	  RIO_EISA_CFG_IRQ3	0x30		/* Interrupt Level 3 */
+
+/*****************************************************************************
+********************************              ********************************
+********************************   RIO SBus   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_SBUS_IDENT	"JBPGK#\0\0\0\0\0\0\0\0\0\0"
+
+#define	RIO_SBUS_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_SBUS_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_SBUS_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+#define	RIO_SBUS_CFG_IRQMASK	0x38		/* Interrupt mask */
+#define	  RIO_SBUS_CFG_IRQNONE	0x00		/* No Interrupt */
+#define	  RIO_SBUS_CFG_IRQ7	0x38		/* Interrupt Level 7 */
+#define	  RIO_SBUS_CFG_IRQ6	0x30		/* Interrupt Level 6 */
+#define	  RIO_SBUS_CFG_IRQ5	0x28		/* Interrupt Level 5 */
+#define	  RIO_SBUS_CFG_IRQ4	0x20		/* Interrupt Level 4 */
+#define	  RIO_SBUS_CFG_IRQ3	0x18		/* Interrupt Level 3 */
+#define	  RIO_SBUS_CFG_IRQ2	0x10		/* Interrupt Level 2 */
+#define	  RIO_SBUS_CFG_IRQ1	0x08		/* Interrupt Level 1 */
+#define	RIO_SBUS_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+#define	RIO_SBUS_CFG_PROC25	0x80		/* 25Mhz processor clock, else 20Mhz */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   RIO PCI   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_PCI_IDENT	"ECDDPGJGJHJRGSK#"
+
+#define	RIO_PCI_CFG_BOOTRAM	0x01		/* Boot from RAM, else Link */
+#define	RIO_PCI_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_PCI_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+#define	RIO_PCI_CFG_LINK20	0x40		/* 20Mbps link, else 10Mbps */
+#define	RIO_PCI_CFG_PROC25	0x80		/* 25Mhz processor clock, else 20Mhz */
+
+/* PCI Definitions... */
+#define	SPX_VENDOR_ID		0x11CB		/* Assigned by the PCI SIG */
+#define	SPX_DEVICE_ID		0x8000		/* RIO bridge boards */
+#define	SPX_PLXDEVICE_ID	0x2000		/* PLX bridge boards */
+#define	SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
+#define	RIO_SUB_SYS_ID		0x0800		/* RIO PCI board */
+
+/*****************************************************************************
+*****************************                   ******************************
+*****************************   RIO (Jet) PCI   ******************************
+*****************************                   ******************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_PCI2_IDENT	"JET HOST BY KEV#"
+
+#define	RIO_PCI2_CFG_BUSENABLE	0x02		/* Enable processor bus */
+#define	RIO_PCI2_CFG_INTENABLE	0x04		/* Interrupt enable, else disable */
+
+/* PCI Definitions... */
+#define	RIO2_SUB_SYS_ID		0x0100		/* RIO (Jet) PCI board */
+
+#endif						/*_rioboard_h */
+
+/* End of RIOBOARD.H */
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
new file mode 100644
index 0000000..a8be11d
--- /dev/null
+++ b/drivers/char/rio/rioboot.c
@@ -0,0 +1,1360 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioboot.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:36
+**	Retrieved	: 11/6/98 10:33:48
+**
+**  ident @(#)rioboot.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifdef SCCS_LABELS
+static char *_rioboot_c_sccs_ = "@(#)rioboot.c	1.3";
+#endif
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+
+static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP );
+
+static uchar
+RIOAtVec2Ctrl[] =
+{
+	/* 0 */  INTERRUPT_DISABLE,
+	/* 1 */  INTERRUPT_DISABLE,
+	/* 2 */  INTERRUPT_DISABLE,
+	/* 3 */  INTERRUPT_DISABLE,
+	/* 4 */  INTERRUPT_DISABLE,
+	/* 5 */  INTERRUPT_DISABLE,
+	/* 6 */  INTERRUPT_DISABLE,
+	/* 7 */  INTERRUPT_DISABLE,
+	/* 8 */  INTERRUPT_DISABLE,
+	/* 9 */  IRQ_9|INTERRUPT_ENABLE,
+	/* 10 */ INTERRUPT_DISABLE,
+	/* 11 */ IRQ_11|INTERRUPT_ENABLE,
+	/* 12 */ IRQ_12|INTERRUPT_ENABLE,
+	/* 13 */ INTERRUPT_DISABLE,
+	/* 14 */ INTERRUPT_DISABLE,
+	/* 15 */ IRQ_15|INTERRUPT_ENABLE
+};
+
+/*
+** Load in the RTA boot code.
+*/
+int
+RIOBootCodeRTA(p, rbp)
+struct rio_info *	p;
+struct DownLoad *	rbp; 
+{
+	int offset;
+
+	func_enter ();
+
+	/* Linux doesn't allow you to disable interrupts during a
+	   "copyin". (Crash when a pagefault occurs). */
+	/* disable(oldspl); */
+	
+	rio_dprintk (RIO_DEBUG_BOOT, "Data at user address 0x%x\n",(int)rbp->DataP);
+
+	/*
+	** Check that we have set asside enough memory for this
+	*/
+	if ( rbp->Count > SIXTY_FOUR_K ) {
+		rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n");
+		p->RIOError.Error = HOST_FILE_TOO_LARGE;
+		/* restore(oldspl); */
+		func_exit ();
+		return -ENOMEM;
+	}
+
+	if ( p->RIOBooting ) {
+		rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n");
+		p->RIOError.Error = BOOT_IN_PROGRESS;
+		/* restore(oldspl); */
+		func_exit ();
+		return -EBUSY;
+	}
+
+	/*
+	** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary,
+	** so calculate how far we have to move the data up the buffer
+	** to achieve this.
+	*/
+	offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % 
+							RTA_BOOT_DATA_SIZE;
+
+	/*
+	** Be clean, and clear the 'unused' portion of the boot buffer,
+	** because it will (eventually) be part of the Rta run time environment
+	** and so should be zeroed.
+	*/
+	bzero( (caddr_t)p->RIOBootPackets, offset );
+
+	/*
+	** Copy the data from user space.
+	*/
+
+	if ( copyin((int)rbp->DataP,((caddr_t)(p->RIOBootPackets))+offset,
+				rbp->Count) ==COPYFAIL ) {
+		rio_dprintk (RIO_DEBUG_BOOT, "Bad data copy from user space\n");
+		p->RIOError.Error = COPYIN_FAILED;
+		/* restore(oldspl); */
+		func_exit ();
+		return -EFAULT;
+	}
+
+	/*
+	** Make sure that our copy of the size includes that offset we discussed
+	** earlier.
+	*/
+	p->RIONumBootPkts = (rbp->Count+offset)/RTA_BOOT_DATA_SIZE;
+	p->RIOBootCount   = rbp->Count;
+
+	/* restore(oldspl); */
+	func_exit();
+	return 0;
+}
+
+void rio_start_card_running (struct Host * HostP)
+{
+	func_enter ();
+
+	switch ( HostP->Type ) {
+	case RIO_AT:
+		rio_dprintk (RIO_DEBUG_BOOT, "Start ISA card running\n");
+		WBYTE(HostP->Control, 
+		      BOOT_FROM_RAM | EXTERNAL_BUS_ON
+		      | HostP->Mode
+		      | RIOAtVec2Ctrl[HostP->Ivec & 0xF] );
+		break;
+		
+#ifdef FUTURE_RELEASE
+	case RIO_MCA:
+				/*
+				** MCA handles IRQ vectors differently, so we don't write 
+				** them to this register.
+				*/
+		rio_dprintk (RIO_DEBUG_BOOT, "Start MCA card running\n");
+		WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode);
+		break;
+
+	case RIO_EISA:
+				/*
+				** EISA is totally different and expects OUTBZs to turn it on.
+				*/
+		rio_dprintk (RIO_DEBUG_BOOT, "Start EISA card running\n");
+		OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM );
+		break;
+#endif
+
+	case RIO_PCI:
+				/*
+				** PCI is much the same as MCA. Everything is once again memory
+				** mapped, so we are writing to memory registers instead of io
+				** ports.
+				*/
+		rio_dprintk (RIO_DEBUG_BOOT, "Start PCI card running\n");
+		WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode);
+		break;
+	default:
+		rio_dprintk (RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type);
+		break;
+	}
+/* 
+	printk (KERN_INFO "Done with starting the card\n");
+	func_exit ();
+*/
+	return;
+}
+
+/*
+** Load in the host boot code - load it directly onto all halted hosts
+** of the correct type.
+**
+** Put your rubber pants on before messing with this code - even the magic
+** numbers have trouble understanding what they are doing here.
+*/
+int
+RIOBootCodeHOST(p, rbp)
+struct rio_info *	p;
+register struct DownLoad *rbp;
+{
+	register struct Host *HostP;
+	register caddr_t Cad;
+	register PARM_MAP *ParmMapP;
+	register int RupN;
+	int PortN;
+	uint host;
+	caddr_t StartP;
+	BYTE *DestP;
+	int wait_count;
+	ushort OldParmMap;
+	ushort offset;	/* It is very important that this is a ushort */
+	/* uint byte; */
+	caddr_t DownCode = NULL;
+	unsigned long flags;
+
+	HostP = NULL; /* Assure the compiler we've initialized it */
+	for ( host=0; host<p->RIONumHosts; host++ ) {
+		rio_dprintk (RIO_DEBUG_BOOT, "Attempt to boot host %d\n",host);
+		HostP = &p->RIOHosts[host];
+		
+		rio_dprintk (RIO_DEBUG_BOOT,  "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
+		    HostP->Type, HostP->Mode, HostP->Ivec);
+
+
+		if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "%s %d already running\n","Host",host);
+			continue;
+		}
+
+		/*
+		** Grab a 32 bit pointer to the card.
+		*/
+		Cad = HostP->Caddr;
+
+		/*
+		** We are going to (try) and load in rbp->Count bytes.
+		** The last byte will reside at p->RIOConf.HostLoadBase-1;
+		** Therefore, we need to start copying at address
+		** (caddr+p->RIOConf.HostLoadBase-rbp->Count)
+		*/
+		StartP = (caddr_t)&Cad[p->RIOConf.HostLoadBase-rbp->Count];
+
+		rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for host is 0x%x\n", (int)Cad );
+		rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for download is 0x%x\n", (int)StartP);
+		rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%x\n",p->RIOConf.HostLoadBase);
+		rio_dprintk (RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count);
+
+		if ( p->RIOConf.HostLoadBase < rbp->Count ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "Bin too large\n");
+			p->RIOError.Error = HOST_FILE_TOO_LARGE;
+			func_exit ();
+			return -EFBIG;
+		}
+		/*
+		** Ensure that the host really is stopped.
+		** Disable it's external bus & twang its reset line.
+		*/
+		RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );
+
+		/*
+		** Copy the data directly from user space to the SRAM.
+		** This ain't going to be none too clever if the download
+		** code is bigger than this segment.
+		*/
+		rio_dprintk (RIO_DEBUG_BOOT, "Copy in code\n");
+
+		/*
+		** PCI hostcard can't cope with 32 bit accesses and so need to copy 
+		** data to a local buffer, and then dripfeed the card.
+		*/
+		if ( HostP->Type == RIO_PCI ) {
+		  /* int offset; */
+
+			DownCode = sysbrk(rbp->Count);
+			if ( !DownCode ) {
+				rio_dprintk (RIO_DEBUG_BOOT, "No system memory available\n");
+				p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
+				func_exit ();
+				return -ENOMEM;
+			}
+			bzero(DownCode, rbp->Count);
+
+			if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) {
+				rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n");
+				sysfree( DownCode, rbp->Count );
+				p->RIOError.Error = COPYIN_FAILED;
+				func_exit ();
+				return -EFAULT;
+			}
+
+			HostP->Copy( DownCode, StartP, rbp->Count );
+
+			sysfree( DownCode, rbp->Count );
+		}
+		else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			func_exit ();
+			return -EFAULT;
+		}
+
+		rio_dprintk (RIO_DEBUG_BOOT, "Copy completed\n");
+
+		/*
+		**			S T O P !
+		**
+		** Upto this point the code has been fairly rational, and possibly
+		** even straight forward. What follows is a pile of crud that will
+		** magically turn into six bytes of transputer assembler. Normally
+		** you would expect an array or something, but, being me, I have
+		** chosen [been told] to use a technique whereby the startup code
+		** will be correct if we change the loadbase for the code. Which
+		** brings us onto another issue - the loadbase is the *end* of the
+		** code, not the start.
+		**
+		** If I were you I wouldn't start from here.
+		*/
+
+		/*
+		** We now need to insert a short boot section into
+		** the memory at the end of Sram2. This is normally (de)composed
+		** of the last eight bytes of the download code. The
+		** download has been assembled/compiled to expect to be
+		** loaded from 0x7FFF downwards. We have loaded it
+		** at some other address. The startup code goes into the small
+		** ram window at Sram2, in the last 8 bytes, which are really
+		** at addresses 0x7FF8-0x7FFF.
+		**
+		** If the loadbase is, say, 0x7C00, then we need to branch to
+		** address 0x7BFE to run the host.bin startup code. We assemble
+		** this jump manually.
+		**
+		** The two byte sequence 60 08 is loaded into memory at address
+		** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0,
+		** which adds '0' to the .O register, complements .O, and then shifts
+		** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will
+		** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new
+		** location. Now, the branch starts from the value of .PC (or .IP or
+		** whatever the bloody register is called on this chip), and the .PC
+		** will be pointing to the location AFTER the branch, in this case
+		** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8.
+		**
+		** A long branch is coded at 0x7FF8. This consists of loading a four
+		** byte offset into .O using nfix (as above) and pfix operators. The
+		** pfix operates in exactly the same way as the nfix operator, but
+		** without the complement operation. The offset, of course, must be
+		** relative to the address of the byte AFTER the branch instruction,
+		** which will be (urm) 0x7FFC, so, our final destination of the branch
+		** (loadbase-2), has to be reached from here. Imagine that the loadbase
+		** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which
+		** is the first byte of the initial two byte short local branch of the
+		** download code).
+		**
+		** To code a jump from 0x7FFC (which is where the branch will start
+		** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)=
+		** 0x7BFE.
+		** This will be coded as four bytes:
+		** 60 2C 20 02
+		** being nfix .O+0
+		**	   pfix .O+C
+		**	   pfix .O+0
+		**	   jump .O+2
+		**
+		** The nfix operator is used, so that the startup code will be
+		** compatible with the whole Tp family. (lies, damn lies, it'll never
+		** work in a month of Sundays).
+		**
+		** The nfix nyble is the 1s complement of the nyble value you
+		** want to load - in this case we wanted 'F' so we nfix loaded '0'.
+		*/
+
+
+		/*
+		** Dest points to the top 8 bytes of Sram2. The Tp jumps
+		** to 0x7FFE at reset time, and starts executing. This is
+		** a short branch to 0x7FF8, where a long branch is coded.
+		*/
+
+		DestP = (BYTE *)&Cad[0x7FF8];	/* <<<---- READ THE ABOVE COMMENTS */
+
+#define	NFIX(N)	(0x60 | (N))	/* .O  = (~(.O + N))<<4 */
+#define	PFIX(N)	(0x20 | (N))	/* .O  =   (.O + N)<<4  */
+#define	JUMP(N)	(0x00 | (N))	/* .PC =   .PC + .O	 */
+
+		/*
+		** 0x7FFC is the address of the location following the last byte of
+		** the four byte jump instruction.
+		** READ THE ABOVE COMMENTS
+		**
+		** offset is (TO-FROM) % MEMSIZE, but with compound buggering about.
+		** Memsize is 64K for this range of Tp, so offset is a short (unsigned,
+		** cos I don't understand 2's complement).
+		*/
+		offset = (p->RIOConf.HostLoadBase-2)-0x7FFC;
+		WBYTE( DestP[0] , NFIX(((ushort)(~offset) >> (ushort)12) & 0xF) );
+		WBYTE( DestP[1] , PFIX(( offset >> 8) & 0xF) );
+		WBYTE( DestP[2] , PFIX(( offset >> 4) & 0xF) );
+		WBYTE( DestP[3] , JUMP( offset & 0xF) );
+
+		WBYTE( DestP[6] , NFIX(0) );
+		WBYTE( DestP[7] , JUMP(8) );
+
+		rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%x\n",p->RIOConf.HostLoadBase);
+		rio_dprintk (RIO_DEBUG_BOOT, "startup offset is 0x%x\n",offset);
+
+		/*
+		** Flag what is going on
+		*/
+		HostP->Flags &= ~RUN_STATE;
+		HostP->Flags |= RC_STARTUP;
+
+		/*
+		** Grab a copy of the current ParmMap pointer, so we
+		** can tell when it has changed.
+		*/
+		OldParmMap = RWORD(HostP->__ParmMapR);
+
+		rio_dprintk (RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n",OldParmMap);
+
+		/*
+		** And start it running (I hope).
+		** As there is nothing dodgy or obscure about the
+		** above code, this is guaranteed to work every time.
+		*/
+		rio_dprintk (RIO_DEBUG_BOOT,  "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
+		    HostP->Type, HostP->Mode, HostP->Ivec);
+
+		rio_start_card_running(HostP);
+
+		rio_dprintk (RIO_DEBUG_BOOT, "Set control port\n");
+
+		/*
+		** Now, wait for upto five seconds for the Tp to setup the parmmap
+		** pointer:
+		*/
+		for ( wait_count=0; (wait_count<p->RIOConf.StartupTime)&&
+			(RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR));
+			delay(HostP, HUNDRED_MS);
+
+		}
+
+		/*
+		** If the parmmap pointer is unchanged, then the host code
+		** has crashed & burned in a really spectacular way
+		*/
+		if ( RWORD(HostP->__ParmMapR) == OldParmMap ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "parmmap 0x%x\n", RWORD(HostP->__ParmMapR));
+			rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n");
+
+#define	HOST_DISABLE \
+		HostP->Flags &= ~RUN_STATE; \
+		HostP->Flags |= RC_STUFFED; \
+		RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );\
+		continue
+
+			HOST_DISABLE;
+		}
+
+		rio_dprintk (RIO_DEBUG_BOOT, "Running 0x%x\n", RWORD(HostP->__ParmMapR));
+
+		/*
+		** Well, the board thought it was OK, and setup its parmmap
+		** pointer. For the time being, we will pretend that this
+		** board is running, and check out what the error flag says.
+		*/
+
+		/*
+		** Grab a 32 bit pointer to the parmmap structure
+		*/
+		ParmMapP = (PARM_MAP *)RIO_PTR(Cad,RWORD(HostP->__ParmMapR));
+		rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int)ParmMapP);
+		ParmMapP = (PARM_MAP *)((unsigned long)Cad + 
+						(unsigned long)((RWORD((HostP->__ParmMapR))) & 0xFFFF)); 
+		rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int)ParmMapP);
+
+		/*
+		** The links entry should be 0xFFFF; we set it up
+		** with a mask to say how many PHBs to use, and 
+		** which links to use.
+		*/
+		if ( (RWORD(ParmMapP->links) & 0xFFFF) != 0xFFFF ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
+			rio_dprintk (RIO_DEBUG_BOOT, "Links = 0x%x\n",RWORD(ParmMapP->links));
+			HOST_DISABLE;
+		}
+
+		WWORD(ParmMapP->links , RIO_LINK_ENABLE);
+
+		/*
+		** now wait for the card to set all the parmmap->XXX stuff
+		** this is a wait of upto two seconds....
+		*/
+		rio_dprintk (RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n",p->RIOConf.StartupTime);
+		HostP->timeout_id = 0;
+		for ( wait_count=0; (wait_count<p->RIOConf.StartupTime) && 
+						!RWORD(ParmMapP->init_done); wait_count++ ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "Waiting for init_done\n");
+			delay(HostP, HUNDRED_MS);
+		}
+		rio_dprintk (RIO_DEBUG_BOOT, "OK! init_done!\n");
+
+		if (RWORD(ParmMapP->error) != E_NO_ERROR || 
+							!RWORD(ParmMapP->init_done) ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
+			rio_dprintk (RIO_DEBUG_BOOT, "Timedout waiting for init_done\n");
+			HOST_DISABLE;
+		}
+
+		rio_dprintk (RIO_DEBUG_BOOT, "Got init_done\n");
+
+		/*
+		** It runs! It runs!
+		*/
+		rio_dprintk (RIO_DEBUG_BOOT, "Host ID %x Running\n",HostP->UniqueNum);
+
+		/*
+		** set the time period between interrupts.
+		*/
+		WWORD(ParmMapP->timer, (short)p->RIOConf.Timer );
+
+		/*
+		** Translate all the 16 bit pointers in the __ParmMapR into
+		** 32 bit pointers for the driver.
+		*/
+		HostP->ParmMapP	 =	ParmMapP;
+		HostP->PhbP		 =	(PHB*)RIO_PTR(Cad,RWORD(ParmMapP->phb_ptr));
+		HostP->RupP		 =	(RUP*)RIO_PTR(Cad,RWORD(ParmMapP->rups));
+		HostP->PhbNumP	  = (ushort*)RIO_PTR(Cad,RWORD(ParmMapP->phb_num_ptr));
+		HostP->LinkStrP	 =	(LPB*)RIO_PTR(Cad,RWORD(ParmMapP->link_str_ptr));
+
+		/*
+		** point the UnixRups at the real Rups
+		*/
+		for ( RupN = 0; RupN<MAX_RUP; RupN++ ) {
+			HostP->UnixRups[RupN].RupP		= &HostP->RupP[RupN];
+			HostP->UnixRups[RupN].Id		  = RupN+1;
+			HostP->UnixRups[RupN].BaseSysPort = NO_PORT;
+			spin_lock_init(&HostP->UnixRups[RupN].RupLock);
+		}
+
+		for ( RupN = 0; RupN<LINKS_PER_UNIT; RupN++ ) {
+			HostP->UnixRups[RupN+MAX_RUP].RupP	= &HostP->LinkStrP[RupN].rup;
+			HostP->UnixRups[RupN+MAX_RUP].Id  = 0;
+			HostP->UnixRups[RupN+MAX_RUP].BaseSysPort = NO_PORT;
+			spin_lock_init(&HostP->UnixRups[RupN+MAX_RUP].RupLock);
+		}
+
+		/*
+		** point the PortP->Phbs at the real Phbs
+		*/
+		for ( PortN=p->RIOFirstPortsMapped; 
+				PortN<p->RIOLastPortsMapped+PORTS_PER_RTA; PortN++ ) {
+			if ( p->RIOPortp[PortN]->HostP == HostP ) {
+				struct Port *PortP = p->RIOPortp[PortN];
+				struct PHB *PhbP;
+				/* int oldspl; */
+
+				if ( !PortP->Mapped )
+					continue;
+
+				PhbP = &HostP->PhbP[PortP->HostPort];
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				PortP->PhbP = PhbP;
+
+				PortP->TxAdd	= (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_add));
+				PortP->TxStart  = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_start));
+				PortP->TxEnd	= (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_end));
+				PortP->RxRemove = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_remove));
+				PortP->RxStart  = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_start));
+				PortP->RxEnd	= (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_end));
+
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				/*
+				** point the UnixRup at the base SysPort
+				*/
+				if ( !(PortN % PORTS_PER_RTA) )
+					HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN;
+			}
+		}
+
+		rio_dprintk (RIO_DEBUG_BOOT, "Set the card running... \n");
+		/*
+		** last thing - show the world that everything is in place
+		*/
+		HostP->Flags &= ~RUN_STATE;
+		HostP->Flags |= RC_RUNNING;
+	}
+	/*
+	** MPX always uses a poller. This is actually patched into the system
+	** configuration and called directly from each clock tick.
+	**
+	*/
+	p->RIOPolling = 1;
+
+	p->RIOSystemUp++;
+	
+	rio_dprintk (RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec);
+	func_exit ();
+	return 0;
+}
+
+
+
+/*
+** Boot an RTA. If we have successfully processed this boot, then
+** return 1. If we havent, then return 0.
+*/
+int
+RIOBootRup( p, Rup, HostP, PacketP)
+struct rio_info *	p;
+uint Rup;
+struct Host *HostP;
+struct PKT *PacketP; 
+{
+	struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
+	struct PktCmd_M *PktReplyP;
+	struct CmdBlk *CmdBlkP;
+	uint sequence;
+
+#ifdef CHECK
+	CheckHost(Host);
+	CheckRup(Rup);
+	CheckHostP(HostP);
+	CheckPacketP(PacketP);
+#endif
+
+	/*
+	** If we haven't been told what to boot, we can't boot it.
+	*/
+	if ( p->RIONumBootPkts == 0 ) {
+		rio_dprintk (RIO_DEBUG_BOOT, "No RTA code to download yet\n");
+		return 0;
+	}
+
+	/* rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_BOOT,"Incoming command packet\n"); */
+	/* ShowPacket( DBG_BOOT, PacketP ); */
+
+	/*
+	** Special case of boot completed - if we get one of these then we
+	** don't need a command block. For all other cases we do, so handle
+	** this first and then get a command block, then handle every other
+	** case, relinquishing the command block if disaster strikes!
+	*/
+	if ( (RBYTE(PacketP->len) & PKT_CMD_BIT) && 
+			(RBYTE(PktCmdP->Command)==BOOT_COMPLETED) )
+		return RIOBootComplete(p, HostP, Rup, PktCmdP );
+
+	/*
+	** try to unhook a command block from the command free list.
+	*/
+	if ( !(CmdBlkP = RIOGetCmdBlk()) ) {
+		rio_dprintk (RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n");
+		return 0;
+	}
+
+	/*
+	** Fill in the default info on the command block
+	*/
+	CmdBlkP->Packet.dest_unit = Rup < (ushort)MAX_RUP ? Rup : 0;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+
+	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
+	PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data;
+
+	/*
+	** process COMMANDS on the boot rup!
+	*/
+	if ( RBYTE(PacketP->len) & PKT_CMD_BIT ) {
+		/*
+		** We only expect one type of command - a BOOT_REQUEST!
+		*/
+		if ( RBYTE(PktCmdP->Command) != BOOT_REQUEST ) {
+			rio_dprintk (RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %d\n", 
+						PktCmdP->Command,Rup,HostP-p->RIOHosts);
+			ShowPacket( DBG_BOOT, PacketP );
+			RIOFreeCmdBlk( CmdBlkP );
+			return 1;
+		}
+
+		/*
+		** Build a Boot Sequence command block
+		**
+		** 02.03.1999 ARG - ESIL 0820 fix
+		** We no longer need to use "Boot Mode", we'll always allow
+		** boot requests - the boot will not complete if the device
+		** appears in the bindings table.
+		** So, this conditional is not required ...
+		**
+		if (p->RIOBootMode == RC_BOOT_NONE)
+			**
+			** If the system is in slave mode, and a boot request is
+			** received, set command to BOOT_ABORT so that the boot
+			** will not complete.
+			**
+			PktReplyP->Command			 = BOOT_ABORT;
+		else
+		**
+		** We'll just (always) set the command field in packet reply
+		** to allow an attempted boot sequence :
+		*/
+		PktReplyP->Command = BOOT_SEQUENCE;
+
+		PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts;
+		PktReplyP->BootSequence.LoadBase   = p->RIOConf.RtaLoadBase;
+		PktReplyP->BootSequence.CodeSize   = p->RIOBootCount;
+
+		CmdBlkP->Packet.len				= BOOT_SEQUENCE_LEN | PKT_CMD_BIT;
+
+		bcopy("BOOT",(void *)&CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN],4);
+
+		rio_dprintk (RIO_DEBUG_BOOT, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n",
+			HostP-p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, 
+								p->RIOConf.RtaLoadBase);
+
+		/*
+		** If this host is in slave mode, send the RTA an invalid boot
+		** sequence command block to force it to kill the boot. We wait
+		** for half a second before sending this packet to prevent the RTA
+		** attempting to boot too often. The master host should then grab
+		** the RTA and make it its own.
+		*/
+		p->RIOBooting++;
+		RIOQueueCmdBlk( HostP, Rup, CmdBlkP );
+		return 1;
+	}
+
+	/*
+	** It is a request for boot data.
+	*/
+	sequence = RWORD(PktCmdP->Sequence);
+
+	rio_dprintk (RIO_DEBUG_BOOT, "Boot block %d on Host %d Rup%d\n",sequence,HostP-p->RIOHosts,Rup);
+
+	if ( sequence >= p->RIONumBootPkts ) {
+		rio_dprintk (RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, 
+					p->RIONumBootPkts);
+		ShowPacket( DBG_BOOT, PacketP );
+	}
+
+	PktReplyP->Sequence = sequence;
+
+	bcopy( p->RIOBootPackets[ p->RIONumBootPkts - sequence - 1 ], 
+				PktReplyP->BootData, RTA_BOOT_DATA_SIZE );
+
+	CmdBlkP->Packet.len = PKT_MAX_DATA_LEN;
+	ShowPacket( DBG_BOOT, &CmdBlkP->Packet );
+	RIOQueueCmdBlk( HostP, Rup, CmdBlkP );
+	return 1;
+}
+
+/*
+** This function is called when an RTA been booted.
+** If booted by a host, HostP->HostUniqueNum is the booting host.
+** If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
+** RtaUniq is the booted RTA.
+*/
+static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP )
+{
+	struct Map	*MapP = NULL;
+	struct Map	*MapP2 = NULL;
+	int	Flag;
+	int	found;
+	int	host, rta;
+	int	EmptySlot = -1;
+	int	entry, entry2;
+	char	*MyType, *MyName;
+	uint	MyLink;
+	ushort	RtaType;
+	uint	RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) +
+			  (RBYTE(PktCmdP->UniqNum[1]) << 8) +
+			  (RBYTE(PktCmdP->UniqNum[2]) << 16) +
+			  (RBYTE(PktCmdP->UniqNum[3]) << 24);
+
+	/* Was RIOBooting-- . That's bad. If an RTA sends two of them, the
+	   driver will never think that the RTA has booted... -- REW */
+	p->RIOBooting = 0;
+
+	rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting);
+
+	/*
+	** Determine type of unit (16/8 port RTA).
+	*/
+	RtaType = GetUnitType(RtaUniq);
+        if ( Rup >= (ushort)MAX_RUP ) {
+	    rio_dprintk (RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n",
+	     HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum)+'A');
+	} else {
+	    rio_dprintk (RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n",
+	     HostP->Mapping[Rup].Name, 8 * RtaType,
+	     RBYTE(PktCmdP->LinkNum)+'A');
+	}
+
+	rio_dprintk (RIO_DEBUG_BOOT, "UniqNum is 0x%x\n",RtaUniq);
+
+        if ( ( RtaUniq == 0x00000000 ) || ( RtaUniq == 0xffffffff ) )
+	{
+	    rio_dprintk (RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n");
+	    return TRUE;
+	}
+
+	/*
+	** If this RTA has just booted an RTA which doesn't belong to this
+	** system, or the system is in slave mode, do not attempt to create
+	** a new table entry for it.
+	*/
+	if (!RIOBootOk(p, HostP, RtaUniq))
+	{
+	    MyLink = RBYTE(PktCmdP->LinkNum);
+	    if (Rup < (ushort) MAX_RUP)
+	    {
+		/*
+		** RtaUniq was clone booted (by this RTA). Instruct this RTA
+		** to hold off further attempts to boot on this link for 30
+		** seconds.
+		*/
+		if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink))
+		{
+		    rio_dprintk (RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n",
+		     'A' + MyLink);
+		}
+	    }
+	    else
+	    {
+		/*
+		** RtaUniq was booted by this host. Set the booting link
+		** to hold off for 30 seconds to give another unit a
+		** chance to boot it.
+		*/
+		WWORD(HostP->LinkStrP[MyLink].WaitNoBoot, 30);
+	    }
+	    rio_dprintk (RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n",
+	      RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum);
+	    return TRUE;
+	}
+
+	/*
+	** Check for a SLOT_IN_USE entry for this RTA attached to the
+	** current host card in the driver table.
+	**
+	** If it exists, make a note that we have booted it. Other parts of
+	** the driver are interested in this information at a later date,
+	** in particular when the booting RTA asks for an ID for this unit,
+	** we must have set the BOOTED flag, and the NEWBOOT flag is used
+	** to force an open on any ports that where previously open on this
+	** unit.
+	*/
+        for ( entry=0; entry<MAX_RUP; entry++ )
+	{
+	    uint sysport;
+
+	    if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && 
+	       (HostP->Mapping[entry].RtaUniqueNum==RtaUniq))
+	    {
+	        HostP->Mapping[entry].Flags |= RTA_BOOTED|RTA_NEWBOOT;
+#if NEED_TO_FIX
+		RIO_SV_BROADCAST(HostP->svFlags[entry]);
+#endif
+		if ( (sysport=HostP->Mapping[entry].SysPort) != NO_PORT )
+		{
+		   if ( sysport < p->RIOFirstPortsBooted )
+			p->RIOFirstPortsBooted = sysport;
+		   if ( sysport > p->RIOLastPortsBooted )
+			p->RIOLastPortsBooted = sysport;
+		   /*
+		   ** For a 16 port RTA, check the second bank of 8 ports
+		   */
+		   if (RtaType == TYPE_RTA16)
+		   {
+			entry2 = HostP->Mapping[entry].ID2 - 1;
+			HostP->Mapping[entry2].Flags |= RTA_BOOTED|RTA_NEWBOOT;
+#if NEED_TO_FIX
+			RIO_SV_BROADCAST(HostP->svFlags[entry2]);
+#endif
+			sysport = HostP->Mapping[entry2].SysPort;
+			if ( sysport < p->RIOFirstPortsBooted )
+			    p->RIOFirstPortsBooted = sysport;
+			if ( sysport > p->RIOLastPortsBooted )
+			    p->RIOLastPortsBooted = sysport;
+		   }
+		}
+		if (RtaType == TYPE_RTA16) {
+		   rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n",
+		    entry+1, entry2+1);
+		} else {
+		   rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given ID %d\n",entry+1);
+		}
+		return TRUE;
+	    }
+	}
+
+	rio_dprintk (RIO_DEBUG_BOOT, "RTA not configured for this host\n");
+
+	if ( Rup >= (ushort)MAX_RUP )
+	{
+	    /*
+	    ** It was a host that did the booting
+	    */
+	    MyType = "Host";
+	    MyName = HostP->Name;
+	}
+	else
+	{
+	    /*
+	    ** It was an RTA that did the booting
+	    */
+	    MyType = "RTA";
+	    MyName = HostP->Mapping[Rup].Name;
+	}
+#ifdef CHECK
+	CheckString(MyType);
+	CheckString(MyName);
+#endif
+
+	MyLink = RBYTE(PktCmdP->LinkNum);
+
+	/*
+	** There is no SLOT_IN_USE entry for this RTA attached to the current
+	** host card in the driver table.
+	**
+	** Check for a SLOT_TENTATIVE entry for this RTA attached to the
+	** current host card in the driver table.
+	**
+	** If we find one, then we re-use that slot.
+	*/
+	for ( entry=0; entry<MAX_RUP; entry++ )
+	{
+	    if ( (HostP->Mapping[entry].Flags & SLOT_TENTATIVE) &&
+		 (HostP->Mapping[entry].RtaUniqueNum == RtaUniq) )
+	    {
+		if (RtaType == TYPE_RTA16)
+		{
+		    entry2 = HostP->Mapping[entry].ID2 - 1;
+		    if ( (HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) &&
+			 (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq) )
+			rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n",
+			 entry, entry2);
+		    else
+			continue;
+		}
+		else
+			rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n",entry);
+		if (! p->RIONoMessage)
+		    cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A');
+		return TRUE;
+	    }
+	}
+
+	/*
+	** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	** attached to the current host card in the driver table.
+	**
+	** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
+	** host for this RTA in the driver table.
+	**
+	** For a SLOT_IN_USE entry on another host, we need to delete the RTA
+	** entry from the other host and add it to this host (using some of
+	** the functions from table.c which do this).
+	** For a SLOT_TENTATIVE entry on another host, we must cope with the
+	** following scenario:
+	**
+	** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
+	**   in table)
+	** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
+	**   entries)
+	** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
+	** + Unplug RTA and plug back into host A.
+	** + Configure RTA on host A. We now have the same RTA configured
+	**   with different ports on two different hosts.
+	*/
+	rio_dprintk (RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq );
+	found = 0;
+	Flag = 0; /* Convince the compiler this variable is initialized */
+	for ( host = 0; !found && (host < p->RIONumHosts); host++ )
+	{
+	    for ( rta=0; rta<MAX_RUP; rta++ )
+	    {
+		if ((p->RIOHosts[host].Mapping[rta].Flags &
+		 (SLOT_IN_USE | SLOT_TENTATIVE)) &&
+		 (p->RIOHosts[host].Mapping[rta].RtaUniqueNum==RtaUniq))
+		{
+		    Flag = p->RIOHosts[host].Mapping[rta].Flags;
+		    MapP = &p->RIOHosts[host].Mapping[rta];
+		    if (RtaType == TYPE_RTA16)
+		    {
+			MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1];
+			rio_dprintk (RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n",
+			 rta+1, MapP->ID2, p->RIOHosts[host].Name);
+		    }
+		    else
+			rio_dprintk (RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n",
+			 rta+1, p->RIOHosts[host].Name);
+		    found = 1;
+		    break;
+		}
+	    }
+	}
+
+	/*
+	** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	** attached to the current host card in the driver table.
+	**
+	** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
+	** another host for this RTA in the driver table...
+	**
+	** Check for a SLOT_IN_USE entry for this RTA in the config table.
+	*/
+	if ( !MapP )
+	{
+	    rio_dprintk (RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n",RtaUniq);
+	    for ( rta=0; rta < TOTAL_MAP_ENTRIES; rta++ )
+	    {
+		rio_dprintk (RIO_DEBUG_BOOT, "Check table entry %d (%x)",
+		      rta,
+		      p->RIOSavedTable[rta].RtaUniqueNum);
+
+		if ( (p->RIOSavedTable[rta].Flags & SLOT_IN_USE) &&
+		 (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq) )
+		{
+		    MapP = &p->RIOSavedTable[rta];
+		    Flag = p->RIOSavedTable[rta].Flags;
+		    if (RtaType == TYPE_RTA16)
+		    {
+                        for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES;
+                         entry2++)
+                        {
+                            if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq)
+                                break;
+                        }
+                        MapP2 = &p->RIOSavedTable[entry2];
+                        rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n",
+                              rta, entry2);
+		    }
+		    else
+			rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta);
+		    break;
+		}
+	    }
+	}
+
+	/*
+	** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	** attached to the current host card in the driver table.
+	**
+	** We may have found a SLOT_IN_USE entry on another host for this
+	** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
+	** on another host for this RTA in the driver table.
+	**
+	** Check the driver table for room to fit this newly discovered RTA.
+	** RIOFindFreeID() first looks for free slots and if it does not
+	** find any free slots it will then attempt to oust any
+	** tentative entry in the table.
+	*/
+	EmptySlot = 1;
+	if (RtaType == TYPE_RTA16)
+	{
+	    if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0)
+	    {
+		RIODefaultName(p, HostP, entry);
+		FillSlot(entry, entry2, RtaUniq, HostP);
+		EmptySlot = 0;
+	    }
+	}
+	else
+	{
+	    if (RIOFindFreeID(p, HostP, &entry, NULL) == 0)
+	    {
+		RIODefaultName(p, HostP, entry);
+		FillSlot(entry, 0, RtaUniq, HostP);
+		EmptySlot = 0;
+	    }
+	}
+
+	/*
+	** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	** attached to the current host card in the driver table.
+	**
+	** If we found a SLOT_IN_USE entry on another host for this
+	** RTA in the config or driver table, and there are enough free
+	** slots in the driver table, then we need to move it over and
+	** delete it from the other host.
+	** If we found a SLOT_TENTATIVE entry on another host for this
+	** RTA in the driver table, just delete the other host entry.
+	*/
+	if (EmptySlot == 0)
+	{
+	    if ( MapP )
+	    {
+		if (Flag & SLOT_IN_USE)
+		{
+		    rio_dprintk (RIO_DEBUG_BOOT, 
+    "This RTA configured on another host - move entry to current host (1)\n");
+		    HostP->Mapping[entry].SysPort = MapP->SysPort;
+		    CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN );
+		    HostP->Mapping[entry].Flags =
+		     SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
+#if NEED_TO_FIX
+		    RIO_SV_BROADCAST(HostP->svFlags[entry]);
+#endif
+		    RIOReMapPorts( p, HostP, &HostP->Mapping[entry] );
+		    if ( HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted )
+			p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort;
+		    if ( HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted )
+			p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort;
+		    rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %s\n",(int)MapP->SysPort,MapP->Name);
+		}
+		else
+		{
+		    rio_dprintk (RIO_DEBUG_BOOT, 
+   "This RTA has a tentative entry on another host - delete that entry (1)\n");
+		    HostP->Mapping[entry].Flags =
+		     SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
+#if NEED_TO_FIX
+		    RIO_SV_BROADCAST(HostP->svFlags[entry]);
+#endif
+		}
+		if (RtaType == TYPE_RTA16)
+		{
+		    if (Flag & SLOT_IN_USE)
+		    {
+			HostP->Mapping[entry2].Flags = SLOT_IN_USE |
+			 RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
+#if NEED_TO_FIX
+			RIO_SV_BROADCAST(HostP->svFlags[entry2]);
+#endif
+			HostP->Mapping[entry2].SysPort = MapP2->SysPort;
+			/*
+			** Map second block of ttys for 16 port RTA
+			*/
+			RIOReMapPorts( p, HostP, &HostP->Mapping[entry2] );
+		       if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted)
+			 p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort;
+		       if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted)
+			 p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort;
+			rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %s\n",
+			       (int)HostP->Mapping[entry2].SysPort,
+			       HostP->Mapping[entry].Name);
+		    }
+		    else
+			HostP->Mapping[entry2].Flags = SLOT_TENTATIVE |
+			 RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
+#if NEED_TO_FIX
+			RIO_SV_BROADCAST(HostP->svFlags[entry2]);
+#endif
+		    bzero( (caddr_t)MapP2, sizeof(struct Map) );
+		}
+		bzero( (caddr_t)MapP, sizeof(struct Map) );
+		if (! p->RIONoMessage)
+		    cprintf("An orphaned RTA has been adopted by %s '%s' (%c).\n",MyType,MyName,MyLink+'A');
+	    }
+	    else if (! p->RIONoMessage)
+		cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A');
+	    RIOSetChange(p);
+	    return TRUE;
+	}
+
+	/*
+	** There is no room in the driver table to make an entry for the
+	** booted RTA. Keep a note of its Uniq Num in the overflow table,
+	** so we can ignore it's ID requests.
+	*/
+	if (! p->RIONoMessage)
+	    cprintf("The RTA connected to %s '%s' (%c) cannot be configured.  You cannot configure more than 128 ports to one host card.\n",MyType,MyName,MyLink+'A');
+	for ( entry=0; entry<HostP->NumExtraBooted; entry++ )
+	{
+	    if ( HostP->ExtraUnits[entry] == RtaUniq )
+	    {
+		/*
+		** already got it!
+		*/
+		return TRUE;
+	    }
+	}
+	/*
+	** If there is room, add the unit to the list of extras
+	*/
+	if ( HostP->NumExtraBooted < MAX_EXTRA_UNITS )
+	    HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq;
+	return TRUE;
+}
+
+
+/*
+** If the RTA or its host appears in the RIOBindTab[] structure then
+** we mustn't boot the RTA and should return FALSE.
+** This operation is slightly different from the other drivers for RIO
+** in that this is designed to work with the new utilities
+** not config.rio and is FAR SIMPLER.
+** We no longer support the RIOBootMode variable. It is all done from the
+** "boot/noboot" field in the rio.cf file.
+*/
+int
+RIOBootOk(p, HostP, RtaUniq)
+struct rio_info *	p;
+struct Host *		HostP;
+ulong RtaUniq;
+{
+    int		Entry;
+    uint HostUniq = HostP->UniqueNum;
+
+	/*
+	** Search bindings table for RTA or its parent.
+	** If it exists, return 0, else 1.
+	*/
+	for (Entry = 0;
+	    ( Entry < MAX_RTA_BINDINGS ) && ( p->RIOBindTab[Entry] != 0 );
+	    Entry++)
+	{
+		if ( (p->RIOBindTab[Entry] == HostUniq) ||
+		     (p->RIOBindTab[Entry] == RtaUniq) )
+			return 0;
+	}
+	return 1;
+}
+
+/*
+** Make an empty slot tentative. If this is a 16 port RTA, make both
+** slots tentative, and the second one RTA_SECOND_SLOT as well.
+*/
+
+void
+FillSlot(entry, entry2, RtaUniq, HostP)
+int entry;
+int entry2;
+uint RtaUniq;
+struct Host *HostP;
+{
+	int		link;
+
+	rio_dprintk (RIO_DEBUG_BOOT, "FillSlot(%d, %d, 0x%x...)\n", entry, entry2, RtaUniq);
+
+	HostP->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE);
+	HostP->Mapping[entry].SysPort = NO_PORT;
+	HostP->Mapping[entry].RtaUniqueNum = RtaUniq;
+	HostP->Mapping[entry].HostUniqueNum = HostP->UniqueNum;
+	HostP->Mapping[entry].ID = entry + 1;
+	HostP->Mapping[entry].ID2 = 0;
+	if (entry2) {
+		HostP->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | 
+								SLOT_TENTATIVE | RTA16_SECOND_SLOT);
+		HostP->Mapping[entry2].SysPort = NO_PORT;
+		HostP->Mapping[entry2].RtaUniqueNum = RtaUniq;
+		HostP->Mapping[entry2].HostUniqueNum = HostP->UniqueNum;
+		HostP->Mapping[entry2].Name[0] = '\0';
+		HostP->Mapping[entry2].ID = entry2 + 1;
+		HostP->Mapping[entry2].ID2 = entry + 1;
+		HostP->Mapping[entry].ID2 = entry2 + 1;
+	}
+	/*
+	** Must set these up, so that utilities show
+	** topology of 16 port RTAs correctly
+	*/
+	for ( link=0; link<LINKS_PER_UNIT; link++ ) {
+		HostP->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT;
+		HostP->Mapping[entry].Topology[link].Link = NO_LINK;
+		if (entry2) {
+			HostP->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT;
+			HostP->Mapping[entry2].Topology[link].Link = NO_LINK;
+		}
+	}
+}
+
+#if 0
+/*
+	Function:	This function is to disable the disk interrupt 
+    Returns :   Nothing
+*/
+void
+disable_interrupt(vector)
+int	vector;
+{
+	int	ps;
+	int	val;
+
+	disable(ps);
+	if (vector > 40)  {
+		val = 1 << (vector - 40);
+		__outb(S8259+1, __inb(S8259+1) | val);
+	}
+	else {
+		val = 1 << (vector - 32);
+		__outb(M8259+1, __inb(M8259+1) | val);
+	}
+	restore(ps);
+}
+
+/*
+	Function:	This function is to enable the disk interrupt 
+    Returns :   Nothing
+*/
+void
+enable_interrupt(vector)
+int	vector;
+{
+	int	ps;
+	int	val;
+
+	disable(ps);
+	if (vector > 40)  {
+		val = 1 << (vector - 40);
+		val = ~val;
+		__outb(S8259+1, __inb(S8259+1) & val);
+	}
+	else {
+		val = 1 << (vector - 32);
+		val = ~val;
+		__outb(M8259+1, __inb(M8259+1) & val);
+	}
+	restore(ps);
+}
+#endif
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
new file mode 100644
index 0000000..533085e
--- /dev/null
+++ b/drivers/char/rio/riocmd.c
@@ -0,0 +1,1041 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  ported from the existing SCO driver source
+**
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riocmd.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:41
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)riocmd.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_riocmd_c_sccs_ = "@(#)riocmd.c	1.2";
+#endif
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+
+
+static struct IdentifyRta IdRta;
+static struct KillNeighbour KillUnit;
+
+int
+RIOFoadRta(struct Host *HostP, struct Map *MapP)
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA\n");
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if ( !CmdBlkP ) {
+		rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
+		return -ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = MapP->ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+	CmdBlkP->Packet.len	   = 0x84;
+	CmdBlkP->Packet.data[0]   = IFOAD;
+	CmdBlkP->Packet.data[1]   = 0;
+	CmdBlkP->Packet.data[2]   = IFOAD_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3]   = (IFOAD_MAGIC >> 8) & 0xFF;
+
+	if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
+		rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+int
+RIOZombieRta(struct Host *HostP, struct Map *MapP)
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA\n");
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if ( !CmdBlkP ) {
+		rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
+		return -ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = MapP->ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+	CmdBlkP->Packet.len	   = 0x84;
+	CmdBlkP->Packet.data[0]   = ZOMBIE;
+	CmdBlkP->Packet.data[1]   = 0;
+	CmdBlkP->Packet.data[2]   = ZOMBIE_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3]   = (ZOMBIE_MAGIC >> 8) & 0xFF;
+
+	if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
+		rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+int
+RIOCommandRta(struct rio_info *p, uint RtaUnique,
+	int (* func)(struct Host *HostP, struct Map *MapP))
+{
+	uint Host;
+
+	rio_dprintk (RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int)func);
+
+	if ( !RtaUnique )
+		return(0);
+
+	for ( Host = 0; Host < p->RIONumHosts; Host++ ) {
+		uint Rta;
+		struct Host *HostP = &p->RIOHosts[Host];
+
+		for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) {
+			struct Map *MapP = &HostP->Mapping[Rta];
+
+			if ( MapP->RtaUniqueNum == RtaUnique ) {
+				uint Link;
+
+				/*
+				** now, lets just check we have a route to it...
+				** IF the routing stuff is working, then one of the
+				** topology entries for this unit will have a legit
+				** route *somewhere*. We care not where - if its got
+				** any connections, we can get to it.
+				*/
+				for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) {
+					if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) {
+						/*
+						** Its worth trying the operation...
+						*/
+						return (*func)( HostP, MapP );
+					}
+				}
+			}
+		}
+	}
+	return -ENXIO;
+}
+
+
+int
+RIOIdentifyRta(struct rio_info *p, caddr_t arg)
+{
+	uint Host;
+
+	if ( copyin( (int)arg, (caddr_t)&IdRta, sizeof(IdRta) ) == COPYFAIL ) {
+		rio_dprintk (RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
+		p->RIOError.Error = COPYIN_FAILED;
+		return -EFAULT;
+	}
+
+	for ( Host = 0 ; Host < p->RIONumHosts; Host++ ) {
+		uint Rta;
+		struct Host *HostP = &p->RIOHosts[Host];
+
+		for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) {
+			struct Map *MapP = &HostP->Mapping[Rta];
+
+			if ( MapP->RtaUniqueNum == IdRta.RtaUnique ) {
+				uint Link;
+				/*
+				** now, lets just check we have a route to it...
+				** IF the routing stuff is working, then one of the
+				** topology entries for this unit will have a legit
+				** route *somewhere*. We care not where - if its got
+				** any connections, we can get to it.
+				*/
+				for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) {
+					if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) {
+						/*
+						** Its worth trying the operation...
+						*/
+						struct CmdBlk *CmdBlkP;
+
+						rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA\n");
+
+						CmdBlkP = RIOGetCmdBlk();
+
+						if ( !CmdBlkP ) {
+							rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
+							return -ENXIO;
+						}
+		
+						CmdBlkP->Packet.dest_unit = MapP->ID;
+						CmdBlkP->Packet.dest_port = BOOT_RUP;
+						CmdBlkP->Packet.src_unit  = 0;
+						CmdBlkP->Packet.src_port  = BOOT_RUP;
+						CmdBlkP->Packet.len	   = 0x84;
+						CmdBlkP->Packet.data[0]   = IDENTIFY;
+						CmdBlkP->Packet.data[1]   = 0;
+						CmdBlkP->Packet.data[2]   = IdRta.ID;
+		
+						if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
+							rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
+							return -EIO;
+						}
+						return 0;
+					}
+				}
+			}
+		}
+	} 
+	return -ENOENT;
+}
+
+
+int
+RIOKillNeighbour(struct rio_info *p, caddr_t arg)
+{
+	uint Host;
+	uint ID;
+	struct Host *HostP;
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprintk (RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
+
+	if ( copyin( (int)arg, (caddr_t)&KillUnit, sizeof(KillUnit) ) == COPYFAIL ) {
+		rio_dprintk (RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
+		p->RIOError.Error = COPYIN_FAILED;
+		return -EFAULT;
+	}
+
+	if ( KillUnit.Link > 3 )
+		return -ENXIO;
+ 
+	CmdBlkP = RIOGetCmdBlk();
+
+	if ( !CmdBlkP ) {
+		rio_dprintk (RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
+		return -ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = 0;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+	CmdBlkP->Packet.len	   = 0x84;
+	CmdBlkP->Packet.data[0]   = UFOAD;
+	CmdBlkP->Packet.data[1]   = KillUnit.Link;
+	CmdBlkP->Packet.data[2]   = UFOAD_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3]   = (UFOAD_MAGIC >> 8) & 0xFF;
+
+	for ( Host = 0; Host < p->RIONumHosts; Host++ ) {
+		ID = 0;
+		HostP = &p->RIOHosts[Host];
+
+		if ( HostP->UniqueNum == KillUnit.UniqueNum ) {
+			if ( RIOQueueCmdBlk( HostP, RTAS_PER_HOST+KillUnit.Link,
+							CmdBlkP) == RIO_FAIL ) {
+				rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
+				return -EIO;
+			}
+			return 0;
+		}
+
+		for ( ID=0; ID < RTAS_PER_HOST; ID++ ) {
+			if ( HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum ) {
+				CmdBlkP->Packet.dest_unit = ID+1;
+				if ( RIOQueueCmdBlk( HostP, ID, CmdBlkP) == RIO_FAIL ) {
+					rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
+					return -EIO;
+				}
+				return 0;
+			}
+		}
+	}
+	RIOFreeCmdBlk( CmdBlkP );
+	return -ENXIO;
+}
+
+int
+RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if ( !CmdBlkP ) {
+		rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
+		return -ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit  = 0;
+	CmdBlkP->Packet.src_port  = BOOT_RUP;
+	CmdBlkP->Packet.len	   = 0x84;
+	CmdBlkP->Packet.data[0]   = IWAIT;
+	CmdBlkP->Packet.data[1]   = Link;
+	CmdBlkP->Packet.data[2]   = IWAIT_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3]   = (IWAIT_MAGIC >> 8) & 0xFF;
+
+	if ( RIOQueueCmdBlk( HostP, ID - 1, CmdBlkP) == RIO_FAIL ) {
+		rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+int
+RIOFoadWakeup(struct rio_info *p)
+{
+	int port;
+	register struct Port *PortP;
+	unsigned long flags;
+
+	for ( port=0; port<RIO_PORTS; port++) {
+		PortP = p->RIOPortp[port];
+
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->Config = 0;
+		PortP->State = 0;
+		PortP->InUse = NOT_INUSE;
+		PortP->PortState = 0;
+		PortP->FlushCmdBodge = 0;
+		PortP->ModemLines = 0;
+		PortP->ModemState = 0;
+		PortP->CookMode = 0;
+		PortP->ParamSem = 0;
+		PortP->Mapped = 0;
+		PortP->WflushFlag = 0;
+		PortP->MagicFlags = 0;
+		PortP->RxDataStart = 0;
+		PortP->TxBufferIn = 0;
+		PortP->TxBufferOut = 0;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	}
+	return(0);
+}
+
+/*
+** Incoming command on the COMMAND_RUP to be processed.
+*/
+static int
+RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
+{
+	struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
+	struct Port *PortP;
+	struct UnixRup *UnixRupP;
+	ushort SysPort;
+	ushort ReportedModemStatus;
+	ushort rup;
+	ushort subCommand;
+	unsigned long flags;
+
+	func_enter ();
+
+#ifdef CHECK
+	CheckHost( Host );
+	CheckHostP( HostP );
+	CheckPacketP( PacketP );
+#endif
+
+	/*
+	** 16 port RTA note:
+	** Command rup packets coming from the RTA will have pkt->data[1] (which
+	** translates to PktCmdP->PhbNum) set to the host port number for the
+	** particular unit. To access the correct BaseSysPort for a 16 port RTA,
+	** we can use PhbNum to get the rup number for the appropriate 8 port
+	** block (for the first block, this should be equal to 'Rup').
+	*/
+	rup = RBYTE(PktCmdP->PhbNum) / (ushort)PORTS_PER_RTA;
+	UnixRupP = &HostP->UnixRups[rup];
+	SysPort = UnixRupP->BaseSysPort + 
+			(RBYTE(PktCmdP->PhbNum) % (ushort)PORTS_PER_RTA);
+	rio_dprintk (RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
+
+#ifdef CHECK
+	CheckRup( rup );
+	CheckUnixRupP( UnixRupP );
+#endif
+	if ( UnixRupP->BaseSysPort == NO_PORT ) {
+		rio_dprintk (RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
+		rio_dprintk (RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
+		rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n", 
+			     HostP-p->RIOHosts, HostP->Name );
+		rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Rup number  0x%x\n", rup);
+
+		if ( Rup >= (ushort)MAX_RUP ) {
+			rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n",
+				     HostP->Mapping[Rup].Name);
+		} else
+			rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", 
+				     ('A' + Rup - MAX_RUP), HostP->Name);
+
+		rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n",
+			     PacketP->dest_unit, PacketP->dest_port );
+		rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Source	  0x%x:0x%x\n",
+			     PacketP->src_unit, PacketP->src_port );
+		rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", PacketP->len,PacketP->len );
+		rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", PacketP->control, PacketP->control);
+		rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", PacketP->csum, PacketP->csum );
+		rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, "
+					"Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command );
+		return TRUE;
+	}
+
+#ifdef CHECK
+	CheckSysPort( SysPort );
+#endif
+	PortP = p->RIOPortp[ SysPort ];
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	switch( RBYTE(PktCmdP->Command) ) {
+		case BREAK_RECEIVED:
+			rio_dprintk (RIO_DEBUG_CMD, "Received a break!\n");
+			/* If the current line disc. is not multi-threading and
+	   			the current processor is not the default, reset rup_intr
+	   			and return FALSE to ensure that the command packet is
+	   			not freed. */
+			/* Call tmgr HANGUP HERE */
+			/* Fix this later when every thing works !!!! RAMRAJ */
+			gs_got_break (&PortP->gs);
+			break;
+
+		case COMPLETE:
+			rio_dprintk (RIO_DEBUG_CMD, "Command complete on phb %d host %d\n",
+			     RBYTE(PktCmdP->PhbNum), HostP-p->RIOHosts);
+			subCommand = 1;
+			switch (RBYTE(PktCmdP->SubCommand)) {
+				case MEMDUMP :
+			rio_dprintk (RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n",
+				     RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr));
+					break;
+				case READ_REGISTER :
+			rio_dprintk (RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr));
+					p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST);
+					break;
+				default :
+					subCommand = 0;
+				break;
+			}
+			if (subCommand)
+				break;
+			rio_dprintk (RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n",
+				     RBYTE(PktCmdP->PortStatus),PortP->PortState);
+			if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) {
+				rio_dprintk (RIO_DEBUG_CMD, "Mark status & wakeup\n");
+				PortP->PortState = RBYTE(PktCmdP->PortStatus);
+				/* What should we do here ...
+				wakeup( &PortP->PortState );
+				*/
+		} else 
+			rio_dprintk (RIO_DEBUG_CMD, "No change\n");
+
+			/* FALLTHROUGH */
+		case MODEM_STATUS:
+			/*
+			** Knock out the tbusy and tstop bits, as these are not relevant
+			** to the check for modem status change (they're just there because
+			** it's a convenient place to put them!).
+			*/
+			ReportedModemStatus = RBYTE(PktCmdP->ModemStatus);
+			if ((PortP->ModemState & MSVR1_HOST) ==
+					(ReportedModemStatus & MSVR1_HOST)) {
+				rio_dprintk (RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
+				/*
+				** Update ModemState just in case tbusy or tstop states have
+				** changed.
+				*/
+				PortP->ModemState = ReportedModemStatus;
+			}
+			else {
+				rio_dprintk (RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n",
+				     PortP->ModemState, ReportedModemStatus);
+				PortP->ModemState = ReportedModemStatus;
+#ifdef MODEM_SUPPORT
+				if ( PortP->Mapped ) {
+				/***********************************************************\
+				*************************************************************
+				***													   ***
+				***		  M O D E M   S T A T E   C H A N G E		  ***
+				***													   ***
+				*************************************************************
+				\***********************************************************/
+				/*
+				** If the device is a modem, then check the modem
+				** carrier.
+				*/
+				if (PortP->gs.tty == NULL)
+					break;
+				if (PortP->gs.tty->termios == NULL)
+					break;
+			  
+				if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) &&
+				((PortP->State & (RIO_MOPEN|RIO_WOPEN)))) {
+
+					rio_dprintk (RIO_DEBUG_CMD, "Is there a Carrier?\n");
+			/*
+			** Is there a carrier?
+			*/
+					if ( PortP->ModemState & MSVR1_CD ) {
+			/*
+			** Has carrier just appeared?
+			*/
+						if (!(PortP->State & RIO_CARR_ON)) {
+							rio_dprintk (RIO_DEBUG_CMD, "Carrier just came up.\n");
+							PortP->State |= RIO_CARR_ON;
+				/*
+				** wakeup anyone in WOPEN
+				*/
+							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN) )
+								wake_up_interruptible (&PortP->gs.open_wait);
+#ifdef STATS
+				PortP->Stat.ModemOnCnt++;
+#endif
+			}
+					} else {
+			/*
+			** Has carrier just dropped?
+			*/
+						if (PortP->State & RIO_CARR_ON) {
+							if (PortP->State & (PORT_ISOPEN|RIO_WOPEN|RIO_MOPEN))
+								tty_hangup (PortP->gs.tty);
+							PortP->State &= ~RIO_CARR_ON;
+							rio_dprintk (RIO_DEBUG_CMD, "Carrirer just went down\n");
+#ifdef STATS
+				PortP->Stat.ModemOffCnt++;
+#endif
+			}
+			}
+		}
+		}
+#endif
+			}
+			break;
+
+		default:
+			rio_dprintk (RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n",
+			     RBYTE(PktCmdP->Command),HostP-p->RIOHosts);
+			break;
+	}
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+	func_exit ();
+
+	return TRUE;
+}
+/*
+** The command mechanism:
+**	Each rup has a chain of commands associated with it.
+**	This chain is maintained by routines in this file.
+**	Periodically we are called and we run a quick check of all the
+**	active chains to determine if there is a command to be executed,
+**	and if the rup is ready to accept it.
+**
+*/
+
+/*
+** Allocate an empty command block.
+*/
+struct CmdBlk *
+RIOGetCmdBlk(void)
+{
+	struct CmdBlk *CmdBlkP;
+
+	CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk));
+	if (CmdBlkP)
+		bzero(CmdBlkP, sizeof(struct CmdBlk));
+
+	return CmdBlkP;
+}
+
+/*
+** Return a block to the head of the free list.
+*/
+void
+RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
+{
+	sysfree((void *)CmdBlkP, sizeof(struct CmdBlk));
+}
+
+/*
+** attach a command block to the list of commands to be performed for
+** a given rup.
+*/
+int
+RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
+{
+	struct CmdBlk **Base;
+	struct UnixRup *UnixRupP;
+	unsigned long flags;
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckRup( Rup );
+	CheckCmdBlkP( CmdBlkP );
+#endif
+	if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) {
+		rio_dprintk (RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n",Rup);
+		RIOFreeCmdBlk( CmdBlkP );
+		return RIO_FAIL;
+	}
+
+	UnixRupP = &HostP->UnixRups[Rup];
+
+	rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+
+	/*
+	** If the RUP is currently inactive, then put the request
+	** straight on the RUP....
+	*/
+	if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && 
+	     (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE ) &&
+		(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP)
+							:TRUE)) {
+		rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n",
+					     CmdBlkP->Packet.data[0]);
+
+		/*
+		** Whammy! blat that pack!
+		*/
+		HostP->Copy( (caddr_t)&CmdBlkP->Packet, 
+			RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt ), sizeof(PKT) );
+
+		/*
+		** place command packet on the pending position.
+		*/
+		UnixRupP->CmdPendingP = CmdBlkP;
+
+		/*
+		** set the command register
+		*/
+		WWORD(UnixRupP->RupP->txcontrol , TX_PACKET_READY);
+
+		rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+
+		return RIO_SUCCESS;
+	}
+	rio_dprintk (RIO_DEBUG_CMD, "RUP active - en-queing\n");
+
+	if ( UnixRupP->CmdsWaitingP != NULL)
+		rio_dprintk (RIO_DEBUG_CMD, "Rup active - command waiting\n");
+	if ( UnixRupP->CmdPendingP != NULL )
+		rio_dprintk (RIO_DEBUG_CMD, "Rup active - command pending\n");
+	if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE )
+		rio_dprintk (RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
+
+	Base = &UnixRupP->CmdsWaitingP;
+
+	rio_dprintk (RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int)CmdBlkP,(int)Base);
+
+	while ( *Base ) {
+		rio_dprintk (RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int)(*Base));
+		Base = &((*Base)->NextP);
+		rio_dprintk (RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n",
+					     (int)CmdBlkP,(int)Base);
+	}
+
+	rio_dprintk (RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base);
+
+	*Base = CmdBlkP;
+
+	CmdBlkP->NextP = NULL;
+
+	rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+
+	return RIO_SUCCESS;
+}
+
+/*
+** Here we go - if there is an empty rup, fill it!
+** must be called at splrio() or higher.
+*/
+void
+RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
+{
+	register struct CmdBlk *CmdBlkP;
+	register struct UnixRup *UnixRupP;
+	struct PKT *PacketP;
+	ushort Rup;
+	unsigned long flags;
+
+
+	Rup = MAX_RUP+LINKS_PER_UNIT;
+
+	do {	/* do this loop for each RUP */
+		/*
+		** locate the rup we are processing & lock it
+		*/
+		UnixRupP = &HostP->UnixRups[--Rup];
+
+		spin_lock_irqsave(&UnixRupP->RupLock, flags);
+
+		/*
+		** First check for incoming commands:
+		*/
+		if ( RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE ) {
+			int FreeMe;
+
+			PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt));
+
+			ShowPacket( DBG_CMD, PacketP );
+
+			switch ( RBYTE(PacketP->dest_port) ) {
+				case BOOT_RUP:
+					rio_dprintk (RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", 
+						RBYTE(PacketP->len) & 0x80 ? "Command":"Data", 
+							     RBYTE(PacketP->data[0])); 
+					rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+					FreeMe= RIOBootRup(p, Rup,HostP,PacketP);
+					rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+					break;
+
+				case COMMAND_RUP:
+					/*
+					** Free the RUP lock as loss of carrier causes a
+					** ttyflush which will (eventually) call another
+					** routine that uses the RUP lock.
+					*/
+					rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+					FreeMe= RIOCommandRup(p, Rup,HostP,PacketP);
+					if (PacketP->data[5] == MEMDUMP) {
+						rio_dprintk (RIO_DEBUG_CMD, "Memdump from 0x%x complete\n",
+								     *(ushort *) &(PacketP->data[6]));
+						HostP->Copy( (caddr_t)&(PacketP->data[8]), 
+								(caddr_t)p->RIOMemDump, 32 );
+					}
+					rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+					break;
+
+				case ROUTE_RUP:
+					rio_spin_unlock_irqrestore( &UnixRupP->RupLock, flags);
+					FreeMe = RIORouteRup(p, Rup, HostP, PacketP );
+					rio_spin_lock_irqsave( &UnixRupP->RupLock, flags );
+					break;
+
+				default:
+					rio_dprintk (RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port));
+					FreeMe = 1;
+					break;
+			}
+
+			if ( FreeMe ) {
+				rio_dprintk (RIO_DEBUG_CMD, "Free processed incoming command packet\n");
+				put_free_end(HostP,PacketP);
+
+				WWORD(UnixRupP->RupP->rxcontrol , RX_RUP_INACTIVE);
+
+				if ( RWORD(UnixRupP->RupP->handshake)==PHB_HANDSHAKE_SET ) {
+					rio_dprintk (RIO_DEBUG_CMD, "Handshake rup %d\n",Rup);
+					WWORD(UnixRupP->RupP->handshake,
+						PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET);
+				}
+			}
+		}
+
+		/*
+		** IF a command was running on the port, 
+		** and it has completed, then tidy it up.
+		*/
+		if ( (CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */
+		     (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
+			/*
+			** we are idle.
+			** there is a command in pending.
+			** Therefore, this command has finished.
+			** So, wakeup whoever is waiting for it (and tell them
+			** what happened).
+			*/
+			if ( CmdBlkP->Packet.dest_port == BOOT_RUP )
+				rio_dprintk (RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", 
+						CmdBlkP->Packet.len & 0x80 ? "Command":"Data", 
+							     CmdBlkP->Packet.data[0]);
+
+			rio_dprintk (RIO_DEBUG_CMD, "Command 0x%x completed\n",(int)CmdBlkP);
+
+			/*
+			** Clear the Rup lock to prevent mutual exclusion.
+			*/
+			if ( CmdBlkP->PostFuncP ) {
+				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+				(*CmdBlkP->PostFuncP) (CmdBlkP->PostArg,CmdBlkP);
+				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+			}
+
+			/*
+			** ....clear the pending flag....
+			*/
+			UnixRupP->CmdPendingP = NULL;
+
+			/*
+			** ....and return the command block to the freelist.
+			*/
+			RIOFreeCmdBlk( CmdBlkP );
+		}
+
+		/*
+		** If there is a command for this rup, and the rup
+		** is idle, then process the command
+		*/
+		if ( (CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */
+			(UnixRupP->CmdPendingP == NULL) &&
+		     (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
+			/*
+			** if the pre-function is non-zero, call it.
+			** If it returns RIO_FAIL then don't
+			** send this command yet!
+			*/
+#ifdef CHECK
+			CheckCmdBlkP (CmdBlkP);
+#endif
+			if ( !(CmdBlkP->PreFuncP ?
+				(*CmdBlkP->PreFuncP)(CmdBlkP->PreArg, CmdBlkP) : TRUE)) {
+				rio_dprintk (RIO_DEBUG_CMD, "Not ready to start command 0x%x\n",(int)CmdBlkP);
+			}
+			else {
+				rio_dprintk (RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n",
+							     (int)CmdBlkP, CmdBlkP->Packet.data[0]);
+				/*
+				** Whammy! blat that pack!
+				*/
+#ifdef CHECK
+				CheckPacketP ((PKT *)RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt));
+#endif
+				HostP->Copy( (caddr_t)&CmdBlkP->Packet, 
+					RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
+
+				/*
+				** remove the command from the rup command queue...
+				*/
+				UnixRupP->CmdsWaitingP = CmdBlkP->NextP;
+
+				/*
+				** ...and place it on the pending position.
+				*/
+				UnixRupP->CmdPendingP = CmdBlkP;
+
+				/*
+				** set the command register
+				*/
+				WWORD(UnixRupP->RupP->txcontrol,TX_PACKET_READY);
+
+				/*
+				** the command block will be freed
+				** when the command has been processed.
+				*/
+			}
+		}
+		spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+	} while ( Rup );
+}
+
+int
+RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
+{
+	struct Port *	PortP = (struct Port *)iPortP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+#ifdef CHECK
+	CheckPortP( PortP );
+#endif
+	PortP->WflushFlag++;
+	PortP->MagicFlags |= MAGIC_FLUSH;
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return RIOUnUse( iPortP, CmdBlkP );
+}
+
+int
+RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP)
+{
+	struct Port *	PortP = (struct Port *)iPortP;
+	PKT *PacketP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	while ( can_remove_receive(&PacketP, PortP) ) {
+		remove_receive(PortP);
+		ShowPacket(DBG_PROC, PacketP );
+		put_free_end( PortP->HostP, PacketP );
+	}
+
+	if ( RWORD(PortP->PhbP->handshake)==PHB_HANDSHAKE_SET ) {
+		/*
+		** MAGIC! (Basically, handshake the RX buffer, so that
+		** the RTAs upstream can be re-enabled.)
+		*/
+		rio_dprintk (RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
+		WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET);
+	}
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return RIOUnUse( iPortP, CmdBlkP );
+}
+
+int
+RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
+{
+	struct Port *	PortP = (struct Port *)iPortP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+#ifdef CHECK
+	CheckPortP( PortP );
+#endif
+	rio_dprintk (RIO_DEBUG_CMD, "Decrement in use count for port\n");
+
+	if (PortP->InUse) {
+		if ( --PortP->InUse != NOT_INUSE ) {
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+		}
+	}
+	/*
+	** While PortP->InUse is set (i.e. a preemptive command has been sent to
+	** the RTA and is awaiting completion), any transmit data is prevented from
+	** being transferred from the write queue into the transmit packets
+	** (add_transmit) and no furthur transmit interrupt will be sent for that
+	** data. The next interrupt will occur up to 500ms later (RIOIntr is called
+	** twice a second as a saftey measure). This was the case when kermit was
+	** used to send data into a RIO port. After each packet was sent, TCFLSH
+	** was called to flush the read queue preemptively. PortP->InUse was
+	** incremented, thereby blocking the 6 byte acknowledgement packet
+	** transmitted back. This acknowledgment hung around for 500ms before
+	** being sent, thus reducing input performance substantially!.
+	** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
+	** hanging around in the transmit buffer is sent immediately.
+	*/
+	WWORD(PortP->HostP->ParmMapP->tx_intr, 1);
+	/* What to do here ..
+	wakeup( (caddr_t)&(PortP->InUse) );
+	*/
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return 0;
+}
+
+void
+ShowPacket(uint Flags, struct PKT *PacketP)
+{
+}
+
+/*
+** 
+** How to use this file:
+** 
+** To send a command down a rup, you need to allocate a command block, fill
+** in the packet information, fill in the command number, fill in the pre-
+** and post- functions and arguments, and then add the command block to the
+** queue of command blocks for the port in question. When the port is idle,
+** then the pre-function will be called. If this returns RIO_FAIL then the
+** command will be re-queued and tried again at a later date (probably in one
+** clock tick). If the pre-function returns NOT RIO_FAIL, then the command
+** packet will be queued on the RUP, and the txcontrol field set to the
+** command number. When the txcontrol field has changed from being the
+** command number, then the post-function will be called, with the argument
+** specified earlier, a pointer to the command block, and the value of
+** txcontrol.
+** 
+** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer
+** to the command block structure allocated, or NULL if there aren't any.
+** The block will have been zeroed for you.
+** 
+** The structure has the following fields:
+** 
+** struct CmdBlk
+** {
+**	 struct CmdBlk *NextP;		  ** Pointer to next command block   **
+**	 struct PKT	 Packet;		** A packet, to copy to the rup	**
+**			int	 (*PreFuncP)();  ** The func to call to check if OK **
+**			int	 PreArg;		** The arg for the func			**
+**			int	 (*PostFuncP)(); ** The func to call when completed **
+**			int	 PostArg;	   ** The arg for the func			**
+** };
+** 
+** You need to fill in ALL fields EXCEPT NextP, which is used to link the
+** blocks together either on the free list or on the Rup list.
+** 
+** Packet is an actual packet structure to be filled in with the packet
+** information associated with the command. You need to fill in everything,
+** as the command processore doesn't process the command packet in any way.
+** 
+** The PreFuncP is called before the packet is enqueued on the host rup.
+** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must
+** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL
+** if the packet is NOT to be queued.
+** 
+** The PostFuncP is called when the command has completed. It is called
+** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected
+** to return a value. PostFuncP does NOT need to free the command block,
+** as this happens automatically after PostFuncP returns.
+** 
+** Once the command block has been filled in, it is attached to the correct
+** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is
+** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer
+** to it!), and CmdBlkP is the pointer to the command block allocated using
+** RIOGetCmdBlk().
+** 
+*/
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
new file mode 100644
index 0000000..b4d1a23
--- /dev/null
+++ b/drivers/char/rio/rioctrl.c
@@ -0,0 +1,1869 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioctrl.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:42
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)rioctrl.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c	1.3";
+#endif
+
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+
+
+static struct LpbReq	 LpbReq;
+static struct RupReq	 RupReq;
+static struct PortReq	PortReq;
+static struct HostReq	HostReq;
+static struct HostDpRam HostDpRam;
+static struct DebugCtrl DebugCtrl;
+static struct Map		 MapEnt;
+static struct PortSetup PortSetup;
+static struct DownLoad	DownLoad;
+static struct SendPack  SendPack;
+/* static struct StreamInfo	StreamInfo; */
+/* static char modemtable[RIO_PORTS]; */
+static struct SpecialRupCmd SpecialRupCmd;
+static struct PortParams PortParams;
+static struct portStats portStats;
+
+static struct SubCmdStruct {
+	ushort	Host;
+	ushort	Rup;
+	ushort	Port;
+	ushort	Addr;
+} SubCmd;
+
+struct PortTty {
+	uint		port;
+	struct ttystatics	Tty;
+};
+
+static struct PortTty	PortTty;
+typedef struct ttystatics TERMIO;
+
+/*
+** This table is used when the config.rio downloads bin code to the
+** driver. We index the table using the product code, 0-F, and call
+** the function pointed to by the entry, passing the information
+** about the boot.
+** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
+** process to bog off.
+*/
+static int 
+(*RIOBootTable[MAX_PRODUCT])(struct rio_info *, struct DownLoad *) =
+{
+/* 0 */	RIOBootCodeHOST,	/* Host Card */
+/* 1 */	RIOBootCodeRTA,		/* RTA */
+};
+
+#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
+
+int copyin (int arg, caddr_t dp, int siz)
+{
+  int rv;
+
+  rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *)arg, dp);
+  rv = copy_from_user (dp, (void *)arg, siz);
+  if (rv) return COPYFAIL;
+  else return rv;
+}
+
+static int copyout (caddr_t dp, int arg, int siz)
+{
+  int rv;
+
+  rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *)arg, dp);
+  rv = copy_to_user ((void *)arg, dp, siz);
+  if (rv) return COPYFAIL;
+  else return rv;
+}
+
+int
+riocontrol(p, dev, cmd, arg, su)
+struct rio_info	* p;
+dev_t		dev;
+int		cmd;
+caddr_t		arg;
+int		su;
+{
+	uint	Host;	/* leave me unsigned! */
+	uint	port;	/* and me! */
+	struct Host	*HostP;
+	ushort	loop;
+	int		Entry;
+	struct Port	*PortP;
+	PKT	*PacketP;
+	int		retval = 0;
+	unsigned long flags;
+	
+	func_enter ();
+	
+	/* Confuse the compiler to think that we've initialized these */
+	Host=0;
+	PortP = NULL;
+
+	rio_dprintk (RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int)arg);
+
+	switch (cmd) {
+		/*
+		** RIO_SET_TIMER
+		**
+		** Change the value of the host card interrupt timer.
+		** If the host card number is -1 then all host cards are changed
+		** otherwise just the specified host card will be changed.
+		*/
+		case RIO_SET_TIMER:
+			rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint)arg);
+			{
+				int host, value;
+				host = (uint)arg >> 16;
+				value = (uint)arg & 0x0000ffff;
+				if (host == -1) {
+					for (host = 0; host < p->RIONumHosts; host++) {
+						if (p->RIOHosts[host].Flags == RC_RUNNING) {
+							WWORD(p->RIOHosts[host].ParmMapP->timer , value);
+						}
+					}
+				} else if (host >= p->RIONumHosts) {
+					return -EINVAL;
+				} else {
+					if ( p->RIOHosts[host].Flags == RC_RUNNING ) {
+						WWORD(p->RIOHosts[host].ParmMapP->timer , value);
+					}
+				}
+			}
+			return 0;
+
+		case RIO_IDENTIFY_DRIVER:
+			/*
+			** 15.10.1998 ARG - ESIL 0760 part fix
+			** Added driver ident string output.
+			**
+#ifndef __THIS_RELEASE__
+#warning Driver Version string not defined !
+#endif
+			cprintf("%s %s %s %s\n",
+				RIO_DRV_STR,
+				__THIS_RELEASE__,
+				__DATE__, __TIME__ );
+
+			return 0;
+
+		case RIO_DISPLAY_HOST_CFG:
+			**
+			** 15.10.1998 ARG - ESIL 0760 part fix
+			** Added driver host card ident string output.
+			**
+			** Note that the only types currently supported
+			** are ISA and PCI. Also this driver does not
+			** (yet) distinguish between the Old PCI card
+			** and the Jet PCI card. In fact I think this
+			** driver only supports JET PCI !
+			**
+
+			for (Host = 0; Host < p->RIONumHosts; Host++)
+			{
+				HostP = &(p->RIOHosts[Host]);
+
+				switch ( HostP->Type )
+				{
+				    case RIO_AT :
+					strcpy( host_type, RIO_AT_HOST_STR );
+					break;
+
+				    case RIO_PCI :
+					strcpy( host_type, RIO_PCI_HOST_STR );
+					break;
+
+				    default :
+					strcpy( host_type, "Unknown" );
+					break;
+				}
+
+				cprintf(
+				  "RIO Host %d - Type:%s Addr:%X IRQ:%d\n",
+					Host, host_type,
+					(uint)HostP->PaddrP,
+					(int)HostP->Ivec - 32  );
+			}
+			return 0;
+			**
+			*/
+
+		case RIO_FOAD_RTA:
+			rio_dprintk (RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
+			return RIOCommandRta(p, (uint)arg, RIOFoadRta);
+
+		case RIO_ZOMBIE_RTA:
+			rio_dprintk (RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
+			return RIOCommandRta(p, (uint)arg, RIOZombieRta);
+
+		case RIO_IDENTIFY_RTA:
+			rio_dprintk (RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
+			return RIOIdentifyRta(p, arg);
+
+		case RIO_KILL_NEIGHBOUR:
+			rio_dprintk (RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
+			return RIOKillNeighbour(p, arg);
+
+		case SPECIAL_RUP_CMD:
+			{
+				struct CmdBlk *CmdBlkP;
+
+				rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
+				if (copyin((int)arg, (caddr_t)&SpecialRupCmd, 
+							sizeof(SpecialRupCmd)) == COPYFAIL ) {
+					rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
+					p->RIOError.Error = COPYIN_FAILED;
+		 			return -EFAULT;
+				}
+				CmdBlkP = RIOGetCmdBlk();
+				if ( !CmdBlkP ) {
+					rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
+					return -ENXIO;
+				}
+				CmdBlkP->Packet = SpecialRupCmd.Packet;
+				if ( SpecialRupCmd.Host >= p->RIONumHosts )
+					SpecialRupCmd.Host = 0;
+					rio_dprintk (RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n",
+						SpecialRupCmd.Host, SpecialRupCmd.RupNum);
+					if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], 
+							SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
+						cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n");
+					}
+					return 0;
+				}
+
+			case RIO_DEBUG_MEM:
+#ifdef DEBUG_MEM_SUPPORT
+RIO_DEBUG_CTRL, 				if (su)
+					return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg);
+				else
+#endif
+					return -EPERM;
+
+			case RIO_ALL_MODEM:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
+				p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+				return -EINVAL;
+
+			case RIO_GET_TABLE:
+				/*
+				** Read the routing table from the device driver to user space
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
+
+				if ((retval = RIOApel(p)) != 0)
+		 			return retval;
+
+				if (copyout((caddr_t)p->RIOConnectTable, (int)arg,
+						TOTAL_MAP_ENTRIES*sizeof(struct Map)) == COPYFAIL) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
+		 			p->RIOError.Error = COPYOUT_FAILED;
+		 			return -EFAULT;
+				}
+
+				{
+					int entry;
+					rio_dprintk (RIO_DEBUG_CTRL,  "*****\nMAP ENTRIES\n");
+					for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
+					{
+					  if ((p->RIOConnectTable[entry].ID == 0) &&
+					      (p->RIOConnectTable[entry].HostUniqueNum == 0) &&
+					      (p->RIOConnectTable[entry].RtaUniqueNum == 0)) continue;
+					      
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int)p->RIOConnectTable[entry].Flags );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int)p->RIOConnectTable[entry].SysPort );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link );
+						rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name );
+					}
+					rio_dprintk (RIO_DEBUG_CTRL,  "*****\nEND MAP ENTRIES\n");
+				}
+				p->RIOQuickCheck = NOT_CHANGED;	/* a table has been gotten */
+				return 0;
+
+			case RIO_PUT_TABLE:
+				/*
+				** Write the routing table to the device driver from user space
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
+
+				if ( !su ) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
+		 			p->RIOError.Error = NOT_SUPER_USER;
+		 			return -EPERM;
+				}
+				if ( copyin((int)arg, (caddr_t)&p->RIOConnectTable[0], 
+					TOTAL_MAP_ENTRIES*sizeof(struct Map) ) == COPYFAIL ) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
+		 			p->RIOError.Error = COPYIN_FAILED;
+		 			return -EFAULT;
+				}
+/*
+***********************************
+				{
+					int entry;
+					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nMAP ENTRIES\n") );
+					for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
+					{
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) );
+					}
+					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nEND MAP ENTRIES\n") );
+				}
+***********************************
+*/
+				return RIONewTable(p);
+
+	 		case RIO_GET_BINDINGS :
+				/*
+				** Send bindings table, containing unique numbers of RTAs owned
+				** by this system to user space
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
+
+				if ( !su )
+				{
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
+		 			p->RIOError.Error = NOT_SUPER_USER;
+		 			return -EPERM;
+				}
+				if (copyout((caddr_t) p->RIOBindTab, (int)arg, 
+						(sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL ) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
+		 			p->RIOError.Error = COPYOUT_FAILED;
+		 			return -EFAULT;
+				}
+				return 0;
+
+	 		case RIO_PUT_BINDINGS :
+			/*
+			** Receive a bindings table, containing unique numbers of RTAs owned
+			** by this system
+			*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
+
+				if ( !su )
+				{
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
+		 			p->RIOError.Error = NOT_SUPER_USER;
+		 			return -EPERM;
+				}
+				if (copyin((int)arg, (caddr_t)&p->RIOBindTab[0], 
+						(sizeof(ulong) * MAX_RTA_BINDINGS))==COPYFAIL ) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
+		 			p->RIOError.Error = COPYIN_FAILED;
+		 			return -EFAULT;
+				}
+				return 0;
+
+			case RIO_BIND_RTA :
+				{
+					int	EmptySlot = -1;
+					/*
+					** Bind this RTA to host, so that it will be booted by 
+					** host in 'boot owned RTAs' mode.
+					*/
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
+
+					if ( !su ) {
+		 				rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
+		 				p->RIOError.Error = NOT_SUPER_USER;
+		 				return -EPERM;
+					}
+					for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
+		 				if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
+							EmptySlot = Entry;
+		 				else if (p->RIOBindTab[Entry] == (int) arg) {
+							/*
+							** Already exists - delete
+							*/
+							p->RIOBindTab[Entry] = 0L;
+							rio_dprintk (RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n",
+		 												(int) arg);
+							return 0;
+		 				}
+					}
+					/*
+					** Dosen't exist - add
+					*/
+					if (EmptySlot != -1) {
+		 				p->RIOBindTab[EmptySlot] = (int) arg;
+		 				rio_dprintk (RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n",
+		  					(int) arg);
+					}
+					else {
+		 				rio_dprintk (RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n",
+		  					(int) arg);
+		 				return -ENOMEM;
+					}
+					return 0;
+				}
+
+			case RIO_RESUME :
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME\n");
+				port = (uint) arg;
+				if ((port < 0) || (port > 511)) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
+		 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+		 			return -EINVAL;
+				}
+				PortP = p->RIOPortp[port];
+				if (!PortP->Mapped) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
+		 			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+		 			return -EINVAL;
+				}
+				if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
+		 			return -EINVAL;
+				}
+
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == 
+										RIO_FAIL) {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
+					rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+					return -EBUSY;
+				}
+				else {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
+					PortP->State |= RIO_BUSY;
+				}
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				return retval;
+
+			case RIO_ASSIGN_RTA:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
+				if ( !su ) {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
+					p->RIOError.Error = NOT_SUPER_USER;
+					return -EPERM;
+				}
+				if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
+									== COPYFAIL) {
+					rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n");
+					p->RIOError.Error = COPYIN_FAILED;
+					return -EFAULT;
+				}
+				return RIOAssignRta(p, &MapEnt);
+
+			case RIO_CHANGE_NAME:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
+				if ( !su ) {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
+					p->RIOError.Error = NOT_SUPER_USER;
+					return -EPERM;
+				}
+				if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
+						== COPYFAIL) {
+					rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n");
+					p->RIOError.Error = COPYIN_FAILED;
+					return -EFAULT;
+				}
+				return RIOChangeName(p, &MapEnt);
+
+			case RIO_DELETE_RTA:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
+				if ( !su ) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
+		 			p->RIOError.Error = NOT_SUPER_USER;
+		 			return -EPERM;
+				}
+				if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
+							== COPYFAIL ) {
+		 			rio_dprintk (RIO_DEBUG_CTRL, "Copy from data space failed\n");
+		 			p->RIOError.Error = COPYIN_FAILED;
+		 			return -EFAULT;
+				}
+				return RIODeleteRta(p, &MapEnt);
+
+			case RIO_QUICK_CHECK:
+				/*
+				** 09.12.1998 ARG - ESIL 0776 part fix
+				** A customer was using this to get the RTAs
+				** connect/disconnect status.
+				** RIOConCon() had been botched use RIOHalted
+				** to keep track of RTA connections and
+				** disconnections. That has been changed and
+				** RIORtaDisCons in the rio_info struct now
+				** does the job. So we need to return the value
+				** of RIORtaCons instead of RIOHalted.
+				**
+				if (copyout((caddr_t)&p->RIOHalted,(int)arg,
+							sizeof(uint))==COPYFAIL) {
+				**
+				*/
+
+				if (copyout((caddr_t)&p->RIORtaDisCons,(int)arg,
+							sizeof(uint))==COPYFAIL) {
+					p->RIOError.Error = COPYOUT_FAILED;
+					return -EFAULT;
+				}
+				return 0;
+
+			case RIO_LAST_ERROR:
+				if (copyout((caddr_t)&p->RIOError, (int)arg, 
+						sizeof(struct Error)) ==COPYFAIL )
+					return -EFAULT;
+				return 0;
+
+			case RIO_GET_LOG:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
+#ifdef LOGGING
+				RIOGetLog(arg);
+				return 0;
+#else
+				return -EINVAL;
+#endif
+
+			case RIO_GET_MODTYPE:
+				if ( copyin( (int)arg, (caddr_t)&port, 
+									sizeof(uint)) == COPYFAIL )
+				{
+		 			p->RIOError.Error = COPYIN_FAILED;
+		 			return -EFAULT;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
+				if ( port < 0 || port > 511 )
+				{
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
+		 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+		 			return -EINVAL;
+				}
+				PortP = (p->RIOPortp[port]);
+				if (!PortP->Mapped)
+				{
+		 			rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
+		 			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+		 			return -EINVAL;
+				}
+				/*
+				** Return module type of port
+				*/
+				port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
+				if (copyout((caddr_t)&port, (int)arg, 
+							sizeof(uint)) == COPYFAIL) {
+		 			p->RIOError.Error = COPYOUT_FAILED;
+		 			return -EFAULT;
+				}
+				return(0);
+			/*
+			** 02.03.1999 ARG - ESIL 0820 fix
+			** We are no longer using "Boot Mode", so these ioctls
+			** are not required :
+			**
+	 		case RIO_GET_BOOT_MODE :
+				rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode));
+				**
+				** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE
+				**
+				if (copyout((caddr_t)&p->RIOBootMode, (int)arg, 
+						sizeof(p->RIOBootMode)) == COPYFAIL) {
+		 			p->RIOError.Error = COPYOUT_FAILED;
+		 			return -EFAULT;
+				}
+				return(0);
+			
+ 			case RIO_SET_BOOT_MODE :
+				p->RIOBootMode = (uint) arg;
+				rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode));
+				return(0);
+			**
+			** End ESIL 0820 fix
+			*/
+
+	 		case RIO_BLOCK_OPENS:
+				rio_dprintk (RIO_DEBUG_CTRL, "Opens block until booted\n");
+				for ( Entry=0; Entry < RIO_PORTS; Entry++ ) {
+		 			rio_spin_lock_irqsave(&PortP->portSem, flags);
+		 			p->RIOPortp[Entry]->WaitUntilBooted = 1;
+		 			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				}
+				return 0;
+			
+	 		case RIO_SETUP_PORTS:
+				rio_dprintk (RIO_DEBUG_CTRL, "Setup ports\n");
+				if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) 
+						== COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 rio_dprintk (RIO_DEBUG_CTRL, "EFAULT");
+					 return -EFAULT;
+				}
+				if ( PortSetup.From > PortSetup.To || 
+								PortSetup.To >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 rio_dprintk (RIO_DEBUG_CTRL, "ENXIO");
+					 return -ENXIO;
+				}
+				if ( PortSetup.XpCps > p->RIOConf.MaxXpCps ||
+					 PortSetup.XpCps < p->RIOConf.MinXpCps ) {
+					 p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
+					 rio_dprintk (RIO_DEBUG_CTRL, "EINVAL");
+					 return -EINVAL;
+				}
+				if ( !p->RIOPortp ) {
+					 cprintf("No p->RIOPortp array!\n");
+					 rio_dprintk (RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
+					 return -EIO;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
+				for (loop=PortSetup.From; loop<=PortSetup.To; loop++) {
+				rio_dprintk (RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
+#if 0
+					PortP = p->RIOPortp[loop];
+					if ( !PortP->TtyP )
+						PortP->TtyP = &p->channel[loop];
+
+		 				rio_spin_lock_irqsave(&PortP->portSem, flags);
+						if ( PortSetup.IxAny )
+							PortP->Config |= RIO_IXANY;
+						else
+							PortP->Config &= ~RIO_IXANY;
+						if ( PortSetup.IxOn )
+							PortP->Config |= RIO_IXON;
+						else
+							PortP->Config &= ~RIO_IXON;
+					 
+					 /*
+					 ** If the port needs to wait for all a processes output
+					 ** to drain before closing then this flag will be set.
+					 */
+					 	if (PortSetup.Drain) {
+							PortP->Config |= RIO_WAITDRAIN;
+					 	} else {
+							PortP->Config &= ~RIO_WAITDRAIN;
+					 	}
+					 /*
+					 ** Store settings if locking or unlocking port or if the
+					 ** port is not locked, when setting the store option.
+					 */
+					 if (PortP->Mapped &&
+						 ((PortSetup.Lock && !PortP->Lock) ||
+							(!PortP->Lock &&
+							(PortSetup.Store && !PortP->Store)))) {
+						PortP->StoredTty.iflag = PortP->TtyP->tm.c_iflag;
+						PortP->StoredTty.oflag = PortP->TtyP->tm.c_oflag;
+						PortP->StoredTty.cflag = PortP->TtyP->tm.c_cflag;
+						PortP->StoredTty.lflag = PortP->TtyP->tm.c_lflag;
+						PortP->StoredTty.line = PortP->TtyP->tm.c_line;
+						bcopy(PortP->TtyP->tm.c_cc, PortP->StoredTty.cc,
+					 		NCC + 5);
+					 }
+					 PortP->Lock = PortSetup.Lock;
+					 PortP->Store = PortSetup.Store;
+					 PortP->Xprint.XpCps = PortSetup.XpCps;
+					 bcopy(PortSetup.XpOn,PortP->Xprint.XpOn,MAX_XP_CTRL_LEN);
+					 bcopy(PortSetup.XpOff,PortP->Xprint.XpOff,MAX_XP_CTRL_LEN);
+					 PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
+					 PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
+					 PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+
+								RIOStrlen(PortP->Xprint.XpOff);
+					 rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+#endif
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
+				rio_dprintk (RIO_DEBUG_CTRL, "Retval:%x\n", retval);
+				return retval;
+
+			case RIO_GET_PORT_SETUP :
+				rio_dprintk (RIO_DEBUG_CTRL, "Get port setup\n");
+				if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) 
+							== COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if ( PortSetup.From >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+
+				port = PortSetup.To = PortSetup.From;
+				PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 
+													1 : 0;
+				PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 
+													1 : 0;
+				PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ?
+												 	1 : 0;
+				PortSetup.Store = p->RIOPortp[port]->Store;
+				PortSetup.Lock = p->RIOPortp[port]->Lock;
+				PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
+				bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn,
+													MAX_XP_CTRL_LEN);
+				bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff,
+													MAX_XP_CTRL_LEN);
+				PortSetup.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
+				PortSetup.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
+
+				if ( copyout((caddr_t)&PortSetup,(int)arg,sizeof(PortSetup))
+														==COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return retval;
+
+			case RIO_GET_PORT_PARAMS :
+				rio_dprintk (RIO_DEBUG_CTRL, "Get port params\n");
+				if (copyin( (int)arg, (caddr_t)&PortParams,
+					sizeof(struct PortParams)) == COPYFAIL) {
+					p->RIOError.Error = COPYIN_FAILED;
+					return -EFAULT;
+				}
+				if (PortParams.Port >= RIO_PORTS) {
+					p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					return -ENXIO;
+				}
+				PortP = (p->RIOPortp[PortParams.Port]);
+				PortParams.Config = PortP->Config;
+				PortParams.State = PortP->State;
+				rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
+
+				if (copyout((caddr_t)&PortParams, (int)arg, 
+						sizeof(struct PortParams)) == COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return retval;
+
+			case RIO_GET_PORT_TTY :
+				rio_dprintk (RIO_DEBUG_CTRL, "Get port tty\n");
+				if (copyin((int)arg, (caddr_t)&PortTty, sizeof(struct PortTty)) 
+						== COPYFAIL) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if ( PortTty.port >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+
+				rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
+				PortP = (p->RIOPortp[PortTty.port]);
+#if 0
+				PortTty.Tty.tm.c_iflag = PortP->TtyP->tm.c_iflag;
+				PortTty.Tty.tm.c_oflag = PortP->TtyP->tm.c_oflag;
+				PortTty.Tty.tm.c_cflag = PortP->TtyP->tm.c_cflag;
+				PortTty.Tty.tm.c_lflag = PortP->TtyP->tm.c_lflag;
+#endif
+				if (copyout((caddr_t)&PortTty, (int)arg, 
+							sizeof(struct PortTty)) == COPYFAIL) {
+					p->RIOError.Error = COPYOUT_FAILED;
+					return -EFAULT;
+				}
+				return retval;
+
+			case RIO_SET_PORT_TTY :
+				if (copyin((int)arg, (caddr_t)&PortTty, 
+						sizeof(struct PortTty)) == COPYFAIL) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
+				if (PortTty.port >= (ushort) RIO_PORTS) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+				PortP = (p->RIOPortp[PortTty.port]);
+#if 0
+		 		rio_spin_lock_irqsave(&PortP->portSem, flags);
+				PortP->TtyP->tm.c_iflag = PortTty.Tty.tm.c_iflag;
+				PortP->TtyP->tm.c_oflag = PortTty.Tty.tm.c_oflag;
+				PortP->TtyP->tm.c_cflag = PortTty.Tty.tm.c_cflag;
+				PortP->TtyP->tm.c_lflag = PortTty.Tty.tm.c_lflag;
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+#endif
+
+				RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
+				return retval;
+
+			case RIO_SET_PORT_PARAMS :
+				rio_dprintk (RIO_DEBUG_CTRL, "Set port params\n");
+				if ( copyin((int)arg, (caddr_t)&PortParams, sizeof(PortParams))
+					== COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if (PortParams.Port >= (ushort) RIO_PORTS) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+				PortP = (p->RIOPortp[PortParams.Port]);
+		 		rio_spin_lock_irqsave(&PortP->portSem, flags);
+				PortP->Config = PortParams.Config;
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+			case RIO_GET_PORT_STATS :
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
+				if ( copyin((int)arg, (caddr_t)&portStats, 
+						sizeof(struct portStats)) == COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if ( portStats.port >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+				PortP = (p->RIOPortp[portStats.port]);
+				portStats.gather = PortP->statsGather;
+				portStats.txchars = PortP->txchars;
+				portStats.rxchars = PortP->rxchars;
+				portStats.opens = PortP->opens;
+				portStats.closes = PortP->closes;
+				portStats.ioctls = PortP->ioctls;
+				if ( copyout((caddr_t)&portStats, (int)arg, 
+							sizeof(struct portStats)) == COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return retval;
+
+			case RIO_RESET_PORT_STATS :
+				port = (uint) arg;
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
+				if ( port >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+				PortP = (p->RIOPortp[port]);
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				PortP->txchars	= 0;
+				PortP->rxchars	= 0;
+				PortP->opens	= 0;
+				PortP->closes	= 0;
+				PortP->ioctls	= 0;
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				return retval;
+
+			case RIO_GATHER_PORT_STATS :
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
+				if ( copyin( (int)arg, (caddr_t)&portStats, 
+						sizeof(struct portStats)) == COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if ( portStats.port >= RIO_PORTS ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+				PortP = (p->RIOPortp[portStats.port]);
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				PortP->statsGather = portStats.gather;
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+#ifdef DEBUG_SUPPORTED
+			case RIO_READ_LEVELS:
+				{
+					 int num;
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_LEVELS\n");
+					 for ( num=0; RIODbInf[num].Flag; num++ ) ;
+					 rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copy\n",num);
+					 if (copyout((caddr_t)RIODbInf,(int)arg,
+						sizeof(struct DbInf)*(num+1))==COPYFAIL) {
+						rio_dprintk (RIO_DEBUG_CTRL, "ReadLevels Copy failed\n");
+						p->RIOError.Error = COPYOUT_FAILED;
+						return -EFAULT;
+					 }
+					 rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copied\n",num);
+					 return retval;
+				}
+#endif
+
+			 case RIO_READ_CONFIG:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
+				if (copyout((caddr_t)&p->RIOConf, (int)arg, 
+							sizeof(struct Conf)) ==COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return retval;
+
+			case RIO_SET_CONFIG:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
+				if ( !su ) {
+					 p->RIOError.Error = NOT_SUPER_USER;
+					 return -EPERM;
+				}
+				if ( copyin((int)arg, (caddr_t)&p->RIOConf, sizeof(struct Conf) )
+						==COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				/*
+				** move a few value around
+				*/
+				for (Host=0; Host < p->RIONumHosts; Host++)
+					 if ( (p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING )
+					 	WWORD(p->RIOHosts[Host].ParmMapP->timer , 
+								p->RIOConf.Timer);
+				return retval;
+
+			case RIO_START_POLLER:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
+				return -EINVAL;
+
+			case RIO_STOP_POLLER:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
+				if ( !su ) {
+					 p->RIOError.Error = NOT_SUPER_USER;
+					 return -EPERM;
+				}
+				p->RIOPolling = NOT_POLLING;
+				return retval;
+
+			case RIO_SETDEBUG:
+			case RIO_GETDEBUG:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
+				if ( copyin( (int)arg, (caddr_t)&DebugCtrl, sizeof(DebugCtrl) )
+							==COPYFAIL ) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if ( DebugCtrl.SysPort == NO_PORT ) {
+					if ( cmd == RIO_SETDEBUG ) {
+						if ( !su ) {
+							p->RIOError.Error = NOT_SUPER_USER;
+							return -EPERM;
+						}
+						p->rio_debug = DebugCtrl.Debug;
+						p->RIODebugWait = DebugCtrl.Wait;
+						rio_dprintk (RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n",
+							p->rio_debug,p->RIODebugWait);
+					}
+				 	else {
+						rio_dprintk (RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n",
+										p->rio_debug,p->RIODebugWait);
+						DebugCtrl.Debug = p->rio_debug;
+						DebugCtrl.Wait  = p->RIODebugWait;
+						if ( copyout((caddr_t)&DebugCtrl,(int)arg,
+								sizeof(DebugCtrl)) == COPYFAIL ) {
+							rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n",
+									DebugCtrl.SysPort);
+						 	p->RIOError.Error = COPYOUT_FAILED;
+						 	return -EFAULT;
+						}
+					}
+				}
+				else if ( DebugCtrl.SysPort >= RIO_PORTS && 
+							DebugCtrl.SysPort != NO_PORT ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n",
+									DebugCtrl.SysPort);
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+				else if ( cmd == RIO_SETDEBUG ) {
+					if ( !su ) {
+						p->RIOError.Error = NOT_SUPER_USER;
+						return -EPERM;
+					}
+					rio_spin_lock_irqsave(&PortP->portSem, flags);
+					p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
+					rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n",
+								p->RIOPortp[DebugCtrl.SysPort]->Debug);
+				}
+				else {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n",
+									 p->RIOPortp[DebugCtrl.SysPort]->Debug);
+					DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
+					if ( copyout((caddr_t)&DebugCtrl,(int)arg,
+								sizeof(DebugCtrl))==COPYFAIL ) {
+						rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
+						p->RIOError.Error = COPYOUT_FAILED;
+						return -EFAULT;
+					}
+				}
+				return retval;
+
+			case RIO_VERSID:
+				/*
+				** Enquire about the release and version.
+				** We return MAX_VERSION_LEN bytes, being a
+				** textual null terminated string.
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID\n");
+				if ( copyout(	(caddr_t)RIOVersid(),
+						(int)arg,
+						sizeof(struct rioVersion) ) == COPYFAIL )
+				{
+					 rio_dprintk (RIO_DEBUG_CTRL,  "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return retval;
+
+			/*
+			** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			** !! commented out previous 'RIO_VERSID' functionality !!
+			** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			**
+			case RIO_VERSID:
+				**
+				** Enquire about the release and version.
+				** We return MAX_VERSION_LEN bytes, being a textual null
+				** terminated string.
+				**
+				rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n"));
+				if (copyout((caddr_t)RIOVersid(), 
+						(int)arg, MAX_VERSION_LEN ) == COPYFAIL ) {
+					 rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host));
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return retval;
+			**
+			** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			*/
+
+			case RIO_NUM_HOSTS:
+				/*
+				** Enquire as to the number of hosts located
+				** at init time.
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
+				if (copyout((caddr_t)&p->RIONumHosts, (int)arg, 
+							sizeof(p->RIONumHosts) )==COPYFAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return retval;
+
+			case RIO_HOST_FOAD:
+				/*
+				** Kill host. This may not be in the final version...
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int)arg);
+				if ( !su ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
+					 p->RIOError.Error = NOT_SUPER_USER;
+					 return -EPERM;
+				}
+				p->RIOHalted = 1;
+				p->RIOSystemUp = 0;
+
+				for ( Host=0; Host<p->RIONumHosts; Host++ ) {
+					 (void)RIOBoardTest( p->RIOHosts[Host].PaddrP, 
+						p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, 
+								p->RIOHosts[Host].Slot );
+					 bzero( (caddr_t)&p->RIOHosts[Host].Flags, 
+							((int)&p->RIOHosts[Host].____end_marker____) -
+								 ((int)&p->RIOHosts[Host].Flags) );
+					 p->RIOHosts[Host].Flags  = RC_WAITING;
+#if 0
+					 RIOSetupDataStructs(p);
+#endif
+				}
+				RIOFoadWakeup(p);
+				p->RIONumBootPkts = 0;
+				p->RIOBooting = 0;
+
+#ifdef RINGBUFFER_SUPPORT
+				for( loop=0; loop<RIO_PORTS; loop++ )
+					if ( p->RIOPortp[loop]->TxRingBuffer )
+						sysfree((void *)p->RIOPortp[loop]->TxRingBuffer, 
+							RIOBufferSize );
+#endif
+#if 0
+				bzero((caddr_t)&p->RIOPortp[0],RIO_PORTS*sizeof(struct Port));
+#else
+				printk ("HEEEEELP!\n");
+#endif
+
+				for( loop=0; loop<RIO_PORTS; loop++ ) {
+#if 0
+					p->RIOPortp[loop]->TtyP = &p->channel[loop];
+#endif
+					
+					spin_lock_init(&p->RIOPortp[loop]->portSem);
+					p->RIOPortp[loop]->InUse = NOT_INUSE;
+				}
+
+				p->RIOSystemUp = 0;
+				return retval;
+
+			case RIO_DOWNLOAD:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
+				if ( !su ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
+					 p->RIOError.Error = NOT_SUPER_USER;
+					 return -EPERM;
+				}
+				if ( copyin((int)arg, (caddr_t)&DownLoad, 
+							sizeof(DownLoad) )==COPYFAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n",
+				    DownLoad.ProductCode);
+
+				/*
+				** It is important that the product code is an unsigned object!
+				*/
+				if ( DownLoad.ProductCode > MAX_PRODUCT ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n",
+							DownLoad.ProductCode);
+					 p->RIOError.Error = NO_SUCH_PRODUCT;
+					 return -ENXIO;
+				}
+				/*
+				** do something!
+				*/
+				retval = (*(RIOBootTable[DownLoad.ProductCode]))(p, &DownLoad);
+										/* <-- Panic */
+				p->RIOHalted = 0;
+				/*
+				** and go back, content with a job well completed.
+				*/
+				return retval;
+
+			case RIO_PARMS:
+				{
+					uint host;
+
+					if (copyin((int)arg, (caddr_t)&host, 
+							sizeof(host) ) == COPYFAIL ) {
+						rio_dprintk (RIO_DEBUG_CTRL, 
+							"RIO_HOST_REQ: Copy in from user space failed\n");
+						p->RIOError.Error = COPYIN_FAILED;
+						return -EFAULT;
+					}
+					/*
+					** Fetch the parmmap
+					*/
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS\n");
+					if ( copyout( (caddr_t)p->RIOHosts[host].ParmMapP, 
+								(int)arg, sizeof(PARM_MAP) )==COPYFAIL ) {
+						p->RIOError.Error = COPYOUT_FAILED;
+						rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
+						return -EFAULT;
+					}
+				}
+				return retval;
+
+			case RIO_HOST_REQ:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
+				if (copyin((int)arg, (caddr_t)&HostReq, 
+							sizeof(HostReq) )==COPYFAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if ( HostReq.HostNum >= p->RIONumHosts ) {
+					 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n",
+							HostReq.HostNum);
+					 return -ENXIO;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
+
+				if (copyout((caddr_t)&p->RIOHosts[HostReq.HostNum], 
+					(int)HostReq.HostP,sizeof(struct Host) ) == COPYFAIL) {
+					p->RIOError.Error = COPYOUT_FAILED;
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
+					return -EFAULT;
+				}
+				return retval;
+
+			 case RIO_HOST_DPRAM:
+				rio_dprintk (RIO_DEBUG_CTRL, "Request for DPRAM\n");
+				if ( copyin( (int)arg, (caddr_t)&HostDpRam, 
+								sizeof(HostDpRam) )==COPYFAIL ) {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
+					p->RIOError.Error = COPYIN_FAILED;
+					return -EFAULT;
+				}
+				if ( HostDpRam.HostNum >= p->RIONumHosts ) {
+					p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n",
+										HostDpRam.HostNum);
+					return -ENXIO;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
+
+				if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
+					 int off;
+					 /* It's hardware like this that really gets on my tits. */
+					 static unsigned char copy[sizeof(struct DpRam)];
+					for ( off=0; off<sizeof(struct DpRam); off++ )
+						copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off];
+					if ( copyout( (caddr_t)copy, (int)HostDpRam.DpRamP, 
+							sizeof(struct DpRam) ) == COPYFAIL ) {
+						p->RIOError.Error = COPYOUT_FAILED;
+						rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
+						return -EFAULT;
+					}
+				}
+				else if (copyout((caddr_t)p->RIOHosts[HostDpRam.HostNum].Caddr,
+					(int)HostDpRam.DpRamP, 
+						sizeof(struct DpRam) ) == COPYFAIL ) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
+					 return -EFAULT;
+				}
+				return retval;
+
+			 case RIO_SET_BUSY:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
+				if ( (int)arg < 0 || (int)arg > 511 ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %d\n",(int)arg);
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				p->RIOPortp[(int)arg]->State |= RIO_BUSY;
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+			 case RIO_HOST_PORT:
+				/*
+				** The daemon want port information
+				** (probably for debug reasons)
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
+				if ( copyin((int)arg, (caddr_t)&PortReq, 
+					sizeof(PortReq) )==COPYFAIL ) {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
+					p->RIOError.Error = COPYIN_FAILED;
+					return -EFAULT;
+				}
+
+				if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n",
+											PortReq.SysPort);
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
+				if (copyout((caddr_t)p->RIOPortp[PortReq.SysPort], 
+							 (int)PortReq.PortP,
+								sizeof(struct Port) ) == COPYFAIL) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
+					 return -EFAULT;
+				}
+				return retval;
+
+			case RIO_HOST_RUP:
+				/*
+				** The daemon want rup information
+				** (probably for debug reasons)
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
+				if (copyin((int)arg, (caddr_t)&RupReq, 
+						sizeof(RupReq) )==COPYFAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n",
+								RupReq.HostNum);
+					 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+				if ( RupReq.RupNum >= MAX_RUP+LINKS_PER_UNIT ) { /* eek! */
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n",
+							RupReq.RupNum);
+					 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+				HostP = &p->RIOHosts[RupReq.HostNum];
+
+				if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n",
+							RupReq.HostNum);
+					 p->RIOError.Error = HOST_NOT_RUNNING;
+					 return -EIO;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Request for rup %d from host %d\n",
+						RupReq.RupNum,RupReq.HostNum);
+
+				if (copyout((caddr_t)HostP->UnixRups[RupReq.RupNum].RupP,
+					(int)RupReq.RupP,sizeof(struct RUP) ) == COPYFAIL) {
+					p->RIOError.Error = COPYOUT_FAILED;
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
+					return -EFAULT;
+				}
+				return retval;
+
+			case RIO_HOST_LPB:
+				/*
+				** The daemon want lpb information
+				** (probably for debug reasons)
+				*/
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
+				if (copyin((int)arg, (caddr_t)&LpbReq, 
+					sizeof(LpbReq) )==COPYFAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n",
+							LpbReq.Host);
+					p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					return -ENXIO;
+				}
+				if ( LpbReq.Link >= LINKS_PER_UNIT ) { /* eek! */
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n",
+							LpbReq.Link);
+					 p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+				HostP = &p->RIOHosts[LpbReq.Host];
+
+				if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n",
+						LpbReq.Host );
+					 p->RIOError.Error = HOST_NOT_RUNNING;
+					 return -EIO;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n",
+					LpbReq.Link, LpbReq.Host);
+
+				if (copyout((caddr_t)&HostP->LinkStrP[LpbReq.Link],
+					(int)LpbReq.LpbP,sizeof(struct LPB) ) == COPYFAIL) {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
+					p->RIOError.Error = COPYOUT_FAILED;
+					return -EFAULT;
+				}
+				return retval;
+
+				/*
+				** Here 3 IOCTL's that allow us to change the way in which
+				** rio logs errors. send them just to syslog or send them
+				** to both syslog and console or send them to just the console.
+				**
+				** See RioStrBuf() in util.c for the other half.
+				*/
+			case RIO_SYSLOG_ONLY:
+				p->RIOPrintLogState = PRINT_TO_LOG;	/* Just syslog */
+				return 0;
+
+			case RIO_SYSLOG_CONS:
+				p->RIOPrintLogState = PRINT_TO_LOG_CONS;/* syslog and console */
+				return 0;
+
+			case RIO_CONS_ONLY:
+				p->RIOPrintLogState = PRINT_TO_CONS;	/* Just console */
+				return 0;
+
+			case RIO_SIGNALS_ON:
+				if ( p->RIOSignalProcess ) {
+					 p->RIOError.Error = SIGNALS_ALREADY_SET;
+					 return -EBUSY;
+				}
+				p->RIOSignalProcess = getpid();
+				p->RIOPrintDisabled = DONT_PRINT;
+				return retval;
+
+			case RIO_SIGNALS_OFF:
+				if ( p->RIOSignalProcess != getpid() ) {
+					 p->RIOError.Error = NOT_RECEIVING_PROCESS;
+					 return -EPERM;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "Clear signal process to zero\n");
+				p->RIOSignalProcess = 0;
+				return retval;
+
+			case RIO_SET_BYTE_MODE:
+				for ( Host=0; Host<p->RIONumHosts; Host++ )
+					 if ( p->RIOHosts[Host].Type == RIO_AT )
+						 p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
+				return retval;
+
+			case RIO_SET_WORD_MODE:
+				for ( Host=0; Host<p->RIONumHosts; Host++ )
+					 if ( p->RIOHosts[Host].Type == RIO_AT )
+						 p->RIOHosts[Host].Mode |= WORD_OPERATION;
+				return retval;
+
+			case RIO_SET_FAST_BUS:
+				for ( Host=0; Host<p->RIONumHosts; Host++ )
+					 if ( p->RIOHosts[Host].Type == RIO_AT )
+						 p->RIOHosts[Host].Mode |= FAST_AT_BUS;
+				return retval;
+
+			case RIO_SET_SLOW_BUS:
+				for ( Host=0; Host<p->RIONumHosts; Host++ )
+					 if ( p->RIOHosts[Host].Type == RIO_AT )
+						 p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
+				return retval;
+
+			case RIO_MAP_B50_TO_50:
+			case RIO_MAP_B50_TO_57600:
+			case RIO_MAP_B110_TO_110:
+			case RIO_MAP_B110_TO_115200:
+				rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping\n");
+				port = (uint) arg;
+				if ( port < 0 || port > 511 ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				switch( cmd )
+				{
+					case RIO_MAP_B50_TO_50 :
+						p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
+						break;
+					case RIO_MAP_B50_TO_57600 :
+						p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
+						break;
+					case RIO_MAP_B110_TO_110 :
+						p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
+						break;
+					case RIO_MAP_B110_TO_115200 :
+						p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
+						break;
+				}
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+			case RIO_STREAM_INFO:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
+				return -EINVAL;
+
+			case RIO_SEND_PACKET:
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
+				if ( copyin( (int)arg, (caddr_t)&SendPack,
+									sizeof(SendPack) )==COPYFAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				if ( SendPack.PortNum >= 128 ) {
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -ENXIO;
+				}
+
+				PortP = p->RIOPortp[SendPack.PortNum];
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				if ( !can_add_transmit(&PacketP,PortP) ) {
+					 p->RIOError.Error = UNIT_IS_IN_USE;
+					 rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+					 return -ENOSPC;
+				}
+
+				for ( loop=0; loop<(ushort)(SendPack.Len & 127); loop++ )
+					 WBYTE(PacketP->data[loop], SendPack.Data[loop] );
+
+				WBYTE(PacketP->len, SendPack.Len);
+
+				add_transmit( PortP );
+				/*
+				** Count characters transmitted for port statistics reporting
+				*/
+				if (PortP->statsGather)
+					 PortP->txchars += (SendPack.Len & 127);
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				return retval;
+
+			case RIO_NO_MESG:
+				if ( su )
+					 p->RIONoMessage = 1;
+				return su ? 0 : -EPERM;
+
+			case RIO_MESG:
+				if ( su )
+					p->RIONoMessage = 0;
+				return su ? 0 : -EPERM;
+
+			case RIO_WHAT_MESG:
+				if ( copyout( (caddr_t)&p->RIONoMessage, (int)arg, 
+					sizeof(p->RIONoMessage) )==COPYFAIL ) {
+					rio_dprintk (RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
+					p->RIOError.Error = COPYOUT_FAILED;
+					return -EFAULT;
+				}
+				return 0;
+
+			case RIO_MEM_DUMP :
+				if (copyin((int)arg, (caddr_t)&SubCmd, 
+						sizeof(struct SubCmdStruct)) == COPYFAIL) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", 
+						SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
+
+				if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) {
+					 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+
+				if (SubCmd.Host >= p->RIONumHosts ) {
+					 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+
+				port = p->RIOHosts[SubCmd.Host].
+								UnixRups[SubCmd.Rup].BaseSysPort;
+
+				PortP = p->RIOPortp[port];
+
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				if ( RIOPreemptiveCmd(p,  PortP, MEMDUMP ) == RIO_FAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
+					 rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+					 return -EBUSY;
+				}
+				else
+					 PortP->State |= RIO_BUSY;
+
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				if ( copyout( (caddr_t)p->RIOMemDump, (int)arg, 
+							MEMDUMP_SIZE) == COPYFAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return 0;
+
+			case RIO_TICK:
+				if ((int)arg < 0 || (int)arg >= p->RIONumHosts)
+					 return -EINVAL;
+				rio_dprintk (RIO_DEBUG_CTRL, "Set interrupt for host %d\n", (int)arg);
+				WBYTE(p->RIOHosts[(int)arg].SetInt , 0xff);
+				return 0;
+
+			case RIO_TOCK:
+				if ((int)arg < 0 || (int)arg >= p->RIONumHosts)
+					 return -EINVAL;
+				rio_dprintk (RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int)arg);
+				WBYTE((p->RIOHosts[(int)arg].ResetInt) , 0xff);
+				return 0;
+
+			case RIO_READ_CHECK:
+				/* Check reads for pkts with data[0] the same */
+				p->RIOReadCheck = !p->RIOReadCheck;
+				if (copyout((caddr_t)&p->RIOReadCheck,(int)arg,
+							sizeof(uint))== COPYFAIL) {
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return 0;
+
+			case RIO_READ_REGISTER :
+				if (copyin((int)arg, (caddr_t)&SubCmd, 
+							sizeof(struct SubCmdStruct)) == COPYFAIL) {
+					 p->RIOError.Error = COPYIN_FAILED;
+					 return -EFAULT;
+				}
+				rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", 
+						SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
+
+				if (SubCmd.Port > 511) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", 
+								SubCmd.Port);
+					 p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+
+				if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) {
+					 p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+
+				if (SubCmd.Host >= p->RIONumHosts ) {
+					 p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+					 return -EINVAL;
+				}
+
+				port = p->RIOHosts[SubCmd.Host].
+						UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
+				PortP = p->RIOPortp[port];
+
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
+					 rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+					 return -EBUSY;
+				}
+				else
+					 PortP->State |= RIO_BUSY;
+
+				rio_spin_unlock_irqrestore( &PortP->portSem , flags);
+				if (copyout((caddr_t)&p->CdRegister, (int)arg, 
+							sizeof(uint)) == COPYFAIL ) {
+					 rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
+					 p->RIOError.Error = COPYOUT_FAILED;
+					 return -EFAULT;
+				}
+				return 0;
+				/*
+				** rio_make_dev: given port number (0-511) ORed with port type
+				** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
+				** value to pass to mknod to create the correct device node.
+				*/
+			case RIO_MAKE_DEV:
+				{
+					uint port = (uint)arg & RIO_MODEM_MASK;
+
+					switch ( (uint)arg & RIO_DEV_MASK ) {
+						case RIO_DEV_DIRECT:
+							arg = (caddr_t)drv_makedev(MAJOR(dev), port);
+							rio_dprintk (RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n",port, (int)arg);
+							return (int)arg;
+					 	case RIO_DEV_MODEM:
+							arg =  (caddr_t)drv_makedev(MAJOR(dev), (port|RIO_MODEM_BIT) );
+							rio_dprintk (RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n",port, (int)arg);
+							return (int)arg;
+						case RIO_DEV_XPRINT:
+							arg = (caddr_t)drv_makedev(MAJOR(dev), port);
+							rio_dprintk (RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n",port, (int)arg);
+							return (int)arg;
+					}
+					rio_dprintk (RIO_DEBUG_CTRL, "MAKE Device is called\n");
+					return -EINVAL;
+				}
+				/*
+				** rio_minor: given a dev_t from a stat() call, return
+				** the port number (0-511) ORed with the port type
+				** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
+				*/
+			case RIO_MINOR:
+				{
+					dev_t dv;
+					int mino;
+
+					dv = (dev_t)((int)arg);
+					mino = RIO_UNMODEM(dv);
+
+					if ( RIO_ISMODEM(dv) ) {
+						rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
+						arg = (caddr_t)(mino | RIO_DEV_MODEM);
+					}
+					else {
+						rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
+						arg = (caddr_t)(mino | RIO_DEV_DIRECT);
+					}
+					return (int)arg;
+				}
+	}
+	rio_dprintk (RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n",cmd);
+	p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+
+	func_exit ();
+	return -EINVAL;
+}
+
+/*
+** Pre-emptive commands go on RUPs and are only one byte long.
+*/
+int
+RIOPreemptiveCmd(p, PortP, Cmd)
+struct rio_info *	p;
+struct Port *PortP;
+uchar Cmd;
+{
+	struct CmdBlk *CmdBlkP;
+	struct PktCmd_M *PktCmdP;
+	int Ret;
+	ushort rup;
+	int port;
+
+#ifdef CHECK
+	CheckPortP( PortP );
+#endif
+
+	if ( PortP->State & RIO_DELETED ) {
+		rio_dprintk (RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
+		return RIO_FAIL;
+	}
+
+	if (((int)((char)PortP->InUse) == -1) || ! (CmdBlkP = RIOGetCmdBlk()) ) {
+		rio_dprintk (RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n",
+		       Cmd, PortP->PortNum);
+		return RIO_FAIL;
+	}
+
+	rio_dprintk (RIO_DEBUG_CTRL, "Command blk 0x%x - InUse now %d\n", 
+	       (int)CmdBlkP,PortP->InUse);
+
+	PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
+
+	CmdBlkP->Packet.src_unit  = 0;
+	if (PortP->SecondBlock)
+		rup = PortP->ID2;
+	else
+		rup = PortP->RupNum;
+	CmdBlkP->Packet.dest_unit = rup;
+	CmdBlkP->Packet.src_port  = COMMAND_RUP;
+	CmdBlkP->Packet.dest_port = COMMAND_RUP;
+	CmdBlkP->Packet.len	  = PKT_CMD_BIT | 2;
+	CmdBlkP->PostFuncP	= RIOUnUse;
+	CmdBlkP->PostArg	= (int)PortP;
+	PktCmdP->Command	= Cmd;
+	port				= PortP->HostPort % (ushort)PORTS_PER_RTA;
+	/*
+	** Index ports 8-15 for 2nd block of 16 port RTA.
+	*/
+	if (PortP->SecondBlock)
+		port += (ushort) PORTS_PER_RTA;
+	PktCmdP->PhbNum	   = port;
+
+	switch ( Cmd ) {
+		case MEMDUMP:
+			rio_dprintk (RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%x (addr 0x%x)\n",
+			       (int)CmdBlkP, (int)SubCmd.Addr);
+			PktCmdP->SubCommand		= MEMDUMP;
+			PktCmdP->SubAddr		= SubCmd.Addr;
+			break;
+		case FCLOSE:
+			rio_dprintk (RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP);
+			break;
+		case READ_REGISTER:
+			rio_dprintk (RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%x\n",
+		 		(int)SubCmd.Addr, (int)CmdBlkP);
+			PktCmdP->SubCommand		= READ_REGISTER;
+			PktCmdP->SubAddr		= SubCmd.Addr;
+			break;
+		case RESUME:
+			rio_dprintk (RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n",(int)CmdBlkP);
+			break;
+		case RFLUSH:
+			rio_dprintk (RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP);
+			CmdBlkP->PostFuncP = RIORFlushEnable;
+			break;
+		case SUSPEND:
+			rio_dprintk (RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP);
+			break;
+
+		case MGET :
+			rio_dprintk (RIO_DEBUG_CTRL, "Queue MGET command blk 0x%x\n", (int)CmdBlkP);
+			break;
+
+		case MSET :
+		case MBIC :
+		case MBIS :
+			CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
+			rio_dprintk (RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int)CmdBlkP);
+			break;
+
+		case WFLUSH:
+			/*
+			** If we have queued up the maximum number of Write flushes
+			** allowed then we should not bother sending any more to the
+			** RTA.
+			*/
+			if ((int)((char)PortP->WflushFlag) == (int)-1) {
+				rio_dprintk (RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!");
+				RIOFreeCmdBlk(CmdBlkP);
+				return(RIO_FAIL);
+			} else {
+				rio_dprintk (RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n",
+				       (int)CmdBlkP);
+				CmdBlkP->PostFuncP = RIOWFlushMark;
+			}
+			break;
+	}
+
+	PortP->InUse++;
+
+	Ret = RIOQueueCmdBlk( PortP->HostP, rup, CmdBlkP );
+
+	return Ret;
+}
diff --git a/drivers/char/rio/riodrvr.h b/drivers/char/rio/riodrvr.h
new file mode 100644
index 0000000..bc38ac5
--- /dev/null
+++ b/drivers/char/rio/riodrvr.h
@@ -0,0 +1,144 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riodrvr.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 09:22:46
+**	Retrieved	: 11/6/98 09:22:46
+**
+**  ident @(#)riodrvr.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __riodrvr_h
+#define __riodrvr_h
+
+#include <asm/param.h>	/* for HZ */
+
+#ifdef SCCS_LABELS
+static char *_riodrvr_h_sccs_ = "@(#)riodrvr.h	1.3";
+#endif
+
+#define MEMDUMP_SIZE	32
+#define	MOD_DISABLE	(RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT)
+
+
+struct rio_info {
+	int			mode;			/* Intr or polled, word/byte */
+	spinlock_t		RIOIntrSem;		/* Interrupt thread sem */
+	int			current_chan;		/* current channel */
+	int			RIOFailed;		/* Not initialised ? */
+	int			RIOInstallAttempts;	/* no. of rio-install() calls */
+	int			RIOLastPCISearch;	/* status of last search */
+	int			RIONumHosts;		/* Number of RIO Hosts */
+	struct Host		* RIOHosts;		/* RIO Host values */
+	struct Port		**RIOPortp;		/* RIO port values */
+/*
+** 02.03.1999 ARG - ESIL 0820 fix
+** We no longer use RIOBootMode
+**
+	int			RIOBootMode;		* RIO boot mode *
+**
+*/
+	int			RIOPrintDisabled;	/* RIO printing disabled ? */
+	int			RIOPrintLogState;	/* RIO printing state ? */
+	int			RIOPolling;		/* Polling ? */
+/*
+** 09.12.1998 ARG - ESIL 0776 part fix
+** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted.
+** The fix for this ESIL introduces another member (RIORtaDisCons) here to be
+** updated in RIOConCon() - to keep track of RTA connections/disconnections.
+** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons.
+*/
+	int			RIOHalted;		/* halted ? */
+	int			RIORtaDisCons;		/* RTA connections/disconnections */
+	uint			RIOReadCheck;		/* Rio read check */
+	uint			RIONoMessage;		/* To display message or not */
+	uint			RIONumBootPkts;		/* how many packets for an RTA */
+	uint			RIOBootCount; 		/* size of RTA code */
+	uint			RIOBooting;		/* count of outstanding boots */
+	uint			RIOSystemUp;		/* Booted ?? */
+	uint			RIOCounting;		/* for counting interrupts */
+	uint			RIOIntCount;		/* # of intr since last check */
+	uint			RIOTxCount;		/* number of xmit intrs  */
+	uint			RIORxCount;		/* number of rx intrs */
+	uint			RIORupCount;		/* number of rup intrs */
+	int			RIXTimer; 
+	int			RIOBufferSize;		/* Buffersize */
+	int			RIOBufferMask;		/* Buffersize */
+
+	int			RIOFirstMajor;		/* First host card's major no */
+
+	uint			RIOLastPortsMapped;	/* highest port number known */
+	uint			RIOFirstPortsMapped;	/* lowest port number known */
+
+	uint			RIOLastPortsBooted;	/* highest port number running */
+	uint			RIOFirstPortsBooted;	/* lowest port number running */
+
+	uint			RIOLastPortsOpened;	/* highest port number running */
+	uint			RIOFirstPortsOpened;	/* lowest port number running */
+
+	/* Flag to say that the topology information has been changed. */
+	uint			RIOQuickCheck; 
+	uint			CdRegister;		/* ??? */
+	int			RIOSignalProcess;	/* Signalling process */
+	int			rio_debug;		/* To debug ... */
+	int			RIODebugWait;		/* For what ??? */
+	int			tpri;			/* Thread prio */
+	int			tid;			/* Thread id */
+	uint			_RIO_Polled;		/* Counter for polling */
+	uint			_RIO_Interrupted;	/* Counter for interrupt */
+	int			intr_tid;		/* iointset return value */
+	int			TxEnSem;		/* TxEnable Semaphore */
+
+
+	struct Error		RIOError;		/* to Identify what went wrong */ 
+	struct Conf		RIOConf;		/* Configuration ??? */
+	struct ttystatics	channel[RIO_PORTS];	/* channel information */
+	char			RIOBootPackets[1+(SIXTY_FOUR_K/RTA_BOOT_DATA_SIZE)]
+								[RTA_BOOT_DATA_SIZE];
+	struct Map		RIOConnectTable[TOTAL_MAP_ENTRIES];
+	struct Map		RIOSavedTable[TOTAL_MAP_ENTRIES];
+
+	/* RTA to host binding table for master/slave operation */
+	ulong			RIOBindTab[MAX_RTA_BINDINGS];
+	/* RTA memory dump variable */
+	uchar			RIOMemDump[MEMDUMP_SIZE]; 
+	struct ModuleInfo 	RIOModuleTypes[MAX_MODULE_TYPES];
+
+};
+
+
+#ifdef linux
+#define debug(x)        printk x
+#else
+#define debug(x)	kkprintf x
+#endif
+
+
+
+#define RIO_RESET_INT	0x7d80
+#define WRBYTE(x,y)		*(volatile unsigned char *)((x)) = \
+					(unsigned char)(y)
+
+#endif	/* __riodrvr.h */
diff --git a/drivers/char/rio/rioinfo.h b/drivers/char/rio/rioinfo.h
new file mode 100644
index 0000000..e08421c
--- /dev/null
+++ b/drivers/char/rio/rioinfo.h
@@ -0,0 +1,96 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioinfo.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 14:07:49
+**	Retrieved	: 11/6/98 14:07:50
+**
+**  ident @(#)rioinfo.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rioinfo_h
+#define __rioinfo_h
+
+#ifdef SCCS_LABELS
+static char *_rioinfo_h_sccs_ = "@(#)rioinfo.h	1.2";
+#endif
+
+/*
+** Host card data structure
+*/
+struct RioHostInfo {
+	long	location;	/* RIO Card Base I/O address */
+	long	vector;		/* RIO Card IRQ vector */
+	int	bus;		/* ISA/EISA/MCA/PCI */
+	int	mode;		/* pointer to host mode - INTERRUPT / POLLED */
+	struct old_sgttyb
+		* Sg;		/* pointer to default term characteristics */
+};
+
+
+/* Mode in rio device info */
+#define INTERRUPTED_MODE	0x01		/* Interrupt is generated */
+#define POLLED_MODE		0x02		/* No interrupt */
+#define AUTO_MODE		0x03		/* Auto mode */
+
+#define WORD_ACCESS_MODE	0x10		/* Word Access Mode */
+#define BYTE_ACCESS_MODE	0x20		/* Byte Access Mode */
+
+
+/* Bus type that RIO supports */
+#define ISA_BUS			0x01		/* The card is ISA */
+#define EISA_BUS		0x02		/* The card is EISA */
+#define MCA_BUS			0x04		/* The card is MCA */
+#define PCI_BUS			0x08		/* The card is PCI */
+
+/*
+** 11.11.1998 ARG - ESIL ???? part fix
+** Moved definition for 'CHAN' here from rioinfo.c (it is now
+** called 'DEF_TERM_CHARACTERISTICS').
+*/
+
+#define DEF_TERM_CHARACTERISTICS \
+{ \
+	B19200, B19200,				/* input and output speed */ \
+	'H' - '@',				/* erase char */ \
+	-1,					/* 2nd erase char */ \
+	'U' - '@',				/* kill char */ \
+	ECHO | CRMOD,				/* mode */ \
+	'C' - '@',				/* interrupt character */ \
+	'\\' - '@',				/* quit char */ \
+	'Q' - '@',				/* start char */ \
+	'S' - '@',				/* stop char */ \
+	'D' - '@',				/* EOF */ \
+	-1,					/* brk */ \
+	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */ \
+	'Z' - '@',				/* process stop */ \
+	'Y' - '@',				/* delayed stop */ \
+	'R' - '@',				/* reprint line */ \
+	'O' - '@',				/* flush output */ \
+	'W' - '@',				/* word erase */ \
+	'V' - '@'				/* literal next char */ \
+}
+
+#endif /* __rioinfo_h */
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
new file mode 100644
index 0000000..dca941e
--- /dev/null
+++ b/drivers/char/rio/rioinit.c
@@ -0,0 +1,1617 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioinit.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:43
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)rioinit.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_rioinit_c_sccs_ = "@(#)rioinit.c	1.3";
+#endif
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "rio_linux.h"
+
+#undef bcopy
+#define bcopy rio_pcicopy
+
+int RIOPCIinit(struct rio_info *p, int Mode);
+
+#if 0
+static void RIOAllocateInterrupts(struct rio_info *);
+static int RIOReport(struct rio_info *);
+static void RIOStopInterrupts(struct rio_info *, int, int);
+#endif
+
+static int RIOScrub(int, BYTE *, int);
+
+#if 0
+extern int	rio_intr();
+
+/*
+**	Init time code.
+*/
+void
+rioinit( p, info )
+struct rio_info		* p;
+struct RioHostInfo	* info;
+{
+	/*
+	** Multi-Host card support - taking the easy way out - sorry !
+	** We allocate and set up the Host and Port structs when the
+	** driver is called to 'install' the first host.
+	** We check for this first 'call' by testing the RIOPortp pointer.
+	*/
+	if ( !p->RIOPortp )
+	{
+		rio_dprintk (RIO_DEBUG_INIT,  "Allocating and setting up driver data structures\n");
+
+		RIOAllocDataStructs(p);		/* allocate host/port structs */
+		RIOSetupDataStructs(p);		/* setup topology structs */
+	}
+
+	RIOInitHosts( p, info );	/* hunt down the hardware */
+
+	RIOAllocateInterrupts(p);	/* allocate interrupts */
+	RIOReport(p);			/* show what we found */
+}
+
+/*
+** Initialise the Cards 
+*/ 
+void
+RIOInitHosts(p, info)
+struct rio_info		* p;
+struct RioHostInfo	* info;
+{
+/*
+** 15.10.1998 ARG - ESIL 0762 part fix
+** If there is no ISA card definition - we always look for PCI cards.
+** As we currently only support one host card this lets an ISA card
+** definition take precedence over PLUG and PLAY.
+** No ISA card - we are PLUG and PLAY with PCI.
+*/
+
+	/*
+	** Note - for PCI both these will be zero, that's okay because
+	** RIOPCIInit() fills them in if a card is found.
+	*/
+	p->RIOHosts[p->RIONumHosts].Ivec	= info->vector;
+	p->RIOHosts[p->RIONumHosts].PaddrP	= info->location;
+
+	/*
+	** Check that we are able to accommodate another host
+	*/
+	if ( p->RIONumHosts >= RIO_HOSTS )
+	{
+		p->RIOFailed++;
+		return;
+	}
+
+	if ( info->bus & ISA_BUS )
+	{
+		rio_dprintk (RIO_DEBUG_INIT,  "initialising card %d (ISA)\n", p->RIONumHosts);
+		RIOISAinit(p, p->mode);
+	}
+	else
+	{
+		rio_dprintk (RIO_DEBUG_INIT,  "initialising card %d (PCI)\n", p->RIONumHosts);
+		RIOPCIinit(p, RIO_PCI_DEFAULT_MODE);
+	}
+
+	rio_dprintk (RIO_DEBUG_INIT,  "Total hosts initialised so far : %d\n", p->RIONumHosts);
+
+
+#ifdef FUTURE_RELEASE
+	if (p->bus & EISA_BUS)
+		/* EISA card */
+		RIOEISAinit(p, RIO_EISA_DEFAULT_MODE);
+
+	if (p->bus & MCA_BUS)
+		/* MCA card */
+		RIOMCAinit(p, RIO_MCA_DEFAULT_MODE);
+#endif
+}
+
+/*
+** go through memory for an AT host that we pass in the device info
+** structure and initialise
+*/
+void
+RIOISAinit(p, mode)
+struct rio_info *	p;
+int					mode;
+{
+
+  /* XXX Need to implement this. */
+#if 0
+	p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
+					(int (*)())rio_intr, (char*)p->RIONumHosts);
+
+	rio_dprintk (RIO_DEBUG_INIT,  "Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid );
+
+	if (RIODoAT(p, p->RIOHosts[p->RIONumHosts].PaddrP, mode)) {
+		return;
+	}
+	else {
+		rio_dprintk (RIO_DEBUG_INIT, "RIODoAT failed\n");
+		p->RIOFailed++;
+	}
+#endif
+
+}
+
+/*
+** RIODoAT :
+**
+** Map in a boards physical address, check that the board is there,
+** test the board and if everything is okay assign the board an entry
+** in the Rio Hosts structure.
+*/
+int
+RIODoAT(p, Base, mode)
+struct rio_info *	p;
+int		Base;
+int		mode;
+{
+#define	FOUND		1
+#define NOT_FOUND	0
+
+	caddr_t		cardAddr;
+
+	/*
+	** Check to see if we actually have a board at this physical address.
+	*/
+	if ((cardAddr = RIOCheckForATCard(Base)) != 0) {
+		/*
+		** Now test the board to see if it is working.
+		*/
+		if (RIOBoardTest(Base, cardAddr, RIO_AT, 0) == RIO_SUCCESS) {
+			/*
+			** Fill out a slot in the Rio host structure.
+			*/
+			if (RIOAssignAT(p, Base, cardAddr, mode)) {
+				return(FOUND);
+			}
+		}
+		RIOMapout(Base, RIO_AT_MEM_SIZE, cardAddr);
+	}
+	return(NOT_FOUND);
+}
+
+caddr_t
+RIOCheckForATCard(Base)
+int		Base;
+{
+	int				off;
+	struct DpRam	*cardp;		/* (Points at the host) */
+	caddr_t			virtAddr;
+	unsigned char			RIOSigTab[24];
+/*
+** Table of values to search for as prom signature of a host card
+*/
+	strcpy(RIOSigTab, "JBJGPGGHINSMJPJR");
+
+	/*
+	** Hey! Yes, You reading this code! Yo, grab a load a this:
+	**
+	** IF the card is using WORD MODE rather than BYTE MODE
+	** then it will occupy 128K of PHYSICAL memory area. So,
+	** you might think that the following Mapin is wrong. Well,
+	** it isn't, because the SECOND 64K of occupied space is an
+	** EXACT COPY of the FIRST 64K. (good?), so, we need only
+	** map it in in one 64K block.
+	*/
+	if (RIOMapin(Base, RIO_AT_MEM_SIZE, &virtAddr) == -1) {
+		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't map the board in!\n");
+		return((caddr_t)0);
+	}
+
+	/*
+	** virtAddr points to the DP ram of the system.
+	** We now cast this to a pointer to a RIO Host,
+	** and have a rummage about in the PROM.
+	*/
+	cardp = (struct DpRam *)virtAddr;
+
+	for (off=0; RIOSigTab[off]; off++) {
+		if ((RBYTE(cardp->DpSignature[off]) & 0xFF) != RIOSigTab[off]) {
+			/*
+			** Signature mismatch - card not at this address
+			*/
+			RIOMapout(Base, RIO_AT_MEM_SIZE, virtAddr);
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't match the signature 0x%x 0x%x!\n",
+						(int)cardp, off);
+			return((caddr_t)0);
+		}
+	}
+
+	/*
+	** If we get here then we must have found a valid board so return
+	** its virtual address.
+	*/
+	return(virtAddr);
+}
+#endif
+
+/**
+** RIOAssignAT :
+**
+** Fill out the fields in the p->RIOHosts structure now we know we know
+** we have a board present.
+**
+** bits < 0 indicates 8 bit operation requested,
+** bits > 0 indicates 16 bit operation.
+*/
+int
+RIOAssignAT(p, Base, virtAddr, mode)
+struct rio_info *	p;
+int		Base;
+caddr_t	virtAddr;
+int		mode;
+{
+	int		bits;
+	struct DpRam *cardp = (struct DpRam *)virtAddr;
+
+	if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE))
+		bits = BYTE_OPERATION;
+	else
+		bits = WORD_OPERATION;
+
+	/*
+	** Board has passed its scrub test. Fill in all the
+	** transient stuff.
+	*/
+	p->RIOHosts[p->RIONumHosts].Caddr	= virtAddr;
+	p->RIOHosts[p->RIONumHosts].CardP	= (struct DpRam *)virtAddr;
+
+	/*
+	** Revision 01 AT host cards don't support WORD operations,
+	*/
+	if ( RBYTE(cardp->DpRevision) == 01 )
+		bits = BYTE_OPERATION;
+
+	p->RIOHosts[p->RIONumHosts].Type = RIO_AT;
+	p->RIOHosts[p->RIONumHosts].Copy = bcopy;
+											/* set this later */
+	p->RIOHosts[p->RIONumHosts].Slot = -1;
+	p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits;
+	WBYTE(p->RIOHosts[p->RIONumHosts].Control, 
+			BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+			p->RIOHosts[p->RIONumHosts].Mode | 
+			INTERRUPT_DISABLE );
+	WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
+	WBYTE(p->RIOHosts[p->RIONumHosts].Control,
+			BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+			p->RIOHosts[p->RIONumHosts].Mode |
+			INTERRUPT_DISABLE );
+	WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
+	p->RIOHosts[p->RIONumHosts].UniqueNum =
+		((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
+		((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
+		((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
+		((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
+	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+	p->RIONumHosts++;
+	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base);
+	return(1);
+}
+#if 0
+#ifdef FUTURE_RELEASE
+int RIOMCAinit(int Mode)
+{
+	uchar SlotNumber;
+	caddr_t Caddr;
+	uint	Paddr;
+	uint	Ivec;
+	int	 Handle;
+	int	 ret = 0;
+
+	/*
+	** Valid mode information for MCA cards
+	** is only FAST LINKS
+	*/
+	Mode = (Mode & FAST_LINKS) ? McaTpFastLinks : McaTpSlowLinks;
+	rio_dprintk (RIO_DEBUG_INIT, "RIOMCAinit(%d)\n",Mode);
+
+
+	/*
+	** Check out each of the slots
+	*/
+	for (SlotNumber = 0; SlotNumber < McaMaxSlots; SlotNumber++) {
+	/*
+	** Enable the slot we want to talk to
+	*/
+	outb( McaSlotSelect, SlotNumber | McaSlotEnable );
+
+	/*
+	** Read the ID word from the slot
+	*/
+	if (((inb(McaIdHigh)<< 8)|inb(McaIdLow)) == McaRIOId)
+	{
+		rio_dprintk (RIO_DEBUG_INIT, "Potential MCA card in slot %d\n", SlotNumber);
+
+		/*
+		** Card appears to be a RIO MCA card!
+		*/
+		RIOMachineType |= (1<<RIO_MCA);
+
+		/*
+		** Just check we haven't found too many wonderful objects
+		*/
+		if ( RIONumHosts >= RIO_HOSTS )
+		{
+		Rprintf(RIOMesgTooManyCards);
+		return(ret);
+		}
+
+		/*
+		** McaIrqEnable contains the interrupt vector, and a card
+		** enable bit.
+		*/
+		Ivec = inb(McaIrqEnable);
+
+		rio_dprintk (RIO_DEBUG_INIT, "Ivec is %x\n", Ivec);
+
+		switch ( Ivec & McaIrqMask )
+		{
+		case McaIrq9:
+		rio_dprintk (RIO_DEBUG_INIT, "IRQ9\n");
+		break;
+		case McaIrq3:
+		rio_dprintk (RIO_DEBUG_INIT, "IRQ3\n");
+		break;
+		case McaIrq4:
+		rio_dprintk (RIO_DEBUG_INIT, "IRQ4\n");
+		break;
+		case McaIrq7:
+		rio_dprintk (RIO_DEBUG_INIT, "IRQ7\n");
+		break;
+		case McaIrq10:
+		rio_dprintk (RIO_DEBUG_INIT, "IRQ10\n");
+		break;
+		case McaIrq11:
+		rio_dprintk (RIO_DEBUG_INIT, "IRQ11\n");
+		break;
+		case McaIrq12:
+		rio_dprintk (RIO_DEBUG_INIT, "IRQ12\n");
+		break;
+		case McaIrq15:
+		rio_dprintk (RIO_DEBUG_INIT, "IRQ15\n");
+		break;
+		}
+
+		/*
+		** If the card enable bit isn't set, then set it!
+		*/
+		if ((Ivec & McaCardEnable) != McaCardEnable) {
+			rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable not set - setting!\n");
+			outb(McaIrqEnable,Ivec|McaCardEnable);
+		} else
+			rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable already set\n");
+
+		/*
+		** Convert the IRQ enable mask into something useful
+		*/
+		Ivec = RIOMcaToIvec[Ivec & McaIrqMask];
+
+		/*
+		** Find the physical address
+		*/
+		rio_dprintk (RIO_DEBUG_INIT, "inb(McaMemory) is %x\n", inb(McaMemory));
+		Paddr = McaAddress(inb(McaMemory));
+
+		rio_dprintk (RIO_DEBUG_INIT, "MCA card has Ivec %d Addr %x\n", Ivec, Paddr);
+
+		if ( Paddr != 0 )
+		{
+
+		/*
+		** Tell the memory mapper that we want to talk to it
+		*/
+		Handle = RIOMapin( Paddr, RIO_MCA_MEM_SIZE, &Caddr );
+
+		if ( Handle == -1 ) {
+			rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE, Paddr;
+			continue;
+		}
+
+		rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr);
+
+		/*
+		** And check that it is actually there!
+		*/
+		if ( RIOBoardTest( Paddr,Caddr,RIO_MCA,SlotNumber ) == RIO_SUCCESS )
+		{
+			rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n");
+			rio_dprintk (RIO_DEBUG_INIT, "Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
+			                            SlotNumber, RIO_MCA, Paddr, Caddr, Mode);
+
+			/*
+			** Board has passed its scrub test. Fill in all the
+			** transient stuff.
+			*/
+			p->RIOHosts[RIONumHosts].Slot	 = SlotNumber;
+			p->RIOHosts[RIONumHosts].Ivec	 = Ivec;
+			p->RIOHosts[RIONumHosts].Type	 = RIO_MCA;
+			p->RIOHosts[RIONumHosts].Copy	 = bcopy;
+			p->RIOHosts[RIONumHosts].PaddrP   = Paddr;
+			p->RIOHosts[RIONumHosts].Caddr	= Caddr;
+			p->RIOHosts[RIONumHosts].CardP	= (struct DpRam *)Caddr;
+			p->RIOHosts[RIONumHosts].Mode	 = Mode;
+			WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt , 0xff);
+			p->RIOHosts[RIONumHosts].UniqueNum =
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
+						((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
+			RIONumHosts++;
+			ret++;
+		}
+		else
+		{
+			/*
+			** It failed the test, so ignore it.
+			*/
+			rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n");
+			RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr );
+		}
+		}
+		else
+		{
+		rio_dprintk (RIO_DEBUG_INIT, "Slot %d - Paddr zero!\n", SlotNumber);
+		}
+	}
+	else
+	{
+		rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber);
+	}
+	}
+	/*
+	** Now we have checked all the slots, turn off the MCA slot selector
+	*/
+	outb(McaSlotSelect,0);
+	rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber);
+	return ret;
+}
+
+int RIOEISAinit( int Mode )
+{
+	static int EISADone = 0;
+	uint Paddr;
+	int PollIntMixMsgDone = 0;
+	caddr_t Caddr;
+	ushort Ident;
+	uchar EisaSlot;
+	uchar Ivec;
+	int ret = 0;
+
+	/*
+	** The only valid mode information for EISA hosts is fast or slow
+	** links.
+	*/
+	Mode = (Mode & FAST_LINKS) ? EISA_TP_FAST_LINKS : EISA_TP_SLOW_LINKS;
+
+	if ( EISADone )
+	{
+		rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit() - already done, return.\n");
+		return(0);
+	}
+
+	EISADone++;
+
+	rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit()\n");
+
+
+	/*
+	** First check all cards to see if ANY are set for polled mode operation.
+	** If so, set ALL to polled.
+	*/
+
+	for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
+	{
+	Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
+		 INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
+
+	if ( Ident == RIO_EISA_IDENT )
+	{
+		rio_dprintk (RIO_DEBUG_INIT, "Found Specialix product\n");
+
+		if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
+		{
+		rio_dprintk (RIO_DEBUG_INIT, "Not Specialix RIO - Product number %x\n",
+						INBZ(EisaSlot, EISA_PRODUCT_NUMBER));
+		continue;  /* next slot */
+		}
+		/*
+		** Its a Specialix RIO!
+		*/
+		rio_dprintk (RIO_DEBUG_INIT, "RIO Revision %d\n",
+					INBZ(EisaSlot, EISA_REVISION_NUMBER));
+		
+		RIOMachineType |= (1<<RIO_EISA);
+
+		/*
+		** Just check we haven't found too many wonderful objects
+		*/
+		if ( RIONumHosts >= RIO_HOSTS )
+		{
+		Rprintf(RIOMesgTooManyCards);
+		return 0;
+		}
+
+		/*
+		** Ensure that the enable bit is set!
+		*/
+		OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
+
+		/*
+		** EISA_INTERRUPT_VEC contains the interrupt vector.
+		*/
+		Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
+
+#ifdef RIODEBUG
+		switch ( Ivec & EISA_INTERRUPT_MASK )
+		{
+		case EISA_IRQ_3:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 3\n");
+		break;
+		case EISA_IRQ_4:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 4\n");
+		break;
+		case EISA_IRQ_5:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 5\n");
+		break;
+		case EISA_IRQ_6:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 6\n");
+		break;
+		case EISA_IRQ_7:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 7\n");
+		break;
+		case EISA_IRQ_9:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 9\n");
+		break;
+		case EISA_IRQ_10:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 10\n");
+		break;
+		case EISA_IRQ_11:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 11\n");
+		break;
+		case EISA_IRQ_12:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 12\n");
+		break;
+		case EISA_IRQ_14:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 14\n");
+		break;
+		case EISA_IRQ_15:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 15\n");
+		break;
+		case EISA_POLLED:
+			rio_dprintk (RIO_DEBUG_INIT, "EISA POLLED\n");
+		break;
+		default:
+			rio_dprintk (RIO_DEBUG_INIT, NULL,DBG_INIT|DBG_FAIL,"Shagged interrupt number!\n");
+		Ivec &= EISA_CONTROL_MASK;
+		}
+#endif
+
+		if ( (Ivec & EISA_INTERRUPT_MASK) ==
+		 EISA_POLLED )
+		{
+		RIOWillPoll = 1;
+		break;		/* From EisaSlot loop */
+		}
+	}
+	}
+
+	/*
+	** Do it all again now we know whether to change all cards to polled
+	** mode or not
+	*/
+
+	for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
+	{
+	Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
+		 INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
+
+	if ( Ident == RIO_EISA_IDENT )
+	{
+		if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
+		continue;  /* next slot */
+
+		/*
+		** Its a Specialix RIO!
+		*/
+		
+		/*
+		** Ensure that the enable bit is set!
+		*/
+		OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
+
+		/*
+		** EISA_INTERRUPT_VEC contains the interrupt vector.
+		*/
+		Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
+
+		if ( RIOWillPoll )
+		{
+			/*
+			** If we are going to operate in polled mode, but this
+			** board is configured to be interrupt driven, display
+			** the message explaining the situation to the punter,
+			** assuming we haven't already done so.
+			*/
+
+			if ( !PollIntMixMsgDone &&
+			 (Ivec & EISA_INTERRUPT_MASK) != EISA_POLLED )
+			{
+			Rprintf(RIOMesgAllPolled);
+			PollIntMixMsgDone = 1;
+			}
+
+			/*
+			** Ungraciously ignore whatever the board reports as its
+			** interrupt vector...
+			*/
+
+			Ivec &= ~EISA_INTERRUPT_MASK;
+
+			/*
+			** ...and force it to dance to the poll tune.
+			*/
+
+			Ivec |= EISA_POLLED;
+		}
+
+		/*
+		** Convert the IRQ enable mask into something useful (0-15)
+		*/
+		Ivec = RIOEisaToIvec(Ivec);
+
+		rio_dprintk (RIO_DEBUG_INIT, "EISA host in slot %d has Ivec 0x%x\n",
+		 EisaSlot, Ivec);
+
+		/*
+		** Find the physical address
+		*/
+		Paddr = (INBZ(EisaSlot,EISA_MEMORY_BASE_HI)<<24) |
+				(INBZ(EisaSlot,EISA_MEMORY_BASE_LO)<<16);
+
+		rio_dprintk (RIO_DEBUG_INIT, "EISA card has Ivec %d Addr %x\n", Ivec, Paddr);
+
+		if ( Paddr == 0 )
+		{
+		rio_dprintk (RIO_DEBUG_INIT,
+		 "Board in slot %d configured for address zero!\n", EisaSlot);
+		continue;
+		}
+
+		/*
+		** Tell the memory mapper that we want to talk to it
+		*/
+		rio_dprintk (RIO_DEBUG_INIT, "About to map EISA card \n");
+
+		if (RIOMapin( Paddr, RIO_EISA_MEM_SIZE, &Caddr) == -1) {
+		rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n",
+							RIO_EISA_MEM_SIZE,Paddr);
+		continue;
+		}
+
+		rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr);
+
+		/*
+		** And check that it is actually there!
+		*/
+		if ( RIOBoardTest( Paddr,Caddr,RIO_EISA,EisaSlot) == RIO_SUCCESS )
+			{
+		rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n");
+		rio_dprintk (RIO_DEBUG_INIT, 
+		"Slot %d. Ivec %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
+			EisaSlot,Ivec,RIO_EISA,Paddr,Caddr,Mode);
+
+		/*
+		** Board has passed its scrub test. Fill in all the
+		** transient stuff.
+		*/
+		p->RIOHosts[RIONumHosts].Slot	 = EisaSlot;
+		p->RIOHosts[RIONumHosts].Ivec	 = Ivec;
+		p->RIOHosts[RIONumHosts].Type	 = RIO_EISA;
+		p->RIOHosts[RIONumHosts].Copy	 = bcopy;
+				p->RIOHosts[RIONumHosts].PaddrP   = Paddr;
+				p->RIOHosts[RIONumHosts].Caddr	= Caddr;
+		p->RIOHosts[RIONumHosts].CardP	= (struct DpRam *)Caddr;
+				p->RIOHosts[RIONumHosts].Mode	 = Mode;
+		/*
+		** because the EISA prom is mapped into IO space, we
+		** need to copy the unqiue number into the memory area
+		** that it would have occupied, so that the download
+		** code can determine its ID and card type.
+		*/
+	 WBYTE(p->RIOHosts[RIONumHosts].Unique[0],INBZ(EisaSlot,EISA_UNIQUE_NUM_0));
+	 WBYTE(p->RIOHosts[RIONumHosts].Unique[1],INBZ(EisaSlot,EISA_UNIQUE_NUM_1));
+	 WBYTE(p->RIOHosts[RIONumHosts].Unique[2],INBZ(EisaSlot,EISA_UNIQUE_NUM_2));
+	 WBYTE(p->RIOHosts[RIONumHosts].Unique[3],INBZ(EisaSlot,EISA_UNIQUE_NUM_3));
+		p->RIOHosts[RIONumHosts].UniqueNum =
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
+						((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
+			((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
+		INBZ(EisaSlot,EISA_INTERRUPT_RESET);
+				RIONumHosts++;
+		ret++;
+			}
+		else
+		{
+		/*
+		** It failed the test, so ignore it.
+		*/
+		rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n");
+
+		RIOMapout(Paddr, RIO_EISA_MEM_SIZE, Caddr );
+		}
+	}
+	}
+	if (RIOMachineType & RIO_EISA)
+	return ret+1;
+	return ret;
+}
+#endif
+
+
+#ifndef linux
+
+#define CONFIG_ADDRESS	0xcf8
+#define CONFIG_DATA		0xcfc
+#define FORWARD_REG		0xcfa
+
+
+static int
+read_config(int bus_number, int device_num, int r_number) 
+{
+	unsigned int cav;
+	unsigned int val;
+
+/*
+   Build config_address_value:
+
+      31        24 23        16 15      11 10  8 7        0 
+      ------------------------------------------------------
+      |1| 0000000 | bus_number | device # | 000 | register |
+      ------------------------------------------------------
+*/
+
+	cav = r_number & 0xff;
+	cav |= ((device_num & 0x1f) << 11);
+	cav |= ((bus_number & 0xff) << 16);
+	cav |= 0x80000000; /* Enable bit */
+	outpd(CONFIG_ADDRESS,cav);
+	val = inpd(CONFIG_DATA);
+	outpd(CONFIG_ADDRESS,0);
+	return val;
+}
+
+static
+write_config(bus_number,device_num,r_number,val) 
+{
+	unsigned int cav;
+
+/*
+   Build config_address_value:
+
+      31        24 23        16 15      11 10  8 7        0 
+      ------------------------------------------------------
+      |1| 0000000 | bus_number | device # | 000 | register |
+      ------------------------------------------------------
+*/
+
+	cav = r_number & 0xff;
+	cav |= ((device_num & 0x1f) << 11);
+	cav |= ((bus_number & 0xff) << 16);
+	cav |= 0x80000000; /* Enable bit */
+	outpd(CONFIG_ADDRESS, cav);
+	outpd(CONFIG_DATA, val);
+	outpd(CONFIG_ADDRESS, 0);
+	return val;
+}
+#else
+/* XXX Implement these... */
+static int
+read_config(int bus_number, int device_num, int r_number) 
+{
+  return 0;
+}
+
+static int
+write_config(int bus_number, int device_num, int r_number) 
+{
+  return 0;
+}
+
+#endif
+
+int
+RIOPCIinit(p, Mode)
+struct rio_info	*p;
+int 		Mode;
+{
+	#define MAX_PCI_SLOT		32
+	#define RIO_PCI_JET_CARD	0x200011CB
+
+	static int	slot;	/* count of machine's PCI slots searched so far */
+	caddr_t		Caddr;	/* Virtual address of the current PCI host card. */
+	unsigned char	Ivec;	/* interrupt vector for the current PCI host */
+	unsigned long	Paddr;	/* Physical address for the current PCI host */
+	int		Handle;	/* Handle to Virtual memory allocated for current PCI host */
+
+
+	rio_dprintk (RIO_DEBUG_INIT,  "Search for a RIO PCI card - start at slot %d\n", slot);
+
+	/*
+	** Initialise the search status
+	*/
+	p->RIOLastPCISearch	= RIO_FAIL;
+
+	while ( (slot < MAX_PCI_SLOT) & (p->RIOLastPCISearch != RIO_SUCCESS) )
+	{
+		rio_dprintk (RIO_DEBUG_INIT,  "Currently testing slot %d\n", slot);
+
+		if (read_config(0,slot,0) == RIO_PCI_JET_CARD) {
+			p->RIOHosts[p->RIONumHosts].Ivec = 0;
+			Paddr = read_config(0,slot,0x18);
+			Paddr = Paddr - (Paddr & 0x1); /* Mask off the io bit */
+
+			if ( (Paddr == 0) || ((Paddr & 0xffff0000) == 0xffff0000) ) {
+				rio_dprintk (RIO_DEBUG_INIT,  "Goofed up slot\n");	/* what! */
+				slot++;
+				continue;
+			}
+
+			p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
+			Ivec = (read_config(0,slot,0x3c) & 0xff);
+
+			rio_dprintk (RIO_DEBUG_INIT,  "PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec);
+
+			Handle = RIOMapin( Paddr, RIO_PCI_MEM_SIZE, &Caddr );
+			if (Handle == -1) {
+				rio_dprintk (RIO_DEBUG_INIT,  "Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr);
+				slot++;
+				continue;
+			}
+			p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32;
+			p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
+						(int (*)())rio_intr, (char *)p->RIONumHosts);
+			if (RIOBoardTest( Paddr, Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) {
+				rio_dprintk (RIO_DEBUG_INIT, ("Board has passed test\n");
+				rio_dprintk (RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, Mode);
+
+				/*
+				** Board has passed its scrub test. Fill in all the
+				** transient stuff.
+				*/
+				p->RIOHosts[p->RIONumHosts].Slot	   = 0;
+				p->RIOHosts[p->RIONumHosts].Ivec	   = Ivec + 32;
+				p->RIOHosts[p->RIONumHosts].Type	   = RIO_PCI;
+				p->RIOHosts[p->RIONumHosts].Copy	   = rio_pcicopy; 
+				p->RIOHosts[p->RIONumHosts].PaddrP	   = Paddr;
+				p->RIOHosts[p->RIONumHosts].Caddr	   = Caddr;
+				p->RIOHosts[p->RIONumHosts].CardP	   = (struct DpRam *)Caddr;
+				p->RIOHosts[p->RIONumHosts].Mode	   = Mode;
+
+#if 0
+				WBYTE(p->RIOHosts[p->RIONumHosts].Control, 
+						BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+						p->RIOHosts[p->RIONumHosts].Mode | 
+						INTERRUPT_DISABLE );
+				WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
+				WBYTE(p->RIOHosts[p->RIONumHosts].Control,
+						BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+						p->RIOHosts[p->RIONumHosts].Mode |
+						INTERRUPT_DISABLE );
+				WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
+#else
+				WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+#endif
+				p->RIOHosts[p->RIONumHosts].UniqueNum  =
+					((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
+					((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
+					((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
+					((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
+
+				rio_dprintk (RIO_DEBUG_INIT, "Unique no 0x%x.\n", 
+				    p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+				p->RIOLastPCISearch = RIO_SUCCESS;
+				p->RIONumHosts++;
+			}
+		}
+		slot++;
+	}
+
+	if ( slot >= MAX_PCI_SLOT ) {
+		rio_dprintk (RIO_DEBUG_INIT,  "All %d PCI slots have tested for RIO cards !!!\n",
+			     MAX_PCI_SLOT);
+	}
+
+
+	/*
+	** I don't think we want to do this anymore
+	**
+
+	if (!p->RIOLastPCISearch == RIO_FAIL ) {
+		p->RIOFailed++;
+	}
+
+	**
+	*/
+}
+
+#ifdef FUTURE_RELEASE
+void riohalt( void )
+{
+	int host;
+	for ( host=0; host<p->RIONumHosts; host++ )
+	{
+		rio_dprintk (RIO_DEBUG_INIT, "Stop host %d\n", host);
+		(void)RIOBoardTest( p->RIOHosts[host].PaddrP, p->RIOHosts[host].Caddr, p->RIOHosts[host].Type,p->RIOHosts[host].Slot );
+	}
+}
+#endif
+#endif
+
+static	uchar	val[] = {
+#ifdef VERY_LONG_TEST
+	  0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+	  0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, 
+#endif
+	  0xff, 0x00, 0x00 };
+
+#define	TEST_END sizeof(val)
+
+/*
+** RAM test a board. 
+** Nothing too complicated, just enough to check it out.
+*/
+int
+RIOBoardTest(paddr, caddr, type, slot)
+paddr_t	paddr;
+caddr_t	caddr;
+uchar	type;
+int		slot;
+{
+	struct DpRam *DpRam = (struct DpRam *)caddr;
+	char *ram[4];
+	int  size[4];
+	int  op, bank;
+	int  nbanks;
+
+	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=0x%x, slot=%d\n",
+			type,(int)DpRam, slot);
+
+	RIOHostReset(type, DpRam, slot);
+
+	/*
+	** Scrub the memory. This comes in several banks:
+	** DPsram1	- 7000h bytes
+	** DPsram2	- 200h  bytes
+	** DPsram3	- 7000h bytes
+	** scratch	- 1000h bytes
+	*/
+
+	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n");
+
+	size[0] = DP_SRAM1_SIZE;
+	size[1] = DP_SRAM2_SIZE;
+	size[2] = DP_SRAM3_SIZE;
+	size[3] = DP_SCRATCH_SIZE;
+
+	ram[0] = (char *)&DpRam->DpSram1[0];
+	ram[1] = (char *)&DpRam->DpSram2[0];
+	ram[2] = (char *)&DpRam->DpSram3[0];
+	nbanks = (type == RIO_PCI) ? 3 : 4;
+	if (nbanks == 4)
+		ram[3] = (char *)&DpRam->DpScratch[0];
+
+
+	if (nbanks == 3) {
+		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n",
+				(int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2]);
+	} else {
+		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n",
+			(int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2], (int)ram[3], 
+					size[3]);
+	}
+
+	/*
+	** This scrub operation will test for crosstalk between
+	** banks. TEST_END is a magic number, and relates to the offset
+	** within the 'val' array used by Scrub.
+	*/
+	for (op=0; op<TEST_END; op++) {
+		for (bank=0; bank<nbanks; bank++) {
+			if (RIOScrub(op, (BYTE *)ram[bank], size[bank]) == RIO_FAIL) {
+				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: RIOScrub band %d, op %d failed\n", 
+							bank, op);
+				return RIO_FAIL;
+			}
+		}
+	}
+
+	rio_dprintk (RIO_DEBUG_INIT, "Test completed\n");
+	return RIO_SUCCESS;
+}
+
+
+/*
+** Scrub an area of RAM.
+** Define PRETEST and POSTTEST for a more thorough checking of the
+** state of the memory.
+** Call with op set to an index into the above 'val' array to determine
+** which value will be written into memory.
+** Call with op set to zero means that the RAM will not be read and checked
+** before it is written.
+** Call with op not zero, and the RAM will be read and compated with val[op-1]
+** to check that the data from the previous phase was retained.
+*/
+static int
+RIOScrub(op, ram, size)
+int		op;
+BYTE *	ram;
+int		size; 
+{
+	int				off;
+	unsigned char	oldbyte;
+	unsigned char	newbyte;
+	unsigned char	invbyte;
+	unsigned short	oldword;
+	unsigned short	newword;
+	unsigned short	invword;
+	unsigned short	swapword;
+
+	if (op) {
+		oldbyte = val[op-1];
+		oldword = oldbyte | (oldbyte<<8);
+	} else
+	  oldbyte = oldword = 0; /* Tell the compiler we've initilalized them. */
+	newbyte = val[op];
+	newword = newbyte | (newbyte<<8);
+	invbyte = ~newbyte;
+	invword = invbyte | (invbyte<<8);
+
+	/*
+	** Check that the RAM contains the value that should have been left there
+	** by the previous test (not applicable for pass zero)
+	*/
+	if (op) {
+		for (off=0; off<size; off++) {
+			if (RBYTE(ram[off]) != oldbyte) {
+				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 1: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, RBYTE(ram[off]));
+				return RIO_FAIL;
+			}
+		}
+		for (off=0; off<size; off+=2) {
+			if (*(ushort *)&ram[off] != oldword) {
+				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,oldword,*(ushort *)&ram[off]);
+				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1]));
+				return RIO_FAIL;
+			}
+		}
+	}
+
+	/*
+	** Now write the INVERSE of the test data into every location, using
+	** BYTE write operations, first checking before each byte is written
+	** that the location contains the old value still, and checking after
+	** the write that the location contains the data specified - this is
+	** the BYTE read/write test.
+	*/
+	for (off=0; off<size; off++) {
+		if (op && (RBYTE(ram[off]) != oldbyte)) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, RBYTE(ram[off]));
+			return RIO_FAIL;
+		}
+		WBYTE(ram[off],invbyte);
+		if (RBYTE(ram[off]) != invbyte) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Inv Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, invbyte, RBYTE(ram[off]));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** now, use WORD operations to write the test value into every location,
+	** check as before that the location contains the previous test value
+	** before overwriting, and that it contains the data value written
+	** afterwards.
+	** This is the WORD operation test.
+	*/
+	for (off=0; off<size; off+=2) {
+		if (*(ushort *)&ram[off] != invword) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: WORD at offset 0x%x should have been=%x, was=%x\n", off, invword, *(ushort *)&ram[off]);
+		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1]));
+			return RIO_FAIL;
+		}
+
+		*(ushort *)&ram[off] = newword;
+		if ( *(ushort *)&ram[off] != newword ) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, *(ushort *)&ram[off]);
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1]));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** now run through the block of memory again, first in byte mode
+	** then in word mode, and check that all the locations contain the
+	** required test data.
+	*/
+	for (off=0; off<size; off++) {
+		if (RBYTE(ram[off]) != newbyte) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Byte Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, RBYTE(ram[off]));
+			return RIO_FAIL;
+		}
+	}
+
+	for (off=0; off<size; off+=2) {
+		if ( *(ushort *)&ram[off] != newword ) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, *(ushort *)&ram[off]);
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1]));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** time to check out byte swapping errors
+	*/
+	swapword = invbyte | (newbyte << 8);
+
+	for (off=0; off<size; off+=2) {
+		WBYTE(ram[off],invbyte);
+		WBYTE(ram[off+1],newbyte);
+	}
+
+	for ( off=0; off<size; off+=2 ) {
+		if (*(ushort *)&ram[off] != swapword) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, swapword, *((ushort *)&ram[off]));
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1]));
+			return RIO_FAIL;
+		}
+		*((ushort *)&ram[off]) = ~swapword;
+	}
+
+	for (off=0; off<size; off+=2) {
+		if (RBYTE(ram[off]) != newbyte) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, RBYTE(ram[off]));
+			return RIO_FAIL;
+		}
+		if (RBYTE(ram[off+1]) != invbyte) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off+1, invbyte, RBYTE(ram[off+1]));
+			return RIO_FAIL;
+		}
+		*((ushort *)&ram[off]) = newword;
+	}
+	return RIO_SUCCESS;
+}
+
+/*
+** try to ensure that every host is either in polled mode
+** or is in interrupt mode. Only allow interrupt mode if
+** all hosts can interrupt (why?)
+** and force into polled mode if told to. Patch up the
+** interrupt vector & salute The Queen when you've done.
+*/
+#if 0
+static void
+RIOAllocateInterrupts(p)
+struct rio_info *	p;
+{
+	int Host;
+
+	/*
+	** Easy case - if we have been told to poll, then we poll.
+	*/
+	if (p->mode & POLLED_MODE) {
+		RIOStopInterrupts(p, 0, 0);
+		return;
+	}
+
+	/*
+	** check - if any host has been set to polled mode, then all must be.
+	*/
+	for (Host=0; Host<p->RIONumHosts; Host++) {
+		if ( (p->RIOHosts[Host].Type != RIO_AT) &&
+				(p->RIOHosts[Host].Ivec == POLLED) ) {
+			RIOStopInterrupts(p, 1, Host );
+			return;
+		}
+	}
+	for (Host=0; Host<p->RIONumHosts; Host++) {
+		if (p->RIOHosts[Host].Type == RIO_AT) {
+			if ( (p->RIOHosts[Host].Ivec - 32) == 0) {
+				RIOStopInterrupts(p, 2, Host );
+				return;
+			}
+		}
+	}
+}
+
+/*
+** something has decided that we can't be doing with these
+** new-fangled interrupt thingies. Set everything up to just
+** poll.
+*/
+static void
+RIOStopInterrupts(p, Reason, Host)
+struct rio_info *	p;
+int	Reason;
+int	Host; 
+{
+#ifdef FUTURE_RELEASE
+	switch (Reason) {
+		case 0:	/* forced into polling by rio_polled */
+			break;
+		case 1:	/* SCU has set 'Host' into polled mode */
+			break;
+		case 2:	/* there aren't enough interrupt vectors for 'Host' */
+			break;
+	}
+#endif
+
+	for (Host=0; Host<p->RIONumHosts; Host++ ) {
+		struct Host *HostP = &p->RIOHosts[Host];
+
+		switch (HostP->Type) {
+			case RIO_AT:
+				/*
+				** The AT host has it's interrupts disabled by clearing the
+				** int_enable bit.
+				*/
+				HostP->Mode &= ~INTERRUPT_ENABLE;
+				HostP->Ivec = POLLED;
+				break;
+#ifdef FUTURE_RELEASE
+			case RIO_EISA:
+				/*
+				** The EISA host has it's interrupts disabled by setting the
+				** Ivec to zero
+				*/
+				HostP->Ivec = POLLED;
+				break;
+#endif
+			case RIO_PCI:
+				/*
+				** The PCI host has it's interrupts disabled by clearing the
+				** int_enable bit, like a regular host card.
+				*/
+				HostP->Mode &= ~RIO_PCI_INT_ENABLE;
+				HostP->Ivec = POLLED;
+				break;
+#ifdef FUTURE_RELEASE
+			case RIO_MCA:
+				/*
+				** There's always one, isn't there?
+				** The MCA host card cannot have it's interrupts disabled.
+				*/
+				RIOPatchVec(HostP);
+				break;
+#endif
+		}
+	}
+}
+
+/*
+** This function is called at init time to setup the data structures.
+*/
+void
+RIOAllocDataStructs(p)
+struct rio_info *	p;
+{
+	int	port,
+		host,
+		tm;
+
+	p->RIOPortp = (struct Port *)sysbrk(RIO_PORTS * sizeof(struct Port));
+	if (!p->RIOPortp) {
+		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for port structures\n");
+		p->RIOFailed++;
+		return;
+	} 
+	bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS );
+	rio_dprintk (RIO_DEBUG_INIT,  "RIO-init: allocated and cleared memory for port structs\n");
+	rio_dprintk (RIO_DEBUG_INIT,  "First RIO port struct @0x%x, size=0x%x bytes\n",
+	    (int)p->RIOPortp, sizeof(struct Port));
+
+	for( port=0; port<RIO_PORTS; port++ ) {
+		p->RIOPortp[port].PortNum = port;
+		p->RIOPortp[port].TtyP = &p->channel[port];
+		sreset (p->RIOPortp[port].InUse);	/* Let the first guy uses it */
+		p->RIOPortp[port].portSem = -1;	/* Let the first guy takes it */
+		p->RIOPortp[port].ParamSem = -1;	/* Let the first guy takes it */
+		p->RIOPortp[port].timeout_id = 0;	/* Let the first guy takes it */
+	}
+
+	p->RIOHosts = (struct Host *)sysbrk(RIO_HOSTS * sizeof(struct Host));
+	if (!p->RIOHosts) {
+		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for host structures\n");
+		p->RIOFailed++;
+		return;
+	}
+	bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS);
+	rio_dprintk (RIO_DEBUG_INIT,  "RIO-init: allocated and cleared memory for host structs\n");
+	rio_dprintk (RIO_DEBUG_INIT,  "First RIO host struct @0x%x, size=0x%x bytes\n",
+	    (int)p->RIOHosts, sizeof(struct Host));
+
+	for( host=0; host<RIO_HOSTS; host++ ) {
+		spin_lock_init (&p->RIOHosts[host].HostLock);
+		p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */
+	}
+	/*
+	** check that the buffer size is valid, round down to the next power of
+	** two if necessary; if the result is zero, then, hey, no double buffers.
+	*/
+	for ( tm = 1; tm && tm <= p->RIOConf.BufferSize; tm <<= 1 )
+		;
+	tm >>= 1;
+	p->RIOBufferSize = tm;
+	p->RIOBufferMask = tm ? tm - 1 : 0;
+}
+
+/*
+** this function gets called whenever the data structures need to be
+** re-setup, for example, after a riohalt (why did I ever invent it?)
+*/
+void
+RIOSetupDataStructs(p)
+struct rio_info	* p;
+{
+	int host, entry, rup;
+
+	for ( host=0; host<RIO_HOSTS; host++ ) {
+		struct Host *HostP = &p->RIOHosts[host];
+		for ( entry=0; entry<LINKS_PER_UNIT; entry++ ) {
+			HostP->Topology[entry].Unit = ROUTE_DISCONNECT;
+			HostP->Topology[entry].Link = NO_LINK;
+		}
+		bcopy("HOST X", HostP->Name, 7);
+		HostP->Name[5] = '1'+host;
+		for (rup=0; rup<(MAX_RUP + LINKS_PER_UNIT); rup++) {
+			if (rup < MAX_RUP) {
+				for (entry=0; entry<LINKS_PER_UNIT; entry++ ) {
+					HostP->Mapping[rup].Topology[entry].Unit = ROUTE_DISCONNECT;
+					HostP->Mapping[rup].Topology[entry].Link = NO_LINK;
+				}
+				RIODefaultName(p, HostP, rup);
+			}
+			spin_lock_init(&HostP->UnixRups[rup].RupLock);
+		}
+	}
+}
+#endif
+
+int
+RIODefaultName(p, HostP, UnitId)
+struct rio_info *	p;
+struct Host *	HostP;
+uint			UnitId;
+{
+#ifdef CHECK
+	CheckHost( Host );
+	CheckUnitId( UnitId );
+#endif
+	bcopy("UNKNOWN RTA X-XX",HostP->Mapping[UnitId].Name,17);
+	HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
+	if ((UnitId+1) > 9) {
+		HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10);
+		HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10);
+	}
+	else {
+		HostP->Mapping[UnitId].Name[14]='1'+UnitId;
+		HostP->Mapping[UnitId].Name[15]=0;
+	}
+	return 0;
+}
+
+#define RIO_RELEASE	"Linux"
+#define RELEASE_ID	"1.0"
+
+#if 0
+static int
+RIOReport(p)
+struct rio_info *	p;
+{
+	char *	RIORelease = RIO_RELEASE;
+	char *	RIORelID = RELEASE_ID;
+	int		host;
+
+	rio_dprintk (RIO_DEBUG_INIT, "RIO : Release: %s ID: %s\n", RIORelease, RIORelID);
+
+	if ( p->RIONumHosts==0 ) {
+		rio_dprintk (RIO_DEBUG_INIT, "\nNo Hosts configured\n");
+		return(0);
+	}
+
+	for ( host=0; host < p->RIONumHosts; host++ ) {
+		struct Host *HostP = &p->RIOHosts[host];
+		switch ( HostP->Type ) {
+			case RIO_AT:
+				rio_dprintk (RIO_DEBUG_INIT, "AT BUS : found the card at 0x%x\n", HostP->PaddrP);
+		}
+	}
+	return 0;
+}
+#endif
+
+static struct rioVersion	stVersion;
+
+struct rioVersion *
+RIOVersid(void)
+{
+    strlcpy(stVersion.version, "RIO driver for linux V1.0",
+	    sizeof(stVersion.version));
+    strlcpy(stVersion.buildDate, __DATE__,
+	    sizeof(stVersion.buildDate));
+
+    return &stVersion;
+}
+
+#if 0
+int
+RIOMapin(paddr, size, vaddr)
+paddr_t		paddr;
+int			size;
+caddr_t *	vaddr;
+{
+	*vaddr = (caddr_t)permap( (long)paddr, size);
+	return ((int)*vaddr);
+}
+
+void
+RIOMapout(paddr, size, vaddr)
+paddr_t		paddr;
+long		size;
+caddr_t 	vaddr;
+{
+}
+#endif
+
+
+void
+RIOHostReset(Type, DpRamP, Slot)
+uint Type;
+volatile struct DpRam *DpRamP;
+uint Slot; 
+{
+	/*
+	** Reset the Tpu
+	*/
+	rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: type 0x%x", Type);
+	switch ( Type ) {
+		case RIO_AT:
+			rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n");
+			WBYTE(DpRamP->DpControl,  BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 
+					  INTERRUPT_DISABLE | BYTE_OPERATION |
+					  SLOW_LINKS | SLOW_AT_BUS);
+			WBYTE(DpRamP->DpResetTpu, 0xFF);
+			rio_udelay (3);
+
+			rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: Don't know if it worked. Try reset again\n");
+			WBYTE(DpRamP->DpControl,  BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
+					  INTERRUPT_DISABLE | BYTE_OPERATION |
+					  SLOW_LINKS | SLOW_AT_BUS);
+			WBYTE(DpRamP->DpResetTpu, 0xFF);
+			rio_udelay (3);
+			break;
+#ifdef FUTURE_RELEASE
+	case RIO_EISA:
+	/*
+	** Bet this doesn't work!
+	*/
+	OUTBZ( Slot, EISA_CONTROL_PORT,
+		EISA_TP_RUN		| EISA_TP_BUS_DISABLE   |
+		EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
+	OUTBZ( Slot, EISA_CONTROL_PORT,
+		EISA_TP_RESET	  | EISA_TP_BUS_DISABLE   | 
+		EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
+	suspend( 3 );
+	OUTBZ( Slot, EISA_CONTROL_PORT,
+		EISA_TP_RUN		| EISA_TP_BUS_DISABLE   | 
+		EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
+	break;
+	case RIO_MCA:
+	WBYTE(DpRamP->DpControl  , McaTpBootFromRam | McaTpBusDisable );
+	WBYTE(DpRamP->DpResetTpu , 0xFF );
+	suspend( 3 );
+	WBYTE(DpRamP->DpControl  , McaTpBootFromRam | McaTpBusDisable );
+	WBYTE(DpRamP->DpResetTpu , 0xFF );
+	suspend( 3 );
+		break;
+#endif
+	case RIO_PCI:
+		rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n");
+		DpRamP->DpControl  = RIO_PCI_BOOT_FROM_RAM;
+		DpRamP->DpResetInt = 0xFF;
+		DpRamP->DpResetTpu = 0xFF;
+		rio_udelay (100);
+		/* for (i=0; i<6000; i++);  */
+		/* suspend( 3 ); */
+		break;
+#ifdef FUTURE_RELEASE
+	default:
+	Rprintf(RIOMesgNoSupport,Type,DpRamP,Slot);
+	return;
+#endif
+
+	default:
+		rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n");
+		break;
+	}
+	return;
+}
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
new file mode 100644
index 0000000..e42e7b5
--- /dev/null
+++ b/drivers/char/rio/riointr.c
@@ -0,0 +1,951 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riointr.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:44
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)riointr.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_riointr_c_sccs_ = "@(#)riointr.c	1.2";
+#endif
+
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+#include <linux/delay.h>
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+
+
+static void RIOReceive(struct rio_info *, struct Port *);
+
+
+static char *firstchars (char *p, int nch)
+{
+  static char buf[2][128];
+  static int t=0;
+  t = ! t;
+  memcpy (buf[t], p, nch);
+  buf[t][nch] = 0;
+  return buf[t];
+}
+
+
+#define	INCR( P, I )	((P) = (((P)+(I)) & p->RIOBufferMask))
+/* Enable and start the transmission of packets */
+void
+RIOTxEnable(en)
+char *		en;
+{
+  struct Port *	PortP;
+  struct rio_info *p;
+  struct tty_struct* tty;
+  int c;
+  struct PKT *	PacketP;
+  unsigned long flags;
+
+  PortP = (struct Port *)en; 
+  p = (struct rio_info *)PortP->p;
+  tty = PortP->gs.tty;
+
+
+  rio_dprintk (RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", 
+	      PortP->PortNum, PortP->gs.xmit_cnt);
+
+  if (!PortP->gs.xmit_cnt) return;
+  
+
+  /* This routine is an order of magnitude simpler than the specialix
+     version. One of the disadvantages is that this version will send
+     an incomplete packet (usually 64 bytes instead of 72) once for
+     every 4k worth of data. Let's just say that this won't influence
+     performance significantly..... */
+
+  rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+  while (can_add_transmit( &PacketP, PortP )) {
+    c = PortP->gs.xmit_cnt;
+    if (c > PKT_MAX_DATA_LEN) c = PKT_MAX_DATA_LEN;
+
+    /* Don't copy past the end of the source buffer */
+    if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail) 
+      c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
+
+    { int t;
+    t = (c > 10)?10:c;
+    
+    rio_dprintk (RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", 
+		 PortP->PortNum, c, 
+		 firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail      , t),
+		 firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail + c-t, t));
+    }
+    /* If for one reason or another, we can't copy more data, 
+       we're done! */
+    if (c == 0) break;
+
+    rio_memcpy_toio (PortP->HostP->Caddr, (caddr_t)PacketP->data, 
+		 PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
+    /*    udelay (1); */
+
+    writeb (c, &(PacketP->len));
+    if (!( PortP->State & RIO_DELETED ) ) {
+      add_transmit ( PortP );
+      /*
+      ** Count chars tx'd for port statistics reporting
+      */
+      if ( PortP->statsGather )
+	PortP->txchars += c;
+    }
+    PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1);
+    PortP->gs.xmit_cnt -= c;
+  }
+
+  rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+  if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2*PKT_MAX_DATA_LEN)) {
+    rio_dprintk (RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....",
+		 (int)(PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)),
+		 PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); 
+    if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	PortP->gs.tty->ldisc.write_wakeup)
+      (PortP->gs.tty->ldisc.write_wakeup)(PortP->gs.tty);
+    rio_dprintk (RIO_DEBUG_INTR, "(%d/%d)\n",
+		PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); 
+    wake_up_interruptible(&PortP->gs.tty->write_wait);
+  }
+
+}
+
+
+/*
+** RIO Host Service routine. Does all the work traditionally associated with an
+** interrupt.
+*/
+static int	RupIntr;
+static int	RxIntr;
+static int	TxIntr;
+void
+RIOServiceHost(p, HostP, From)
+struct rio_info *	p;
+struct Host *HostP;
+int From; 
+{
+  rio_spin_lock (&HostP->HostLock);
+  if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) { 
+    static int t =0;
+    rio_spin_unlock (&HostP->HostLock); 
+    if ((t++ % 200) == 0)
+      rio_dprintk (RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int)HostP->Flags);
+    return;
+  }
+  rio_spin_unlock (&HostP->HostLock); 
+
+  if ( RWORD( HostP->ParmMapP->rup_intr ) ) {
+    WWORD( HostP->ParmMapP->rup_intr , 0 );
+    p->RIORupCount++;
+    RupIntr++;
+    rio_dprintk (RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP-p->RIOHosts);
+    RIOPollHostCommands(p, HostP );
+  }
+
+  if ( RWORD( HostP->ParmMapP->rx_intr ) ) {
+    int port;
+
+    WWORD( HostP->ParmMapP->rx_intr , 0 );
+    p->RIORxCount++;
+    RxIntr++;
+
+    rio_dprintk (RIO_DEBUG_INTR, "rio: RX interrupt on host %d\n", HostP-p->RIOHosts);
+    /*
+    ** Loop through every port. If the port is mapped into
+    ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
+    ** worth checking. If the port isn't open, grab any packets
+    ** hanging on its receive queue and stuff them on the free
+    ** list; check for commands on the way.
+    */
+    for ( port=p->RIOFirstPortsBooted; 
+	  port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {
+      struct Port *PortP = p->RIOPortp[port];
+      struct tty_struct *ttyP;
+      struct PKT *PacketP;
+		
+      /*
+      ** not mapped in - most of the RIOPortp[] information
+      ** has not been set up!
+      ** Optimise: ports come in bundles of eight.
+      */
+      if ( !PortP->Mapped ) {
+	port += 7;
+	continue; /* with the next port */
+      }
+
+      /*
+      ** If the host board isn't THIS host board, check the next one.
+      ** optimise: ports come in bundles of eight.
+      */
+      if ( PortP->HostP != HostP ) {
+	port += 7;
+	continue;
+      }
+
+      /*
+      ** Let us see - is the port open? If not, then don't service it.
+      */
+      if ( !( PortP->PortState & PORT_ISOPEN ) ) {
+	continue;
+      }
+
+      /*
+      ** find corresponding tty structure. The process of mapping
+      ** the ports puts these here.
+      */
+      ttyP = PortP->gs.tty;
+
+      /*
+      ** Lock the port before we begin working on it.
+      */
+      rio_spin_lock(&PortP->portSem);
+
+      /*
+      ** Process received data if there is any.
+      */
+      if ( can_remove_receive( &PacketP, PortP ) )
+	RIOReceive(p, PortP);
+
+      /*
+      ** If there is no data left to be read from the port, and
+      ** it's handshake bit is set, then we must clear the handshake,
+      ** so that that downstream RTA is re-enabled.
+      */
+      if ( !can_remove_receive( &PacketP, PortP ) && 
+	   ( RWORD( PortP->PhbP->handshake )==PHB_HANDSHAKE_SET ) ) {
+				/*
+				** MAGIC! ( Basically, handshake the RX buffer, so that
+				** the RTAs upstream can be re-enabled. )
+				*/
+	rio_dprintk (RIO_DEBUG_INTR, "Set RX handshake bit\n");
+	WWORD( PortP->PhbP->handshake, 
+	       PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET );
+      }
+      rio_spin_unlock(&PortP->portSem);
+    }
+  }
+
+  if ( RWORD( HostP->ParmMapP->tx_intr ) ) {
+    int port;
+
+    WWORD( HostP->ParmMapP->tx_intr , 0);
+
+    p->RIOTxCount++;
+    TxIntr++;
+    rio_dprintk (RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP-p->RIOHosts);
+
+    /*
+    ** Loop through every port.
+    ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
+    ** associated ) then it is worth checking.
+    */
+    for ( port=p->RIOFirstPortsBooted; 
+	  port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {
+      struct Port *PortP = p->RIOPortp[port];
+      struct tty_struct *ttyP;
+      struct PKT *PacketP;
+
+      /*
+      ** not mapped in - most of the RIOPortp[] information
+      ** has not been set up!
+      */
+      if ( !PortP->Mapped ) {
+	port += 7;
+	continue; /* with the next port */
+      }
+
+      /*
+      ** If the host board isn't running, then its data structures
+      ** are no use to us - continue quietly.
+      */
+      if ( PortP->HostP != HostP ) {
+	port += 7;
+	continue; /* with the next port */
+      }
+
+      /*
+      ** Let us see - is the port open? If not, then don't service it.
+      */
+      if ( !( PortP->PortState & PORT_ISOPEN ) ) {
+	continue;
+      }
+
+      rio_dprintk (RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
+      /*
+      ** Lock the port before we begin working on it.
+      */
+      rio_spin_lock(&PortP->portSem);
+
+      /*
+      ** If we can't add anything to the transmit queue, then
+      ** we need do none of this processing.
+      */
+      if ( !can_add_transmit( &PacketP, PortP ) ) {
+	rio_dprintk (RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
+	rio_spin_unlock(&PortP->portSem);
+	continue;
+      }
+
+      /*
+      ** find corresponding tty structure. The process of mapping
+      ** the ports puts these here.
+      */
+      ttyP = PortP->gs.tty;
+      /* If ttyP is NULL, the port is getting closed. Forget about it. */
+      if (!ttyP) {
+	rio_dprintk (RIO_DEBUG_INTR, "no tty, so skipping.\n");
+	rio_spin_unlock(&PortP->portSem);
+	continue;
+      }
+      /*
+      ** If there is more room available we start up the transmit
+      ** data process again. This can be direct I/O, if the cookmode
+      ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
+      ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
+      ** characters via the line discipline. We must always call
+      ** the line discipline,
+      ** so that user input characters can be echoed correctly.
+      **
+      ** ++++ Update +++++
+      ** With the advent of double buffering, we now see if
+      ** TxBufferOut-In is non-zero. If so, then we copy a packet
+      ** to the output place, and set it going. If this empties
+      ** the buffer, then we must issue a wakeup( ) on OUT.
+      ** If it frees space in the buffer then we must issue
+      ** a wakeup( ) on IN.
+      **
+      ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
+      ** have to send a WFLUSH command down the PHB, to mark the
+      ** end point of a WFLUSH. We also need to clear out any
+      ** data from the double buffer! ( note that WflushFlag is a
+      ** *count* of the number of WFLUSH commands outstanding! )
+      **
+      ** ++++ And there's more!
+      ** If an RTA is powered off, then on again, and rebooted,
+      ** whilst it has ports open, then we need to re-open the ports.
+      ** ( reasonable enough ). We can't do this when we spot the
+      ** re-boot, in interrupt time, because the queue is probably
+      ** full. So, when we come in here, we need to test if any
+      ** ports are in this condition, and re-open the port before
+      ** we try to send any more data to it. Now, the re-booted
+      ** RTA will be discarding packets from the PHB until it
+      ** receives this open packet, but don't worry tooo much
+      ** about that. The one thing that is interesting is the
+      ** combination of this effect and the WFLUSH effect!
+      */
+      /* For now don't handle RTA reboots. -- REW. 
+	 Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
+      if ( PortP->MagicFlags ) {
+#if 1
+	if ( PortP->MagicFlags & MAGIC_REBOOT ) {
+	  /*
+	  ** well, the RTA has been rebooted, and there is room
+	  ** on its queue to add the open packet that is required.
+	  **
+	  ** The messy part of this line is trying to decide if
+	  ** we need to call the Param function as a tty or as
+	  ** a modem.
+	  ** DONT USE CLOCAL AS A TEST FOR THIS!
+	  **
+	  ** If we can't param the port, then move on to the
+	  ** next port.
+	  */
+	  PortP->InUse = NOT_INUSE;
+
+	  rio_spin_unlock(&PortP->portSem);
+	  if ( RIOParam(PortP, OPEN, ((PortP->Cor2Copy & 
+				       (COR2_RTSFLOW|COR2_CTSFLOW ) )== 
+				      (COR2_RTSFLOW|COR2_CTSFLOW ) ) ? 
+			TRUE : FALSE, DONT_SLEEP ) == RIO_FAIL ) {
+	    continue; /* with next port */
+	  }
+	  rio_spin_lock(&PortP->portSem);
+	  PortP->MagicFlags &= ~MAGIC_REBOOT;
+	}
+#endif
+
+	/*
+	** As mentioned above, this is a tacky hack to cope
+	** with WFLUSH
+	*/
+	if ( PortP->WflushFlag ) {
+	  rio_dprintk (RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
+
+	  if ( PortP->InUse )
+	    rio_dprintk (RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
+	}
+				
+	while ( PortP->WflushFlag &&
+		can_add_transmit( &PacketP, PortP ) && 
+		( PortP->InUse == NOT_INUSE ) ) {
+	  int p;
+	  struct PktCmd *PktCmdP;
+
+	  rio_dprintk (RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
+	  /*
+	  ** make it look just like a WFLUSH command
+	  */
+	  PktCmdP = ( struct PktCmd * )&PacketP->data[0];
+
+	  WBYTE( PktCmdP->Command , WFLUSH );
+
+	  p =  PortP->HostPort % ( ushort )PORTS_PER_RTA;
+
+	  /*
+	  ** If second block of ports for 16 port RTA, add 8
+	  ** to index 8-15.
+	  */
+	  if ( PortP->SecondBlock )
+	    p += PORTS_PER_RTA;
+
+	  WBYTE( PktCmdP->PhbNum, p );
+
+	  /*
+	  ** to make debuggery easier
+	  */
+	  WBYTE( PacketP->data[ 2], 'W'  );
+	  WBYTE( PacketP->data[ 3], 'F'  );
+	  WBYTE( PacketP->data[ 4], 'L'  );
+	  WBYTE( PacketP->data[ 5], 'U'  );
+	  WBYTE( PacketP->data[ 6], 'S'  );
+	  WBYTE( PacketP->data[ 7], 'H'  );
+	  WBYTE( PacketP->data[ 8], ' '  );
+	  WBYTE( PacketP->data[ 9], '0'+PortP->WflushFlag );
+	  WBYTE( PacketP->data[10], ' '  );
+	  WBYTE( PacketP->data[11], ' '  );
+	  WBYTE( PacketP->data[12], '\0' );
+
+	  /*
+	  ** its two bytes long!
+	  */
+	  WBYTE( PacketP->len , PKT_CMD_BIT | 2 );
+
+	  /*
+	  ** queue it!
+	  */
+	  if ( !( PortP->State & RIO_DELETED ) ) {
+	    add_transmit( PortP );
+	    /*
+	    ** Count chars tx'd for port statistics reporting
+	    */
+	    if ( PortP->statsGather )
+	      PortP->txchars += 2;
+	  }
+
+	  if ( --( PortP->WflushFlag ) == 0 ) {
+	    PortP->MagicFlags &= ~MAGIC_FLUSH;
+	  }
+
+	  rio_dprintk (RIO_DEBUG_INTR, "Wflush count now stands at %d\n", 
+		 PortP->WflushFlag);
+	}
+	if ( PortP->MagicFlags & MORE_OUTPUT_EYGOR ) {
+	  if ( PortP->MagicFlags & MAGIC_FLUSH ) {
+	    PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+	  }
+	  else {
+	    if ( !can_add_transmit( &PacketP, PortP ) ) {
+	      rio_spin_unlock(&PortP->portSem);
+	      continue;
+	    }
+	    rio_spin_unlock(&PortP->portSem);
+	    RIOTxEnable((char *)PortP);
+	    rio_spin_lock(&PortP->portSem);
+	    PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+	  }
+	}
+      }
+
+
+      /*
+      ** If we can't add anything to the transmit queue, then
+      ** we need do none of the remaining processing.
+      */
+      if (!can_add_transmit( &PacketP, PortP ) ) {
+	rio_spin_unlock(&PortP->portSem);
+	continue;
+      }
+
+      rio_spin_unlock(&PortP->portSem);
+      RIOTxEnable((char *)PortP);
+    }
+  }
+}
+
+/*
+** Routine for handling received data for clist drivers.
+** NB: Called with the tty locked. The spl from the lockb( ) is passed.
+** we return the ttySpl level that we re-locked at.
+*/
+static void
+RIOReceive(p, PortP)
+struct rio_info *	p;
+struct Port *		PortP;
+{
+  struct tty_struct *TtyP;
+  register ushort transCount;
+  struct PKT *PacketP;
+  register uint	DataCnt;
+  uchar *	ptr;
+  int copied =0;
+
+  static int intCount, RxIntCnt;
+
+  /*
+  ** The receive data process is to remove packets from the
+  ** PHB until there aren't any more or the current cblock
+  ** is full. When this occurs, there will be some left over
+  ** data in the packet, that we must do something with.
+  ** As we haven't unhooked the packet from the read list
+  ** yet, we can just leave the packet there, having first
+  ** made a note of how far we got. This means that we need
+  ** a pointer per port saying where we start taking the
+  ** data from - this will normally be zero, but when we
+  ** run out of space it will be set to the offset of the
+  ** next byte to copy from the packet data area. The packet
+  ** length field is decremented by the number of bytes that
+  ** we succesfully removed from the packet. When this reaches
+  ** zero, we reset the offset pointer to be zero, and free
+  ** the packet from the front of the queue.
+  */
+
+  intCount++;
+
+  TtyP = PortP->gs.tty;
+  if (!TtyP) {
+    rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
+    return;
+  }
+
+  if (PortP->State & RIO_THROTTLE_RX) {
+    rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
+    return;
+  }
+
+  if ( PortP->State & RIO_DELETED )
+    {
+      while ( can_remove_receive( &PacketP, PortP ) )
+	{
+	  remove_receive( PortP );
+	  put_free_end( PortP->HostP, PacketP );
+	}
+    }
+  else
+    {
+      /*
+      ** loop, just so long as:
+      **   i ) there's some data ( i.e. can_remove_receive )
+      **  ii ) we haven't been blocked
+      ** iii ) there's somewhere to put the data
+      **  iv ) we haven't outstayed our welcome
+      */
+      transCount = 1;
+      while ( can_remove_receive(&PacketP, PortP)
+	      && transCount)
+	{
+#ifdef STATS
+	  PortP->Stat.RxIntCnt++;
+#endif /* STATS */
+	  RxIntCnt++;
+
+	  /*
+	  ** check that it is not a command!
+	  */
+	  if ( PacketP->len & PKT_CMD_BIT ) {
+	    rio_dprintk (RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
+	    /*	    rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */
+	    rio_dprintk (RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit);
+	    rio_dprintk (RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port);
+	    rio_dprintk (RIO_DEBUG_INTR, " src_unit  = %d\n", PacketP->src_unit);
+	    rio_dprintk (RIO_DEBUG_INTR, " src_port  = %d\n", PacketP->src_port);
+	    rio_dprintk (RIO_DEBUG_INTR, " len	   = %d\n", PacketP->len);
+	    rio_dprintk (RIO_DEBUG_INTR, " control   = %d\n", PacketP->control);
+	    rio_dprintk (RIO_DEBUG_INTR, " csum	   = %d\n", PacketP->csum);
+	    rio_dprintk (RIO_DEBUG_INTR, "	 data bytes: ");
+	    for ( DataCnt=0; DataCnt<PKT_MAX_DATA_LEN; DataCnt++ )
+	      rio_dprintk (RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]);
+	    remove_receive( PortP );
+	    put_free_end( PortP->HostP, PacketP );
+	    continue; /* with next packet */
+	  }
+
+	  /*
+	  ** How many characters can we move 'upstream' ?
+	  **
+	  ** Determine the minimum of the amount of data
+	  ** available and the amount of space in which to
+	  ** put it.
+	  **
+	  ** 1.	Get the packet length by masking 'len'
+	  **	for only the length bits.
+	  ** 2.	Available space is [buffer size] - [space used]
+	  **
+	  ** Transfer count is the minimum of packet length
+	  ** and available space.
+	  */
+			
+	  transCount = min_t(unsigned int, PacketP->len & PKT_LEN_MASK,
+			   TTY_FLIPBUF_SIZE - TtyP->flip.count);
+	  rio_dprintk (RIO_DEBUG_REC,  "port %d: Copy %d bytes\n", 
+				      PortP->PortNum, transCount);
+	  /*
+	  ** To use the following 'kkprintfs' for debugging - change the '#undef'
+	  ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
+	  ** driver).
+	  */
+#undef ___DEBUG_IT___
+#ifdef ___DEBUG_IT___
+	  kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ",
+		   intCount,
+		   RxIntCnt,
+		   PortP->PortNum,
+		   TtyP->rxqueue.count,
+		   transCount,
+		   TtyP->flags );
+#endif
+	  ptr = (uchar *) PacketP->data + PortP->RxDataStart;
+
+	  rio_memcpy_fromio (TtyP->flip.char_buf_ptr, ptr, transCount);
+	  memset(TtyP->flip.flag_buf_ptr, TTY_NORMAL, transCount);
+
+#ifdef STATS
+	  /*
+	  ** keep a count for statistical purposes
+	  */
+	  PortP->Stat.RxCharCnt	+= transCount;
+#endif
+	  PortP->RxDataStart	+= transCount;
+	  PacketP->len		-= transCount;
+	  copied += transCount;
+	  TtyP->flip.count += transCount;
+	  TtyP->flip.char_buf_ptr += transCount;
+	  TtyP->flip.flag_buf_ptr += transCount;
+
+
+#ifdef ___DEBUG_IT___
+	  kkprintf("T:%d L:%d\n", DataCnt, PacketP->len );
+#endif
+
+	  if ( PacketP->len == 0 )
+	    {
+				/*
+				** If we have emptied the packet, then we can
+				** free it, and reset the start pointer for
+				** the next packet.
+				*/
+	      remove_receive( PortP );
+	      put_free_end( PortP->HostP, PacketP );
+	      PortP->RxDataStart = 0;
+#ifdef STATS
+				/*
+				** more lies ( oops, I mean statistics )
+				*/
+	      PortP->Stat.RxPktCnt++;
+#endif /* STATS */
+	    }
+	}
+    }
+  if (copied) {
+    rio_dprintk (RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
+    tty_flip_buffer_push (TtyP);
+  }
+
+  return;
+}
+
+#ifdef FUTURE_RELEASE
+/*
+** The proc routine called by the line discipline to do the work for it.
+** The proc routine works hand in hand with the interrupt routine.
+*/
+int
+riotproc(p, tp, cmd, port)
+struct rio_info *	p;
+register struct ttystatics *tp;
+int cmd;
+int	port;
+{
+	register struct Port *PortP;
+	int SysPort;
+	struct PKT *PacketP;
+
+	SysPort = port;	/* Believe me, it works. */
+
+	if ( SysPort < 0 || SysPort >= RIO_PORTS ) {
+		rio_dprintk (RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n",SysPort);
+		return 0;
+	}
+	PortP = p->RIOPortp[SysPort];
+
+	if ((uint)PortP->PhbP < (uint)PortP->Caddr || 
+			(uint)PortP->PhbP >= (uint)PortP->Caddr+SIXTY_FOUR_K ) {
+		rio_dprintk (RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n",
+							SysPort);
+		rio_dprintk (RIO_DEBUG_INTR, "	 PortP = 0x%x\n",PortP);
+		rio_dprintk (RIO_DEBUG_INTR, "	 PortP->PhbP = 0x%x\n",PortP->PhbP);
+		rio_dprintk (RIO_DEBUG_INTR, "	 PortP->Caddr = 0x%x\n",PortP->PhbP);
+		rio_dprintk (RIO_DEBUG_INTR, "	 PortP->HostPort = 0x%x\n",PortP->HostPort);
+		return 0;
+	}
+
+	switch(cmd) {
+		case T_WFLUSH:
+			rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH\n");
+			/*
+			** Because of the spooky way the RIO works, we don't need
+			** to issue a flush command on any of the SET*F commands,
+			** as that causes trouble with getty and login, which issue
+			** these commands to incur a READ flush, and rely on the fact
+			** that the line discipline does a wait for drain for them.
+			** As the rio doesn't wait for drain, the write flush would
+			** destroy the Password: prompt. This isn't very friendly, so
+			** here we only issue a WFLUSH command if we are in the interrupt
+			** routine, or we aren't executing a SET*F command.
+			*/
+			if ( PortP->HostP->InIntr || !PortP->FlushCmdBodge ) {
+				/*
+				** form a wflush packet - 1 byte long, no data
+				*/
+				if ( PortP->State & RIO_DELETED ) {
+					rio_dprintk (RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n");
+				}
+				else {
+					if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) {
+						rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command failed\n");
+					}
+					else
+						rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command\n");
+				}
+				/*
+				** WFLUSH operation - flush the data!
+				*/
+				PortP->TxBufferIn = PortP->TxBufferOut = 0;
+			}
+			else {
+				rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n");
+			}
+			/*
+			** sort out the line discipline
+			*/
+			if (PortP->CookMode == COOK_WELL)
+				goto start;
+			break;
+	
+		case T_RESUME:
+			rio_dprintk (RIO_DEBUG_INTR, "T_RESUME\n");
+			/*
+			** send pre-emptive resume packet
+			*/
+			if ( PortP->State & RIO_DELETED ) {
+				rio_dprintk (RIO_DEBUG_INTR, "RESUME on deleted RTA\n");
+			}
+			else {
+				if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) {
+					rio_dprintk (RIO_DEBUG_INTR, "T_RESUME Command failed\n");
+				}
+			}
+			/*
+			** and re-start the sender software!
+			*/
+			if (PortP->CookMode == COOK_WELL)
+				goto start;
+			break;
+	
+		case T_TIME:
+			rio_dprintk (RIO_DEBUG_INTR, "T_TIME\n");
+			/*
+			** T_TIME is called when xDLY is set in oflags and
+			** the line discipline timeout has expired. It's
+			** function in life is to clear the TIMEOUT flag
+			** and to re-start output to the port.
+			*/
+			/*
+			** Fall through and re-start output
+			*/
+		case T_OUTPUT:
+start:
+			if ( PortP->MagicFlags & MAGIC_FLUSH ) {
+				PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+				return 0;
+			}
+			RIOTxEnable((char *)PortP);
+			PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+			/*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n");*/
+			break;
+	
+		case T_SUSPEND:
+			rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND\n");
+			/*
+			** send a suspend pre-emptive packet.
+			*/
+			if ( PortP->State & RIO_DELETED ) {
+				rio_dprintk (RIO_DEBUG_INTR, "SUSPEND deleted RTA\n");
+			}
+			else {
+				if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) {
+					rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND Command failed\n");
+				}
+			}
+			/*
+			** done!
+			*/
+			break;
+	
+		case T_BLOCK:
+			rio_dprintk (RIO_DEBUG_INTR, "T_BLOCK\n");
+			break;
+	
+		case T_RFLUSH:
+			rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH\n");
+			if ( PortP->State & RIO_DELETED ) {
+				rio_dprintk (RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n");
+				PortP->RxDataStart = 0;
+			}
+			else {
+				if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) {
+					rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH Command failed\n");
+					return 0;
+				}
+				PortP->RxDataStart = 0;
+				while ( can_remove_receive(&PacketP, PortP) ) {
+					remove_receive(PortP);
+					ShowPacket(DBG_PROC, PacketP );
+					put_free_end(PortP->HostP, PacketP );
+				}
+				if ( PortP->PhbP->handshake == PHB_HANDSHAKE_SET ) {
+					/*
+					** MAGIC!
+					*/
+					rio_dprintk (RIO_DEBUG_INTR, "Set receive handshake bit\n");
+					PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET;
+				}
+			}
+			break;
+			/* FALLTHROUGH */
+		case T_UNBLOCK:
+			rio_dprintk (RIO_DEBUG_INTR, "T_UNBLOCK\n");
+			/*
+			** If there is any data to receive set a timeout to service it.
+			*/
+			RIOReceive(p, PortP);
+			break;
+	
+		case T_BREAK:
+			rio_dprintk (RIO_DEBUG_INTR, "T_BREAK\n");
+			/*
+			** Send a break command. For Sys V
+			** this is a timed break, so we
+			** send a SBREAK[time] packet
+			*/
+			/*
+			** Build a BREAK command
+			*/
+			if ( PortP->State & RIO_DELETED ) {
+				rio_dprintk (RIO_DEBUG_INTR, "BREAK on deleted RTA\n");
+			}
+			else {
+				if (RIOShortCommand(PortP,SBREAK,2,
+								p->RIOConf.BreakInterval)==RIO_FAIL) {
+			   		rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+				}
+			}
+	
+			/*
+			** done!
+			*/
+			break;
+	
+		case T_INPUT:
+			rio_dprintk (RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n");
+			break;
+		case T_PARM:
+			rio_dprintk (RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n");
+			break;
+	
+		case T_SWTCH:
+			rio_dprintk (RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n");
+			break;
+	
+		default:
+			rio_dprintk (RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n",cmd);
+	}
+	/*
+	** T_OUTPUT returns without passing through this point!
+	*/
+	/*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n");*/
+	return(0);
+}
+#endif
diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h
new file mode 100644
index 0000000..c3d6797
--- /dev/null
+++ b/drivers/char/rio/rioioctl.h
@@ -0,0 +1,103 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioioctl.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)rioioctl.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rioioctl_h__
+#define	__rioioctl_h__
+
+#ifdef SCCS_LABELS
+static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h	1.2";
+#endif
+
+/*
+** RIO device driver - user ioctls and associated structures.
+*/
+
+struct portStats {
+	int	port;
+	int	gather;
+	ulong	txchars;
+	ulong	rxchars;
+	ulong	opens;
+	ulong	closes;
+	ulong	ioctls;
+}; 
+
+
+#define rIOC	('r'<<8)
+#define	TCRIOSTATE	(rIOC | 1)
+#define	TCRIOXPON	(rIOC | 2)
+#define	TCRIOXPOFF	(rIOC | 3)
+#define	TCRIOXPCPS	(rIOC | 4)
+#define	TCRIOXPRINT	(rIOC | 5)
+#define TCRIOIXANYON	(rIOC | 6)
+#define	TCRIOIXANYOFF	(rIOC | 7)
+#define TCRIOIXONON	(rIOC | 8)
+#define	TCRIOIXONOFF	(rIOC | 9)
+#define	TCRIOMBIS	(rIOC | 10)
+#define	TCRIOMBIC	(rIOC | 11)
+#define	TCRIOTRIAD	(rIOC | 12)
+#define TCRIOTSTATE	(rIOC | 13)
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** Add RIO ioctls for manipulating RTS and CTS flow control, (as LynxOS
+** appears to not support hardware flow control).
+*/
+#define TCRIOCTSFLOWEN	(rIOC | 14)	/* enable CTS flow control */
+#define TCRIOCTSFLOWDIS	(rIOC | 15)	/* disable CTS flow control */
+#define TCRIORTSFLOWEN	(rIOC | 16)	/* enable RTS flow control */
+#define TCRIORTSFLOWDIS	(rIOC | 17)	/* disable RTS flow control */
+
+/*
+** 09.12.1998 ARG - ESIL 0776 part fix
+** Definition for 'RIOC' also appears in daemon.h, so we'd better do a
+** #ifndef here first.
+** 'RIO_QUICK_CHECK' also #define'd here as this ioctl is now
+** allowed to be used by customers.
+**
+** 05.02.1999 ARG -
+** This is what I've decied to do with ioctls etc., which are intended to be
+** invoked from users applications :
+** Anything that needs to be defined here will be removed from daemon.h, that
+** way it won't end up having to be defined/maintained in two places. The only
+** consequence of this is that this file should now be #include'd by daemon.h
+**
+** 'stats' ioctls now #define'd here as they are to be used by customers.
+*/
+#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
+
+#define	RIO_QUICK_CHECK	  	(RIOC | 105)
+#define RIO_GATHER_PORT_STATS	(RIOC | 193)
+#define RIO_RESET_PORT_STATS	(RIOC | 194)
+#define RIO_GET_PORT_STATS	(RIOC | 195)
+
+#endif	/* __rioioctl_h__ */
diff --git a/drivers/char/rio/riolocks.h b/drivers/char/rio/riolocks.h
new file mode 100644
index 0000000..0e0cdac
--- /dev/null
+++ b/drivers/char/rio/riolocks.h
@@ -0,0 +1,43 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riolocks.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)riolocks.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_riolocks_h__
+#define	__rio_riolocks_h__
+
+#ifdef SCCS_LABELS
+static char *_riolocks_h_sccs_ = "@(#)riolocks.h	1.2";
+#endif
+
+#define LOCKB(lk)		lockb(lk);
+#define UNLOCKB(lk, oldspl)	unlockb(lk, oldspl);
+
+#endif
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
new file mode 100644
index 0000000..f109163
--- /dev/null
+++ b/drivers/char/rio/rioparam.c
@@ -0,0 +1,744 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioparam.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:45
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)rioparam.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifdef SCCS_LABELS
+static char *_rioparam_c_sccs_ = "@(#)rioparam.c	1.3";
+#endif
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+
+
+
+/*
+** The Scam, based on email from jeremyr@bugs.specialix.co.uk....
+**
+** To send a command on a particular port, you put a packet with the
+** command bit set onto the port. The command bit is in the len field,
+** and gets ORed in with the actual byte count.
+**
+** When you send a packet with the command bit set, then the first
+** data byte ( data[0] ) is interpretted as the command to execute.
+** It also governs what data structure overlay should accompany the packet.
+** Commands are defined in cirrus/cirrus.h
+**
+** If you want the command to pre-emt data already on the queue for the
+** port, set the pre-emptive bit in conjunction with the command bit.
+** It is not defined what will happen if you set the preemptive bit
+** on a packet that is NOT a command.
+**
+** Pre-emptive commands should be queued at the head of the queue using
+** add_start(), whereas normal commands and data are enqueued using
+** add_end().
+**
+** Most commands do not use the remaining bytes in the data array. The
+** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and
+** OPEN are currently analagous). With these three commands the following
+** 11 data bytes are all used to pass config information such as baud rate etc.
+** The fields are also defined in cirrus.h. Some contain straightforward
+** information such as the transmit XON character. Two contain the transmit and
+** receive baud rates respectively. For most baud rates there is a direct
+** mapping between the rates defined in <sys/termio.h> and the byte in the
+** packet. There are additional (non UNIX-standard) rates defined in
+** /u/dos/rio/cirrus/h/brates.h.
+**
+** The rest of the data fields contain approximations to the Cirrus registers
+** that are used to program number of bits etc. Each registers bit fields is
+** defined in cirrus.h.
+** 
+** NB. Only use those bits that are defined as being driver specific
+** or common to the RTA and the driver.
+** 
+** All commands going from RTA->Host will be dealt with by the Host code - you
+** will never see them. As with the SI there will be three fields to look out
+** for in each phb (not yet defined - needs defining a.s.a.p).
+** 
+** modem_status	- current state of handshake pins.
+**
+** port_status	 - current port status - equivalent to hi_stat for SI, indicates
+** if port is IDLE_OPEN, IDLE_CLOSED etc.
+**
+** break_status	- bit X set if break has been received.
+** 
+** Happy hacking.
+** 
+*/
+
+/* 
+** RIOParam is used to open or configure a port. You pass it a PortP,
+** which will have a tty struct attached to it. You also pass a command,
+** either OPEN or CONFIG. The port's setup is taken from the t_ fields
+** of the tty struct inside the PortP, and the port is either opened
+** or re-configured. You must also tell RIOParam if the device is a modem
+** device or not (i.e. top bit of minor number set or clear - take special
+** care when deciding on this!).
+** RIOParam neither flushes nor waits for drain, and is NOT preemptive.
+**
+** RIOParam assumes it will be called at splrio(), and also assumes
+** that CookMode is set correctly in the port structure.
+**
+** NB. for MPX
+**	tty lock must NOT have been previously acquired.
+*/
+int
+RIOParam(PortP, cmd, Modem, SleepFlag)
+struct Port *PortP;
+int cmd;
+int Modem;
+int SleepFlag; 
+{
+	register struct tty_struct *TtyP;
+	int	retval;
+	register struct phb_param *phb_param_ptr;
+	PKT *PacketP;
+	int res;
+	uchar Cor1=0, Cor2=0, Cor4=0, Cor5=0;
+	uchar TxXon=0, TxXoff=0, RxXon=0, RxXoff=0;
+	uchar LNext=0, TxBaud=0, RxBaud=0;
+	int		retries = 0xff;
+	unsigned long flags;
+
+	func_enter ();
+
+	TtyP = PortP->gs.tty;
+
+	rio_dprintk (RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n",
+	    PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
+
+	if (!TtyP) {
+	  rio_dprintk (RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
+
+	  func_exit ();
+
+	  return RIO_FAIL;
+	}
+	rio_spin_lock_irqsave(&PortP->portSem, flags );
+
+	if (cmd == OPEN) {
+		/*
+		** If the port is set to store or lock the parameters, and it is
+		** paramed with OPEN, we want to restore the saved port termio, but
+		** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
+		*/
+#if 0
+		if (PortP->FirstOpen) {
+			PortP->StoredTty.iflag = TtyP->tm.c_iflag;
+			PortP->StoredTty.oflag = TtyP->tm.c_oflag;
+			PortP->StoredTty.cflag = TtyP->tm.c_cflag;
+			PortP->StoredTty.lflag = TtyP->tm.c_lflag;
+			PortP->StoredTty.line = TtyP->tm.c_line;
+			for (i = 0; i < NCC + 5; i++)
+				PortP->StoredTty.cc[i] = TtyP->tm.c_cc[i];
+			PortP->FirstOpen = 0;
+		}
+		else if (PortP->Store || PortP->Lock) {
+			rio_dprintk (RIO_DEBUG_PARAM, "OPEN: Restoring stored/locked params\n");
+			TtyP->tm.c_iflag = PortP->StoredTty.iflag;
+			TtyP->tm.c_oflag = PortP->StoredTty.oflag;
+			TtyP->tm.c_cflag = PortP->StoredTty.cflag;
+			TtyP->tm.c_lflag = PortP->StoredTty.lflag;
+			TtyP->tm.c_line = PortP->StoredTty.line;
+			for (i = 0; i < NCC + 5; i++)
+				TtyP->tm.c_cc[i] = PortP->StoredTty.cc[i];
+		}
+#endif
+	}
+
+	/*
+	** wait for space
+	*/
+	while ( !(res=can_add_transmit(&PacketP,PortP)) || 
+			(PortP->InUse != NOT_INUSE) ) {
+		if (retries -- <= 0) {
+			break;
+		}
+		if ( PortP->InUse != NOT_INUSE ) {
+			rio_dprintk (RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
+		}
+
+		if ( !res ) {
+			rio_dprintk (RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
+		}
+
+		if ( SleepFlag != OK_TO_SLEEP ) {
+			rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+			func_exit();
+			
+			return RIO_FAIL;
+		}
+
+		rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
+		rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+		retval = RIODelay(PortP, HUNDRED_MS);
+		rio_spin_lock_irqsave( &PortP->portSem, flags);
+		if (retval == RIO_FAIL) {
+			rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
+			rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+			pseterr(EINTR);
+			func_exit();
+
+			return RIO_FAIL;
+		}
+		if ( PortP->State & RIO_DELETED ) {
+			rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+			func_exit ();
+
+			return RIO_SUCCESS;
+		}
+	}
+
+	if (!res) {
+		rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+		func_exit ();
+
+		return RIO_FAIL;
+	}
+
+	rio_dprintk (RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n",res);
+	rio_dprintk (RIO_DEBUG_PARAM, "Packet is 0x%x\n",(int) PacketP);
+
+	phb_param_ptr = (struct phb_param *)PacketP->data;
+
+
+#if 0
+	/*
+	** COR 1
+	*/
+	if ( TtyP->tm.c_iflag & INPCK ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Parity checking on input enabled\n");
+		Cor1 |= COR1_INPCK;
+	}
+#endif
+
+	switch ( TtyP->termios->c_cflag & CSIZE ) {
+		case CS5:
+		{
+			rio_dprintk (RIO_DEBUG_PARAM, "5 bit data\n");
+			Cor1 |= COR1_5BITS;
+			break;
+		}
+		case CS6:
+		{
+			rio_dprintk (RIO_DEBUG_PARAM, "6 bit data\n");
+			Cor1 |= COR1_6BITS;
+			break;
+		}
+		case CS7:
+		{
+			rio_dprintk (RIO_DEBUG_PARAM, "7 bit data\n");
+			Cor1 |= COR1_7BITS;
+			break;
+		}
+		case CS8:
+		{
+			rio_dprintk (RIO_DEBUG_PARAM, "8 bit data\n");
+			Cor1 |= COR1_8BITS;
+			break;
+		}
+	}
+
+	if ( TtyP->termios->c_cflag & CSTOPB ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "2 stop bits\n");
+		Cor1 |= COR1_2STOP;
+	}
+	else {
+		rio_dprintk (RIO_DEBUG_PARAM, "1 stop bit\n");
+		Cor1 |= COR1_1STOP;
+	}
+
+	if ( TtyP->termios->c_cflag & PARENB ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable parity\n");
+		Cor1 |= COR1_NORMAL;
+	}
+	else {
+		rio_dprintk (RIO_DEBUG_PARAM, "Disable parity\n");
+		Cor1 |= COR1_NOP;
+	}
+	if ( TtyP->termios->c_cflag & PARODD ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Odd parity\n");
+		Cor1 |= COR1_ODD;
+	}
+	else {
+		rio_dprintk (RIO_DEBUG_PARAM, "Even parity\n");
+		Cor1 |= COR1_EVEN; 
+	}
+
+	/*
+	** COR 2
+	*/
+	if ( TtyP->termios->c_iflag & IXON ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop output control\n");
+		Cor2 |= COR2_IXON;
+	}
+	else {
+		if ( PortP->Config & RIO_IXON ) {
+			rio_dprintk (RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
+			Cor2 |= COR2_IXON;
+		}
+		else
+			rio_dprintk (RIO_DEBUG_PARAM, "IXON has been disabled.\n");
+	}
+
+	if (TtyP->termios->c_iflag & IXANY) {
+		if ( PortP->Config & RIO_IXANY ) {
+			rio_dprintk (RIO_DEBUG_PARAM, "Enable any key to restart output\n");
+			Cor2 |= COR2_IXANY;
+		}
+		else
+			rio_dprintk (RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
+	}
+
+	if ( TtyP->termios->c_iflag & IXOFF ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
+		Cor2 |= COR2_IXOFF;
+	}
+
+	if ( TtyP->termios->c_cflag & HUPCL ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Hangup on last close\n");
+		Cor2 |= COR2_HUPCL;
+	}
+
+	if ( C_CRTSCTS (TtyP)) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
+		Cor2 |= COR2_CTSFLOW;
+		Cor2 |= COR2_RTSFLOW;
+	} else {
+		rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
+		Cor2 &= ~COR2_CTSFLOW;
+		Cor2 &= ~COR2_RTSFLOW;
+	}
+
+
+	if ( TtyP->termios->c_cflag & CLOCAL ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Local line\n");
+	}
+	else {
+		rio_dprintk (RIO_DEBUG_PARAM, "Possible Modem line\n");
+	}
+
+	/*
+	** COR 4 (there is no COR 3)
+	*/
+	if ( TtyP->termios->c_iflag & IGNBRK ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Ignore break condition\n");
+		Cor4 |= COR4_IGNBRK;
+	}
+	if ( !(TtyP->termios->c_iflag & BRKINT) ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Break generates NULL condition\n");
+		Cor4 |= COR4_NBRKINT;
+	} else {
+		rio_dprintk (RIO_DEBUG_PARAM, "Interrupt on	break condition\n");
+	}
+
+	if ( TtyP->termios->c_iflag & INLCR ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
+		Cor4 |= COR4_INLCR;
+	}
+
+	if ( TtyP->termios->c_iflag & IGNCR ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
+		Cor4 |= COR4_IGNCR;
+	}
+
+	if ( TtyP->termios->c_iflag & ICRNL ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
+		Cor4 |= COR4_ICRNL;
+	}
+	if ( TtyP->termios->c_iflag & IGNPAR ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
+		Cor4 |= COR4_IGNPAR;
+	}
+	if ( TtyP->termios->c_iflag & PARMRK ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Mark parity errors\n");
+		Cor4 |= COR4_PARMRK;
+	}
+
+	/*
+	** Set the RAISEMOD flag to ensure that the modem lines are raised
+	** on reception of a config packet.
+	** The download code handles the zero baud condition.
+	*/
+	Cor4 |= COR4_RAISEMOD;
+
+	/*
+	** COR 5
+	*/
+
+	Cor5 = COR5_CMOE;
+
+	/*
+	** Set to monitor tbusy/tstop (or not).
+	*/
+
+	if (PortP->MonitorTstate)
+		Cor5 |= COR5_TSTATE_ON;
+	else
+		Cor5 |= COR5_TSTATE_OFF;
+
+	/*
+	** Could set LNE here if you wanted LNext processing. SVR4 will use it.
+	*/
+	if ( TtyP->termios->c_iflag & ISTRIP ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Strip input characters\n");
+		if (! (PortP->State & RIO_TRIAD_MODE)) {
+			Cor5 |= COR5_ISTRIP;
+		}
+	}
+
+	if ( TtyP->termios->c_oflag & ONLCR ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
+		if ( PortP->CookMode == COOK_MEDIUM )
+			Cor5 |= COR5_ONLCR;
+	}
+	if ( TtyP->termios->c_oflag & OCRNL ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
+		if ( PortP->CookMode == COOK_MEDIUM )
+			Cor5 |= COR5_OCRNL;
+	}
+	if ( ( TtyP->termios->c_oflag & TABDLY) == TAB3 ) {
+		rio_dprintk (RIO_DEBUG_PARAM, "Tab delay 3 set\n");
+		if ( PortP->CookMode == COOK_MEDIUM )
+			Cor5 |= COR5_TAB3;
+	}
+
+	/*
+	** Flow control bytes.
+	*/
+	TxXon = TtyP->termios->c_cc[VSTART];
+	TxXoff = TtyP->termios->c_cc[VSTOP];
+	RxXon = TtyP->termios->c_cc[VSTART];
+	RxXoff = TtyP->termios->c_cc[VSTOP];
+	/*
+	** LNEXT byte
+	*/
+	LNext = 0;
+
+	/*
+	** Baud rate bytes
+	*/
+	rio_dprintk (RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", 
+				     TtyP->termios->c_cflag, CBAUD);
+
+	switch (TtyP->termios->c_cflag & CBAUD) {
+#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
+	  e(50);e(75);e(110);e(134);e(150);e(200);e(300);e(600);e(1200);
+	  e(1800);e(2400);e(4800);e(9600);e(19200);e(38400);e(57600);
+	  e(115200); /* e(230400);e(460800); e(921600);  */
+	}
+
+	/* XXX MIssing conversion table. XXX */
+	/* 	 (TtyP->termios->c_cflag & V_CBAUD); */
+
+	rio_dprintk (RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
+
+
+	/*
+	** Leftovers
+	*/
+	if ( TtyP->termios->c_cflag & CREAD )
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable receiver\n");
+#ifdef RCV1EN
+	if ( TtyP->termios->c_cflag & RCV1EN )
+		rio_dprintk (RIO_DEBUG_PARAM, "RCV1EN (?)\n");
+#endif
+#ifdef XMT1EN
+	if ( TtyP->termios->c_cflag & XMT1EN )
+		rio_dprintk (RIO_DEBUG_PARAM, "XMT1EN (?)\n");
+#endif
+#if 0
+	if ( TtyP->termios->c_cflag & LOBLK )
+		rio_dprintk (RIO_DEBUG_PARAM, "LOBLK - JCL output blocks when not current\n");
+#endif
+	if ( TtyP->termios->c_lflag & ISIG )
+		rio_dprintk (RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
+	if ( TtyP->termios->c_lflag & ICANON )
+		rio_dprintk (RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
+	if ( TtyP->termios->c_lflag & XCASE )
+		rio_dprintk (RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
+	if ( TtyP->termios->c_lflag & ECHO )
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable input echo\n");
+	if ( TtyP->termios->c_lflag & ECHOE )
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable echo erase\n");
+	if ( TtyP->termios->c_lflag & ECHOK )
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable echo kill\n");
+	if ( TtyP->termios->c_lflag & ECHONL )
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable echo newline\n");
+	if ( TtyP->termios->c_lflag & NOFLSH )
+		rio_dprintk (RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
+#ifdef TOSTOP
+	if ( TtyP->termios->c_lflag & TOSTOP )
+		rio_dprintk (RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
+#endif
+#ifdef XCLUDE
+	if ( TtyP->termios->c_lflag & XCLUDE )
+		rio_dprintk (RIO_DEBUG_PARAM, "Exclusive use of this line\n");
+#endif
+	if ( TtyP->termios->c_iflag & IUCLC )
+		rio_dprintk (RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
+	if ( TtyP->termios->c_oflag & OPOST )
+		rio_dprintk (RIO_DEBUG_PARAM, "Enable output post-processing\n");
+	if ( TtyP->termios->c_oflag & OLCUC )
+		rio_dprintk (RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
+	if ( TtyP->termios->c_oflag & ONOCR )
+		rio_dprintk (RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
+	if ( TtyP->termios->c_oflag & ONLRET )
+		rio_dprintk (RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
+	if ( TtyP->termios->c_oflag & OFILL )
+		rio_dprintk (RIO_DEBUG_PARAM, "Use fill characters for delay\n");
+	if ( TtyP->termios->c_oflag & OFDEL )
+		rio_dprintk (RIO_DEBUG_PARAM, "Fill character is DEL\n");
+	if ( TtyP->termios->c_oflag & NLDLY )
+		rio_dprintk (RIO_DEBUG_PARAM, "Newline delay set\n");
+	if ( TtyP->termios->c_oflag & CRDLY )
+		rio_dprintk (RIO_DEBUG_PARAM, "Carriage return delay set\n");
+	if ( TtyP->termios->c_oflag & TABDLY )
+		rio_dprintk (RIO_DEBUG_PARAM, "Tab delay set\n");
+#if 0
+	if ( TtyP->termios->c_oflag & BSDLY )
+		rio_dprintk (RIO_DEBUG_PARAM, "Back-space delay set\n");
+	if ( TtyP->termios->c_oflag & VTDLY )
+		rio_dprintk (RIO_DEBUG_PARAM, "Vertical tab delay set\n");
+	if ( TtyP->termios->c_oflag & FFDLY )
+		rio_dprintk (RIO_DEBUG_PARAM, "Form-feed delay set\n");
+#endif
+	/*
+	** These things are kind of useful in a later life!
+	*/
+	PortP->Cor2Copy = Cor2;
+
+	if ( PortP->State & RIO_DELETED ) {
+		rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+		func_exit ();
+
+		return RIO_FAIL;
+	}
+
+	/*
+	** Actually write the info into the packet to be sent
+	*/
+	WBYTE(phb_param_ptr->Cmd,	cmd);
+	WBYTE(phb_param_ptr->Cor1,	 Cor1);
+	WBYTE(phb_param_ptr->Cor2,	 Cor2);
+	WBYTE(phb_param_ptr->Cor4,	 Cor4);
+	WBYTE(phb_param_ptr->Cor5,	 Cor5);
+	WBYTE(phb_param_ptr->TxXon,	TxXon);
+	WBYTE(phb_param_ptr->RxXon,	RxXon);
+	WBYTE(phb_param_ptr->TxXoff, TxXoff);
+	WBYTE(phb_param_ptr->RxXoff, RxXoff);
+	WBYTE(phb_param_ptr->LNext,	LNext);
+	WBYTE(phb_param_ptr->TxBaud, TxBaud);
+	WBYTE(phb_param_ptr->RxBaud, RxBaud);
+
+	/*
+	** Set the length/command field
+	*/
+	WBYTE(PacketP->len , 12 | PKT_CMD_BIT);
+
+	/*
+	** The packet is formed - now, whack it off
+	** to its final destination:
+	*/
+	add_transmit(PortP);
+	/*
+	** Count characters transmitted for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->txchars += 12;
+
+	rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+
+	rio_dprintk (RIO_DEBUG_PARAM, "add_transmit returned.\n");
+	/*
+	** job done.
+	*/
+	func_exit ();
+
+	return RIO_SUCCESS;
+}
+
+
+/*
+** We can add another packet to a transmit queue if the packet pointer pointed
+** to by the TxAdd pointer has PKT_IN_USE clear in its address.
+*/
+int
+can_add_transmit(PktP, PortP)
+PKT **PktP;
+struct Port *PortP; 
+{
+	register PKT *tp;
+
+	*PktP = tp = (PKT *)RIO_PTR(PortP->Caddr,RWORD(*PortP->TxAdd));
+
+	return !((uint)tp & PKT_IN_USE);
+}
+
+/*
+** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
+** and then move the TxAdd pointer along one position to point to the next
+** packet pointer. You must wrap the pointer from the end back to the start.
+*/
+void
+add_transmit(PortP)
+struct Port *PortP; 
+{
+  if (RWORD(*PortP->TxAdd) & PKT_IN_USE) {
+    rio_dprintk (RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
+  }
+	WWORD( *(ushort *)PortP->TxAdd, RWORD(*PortP->TxAdd) | PKT_IN_USE);
+	PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : 
+					PortP->TxAdd + 1;
+	WWORD( PortP->PhbP->tx_add , RIO_OFF(PortP->Caddr,PortP->TxAdd) );
+}
+
+/****************************************
+ * Put a packet onto the end of the
+ * free list
+ ****************************************/
+void
+put_free_end(HostP, PktP)
+struct Host *HostP;
+PKT *PktP;
+{
+	FREE_LIST *tmp_pointer;
+	ushort old_end, new_end;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&HostP->HostLock, flags);
+
+	 /*************************************************
+	* Put a packet back onto the back of the free list
+	*
+	************************************************/
+
+	rio_dprintk (RIO_DEBUG_PFE,  "put_free_end(PktP=%x)\n",(int)PktP);
+
+	if ((old_end=RWORD(HostP->ParmMapP->free_list_end)) != TPNULL) {
+		new_end = RIO_OFF(HostP->Caddr,PktP);
+		tmp_pointer = (FREE_LIST *)RIO_PTR(HostP->Caddr,old_end);
+		WWORD(tmp_pointer->next , new_end );
+		WWORD(((FREE_LIST *)PktP)->prev , old_end);
+		WWORD(((FREE_LIST *)PktP)->next , TPNULL);
+		WWORD(HostP->ParmMapP->free_list_end, new_end);
+	}
+	else {	/* First packet on the free list this should never happen! */
+		rio_dprintk (RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
+		WWORD(HostP->ParmMapP->free_list_end , RIO_OFF(HostP->Caddr,PktP));
+		tmp_pointer = (FREE_LIST *)PktP;
+		WWORD(tmp_pointer->prev , TPNULL);
+		WWORD(tmp_pointer->next , TPNULL);
+	}
+	rio_dprintk (RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
+	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+}
+
+/*
+** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set
+** for the next packet on the queue. It will also set PktP to point to the
+** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
+** then can_remove_receive() returns 0.
+*/
+int
+can_remove_receive(PktP, PortP)
+PKT **PktP;
+struct Port *PortP;
+{
+	if ( RWORD(*PortP->RxRemove) & PKT_IN_USE) {
+		*PktP = (PKT *)RIO_PTR(PortP->Caddr,
+					RWORD(*PortP->RxRemove) & ~PKT_IN_USE);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+** To remove a packet from the receive queue you clear its PKT_IN_USE bit,
+** and then bump the pointers. Once the pointers get to the end, they must
+** be wrapped back to the start.
+*/
+void
+remove_receive(PortP)
+struct Port *PortP; 
+{
+	WWORD( *PortP->RxRemove, RWORD(*PortP->RxRemove) & ~PKT_IN_USE );
+	PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : 
+								PortP->RxRemove + 1;
+	WWORD( PortP->PhbP->rx_remove , RIO_OFF(PortP->Caddr, PortP->RxRemove) );
+}
diff --git a/drivers/char/rio/riopcicopy.c b/drivers/char/rio/riopcicopy.c
new file mode 100644
index 0000000..2ea99a6
--- /dev/null
+++ b/drivers/char/rio/riopcicopy.c
@@ -0,0 +1,8 @@
+
+/* Yeah. We have copyright on this one. Sure. */
+
+void rio_pcicopy( char *from, char *to, int amount)
+{
+  while ( amount-- )
+    *to++ = *from++;
+}
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
new file mode 100644
index 0000000..106b31f
--- /dev/null
+++ b/drivers/char/rio/rioroute.c
@@ -0,0 +1,1238 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioroute.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:46
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)rioroute.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_rioroute_c_sccs_ = "@(#)rioroute.c	1.3";
+#endif
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+
+static int RIOCheckIsolated(struct rio_info *, struct Host *, uint);
+static int RIOIsolate(struct rio_info *, struct Host *, uint);
+static int RIOCheck(struct Host *, uint);
+static void RIOConCon(struct rio_info *, struct Host *, uint, uint, uint, uint, int);
+
+
+/*
+** Incoming on the ROUTE_RUP
+** I wrote this while I was tired. Forgive me.
+*/
+int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP )
+{
+  struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
+  struct PktCmd_M *PktReplyP;
+  struct CmdBlk *CmdBlkP;
+  struct Port *PortP;
+  struct Map *MapP;
+  struct Top *TopP;
+  int ThisLink, ThisLinkMin, ThisLinkMax;
+  int port;
+  int Mod, Mod1, Mod2;
+  ushort RtaType;
+  uint RtaUniq;
+  uint ThisUnit, ThisUnit2;	/* 2 ids to accommodate 16 port RTA */
+  uint OldUnit, NewUnit, OldLink, NewLink;
+  char *MyType, *MyName;
+  int Lies;
+  unsigned long flags;
+
+#ifdef STACK
+    RIOStackCheck("RIORouteRup");
+#endif
+#ifdef CHECK
+    CheckPacketP(PacketP);
+    CheckHostP(HostP);
+    CheckRup(Rup);
+    CheckHost(Host);
+#endif
+  /*
+  ** Is this unit telling us it's current link topology?
+  */
+  if ( RBYTE(PktCmdP->Command) == ROUTE_TOPOLOGY )
+  {
+    MapP = HostP->Mapping;
+
+    /*
+    ** The packet can be sent either by the host or by an RTA.
+    ** If it comes from the host, then we need to fill in the
+    ** Topology array in the host structure. If it came in
+    ** from an RTA then we need to fill in the Mapping structure's
+    ** Topology array for the unit.
+    */
+    if ( Rup >= (ushort)MAX_RUP )
+    {
+      ThisUnit = HOST_ID;
+      TopP = HostP->Topology;
+      MyType = "Host";
+      MyName = HostP->Name;
+      ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
+    }
+    else
+    {
+      ThisUnit = Rup+1;
+      TopP = HostP->Mapping[Rup].Topology;
+      MyType = "RTA";
+      MyName = HostP->Mapping[Rup].Name;
+      ThisLinkMin = 0;
+      ThisLinkMax = LINKS_PER_UNIT - 1;
+    }
+
+    /*
+    ** Lies will not be tolerated.
+    ** If any pair of links claim to be connected to the same
+    ** place, then ignore this packet completely.
+    */
+    Lies = 0;
+    for ( ThisLink=ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++)
+    {
+      /*
+      ** it won't lie about network interconnect, total disconnects
+      ** and no-IDs. (or at least, it doesn't *matter* if it does)
+      */
+      if ( RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort)MAX_RUP )
+	  continue;
+
+      for ( NewLink=ThisLinkMin; NewLink < ThisLink; NewLink++ )
+      {
+        if ( (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) ==
+              RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) &&
+	     (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) ==
+              RBYTE(PktCmdP->RouteTopology[NewLink].Link)) )
+	{
+          Lies++;
+	}
+      }
+    }
+
+    if ( Lies )
+    {
+      rio_dprintk (RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n",Lies);
+      rio_dprintk (RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
+          RBYTE(PktCmdP->RouteTopology[0].Unit), 
+	  'A'+RBYTE(PktCmdP->RouteTopology[0].Link),
+          RBYTE(PktCmdP->RouteTopology[1].Unit),
+	  'A'+RBYTE(PktCmdP->RouteTopology[1].Link),
+          RBYTE(PktCmdP->RouteTopology[2].Unit),
+	  'A'+RBYTE(PktCmdP->RouteTopology[2].Link),
+          RBYTE(PktCmdP->RouteTopology[3].Unit),
+	  'A'+RBYTE(PktCmdP->RouteTopology[3].Link));
+      return TRUE;
+    }
+
+    /*
+    ** now, process each link.
+    */
+    for ( ThisLink=ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++)
+    {
+      /*
+      ** this is what it was connected to
+      */
+      OldUnit = TopP[ThisLink].Unit;
+      OldLink = TopP[ThisLink].Link;
+
+      /*
+      ** this is what it is now connected to
+      */
+      NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit);
+      NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link);
+
+      if ( OldUnit != NewUnit || OldLink != NewLink )
+      {
+	/*
+	** something has changed!
+	*/
+
+        if ( NewUnit > MAX_RUP &&
+	     NewUnit != ROUTE_DISCONNECT &&
+	     NewUnit != ROUTE_NO_ID &&
+	     NewUnit != ROUTE_INTERCONNECT )
+	{
+	    rio_dprintk (RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n",
+		  MyType,
+		  MyName,
+		  NewUnit,
+		  NewLink);
+	}
+	else
+	{
+	  /*
+	  ** put the new values in
+	  */
+	  TopP[ThisLink].Unit = NewUnit;
+	  TopP[ThisLink].Link = NewLink;
+
+	  RIOSetChange(p);
+
+	  if ( OldUnit <= MAX_RUP )
+	  {
+	    /*
+	    ** If something has become bust, then re-enable them messages
+	    */
+	    if (! p->RIONoMessage)
+		RIOConCon(p,HostP,ThisUnit,ThisLink,OldUnit,OldLink,DISCONNECT);
+	  }
+
+	  if ( ( NewUnit <= MAX_RUP ) && !p->RIONoMessage )
+	    RIOConCon(p,HostP,ThisUnit,ThisLink,NewUnit,NewLink,CONNECT);
+
+	  if ( NewUnit == ROUTE_NO_ID )
+	    rio_dprintk (RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n",
+		    MyType,MyName,'A'+ThisLink);
+
+	  if ( NewUnit == ROUTE_INTERCONNECT )
+	  {
+	    if (! p->RIONoMessage)
+		cprintf("%s '%s' (%c) is connected to another network.\n", MyType,MyName,'A'+ThisLink);
+	  }
+
+	  /*
+	  ** perform an update for 'the other end', so that these messages
+	  ** only appears once. Only disconnect the other end if it is pointing
+	  ** at us!
+	  */
+	  if ( OldUnit == HOST_ID )
+	  {
+	    if ( HostP->Topology[OldLink].Unit == ThisUnit &&
+		 HostP->Topology[OldLink].Link == ThisLink )
+	    {
+	      rio_dprintk (RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink+'A');
+	      HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
+	      HostP->Topology[OldLink].Link = NO_LINK;
+	    }
+	    else
+	    {
+	      rio_dprintk (RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n",
+		    OldLink+'A',HostP->Mapping[ThisUnit-1].Name,ThisLink+'A');
+	    }
+	  }
+	  else if ( OldUnit <= MAX_RUP )
+	  {
+	    if ( HostP->Mapping[OldUnit-1].Topology[OldLink].Unit == ThisUnit &&
+	         HostP->Mapping[OldUnit-1].Topology[OldLink].Link == ThisLink )
+	    {
+	      rio_dprintk (RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n",
+				   HostP->Mapping[OldUnit-1].Name,OldLink+'A');
+	      HostP->Mapping[OldUnit-1].Topology[OldLink].Unit=ROUTE_DISCONNECT;
+	      HostP->Mapping[OldUnit-1].Topology[OldLink].Link=NO_LINK;
+	    }
+	    else
+	    {
+	      rio_dprintk (RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n",
+			    HostP->Mapping[OldUnit-1].Name,OldLink+'A',
+			    HostP->Mapping[ThisUnit-1].Name,ThisLink+'A');
+	    }
+	  }
+	  if ( NewUnit == HOST_ID )
+	  {
+	    rio_dprintk (RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n",
+				NewLink+'A',MyName,ThisLink+'A');
+	    HostP->Topology[NewLink].Unit = ThisUnit;
+	    HostP->Topology[NewLink].Link = ThisLink;
+	  }
+	  else if ( NewUnit <= MAX_RUP )
+	  {
+	    rio_dprintk (RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n",
+	      HostP->Mapping[NewUnit-1].Name,NewLink+'A',MyName,ThisLink+'A');
+	    HostP->Mapping[NewUnit-1].Topology[NewLink].Unit=ThisUnit;
+	    HostP->Mapping[NewUnit-1].Topology[NewLink].Link=ThisLink;
+	  }
+	}
+	RIOSetChange(p);
+	RIOCheckIsolated(p, HostP, OldUnit );
+      }
+    }
+    return TRUE;
+  }
+
+  /*
+  ** The only other command we recognise is a route_request command
+  */
+  if ( RBYTE(PktCmdP->Command) != ROUTE_REQUEST )
+  {
+    rio_dprintk (RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %d ROUTE_RUP\n", 
+	   RBYTE(PktCmdP->Command),Rup,(int)HostP);
+    return TRUE;
+  }
+      
+  RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) +
+	    (RBYTE(PktCmdP->UniqNum[1]) << 8) +
+	    (RBYTE(PktCmdP->UniqNum[2]) << 16) +
+	    (RBYTE(PktCmdP->UniqNum[3]) << 24);
+
+  /*
+  ** Determine if 8 or 16 port RTA
+  */
+  RtaType = GetUnitType(RtaUniq);
+
+  rio_dprintk (RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
+
+  Mod = RBYTE(PktCmdP->ModuleTypes);
+  Mod1 = LONYBLE(Mod);
+  if (RtaType == TYPE_RTA16)
+  {
+    /*
+    ** Only one ident is set for a 16 port RTA. To make compatible
+    ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
+    */
+    Mod2 = Mod1;
+    rio_dprintk (RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n",
+     p->RIOModuleTypes[Mod1].Name);
+  }
+  else
+  {
+    Mod2 = HINYBLE(Mod);
+    rio_dprintk (RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n",
+     p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
+  }
+
+  if ( RtaUniq == 0xffffffff )
+  {
+      ShowPacket( DBG_SPECIAL, PacketP );
+  }
+
+  /*
+  ** try to unhook a command block from the command free list.
+  */
+  if ( !(CmdBlkP = RIOGetCmdBlk()) )
+  {
+    rio_dprintk (RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
+    return 0;
+  }
+
+  /*
+  ** Fill in the default info on the command block
+  */
+  CmdBlkP->Packet.dest_unit = Rup;
+  CmdBlkP->Packet.dest_port = ROUTE_RUP;
+  CmdBlkP->Packet.src_unit = HOST_ID;
+  CmdBlkP->Packet.src_port = ROUTE_RUP;
+  CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
+  CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
+  PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data;
+
+  if (! RIOBootOk(p, HostP, RtaUniq))
+  {
+    rio_dprintk (RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n",
+	  RtaUniq);
+    PktReplyP->Command = ROUTE_FOAD;
+    HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+    RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+    return TRUE;
+  }
+
+  /*
+  ** Check to see if the RTA is configured for this host
+  */
+  for ( ThisUnit=0; ThisUnit<MAX_RUP; ThisUnit++ )
+  {
+    rio_dprintk (RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
+			ThisUnit,
+			HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ?
+					    "Slot-In-Use":"Not In Use",
+			HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? 
+					    "Slot-Tentative":"Not Tentative",
+			HostP->Mapping[ThisUnit].RtaUniqueNum);
+
+    /*
+    ** We have an entry for it.
+    */
+    if ( (HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) &&
+         (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq) )
+    {
+      if (RtaType == TYPE_RTA16)
+      {
+	  ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
+          rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n",
+					    RtaUniq,ThisUnit,ThisUnit2);
+      }
+      else
+          rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n",
+					    RtaUniq,ThisUnit);
+      /*
+      ** If we have no knowledge of booting it, then the host has
+      ** been re-booted, and so we must kill the RTA, so that it
+      ** will be booted again (potentially with new bins)
+      ** and it will then re-ask for an ID, which we will service.
+      */
+      if ( (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && 
+	  !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED) )
+      {
+	if ( !(HostP->Mapping[ThisUnit].Flags & MSG_DONE) )
+	{
+	    if ( !p->RIONoMessage )
+	        cprintf("RTA '%s' is being updated.\n",HostP->Mapping[ThisUnit].Name);
+	    HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
+	}
+	PktReplyP->Command = ROUTE_FOAD;
+	HostP->Copy("RT_FOAD",PktReplyP->CommandText,7);
+	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+	return TRUE;
+      }
+
+      /*
+      ** Send the ID (entry) to this RTA. The ID number is implicit as
+      ** the offset into the table. It is worth noting at this stage
+      ** that offset zero in the table contains the entries for the
+      ** RTA with ID 1!!!!
+      */
+      PktReplyP->Command = ROUTE_ALLOCATE;
+      PktReplyP->IDNum   = ThisUnit+1;
+      if (RtaType == TYPE_RTA16)
+      {
+        if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
+	    /*
+	    ** Adjust the phb and tx pkt dest_units for 2nd block of 8
+	    ** only if the RTA has ports associated (SLOT_IN_USE)
+	    */
+	    RIOFixPhbs(p, HostP, ThisUnit2);
+	    PktReplyP->IDNum2  = ThisUnit2+1;
+	    rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n",
+	          HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
+      }
+      else
+      {
+	    PktReplyP->IDNum2 = ROUTE_NO_ID;
+	    rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n",
+	          HostP->Mapping[ThisUnit].Name,PktReplyP->IDNum);
+      }
+      HostP->Copy("RT_ALLOCAT",PktReplyP->CommandText,10);
+
+      RIOQueueCmdBlk( HostP, Rup, CmdBlkP);
+
+      /*
+      ** If this is a freshly booted RTA, then we need to re-open
+      ** the ports, if any where open, so that data may once more
+      ** flow around the system!
+      */
+      if ( (HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) &&
+	   (HostP->Mapping[ThisUnit].SysPort != NO_PORT) )
+      {
+	/*
+	** look at the ports associated with this beast and
+	** see if any where open. If they was, then re-open
+	** them, using the info from the tty flags.
+	*/
+	for ( port=0; port<PORTS_PER_RTA; port++ )
+	{
+	  PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort];
+	  if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) )
+	  {
+	    rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n");
+	    rio_spin_lock_irqsave(&PortP->portSem, flags);
+	    PortP->MagicFlags |= MAGIC_REBOOT;
+	    rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	  }
+	}
+	if (RtaType == TYPE_RTA16)
+	{
+	  for ( port=0; port<PORTS_PER_RTA; port++ )
+	  {
+	    PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort];
+	    if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) )
+	    {
+	      rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n");
+	      rio_spin_lock_irqsave(&PortP->portSem, flags);
+	      PortP->MagicFlags |= MAGIC_REBOOT;
+	      rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	    }
+	  }
+	}
+      }
+
+      /*
+      ** keep a copy of the module types!
+      */
+      HostP->UnixRups[ThisUnit].ModTypes = Mod;
+      if (RtaType == TYPE_RTA16)
+	      HostP->UnixRups[ThisUnit2].ModTypes = Mod;
+
+      /*
+      ** If either of the modules on this unit is read-only or write-only
+      ** or none-xprint, then we need to transfer that info over to the
+      ** relevant ports.
+      */
+      if ( HostP->Mapping[ThisUnit].SysPort != NO_PORT )
+      {
+        for ( port=0; port<PORTS_PER_MODULE; port++ )
+	{
+	  p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+	  p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config |=
+	   p->RIOModuleTypes[Mod1].Flags[port];
+	  p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+	  p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+	}
+	if (RtaType == TYPE_RTA16)
+	{
+          for ( port=0; port<PORTS_PER_MODULE; port++ )
+	  {
+	    p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+	    p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
+	    p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+	    p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+          }
+	}
+      }
+
+      /*
+      ** Job done, get on with the interrupts!
+      */
+      return TRUE;
+    }
+  }
+  /*
+  ** There is no table entry for this RTA at all.
+  **
+  ** Lets check to see if we actually booted this unit - if not,
+  ** then we reset it and it will go round the loop of being booted
+  ** we can then worry about trying to fit it into the table.
+  */
+  for ( ThisUnit=0; ThisUnit<HostP->NumExtraBooted; ThisUnit++ )
+    if ( HostP->ExtraUnits[ThisUnit] == RtaUniq )
+      break;
+  if ( ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS )
+  {
+    /*
+    ** if the unit wasn't in the table, and the table wasn't full, then
+    ** we reset the unit, because we didn't boot it.
+    ** However, if the table is full, it could be that we did boot
+    ** this unit, and so we won't reboot it, because it isn't really
+    ** all that disasterous to keep the old bins in most cases. This
+    ** is a rather tacky feature, but we are on the edge of reallity
+    ** here, because the implication is that someone has connected
+    ** 16+MAX_EXTRA_UNITS onto one host.
+    */
+    static int UnknownMesgDone = 0;
+
+    if ( !UnknownMesgDone )
+    {
+	if (! p->RIONoMessage)
+	    cprintf("One or more unknown RTAs are being updated.\n");
+	UnknownMesgDone = 1;
+    }
+
+    PktReplyP->Command = ROUTE_FOAD;
+    HostP->Copy("RT_FOAD",PktReplyP->CommandText,7);
+  }
+  else
+  {
+    /*
+    ** we did boot it (as an extra), and there may now be a table
+    ** slot free (because of a delete), so we will try to make
+    ** a tentative entry for it, so that the configurator can see it
+    ** and fill in the details for us.
+    */
+    if (RtaType == TYPE_RTA16)
+    {
+	if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0)
+	{
+	    RIODefaultName(p, HostP, ThisUnit);
+	    FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP);
+	}
+    }
+    else
+    {
+	if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0)
+	{
+	    RIODefaultName(p, HostP, ThisUnit);
+	    FillSlot(ThisUnit, 0, RtaUniq, HostP);
+	}
+    }
+    PktReplyP->Command = ROUTE_USED;
+    HostP->Copy("RT_USED",PktReplyP->CommandText,7);
+  }
+  RIOQueueCmdBlk( HostP, Rup, CmdBlkP);
+  return TRUE;
+}
+
+
+void
+RIOFixPhbs(p, HostP, unit)
+struct rio_info *p;
+struct Host *HostP;
+uint unit;
+{
+	ushort			link, port;
+	struct Port		*PortP;
+	unsigned long flags;
+	int PortN = HostP->Mapping[unit].SysPort;
+
+	rio_dprintk (RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
+
+	if (PortN != -1) {
+		ushort		dest_unit = HostP->Mapping[unit].ID2;
+
+		/*
+		** Get the link number used for the 1st 8 phbs on this unit.
+		*/
+		PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
+
+		link = RWORD(PortP->PhbP->link);
+
+		for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
+			ushort		dest_port = port + 8;
+#if 0
+			uint		PktInt;
+#endif
+			WORD		*TxPktP;
+			PKT		*Pkt;
+
+			PortP = p->RIOPortp[PortN];
+
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+			/*
+			** If RTA is not powered on, the tx packets will be
+			** unset, so go no further.
+			*/
+			if (PortP->TxStart == 0) {
+					rio_dprintk (RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
+					rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+					break;
+			}
+
+			/*
+			** For the second slot of a 16 port RTA, the driver needs to
+			** sort out the phb to port mappings. The dest_unit for this
+			** group of 8 phbs is set to the dest_unit of the accompanying
+			** 8 port block. The dest_port of the second unit is set to
+			** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
+			** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
+			** (being the second map ID) will be sent to dest_unit 5, port
+			** 14. When this RTA is deleted, dest_unit for ID 6 will be
+			** restored, and the dest_port will be reduced by 8.
+			** Transmit packets also have a destination field which needs
+			** adjusting in the same manner.
+			** Note that the unit/port bytes in 'dest' are swapped.
+			** We also need to adjust the phb and rup link numbers for the
+			** second block of 8 ttys.
+			*/
+			for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
+				/*
+				** *TxPktP is the pointer to the transmit packet on the host
+				** card. This needs to be translated into a 32 bit pointer
+				** so it can be accessed from the driver.
+				*/
+				Pkt = (PKT *) RIO_PTR(HostP->Caddr,RINDW(TxPktP));
+
+				/*
+				** If the packet is used, reset it.
+				*/
+				Pkt = (PKT *)((uint)Pkt & ~PKT_IN_USE);
+				WBYTE(Pkt->dest_unit, dest_unit);
+				WBYTE(Pkt->dest_port, dest_port);
+			}
+			rio_dprintk (RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n",
+					RWORD(PortP->PhbP->destination) & 0xff,
+					(RWORD(PortP->PhbP->destination) >> 8) & 0xff,
+					dest_unit, dest_port);
+			WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8));
+			WWORD(PortP->PhbP->link, link);
+
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		}
+		/*
+		** Now make sure the range of ports to be serviced includes
+		** the 2nd 8 on this 16 port RTA.
+		*/
+		if (link > 3) return;
+		if (((unit * 8) + 7) > RWORD(HostP->LinkStrP[link].last_port)) {
+			rio_dprintk (RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
+			WWORD(HostP->LinkStrP[link].last_port, (unit * 8) + 7);
+		}
+	}
+}
+
+/*
+** Check to see if the new disconnection has isolated this unit.
+** If it has, then invalidate all its link information, and tell
+** the world about it. This is done to ensure that the configurator
+** only gets up-to-date information about what is going on.
+*/
+static int
+RIOCheckIsolated(p, HostP, UnitId)
+struct rio_info *	p;
+struct Host *HostP;
+uint UnitId;
+{
+	unsigned long flags;
+	rio_spin_lock_irqsave(&HostP->HostLock, flags);
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckUnitId( UnitId );
+#endif
+	if ( RIOCheck( HostP, UnitId ) ) {
+		rio_dprintk (RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
+		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+		return(0);
+	}
+
+	RIOIsolate(p, HostP, UnitId );
+	RIOSetChange(p);
+	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+	return 1;
+}
+
+/*
+** Invalidate all the link interconnectivity of this unit, and of
+** all the units attached to it. This will mean that the entire
+** subnet will re-introduce itself.
+*/
+static int
+RIOIsolate(p, HostP, UnitId)
+struct rio_info *	p;
+struct Host *		HostP;
+uint UnitId; 
+{
+	uint link, unit;
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckUnitId( UnitId );
+#endif
+	UnitId--;		/* this trick relies on the Unit Id being UNSIGNED! */
+
+	if ( UnitId >= MAX_RUP )	/* dontcha just lurv unsigned maths! */
+		return(0);
+
+	if ( HostP->Mapping[UnitId].Flags & BEEN_HERE )
+		return(0);
+
+	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
+
+	if ( p->RIOPrintDisabled == DO_PRINT )
+		rio_dprintk (RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
+
+	for ( link=0; link<LINKS_PER_UNIT; link++) {
+		unit = HostP->Mapping[UnitId].Topology[link].Unit;
+		HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
+		HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
+		RIOIsolate(p, HostP, unit );
+	}
+	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+	return 1;
+}
+
+static int
+RIOCheck(HostP, UnitId)
+struct Host *HostP;
+uint UnitId;
+{
+  unsigned char link;
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckUnitId( UnitId );
+#endif
+/* 	rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
+	rio_dprintk (RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
+
+	if ( UnitId == HOST_ID ) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */
+		return 1;
+	}
+
+	UnitId--;
+
+	if ( UnitId >= MAX_RUP ) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */
+		return 0;
+	}
+
+	for ( link=0; link<LINKS_PER_UNIT; link++ ) {
+		if ( HostP->Mapping[UnitId].Topology[link].Unit==HOST_ID ) {
+			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", 
+						UnitId, 'A'+link)); */
+			return 1;
+		}
+	}
+
+	if ( HostP->Mapping[UnitId].Flags & BEEN_HERE ) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
+		return 0;
+	}
+
+	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
+
+	for ( link=0; link < LINKS_PER_UNIT; link++ ) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */
+		if ( RIOCheck( HostP, HostP->Mapping[UnitId].Topology[link].Unit ) ) {
+			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */
+			HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+			return 1;
+		}
+	}
+
+	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+
+	/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */
+	
+	return 0;
+}
+
+/*
+** Returns the type of unit (host, 16/8 port RTA)
+*/
+
+uint
+GetUnitType(Uniq)
+uint Uniq;
+{
+	switch ( (Uniq >> 28) & 0xf)
+	{
+		case RIO_AT:
+		case RIO_MCA:
+		case RIO_EISA:
+		case RIO_PCI:
+			rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Host\n");
+			return(TYPE_HOST);
+		case RIO_RTA_16:
+			rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
+			return(TYPE_RTA16);
+		case RIO_RTA:
+			rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
+			return(TYPE_RTA8);
+		default :
+			rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
+			return(99);
+	}
+}
+
+int
+RIOSetChange(p)
+struct rio_info *	p;
+{
+	if ( p->RIOQuickCheck != NOT_CHANGED )
+		return(0);
+	p->RIOQuickCheck = CHANGED;
+	if ( p->RIOSignalProcess ) {
+		rio_dprintk (RIO_DEBUG_ROUTE, "Send SIG-HUP");
+		/*
+		psignal( RIOSignalProcess, SIGHUP );
+		*/
+	}
+	return(0);
+}
+
+static void
+RIOConCon(p, HostP, FromId, FromLink, ToId, ToLink, Change)
+struct rio_info *	p;
+struct Host *HostP;
+uint FromId;
+uint FromLink;
+uint ToId;
+uint ToLink;
+int Change; 
+{
+    char *FromName;
+    char *FromType;
+    char *ToName;
+    char *ToType;
+    unsigned int tp;
+
+/*
+** 15.10.1998 ARG - ESIL 0759
+** (Part) fix for port being trashed when opened whilst RTA "disconnected"
+**
+** What's this doing in here anyway ?
+** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected"
+**
+** 09.12.1998 ARG - ESIL 0776 - part fix
+** Okay, We've found out what this was all about now !
+** Someone had botched this to use RIOHalted to indicated the number of RTAs
+** 'disconnected'. The value in RIOHalted was then being used in the
+** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA
+** is 'disconnected'. The change was put in to satisfy a customer's needs.
+** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for
+** the customer.
+**
+    if (Change == CONNECT) {
+		if (p->RIOHalted) p->RIOHalted --;
+	 }
+	 else {
+		p->RIOHalted ++;
+	 }
+**
+** So - we need to implement it slightly differently - a new member of the
+** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA
+** connections and disconnections. 
+*/
+    if (Change == CONNECT) {
+		if (p->RIORtaDisCons) p->RIORtaDisCons--;
+	 }
+	 else {
+		p->RIORtaDisCons++;
+	 }
+
+    if ( p->RIOPrintDisabled == DONT_PRINT )
+		return;
+
+    if ( FromId > ToId ) {
+		tp = FromId;
+		FromId = ToId;
+		ToId = tp;
+		tp = FromLink;
+		FromLink = ToLink;
+		ToLink = tp;
+    }
+
+    FromName = FromId ? HostP->Mapping[FromId-1].Name : HostP->Name;
+    FromType = FromId ? "RTA" : "HOST";
+    ToName = ToId ? HostP->Mapping[ToId-1].Name : HostP->Name;
+    ToType = ToId ? "RTA" : "HOST";
+
+    rio_dprintk (RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n",
+			    FromType, FromName, 'A'+FromLink,
+			    ToType,   ToName,   'A'+ToLink,
+			    (Change==CONNECT) ? "established" : "disconnected");
+    cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n",
+			    FromType, FromName, 'A'+FromLink,
+			    ToType,   ToName,   'A'+ToLink,
+			    (Change==CONNECT) ? "established" : "disconnected");
+}
+
+/*
+** RIORemoveFromSavedTable :
+**
+** Delete and RTA entry from the saved table given to us
+** by the configuration program.
+*/
+static int
+RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
+{
+    int		entry;
+
+    /*
+    ** We loop for all entries even after finding an entry and
+    ** zeroing it because we may have two entries to delete if
+    ** it's a 16 port RTA.
+    */
+    for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++)
+    {
+	if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum)
+	{
+	    bzero((caddr_t)&p->RIOSavedTable[entry], sizeof(struct Map));
+	}
+    }
+    return 0;
+}
+
+
+/*
+** RIOCheckDisconnected :
+**
+** Scan the unit links to and return zero if the unit is completely
+** disconnected.
+*/
+static int
+RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
+{
+    int		link;
+
+
+    rio_dprintk (RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
+    /*
+    ** If the slot is tentative and does not belong to the
+    ** second half of a 16 port RTA then scan to see if
+    ** is disconnected.
+    */
+    for (link = 0; link < LINKS_PER_UNIT; link++)
+    {
+	if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
+	    break;
+    }
+
+    /*
+    ** If not all links are disconnected then we can forget about it.
+    */
+    if (link < LINKS_PER_UNIT)
+	    return 1;
+
+#if NEED_TO_FIX_THIS
+    /* Ok so all the links are disconnected. But we may have only just
+    ** made this slot tentative and not yet received a topology update.
+    ** Lets check how long ago we made it tentative.
+    */
+    rio_dprintk (RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
+    if (drv_getparm(LBOLT, (ulong_t *) &current_time))
+        rio_dprintk (RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
+
+    elapse_time = current_time - TentTime[unit];
+    rio_dprintk (RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n",
+        elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
+    if (drv_hztousec(elapse_time) < WAIT_TO_FINISH)
+    {
+      rio_dprintk (RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n",
+            unit, drv_hztousec(elapse_time));
+        return 1;
+    }
+#endif
+
+    /*
+    ** We have found an usable slot.
+    ** If it is half of a 16 port RTA then delete the other half.
+    */
+    if (HostP->Mapping[unit].ID2 != 0)
+    {
+	int nOther = (HostP->Mapping[unit].ID2) -1;
+
+	rio_dprintk (RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
+	bzero((caddr_t)&HostP->Mapping[nOther], sizeof(struct Map));
+    }
+    RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
+
+    return 0;
+}
+
+
+/*
+** RIOFindFreeID :
+**
+** This function scans the given host table for either one
+** or two free unit ID's.
+*/
+int
+RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2)
+{
+    int unit,tempID;
+
+    /*
+    ** Initialise the ID's to MAX_RUP.
+    ** We do this to make the loop for setting the ID's as simple as
+    ** possible.
+    */
+    *pID1 = MAX_RUP;
+    if (pID2 != NULL)
+	*pID2 = MAX_RUP;
+
+    /*
+    ** Scan all entries of the host mapping table for free slots.
+    ** We scan for free slots first and then if that is not successful
+    ** we start all over again looking for tentative slots we can re-use.
+    */
+    for (unit = 0; unit < MAX_RUP; unit++)
+    {
+	rio_dprintk (RIO_DEBUG_ROUTE, "Scanning unit %d\n",unit);
+	/*
+	** If the flags are zero then the slot is empty.
+	*/
+	if (HostP->Mapping[unit].Flags == 0)
+	{
+	    rio_dprintk (RIO_DEBUG_ROUTE, "      This slot is empty.\n");
+	    /*
+	    ** If we haven't allocated the first ID then do it now.
+	    */
+	    if (*pID1 == MAX_RUP)
+	    {
+		rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
+		*pID1 = unit;
+
+		/*
+		** If the second ID is not needed then we can return
+		** now.
+		*/
+		if (pID2 == NULL)
+		    return 0;
+	    }
+	    else
+	    {
+		/*
+		** Allocate the second slot and return.
+		*/
+		rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
+		*pID2 = unit;
+		return 0;
+	    }
+	}
+    }
+
+    /*
+    ** If we manage to come out of the free slot loop then we
+    ** need to start all over again looking for tentative slots
+    ** that we can re-use.
+    */
+    rio_dprintk (RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
+    for (unit = 0; unit < MAX_RUP; unit++)
+    {
+	if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) ||
+	                       (HostP->Mapping[unit].Flags == 0))  && ! 
+	   (HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT ))
+	{
+	    rio_dprintk (RIO_DEBUG_ROUTE, "    Slot %d looks promising.\n",unit);
+
+	    if(unit == *pID1)
+	    {
+	    	rio_dprintk (RIO_DEBUG_ROUTE, "    No it isn't, its the 1st half\n");
+		continue;
+	    }
+
+	    /*
+	    ** Slot is Tentative or Empty, but not a tentative second 
+	    ** slot of a 16 porter.
+	    ** Attempt to free up this slot (and its parnter if
+	    ** it is a 16 port slot. The second slot will become
+	    ** empty after a call to RIOFreeDisconnected so thats why
+	    ** we look for empty slots above  as well).
+	    */
+	    if (HostP->Mapping[unit].Flags != 0) 
+	    	if (RIOFreeDisconnected(p, HostP, unit) != 0)
+			    continue;
+	    /*
+	    ** If we haven't allocated the first ID then do it now.
+	    */
+	    if (*pID1 == MAX_RUP)
+	    {
+		rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
+		*pID1 = unit;
+
+		/*
+		** Clear out this slot now that we intend to use it.
+		*/
+		bzero(&HostP->Mapping[unit], sizeof(struct Map));
+
+		/*
+		** If the second ID is not needed then we can return
+		** now.
+		*/
+		if (pID2 == NULL)
+		    return 0;
+	    }
+	    else
+	    {
+		/*
+		** Allocate the second slot and return.
+		*/
+		rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative/empty  entry for second unit %d\n",
+		      unit);
+		*pID2 = unit;
+
+		/*
+		** Clear out this slot now that we intend to use it.
+		*/
+		bzero(&HostP->Mapping[unit], sizeof(struct Map));
+
+		/* At this point under the right(wrong?) conditions
+		** we may have a first unit ID being higher than the
+		** second unit ID. This is a bad idea if we are about
+		** to fill the slots with a 16 port RTA.
+		** Better check and swap them over.
+		*/
+
+		if (*pID1 > *pID2)
+		{
+			rio_dprintk (RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
+			tempID = *pID1;
+			*pID1 = *pID2;
+			*pID2 = tempID;
+		}
+		return 0;
+	    }
+	}
+    }
+
+    /*
+    ** If we manage to get to the end of the second loop then we
+    ** can give up and return a failure.
+    */
+    return 1;
+}
+
+
+/*
+** The link switch scenario.
+**
+** Rta Wun (A) is connected to Tuw (A).
+** The tables are all up to date, and the system is OK.
+**
+** If Wun (A) is now moved to Wun (B) before Wun (A) can
+** become disconnected, then the follow happens:
+**
+** Tuw (A) spots the change of unit:link at the other end
+** of its link and Tuw sends a topology packet reflecting
+** the change: Tuw (A) now disconnected from Wun (A), and
+** this is closely followed by a packet indicating that 
+** Tuw (A) is now connected to Wun (B).
+**
+** Wun (B) will spot that it has now become connected, and
+** Wun will send a topology packet, which indicates that
+** both Wun (A) and Wun (B) is connected to Tuw (A).
+**
+** Eventually Wun (A) realises that it is now disconnected
+** and Wun will send out a topology packet indicating that
+** Wun (A) is now disconnected.
+*/
diff --git a/drivers/char/rio/riospace.h b/drivers/char/rio/riospace.h
new file mode 100644
index 0000000..32b09b0
--- /dev/null
+++ b/drivers/char/rio/riospace.h
@@ -0,0 +1,161 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riospace.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)riospace.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_riospace_h__
+#define __rio_riospace_h__
+
+#ifdef SCCS_LABELS
+static char *_riospace_h_sccs_ = "@(#)riospace.h	1.2";
+#endif
+
+#define	RIO_LOCATOR_LEN	16
+#define	MAX_RIO_BOARDS	4
+
+/*
+** DONT change this file. At all. Unless you can rebuild the entire
+** device driver, which you probably can't, then the rest of the
+** driver won't see any changes you make here. So don't make any.
+** In particular, it won't be able to see changes to RIO_SLOTS
+*/
+
+struct Conf
+{
+	char         Locator[24];
+	unsigned int StartupTime;
+	unsigned int SlowCook;
+	unsigned int IntrPollTime;
+	unsigned int BreakInterval;
+	unsigned int Timer;
+	unsigned int RtaLoadBase;
+	unsigned int HostLoadBase;
+	unsigned int XpHz;
+	unsigned int XpCps;
+	char         *XpOn;
+	char         *XpOff;
+	unsigned int MaxXpCps;
+	unsigned int MinXpCps;
+	unsigned int SpinCmds;
+	unsigned int FirstAddr;
+	unsigned int LastAddr;
+	unsigned int BufferSize;
+	unsigned int LowWater;
+	unsigned int LineLength;
+	unsigned int CmdTime;
+};
+
+/*
+**	Board types - these MUST correspond to product codes!
+*/ 
+#define	RIO_EMPTY	0x0
+#define	RIO_EISA	0x3
+#define	RIO_RTA_16	0x9
+#define	RIO_AT		0xA
+#define	RIO_MCA		0xB
+#define	RIO_PCI		0xD
+#define	RIO_RTA		0xE
+
+/*
+**	Board data structure. This is used for configuration info
+*/
+struct	Brd
+{
+    unsigned char Type;	/* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
+    unsigned char Ivec;	/* POLLED or ivec number */
+    unsigned char Mode;	/* Control stuff, see below */
+};
+
+struct	Board
+{
+    char       Locator[RIO_LOCATOR_LEN];
+    int        NumSlots;
+    struct Brd Boards[MAX_RIO_BOARDS];
+};
+
+#define	BOOT_FROM_LINK		0x00
+#define	BOOT_FROM_RAM		0x01
+#define	EXTERNAL_BUS_OFF	0x00
+#define	EXTERNAL_BUS_ON		0x02
+#define	INTERRUPT_DISABLE	0x00
+#define	INTERRUPT_ENABLE	0x04
+#define	BYTE_OPERATION		0x00
+#define	WORD_OPERATION		0x08
+#define	POLLED			INTERRUPT_DISABLE
+#define	IRQ_15			(0x00 | INTERRUPT_ENABLE)
+#define	IRQ_12			(0x10 | INTERRUPT_ENABLE)
+#define	IRQ_11			(0x20 | INTERRUPT_ENABLE)
+#define	IRQ_9			(0x30 | INTERRUPT_ENABLE)
+#define	SLOW_LINKS		0x00
+#define	FAST_LINKS		0x40
+#define	SLOW_AT_BUS		0x00
+#define	FAST_AT_BUS		0x80
+#define	SLOW_PCI_TP		0x00
+#define	FAST_PCI_TP		0x80
+/*
+**	Debug levels
+*/
+#define	DBG_NONE	0x00000000
+
+#define	DBG_INIT	0x00000001
+#define	DBG_OPEN	0x00000002
+#define	DBG_CLOSE	0x00000004
+#define	DBG_IOCTL	0x00000008
+
+#define	DBG_READ	0x00000010
+#define	DBG_WRITE	0x00000020
+#define	DBG_INTR	0x00000040
+#define	DBG_PROC	0x00000080
+
+#define	DBG_PARAM	0x00000100
+#define	DBG_CMD		0x00000200
+#define	DBG_XPRINT	0x00000400
+#define	DBG_POLL	0x00000800
+
+#define	DBG_DAEMON	0x00001000
+#define	DBG_FAIL	0x00002000
+#define DBG_MODEM	0x00004000
+#define	DBG_LIST	0x00008000
+
+#define	DBG_ROUTE	0x00010000
+#define DBG_UTIL        0x00020000
+#define DBG_BOOT	0x00040000
+#define DBG_BUFFER	0x00080000
+
+#define	DBG_MON		0x00100000
+#define DBG_SPECIAL     0x00200000
+#define	DBG_VPIX	0x00400000
+#define	DBG_FLUSH	0x00800000
+
+#define	DBG_QENABLE	0x01000000
+
+#define	DBG_ALWAYS	0x80000000
+
+#endif /* __rio_riospace_h__ */
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
new file mode 100644
index 0000000..8fb26ad
--- /dev/null
+++ b/drivers/char/rio/riotable.c
@@ -0,0 +1,1044 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riotable.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:47
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)riotable.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_riotable_c_sccs_ = "@(#)riotable.c	1.2";
+#endif
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+#include "protsts.h"
+
+/*
+** A configuration table has been loaded. It is now up to us
+** to sort it out and use the information contained therein.
+*/
+int
+RIONewTable(p)
+struct rio_info *	p;
+{
+	int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
+	struct Map *MapP;
+	struct Map *HostMapP;
+	struct Host *HostP;
+
+	char *cptr;
+
+	/*
+	** We have been sent a new table to install. We need to break
+	** it down into little bits and spread it around a bit to see
+	** what we have got.
+	*/
+	/*
+	** Things to check:
+	** (things marked 'xx' aren't checked any more!)
+	** (1)	That there are no booted Hosts/RTAs out there.
+	** (2)	That the names are properly formed
+	** (3)	That blank entries really are.
+	** xx (4)	That hosts mentioned in the table actually exist. xx
+	** (5)	That the IDs are unique (per host).
+	** (6)	That host IDs are zero
+	** (7)	That port numbers are valid
+	** (8)	That port numbers aren't duplicated
+	** (9)	That names aren't duplicated
+	** xx (10) That hosts that actually exist are mentioned in the table. xx
+	*/
+	rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n"); 
+	if ( p->RIOSystemUp ) {		/* (1) */
+		p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
+		return -EBUSY;
+	}
+
+	p->RIOError.Error = NOTHING_WRONG_AT_ALL;
+	p->RIOError.Entry = -1;
+	p->RIOError.Other = -1;
+
+	for ( Entry=0; Entry<TOTAL_MAP_ENTRIES; Entry++ ) {
+		MapP = &p->RIOConnectTable[Entry];
+		if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
+			rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
+			cptr = MapP->Name;		/* (2) */
+			cptr[MAX_NAME_LEN-1]='\0';
+			if ( cptr[0]=='\0' ) {
+				bcopy(MapP->RtaUniqueNum?"RTA	NN":"HOST NN",MapP->Name,8);
+				MapP->Name[5] = '0'+Entry/10;
+				MapP->Name[6] = '0'+Entry%10;
+			}
+			while ( *cptr ) {
+				if ( *cptr<' ' || *cptr>'~' ) {
+					p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+					p->RIOError.Entry = Entry;
+					return -ENXIO;
+				}
+				cptr++;
+			}
+		}
+
+		/*
+		** If the entry saved was a tentative entry then just forget
+		** about it.
+		*/
+		if ( MapP->Flags & SLOT_TENTATIVE ) {
+			MapP->HostUniqueNum = 0;
+			MapP->RtaUniqueNum = 0;
+			continue;
+		}
+
+		rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
+		if ( !MapP->RtaUniqueNum && !MapP->HostUniqueNum ) { /* (3) */
+			if ( MapP->ID || MapP->SysPort || MapP->Flags ) {
+				rio_dprintk (RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n",MapP->Name);
+				p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			rio_dprintk (RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
+			continue;
+		}
+
+		rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
+		for ( Host=0; Host<p->RIONumHosts; Host++ ) { /* (4) */
+			if ( p->RIOHosts[Host].UniqueNum==MapP->HostUniqueNum ) {
+				HostP = &p->RIOHosts[Host];
+				/*
+				** having done the lookup, we don't really want to do
+				** it again, so hang the host number in a safe place
+				*/
+				MapP->Topology[0].Unit = Host;
+				break;
+			}
+		}
+
+		if ( Host >= p->RIONumHosts ) {
+			rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n",
+									MapP->Name, MapP->HostUniqueNum);
+			MapP->HostUniqueNum = 0;
+			/* MapP->RtaUniqueNum	= 0; */
+			/* MapP->ID			= 0; */
+			/* MapP->Flags		 = 0; */
+			/* MapP->SysPort		 = 0; */
+			/* MapP->Name[0]		 = 0; */
+			continue;
+		}
+
+		rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n"); 
+		if ( MapP->RtaUniqueNum ) { /* (5) */
+			if ( !MapP->ID ) {
+				rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n",
+							MapP->Name);
+				p->RIOError.Error		 = ZERO_RTA_ID;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			if ( MapP->ID > MAX_RUP ) {
+				rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n",
+							MapP->Name, MapP->ID);
+				p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) {
+				if ( MapP->HostUniqueNum == 
+						p->RIOConnectTable[SubEnt].HostUniqueNum && 
+						MapP->ID == p->RIOConnectTable[SubEnt].ID ) {
+					rio_dprintk (RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n",
+							MapP->Name, p->RIOConnectTable[SubEnt].Name);
+					p->RIOError.Error = DUPLICATED_RTA_ID;
+					p->RIOError.Entry = Entry;
+					p->RIOError.Other = SubEnt;
+					return -ENXIO;
+				}
+				/*
+				** If the RtaUniqueNum is the same, it may be looking at both
+				** entries for a 16 port RTA, so check the ids
+				*/
+				if ((MapP->RtaUniqueNum == 
+						p->RIOConnectTable[SubEnt].RtaUniqueNum)
+				 		&& (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
+					rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n",MapP->Name);
+					rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n",
+										p->RIOConnectTable[SubEnt].Name);
+					p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
+					p->RIOError.Entry = Entry;
+					p->RIOError.Other = SubEnt;
+					return -ENXIO;
+				}
+			}
+			rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n"); 
+			/* (7a) */
+			if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort % PORTS_PER_RTA)) {
+				rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n",
+					(int)MapP->SysPort,MapP->Name, PORTS_PER_RTA);
+				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n"); 
+			/* (7b) */
+			if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort >= RIO_PORTS)) {
+				rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n",
+							(int)MapP->SysPort, MapP->Name);
+				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) {
+				if ( p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT )
+						continue;
+				if ( p->RIOConnectTable[SubEnt].RtaUniqueNum ) {
+					rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n"); 
+					/* (8) */
+					if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort == 
+									p->RIOConnectTable[SubEnt].SysPort) ) {
+						rio_dprintk (RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n",
+							MapP->Name, p->RIOConnectTable[SubEnt].Name,
+							(int)MapP->SysPort);
+						p->RIOError.Error = TTY_NUMBER_IN_USE;
+						p->RIOError.Entry = Entry;
+						p->RIOError.Other = SubEnt;
+						return -ENXIO;
+					}
+					rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n"); 
+					if (strcmp(MapP->Name,
+							p->RIOConnectTable[SubEnt].Name)==0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */
+						rio_dprintk (RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
+						p->RIOError.Error = NAME_USED_TWICE;
+						p->RIOError.Entry = Entry;
+						p->RIOError.Other = SubEnt;
+						return -ENXIO;
+					}
+				}
+			}
+		}
+		else { /* (6) */
+			rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n"); 
+			if ( MapP->ID ) {
+				rio_dprintk (RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n",
+					MapP->Name);
+				p->RIOError.Error = HOST_ID_NOT_ZERO;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			if ( MapP->SysPort != NO_PORT ) {
+				rio_dprintk (RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n",
+					MapP->Name);
+				p->RIOError.Error = HOST_SYSPORT_BAD;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+		}
+	}
+
+	/*
+	** wow! if we get here then it's a goody!
+	*/
+
+	/*
+	** Zero the (old) entries for each host...
+	*/
+	for ( Host=0; Host<RIO_HOSTS; Host++ ) {
+		for ( Entry=0; Entry<MAX_RUP; Entry++ ) {
+			bzero((caddr_t)&p->RIOHosts[Host].Mapping[Entry], 
+											sizeof(struct Map));
+		}
+		bzero((caddr_t)&p->RIOHosts[Host].Name[0],
+								sizeof(p->RIOHosts[Host].Name) );
+	}
+
+	/*
+	** Copy in the new table entries
+	*/
+	for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) {
+		rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
+		MapP = &p->RIOConnectTable[Entry];
+
+		/*
+		** Now, if it is an empty slot ignore it!
+		*/
+		if ( MapP->HostUniqueNum==0 )
+			continue;
+
+		/*
+		** we saved the host number earlier, so grab it back
+		*/
+		HostP = &p->RIOHosts[MapP->Topology[0].Unit];
+
+		/*
+		** If it is a host, then we only need to fill in the name field.
+		*/
+		if ( MapP->ID==0 ) {
+			rio_dprintk (RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
+			bcopy(MapP->Name,HostP->Name,MAX_NAME_LEN);
+			continue;
+		}
+
+		/*
+		** Its an RTA entry, so fill in the host mapping entries for it
+		** and the port mapping entries. Notice that entry zero is for
+		** ID one.
+		*/
+		HostMapP = &HostP->Mapping[MapP->ID-1];
+
+		if (MapP->Flags & SLOT_IN_USE) {
+			rio_dprintk (RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
+			/*
+			** structure assign, then sort out the bits we shouldn't have done
+			*/
+			*HostMapP = *MapP;
+
+			HostMapP->Flags = SLOT_IN_USE;
+			if (MapP->Flags & RTA16_SECOND_SLOT)
+				HostMapP->Flags |= RTA16_SECOND_SLOT;
+
+			RIOReMapPorts(p, HostP, HostMapP );
+		}
+		else {
+			rio_dprintk (RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
+		}
+	}
+
+	for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) {
+		p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
+	}
+
+	for ( Host=0; Host<p->RIONumHosts; Host++ ) {
+		for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) {
+			p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
+			p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
+		}
+		for ( Entry=0; Entry<MAX_RUP; Entry++ ) {
+			for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) {
+				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = 
+								ROUTE_DISCONNECT;
+				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = 
+								NO_LINK;
+			}
+		}
+		if ( !p->RIOHosts[Host].Name[0] ) {
+			bcopy("HOST 1",p->RIOHosts[Host].Name,7);
+			p->RIOHosts[Host].Name[5] += Host;
+		}
+		/*
+		** Check that default name assigned is unique.
+		*/
+		Host1 = Host;
+		NameIsUnique = 0;
+		while (!NameIsUnique) {
+			NameIsUnique = 1;
+			for ( Host2=0; Host2<p->RIONumHosts; Host2++ ) {
+				if (Host2 == Host)
+					continue;
+				if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
+									 == 0) {
+					NameIsUnique = 0;
+					Host1++;
+					if (Host1 >= p->RIONumHosts)
+						Host1 = 0;
+					p->RIOHosts[Host].Name[5] = '1' + Host1;
+				}
+			}
+		}
+		/*
+		** Rename host if name already used.
+		*/
+		if (Host1 != Host)
+		{
+			rio_dprintk (RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
+			bcopy("HOST 1",p->RIOHosts[Host].Name,7);
+			p->RIOHosts[Host].Name[5] += Host1;
+		}
+		rio_dprintk (RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
+	}
+	return 0;
+}
+
+/*
+** User process needs the config table - build it from first
+** principles.
+*/
+int
+RIOApel(p)
+struct rio_info *	p;
+{
+	int Host;
+	int link;
+	int Rup;
+	int Next = 0;
+	struct Map *MapP;
+	struct Host *HostP;
+	long oldspl;
+
+	disable(oldspl);		/* strange but true! */
+ 
+	rio_dprintk (RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
+
+	bzero((caddr_t)&p->RIOConnectTable[0], 
+					sizeof(struct Map) * TOTAL_MAP_ENTRIES );
+
+	for ( Host=0; Host<RIO_HOSTS; Host++ ) {
+		rio_dprintk (RIO_DEBUG_TABLE, "Processing host %d\n", Host);
+		HostP = &p->RIOHosts[Host];
+		MapP = &p->RIOConnectTable[Next++];
+		MapP->HostUniqueNum = HostP->UniqueNum;
+		if ( (HostP->Flags & RUN_STATE) != RC_RUNNING )
+			continue;
+		MapP->RtaUniqueNum = 0;
+		MapP->ID = 0;
+		MapP->Flags = SLOT_IN_USE;
+		MapP->SysPort = NO_PORT;
+		for ( link=0; link<LINKS_PER_UNIT; link++ )
+			MapP->Topology[link] = HostP->Topology[link];
+		bcopy(HostP->Name,MapP->Name,MAX_NAME_LEN);
+		for ( Rup=0; Rup<MAX_RUP; Rup++ ) {
+			if ( HostP->Mapping[Rup].Flags & (SLOT_IN_USE|SLOT_TENTATIVE) ) {
+				p->RIOConnectTable[Next] = HostP->Mapping[Rup];
+				if ( HostP->Mapping[Rup].Flags & SLOT_IN_USE)
+					p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
+				if ( HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
+					p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
+				if ( HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT )
+					p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
+				Next++;
+			}
+		}
+	}
+	restore(oldspl);
+	return 0;
+}
+
+/*
+** config.rio has taken a dislike to one of the gross maps entries.
+** if the entry is suitably inactive, then we can gob on it and remove
+** it from the table.
+*/
+int
+RIODeleteRta(p, MapP)
+struct rio_info *p;
+struct Map *MapP;
+{
+	int host, entry, port, link;
+	int SysPort;
+	struct Host *HostP;
+	struct Map *HostMapP;
+	struct Port *PortP;
+	int work_done = 0;
+	unsigned long lock_flags, sem_flags;
+
+	rio_dprintk (RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n",
+								MapP->HostUniqueNum, MapP->RtaUniqueNum);
+
+	for ( host=0; host < p->RIONumHosts; host++ ) {
+		HostP = &p->RIOHosts[host];
+
+		rio_spin_lock_irqsave( &HostP->HostLock, lock_flags );
+
+		if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+			rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
+			continue;
+		}
+
+		for ( entry=0; entry<MAX_RUP; entry++ ) {
+			if ( MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum ) {
+				HostMapP = &HostP->Mapping[entry];
+				rio_dprintk (RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", 
+						entry, HostP->Name);
+
+				/*
+				** Check all four links of the unit are disconnected
+				*/
+				for ( link=0; link< LINKS_PER_UNIT; link++ ) {
+					if ( HostMapP->Topology[link].Unit != ROUTE_DISCONNECT ) {
+						rio_dprintk (RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
+						p->RIOError.Error = UNIT_IS_IN_USE;
+						rio_spin_unlock_irqrestore( &HostP->HostLock, lock_flags);
+						return -EBUSY;
+					}
+				}
+				/*
+				** Slot has been allocated, BUT not booted/routed/
+				** connected/selected or anything else-ed
+				*/
+				SysPort = HostMapP->SysPort;
+
+				if ( SysPort != NO_PORT ) {
+					for (port=SysPort; port < SysPort+PORTS_PER_RTA; port++) {
+						PortP = p->RIOPortp[port];
+						rio_dprintk (RIO_DEBUG_TABLE, "Unmap port\n");
+
+						rio_spin_lock_irqsave( &PortP->portSem, sem_flags );
+
+						PortP->Mapped = 0;
+
+						if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) {
+
+							rio_dprintk (RIO_DEBUG_TABLE, "Gob on port\n");
+							PortP->TxBufferIn = PortP->TxBufferOut = 0;
+							/* What should I do 
+							wakeup( &PortP->TxBufferIn );
+							wakeup( &PortP->TxBufferOut);
+							*/
+							PortP->InUse = NOT_INUSE;
+							/* What should I do 
+							wakeup( &PortP->InUse );
+							signal(PortP->TtyP->t_pgrp,SIGKILL);
+							ttyflush(PortP->TtyP,(FREAD|FWRITE));
+							*/
+							PortP->State |= RIO_CLOSING | RIO_DELETED;
+						}
+
+						/*
+						** For the second slot of a 16 port RTA, the
+						** driver needs to reset the changes made to
+						** the phb to port mappings in RIORouteRup.
+						*/
+						if (PortP->SecondBlock) {
+							ushort dest_unit = HostMapP->ID;
+							ushort dest_port = port - SysPort;
+							WORD	 *TxPktP;
+							PKT	*Pkt;
+
+							for (TxPktP = PortP->TxStart;
+								TxPktP <= PortP->TxEnd; TxPktP++) {
+								/*
+								** *TxPktP is the pointer to the
+								** transmit packet on the host card.
+								** This needs to be translated into
+								** a 32 bit pointer so it can be
+								** accessed from the driver.
+								*/
+								Pkt = (PKT *) RIO_PTR(HostP->Caddr,
+								 	RWORD(*TxPktP));
+								rio_dprintk (RIO_DEBUG_TABLE, 
+						"Tx packet (%x) destination: Old %x:%x New %x:%x\n",
+								 *TxPktP, Pkt->dest_unit,
+								 Pkt->dest_port, dest_unit, dest_port);
+								WWORD(Pkt->dest_unit, dest_unit);
+								WWORD(Pkt->dest_port, dest_port);
+							}
+							rio_dprintk (RIO_DEBUG_TABLE, 
+						"Port %d phb destination: Old %x:%x New %x:%x\n",
+							 port, PortP->PhbP->destination & 0xff,
+							 (PortP->PhbP->destination >> 8) & 0xff,
+							 dest_unit, dest_port);
+							WWORD(PortP->PhbP->destination,
+							 dest_unit + (dest_port << 8));
+						}
+						rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
+					}
+				}
+				rio_dprintk (RIO_DEBUG_TABLE, "Entry nulled.\n");
+				bzero((char *)HostMapP,sizeof(struct Map));
+				work_done++;
+			}
+		}
+		rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
+	}
+
+	/* XXXXX lock me up */
+	for ( entry=0; entry< TOTAL_MAP_ENTRIES; entry++ ) {
+		if ( p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) {
+			bzero((char *)&p->RIOSavedTable[entry],sizeof(struct Map));
+			work_done++;
+		}
+		if ( p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) {
+			bzero((char *)&p->RIOConnectTable[entry],sizeof(struct Map));
+			work_done++;
+		}
+	}
+	if ( work_done )
+		return 0;
+
+	rio_dprintk (RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
+	p->RIOError.Error = COULDNT_FIND_ENTRY;
+	return -ENXIO;
+}
+
+int RIOAssignRta( struct rio_info *p, struct Map *MapP )
+{
+    int host;
+    struct Map *HostMapP;
+    char *sptr;
+    int	link;
+
+
+    rio_dprintk (RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n",
+				MapP->HostUniqueNum,MapP->RtaUniqueNum,
+				MapP->ID, (int)MapP->SysPort);
+
+    if ((MapP->ID != (ushort)-1) &&
+	((int)MapP->ID < (int)1 || (int)MapP->ID > MAX_RUP ))
+    {
+	rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
+	p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+	return -EINVAL;
+    }
+    if (MapP->RtaUniqueNum == 0)
+    {
+	rio_dprintk (RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
+	p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
+	return -EINVAL;
+    }
+    if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA) )
+    {
+	rio_dprintk (RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n",(int)MapP->SysPort,PORTS_PER_RTA);
+	p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+	return -EINVAL;
+    }
+    if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS) )
+    {
+	rio_dprintk (RIO_DEBUG_TABLE, "Port %d not valid!\n",(int)MapP->SysPort);
+	p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+	return -EINVAL;
+    }
+
+    /*
+    ** Copy the name across to the map entry.
+    */
+    MapP->Name[MAX_NAME_LEN-1] = '\0';
+    sptr = MapP->Name;
+    while ( *sptr )
+    {
+    if ( *sptr<' ' || *sptr>'~' )
+    {
+	rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
+	p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+	return -EINVAL;
+    }
+    sptr++;
+    }
+
+    for ( host=0; host < p->RIONumHosts; host++ )
+    {
+	if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum )
+	{
+	    if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING )
+	    {
+		p->RIOError.Error = HOST_NOT_RUNNING;
+		return -ENXIO;
+	    }
+
+	    /*
+	    ** Now we have a host we need to allocate an ID
+	    ** if the entry does not already have one.
+	    */
+	    if (MapP->ID == (ushort)-1)
+	    {
+		int nNewID;
+
+		rio_dprintk (RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n",
+		      MapP->Name);
+		/*
+		** The idea here is to allow RTA's to be assigned
+		** before they actually appear on the network.
+		** This allows the addition of RTA's without having
+		** to plug them in.
+		** What we do is:
+		**  - Find a free ID and allocate it to the RTA.
+		**  - If this map entry is the second half of a
+		**    16 port entry then find the other half and
+		**    make sure the 2 cross reference each other.
+		*/
+		if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0)
+		{
+		    p->RIOError.Error = COULDNT_FIND_ENTRY;
+		    return -EBUSY;
+		}
+		MapP->ID = (ushort)nNewID + 1;
+		rio_dprintk (RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
+		HostMapP = &p->RIOHosts[host].Mapping[nNewID];
+		HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
+		HostMapP->HostUniqueNum = MapP->HostUniqueNum;
+		HostMapP->ID = MapP->ID;
+		for (link = 0; link < LINKS_PER_UNIT; link++)
+		{
+		    HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
+		    HostMapP->Topology[link].Link = NO_LINK;
+		}
+		if (MapP->Flags & RTA16_SECOND_SLOT)
+		{
+		    int unit;
+
+		    for (unit = 0; unit < MAX_RUP; unit++)
+			if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum ==
+			    MapP->RtaUniqueNum)
+			    break;
+		    if (unit == MAX_RUP)
+		    {
+			p->RIOError.Error = COULDNT_FIND_ENTRY;
+			return -EBUSY;
+		    }
+		    HostMapP->Flags |= RTA16_SECOND_SLOT;
+		    HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
+		    p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
+		    rio_dprintk (RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n",
+			  MapP->ID,
+			  p->RIOHosts[host].Mapping[unit].ID);
+		}
+	    }
+
+	    HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+
+	    if ( HostMapP->Flags & SLOT_IN_USE )
+	    {
+		rio_dprintk (RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
+		p->RIOError.Error = ID_ALREADY_IN_USE;
+		return -EBUSY;
+	    }
+
+	    /*
+	    ** Assign the sys ports and the name, and mark the slot as
+	    ** being in use.
+	    */
+	    HostMapP->SysPort = MapP->SysPort;
+	    if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
+	      CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
+	    HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
+#if NEED_TO_FIX
+	    RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]);
+#endif
+	    if (MapP->Flags & RTA16_SECOND_SLOT)
+		HostMapP->Flags |= RTA16_SECOND_SLOT;
+
+	    RIOReMapPorts( p, &p->RIOHosts[host], HostMapP );
+	    /*
+	    ** Adjust 2nd block of 8 phbs
+	    */
+	    if (MapP->Flags & RTA16_SECOND_SLOT)
+		RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
+
+	    if ( HostMapP->SysPort != NO_PORT )
+	    {
+		if ( HostMapP->SysPort < p->RIOFirstPortsBooted )
+		    p->RIOFirstPortsBooted = HostMapP->SysPort;
+		if ( HostMapP->SysPort > p->RIOLastPortsBooted )
+		    p->RIOLastPortsBooted = HostMapP->SysPort;
+	    }
+	    if (MapP->Flags & RTA16_SECOND_SLOT)
+	        rio_dprintk (RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n",
+		 p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
+	    else
+	        rio_dprintk (RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
+	    return 0;
+	}
+    }
+    p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+    rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
+    return -ENXIO;
+}
+
+
+int
+RIOReMapPorts(p, HostP, HostMapP)
+struct rio_info *	p;
+struct Host *HostP;
+struct Map *HostMapP; 
+{
+	register struct Port *PortP;
+	uint SubEnt;
+	uint HostPort;
+	uint SysPort;
+	ushort RtaType;
+	unsigned long flags;
+
+#ifdef CHECK
+	CheckHostP( HostP );
+	CheckHostMapP( HostMapP );
+#endif
+
+	rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int)HostMapP->SysPort, HostMapP->ID);
+
+	/*
+	** We need to tell the UnixRups which sysport the rup corresponds to
+	*/
+	HostP->UnixRups[HostMapP->ID-1].BaseSysPort = HostMapP->SysPort;
+
+	if ( HostMapP->SysPort == NO_PORT )
+		return(0);
+
+	RtaType = GetUnitType(HostMapP->RtaUniqueNum);
+	rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n",
+				(int)HostMapP->SysPort, (int)HostMapP->SysPort+PORTS_PER_RTA-1);
+
+	/*
+	** now map each of its eight ports
+	*/
+	for ( SubEnt=0; SubEnt<PORTS_PER_RTA; SubEnt++) {
+	  rio_dprintk (RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", 
+		  SubEnt, (int)HostMapP->SysPort);
+		SysPort = HostMapP->SysPort+SubEnt;		/* portnumber within system */
+					/* portnumber on host */
+		
+		HostPort = (HostMapP->ID-1)*PORTS_PER_RTA+SubEnt; 
+
+		rio_dprintk (RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
+		PortP = p->RIOPortp[SysPort];
+#if 0
+		PortP->TtyP	= &p->channel[SysPort];
+#endif
+		rio_dprintk (RIO_DEBUG_TABLE, "Map port\n");
+
+		/*
+		** Point at all the real neat data structures
+		*/
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->HostP = HostP;
+		PortP->Caddr = HostP->Caddr;
+
+		/*
+		** The PhbP cannot be filled in yet
+		** unless the host has been booted
+		*/
+		if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
+			struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
+			PortP->TxAdd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_add));
+			PortP->TxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_start));
+			PortP->TxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_end));
+			PortP->RxRemove=(WORD *)RIO_PTR(HostP->Caddr,
+									RWORD(PhbP->rx_remove));
+			PortP->RxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_start));
+			PortP->RxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_end));
+		}
+		else
+			PortP->PhbP = NULL;
+
+		/*
+		** port related flags
+		*/
+		PortP->HostPort	= HostPort;
+		/*
+		** For each part of a 16 port RTA, RupNum is ID - 1.
+		*/
+		PortP->RupNum = HostMapP->ID - 1;
+		if (HostMapP->Flags & RTA16_SECOND_SLOT) {
+			PortP->ID2			 = HostMapP->ID2 - 1;
+			PortP->SecondBlock	 = TRUE;
+		}
+		else {
+			PortP->ID2			 = 0;
+			PortP->SecondBlock	 = FALSE;
+		}
+		PortP->RtaUniqueNum	= HostMapP->RtaUniqueNum;
+
+		/*
+		** If the port was already mapped then thats all we need to do.
+		*/
+		if (PortP->Mapped) {
+			rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+			continue;
+		}
+		else HostMapP->Flags &= ~RTA_NEWBOOT;
+
+		PortP->State		 = 0;
+		PortP->Config		= 0;
+		/*
+		** Check out the module type - if it is special (read only etc.)
+		** then we need to set flags in the PortP->Config.
+		** Note: For 16 port RTA, all ports are of the same type.
+		*/
+		if (RtaType == TYPE_RTA16) {
+			PortP->Config |= p->RIOModuleTypes[HostP->UnixRups
+				[HostMapP->ID-1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
+		} else {
+			if ( SubEnt < PORTS_PER_MODULE )
+				PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups
+				[HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+			else
+				PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups
+				[HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+		}
+
+		/*
+		** more port related flags
+		*/
+		PortP->PortState	= 0;
+		PortP->ModemLines	= 0;
+		PortP->ModemState	= 0;
+		PortP->CookMode		= COOK_WELL;
+		PortP->ParamSem		= 0;
+		PortP->FlushCmdBodge= 0;
+		PortP->WflushFlag	= 0;
+		PortP->MagicFlags	= 0;
+		PortP->Lock			= 0;
+		PortP->Store		= 0;
+		PortP->FirstOpen	= 1;
+
+		/*
+		** Buffers 'n things
+		*/
+		PortP->RxDataStart	= 0;
+		PortP->Cor2Copy	 = 0;
+		PortP->Name		 = &HostMapP->Name[0];
+#ifdef STATS
+		bzero( (caddr_t)&PortP->Stat, sizeof(struct RIOStats) );
+#endif
+		PortP->statsGather = 0;
+		PortP->txchars = 0;
+		PortP->rxchars = 0;
+		PortP->opens = 0;
+		PortP->closes = 0;
+		PortP->ioctls = 0;
+		if ( PortP->TxRingBuffer )
+			bzero( PortP->TxRingBuffer, p->RIOBufferSize );
+		else if ( p->RIOBufferSize ) {
+			PortP->TxRingBuffer = sysbrk(p->RIOBufferSize);
+			bzero( PortP->TxRingBuffer, p->RIOBufferSize );
+		}
+		PortP->TxBufferOut	= 0;
+		PortP->TxBufferIn	 = 0;
+		PortP->Debug		= 0;
+		/*
+		** LastRxTgl stores the state of the rx toggle bit for this
+		** port, to be compared with the state of the next pkt received.
+		** If the same, we have received the same rx pkt from the RTA
+		** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
+		*/
+		PortP->LastRxTgl	= ~(uchar)PHB_RX_TGL;
+
+		/*
+		** and mark the port as usable
+		*/
+		PortP->Mapped = 1;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	}
+	if ( HostMapP->SysPort < p->RIOFirstPortsMapped )
+		p->RIOFirstPortsMapped = HostMapP->SysPort;
+	if ( HostMapP->SysPort > p->RIOLastPortsMapped )
+		p->RIOLastPortsMapped = HostMapP->SysPort;
+
+	return 0;
+}
+
+int
+RIOChangeName(p, MapP)
+struct rio_info *p;
+struct Map* MapP; 
+{
+	int host;
+	struct Map *HostMapP;
+	char *sptr;
+
+	rio_dprintk (RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n",
+								MapP->HostUniqueNum,MapP->RtaUniqueNum,
+								MapP->ID, (int)MapP->SysPort);
+
+	if ( MapP->ID > MAX_RUP ) {
+		rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
+		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+		return -EINVAL;
+	}
+
+	MapP->Name[MAX_NAME_LEN-1] = '\0';
+	sptr = MapP->Name;
+
+	while ( *sptr ) {
+		if ( *sptr<' ' || *sptr>'~' ) {
+			rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
+			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+			return -EINVAL;
+		}
+		sptr++;
+	}
+
+	for ( host=0; host < p->RIONumHosts; host++ ) {
+		if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum ) {
+			if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING ) {
+				p->RIOError.Error = HOST_NOT_RUNNING;
+				return -ENXIO;
+			}
+			if ( MapP->ID==0 ) {
+				CCOPY( MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN );
+				return 0;
+			}
+
+			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+
+			if ( HostMapP->RtaUniqueNum != MapP->RtaUniqueNum ) {
+				p->RIOError.Error = RTA_NUMBER_WRONG;
+				return -ENXIO;
+			}
+			CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
+			return 0;
+		}
+	}
+	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+	rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
+	return -ENXIO;
+}
diff --git a/drivers/char/rio/riotime.h b/drivers/char/rio/riotime.h
new file mode 100644
index 0000000..66d52bc0
--- /dev/null
+++ b/drivers/char/rio/riotime.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+ *******                                                              *******
+ *******            T I M E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _riotime_h
+#define _riotime_h 1
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_riotime_h_sccs = "@(#)riotime.h	1.1" ;
+#endif
+#endif
+
+#define TWO_POWER_FIFTEEN (ushort)32768
+#define RioTime()    riotime
+#define RioTimeAfter(time1,time2) ((ushort)time1 - (ushort)time2) < TWO_POWER_FIFTEEN
+#define RioTimePlus(time1,time2) ((ushort)time1 + (ushort)time2)
+
+/**************************************
+ * Convert a RIO tick (1/10th second)
+ * into transputer low priority ticks
+ *************************************/ 
+#define RioTimeToLow(time) (time*(100000 / 64))
+#define RioLowToTime(time) ((time*64)/100000)
+
+#define RIOTENTHSECOND (ushort)1
+#define RIOSECOND (ushort)(RIOTENTHSECOND * 10)
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
new file mode 100644
index 0000000..db65500
--- /dev/null
+++ b/drivers/char/rio/riotty.c
@@ -0,0 +1,1376 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riotty.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:47
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)riotty.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+#ifdef SCCS_LABELS
+static char *_riotty_c_sccs_ = "@(#)riotty.c	1.3";
+#endif
+
+
+#define __EXPLICIT_DEF_H__
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "typdef.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "top.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "riotypes.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "error.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "control.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "list.h"
+#include "sam.h"
+
+#if 0
+static void ttyseth_pv(struct Port *, struct ttystatics *, 
+				struct termios *sg, int);
+#endif
+
+static void RIOClearUp(struct Port *PortP);
+int RIOShortCommand(struct rio_info *p, struct Port *PortP, 
+			   int command, int len, int arg);
+
+#if 0
+static int RIOCookMode(struct ttystatics *);
+#endif
+
+extern int	conv_vb[];	/* now defined in ttymgr.c */
+extern int	conv_bv[];	/* now defined in ttymgr.c */
+ 
+/*
+** 16.09.1998 ARG - Fix to build riotty.k.o for Modular Kernel Support
+**
+** ep.def.h is necessary for Modular Kernel Support
+** DO NOT place any kernel 'extern's after this line
+** or this source file will not build riotty.k.o
+*/
+#ifdef uLYNX
+#include <ep.def.h>
+#endif
+
+#ifdef NEED_THIS2
+static struct old_sgttyb 
+default_sg = 
+{ 
+	B19200, B19200,				/* input and output speed */ 
+	'H' - '@',					/* erase char */ 
+	-1,							/* 2nd erase char */ 
+	'U' - '@',					/* kill char */ 
+	ECHO | CRMOD,				/* mode */ 
+	'C' - '@',					/* interrupt character */ 
+	'\\' - '@',					/* quit char */ 
+	'Q' - '@',					/* start char */
+	'S' - '@',					/* stop char */ 
+	'D' - '@',					/* EOF */
+	-1,							/* brk */
+	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */ 
+	'Z' - '@',					/* process stop */
+	'Y' - '@',					/* delayed stop */
+	'R' - '@',					/* reprint line */ 
+	'O' - '@',					/* flush output */
+	'W' - '@',					/* word erase */
+	'V' - '@'					/* literal next char */
+};
+#endif
+
+
+extern struct rio_info *p;
+
+
+int
+riotopen(struct tty_struct * tty, struct file * filp)
+{
+	register uint SysPort;
+	int Modem;
+	int repeat_this = 250;
+	struct Port *PortP;		 /* pointer to the port structure */
+	unsigned long flags;
+	int retval = 0;
+
+	func_enter ();
+
+	/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
+	   is going to oops.
+	*/
+	tty->driver_data = NULL;
+        
+	SysPort = rio_minor(tty);
+	Modem   = rio_ismodem(tty);
+
+	if ( p->RIOFailed ) {
+		rio_dprintk (RIO_DEBUG_TTY, "System initialisation failed\n");
+		pseterr(ENXIO);
+		func_exit ();
+		return -ENXIO;
+	}
+
+	rio_dprintk (RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n",
+	       SysPort,  Modem ? "Modem" : "tty",
+				   p->RIOPortp[SysPort]->Mapped);
+
+	/*
+	** Validate that we have received a legitimate request.
+	** Currently, just check that we are opening a port on
+	** a host card that actually exists, and that the port
+	** has been mapped onto a host.
+	*/
+	if (SysPort >= RIO_PORTS) {	/* out of range ? */
+		rio_dprintk (RIO_DEBUG_TTY, "Illegal port number %d\n",SysPort);
+		pseterr(ENXIO);
+		func_exit();
+		return -ENXIO;
+	}
+
+	/*
+	** Grab pointer to the port stucture
+	*/
+	PortP = p->RIOPortp[SysPort];	/* Get control struc */
+	rio_dprintk (RIO_DEBUG_TTY, "PortP: %p\n", PortP);
+	if ( !PortP->Mapped ) {	/* we aren't mapped yet! */
+		/*
+		** The system doesn't know which RTA this port
+		** corresponds to.
+		*/
+		rio_dprintk (RIO_DEBUG_TTY, "port not mapped into system\n");
+		func_exit ();
+		pseterr(ENXIO);
+		return -ENXIO;
+	}
+
+	tty->driver_data = PortP;
+
+	PortP->gs.tty = tty;
+	PortP->gs.count++;
+
+	rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n",
+				   PortP->gs.xmit_cnt);
+
+	retval = gs_init_port (&PortP->gs);
+	if (retval) {
+		PortP->gs.count--;
+		return -ENXIO;
+	}
+	/*
+	** If the host hasn't been booted yet, then 
+	** fail
+	*/
+	if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Host not running\n");
+		pseterr(ENXIO);
+		func_exit ();
+		return -ENXIO;
+	}
+
+	/*
+	** If the RTA has not booted yet and the user has choosen to block
+	** until the RTA is present then we must spin here waiting for
+	** the RTA to boot.
+	*/
+#if 0
+	if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
+		if (PortP->WaitUntilBooted) {
+			rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot\n");
+			do {
+				if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+					rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+					func_exit ();
+					return -EINTR;
+				}
+				if (repeat_this -- <= 0) {
+					rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
+					RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+					pseterr(EINTR);
+					func_exit ();
+					return -EIO;
+				}
+			} while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
+			rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n");
+		} else {
+			rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n");
+			pseterr(ENXIO);
+			func_exit ();
+			return 0;
+		}
+	}
+#else
+	/* I find the above code a bit hairy. I find the below code
+           easier to read and shorter. Now, if it works too that would
+	   be great... -- REW 
+	*/
+	rio_dprintk (RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
+	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
+	  if (!PortP->WaitUntilBooted) {
+	    rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n");
+	    func_exit ();
+	    return -ENXIO;
+	  }
+
+	  /* Under Linux you'd normally use a wait instead of this
+	     busy-waiting. I'll stick with the old implementation for
+	     now. --REW 
+	  */
+	  if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+	    rio_dprintk (RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
+	    func_exit ();
+	    return -EINTR;
+	  }
+	  if (repeat_this -- <= 0) {
+	    rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
+	    func_exit ();
+	    return -EIO;
+	  }
+	}
+	rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n");
+#endif
+#if 0
+	tp =  PortP->TtyP;		/* get tty struct */
+#endif
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	if ( p->RIOHalted ) {
+		goto bombout;
+	}
+#if 0
+	retval = gs_init_port(&PortP->gs);
+	if (retval){
+		func_exit ();
+		return retval;
+	}
+#endif
+
+	/*
+	** If the port is in the final throws of being closed,
+	** we should wait here (politely), waiting
+	** for it to finish, so that it doesn't close us!
+	*/
+	while ( (PortP->State & RIO_CLOSING) && !p->RIOHalted ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
+		if (repeat_this -- <= 0) {
+			rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+			RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+			retval = -EINTR;
+			goto bombout;
+		}
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+			rio_spin_lock_irqsave(&PortP->portSem, flags); 
+			retval = -EINTR;
+			goto bombout;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags); 
+	}
+
+	if ( !PortP->Mapped ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Port unmapped while closing!\n");
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		retval = -ENXIO;
+		func_exit ();
+		return retval;
+	}
+
+	if ( p->RIOHalted ) {
+		goto bombout;
+	}
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,
+** we need to make sure that the flags are clear when the port is opened.
+*/
+	/* Uh? Suppose I turn these on and then another process opens
+	   the port again? The flags get cleared! Not good. -- REW */
+	if ( !(PortP->State & (RIO_LOPEN | RIO_MOPEN)) ) {
+		PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
+	}
+
+	if (!(PortP->firstOpen)) {	/* First time ? */
+		rio_dprintk (RIO_DEBUG_TTY, "First open for this port\n");
+	
+
+		PortP->firstOpen++;
+		PortP->CookMode = 0; /* XXX RIOCookMode(tp); */
+		PortP->InUse = NOT_INUSE;
+
+		/* Tentative fix for bug PR27. Didn't work. */
+		/* PortP->gs.xmit_cnt = 0; */
+
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+#ifdef NEED_THIS
+		ttyseth(PortP, tp, (struct old_sgttyb *)&default_sg);
+#endif
+
+		/* Someone explain to me why this delay/config is
+                   here. If I read the docs correctly the "open"
+                   command piggybacks the parameters immediately. 
+		   -- REW */
+		RIOParam(PortP,OPEN,Modem,OK_TO_SLEEP);		/* Open the port */
+#if 0
+		/* This delay of 1 second was annoying. I removed it. -- REW */
+		RIODelay(PortP, HUNDRED_MS*10);
+		RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	/* Config the port */
+#endif
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+		/*
+		** wait for the port to be not closed.
+		*/
+		while ( !(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted ) {
+			rio_dprintk (RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n",PortP->PortState);
+/*
+** 15.10.1998 ARG - ESIL 0759
+** (Part) fix for port being trashed when opened whilst RTA "disconnected"
+** Take out the limited wait - now wait for ever or until user
+** bangs us out.
+**
+			if (repeat_this -- <= 0) {
+				rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish timed out.\n"));
+				RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				return -EINTR;
+			}
+**
+*/
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+				rio_dprintk (RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
+				RIOPreemptiveCmd(p, PortP, FCLOSE );
+				func_exit ();
+				return -EINTR;
+			}
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+		}
+
+		if ( p->RIOHalted ) {
+		  retval = -EIO;
+bombout:
+		  /* 			RIOClearUp( PortP ); */
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return retval;
+		}
+		rio_dprintk (RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
+	}
+
+#ifdef MODEM_SUPPORT 
+	if (Modem) {
+		rio_dprintk (RIO_DEBUG_TTY, "Modem - test for carrier\n");
+		/*
+		** ACTION
+		** insert test for carrier here. -- ???
+		** I already see that test here. What's the deal? -- REW
+		*/
+		if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD))
+		{
+			rio_dprintk (RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
+			/*
+			tp->tm.c_state |= CARR_ON;
+			wakeup((caddr_t) &tp->tm.c_canq);
+			*/
+			PortP->State |= RIO_CARR_ON;
+			wake_up_interruptible (&PortP->gs.open_wait);
+		}
+		else /* no carrier - wait for DCD */
+		{
+		  /*
+			while (!(PortP->gs.tty->termios->c_state & CARR_ON) && 
+			       !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
+		  */
+			while (!(PortP->State & RIO_CARR_ON) && 
+			       !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) {
+
+				rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n",SysPort);
+				/*
+				PortP->gs.tty->termios->c_state |= WOPEN;
+				*/
+				PortP->State |= RIO_WOPEN;
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				if (RIODelay (PortP, HUNDRED_MS) == RIO_FAIL)
+#if 0
+				if ( sleep((caddr_t)&tp->tm.c_canqo, TTIPRI|PCATCH))
+#endif
+				{
+					/*
+					** ACTION: verify that this is a good thing
+					** to do here. -- ???
+					** I think it's OK. -- REW
+					*/
+					rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n",
+					       SysPort);
+					RIOPreemptiveCmd( p, PortP, FCLOSE );
+					/*
+					tp->tm.c_state &= ~WOPEN;
+					*/
+					PortP->State &= ~RIO_WOPEN;
+					rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+					func_exit ();
+					return -EINTR;
+				}
+			}
+			PortP->State &= ~RIO_WOPEN;
+		}
+		if ( p->RIOHalted )
+			goto bombout;
+		rio_dprintk (RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
+		PortP->State |= RIO_MOPEN;
+	}
+	else
+#endif
+	{
+		/*
+		** ACTION
+		** Direct line open - force carrier (will probably mean
+		** that sleeping Modem line fubar)
+		*/
+		PortP->State |= RIO_LOPEN;
+	}
+
+	if ( p->RIOHalted ) {
+		goto bombout;
+	}
+
+	rio_dprintk (RIO_DEBUG_TTY, "high level open done\n");
+
+#ifdef STATS
+	PortP->Stat.OpenCnt++;
+#endif
+	/*
+	** Count opens for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->opens++;
+
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	rio_dprintk (RIO_DEBUG_TTY, "Returning from open\n");
+	func_exit ();
+	return 0;
+}
+
+/*
+** RIOClose the port.
+** The operating system thinks that this is last close for the device.
+** As there are two interfaces to the port (Modem and tty), we need to
+** check that both are closed before we close the device.
+*/ 
+int
+riotclose(void  *ptr)
+{
+#if 0
+	register uint SysPort = dev;
+	struct ttystatics *tp;		/* pointer to our ttystruct */
+#endif
+	struct Port *PortP =ptr;	/* pointer to the port structure */
+	int deleted = 0;
+	int	try = -1; /* Disable the timeouts by setting them to -1 */
+	int	repeat_this = -1; /* Congrats to those having 15 years of 
+				     uptime! (You get to break the driver.) */
+	long end_time;
+	struct tty_struct * tty;
+	unsigned long flags;
+	int Modem;
+	int rv =0;
+	
+	rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum);
+
+	/* PortP = p->RIOPortp[SysPort]; */
+	rio_dprintk (RIO_DEBUG_TTY, "Port is at address 0x%x\n",(int)PortP);
+	/* tp = PortP->TtyP;*/			/* Get tty */
+	tty = PortP->gs.tty;
+	rio_dprintk (RIO_DEBUG_TTY, "TTY is at address 0x%x\n",(int)tty);
+
+	if (PortP->gs.closing_wait) 
+		end_time = jiffies + PortP->gs.closing_wait;
+	else 
+		end_time = jiffies + MAX_SCHEDULE_TIMEOUT;
+
+	Modem = rio_ismodem(tty);
+#if 0
+	/* What F.CKING cache? Even then, a higly idle multiprocessor,
+	   system with large caches this won't work . Better find out when 
+	   this doesn't work asap, and fix the cause.  -- REW */
+	
+	RIODelay(PortP, HUNDRED_MS*10);	/* To flush the cache */
+#endif
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	/*
+	** Setting this flag will make any process trying to open
+	** this port block until we are complete closing it.
+	*/
+	PortP->State |= RIO_CLOSING;
+
+	if ( (PortP->State & RIO_DELETED) ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Close on deleted RTA\n");
+		deleted = 1;
+	}
+	
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		rv = -EIO;
+		goto close_end;
+	}
+
+	rio_dprintk (RIO_DEBUG_TTY, "Clear bits\n");
+	/*
+	** clear the open bits for this device
+	*/
+	PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN);
+	PortP->State &= ~RIO_CARR_ON;
+	PortP->ModemState &= ~MSVR1_CD;
+	/*
+	** If the device was open as both a Modem and a tty line
+	** then we need to wimp out here, as the port has not really
+	** been finally closed (gee, whizz!) The test here uses the
+	** bit for the OTHER mode of operation, to see if THAT is
+	** still active!
+	*/
+	if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {
+		/*
+		** The port is still open for the other task -
+		** return, pretending that we are still active.
+		*/
+		rio_dprintk (RIO_DEBUG_TTY, "Channel %d still open !\n",PortP->PortNum);
+		PortP->State &= ~RIO_CLOSING;
+		if (PortP->firstOpen)
+			PortP->firstOpen--;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return -EIO;
+	}
+
+	rio_dprintk (RIO_DEBUG_TTY, "Closing down - everything must go!\n");
+
+	PortP->State &= ~RIO_DYNOROD;
+
+	/*
+	** This is where we wait for the port
+	** to drain down before closing. Bye-bye....
+	** (We never meant to do this)
+	*/
+	rio_dprintk (RIO_DEBUG_TTY, "Timeout 1 starts\n");
+
+	if (!deleted)
+	while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted && 
+		(PortP->TxBufferIn != PortP->TxBufferOut) ) {
+		cprintf("Need to flush the ttyport\n");
+		if (repeat_this -- <= 0) {
+			rv = -EINTR;
+			rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+			RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+			goto close_end;
+		}
+		rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (RIODelay_ni(PortP, HUNDRED_MS*10) == RIO_FAIL) {
+			rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+			rv = -EINTR;
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+			goto close_end;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+
+	PortP->TxBufferIn = PortP->TxBufferOut = 0;
+	repeat_this = 0xff;
+
+	PortP->InUse = 0;
+	if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {
+		/*
+		** The port has been re-opened for the other task -
+		** return, pretending that we are still active.
+		*/
+		rio_dprintk (RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
+		PortP->State &= ~RIO_CLOSING;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (PortP->firstOpen)
+			PortP->firstOpen--;
+		return -EIO;
+	}
+
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		goto close_end;
+	}
+
+	
+
+	/* Can't call RIOShortCommand with the port locked. */
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+	if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
+	  RIOPreemptiveCmd(p, PortP,FCLOSE);
+	  goto close_end;
+	}
+
+	if (!deleted)
+	  while (try && (PortP->PortState & PORT_ISOPEN)) {
+	        try--;
+		if (time_after (jiffies, end_time)) {
+		  rio_dprintk (RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n" );
+		  RIOPreemptiveCmd(p, PortP,FCLOSE);
+		  break;
+		}
+		rio_dprintk (RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", 
+					   PortP->PortState & PORT_ISOPEN);
+
+		if ( p->RIOHalted ) {
+			RIOClearUp( PortP );
+			goto close_end;
+		}
+		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+			rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+			RIOPreemptiveCmd(p, PortP,FCLOSE);
+			break;
+		}
+	}
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	rio_dprintk (RIO_DEBUG_TTY, "Close: try was %d on completion\n", try );
+ 
+	/* RIOPreemptiveCmd(p, PortP, FCLOSE); */
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
+*/
+	PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
+
+
+#ifdef STATS
+	PortP->Stat.CloseCnt++;
+#endif
+	/*
+	** Count opens for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->closes++;
+
+close_end:
+	/* XXX: Why would a "DELETED" flag be reset here? I'd have
+	   thought that a "deleted" flag means that the port was
+	   permanently gone, but here we can make it reappear by it
+	   being in close during the "deletion".
+	*/
+	PortP->State &= ~(RIO_CLOSING|RIO_DELETED);
+	if (PortP->firstOpen)
+		PortP->firstOpen--;
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	rio_dprintk (RIO_DEBUG_TTY, "Return from close\n");
+	return rv;
+}
+
+
+/*
+** decide if we need to use the line discipline.
+** This routine can return one of three values:
+** COOK_RAW if no processing has to be done by the line discipline or the card
+** COOK_WELL if the line discipline must be used to do the processing
+** COOK_MEDIUM if the card can do all the processing necessary.
+*/
+#if 0
+static int
+RIOCookMode(struct ttystatics *tp)
+{
+	/*
+	** We can't handle tm.c_mstate != 0 on SCO
+	** We can't handle mapping
+	** We can't handle non-ttwrite line disc.
+	** We can't handle lflag XCASE
+	** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3)
+	*/
+
+#ifdef CHECK
+	CheckTtyP( tp );
+#endif
+	if (!(tp->tm.c_oflag & OPOST))	/* No post processing */
+		return COOK_RAW;	/* Raw mode o/p */
+
+	if ( tp->tm.c_lflag & XCASE )
+		return COOK_WELL;	/* Use line disc */
+
+	if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3 ) )
+		return COOK_WELL;	/* Use line disc for strange modes */
+
+	if ( tp->tm.c_oflag == OPOST )	/* If only OPOST is set, do RAW */
+		return COOK_RAW;
+
+	/*
+	** So, we need to output process!
+	*/
+	return COOK_MEDIUM;
+}
+#endif
+
+static void
+RIOClearUp(PortP)
+struct Port *PortP;
+{
+	rio_dprintk (RIO_DEBUG_TTY, "RIOHalted set\n");
+	PortP->Config = 0;	  /* Direct semaphore */
+	PortP->PortState = 0;
+	PortP->firstOpen = 0;
+	PortP->FlushCmdBodge = 0;
+	PortP->ModemState = PortP->CookMode = 0;
+	PortP->Mapped = 0;
+	PortP->WflushFlag = 0;
+	PortP->MagicFlags	= 0;
+	PortP->RxDataStart = 0;
+	PortP->TxBufferIn = 0;
+	PortP->TxBufferOut = 0;
+}
+
+/*
+** Put a command onto a port.
+** The PortPointer, command, length and arg are passed.
+** The len is the length *inclusive* of the command byte,
+** and so for a command that takes no data, len==1.
+** The arg is a single byte, and is only used if len==2.
+** Other values of len aren't allowed, and will cause
+** a panic.
+*/
+int RIOShortCommand(struct rio_info *p, struct Port *PortP,
+		int command, int len, int arg)
+{
+	PKT *PacketP;
+	int		retries = 20; /* at 10 per second -> 2 seconds */
+	unsigned long flags;
+
+	rio_dprintk (RIO_DEBUG_TTY, "entering shortcommand.\n");
+#ifdef CHECK
+	CheckPortP( PortP );
+	if ( len < 1 || len > 2 )
+		cprintf(("STUPID LENGTH %d\n",len));
+#endif
+
+	if ( PortP->State & RIO_DELETED ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
+		return RIO_FAIL;
+	}
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	/*
+	** If the port is in use for pre-emptive command, then wait for it to 
+	** be free again.
+	*/
+	while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", 
+					   retries);
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (retries-- <= 0) {
+			return RIO_FAIL;
+		}
+		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
+			return RIO_FAIL;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+	if ( PortP->State & RIO_DELETED ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return RIO_FAIL;
+	}
+
+	while ( !can_add_transmit(&PacketP,PortP) && !p->RIOHalted ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (retries-- <= 0) {
+		  rio_dprintk (RIO_DEBUG_TTY, "out of tries. Failing\n");
+			return RIO_FAIL;
+		}
+		if ( RIODelay_ni(PortP, HUNDRED_MS)==RIO_FAIL ) {
+			return RIO_FAIL;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+
+	if ( p->RIOHalted ) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return RIO_FAIL;
+	}
+
+	/*
+	** set the command byte and the argument byte
+	*/
+	WBYTE(PacketP->data[0] , command);
+
+	if ( len==2 )
+		WBYTE(PacketP->data[1] , arg);
+
+	/*
+	** set the length of the packet and set the command bit.
+	*/
+	WBYTE(PacketP->len , PKT_CMD_BIT | len);
+
+	add_transmit(PortP);
+	/*
+	** Count characters transmitted for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->txchars += len;
+
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;
+}
+
+
+#if 0
+/*
+** This is an ioctl interface. This is the twentieth century. You know what
+** its all about.
+*/
+int
+riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
+{
+	register struct		Port *PortP;
+	register struct		ttystatics *tp;
+	int					current;
+	int					ParamSemIncremented = 0;
+	int					old_oflag, old_cflag, old_iflag, changed, oldcook;
+	int					i;
+	unsigned char		sio_regs[5];		/* Here be magic */
+	short				vpix_cflag;
+	short				divisor;
+	int					baud;
+	uint				SysPort = rio_minor(tty);
+	int				Modem = rio_ismodem(tty);
+	int					ioctl_processed;
+
+	rio_dprintk (RIO_DEBUG_TTY, "port ioctl SysPort %d command 0x%x argument 0x%x %s\n",
+			SysPort, cmd, arg, Modem?"Modem":"tty") ;
+
+	if ( SysPort >= RIO_PORTS ) {
+		rio_dprintk (RIO_DEBUG_TTY, "Bad port number %d\n", SysPort);
+		return -ENXIO;
+	}
+
+	PortP = p->RIOPortp[SysPort];
+	tp = PortP->TtyP;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+#ifdef STATS
+	PortP->Stat.IoctlCnt++;
+#endif
+
+	if ( PortP->State & RIO_DELETED ) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return -EIO;
+	}
+
+
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return -EIO;
+	}
+
+	/*
+	** Count ioctls for port statistics reporting
+	*/
+	if (PortP->statsGather)
+		PortP->ioctls++;
+
+	/*
+	** Specialix RIO Ioctl calls
+	*/
+	switch (cmd) {
+
+		case TCRIOTRIAD:
+			if ( arg )
+				PortP->State |= RIO_TRIAD_MODE;
+			else
+				PortP->State &= ~RIO_TRIAD_MODE;
+			/*
+			** Normally, when istrip is set on a port, a config is
+			** sent to the RTA instructing the CD1400 to do the
+			** stripping. In TRIAD mode, the interrupt receive routine
+			** must do the stripping instead, since it has to detect
+			** an 8 bit function key sequence. If istrip is set with
+			** TRIAD mode on(off), and 8 bit data is being read by
+			** the port, the user then turns TRIAD mode off(on), the RTA
+			** must be reconfigured (not) to do the stripping.
+			** Hence we call RIOParam here.
+			*/
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+		case TCRIOTSTATE:
+			rio_dprintk (RIO_DEBUG_TTY, "tbusy/tstop monitoring %sabled\n",
+		 		arg ? "en" : "dis");
+			/* MonitorTstate = 0 ;*/
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
+			return 0;
+
+		case TCRIOSTATE: /* current state of Modem input pins */
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE\n");
+			if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL)
+				rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE command failed\n");
+			PortP->State |= RIO_BUSY;
+			current = PortP->ModemState;
+			if ( copyout((caddr_t)&current, (int)arg,
+							sizeof(current))==COPYFAIL ) {
+				rio_dprintk (RIO_DEBUG_TTY, "Copyout failed\n");
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EFAULT);
+			}
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOMBIS:		/* Set modem lines */
+		case TCRIOMBIC:		/* Clear modem lines */
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIS/TCRIOMBIC\n");
+			if (cmd == TCRIOMBIS) {
+				uint		state;
+				state = (uint)arg;
+				PortP->ModemState |= (ushort)state;
+				PortP->ModemLines = (ulong) arg;
+				if (RIOPreemptiveCmd(p, PortP, MBIS) == RIO_FAIL)
+					rio_dprintk (RIO_DEBUG_TTY, 
+					 "TCRIOMBIS command failed\n");
+			}
+			else {
+				uint		state;
+
+				state = (uint)arg;
+				PortP->ModemState &= ~(ushort)state;
+				PortP->ModemLines = (ulong) arg;
+				if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL)
+					rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIC command failed\n");
+			}
+			PortP->State |= RIO_BUSY;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOXPON: /* set Xprint ON string */
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPON\n");
+			if ( copyin((int)arg, (caddr_t)PortP->Xprint.XpOn,
+						MAX_XP_CTRL_LEN)==COPYFAIL ) {
+				rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n");
+				PortP->Xprint.XpOn[0] = '\0';
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EFAULT);
+			}
+			PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
+			PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+
+												strlen(PortP->Xprint.XpOff);
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOXPOFF: /* set Xprint OFF string */
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPOFF\n");
+			if ( copyin( (int)arg, (caddr_t)PortP->Xprint.XpOff,
+						MAX_XP_CTRL_LEN)==COPYFAIL ) {
+				rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n");
+				PortP->Xprint.XpOff[0] = '\0';
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EFAULT);
+			}
+			PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
+			PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+
+										strlen(PortP->Xprint.XpOff);
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOXPCPS: /* set Xprint CPS string */
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPCPS\n");
+			if ( (uint)arg > p->RIOConf.MaxXpCps || 
+					(uint)arg < p->RIOConf.MinXpCps ) {
+				rio_dprintk (RIO_DEBUG_TTY, "%d CPS out of range\n",arg);
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EINVAL);
+				return 0;
+			}
+			PortP->Xprint.XpCps = (uint)arg;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOXPRINT:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPRINT\n");
+			if ( copyout((caddr_t)&PortP->Xprint, (int)arg,
+					sizeof(struct Xprint))==COPYFAIL ) {
+			        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				pseterr(EFAULT);
+			}
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOIXANYON:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYON\n");
+			PortP->Config |= RIO_IXANY;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOIXANYOFF:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYOFF\n");
+			PortP->Config &= ~RIO_IXANY;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOIXONON:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONON\n");
+			PortP->Config |= RIO_IXON;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+		case TCRIOIXONOFF:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONOFF\n");
+			PortP->Config &= ~RIO_IXON;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** Added support for CTS and RTS flow control ioctls :
+*/
+		case TCRIOCTSFLOWEN:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWEN\n");
+			PortP->Config |= RIO_CTSFLOW;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+		case TCRIOCTSFLOWDIS:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWDIS\n");
+			PortP->Config &= ~RIO_CTSFLOW;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+		case TCRIORTSFLOWEN:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWEN\n");
+			PortP->Config |= RIO_RTSFLOW;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+		case TCRIORTSFLOWDIS:
+			rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWDIS\n");
+			PortP->Config &= ~RIO_RTSFLOW;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+			return 0;
+
+/* end ESIL 0761 part fix */
+
+	}
+
+
+	/* Lynx IOCTLS */
+	switch (cmd) {
+		case TIOCSETP:
+		case TIOCSETN:
+		case OTIOCSETP:
+		case OTIOCSETN:
+			ioctl_processed++;
+			ttyseth(PortP, tp, (struct old_sgttyb *)arg);
+			break;
+		case TCSETA:
+		case TCSETAW:
+		case TCSETAF:
+			ioctl_processed++;
+			rio_dprintk (RIO_DEBUG_TTY, "NON POSIX ioctl\n");
+			ttyseth_pv(PortP, tp, (struct termios *)arg, 0);
+			break;
+		case TCSETAP:	/* posix tcsetattr() */
+		case TCSETAWP:	/* posix tcsetattr() */
+		case TCSETAFP:	/* posix tcsetattr() */
+			rio_dprintk (RIO_DEBUG_TTY, "NON POSIX SYSV ioctl\n");
+			ttyseth_pv(PortP, tp, (struct termios *)arg, 1);
+			ioctl_processed++;
+			break;
+	}
+
+	/*
+	** If its any of the commands that require the port to be in the
+	** non-busy state wait until all output has drained 
+	*/
+	if (!ioctl_processed)
+	switch(cmd) {
+		case TCSETAW:
+		case TCSETAF:
+		case TCSETA:
+		case TCSBRK:
+#define OLD_POSIX ('x' << 8)
+#define OLD_POSIX_SETA (OLD_POSIX | 2)
+#define OLD_POSIX_SETAW (OLD_POSIX | 3)
+#define OLD_POSIX_SETAF (OLD_POSIX | 4)
+#define NEW_POSIX (('i' << 24) | ('X' << 16))
+#define NEW_POSIX_SETA (NEW_POSIX | 2)
+#define NEW_POSIX_SETAW (NEW_POSIX | 3)
+#define NEW_POSIX_SETAF (NEW_POSIX | 4)
+		case OLD_POSIX_SETA:
+		case OLD_POSIX_SETAW:
+		case OLD_POSIX_SETAF:
+		case NEW_POSIX_SETA:
+		case NEW_POSIX_SETAW:
+		case NEW_POSIX_SETAF:
+#ifdef TIOCSETP
+		case TIOCSETP:
+#endif
+		case TIOCSETD:
+		case TIOCSETN:
+			rio_dprintk (RIO_DEBUG_TTY, "wait for non-BUSY, semaphore set\n");
+			/*
+			** Wait for drain here, at least as far as the double buffer
+			** being empty.
+			*/
+			/* XXX Does the above comment mean that this has
+			   still to be implemented? -- REW */
+			/* XXX Is the locking OK together with locking
+                           in txenable? (Deadlock?) -- REW */
+			
+			RIOTxEnable((char *)PortP);
+			break;
+		default:
+			break;
+	}
+
+	old_cflag = tp->tm.c_cflag;
+	old_iflag = tp->tm.c_iflag;
+	old_oflag = tp->tm.c_oflag;
+	oldcook = PortP->CookMode;
+
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		pseterr(EIO);
+		return 0;
+	}
+
+	PortP->FlushCmdBodge = 0;
+
+	/*
+	** If the port is locked, and it is reconfigured, we want
+	** to restore the state of the tty structure so the change is NOT
+	** made.
+	*/
+	if (PortP->Lock) {
+		tp->tm.c_iflag = PortP->StoredTty.iflag;
+		tp->tm.c_oflag = PortP->StoredTty.oflag;
+		tp->tm.c_cflag = PortP->StoredTty.cflag;
+		tp->tm.c_lflag = PortP->StoredTty.lflag;
+		tp->tm.c_line = PortP->StoredTty.line;
+		for (i = 0; i < NCC + 1; i++)
+			tp->tm.c_cc[i] = PortP->StoredTty.cc[i];
+	}
+	else {
+		/*
+		** If the port is set to store the parameters, and it is
+		** reconfigured, we want to save the current tty struct so it
+		** may be restored on the next open.
+		*/
+		if (PortP->Store) {
+			PortP->StoredTty.iflag = tp->tm.c_iflag;
+			PortP->StoredTty.oflag = tp->tm.c_oflag;
+			PortP->StoredTty.cflag = tp->tm.c_cflag;
+			PortP->StoredTty.lflag = tp->tm.c_lflag;
+			PortP->StoredTty.line = tp->tm.c_line;
+			for (i = 0; i < NCC + 1; i++)
+				PortP->StoredTty.cc[i] = tp->tm.c_cc[i];
+		}
+	}
+
+	changed = (tp->tm.c_cflag != old_cflag) ||
+				(tp->tm.c_iflag != old_iflag) ||
+				(tp->tm.c_oflag != old_oflag);
+
+	PortP->CookMode = RIOCookMode(tp);	/* Set new cooking mode */
+
+	rio_dprintk (RIO_DEBUG_TTY, "RIOIoctl changed %d newcook %d oldcook %d\n",
+			changed,PortP->CookMode,oldcook);
+
+#ifdef MODEM_SUPPORT
+	/*
+	** kludge to force CARR_ON if CLOCAL set
+	*/
+	if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD))	{
+		tp->tm.c_state |= CARR_ON;
+		wakeup ((caddr_t)&tp->tm.c_canq);
+	}
+#endif
+
+	if ( p->RIOHalted ) {
+		RIOClearUp( PortP );
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		pseterr(EIO);
+		return 0;
+	}
+	/*
+	** Re-configure if modes or cooking have changed
+	*/
+	if (changed || oldcook != PortP->CookMode || (ioctl_processed)) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		rio_dprintk (RIO_DEBUG_TTY, "Ioctl changing the PORT settings\n");
+		RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);	
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+
+	if (p->RIOHalted) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		RIOClearUp( PortP );
+		pseterr(EIO);
+		return 0;
+	}
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return 0;
+}
+
+/*
+	ttyseth -- set hardware dependent tty settings
+*/
+void
+ttyseth(PortP, s, sg)
+struct Port *		PortP;
+struct ttystatics *		s;
+struct old_sgttyb *sg;
+{
+	struct old_sgttyb *	tsg;
+	struct termios *tp = &s->tm;
+
+	tsg = &s->sg;
+
+	if (sg->sg_flags & (EVENP|ODDP))  {
+		tp->c_cflag &= PARENB;
+		if (sg->sg_flags & EVENP) {
+			if (sg->sg_flags & ODDP) {
+				tp->c_cflag &= V_CS7;
+				tp->c_cflag &= ~PARENB;
+			}
+			else {
+				tp->c_cflag &= V_CS7;
+				tp->c_cflag &= PARENB;
+				tp->c_cflag &= PARODD;
+			}
+		}
+		else if (sg->sg_flags & ODDP) {
+			tp->c_cflag &= V_CS7;
+			tp->c_cflag &= PARENB;
+			tp->c_cflag &= PARODD;
+		}
+		else {
+			tp->c_cflag &= V_CS7;
+			tp->c_cflag &= PARENB;
+		}
+	}
+/*
+ * Use ispeed as the desired speed.  Most implementations don't handle 
+ * separate input and output speeds very well. If the RIO handles this, 
+ * I will have to use separate sets of flags to store them in the 
+ * Port structure.
+ */
+	if ( !sg->sg_ospeed )
+		sg->sg_ospeed = sg->sg_ispeed;
+	else
+		sg->sg_ispeed = sg->sg_ospeed;
+	if (sg->sg_ispeed > V_EXTB ) 
+		sg->sg_ispeed = V_EXTB;
+	if (sg->sg_ispeed < V_B0)
+		sg->sg_ispeed = V_B0;
+	*tsg = *sg;
+   tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int)sg->sg_ispeed];
+}
+
+/*
+	ttyseth_pv -- set hardware dependent tty settings using either the
+			POSIX termios structure or the System V termio structure.
+				sysv = 0 => (POSIX):	 struct termios *sg
+				sysv != 0 => (System V): struct termio *sg
+*/
+static void
+ttyseth_pv(PortP, s, sg, sysv)
+struct Port *PortP;
+struct ttystatics *s;
+struct termios *sg;
+int sysv;
+{
+    int speed;
+    unsigned char csize;
+    unsigned char cread;
+    unsigned int lcr_flags;
+    int ps;
+ 
+    if (sysv) {
+        /* sg points to a System V termio structure */
+        csize = ((struct termio *)sg)->c_cflag & CSIZE;
+        cread = ((struct termio *)sg)->c_cflag & CREAD;
+        speed = conv_vb[((struct termio *)sg)->c_cflag & V_CBAUD];
+    }
+    else {
+        /* sg points to a POSIX termios structure */
+        csize = sg->c_cflag & CSIZE;
+        cread = sg->c_cflag & CREAD;
+        speed = conv_vb[sg->c_cflag & V_CBAUD];
+    }
+    if (s->sg.sg_ispeed != speed || s->sg.sg_ospeed != speed) {
+        s->sg.sg_ispeed = speed;
+        s->sg.sg_ospeed = speed;
+        s->tm.c_cflag = (s->tm.c_cflag & ~V_CBAUD) |
+                         conv_bv[(int)s->sg.sg_ispeed];
+    }
+}
+#endif
diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h
new file mode 100644
index 0000000..1c7c42c
--- /dev/null
+++ b/drivers/char/rio/riotypes.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      R I O T Y P E S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jon Brawn
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _riotypes_h
+#define _riotypes_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_riotypes_h_sccs = "@(#)riotypes.h	1.10"; */
+#endif
+#endif
+
+#ifdef INKERNEL
+
+#if !defined(MIPSAT)
+typedef unsigned short NUMBER_ptr;
+typedef unsigned short WORD_ptr;
+typedef unsigned short BYTE_ptr;
+typedef unsigned short char_ptr;
+typedef unsigned short Channel_ptr;
+typedef unsigned short FREE_LIST_ptr_ptr;
+typedef unsigned short FREE_LIST_ptr;
+typedef unsigned short LPB_ptr;
+typedef unsigned short Process_ptr;
+typedef unsigned short PHB_ptr;
+typedef unsigned short PKT_ptr;
+typedef unsigned short PKT_ptr_ptr;
+typedef unsigned short Q_BUF_ptr;
+typedef unsigned short Q_BUF_ptr_ptr;
+typedef unsigned short ROUTE_STR_ptr;
+typedef unsigned short RUP_ptr;
+typedef unsigned short short_ptr;
+typedef unsigned short u_short_ptr;
+typedef unsigned short ushort_ptr;
+#else
+/* MIPSAT types */
+typedef char RIO_POINTER[8];
+typedef RIO_POINTER NUMBER_ptr;
+typedef RIO_POINTER WORD_ptr;
+typedef RIO_POINTER BYTE_ptr;
+typedef RIO_POINTER char_ptr;
+typedef RIO_POINTER Channel_ptr;
+typedef RIO_POINTER FREE_LIST_ptr_ptr;
+typedef RIO_POINTER FREE_LIST_ptr;
+typedef RIO_POINTER LPB_ptr;
+typedef RIO_POINTER Process_ptr;
+typedef RIO_POINTER PHB_ptr;
+typedef RIO_POINTER PKT_ptr;
+typedef RIO_POINTER PKT_ptr_ptr;
+typedef RIO_POINTER Q_BUF_ptr;
+typedef RIO_POINTER Q_BUF_ptr_ptr;
+typedef RIO_POINTER ROUTE_STR_ptr;
+typedef RIO_POINTER RUP_ptr;
+typedef RIO_POINTER short_ptr;
+typedef RIO_POINTER u_short_ptr;
+typedef RIO_POINTER ushort_ptr;
+#endif
+
+#else /* not INKERNEL */
+typedef unsigned char   BYTE;
+typedef unsigned short  WORD;
+typedef unsigned long   DWORD;
+typedef short           NUMBER;
+typedef short           *NUMBER_ptr;
+typedef unsigned short  *WORD_ptr;
+typedef unsigned char   *BYTE_ptr;
+typedef unsigned char   uchar ;
+typedef unsigned short  ushort ;
+typedef unsigned int    uint ;
+typedef unsigned long   ulong ;
+typedef unsigned char   u_char ;
+typedef unsigned short  u_short ;
+typedef unsigned int    u_int ;
+typedef unsigned long   u_long ;
+typedef unsigned short  ERROR ;
+typedef unsigned long ID ;
+typedef char             *char_ptr;
+typedef Channel          *Channel_ptr;
+typedef struct FREE_LIST *FREE_LIST_ptr;
+typedef struct FREE_LIST **FREE_LIST_ptr_ptr;
+typedef struct LPB       *LPB_ptr;
+typedef struct Process   *Process_ptr;
+typedef struct PHB       *PHB_ptr;
+typedef struct PKT       *PKT_ptr;
+typedef struct PKT       **PKT_ptr_ptr;
+typedef struct Q_BUF     *Q_BUF_ptr;
+typedef struct Q_BUF     **Q_BUF_ptr_ptr;
+typedef struct ROUTE_STR *ROUTE_STR_ptr;
+typedef struct RUP       *RUP_ptr;
+typedef short            *short_ptr;
+typedef u_short          *u_short_ptr;
+typedef ushort           *ushort_ptr;
+typedef struct PKT	 PKT;
+typedef struct LPB	 LPB;
+typedef struct RUP	 RUP;
+#endif
+
+
+#endif /* __riotypes__ */
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/riowinif.h b/drivers/char/rio/riowinif.h
new file mode 100644
index 0000000..18a4f14
--- /dev/null
+++ b/drivers/char/rio/riowinif.h
@@ -0,0 +1,1335 @@
+/************************************************************************/
+/*									*/
+/*	Title		:	RIO Shared Memory Window Inteface	*/
+/*									*/
+/*	Author		:	N.P.Vassallo				*/
+/*									*/
+/*	Creation	:	7th June 1999				*/
+/*									*/
+/*	Version		:	1.0.0					*/
+/*									*/
+/*	Copyright	:	(c) Specialix International Ltd. 1999	*
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *									*/
+/*	Description	:	Prototypes, structures and definitions	*/
+/*				describing RIO host card shared	memory	*/
+/*				window interface structures:		*/
+/*					PARMMAP				*/
+/*					RUP				*/
+/*					PHB				*/
+/*					LPB				*/
+/*					PKT				*/
+/*									*/
+/************************************************************************/
+
+/* History...
+
+1.0.0	07/06/99 NPV	Creation. (based on PARMMAP.H)
+
+*/
+
+#ifndef	_riowinif_h				/* If RIOWINDIF.H not already defined */
+#define	_riowinif_h    1
+
+/*****************************************************************************
+********************************             *********************************
+********************************   General   *********************************
+********************************             *********************************
+*****************************************************************************/
+
+#define	TPNULL		((_u16)(0x8000))
+
+/*****************************************************************************
+********************************              ********************************
+********************************   PARM_MAP   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+/* The PARM_MAP structure defines global values relating to the Host Card / RTA
+   and is the main structure from which all other structures are referenced. */
+
+typedef	struct	_PARM_MAP
+{
+	_u16	phb_ptr;		/* 0x00 Pointer to the PHB array */
+	_u16	phb_num_ptr;		/* 0x02 Ptr to Number of PHB's */
+	_u16	free_list;		/* 0x04 Free List pointer */
+	_u16	free_list_end;		/* 0x06 Free List End pointer */
+	_u16	q_free_list_ptr;	/* 0x08 Ptr to Q_BUF variable */
+	_u16	unit_id_ptr;		/* 0x0A Unit Id */
+	_u16	link_str_ptr;		/* 0x0C Link Structure Array */
+	_u16	bootloader_1;		/* 0x0E 1st Stage Boot Loader */
+	_u16	bootloader_2;		/* 0x10 2nd Stage Boot Loader */
+	_u16	port_route_map_ptr;	/* 0x12 Port Route Map */
+	_u16	route_ptr;		/* 0x14 Route Map */
+	_u16	map_present;		/* 0x16 Route Map present */
+	_u16	pkt_num;		/* 0x18 Total number of packets */
+	_u16	q_num;			/* 0x1A Total number of Q packets */
+	_u16	buffers_per_port;	/* 0x1C Number of buffers per port */
+	_u16	heap_size;		/* 0x1E Initial size of heap */
+	_u16	heap_left;		/* 0x20 Current Heap left */
+	_u16	error;			/* 0x22 Error code */
+	_u16	tx_max;			/* 0x24 Max number of tx pkts per phb */
+	_u16	rx_max;			/* 0x26 Max number of rx pkts per phb */
+	_u16	rx_limit;		/* 0x28 For high / low watermarks */
+	_u16	links;			/* 0x2A Links to use */
+	_u16	timer;			/* 0x2C Interrupts per second */
+	_u16	rups;			/* 0x2E Pointer to the RUPs */
+	_u16	max_phb;		/* 0x30 Mostly for debugging */
+	_u16	living;			/* 0x32 Just increments!! */
+	_u16	init_done;		/* 0x34 Initialisation over */
+	_u16	booting_link;		/* 0x36 */
+	_u16	idle_count;		/* 0x38 Idle time counter */
+	_u16	busy_count;		/* 0x3A Busy counter */
+	_u16	idle_control;		/* 0x3C Control Idle Process */
+	_u16	tx_intr;		/* 0x3E TX interrupt pending */
+	_u16	rx_intr;		/* 0x40 RX interrupt pending */
+	_u16	rup_intr;		/* 0x42 RUP interrupt pending */
+
+} PARM_MAP;
+
+/* Same thing again, but defined as offsets... */
+
+#define	PM_phb_ptr		0x00	/* 0x00 Pointer to the PHB array */
+#define	PM_phb_num_ptr		0x02	/* 0x02 Ptr to Number of PHB's */
+#define	PM_free_list		0x04	/* 0x04 Free List pointer */
+#define	PM_free_list_end	0x06	/* 0x06 Free List End pointer */
+#define	PM_q_free_list_ptr	0x08	/* 0x08 Ptr to Q_BUF variable */
+#define	PM_unit_id_ptr		0x0A	/* 0x0A Unit Id */
+#define	PM_link_str_ptr		0x0C	/* 0x0C Link Structure Array */
+#define	PM_bootloader_1		0x0E	/* 0x0E 1st Stage Boot Loader */
+#define	PM_bootloader_2		0x10	/* 0x10 2nd Stage Boot Loader */
+#define	PM_port_route_map_ptr	0x12	/* 0x12 Port Route Map */
+#define	PM_route_ptr		0x14	/* 0x14 Route Map */
+#define	PM_map_present		0x16	/* 0x16 Route Map present */
+#define	PM_pkt_num		0x18	/* 0x18 Total number of packets */
+#define	PM_q_num		0x1A	/* 0x1A Total number of Q packets */
+#define	PM_buffers_per_port	0x1C	/* 0x1C Number of buffers per port */
+#define	PM_heap_size		0x1E	/* 0x1E Initial size of heap */
+#define	PM_heap_left		0x20	/* 0x20 Current Heap left */
+#define	PM_error		0x22	/* 0x22 Error code */
+#define	PM_tx_max		0x24	/* 0x24 Max number of tx pkts per phb */
+#define	PM_rx_max		0x26	/* 0x26 Max number of rx pkts per phb */
+#define	PM_rx_limit		0x28	/* 0x28 For high / low watermarks */
+#define	PM_links		0x2A	/* 0x2A Links to use */
+#define	PM_timer		0x2C	/* 0x2C Interrupts per second */
+#define	PM_rups			0x2E	/* 0x2E Pointer to the RUPs */
+#define	PM_max_phb		0x30	/* 0x30 Mostly for debugging */
+#define	PM_living		0x32	/* 0x32 Just increments!! */
+#define	PM_init_done		0x34	/* 0x34 Initialisation over */
+#define	PM_booting_link		0x36	/* 0x36 */
+#define	PM_idle_count		0x38	/* 0x38 Idle time counter */
+#define	PM_busy_count		0x3A	/* 0x3A Busy counter */
+#define	PM_idle_control		0x3C	/* 0x3C Control Idle Process */
+#define	PM_tx_intr		0x3E	/* 0x4E TX interrupt pending */
+#define	PM_rx_intr		0x40	/* 0x40 RX interrupt pending */
+#define	PM_rup_intr		0x42	/* 0x42 RUP interrupt pending */
+#define	sizeof_PARM_MAP		0x44	/* structure size = 0x44 */
+
+/* PARM_MAP.error definitions... */
+#define	E_NO_ERROR		0x00
+#define	E_PROCESS_NOT_INIT	0x01
+#define	E_LINK_TIMEOUT		0x02
+#define	E_NO_ROUTE		0x03
+#define	E_CONFUSED		0x04
+#define	E_HOME			0x05
+#define	E_CSUM_FAIL		0x06
+#define	E_DISCONNECTED		0x07
+#define	E_BAD_RUP		0x08
+#define	E_NO_VIRGIN		0x09
+#define	E_BOOT_RUP_BUSY		0x10
+#define	E_CHANALLOC		0x80
+#define	E_POLL_ALLOC		0x81
+#define	E_LTTWAKE		0x82
+#define	E_LTT_ALLOC		0x83
+#define	E_LRT_ALLOC		0x84
+#define	E_CIRRUS		0x85
+#define	E_MONITOR		0x86
+#define	E_PHB_ALLOC		0x87
+#define	E_ARRAY_ALLOC		0x88
+#define	E_QBUF_ALLOC		0x89
+#define	E_PKT_ALLOC		0x8a
+#define	E_GET_TX_Q_BUF		0x8b
+#define	E_GET_RX_Q_BUF		0x8c
+#define	E_MEM_OUT		0x8d
+#define	E_MMU_INIT		0x8e
+#define	E_LTT_INIT		0x8f
+#define	E_LRT_INIT		0x90
+#define	E_LINK_RUN		0x91
+#define	E_MONITOR_ALLOC		0x92
+#define	E_MONITOR_INIT		0x93
+#define	E_POLL_INIT		0x94
+
+/* PARM_MAP.links definitions... */
+#define	RIO_LINK_ENABLE	0x80FF
+
+/*****************************************************************************
+**********************************         ***********************************
+**********************************   RUP   ***********************************
+**********************************         ***********************************
+*****************************************************************************/
+
+/* The RUP (Remote Unit Port) structure relates to the Remote Terminal Adapters
+   attached to the system and there is normally an array of MAX_RUPS (=16) structures
+   in a host card, defined by PARM_MAP->rup. */
+
+typedef	struct	_RUP
+{
+	_u16		txpkt;			/* 0x00 Outgoing packet */
+	_u16		rxpkt;			/* 0x02 ncoming packet */
+	_u16		link;			/* 0x04 Which link to send packet down ? */
+	_u8		rup_dest_unit[2];	/* 0x06 Destination Unit */
+	_u16		handshake;		/* 0x08 Handshaking */
+	_u16		timeout;		/* 0x0A Timeout */
+	_u16		status;			/* 0x0C Status */
+	_u16		txcontrol;		/* 0x0E Transmit control */
+	_u16		rxcontrol;		/* 0x10 Receive control */
+
+} RUP;
+
+/* Same thing again, but defined as offsets... */
+
+#define	RUP_txpkt		0x00		/* 0x00 Outgoing packet */
+#define	RUP_rxpkt		0x02		/* 0x02 Incoming packet */
+#define	RUP_link		0x04		/* 0x04 Which link to send packet down ? */
+#define	RUP_rup_dest_unit	0x06		/* 0x06 Destination Unit */
+#define	RUP_handshake		0x08		/* 0x08 Handshaking */
+#define	RUP_timeout		0x0A		/* 0x0A Timeout */
+#define	RUP_status		0x0C		/* 0x0C Status */
+#define	RUP_txcontrol		0x0E		/* 0x0E Transmit control */
+#define	RUP_rxcontrol		0x10		/* 0x10 Receive control */
+#define	sizeof_RUP		0x12		/* structure size = 0x12 */
+
+#define MAX_RUP			16
+
+/* RUP.txcontrol definitions... */
+#define	TX_RUP_INACTIVE		0		/* Nothing to transmit */
+#define	TX_PACKET_READY		1		/* Transmit packet ready */
+#define	TX_LOCK_RUP		2		/* Transmit side locked */
+
+/* RUP.txcontrol definitions... */
+#define	RX_RUP_INACTIVE		0		/* Nothing received */
+#define	RX_PACKET_READY		1		/* Packet received */
+
+#define	RUP_NO_OWNER		0xFF		/* RUP not owned by any process */
+
+/*****************************************************************************
+**********************************         ***********************************
+**********************************   PHB   ***********************************
+**********************************         ***********************************
+*****************************************************************************/
+
+/* The PHB (Port Header Block) structure relates to the serial ports attached
+   to the system and there is normally an array of MAX_PHBS (=128) structures
+   in a host card, defined by PARM_MAP->phb_ptr and PARM_MAP->phb_num_ptr. */
+
+typedef	struct	_PHB
+{
+	_u16		source;			/* 0x00 Location of the PHB in the host card */
+	_u16		handshake;		/* 0x02 Used to manage receive packet flow control */
+	_u16		status;			/* 0x04 Internal port transmit/receive status */
+	_u16		timeout;		/* 0x06 Time period to wait for an ACK */
+	_u16		link;			/* 0x08 The host link associated with the PHB */
+	_u16		destination;		/* 0x0A Location of the remote port on the network */
+
+	_u16		tx_start;		/* 0x0C first entry in the packet array for transmit packets */
+	_u16		tx_end;			/* 0x0E last entry in the packet array for transmit packets */
+	_u16		tx_add;			/* 0x10 position in the packet array for new transmit packets */
+	_u16		tx_remove;		/* 0x12 current position in the packet pointer array */
+
+	_u16		rx_start;		/* 0x14 first entry in the packet array for receive packets */
+	_u16		rx_end;			/* 0x16 last entry in the packet array for receive packets */
+	_u16		rx_add;			/* 0x18 position in the packet array for new receive packets */
+	_u16		rx_remove;		/* 0x1A current position in the packet pointer array */
+
+} PHB;
+
+/* Same thing again, but defined as offsets... */
+
+#define	PHB_source		0x00		/* 0x00 Location of the PHB in the host card */
+#define	PHB_handshake		0x02		/* 0x02 Used to manage receive packet flow control */
+#define	PHB_status		0x04		/* 0x04 Internal port transmit/receive status */
+#define	PHB_timeout		0x06		/* 0x06 Time period to wait for an ACK */
+#define	PHB_link		0x08		/* 0x08 The host link associated with the PHB */
+#define	PHB_destination		0x0A		/* 0x0A Location of the remote port on the network */
+#define	PHB_tx_start		0x0C		/* 0x0C first entry in the packet array for transmit packets */
+#define	PHB_tx_end		0x0E		/* 0x0E last entry in the packet array for transmit packets */
+#define	PHB_tx_add		0x10		/* 0x10 position in the packet array for new transmit packets */
+#define	PHB_tx_remove		0x12		/* 0x12 current position in the packet pointer array */
+#define	PHB_rx_start		0x14		/* 0x14 first entry in the packet array for receive packets */
+#define	PHB_rx_end		0x16		/* 0x16 last entry in the packet array for receive packets */
+#define	PHB_rx_add		0x18		/* 0x18 position in the packet array for new receive packets */
+#define	PHB_rx_remove		0x1A		/* 0x1A current position in the packet pointer array */
+#define	sizeof_PHB		0x1C		/* structure size = 0x1C */
+
+/* PHB.handshake definitions... */
+#define	PHB_HANDSHAKE_SET	0x0001		/* Set by LRT */
+#define	PHB_HANDSHAKE_RESET	0x0002		/* Set by ISR / driver */
+#define	PHB_HANDSHAKE_FLAGS	(PHB_HANDSHAKE_RESET|PHB_HANDSHAKE_SET)
+						/* Reset by ltt */
+
+#define	MAX_PHB			128		/* range 0-127 */
+
+/*****************************************************************************
+**********************************         ***********************************
+**********************************   LPB   ***********************************
+**********************************         ***********************************
+*****************************************************************************/
+
+/* The LPB (Link Parameter Block) structure relates to a RIO Network Link
+   and there is normally an array of MAX_LINKS (=4) structures in a host card,
+   defined by PARM_MAP->link_str_ptr. */
+
+typedef	struct	_LPB
+{
+	_u16		link_number;		/* 0x00 Link Number */
+	_u16		in_ch;			/* 0x02 Link In Channel */
+	_u16		out_ch;			/* 0x04 Link Out Channel */
+	_u8		attached_serial[4];	/* 0x06 Attached serial number */
+	_u8		attached_host_serial[4];/* 0x0A Serial number of Host who booted other end */
+	_u16		descheduled;		/* 0x0E Currently Descheduled */
+	_u16		state;			/* 0x10 Current state */
+	_u16		send_poll;		/* 0x12 Send a Poll Packet */
+	_u16		ltt_p;			/* 0x14 Process Descriptor */
+	_u16		lrt_p;			/* 0x16 Process Descriptor */
+	_u16		lrt_status;		/* 0x18 Current lrt status */
+	_u16		ltt_status;		/* 0x1A Current ltt status */
+	_u16		timeout;		/* 0x1C Timeout value */
+	_u16		topology;		/* 0x1E Topology bits */
+	_u16		mon_ltt;		/* 0x20 */
+	_u16		mon_lrt;		/* 0x22 */
+	_u16		num_pkts;		/* 0x24 */
+	_u16		add_packet_list;	/* 0x26 Add packets to here */
+	_u16		remove_packet_list;	/* 0x28 Send packets from here */
+
+	_u16		lrt_fail_chan;		/* 0x2A Lrt's failure channel */
+	_u16		ltt_fail_chan;		/* 0x2C Ltt's failure channel */
+
+	RUP		rup;			/* 0x2E RUP structure for HOST to driver comms */
+	RUP		link_rup;		/* 0x40 RUP for the link (POLL, topology etc.) */
+	_u16		attached_link;		/* 0x52 Number of attached link */
+	_u16		csum_errors;		/* 0x54 csum errors */
+	_u16		num_disconnects;	/* 0x56 number of disconnects */
+	_u16		num_sync_rcvd;		/* 0x58 # sync's received */
+	_u16		num_sync_rqst;		/* 0x5A # sync requests */
+	_u16		num_tx;			/* 0x5C Num pkts sent */
+	_u16		num_rx;			/* 0x5E Num pkts received */
+	_u16		module_attached;	/* 0x60 Module tpyes of attached */
+	_u16		led_timeout;		/* 0x62 LED timeout */
+	_u16		first_port;		/* 0x64 First port to service */
+	_u16		last_port;		/* 0x66 Last port to service */
+
+} LPB;
+
+/* Same thing again, but defined as offsets... */
+
+#define	LPB_link_number		0x00		/* 0x00 Link Number */
+#define	LPB_in_ch		0x02		/* 0x02 Link In Channel */
+#define	LPB_out_ch		0x04		/* 0x04 Link Out Channel */
+#define	LPB_attached_serial	0x06		/* 0x06 Attached serial number */
+#define	LPB_attached_host_serial 0x0A		/* 0x0A Serial number of Host who booted other end */
+#define	LPB_descheduled		0x0E		/* 0x0E Currently Descheduled */
+#define	LPB_state		0x10		/* 0x10 Current state */
+#define	LPB_send_poll		0x12		/* 0x12 Send a Poll Packet */
+#define	LPB_ltt_p		0x14		/* 0x14 Process Descriptor */
+#define	LPB_lrt_p		0x16		/* 0x16 Process Descriptor */
+#define	LPB_lrt_status		0x18		/* 0x18 Current lrt status */
+#define	LPB_ltt_status		0x1A		/* 0x1A Current ltt status */
+#define	LPB_timeout		0x1C		/* 0x1C Timeout value */
+#define	LPB_topology		0x1E		/* 0x1E Topology bits */
+#define	LPB_mon_ltt		0x20		/* 0x20 */
+#define	LPB_mon_lrt		0x22		/* 0x22 */
+#define	LPB_num_pkts		0x24		/* 0x24 */
+#define	LPB_add_packet_list	0x26		/* 0x26 Add packets to here */
+#define	LPB_remove_packet_list	0x28		/* 0x28 Send packets from here */
+#define	LPB_lrt_fail_chan	0x2A		/* 0x2A Lrt's failure channel */
+#define	LPB_ltt_fail_chan	0x2C		/* 0x2C Ltt's failure channel */
+#define	LPB_rup			0x2E		/* 0x2E RUP structure for HOST to driver comms */
+#define	LPB_link_rup		0x40		/* 0x40 RUP for the link (POLL, topology etc.) */
+#define	LPB_attached_link	0x52		/* 0x52 Number of attached link */
+#define	LPB_csum_errors		0x54		/* 0x54 csum errors */
+#define	LPB_num_disconnects	0x56		/* 0x56 number of disconnects */
+#define	LPB_num_sync_rcvd	0x58		/* 0x58 # sync's received */
+#define	LPB_num_sync_rqst	0x5A		/* 0x5A # sync requests */
+#define	LPB_num_tx		0x5C		/* 0x5C Num pkts sent */
+#define	LPB_num_rx		0x5E		/* 0x5E Num pkts received */
+#define	LPB_module_attached	0x60		/* 0x60 Module tpyes of attached */
+#define	LPB_led_timeout		0x62		/* 0x62 LED timeout */
+#define	LPB_first_port		0x64		/* 0x64 First port to service */
+#define	LPB_last_port		0x66		/* 0x66 Last port to service */
+#define	sizeof_LPB		0x68		/* structure size = 0x68 */
+
+#define	LINKS_PER_UNIT		4		/* number of links from a host */
+
+/*****************************************************************************
+********************************               *******************************
+********************************   FREE_LIST   *******************************
+********************************               *******************************
+*****************************************************************************/
+
+/* Used to overlay packet headers when allocating/freeing packets from the free list */
+
+typedef	struct	_FREE_LIST
+{
+	_u16		next;			/* 0x00 offset of next list item */
+	_u16		prev;			/* 0x02 offset of previous list item */
+
+} FREE_LIST;
+
+/* Same thing again, but defined as offsets... */
+
+#define	FL_next			0x00		/* 0x00 offset of next list item */
+#define	FL_prev			0x02		/* 0x02 offset of previous list item */
+
+/*****************************************************************************
+**********************************         ***********************************
+**********************************   PKT   ***********************************
+**********************************         ***********************************
+*****************************************************************************/
+
+/* The PKT is the main unit of communication between Host Cards and RTAs across
+   the RIO network.  */
+
+#define PKT_MAX_DATA_LEN   72			/* Size of packet data */
+
+typedef	struct	_PKT
+{
+	_u8		dest_unit;		/* 0x00 Destination Unit Id */
+	_u8		dest_port;		/* 0x01 Destination Port */
+	_u8		src_unit;		/* 0x02 Source Unit Id */
+	_u8		src_port;		/* 0x03 Source Port */
+	_u8		len;			/* 0x04 Length (in bytes) of data field */
+	_u8		control;		/* 0x05 */
+	_u8		data[PKT_MAX_DATA_LEN];	/* 0x06 Actual data */
+	_u16		csum;			/* 0x4E C-SUM */
+
+} PKT;
+
+/* Same thing again, but defined as offsets... */
+
+#define	PKT_dest_unit		0x00		/* 0x00 Destination Unit Id */
+#define	PKT_dest_port		0x01		/* 0x01 Destination Port */
+#define	PKT_src_unit		0x02		/* 0x02 Source Unit Id */
+#define	PKT_src_port		0x03		/* 0x03 Source Port */
+#define	PKT_len			0x04		/* 0x04 Length (in bytes) of data field */
+#define	PKT_control		0x05		/* 0x05 */
+#define	PKT_data		0x06		/* 0x06 Actual data */
+#define	PKT_csum		0x4E		/* 0x4E C-SUM */
+#define	sizeof_PKT		0x50		/* structure size = 0x50 */
+
+/* PKT.len definitions... */
+#define	PKT_CMD_BIT		0x80
+#define	PKT_CMD_DATA		0x80
+#define	PKT_LEN_MASK		0x7F
+
+/* PKT.control definitions... */
+#define	PKT_ACK			0x40
+#define	PKT_TGL			0x20
+#define	DATA_WNDW		0x10
+#define	PKT_TTL_MASK		0x0F
+#define	MAX_TTL			0x0F
+
+/*****************************************************************************
+*****************************                     ****************************
+*****************************   Control Packets   ****************************
+*****************************                     ****************************
+*****************************************************************************/
+
+/* The following definitions and structures define the control packets sent
+   between the driver and RIO Ports, RTAs and Host Cards. */
+
+#define	PRE_EMPTIVE		0x80			/* Pre-emptive command (sent via port's RUP) */
+
+/* "in-band" and "pre-emptive" port commands... */
+#define	OPEN			0x00			/* Driver->RIO Open a port */
+#define	CONFIG			0x01			/* Driver->RIO Configure a port */
+#define	MOPEN			0x02			/* Driver->RIO Modem open (wait for DCD) */
+#define	CLOSE			0x03			/* Driver->RIO Close a port */
+#define	WFLUSH			(0x04|PRE_EMPTIVE)	/* Driver->RIO Write flush */
+#define	RFLUSH			(0x05|PRE_EMPTIVE)	/* Driver->RIO Read flush */
+#define	RESUME			(0x06|PRE_EMPTIVE)	/* Driver->RIO Behave as if XON received */
+#define	SBREAK			0x07			/* Driver->RIO Start break */
+#define	EBREAK			0x08			/* Driver->RIO End break */
+#define	SUSPEND			(0x09|PRE_EMPTIVE)	/* Driver->RIO Behave as if XOFF received */
+#define	FCLOSE			(0x0A|PRE_EMPTIVE)	/* Driver->RIO Force close */
+#define	XPRINT			0x0B			/* Driver->RIO Xprint packet */
+#define	MBIS			(0x0C|PRE_EMPTIVE)	/* Driver->RIO Set modem lines */
+#define	MBIC			(0x0D|PRE_EMPTIVE)	/* Driver->RIO Clear modem lines */
+#define	MSET			(0x0E|PRE_EMPTIVE)	/* Driver->RIO Set modem lines */
+#define	PCLOSE			0x0F			/* Driver->RIO Pseudo close */
+#define	MGET			(0x10|PRE_EMPTIVE)	/* Driver->RIO Force update of modem status */
+#define	MEMDUMP			(0x11|PRE_EMPTIVE)	/* Driver->RIO DEBUG request for RTA memory */
+#define	READ_REGISTER		(0x12|PRE_EMPTIVE)	/* Driver->RIO DEBUG read CD1400 register */
+
+/* Remote Unit Port (RUP) packet definitions... (specified in PKT.dest_unit and PKT.src_unit) */
+#define	SYNC_RUP		0xFF			/* Download internal */
+#define	COMMAND_RUP		0xFE			/* Command ack/status */
+#define	ERROR_RUP		0xFD			/* Download internal */
+#define	POLL_RUP		0xFC			/* Download internal */
+#define	BOOT_RUP		0xFB			/* Used to boot RTAs */
+#define	ROUTE_RUP		0xFA			/* Used to specify routing/topology */
+#define	STATUS_RUP		0xF9			/* Not used */
+#define	POWER_RUP		0xF8			/* Download internal */
+
+/* COMMAND_RUP definitions... */
+#define	COMPLETE		(0x20|PRE_EMPTIVE)	/* RIO->Driver Command complete */
+#define	BREAK_RECEIVED		(0x21|PRE_EMPTIVE)	/* RIO->Driver Break received */
+#define	MODEM_STATUS		(0x22|PRE_EMPTIVE)	/* RIO->Driver Modem status change */
+
+/* BOOT_RUP definitions... */
+#define	BOOT_REQUEST		0x00			/* RIO->Driver Request for boot */
+#define	BOOT_ABORT		0x01			/* Driver->RIO Abort a boot */
+#define	BOOT_SEQUENCE		0x02			/* Driver->RIO Packet with firmware details */
+#define	BOOT_COMPLETED		0x03			/* RIO->Driver Boot completed */
+#define IFOAD			0x2F			/* Driver->RIO Shutdown/Reboot RTA (Fall Over And Die) */
+#define	IDENTIFY		0x30			/* Driver->RIO Identify RTA */
+#define	ZOMBIE			0x31			/* Driver->RIO Shutdown/Flash LEDs */
+#define	UFOAD			0x32			/* Driver->RIO Shutdown/Reboot neighbouring RTA */
+#define IWAIT			0x33			/* Driver->RIO Pause booting process */
+
+/* ROUTE_RUP definitions... */
+#define	ROUTE_REQUEST		0x00			/* RIO->Driver Request an ID */
+#define	ROUTE_FOAD		0x01			/* Driver->RIO Shutdown/reboot RTA */
+#define	ROUTE_ALREADY		0x02			/* Driver->RIO Not used */
+#define	ROUTE_USED		0x03			/* Driver->RIO Not used */
+#define	ROUTE_ALLOCATE		0x04			/* Driver->RIO Allocate RTA RUP numbers */
+#define	ROUTE_REQ_TOP		0x05			/* Driver->RIO Not used */
+#define ROUTE_TOPOLOGY		0x06			/* RIO->Driver Route/Topology status */
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   OPEN   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   Sent to open a port. 
+   Structure of configuration info used with OPEN, CONFIG and MOPEN packets... */
+
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_Cor1		(PKT_Data+1)		/* Channel Option Register 1 */
+#define	PKT_Cor2		(PKT_Data+2)		/* Channel Option Register 2 */
+#define	PKT_Cor4		(PKT_Data+3)		/* Channel Option Register 4 */
+#define	PKT_Cor5		(PKT_Data+4)		/* Channel Option Register 5 */
+#define	PKT_TxXon		(PKT_Data+5)		/* Transmit XON character */
+#define	PKT_TxXoff		(PKT_Data+6)		/* Transmit XOFF character */
+#define	PKT_RxXon		(PKT_Data+7)		/* Receive XON character */
+#define	PKT_RxXoff		(PKT_Data+8)		/* Receive XOFF character */
+#define	PKT_Lnext		(PKT_Data+9)		/* Lnext character */
+#define	PKT_TxBaud		(PKT_Data+10)		/* Transmit baud rate */
+#define	PKT_RxBaud		(PKT_Data+11)		/* Receive baud rate */
+
+/* COR1 definitions... */
+#define	COR1_PARITY		0xE0			/* Parity mask */
+#define	COR1_NONE		0x00			/* No parity */
+#define	COR1_SPACE		0x20			/* Space parity */
+#define	COR1_EVEN		0x40			/* Even parity */
+#define	COR1_MARK		0xA0			/* Mark parity */
+#define	COR1_ODD		0xC0			/* Odd parity */
+
+#define	COR1_STOPBITS		0x0C			/* Stop bits mask */
+#define	COR1_STOP1		0x00			/* 1 stop bit */
+#define	COR1_STOP1_5		0x04			/* 1.5 stop bits */
+#define	COR1_STOP2		0x08			/* 2 stop bits */
+
+#define	COR1_DATABITS		0x03			/* Data bits mask */
+#define	COR1_DATA5		0x00			/* 5 data bits */
+#define	COR1_DATA6		0x01			/* 6 data bits */
+#define	COR1_DATA7		0x02			/* 7 data bits */
+#define	COR1_DATA8		0x03			/* 8 data bits */
+
+/* COR2 definitions... */
+#define	COR2_XON_TXFLOW		0x40			/* XON/XOFF Transmit Flow */
+#define	COR2_XANY_TXFLOW	0xC0			/* XON/XANY Transmit Flow */
+#define	COR2_HUPCL		0x20			/* Hang Up On Close */
+#define	COR2_DSR_TXFLOW		0x08			/* DSR Transmit Flow Control */
+#define	COR2_RTS_RXFLOW		0x04			/* RTS Receive Flow Control */
+#define	COR2_CTS_TXFLOW		0x02			/* CTS Transmit Flow Control */
+#define	COR2_XON_RXFLOW		0x01			/* XON/XOFF Receive Flow */
+
+/* COR4 definition... */
+#define	COR4_IGNCR		0x80			/* Discard received CR */
+#define	COR4_ICRNL		0x40			/* Map received CR -> NL */
+#define	COR4_INLCR		0x20			/* Map received NL -> CR */
+#define	COR4_IGNBRK		0x10			/* Ignore Received Break */
+#define	COR4_NBRKINT		0x08			/* No interrupt on rx Break */
+#define	COR4_IGNPAR		0x04			/* ignore rx parity error chars */
+#define	COR4_PARMRK		0x02			/* Mark rx parity error chars */
+#define	COR4_RAISEMOD		0x01			/* Raise modem lines on !0 baud */
+
+/* COR5 definitions... */
+#define	COR5_ISTRIP		0x80			/* Strip input chars to 7 bits */
+#define	COR5_LNE		0x40			/* Enable LNEXT processing */
+#define	COR5_CMOE		0x20			/* Match good & error characters */
+#define	COR5_TAB3		0x10			/* TAB3 mode */
+#define	COR5_TSTATE_ON		0x08			/* Enable tbusy/tstop monitoring */
+#define	COR5_TSTATE_OFF		0x04			/* Disable tbusy/tstop monitoring */
+#define	COR5_ONLCR		0x02			/* NL -> CR NL on output */
+#define	COR5_OCRNL		0x01			/* CR -> NL on output */
+
+/* RxBaud and TxBaud definitions... */
+#define	RIO_B0			0x00			/* RTS / DTR signals dropped */
+#define	RIO_B50			0x01			/* 50 baud */
+#define	RIO_B75			0x02			/* 75 baud */
+#define	RIO_B110		0x03			/* 110 baud */
+#define	RIO_B134		0x04			/* 134.5 baud */
+#define	RIO_B150		0x05			/* 150 baud */
+#define	RIO_B200		0x06			/* 200 baud */
+#define	RIO_B300		0x07			/* 300 baud */
+#define	RIO_B600		0x08			/* 600 baud */
+#define	RIO_B1200		0x09			/* 1200 baud */
+#define	RIO_B1800		0x0A			/* 1800 baud */
+#define	RIO_B2400		0x0B			/* 2400 baud */
+#define	RIO_B4800		0x0C			/* 4800 baud */
+#define	RIO_B9600		0x0D			/* 9600 baud */
+#define	RIO_B19200		0x0E			/* 19200 baud */
+#define	RIO_B38400		0x0F			/* 38400 baud */
+#define	RIO_B56000		0x10			/* 56000 baud */
+#define	RIO_B57600		0x11			/* 57600 baud */
+#define	RIO_B64000		0x12			/* 64000 baud */
+#define	RIO_B115200		0x13			/* 115200 baud */
+#define	RIO_B2000		0x14			/* 2000 baud */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   CONFIG   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   CONFIG is sent from the driver to configure an already opened port.
+   Packet structure is same as OPEN.  */
+
+/*****************************************************************************
+*********************************           **********************************
+*********************************   MOPEN   **********************************
+*********************************           **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   MOPEN is sent from the driver to open a port attached to a modem. (in-band)
+   Packet structure is same as OPEN.  */
+
+/*****************************************************************************
+*********************************           **********************************
+*********************************   CLOSE   **********************************
+*********************************           **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   CLOSE is sent from the driver to close a previously opened port.
+   No parameters.
+ */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+/*****************************************************************************
+*********************************            *********************************
+*********************************   WFLUSH   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   WFLUSH is sent pre-emptively from the driver to flush the write buffers and
+   packets of a port.  (pre-emptive)
+   
+   WFLUSH is also sent in-band from the driver to a port as a marker to end
+   write flushing previously started by a pre-emptive WFLUSH packet. (in-band)
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   RFLUSH   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   RFLUSH is sent pre-emptively from the driver to flush the read buffers and
+   packets of a port.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   RESUME   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   RESUME is sent pre-emptively from the driver to cause a port to resume 
+   transmission of data if blocked by XOFF.  (as if XON had been received)
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   SBREAK   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   SBREAK is sent in-band from the driver to a port to suspend data and start
+   break signal transmission.
+
+   If the break delay is 0, the break signal will be acknowledged with a
+   RUP_COMMAND, COMPLETE packet and continue until an EBREAK packet is received.
+
+   Otherwise, there is no acknowledgement and the break signal will last for the
+   specified number of mS.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_BreakDelay		(PKT_Data+1)		/* Break delay in mS */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   EBREAK   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   EBREAK is sent in-band from the driver to a port to stop transmission of a
+   break signal.
+
+   No parameters.  */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   SUSPEND   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   SUSPEND is sent pre-emptively from the driver to cause a port to suspend
+   transmission of data.  (as if XOFF had been received)
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   FCLOSE   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   FCLOSE is sent pre-emptively from the driver to force close a port.
+   A force close flushes receive and transmit queues, and also lowers all output
+   modem signals if the COR5_HUPCL (Hang Up On Close) flag is set.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   XPRINT   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   XPRINT is sent as a normal I/O data packet except that the PKT_CMD_BIT of
+   the "len" field is set, and the first "data" byte is XPRINT.
+
+   The I/O data in the XPRINT packet will contain the following:
+   -	Transparent Print Start Sequence
+   -	Transparent Print Data
+   -	Transparent Print Stop Sequence.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   MBIS   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MBIS is sent pre-emptively from the driver to set a port's modem signals.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+#define	PKT_ModemSet		(PKT_Data+4)		/* Modem set signals mask */
+
+/* ModemSet definitions... */
+#define	MBIS_RTS		0x01			/* RTS modem signal */
+#define	MBIS_DTR		0x02			/* DTR modem signal */
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   MBIC   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MBIC is sent pre-emptively from the driver to clear a port's modem signals.
+   */
+#if 0   
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+#define	PKT_ModemClear		(PKT_Data+4)		/* Modem clear signals mask */
+
+/* ModemClear definitions... */
+#define	MBIC_RTS		0x01			/* RTS modem signal */
+#define	MBIC_DTR		0x02			/* DTR modem signal */
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   MSET   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MSET is sent pre-emptively from the driver to set/clear a port's modem signals. */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#endif
+
+#define	PKT_ModemSet		(PKT_Data+4)		/* Modem set signals mask */
+
+/* ModemSet definitions... */
+#define	MSET_RTS		0x01			/* RTS modem signal */
+#define	MSET_DTR		0x02			/* DTR modem signal */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   PCLOSE   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+/* (Driver->RIO,in-band)
+
+   PCLOSE is sent from the driver to pseudo close a previously opened port.
+   
+   The port will close when all data has been sent/received, however, the
+   port's transmit / receive and modem signals will be left enabled and the
+   port marked internally as Pseudo Closed. */
+
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   MGET   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MGET is sent pre-emptively from the driver to request the port's current modem signals. */
+
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   MEMDUMP   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   MEMDUMP is sent pre-emptively from the driver to request a dump of 32 bytes
+   of the specified port's RTA address space.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#define	PKT_Address		(PKT_Data+6)		/* Requested address */
+
+/*****************************************************************************
+******************************                   *****************************
+******************************   READ_REGISTER   *****************************
+******************************                   *****************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   READ_REGISTER is sent pre-emptively from the driver to request the contents
+   of the CD1400 register specified in address.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#define	PKT_Address		(PKT_Data+6)		/* Requested address */
+
+/*****************************************************************************
+************************                            **************************
+************************   COMMAND_RUP - COMPLETE   **************************
+************************                            **************************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
+   packets, except MEMDUMP and READ_REGISTER.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#define	PKT_ModemStatus		(PKT_Data+3)		/* Modem signal status */
+#define	PKT_PortStatus		(PKT_Data+4)		/* Port signal status */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+
+/* ModemStatus definitions... */
+#define	MODEM_DSR		0x80			/* Data Set Ready modem state */
+#define	MODEM_CTS		0x40			/* Clear To Send modem state */
+#define	MODEM_RI		0x20			/* Ring Indicate modem state */
+#define	MODEM_CD		0x10			/* Carrier Detect modem state */
+#define	MODEM_TSTOP		0x08			/* Transmit Stopped state */
+#define	MODEM_TEMPTY		0x04			/* Transmit Empty state */
+#define	MODEM_DTR		0x02			/* DTR modem output state */
+#define	MODEM_RTS		0x01			/* RTS modem output state */
+
+/* PortStatus definitions... */
+#define	PORT_ISOPEN		0x01			/* Port open ? */
+#define	PORT_HUPCL		0x02			/* Hangup on close? */
+#define	PORT_MOPENPEND		0x04			/* Modem open pending */
+#define	PORT_ISPARALLEL		0x08			/* Parallel port */
+#define	PORT_BREAK		0x10			/* Port on break */
+#define	PORT_STATUSPEND		0020			/* Status packet pending */
+#define	PORT_BREAKPEND		0x40			/* Break packet pending */
+#define	PORT_MODEMPEND		0x80			/* Modem status packet pending */
+
+/*****************************************************************************
+************************                            **************************
+************************   COMMAND_RUP - COMPLETE   **************************
+************************                            **************************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
+   packets, except MEMDUMP and READ_REGISTER.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#endif
+#define	PKT_ModemStatus		(PKT_Data+3)		/* Modem signal status */
+#define	PKT_PortStatus		(PKT_Data+4)		/* Port signal status */
+#if 0
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#endif
+
+/* ModemStatus definitions... */
+#define	MODEM_DSR		0x80			/* Data Set Ready modem state */
+#define	MODEM_CTS		0x40			/* Clear To Send modem state */
+#define	MODEM_RI		0x20			/* Ring Indicate modem state */
+#define	MODEM_CD		0x10			/* Carrier Detect modem state */
+#define	MODEM_TSTOP		0x08			/* Transmit Stopped state */
+#define	MODEM_TEMPTY		0x04			/* Transmit Empty state */
+#define	MODEM_DTR		0x02			/* DTR modem output state */
+#define	MODEM_RTS		0x01			/* RTS modem output state */
+
+/* PortStatus definitions... */
+#define	PORT_ISOPEN		0x01			/* Port open ? */
+#define	PORT_HUPCL		0x02			/* Hangup on close? */
+#define	PORT_MOPENPEND		0x04			/* Modem open pending */
+#define	PORT_ISPARALLEL		0x08			/* Parallel port */
+#define	PORT_BREAK		0x10			/* Port on break */
+#define	PORT_STATUSPEND		0020			/* Status packet pending */
+#define	PORT_BREAKPEND		0x40			/* Break packet pending */
+#define	PORT_MODEMPEND		0x80			/* Modem status packet pending */
+
+/*****************************************************************************
+********************                                      ********************
+********************   COMMAND_RUP - COMPLETE - MEMDUMP   ********************
+********************                                      ********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - COMPLETE - MEMDUMP is sent as an acknowledgement for a MEMDUMP
+   port I/O control command packet.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#define	PKT_ModemStatus		(PKT_Data+3)		/* Modem signal status */
+#define	PKT_PortStatus		(PKT_Data+4)		/* Port signal status */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#define	PKT_Address		(PKT_Data+6)		/* Requested address */
+#endif
+#define	PKT_Dump		(PKT_Data+8)		/* 32bytes of requested dump data */
+
+/*****************************************************************************
+*****************                                            *****************
+*****************   COMMAND_RUP - COMPLETE - READ_REGISTER   *****************
+*****************                                            *****************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - COMPLETE - READ_REGISTER is sent as an acknowledgement for a
+   READ_REGISTER port I/O control command packet.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/*Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/*Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#endif
+#define	PKT_RegisterValue	(PKT_Data+3)		/* Modem signal status */
+#if 0
+#define	PKT_PortStatus		(PKT_Data+4)		/* Port signal status */
+#define	PKT_SubCmd		(PKT_Data+5)		/* Sub Command */
+#endif
+
+/*****************************************************************************
+*********************                                  ***********************
+*********************   COMMAND_RUP - BREAK_RECEIVED   ***********************
+*********************                                  ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - BREAK_RECEIVED packets are sent when the port detects a receive BREAK signal.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#endif
+
+/*****************************************************************************
+*********************                                *************************
+*********************   COMMAND_RUP - MODEM_STATUS   *************************
+*********************                                *************************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   COMMAND_RUP - MODEM_STATUS packets are sent whenever the port detects a
+   change in the input modem signal states.
+
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_PhbNum		(PKT_Data+1)		/* Port number wrt RTA */
+#define	PKT_Cmd2		(PKT_Data+2)		/* Command code copy */
+#define	PKT_ModemStatus		(PKT_Data+3)		/* Modem signal status */
+#endif
+
+/*****************************************************************************
+************************                             *************************
+************************   BOOT_RUP - BOOT_REQUEST   *************************
+************************                             *************************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   BOOT_RUP - BOOT_REQUEST packets are sent to the Driver from RIO to request
+   firmware code to load onto attached RTAs.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+
+/*****************************************************************************
+************************                              ************************
+************************   BOOT_RUP - BOOT_SEQUENCE   ************************
+************************                              ************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - BOOT_SEQUENCE packets are sent from the Driver to RIO in response
+   to a BOOT_RUP - BOOT_REQUEST packet.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_NumPackets		(PKT_Data+2)		/* Packets required to load firmware */
+#define	PKT_LoadBase		(PKT_Data+4)		/* RTA firmware load address */
+#define	PKT_CodeSize		(PKT_Data+6)		/* Size of firmware in bytes */
+#define	PKT_CmdString		(PKT_Data+8)		/* Command string */
+
+/*****************************************************************************
+************************                               ***********************
+************************   BOOT_RUP - BOOT_COMPLETED   ***********************
+************************                               ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   BOOT_RUP - BOOT_COMPLETE is sent to the Driver from RIO when downloading of
+   RTA firmware has completed.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_LinkNumber		(PKT_Data+1)		/* Link number RTA booted on */
+#define	PKT_SerialNumber	(PKT_Data+2)		/* 4 byte serial number */
+
+/*****************************************************************************
+************************                               ***********************
+************************   BOOT_RUP - Packet Request   ***********************
+************************                               ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   BOOT_RUP packet without the PKT_CMD_BIT set in the PKT->len field is sent
+   from RIO to the Driver as a request for a firmware boot packet. */
+
+#define	PKT_SequenceNumber	(PKT_Data+0)		/* Packet sequence number */
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   BOOT_RUP - Packet Response   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   In response to a BOOT_RUP boot packet request, the driver fills out the response
+   packet with the 70 bytes of the requested sequence.
+   */
+#if 0
+#define	PKT_SequenceNumber	(PKT_Data+0)		/* Packet sequence number */
+#endif
+#define	PKT_FirmwarePacket	(PKT_Data+2)		/* Firmware packet */
+
+/*****************************************************************************
+****************************                      ****************************
+****************************   BOOT_RUP - IFOAD   ****************************
+****************************                      ****************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - IFOAD packets are sent from the Driver to an RTA to cause the
+   RTA to shut down and reboot.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_IfoadId1		(PKT_Data+2)		/* IFOAD Id 1 */
+#define	PKT_IfoadId2		(PKT_Data+3)		/* IFOAD Id 2 */
+
+#define	IFOADID1		0xAD
+#define	IFOADID2		0xF0
+
+/*****************************************************************************
+**************************                         ***************************
+**************************   BOOT_RUP - IDENTIFY   ***************************
+**************************                         ***************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - IDENTIFY packets are sent from the Driver to an RTA to cause the
+   RTA to flash its LEDs for a period of time.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_IdentifyId		(PKT_Data+2)		/* defines pattern to flash */
+
+/*****************************************************************************
+****************************                       ***************************
+****************************   BOOT_RUP - ZOMBIE   ***************************
+****************************                       ***************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - ZOMBIE packets are sent from the Driver to an RTA to cause the
+   RTA to shut down and flash it's LEDs.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_ZombieId1		(PKT_Data+2)		/* ZOMBIE Id 1 */
+#define	PKT_ZombieId2		(PKT_Data+3)		/* ZOMBIE Id 2 */
+
+#define	ZOMBIEID1		0x52
+#define	ZOMBIEID2		0x21
+
+/*****************************************************************************
+****************************                      ****************************
+****************************   BOOT_RUP - UFOAD   ****************************
+****************************                      ****************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - UFOAD packets are sent from the Driver to an RTA to cause the RTA
+   to ask it's neighbouring RTA to shut down and reboot.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_LinkNumber		(PKT_Data+1)		/* Link number of RTA to UFOAD */
+#endif
+#define	PKT_UfoadId1		(PKT_Data+2)		/* UFOAD Id 1 */
+#define	PKT_UfoadId2		(PKT_Data+3)		/* UFOAD Id 2 */
+
+#define	UFOADID1		0x1E
+#define	UFOADID2		0x0D
+
+/*****************************************************************************
+****************************                      ****************************
+****************************   BOOT_RUP - IWAIT   ****************************
+****************************                      ****************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   BOOT_RUP - IWAIT packets are sent from the Driver to an RTA to cause the RTA
+   to pause booting on the specified link for 30 seconds.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#define	PKT_LinkNumber		(PKT_Data+1)		/* Link number of RTA to UFOAD */
+#endif
+#define	PKT_IwaitId1		(PKT_Data+2)		/* IWAIT Id 1 */
+#define	PKT_IwaitId2		(PKT_Data+3)		/* IWAIT Id 2 */
+
+#define	IWAITID1		0xDE
+#define	IWAITID2		0xB1
+
+/*****************************************************************************
+************************                               ***********************
+************************   ROUTE_RUP - ROUTE_REQUEST   ***********************
+************************                               ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   ROUTE_RUP - ROUTE_REQUEST packets are sent from a newly booted or connected
+   RTA to a Driver to request an ID (RUP or unit number).
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_SerialNumber	(PKT_Data+2)		/* 4 byte serial number */
+#define	PKT_ModuleTypes		(PKT_Data+6)		/* RTA Module types */
+
+/* ModuleTypes definitions... */
+#define	MOD_BLANK		0x0F			/* Blank plate attached */
+#define	MOD_RS232DB25		0x00			/* RS232 DB25 connector */
+#define	MOD_RS232RJ45		0x01			/* RS232 RJ45 connector */
+#define	MOD_RS422DB25		0x02			/* RS422 DB25 connector */
+#define	MOD_RS485DB25		0x03			/* RS485 DB25 connector */
+#define	MOD_PARALLEL		0x04			/* Centronics parallel */
+
+#define	MOD2			0x08			/* Set to indicate Rev2 module */
+
+/*****************************************************************************
+*************************                            *************************
+*************************   ROUTE_RUP - ROUTE_FOAD   *************************
+*************************                            *************************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   ROUTE_RUP - ROUTE_FOAD packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
+   packet to cause the RTA to "Fall Over And Die"., i.e. shutdown and reboot.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_RouteCmdString	(PKT_Data+2)		/* Command string */
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   ROUTE_RUP - ROUTE_ALLOCATE   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* (Driver->RIO,pre-emptive)
+
+   ROUTE_RUP - ROUTE_ALLOCATE packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
+   packet to allocate the RTA's Id number (RUP number 1..16)
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_IdNum		(PKT_Data+1)		/* RUP number for ports 1..8 */
+#if 0
+#define	PKT_RouteCmdString	(PKT_Data+2)		/* Command string */
+#endif
+#define	PKT_IdNum2		(PKT_Data+0x17)		/* RUP number for ports 9..16 */
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   ROUTE_RUP - ROUTE_TOPOLOGY   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* (RIO->Driver,pre-emptive)
+
+   ROUTE_RUP - ROUTE_TOPOLOGY packet is sent to inform the driver of an RTA's
+   current link status.
+   */
+#if 0
+#define	PKT_Cmd			(PKT_Data+0)		/* Command code */
+#endif
+#define	PKT_Link1Rup		(PKT_Data+2)		/* Link 1 RUP number */
+#define	PKT_Link1Link		(PKT_Data+3)		/* Link 1 link number */
+#define	PKT_Link2Rup		(PKT_Data+4)		/* Link 2 RUP number */
+#define	PKT_Link2Link		(PKT_Data+5)		/* Link 2 link number */
+#define	PKT_Link3Rup		(PKT_Data+6)		/* Link 3 RUP number */
+#define	PKT_Link3Link		(PKT_Data+7)		/* Link 3 link number */
+#define	PKT_Link4Rup		(PKT_Data+8)		/* Link 4 RUP number */
+#define	PKT_Link4Link		(PKT_Data+9)		/* Link 4 link number */
+#define	PKT_RtaVpdProm		(PKT_Data+10)		/* 32 bytes of RTA VPD PROM Contents */
+
+#endif						/* _sxwinif_h */
+
+/* End of RIOWINIF.H */
diff --git a/drivers/char/rio/riscos.h b/drivers/char/rio/riscos.h
new file mode 100644
index 0000000..7685cc1
--- /dev/null
+++ b/drivers/char/rio/riscos.h
@@ -0,0 +1,63 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riscos.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:19
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)riscos.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_riscos_h__
+#define __rio_riscos_h__
+
+#ifdef SCCS_LABELS
+static char *_riscos_h_sccs_ = "@(#)riscos.h	1.2";
+#endif
+
+/*
+** This module used to define all those little itsy bits required for RISC/OS
+** now it's full of null macros.
+*/
+
+/*
+**	RBYTE reads a byte from a location.
+**	RWORD reads a word from a location.
+**	WBYTE writes a byte to a location.
+**	WWORD writes a word to a location.
+**	RINDW reads a word through a pointer.
+**	WINDW writes a word through a pointer.
+**	RIOSWAB swaps the two bytes of a word, if needed.
+*/
+
+#define	RIOSWAB(N)      (N)
+#define	WBYTE(A,V)	(A)=(uchar)(V)
+#define WWORD(A,V)	(A)=(ushort)(V)
+#define RBYTE(A)	(uchar)(A)
+#define RWORD(A)	(ushort)(A)
+#define RINDW(A)	(*(ushort *)(A))
+#define WINDW(A,V)	(*(ushort *)(A)=(ushort)(V))
+
+#endif /* __rio_riscos_h__ */
diff --git a/drivers/char/rio/rom.h b/drivers/char/rio/rom.h
new file mode 100644
index 0000000..ee79b8e
--- /dev/null
+++ b/drivers/char/rio/rom.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      R O M
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _rom_h
+#define _rom_h 1
+
+#ifndef lint
+#ifdef SCCS
+static char *_rio_rom_h_sccs = "@(#)rom.h	1.1" ;
+#endif
+#endif
+
+typedef struct  ROM  ROM ;
+struct  ROM  {
+                 u_short    slx ;
+                 char       pcb_letter_rev ;
+                 char       pcb_number_rev ;
+                 char       serial[4] ;
+                 char       year ;
+                 char       week ;
+             } ;
+
+#endif
+
+#define HOST_ROM    (ROM *) 0x7c00
+#define RTA_ROM	    (ROM *) 0x7801
+#define ROM_LENGTH  0x20
+
+/*********** end of file ***********/
+
+
diff --git a/drivers/char/rio/route.h b/drivers/char/rio/route.h
new file mode 100644
index 0000000..c42dbb9
--- /dev/null
+++ b/drivers/char/rio/route.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                 R O U T E     H E A D E R
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _route_h
+#define _route_h
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_route_h_sccs = "@(#)route.h	1.3"; */
+#endif
+#endif
+
+#define MAX_LINKS 4
+#define MAX_NODES 17                          /* Maximum nodes in a subnet */
+#define NODE_BYTES ((MAX_NODES / 8) + 1)      /* Number of bytes needed for
+                                                 1 bit per node */
+#define ROUTE_DATA_SIZE  (NODE_BYTES + 2)     /* Number of bytes for complete 
+                                                 info about cost etc. */
+#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE)
+                                              /* Number of nodes we can squeeze
+                                                 into one packet */
+#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1)
+/************************************************
+ * Define the types of command for the ROUTE RUP.
+ ************************************************/
+#define ROUTE_REQUEST    0                    /* Request an ID */
+#define ROUTE_FOAD       1                    /* Kill the RTA */
+#define ROUTE_ALREADY    2                    /* ID given already */
+#define ROUTE_USED       3                    /* All ID's used */
+#define ROUTE_ALLOCATE   4                    /* Here it is */
+#define ROUTE_REQ_TOP    5                    /* I bet you didn't expect....
+                                                 the Topological Inquisition */
+#define ROUTE_TOPOLOGY   6                    /* Topology request answered FD */
+/*******************************************************************
+ * Define the Route Map Structure
+ *
+ * The route map gives a pointer to a Link Structure to use.
+ * This allows Disconnected Links to be checked quickly
+ ******************************************************************/
+typedef struct COST_ROUTE COST_ROUTE;
+struct COST_ROUTE {
+                      unsigned char cost;        /* Cost down this link */
+                      unsigned char route[NODE_BYTES]; /* Nodes thorough this route */
+                  } ;
+
+typedef struct ROUTE_STR ROUTE_STR ;
+struct  ROUTE_STR {
+                      COST_ROUTE cost_route[MAX_LINKS];
+                                                /* cost / route for this link */
+                      ushort favoured;          /* favoured link */
+                  } ;
+
+
+#define NO_LINK            (short) 5      /* Link unattached */
+#define ROUTE_NO_ID        (short) 100    /* No Id */
+#define ROUTE_DISCONNECT   (ushort) 0xff  /* Not connected */
+#define ROUTE_INTERCONNECT (ushort) 0x40  /* Sub-net interconnect */
+
+
+#define SYNC_RUP         (ushort) 255
+#define COMMAND_RUP      (ushort) 254
+#define ERROR_RUP        (ushort) 253
+#define POLL_RUP         (ushort) 252
+#define BOOT_RUP         (ushort) 251
+#define ROUTE_RUP        (ushort) 250
+#define STATUS_RUP       (ushort) 249
+#define POWER_RUP        (ushort) 248
+
+#define HIGHEST_RUP      (ushort) 255   /* Set to Top one */
+#define LOWEST_RUP       (ushort) 248   /* Set to bottom one */
+
+#endif
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/rtahw.h b/drivers/char/rio/rtahw.h
new file mode 100644
index 0000000..0686011
--- /dev/null
+++ b/drivers/char/rio/rtahw.h
@@ -0,0 +1,75 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******                R T A    H A R D W A R E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_rtahw_h_sccs = "@(#)rtahw.h	1.5" ;
+#endif
+#endif
+
+#define	WATCHDOG_ADDR	((unsigned short *)0x7a00)
+#define RTA_LED_ADDR	((unsigned short *)0x7c00)
+#define SERIALNUM_ADDR	((unsigned char *)0x7809)
+#define LATCH_ADDR      ((unsigned char *)0x7800)
+
+/*
+** Here we define where the cd1400 chips are in memory.
+*/
+#define CD1400_ONE_ADDR		(0x7300)
+#define CD1400_TWO_ADDR		(0x7200)
+#define CD1400_THREE_ADDR	(0x7100)
+#define CD1400_FOUR_ADDR	(0x7000)
+
+/*
+** Define the different types of modules we can have
+*/
+enum module {
+    MOD_BLANK		= 0x0f,		/* Blank plate attached */
+    MOD_RS232DB25	= 0x00,		/* RS232 DB25 connector */
+    MOD_RS232RJ45	= 0x01,		/* RS232 RJ45 connector */
+    MOD_RS422DB25	= 0x02,		/* RS422 DB25 connector */
+    MOD_RS485DB25	= 0x03,		/* RS485 DB25 connector */
+    MOD_PARALLEL	= 0x04		/* Centronics parallel */
+};
+
+#define TYPE_HOST	0
+#define TYPE_RTA8	1
+#define TYPE_RTA16	2
+
+#define	WATCH_DOG	WATCHDOG_ADDR
+
+/*********** end of file ***********/
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h
new file mode 100644
index 0000000..b9d2bc0
--- /dev/null
+++ b/drivers/char/rio/rup.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+ *******                                                              *******
+ *******               R U P   S T R U C T U R E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _rup_h
+#define _rup_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_rup_h_sccs = "@(#)rup.h	1.5"; */
+#endif
+#endif
+
+#if defined( HOST ) || defined( INKERNEL )
+#define MAX_RUP          ((short) 16) 
+#endif
+#ifdef RTA
+#define MAX_RUP          ((short) 1)
+#endif
+
+#define PKTS_PER_RUP     ((short) 2)     /* They are always used in pairs */
+
+/*************************************************
+ * Define all the  packet request stuff
+ ************************************************/
+#define TX_RUP_INACTIVE          0        /* Nothing to transmit */
+#define TX_PACKET_READY          1        /* Transmit packet ready */
+#define TX_LOCK_RUP              2        /* Transmit side locked */
+
+#define RX_RUP_INACTIVE          0        /* Nothing received */
+#define RX_PACKET_READY          1        /* Packet received */
+
+#define RUP_NO_OWNER             0xff     /* RUP not owned by any process */
+
+struct RUP {
+             PKT_ptr    txpkt;            /* Outgoing packet */
+             PKT_ptr    rxpkt;            /* Incoming packet */
+             WORD       link;             /* Which link to send down? */
+             BYTE       rup_dest_unit[2]; /* Destination unit */
+             WORD       handshake;        /* For handshaking */
+             WORD       timeout;          /* Timeout */
+             WORD       status;           /* Status */
+             WORD       txcontrol;        /* Transmit control */
+             WORD       rxcontrol;        /* Receive control */
+           };
+ 
+#endif
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/rupstat.h b/drivers/char/rio/rupstat.h
new file mode 100644
index 0000000..b4aafaf
--- /dev/null
+++ b/drivers/char/rio/rupstat.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      RUPSTAT
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _rupstat_h
+#define _rupstat_h
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_rupstat_h_sccs = "@(#)rupstat.h	1.1" ;
+#endif
+#endif
+
+#define    STATUS_SYNC    0
+#define    STATUS_REQ_TOP 1
+#define    STATUS_TOPOLOGY    2
+
+#endif
+
diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h
new file mode 100644
index 0000000..c1accb8
--- /dev/null
+++ b/drivers/char/rio/sam.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                    S A M . H
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+#ifndef _sam_h
+#define _sam_h 1
+
+#ifdef SCCS_LABELS
+#ifndef lint
+/* static char *_rio_sam_h_sccs = "@(#)sam.h	1.3"; */
+#endif
+#endif
+
+
+#if !defined( HOST ) && !defined( INKERNEL )
+#define RTA 1
+#endif
+
+#define NUM_FREE_LIST_UNITS     500
+
+#ifndef FALSE
+#define FALSE (short)  0x00
+#endif
+#ifndef TRUE
+#define TRUE  (short)  !FALSE
+#endif
+
+#define TX    TRUE
+#define RX    FALSE
+
+
+typedef struct FREE_LIST FREE_LIST ;
+struct FREE_LIST   {
+                       FREE_LIST_ptr next ;
+                       FREE_LIST_ptr prev ;
+                   } ;
+
+
+#endif
+/*********** end of file ***********/
+
+
+
diff --git a/drivers/char/rio/selftest.h b/drivers/char/rio/selftest.h
new file mode 100644
index 0000000..deae487
--- /dev/null
+++ b/drivers/char/rio/selftest.h
@@ -0,0 +1,73 @@
+/*
+** File:		selftest.h
+**
+** Author:		David Dix
+**
+** Created:		15th March 1993
+**
+** Last modified:	94/06/14
+**
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef	_selftests_h_
+#define _selftests_h_
+
+/*
+** Selftest identifier...
+*/
+#define SELFTEST_MAGIC	0x5a5a
+
+/*
+** This is the structure of the packet that is sent back after each
+** selftest on a booting RTA.
+*/
+typedef struct {
+    short		magic;			/* Identifies packet type */
+    int			test;			/* Test number, see below */
+    unsigned int	result;			/* Result value */
+    unsigned int	dataIn;
+    unsigned int	dataOut;
+}selftestStruct;
+
+/*
+** The different tests are identified by the following data values.
+*/
+enum test {
+    TESTS_COMPLETE	= 0x00,
+    MEMTEST_ADDR	= 0x01,
+    MEMTEST_BIT		= 0x02,
+    MEMTEST_FILL	= 0x03,
+    MEMTEST_DATABUS	= 0x04,
+    MEMTEST_ADDRBUS	= 0x05,
+    CD1400_INIT		= 0x10,
+    CD1400_LOOP		= 0x11,
+    CD1400_INTERRUPT    = 0x12
+};
+
+enum result {
+    E_PORT		= 0x10,
+    E_TX		= 0x11,
+    E_RX		= 0x12,
+    E_EXCEPT		= 0x13,
+    E_COMPARE		= 0x14,
+    E_MODEM		= 0x15,
+    E_TIMEOUT		= 0x16,
+    E_INTERRUPT         = 0x17
+};
+#endif	/* _selftests_h_ */
diff --git a/drivers/char/rio/space.h b/drivers/char/rio/space.h
new file mode 100644
index 0000000..72398d3
--- /dev/null
+++ b/drivers/char/rio/space.h
@@ -0,0 +1,45 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: space.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:19
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)space.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_space_h__
+#define __rio_space_h__
+
+#ifdef SCCS_LABELS
+static char *_space_h_sccs_ = "@(#)space.h	1.2";
+#endif
+
+extern int rio_cntls;
+extern int rio_bases[];
+extern int rio_limits[];
+extern int rio_vects[];
+
+#endif /* __rio_space_h__ */
diff --git a/drivers/char/rio/sysmap.h b/drivers/char/rio/sysmap.h
new file mode 100644
index 0000000..fdc7313
--- /dev/null
+++ b/drivers/char/rio/sysmap.h
@@ -0,0 +1,63 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******          S Y S T E M   M A P   H E A D E R
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_sysmap_h_sccs = "@(#)sysmap.h	1.1" ;
+#endif
+#endif
+
+#define SYSTEM_MAP_LEN     64           /* Len of System Map array */
+
+
+typedef struct SYS_MAP        SYS_MAP ;
+typedef struct SYS_MAP_LINK   SYS_MAP_LINK ;
+
+struct SYS_MAP_LINK {
+                        short id ;          /* Unit Id */
+                        short link ;        /* Id's Link */
+                        short been_here ;   /* Used by map_gen */
+                    } ;
+
+struct SYS_MAP {
+                   char         serial_num[4] ;
+                   SYS_MAP_LINK link[4] ;
+               } ;
+
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/timeouts.h b/drivers/char/rio/timeouts.h
new file mode 100644
index 0000000..11b3133
--- /dev/null
+++ b/drivers/char/rio/timeouts.h
@@ -0,0 +1,51 @@
+
+/****************************************************************************
+ *******                                                              *******
+ *******                     T I M E O U T S
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef lint
+#ifdef SCCS_LABELS
+static char *_rio_defaults_h_sccs = "@(#)timeouts.h	1.3" ;
+#endif
+#endif
+
+#define MILLISECOND           (int) (1000/64)   /* 15.625 low ticks */
+#define SECOND                (int) 15625       /* Low priority ticks */
+
+#define TX_TIMEOUT          (int) (200 * MILLISECOND)
+
+
+/*********** end of file ***********/
+
diff --git a/drivers/char/rio/top.h b/drivers/char/rio/top.h
new file mode 100644
index 0000000..255c40d
--- /dev/null
+++ b/drivers/char/rio/top.h
@@ -0,0 +1,49 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: top.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:19
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)top.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_top_h__
+#define __rio_top_h__
+
+#ifdef SCCS_LABELS
+static char *_top_h_sccs_ = "@(#)top.h	1.2";
+#endif
+
+/*
+** Topology information
+*/
+struct Top
+{
+    uchar Unit;
+    uchar Link;
+};
+
+#endif /* __rio_top_h__ */
diff --git a/drivers/char/rio/typdef.h b/drivers/char/rio/typdef.h
new file mode 100644
index 0000000..2cb9dd6
--- /dev/null
+++ b/drivers/char/rio/typdef.h
@@ -0,0 +1,82 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: typdef.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:20
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)typdef.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_typdef_h__
+#define __rio_typdef_h__
+
+#ifdef SCCS_LABELS
+static char *_typdef_h_sccs_ = "@(#)typdef.h	1.2";
+#endif
+
+#undef VPIX
+
+/*
+** IT IS REALLY, REALLY, IMPORTANT THAT BYTES ARE UNSIGNED!
+**
+** These types are ONLY to be used for refering to data structures
+** on the RIO Host card!
+*/
+typedef	volatile unsigned char	BYTE;
+typedef volatile unsigned short	WORD;
+typedef volatile unsigned int	DWORD;
+typedef	volatile unsigned short RIOP;
+typedef	volatile short          NUMBER;
+
+
+/*
+** 27.01.199 ARG - mods to compile 'newutils' on LyxnOS -
+** These #defines are for the benefit of the 'libfuncs' library
+** only. They are not necessarily correct type mappings and
+** are here only to make the source compile.
+*/
+/* typedef unsigned int	uint; */
+typedef unsigned long	ulong_t;
+typedef unsigned short	ushort_t;
+typedef unsigned char	uchar_t;
+typedef unsigned char	queue_t;
+typedef unsigned char	mblk_t;
+typedef	unsigned int 	paddr_t;
+typedef unsigned char   uchar;
+
+#define	TPNULL	((ushort)(0x8000))
+
+
+/*
+** RIO structures defined in other include files.
+*/
+typedef struct PKT	 	PKT;
+typedef struct LPB	 	LPB;
+typedef struct RUP	 	RUP;
+typedef struct Port		Port;
+typedef struct DpRam		DpRam;
+
+#endif /* __rio_typdef_h__ */
diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h
new file mode 100644
index 0000000..eddf862
--- /dev/null
+++ b/drivers/char/rio/unixrup.h
@@ -0,0 +1,56 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: unixrup.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:20
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)unixrup.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_unixrup_h__
+#define __rio_unixrup_h__
+
+#ifdef SCCS_LABELS
+static char *_unixrup_h_sccs_ = "@(#)unixrup.h	1.2";
+#endif
+
+/*
+**    UnixRup data structure. This contains pointers to actual RUPs on the
+**    host card, and all the command/boot control stuff.
+*/
+struct    UnixRup
+{
+    struct CmdBlk    *CmdsWaitingP;	/* Commands waiting to be done */
+    struct CmdBlk    *CmdPendingP;	/* The command currently being sent */
+    struct RUP       *RupP;		/* the Rup to send it to */
+    uint             Id;		/* Id number */
+    uint             BaseSysPort;	/* SysPort of first tty on this RTA */
+    uint             ModTypes;		/* Modules on this RTA */
+    spinlock_t	     RupLock;		/* Lock structure for MPX */
+/*    struct lockb     RupLock;	*/	/* Lock structure for MPX */
+};
+
+#endif /* __rio_unixrup_h__ */