]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.99pre7-9 2.3.99pre7-9
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:34:39 +0000 (15:34 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:34:39 +0000 (15:34 -0500)
123 files changed:
Documentation/sound/Maestro
Documentation/usb/input.txt
arch/i386/kernel/setup.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/isicom.c
drivers/char/rio/Makefile [new file with mode: 0644]
drivers/char/rio/board.h [new file with mode: 0644]
drivers/char/rio/bootpkt.h [new file with mode: 0644]
drivers/char/rio/brates.h [new file with mode: 0644]
drivers/char/rio/cdproto.h [new file with mode: 0644]
drivers/char/rio/chan.h [new file with mode: 0644]
drivers/char/rio/cirrus.h [new file with mode: 0644]
drivers/char/rio/cmd.h [new file with mode: 0644]
drivers/char/rio/cmdblk.h [new file with mode: 0644]
drivers/char/rio/cmdpkt.h [new file with mode: 0644]
drivers/char/rio/control.h [new file with mode: 0644]
drivers/char/rio/daemon.h [new file with mode: 0644]
drivers/char/rio/data.h [new file with mode: 0644]
drivers/char/rio/debug.h [new file with mode: 0644]
drivers/char/rio/defaults.h [new file with mode: 0644]
drivers/char/rio/eisa.h [new file with mode: 0644]
drivers/char/rio/enable.h [new file with mode: 0644]
drivers/char/rio/error.h [new file with mode: 0644]
drivers/char/rio/errors.h [new file with mode: 0644]
drivers/char/rio/formpkt.h [new file with mode: 0644]
drivers/char/rio/func.h [new file with mode: 0644]
drivers/char/rio/host.h [new file with mode: 0644]
drivers/char/rio/hosthw.h [new file with mode: 0644]
drivers/char/rio/link.h [new file with mode: 0644]
drivers/char/rio/linux_compat.h [new file with mode: 0644]
drivers/char/rio/list.h [new file with mode: 0644]
drivers/char/rio/lrt.h [new file with mode: 0644]
drivers/char/rio/ltt.h [new file with mode: 0644]
drivers/char/rio/lttwake.h [new file with mode: 0644]
drivers/char/rio/map.h [new file with mode: 0644]
drivers/char/rio/mca.h [new file with mode: 0644]
drivers/char/rio/mesg.h [new file with mode: 0644]
drivers/char/rio/param.h [new file with mode: 0644]
drivers/char/rio/parmmap.h [new file with mode: 0644]
drivers/char/rio/pci.h [new file with mode: 0644]
drivers/char/rio/phb.h [new file with mode: 0644]
drivers/char/rio/pkt.h [new file with mode: 0644]
drivers/char/rio/poll.h [new file with mode: 0644]
drivers/char/rio/port.h [new file with mode: 0644]
drivers/char/rio/proto.h [new file with mode: 0644]
drivers/char/rio/protsts.h [new file with mode: 0644]
drivers/char/rio/qbuf.h [new file with mode: 0644]
drivers/char/rio/rio.h [new file with mode: 0644]
drivers/char/rio/rio_linux.c [new file with mode: 0644]
drivers/char/rio/rio_linux.h [new file with mode: 0644]
drivers/char/rio/rioboard.h [new file with mode: 0644]
drivers/char/rio/rioboot.c [new file with mode: 0644]
drivers/char/rio/riocmd.c [new file with mode: 0644]
drivers/char/rio/rioctrl.c [new file with mode: 0644]
drivers/char/rio/riodrvr.h [new file with mode: 0644]
drivers/char/rio/rioinfo.h [new file with mode: 0644]
drivers/char/rio/rioinit.c [new file with mode: 0644]
drivers/char/rio/riointr.c [new file with mode: 0644]
drivers/char/rio/rioioctl.h [new file with mode: 0644]
drivers/char/rio/riolocks.h [new file with mode: 0644]
drivers/char/rio/rioparam.c [new file with mode: 0644]
drivers/char/rio/riopcicopy.c [new file with mode: 0644]
drivers/char/rio/rioroute.c [new file with mode: 0644]
drivers/char/rio/riospace.h [new file with mode: 0644]
drivers/char/rio/riotable.c [new file with mode: 0644]
drivers/char/rio/riotime.h [new file with mode: 0644]
drivers/char/rio/riotty.c [new file with mode: 0644]
drivers/char/rio/riotypes.h [new file with mode: 0644]
drivers/char/rio/riowinif.h [new file with mode: 0644]
drivers/char/rio/riscos.h [new file with mode: 0644]
drivers/char/rio/rom.h [new file with mode: 0644]
drivers/char/rio/route.h [new file with mode: 0644]
drivers/char/rio/rtahw.h [new file with mode: 0644]
drivers/char/rio/rup.h [new file with mode: 0644]
drivers/char/rio/rupstat.h [new file with mode: 0644]
drivers/char/rio/sam.h [new file with mode: 0644]
drivers/char/rio/selftest.h [new file with mode: 0644]
drivers/char/rio/space.h [new file with mode: 0644]
drivers/char/rio/sysmap.h [new file with mode: 0644]
drivers/char/rio/timeouts.h [new file with mode: 0644]
drivers/char/rio/top.h [new file with mode: 0644]
drivers/char/rio/typdef.h [new file with mode: 0644]
drivers/char/rio/unixrup.h [new file with mode: 0644]
drivers/char/tty_io.c
drivers/i2o/i2o_block.c
drivers/i2o/i2o_config.c
drivers/i2o/i2o_core.c
drivers/i2o/i2o_lan.c
drivers/i2o/i2o_lan.h
drivers/i2o/i2o_pci.c
drivers/net/de4x5.c
drivers/net/pcmcia/ibmtr_cs.c
drivers/net/tokenring/smctr.c
drivers/net/tokenring/smctr.h
drivers/scsi/NCR5380.c
drivers/scsi/ini9100u.c
drivers/sound/Makefile
drivers/sound/ac97_codec.c
drivers/sound/i810_audio.c
drivers/sound/mad16.c
drivers/sound/sb_card.c
drivers/sound/trident.c
drivers/sound/trix.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/buffer.c
fs/coda/psdev.c
fs/exec.c
fs/proc/array.c
fs/proc/base.c
fs/super.c
fs/udf/inode.c
include/linux/file.h
include/linux/i2o.h
include/linux/sched.h
ipc/shm.c
kernel/exec_domain.c
kernel/exit.c
mm/filemap.c
mm/page_alloc.c
mm/slab.c
mm/vmscan.c

index b7e1334cd2f62b67c1a1c014f5541de14d01680f..940156fc68b1432d186f417e2a27e6d17e253947 100644 (file)
@@ -30,7 +30,8 @@ Driver OSS Behavior
 --------------------
 
 This OSS driver exports /dev/mixer and /dev/dsp to applications, which
-mostly adhere to the OSS spec.
+mostly adhere to the OSS spec.   This driver doesn't register itself
+with /dev/sndstat, so don't expect information to appear there.
 
 The /dev/dsp device exported behaves almost as expected.  Playback is
 supported in all the various lovely formats.  8/16bit stereo/mono from
index ebf9058de68f6bdc29cc1912942a2392af84e545..262c595e4ba4d70ce3f725ca25b0febb059e1c13 100644 (file)
@@ -185,24 +185,28 @@ programs could use a more reasonable interface, for example evdev.c
        crw-r--r--   1 root     root      13,  33 Mar 29 00:41 mouse1
        crw-r--r--   1 root     root      13,  34 Mar 29 00:41 mouse2
        crw-r--r--   1 root     root      13,  35 Apr  1 10:50 mouse3
+       ...
+       ...
+       crw-r--r--   1 root     root      13,  62 Apr  1 10:50 mouse30
+       crw-r--r--   1 root     root      13,  63 Apr  1 10:50 mice
 
-and so on, up to mouse31. Each is assigned to a single mouse or digitizer,
-unless CONFIG_INPUT_MOUSEDEV_MIX is set. In that case all mice and
-digitizers share a single character device, mouse0, and even when none are
-connected, mouse0 is present. This is useful for hotplugging USB mice, so
-that programs can open the device even when no mice are present.
+Each 'mouse' device is assigned to a single mouse or digitizer, except the last
+one - 'mice'. This single character device is shared by all mice and
+digitizers, and even if none are connected, the device is present.  This is
+useful for hotplugging USB mice, so that programs can open the device even when
+no mice are present.
 
   CONFIG_INPUT_MOUSEDEV_SCREEN_[XY] in the kernel configuration are the size
 of your screen (in pixels) in XFree86. This is needed if you want to use
 your digitizer in X, because it's movement is sent to X via a virtual PS/2
-mouse.
+mouse. These values won't be used if you use a mouse only.
 
   Mousedev.c will generate either PS/2, ImPS/2 (microsoft intellimouse) or
 GenPS/2 (genius netmouse/netscroll) protocols, depending on what the program
-wishes. You can set GPM and X to any of these. You'll need ImPS/2 if you
-want to make use of a wheel on a USB mouse and GenPS/2 if you want to use
-extra (up to 5) buttons. I'm not sure how much is GenPS/2 supported in X,
-though.
+reading the data wishes. You can set GPM and X to any of these. You'll need
+ImPS/2 if you want to make use of a wheel on a USB mouse and GenPS/2 if you
+want to use extra (up to 5) buttons. I'm not sure how much is GenPS/2 supported
+in X, though.
 
 3.2.3 joydev.c
 ~~~~~~~~~~~~~~
@@ -216,6 +220,7 @@ though. As soon as any USB joystick is connected, it can be accessed in
        crw-r--r--   1 root     root      13,   1 Apr  1 10:50 js1
        crw-r--r--   1 root     root      13,   2 Apr  1 10:50 js2
        crw-r--r--   1 root     root      13,   3 Apr  1 10:50 js3
+       ...
 
 And so on up to js31.
 
@@ -236,6 +241,7 @@ independent.
        crw-r--r--   1 root     root      13,  65 Apr  1 10:50 event1
        crw-r--r--   1 root     root      13,  66 Apr  1 10:50 event2
        crw-r--r--   1 root     root      13,  67 Apr  1 10:50 event3
+       ...
 
 3. Contacts
 ~~~~~~~~~~~
index 455170f5d7439226b9685f664baa5697b0cf7b06..e3e043b2372c20c6c2198e3e0edeff1a3556735e 100644 (file)
@@ -1344,7 +1344,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
                        /* Names for the Pentium II/Celeron processors 
                           detectable only by also checking the cache size.
                           Dixon is NOT a Celeron. */
-                       if (cpu_models[i].x86 == 6) {
+                       if (c->x86 == 6) {
                                switch (c->x86_model) {
                                        case 5:
                                                if (c->x86_cache_size == 0)
index 89f51af944de58ce468f64d1e325131d0dd7a8b2..9df21affa0be7db8f1ec92f81c14036ed78088bd 100644 (file)
@@ -204,6 +204,9 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
       dep_tristate '  BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT
    fi
    dep_tristate '  Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_ALL_PPC" = "y" ]; then
+      dep_tristate '  PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV
+   fi
    if [ "$CONFIG_PARPORT" != "n" ]; then
       dep_tristate '  Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
index 150472a2fba414c3be1bad1a3c5e6905f2d2b958..280bf4a927a63b571fd7ac23cd668543d8a04800 100644 (file)
@@ -23,7 +23,7 @@ obj-          :=
 
 SUB_DIRS     := 
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia
+ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia rio
 
 #
 # This file contains the font map for the default (hardware) font
@@ -45,6 +45,13 @@ KEYBD    =pc_keyb.o
 CONSOLE  =console.o
 SERIAL   =serial.o
 
+ifeq ($(ARCH),s390)
+  KEYMAP   =
+  KEYBD    =
+  CONSOLE  =
+  SERIAL   =
+endif
+
 ifeq ($(ARCH),m68k)
    ifdef CONFIG_AMIGA
       KEYBD = amikeyb.o
@@ -127,11 +134,41 @@ obj-$(CONFIG_SYNCLINK) += synclink.o
 obj-$(CONFIG_N_HDLC) += n_hdlc.o
 obj-$(CONFIG_SPECIALIX) += specialix.o
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
+obj-$(CONFIG_SX) += sx.o
+
 
+# If either is in the kernel, generic_serial goes in the kernel, and
+# the module is no longer required. The "in kernel" case is last to be
+# able to override the module case....  This is an example of the new
+# "makefile automatically figures out the dependencies"....  -- REW
+
+GS = n
+ifeq ($(CONFIG_SX),m)
+  GS = m
+endif
+ifeq ($(CONFIG_RIO),m)
+  GS = m 
+endif
 ifeq ($(CONFIG_SX),y)
-obj-y += sx.o generic_serial.o
+  GS = y 
+endif
+ifeq ($(CONFIG_RIO),y)
+  GS = y 
+endif
+obj-$(GS) += generic_serial.o
+
+
+
+
+ifeq ($(CONFIG_RIO),y)
+obj-y += rio/rio.o  generic_serial.o
+SUB_DIRS += rio
+MOD_SUB_DIRS += rio
 else
-  obj-$(CONFIG_SX) += sx.o
+  ifeq ($(CONFIG_RIO),m)
+  obj-m += generic_serial.o
+  MOD_SUB_DIRS += rio
+  endif
 endif
 
 obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o
index 5e04e5e6d1d839fcddb6a3888233514054882699..958fbf77638274e98704cafa9de1a597e3696277 100644 (file)
@@ -98,7 +98,7 @@ static DECLARE_MUTEX(tmp_buf_sem);
 
 /*   baud index mappings from linux defns to isi */
 
-static char linuxb_to_isib[] = {
+static signed char linuxb_to_isib[] = {
        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,     
        18, 19
 };
diff --git a/drivers/char/rio/Makefile b/drivers/char/rio/Makefile
new file mode 100644 (file)
index 0000000..d6d6965
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# 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. 
+#
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := rio.o
+O_OBJS   := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \
+            rioparam.o riopcicopy.o rioroute.o riotable.o riotty.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
+
+rio.o: $(O_OBJS)
\ No newline at end of file
diff --git a/drivers/char/rio/board.h b/drivers/char/rio/board.h
new file mode 100644 (file)
index 0000000..0b397e1
--- /dev/null
@@ -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 (file)
index 0000000..c329aeb
--- /dev/null
@@ -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 (file)
index 0000000..bd4fc84
--- /dev/null
@@ -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/cdproto.h b/drivers/char/rio/cdproto.h
new file mode 100644 (file)
index 0000000..d53a03c
--- /dev/null
@@ -0,0 +1,55 @@
+/* 
+ *
+ *  (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 _cirrusprots_h
+#define _cirrusprots_h
+
+#ifdef RTA
+extern void cd1400_reset ( int uart) ;
+extern void cd1400_init ( int uart ) ;
+extern void ccr_wait ( int priority, int port) ;
+extern void cd1400_txstart( int port) ;
+extern void cd1400_rxstart ( int port) ;
+extern void command_acknowledge ( PHB *port_header ) ;
+extern int close_port ( ushort port, PHB *port_header, ushort preemptive, int pseudo) ;
+extern void command_preemptive ( PKT *packet) ;
+extern void rup_service ( void ) ;
+extern ushort GetModemLines(struct PHB *, register short *);
+extern void cd1400_intr (Process *cirrus_p, ushort *RtaType) ;
+extern void cd1400_mdint ( short port) ;
+extern void cd1400_rxint ( short port) ;
+extern void cd1400_rxexcept ( short port) ;
+extern void cd1400_txdata ( short port, PHB *port_header, PKT *packet) ;
+extern void cd1400_fast_clock(void);
+extern void cd1400_map_baud ( ushort host_rate, ushort *prescaler, ushort *divisor) ;
+extern void cd1400_modem ( ushort port, ushort way) ;
+extern void cd1400_txcommand ( short port, PHB *port_header, PKT *packet) ;
+extern void cd1400_txint ( int port) ;
+void Rprintf( char *RIOPrBuf, char *Str, ... );
+#if defined(DCIRRUS)
+void debug_packet(PKT *pkt, int option, char *string, int channel);
+#endif /* defined(DCIRRUS) */
+#endif
+
+#ifdef HOST
+extern void wflush (PHB *);
+extern void command_preemptive (PKT *);
+#endif
+
+#endif /* _cirrusprots_h */
diff --git a/drivers/char/rio/chan.h b/drivers/char/rio/chan.h
new file mode 100644 (file)
index 0000000..5b30654
--- /dev/null
@@ -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 (file)
index 0000000..cf056a9
--- /dev/null
@@ -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 (file)
index 0000000..c369eda
--- /dev/null
@@ -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 (file)
index 0000000..2b8efbd
--- /dev/null
@@ -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 (file)
index 0000000..6db1009
--- /dev/null
@@ -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 seperate
+** 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 (file)
index 0000000..1712f62
--- /dev/null
@@ -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 (file)
index 0000000..62dba0e
--- /dev/null
@@ -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 (file)
index 0000000..dabc2d1
--- /dev/null
@@ -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 (file)
index 0000000..b6e0d09
--- /dev/null
@@ -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 (file)
index 0000000..2e7309e
--- /dev/null
@@ -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 (file)
index 0000000..59371b0
--- /dev/null
@@ -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 (file)
index 0000000..8e9a419
--- /dev/null
@@ -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 (file)
index 0000000..229438e
--- /dev/null
@@ -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 (file)
index 0000000..f920b9f
--- /dev/null
@@ -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 (file)
index 0000000..a8b65ae
--- /dev/null
@@ -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 (file)
index 0000000..f51eeb0
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+#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 RIOBootComplete(struct rio_info *, struct Host *, uint, struct PktCmd *);
+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 *);
+int RIOCommandRup(struct rio_info *, uint, struct Host *, struct PKT *);
+struct CmdBlk * RIOGetCmdBlk(void);
+void RIOFreeCmdBlk(struct CmdBlk *);
+int RIOQueueCmdBlk(struct Host *, uint, struct CmdBlk *);
+void RIOPollHostCommands(struct rio_info *, struct Host *);
+int RIOStrlen(register char *);
+int RIOStrCmp(register char *, register char *);
+int RIOStrnCmp(register char *, register char *, int);
+void  RIOStrNCpy(char *, char *, int);
+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 copyout(caddr_t, int, 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);
+int RIOScrub(int, BYTE *, int);
+void RIOAllocateInterrupts(struct rio_info *);
+void RIOStopInterrupts(struct rio_info *, int, int);
+void RIOAllocDataStructs(struct rio_info *);
+void RIOSetupDataStructs(struct rio_info *);
+int RIODefaultName(struct rio_info *, struct Host *, uint);
+int RIOReport(struct rio_info *);
+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 riopoll(struct rio_info *);
+void riointr(struct rio_info *);
+void RIOTxEnable(char *);
+void RIOServiceHost(struct rio_info *, struct Host *, int);
+void RIOReceive(struct rio_info *, struct Port *);
+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); 
+int RIOCheckIsolated(struct rio_info *, struct Host *, uint);
+int RIOIsolate(struct rio_info *, struct Host *, uint);
+int RIOCheck(struct Host *, uint);
+uint GetUnitType(uint);
+int RIOSetChange(struct rio_info *);
+void RIOConCon(struct rio_info *, struct Host *, uint, uint, uint, uint, int);
+int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *);
+int RIOFreeDisconnected(struct rio_info *, struct Host *, int );
+int RIORemoveFromSavedTable(struct rio_info *, struct Map *);
+
+
+/* riotty.c */
+
+int riotopen(struct tty_struct * tty, struct file * filp);
+int riotclose(void  *ptr);
+int RIOCookMode(struct ttystatics *);
+int riotioctl(struct rio_info *, dev_t, 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 (kdev_t device);
+extern int rio_ismodem (kdev_t device);
+extern void rio_udelay (int usecs);
+
+#endif /* __func_h_def */
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
new file mode 100644 (file)
index 0000000..6a155c1
--- /dev/null
@@ -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 */
+    int locks;
+    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 (file)
index 0000000..f6f31ec
--- /dev/null
@@ -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 (file)
index 0000000..9722503
--- /dev/null
@@ -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 (file)
index 0000000..5a4ae63
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * (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.
+ */
+
+
+#define disable(oldspl) save_flags (oldspl)
+#define restore(oldspl) restore_flags (oldspl)
+
+#define sysbrk(x) kmalloc ((x), 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 major(dev) MAJOR(dev)
+#define minor(dev) MINOR(dev)
+
+#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_dprint(f, p) do {if (rio_debug & f) printk p;} while (0)
+
+#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
+
+
+/* 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 (file)
index 0000000..ae7368d
--- /dev/null
@@ -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
+** relevent 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 (file)
index 0000000..bbac8fa
--- /dev/null
@@ -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 (file)
index 0000000..f27dcec
--- /dev/null
@@ -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 (file)
index 0000000..fe17d0e
--- /dev/null
@@ -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 (file)
index 0000000..400645a
--- /dev/null
@@ -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 (file)
index 0000000..08a327e
--- /dev/null
@@ -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 (file)
index 0000000..9cf6c0b
--- /dev/null
@@ -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 (file)
index 0000000..2dc30b9
--- /dev/null
@@ -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 (file)
index 0000000..ea67100
--- /dev/null
@@ -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 accomodate 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 (file)
index 0000000..dc635bd
--- /dev/null
@@ -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 (file)
index 0000000..e1483a0
--- /dev/null
@@ -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 (file)
index 0000000..66bb2ff
--- /dev/null
@@ -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 (file)
index 0000000..d9b8e98
--- /dev/null
@@ -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 (file)
index 0000000..8506af0
--- /dev/null
@@ -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 (file)
index 0000000..ddff0ef
--- /dev/null
@@ -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 (file)
index 0000000..848111a
--- /dev/null
@@ -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 (file)
index 0000000..1fce02f
--- /dev/null
@@ -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 (file)
index 0000000..23f90a1
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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)
+
+/*
+**     Min and Max
+*/
+#ifndef min
+#define        min(A,B)        ((A)<(B)?(A):(B))
+#endif
+#ifndef max
+#define        max(A,B)        ((A)>(B)?(A):(B))
+#endif
+
+#define        splrio  spltty
+
+#define        RIO_IPL 5
+#define        RIO_PRI (PZERO+10)
+#define RIO_CLOSE_PRI  PZERO-1 /* uninteruptible 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 (file)
index 0000000..0adc6ef
--- /dev/null
@@ -0,0 +1,1557 @@
+
+/* 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
+ *
+ * */
+
+
+#define RCS_ID "$Id: rio.c,v 1.1 1999/07/11 10:13:54 wolff Exp wolff $"
+#define RCS_REV "$Revision: 1.1 $"
+
+
+#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/tqueue.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+#include <linux/miscdevice.h>
+
+#include <linux/compatmac.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 "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.... */
+
+
+/* ************************************************************** */
+/* * This section can be removed when 2.0 becomes outdated....  * */
+/* ************************************************************** */
+
+#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
+#define TWO_ZERO
+#else
+#if LINUX_VERSION_CODE < 0x020209   /* less than 2.2.x */
+#warning "Please use a recent 2.2.x kernel. "
+#endif
+#endif
+
+
+#ifdef TWO_ZERO
+
+/* Here is the section that makes the 2.2 compatible driver source 
+   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
+   and provide for compatibility stuff here if possible. */
+
+#include <linux/bios32.h>
+
+#define Get_user(a,b)                a = get_user(b)
+#define Put_user(a,b)                0,put_user(a,b)
+#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
+
+static inline int copy_from_user(void *to,const void *from, int c) 
+{
+  memcpy_fromfs(to, from, c);
+  return 0;
+}
+
+#define pci_present                  pcibios_present
+#define pci_read_config_word         pcibios_read_config_word
+#define pci_read_config_dword        pcibios_read_config_dword
+
+static inline unsigned char get_irq (unsigned char bus, unsigned char fn)
+{
+  unsigned char t; 
+  pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t);
+  return t;
+}
+
+static inline void *ioremap(unsigned long base, long length)
+{
+  if (base < 0x100000) return (void *)base;
+  return vremap (base, length);
+}
+
+#define my_iounmap(x, b)             (((long)x<0x100000)?0:vfree ((void*)x))
+
+#define capable(x)                   suser()
+
+#define queue_task                   queue_task_irq_off
+#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
+#define signal_pending(current)      (current->signal & ~current->blocked)
+#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
+#define time_after(t1,t2)            (((long)t1-t2) > 0)
+
+
+#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
+#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
+
+/* Not yet implemented on 2.0 */
+#define ASYNC_SPD_SHI  -1
+#define ASYNC_SPD_WARP -1
+
+
+/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
+   to the "name" field that does exist. As long as the assignments are
+   done in the right order, there is nothing to worry about. */
+#define driver_name           name 
+
+/* Should be in a header somewhere. They are in tty.h on 2.2 */
+#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
+#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
+
+/* The return type of a "close" routine. */
+#define INT                   void
+#define NO_ERROR              /* Nothing */
+
+#else
+
+/* The 2.2.x compatibility section. */
+#include <asm/uaccess.h>
+
+#define Get_user(a,b)         get_user(a,b)
+#define Put_user(a,b)         put_user(a,b)
+#define get_irq(pdev)         pdev->irq
+
+#define INT                   int
+#define NO_ERROR              0              
+
+#define my_iounmap(x,b)       (iounmap((char *)(b)))
+
+#endif
+
+/* ************************************************************** */
+/* *                End of compatibility section..              * */
+/* ************************************************************** */
+
+
+
+/* Why the hell am I defining these here? */
+#define RIO_TYPE_NORMAL 1
+#define RIO_TYPE_CALLOUT 2
+
+#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_CALLOUT_MAJOR0 155
+#define RIO_NORMAL_MAJOR1  156
+#define RIO_CALLOUT_MAJOR1 157
+#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 */
+  /* 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_fw_open(struct inode *inode, struct file *filp);
+static INT rio_fw_release(struct inode *inode, struct file *filp);
+static int rio_init_drivers(void);
+
+
+void my_hd (void *addr, int len);
+
+
+
+static struct tty_driver rio_driver, rio_callout_driver;
+static struct tty_driver rio_driver2, rio_callout_driver2;
+
+static struct tty_struct * rio_table[RIO_NPORTS] = { NULL, };
+static struct termios ** rio_termios;
+static struct termios ** rio_termios_locked;
+
+/* 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;
+
+/* struct rio_board boards[RIO_HOSTS]; */
+struct rio_port *rio_ports;
+
+int rio_refcount;
+int rio_initialized = 0;
+int rio_nports = 0;
+int rio_debug = 0;
+
+
+/* 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.
+*/
+int rio_poll = 1;
+
+
+/* These are the only open spaces in my computer. Yours may have more
+   or less.... */
+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;
+
+#ifndef TWO_ZERO
+#ifdef MODULE
+MODULE_PARM(rio_poll, "i");
+MODULE_PARM(rio_debug, "i");
+MODULE_PARM(rio_irqmask, "i");
+#endif
+#endif
+
+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
+};
+
+
+/* 
+   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... 
+*/
+#define DEBUG
+
+#ifdef DEBUG
+#define rio_dprintk(f, str...) if (rio_debug & f) printk (str)
+#else
+#define rio_dprintk(f, str...) /* nothing */
+#endif
+
+
+#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n")
+#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  " __FUNCTION__ "\n")
+
+#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \
+                                  "(port %d)\n", port->line)
+
+
+
+
+/* 
+ *  Firmware loader driver specific routines
+ *
+ */
+
+static struct file_operations rio_fw_fops = {
+       NULL,   /*      lseek   */
+       NULL,   /*      read    */
+       NULL,   /*      write   */
+       NULL,   /*      readdir */
+       NULL,   /*      select  */
+       rio_fw_ioctl,
+       NULL,   /*      mmap    */
+       rio_fw_open,
+#ifndef TWO_ZERO
+       NULL,   /*      flush   */
+#endif
+       rio_fw_release,
+       NULL,   /*      fsync   */
+       NULL,   /*      fasync  */
+       NULL,   /*      check_media_change      */
+       NULL,   /*      revalidate      */
+};
+
+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,
+                                   kdev_t device, 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, kdevname(device), routine);
+    return 1;
+  }
+  if (port->magic != RIO_MAGIC) {
+    printk(badmagic, kdevname(device), routine);
+    return 1;
+  }
+
+  return 0;
+}
+#else
+#define rio_paranoia_check(a,b,c) 0
+#endif
+
+
+#ifdef DEBUG
+void my_hd (void *ad, int len)
+{
+  int i, j, ch;
+  unsigned char *addr = ad;
+  
+  for (i=0;i<len;i+=16) {
+    printk ("%08x ", (int) addr+i);
+    for (j=0;j<16;j++) {
+      printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+    }
+    for (j=0;j<16;j++) {
+      ch = addr[j+i];
+      printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+    }
+    printk ("\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);  
+  current->state = TASK_INTERRUPTIBLE;
+  schedule_timeout(njiffies);
+  current->state = TASK_RUNNING;
+  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);  
+  current->state = TASK_UNINTERRUPTIBLE;
+  schedule_timeout(njiffies);
+  current->state = TASK_RUNNING;
+  func_exit();
+  return !RIO_FAIL;
+}
+
+
+int rio_minor (kdev_t device)
+{
+  return MINOR (device) + 
+    256 * ((MAJOR (device) == RIO_NORMAL_MAJOR1) ||
+          (MAJOR (device) == RIO_CALLOUT_MAJOR1));
+}
+
+
+int rio_ismodem (kdev_t device)
+{
+  return (MAJOR (device) != RIO_NORMAL_MAJOR0) &&
+         (MAJOR (device) != RIO_NORMAL_MAJOR1);
+}
+
+
+void rio_udelay (int usecs)
+{
+  udelay (usecs);
+}
+
+
+void rio_inc_mod_count (void)
+{
+  func_enter ();
+  MOD_INC_USE_COUNT; 
+  func_exit ();
+}
+
+
+void rio_dec_mod_count (void)
+{
+  func_enter ();
+  MOD_DEC_USE_COUNT; 
+  func_exit ();
+}
+
+
+static int rio_set_real_termios (void *ptr)
+{
+  int rv;
+  func_enter();
+
+  rv = RIOParam( (struct Port *) ptr, CONFIG, 0, 1);
+
+  func_exit ();
+
+  return rv;
+}
+
+
+void rio_reset_interrupt (struct Host *HostP)
+{
+  switch( HostP->Type ) {
+  case RIO_AT:
+  case RIO_MCA:
+  case RIO_PCI:
+    WBYTE(HostP->ResetInt , 0xff);
+  }
+}
+
+
+static void rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
+{
+  struct Host *HostP;
+
+  HostP = &p->RIOHosts[(long)ptr];
+  /*   func_enter ();  */
+  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 wont
+       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
+
+  if (HostP->Ivec == irq) {
+    /* Tell the card we've noticed the interrupt. */
+    rio_reset_interrupt (HostP);
+  }
+
+  if ((HostP->Flags & RUN_STATE) != RC_RUNNING) return;
+
+  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;
+  }
+
+  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 ();  */
+}
+
+
+static void rio_pollfunc (unsigned long data)
+{
+  func_enter ();
+
+  rio_interrupt (0, (void *)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) 
+{
+  func_enter();
+
+#if 0
+  port->gs.flags &= ~ GS_ACTIVE;
+  if (!port->gs.tty) {
+    printk ("No tty.\n");
+    return;
+  }
+  if (!port->gs.tty->termios) {
+    printk ("No termios.\n");
+    return;
+  }
+  if (port->gs.tty->termios->c_cflag & HUPCL) {
+    rio_setsignals (port, 0, 0);
+  }
+#endif
+
+  func_exit();
+}
+
+
+
+/* ********************************************************************** *
+ *                Here are the routines that actually                     *
+ *               interface with the rest of the system                    *
+ * ********************************************************************** */
+
+
+static int rio_fw_open(struct inode *inode, struct file *filp)
+{
+  func_enter ();
+  rio_inc_mod_count ();
+  func_exit ();
+  return 0;
+}
+
+
+static INT rio_fw_release(struct inode *inode, struct file *filp)
+{
+  func_enter ();
+  rio_dec_mod_count ();
+  func_exit ();
+  return NO_ERROR;
+}
+
+
+/* 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)
+{
+  func_enter ();
+  /* rio_dec_mod_count (); */
+  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)
+{
+  func_enter ();
+  riotclose (ptr);
+  rio_dec_mod_count ();
+  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, suser ());
+
+  func_exit ();
+  return rc;
+}
+
+
+static int rio_ioctl (struct tty_struct * tty, struct file * filp, 
+                     unsigned int cmd, unsigned long arg)
+{
+#if 0
+  int rc;
+  struct rio_port *port = tty->driver_data;
+  int ival;
+
+  /* func_enter2(); */
+
+
+  rc  = 0;
+  switch (cmd) {
+  case TIOCGSOFTCAR:
+    rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
+                  (unsigned int *) arg);
+    break;
+  case TIOCSSOFTCAR:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(int))) == 0) {
+      Get_user(ival, (unsigned int *) arg);
+      tty->termios->c_cflag =
+        (tty->termios->c_cflag & ~CLOCAL) |
+        (ival ? CLOCAL : 0);
+    }
+    break;
+  case TIOCGSERIAL:
+    if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
+                          sizeof(struct serial_struct))) == 0)
+      gs_getserial(&port->gs, (struct serial_struct *) arg);
+    break;
+  case TIOCSSERIAL:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(struct serial_struct))) == 0)
+      rc = gs_setserial(&port->gs, (struct serial_struct *) arg);
+    break;
+  case TIOCMGET:
+    if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
+                          sizeof(unsigned int))) == 0) {
+      ival = rio_getsignals(port);
+      put_user(ival, (unsigned int *) arg);
+    }
+    break;
+  case TIOCMBIS:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(unsigned int))) == 0) {
+      Get_user(ival, (unsigned int *) arg);
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
+                           ((ival & TIOCM_RTS) ? 1 : -1));
+    }
+    break;
+  case TIOCMBIC:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(unsigned int))) == 0) {
+      Get_user(ival, (unsigned int *) arg);
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
+                           ((ival & TIOCM_RTS) ? 0 : -1));
+    }
+    break;
+  case TIOCMSET:
+    if ((rc = verify_area(VERIFY_READ, (void *) arg,
+                          sizeof(unsigned int))) == 0) {
+      Get_user(ival, (unsigned int *) arg);
+      rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
+                           ((ival & TIOCM_RTS) ? 1 : 0));
+    }
+    break;
+
+  default:
+    rc = -ENOIOCTLCMD;
+    break;
+  }
+  /* func_exit(); */
+  return rc;
+#else
+  return -ENOIOCTLCMD;
+#endif
+
+}
+
+
+/* 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.               *
+ * ********************************************************************** */
+
+
+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);
+
+  return &vpdp;
+}
+
+
+
+static int rio_init_drivers(void)
+{
+  int error;
+  
+  func_enter();
+
+  memset(&rio_driver, 0, sizeof(rio_driver));
+  rio_driver.magic = TTY_DRIVER_MAGIC;
+  rio_driver.driver_name = "specialix_rio";
+  rio_driver.name = "ttySR";
+  rio_driver.major = RIO_NORMAL_MAJOR0;
+  rio_driver.num = 256;
+  rio_driver.type = TTY_DRIVER_TYPE_SERIAL;
+  rio_driver.subtype = RIO_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;
+  rio_driver.refcount = &rio_refcount;
+  rio_driver.table = rio_table;
+  rio_driver.termios = rio_termios;
+  rio_driver.termios_locked = rio_termios_locked;
+
+  rio_driver.open  = riotopen;
+  rio_driver.close = gs_close;
+  rio_driver.write = gs_write;
+  rio_driver.put_char = gs_put_char;
+  rio_driver.flush_chars = gs_flush_chars;
+  rio_driver.write_room = gs_write_room;
+  rio_driver.chars_in_buffer = gs_chars_in_buffer;
+  rio_driver.flush_buffer = gs_flush_buffer;
+  rio_driver.ioctl = rio_ioctl;
+  rio_driver.throttle = rio_throttle;
+  rio_driver.unthrottle = rio_unthrottle;
+  rio_driver.set_termios = gs_set_termios;
+  rio_driver.stop = gs_stop;
+  rio_driver.start = gs_start;
+  rio_driver.hangup = gs_hangup;
+
+  rio_driver2 = rio_driver;
+  rio_driver.major = RIO_NORMAL_MAJOR1;
+
+  rio_callout_driver = rio_driver;
+  rio_callout_driver.name = "cusr";
+  rio_callout_driver.major = RIO_CALLOUT_MAJOR0;
+  rio_callout_driver.subtype = RIO_TYPE_CALLOUT;
+
+  rio_callout_driver2 = rio_callout_driver;
+  rio_callout_driver2.major = RIO_CALLOUT_MAJOR1;
+
+  rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
+
+  if ((error = tty_register_driver(&rio_driver))) goto bad1;
+  if ((error = tty_register_driver(&rio_driver2))) goto bad2;
+  if ((error = tty_register_driver(&rio_callout_driver))) goto bad3;
+  if ((error = tty_register_driver(&rio_callout_driver2))) goto bad4;
+
+  func_exit();
+  return 0;
+  /* 
+ bad5:tty_unregister_driver (&rio_callout_driver2); */
+ bad4:tty_unregister_driver (&rio_callout_driver);
+ bad3:tty_unregister_driver (&rio_driver2);
+ bad2:tty_unregister_driver (&rio_driver);
+ bad1: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;
+  if (!(rio_termios        = ckmalloc (RIO_PORTS * TMIO_SZ))) goto free3;
+  if (!(rio_termios_locked = ckmalloc (RIO_PORTS * TMIO_SZ))) goto free4;
+  p->RIOConf = RIOConf;
+  rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p %p %p\n", 
+               p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+
+  /* Adjust the values in the "driver" */
+  rio_driver.termios = rio_termios;
+  rio_driver.termios_locked = rio_termios_locked;
+  
+#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.callout_termios = tty_std_termios;
+    port->gs.normal_termios  = tty_std_termios;
+    port->gs.magic = RIO_MAGIC;
+    port->gs.close_delay = HZ/2;
+    port->gs.closing_wait = 30 * HZ;
+    port->gs.rd = &rio_real_driver;
+  }
+#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: */
+       kfree (rio_termios_locked); 
+ free4:kfree (rio_termios);
+ free3:kfree (p->RIOPortp);
+ free2:kfree (p->RIOHosts);
+ free1:kfree (p);
+ free0:
+  rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p %p %p\n", 
+               p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+  return -ENOMEM;
+}
+
+
+#ifdef MODULE
+static void rio_release_drivers(void)
+{
+  func_enter();
+  tty_unregister_driver (&rio_callout_driver2);
+  tty_unregister_driver (&rio_callout_driver);
+  tty_unregister_driver (&rio_driver2);
+  tty_unregister_driver (&rio_driver);
+  func_exit();
+}
+#endif
+
+#ifdef TWO_ZERO
+#define PDEV unsigned char pci_bus, unsigned pci_fun
+#define pdev pci_bus, pci_fun
+#else
+#define PDEV   struct pci_dev *pdev
+#endif
+
+
+#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 */
+
+void fix_rio_pci (PDEV)
+{
+  unsigned int hwbase;
+  unsigned long rebase;
+  unsigned int t;
+
+#define CNTRL_REG_OFFSET        0x50
+#define CNTRL_REG_GOODVALUE     0x00260000
+
+  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);  
+  }
+  my_iounmap (hwbase, rebase);
+}
+#endif
+
+
+#ifdef MODULE
+#define rio_init init_module
+#endif
+
+extern int gs_debug;
+
+int rio_init(void) 
+{
+  int found = 0;
+  int i;
+  struct Host *hp;
+  int retval;
+  struct vpd_prom *vpdp;
+  int okboard;
+
+
+#ifdef CONFIG_PCI
+#ifndef TWO_ZERO
+  struct pci_dev *pdev = NULL;
+#else
+  unsigned char pci_bus, pci_fun;
+  /* in 2.2.x pdev is a pointer defining a PCI device. In 2.0 its the bus/fn */
+#endif
+  unsigned int tint;
+  unsigned short tshort;
+#endif
+
+  func_enter();
+  rio_dprintk (RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", 
+              rio_debug);
+  gs_debug = rio_debug >> 24;
+
+  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;
+  }
+
+  retval = rio_init_datastructures ();
+  if (retval < 0) return retval;
+
+#ifdef CONFIG_PCI
+  if (pci_present ()) {
+    /* First look for the JET devices: */
+#ifndef TWO_ZERO
+    while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 
+                                    PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, 
+                                    pdev))) {
+#else
+    for (i=0;i< RIO_NBOARDS;i++) {
+      if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, 
+                              PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, i,
+                              &pci_bus, &pci_fun)) break;
+#endif
+      /* 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);
+      /* rio_dprintk (RIO_DEBUG_PROBE, "pdev = %d/%d  (%x)\n", pdev, 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 = get_irq (pdev);
+      if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+      hp->CardP        = (struct DpRam *)
+      hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->Type  = RIO_PCI;
+      hp->Copy  = rio_pcicopy; 
+      hp->Mode  = RIO_PCI_DEFAULT_MODE;
+      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);
+
+#if 1
+        fix_rio_pci (pdev);
+#endif
+        p->RIOLastPCISearch = RIO_SUCCESS;
+        p->RIONumHosts++;
+        found++;
+      } else {
+        my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
+                    p->RIOHosts[p->RIONumHosts].Caddr);
+      }
+
+#ifdef TWO_ZERO
+    }  /* We have two variants with the opening brace, so to prevent */
+#else
+    }  /* Emacs from getting confused we have two closing braces too. */
+#endif
+    
+
+    /* Then look for the older PCI card.... : */
+#ifndef TWO_ZERO
+
+  /* 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))) {
+#else
+    for (i=0;i< RIO_NBOARDS;i++) {
+      if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, 
+                              PCI_DEVICE_ID_SPECIALIX_RIO, i,
+                              &pci_bus, &pci_fun)) break;
+#endif
+
+#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 = get_irq (pdev);
+      if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+      hp->Ivec |= 0x8000; /* Mark as non-sharable */
+      hp->CardP        = (struct DpRam *)
+      hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->Type  = RIO_PCI;
+      hp->Copy  = rio_pcicopy;
+      hp->Mode  = RIO_PCI_DEFAULT_MODE;
+      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 {
+        my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
+                    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
+#ifdef TWO_ZERO
+    }  /* We have two variants with the opening brace, so to prevent */
+#else
+    }  /* Emacs from getting confused we have two closing braces too. */
+#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->CardP = (struct DpRam *)
+    hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+    hp->Type = RIO_AT;
+    hp->Copy = rio_pcicopy;
+    hp->Mode = 0;
+
+    vpdp = get_VPD_PROM (hp);
+
+    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)
+      my_iounmap (hp->PaddrP, 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;}
+      if (request_irq (hp->Ivec, rio_interrupt, mode, "rio", (void *)i)) {
+        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);
+    }
+    /* 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) {
+    printk (KERN_INFO "rio: total of %d boards detected.\n", found);
+
+    if (misc_register(&rio_fw_device) < 0) {
+      printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
+      return -EIO;
+    }
+    rio_init_drivers ();
+  }
+
+  func_exit();
+  return found?0:-EIO;
+}
+
+
+#ifdef MODULE
+void cleanup_module(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, (void *)i);
+      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 (rio_termios_locked); 
+  kfree (rio_termios);
+  kfree (p->RIOPortp);
+  kfree (p->RIOHosts);
+  kfree (p);
+
+  func_exit();
+}
+#endif
+
+
+
+/*
+ * 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 (file)
index 0000000..5141355
--- /dev/null
@@ -0,0 +1,162 @@
+
+/*
+ *  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. 
+ * 
+ */
+
+#define RIO_NBOARDS        4
+#define RIO_PORTSPERBOARD 128
+#define RIO_NPORTS        (RIO_NBOARDS * RIO_PORTSPERBOARD)
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+
+#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_dprint(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_dprint(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_dprint(RIO_DEBUG_SPINLOCK, ("spinlock: %p %s:%d\n",\
+                                       sem, __FILE__, __LINE__));\
+        spin_lock(sem);\
+        } while (0)
+
+#define rio_spin_unlock(sem) do { \
+       rio_dprint(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
+
diff --git a/drivers/char/rio/rioboard.h b/drivers/char/rio/rioboard.h
new file mode 100644 (file)
index 0000000..cc6ac6a
--- /dev/null
@@ -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 (file)
index 0000000..7a06b0d
--- /dev/null
@@ -0,0 +1,1329 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.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/compatmac.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 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;
+
+       /* Linux doesn't allow you to disable interrupts during a
+          "copyin". (Crash when a pagefault occurs). */
+       /* disable(oldspl); */
+       
+       rio_dprint(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_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code Too Large!\n"));
+               p->RIOError.Error = HOST_FILE_TOO_LARGE;
+               /* restore(oldspl); */
+               return ENOMEM;
+       }
+
+       if ( p->RIOBooting ) {
+               rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code : BUSY BUSY BUSY!\n"));
+               p->RIOError.Error = BOOT_IN_PROGRESS;
+               /* restore(oldspl); */
+               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_dprint(RIO_DEBUG_BOOT, ("Bad data copy from user space\n"));
+               p->RIOError.Error = COPYIN_FAILED;
+               /* restore(oldspl); */
+               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); */
+       return 0;
+}
+
+
+/*
+** 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_dprint(RIO_DEBUG_BOOT, ("Attempt to boot host %d\n",host));
+               HostP = &p->RIOHosts[host];
+
+               if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) {
+                       rio_dprint(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_dprint(RIO_DEBUG_BOOT,  ("kernel virtual address for host is 0x%x\n", (int)Cad ) );
+               rio_dprint(RIO_DEBUG_BOOT,  ("kernel virtual address for download is 0x%x\n", (int)StartP ) );
+               rio_dprint(RIO_DEBUG_BOOT, ("host loadbase is 0x%x\n",p->RIOConf.HostLoadBase));
+               rio_dprint(RIO_DEBUG_BOOT,  ("size of download is 0x%x\n", rbp->Count ) );
+
+               if ( p->RIOConf.HostLoadBase < rbp->Count ) {
+                       rio_dprint(RIO_DEBUG_BOOT, ("Bin too large\n"));
+                       p->RIOError.Error = HOST_FILE_TOO_LARGE;
+                       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_dprint(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_dprint(RIO_DEBUG_BOOT, ("No system memory available\n"));
+                               p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
+                               return ENOMEM;
+                       }
+                       bzero(DownCode, rbp->Count);
+
+                       if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) {
+                               rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n"));
+                               p->RIOError.Error = COPYIN_FAILED;
+                               return EFAULT;
+                       }
+
+                       HostP->Copy( DownCode, StartP, rbp->Count );
+
+                       sysfree( DownCode, rbp->Count );
+               }
+               else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) {
+                       rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n"));
+                       p->RIOError.Error = COPYIN_FAILED;
+                       return EFAULT;
+               }
+
+               rio_dprint(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 compliment 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_dprint(RIO_DEBUG_BOOT, ("host loadbase is 0x%x\n",p->RIOConf.HostLoadBase));
+               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT,  ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
+                   HostP->Type, HostP->Mode, HostP->Ivec ) );
+
+               switch ( HostP->Type ) {
+                       case RIO_AT:
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"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_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n"));
+                               WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode);
+                               break;
+                       default:
+                               rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type));
+                               break;
+               }
+               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, ("parmmap 0x%x\n", RWORD(HostP->__ParmMapR)));
+                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, ("ParmMapP : %x\n", (int)ParmMapP));
+               ParmMapP = (PARM_MAP *)((unsigned long)Cad + 
+                                               (unsigned long)((RWORD((HostP->__ParmMapR))) & 0xFFFF)); 
+               rio_dprint(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_dprint(RIO_DEBUG_BOOT, ("RIO Mesg Run Fail %s\n", HostP->Name));
+                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, ("Waiting for init_done\n"));
+                       delay(HostP, HUNDRED_MS);
+               }
+               rio_dprint(RIO_DEBUG_BOOT, ("OK! init_done!\n"));
+
+               if (RWORD(ParmMapP->error) != E_NO_ERROR || 
+                                                       !RWORD(ParmMapP->init_done) ) {
+                       rio_dprint(RIO_DEBUG_BOOT, ("RIO Mesg Run Fail %s\n", HostP->Name));
+                       rio_dprint(RIO_DEBUG_BOOT, ("Timedout waiting for init_done\n"));
+                       HOST_DISABLE;
+               }
+
+               rio_dprint(RIO_DEBUG_BOOT, ("Got init_done\n"));
+
+               /*
+               ** It runs! It runs!
+               */
+               rio_dprint(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;
+               }
+
+               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;
+               }
+
+               /*
+               ** 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_dprint(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_dprint(RIO_DEBUG_BOOT, ("Done everything %x\n", HostP->Ivec));
+       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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, ("Boot block %d on Host %d Rup%d\n",sequence,HostP-p->RIOHosts,Rup));
+
+       if ( sequence >= p->RIONumBootPkts ) {
+               rio_dprint(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.
+*/
+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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, ("UniqNum is 0x%x\n",RtaUniq));
+
+        if ( ( RtaUniq == 0x00000000 ) || ( RtaUniq == 0xffffffff ) )
+       {
+           rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, ("RTA will be given IDs %d+%d\n",
+                   entry+1, entry2+1));
+               } else {
+                  rio_dprint(RIO_DEBUG_BOOT, ("RTA will be given ID %d\n",entry+1));
+               }
+               return TRUE;
+           }
+       }
+
+       rio_dprint(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_dprint(RIO_DEBUG_BOOT, ("Found previous tentative slots (%d+%d)\n",
+                        entry, entry2));
+                   else
+                       continue;
+               }
+               else
+                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, ("This RTA is units %d+%d from host %s\n",
+                        rta+1, MapP->ID2, p->RIOHosts[host].Name ));
+                   }
+                   else
+                       rio_dprint(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_dprint(RIO_DEBUG_BOOT, ("Look for RTA %x in RIOSavedTable\n",RtaUniq));
+           for ( rta=0; rta < TOTAL_MAP_ENTRIES; rta++ )
+           {
+               rio_dprint(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_dprint(RIO_DEBUG_BOOT, ("This RTA is from table entries %d+%d\n",
+                              rta, entry2));
+                   }
+                   else
+                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_BOOT, ("SysPort %d, Name %s\n",(int)MapP->SysPort,MapP->Name));
+               }
+               else
+               {
+                   rio_dprint(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_dprint(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_dprint(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 (file)
index 0000000..6f2e43d
--- /dev/null
@@ -0,0 +1,1144 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/errno.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/compatmac.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(HostP, MapP)
+struct Host *  HostP;
+struct Map *   MapP;
+{
+       struct CmdBlk *CmdBlkP;
+
+       rio_dprint(RIO_DEBUG_CMD, ("FOAD RTA\n"));
+
+       CmdBlkP = RIOGetCmdBlk();
+
+       if ( !CmdBlkP ) {
+               rio_dprint(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_dprint(RIO_DEBUG_CMD, ("FOAD RTA: Failed to queue foad command\n"));
+               return EIO;
+       }
+       return 0;
+}
+
+int
+RIOZombieRta(HostP, MapP)
+struct Host *  HostP;
+struct Map *   MapP;
+{
+       struct CmdBlk *CmdBlkP;
+
+       rio_dprint(RIO_DEBUG_CMD, ("ZOMBIE RTA\n"));
+
+       CmdBlkP = RIOGetCmdBlk();
+
+       if ( !CmdBlkP ) {
+               rio_dprint(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_dprint(RIO_DEBUG_CMD, ("ZOMBIE RTA: Failed to queue zombie command\n"));
+               return EIO;
+       }
+       return 0;
+}
+
+int
+RIOCommandRta(p, RtaUnique, func)
+struct rio_info *      p;
+uint RtaUnique;
+int (* func)( struct Host *HostP, struct Map *MapP );
+{
+       uint Host;
+
+       rio_dprint(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(p, arg)
+struct rio_info *      p;
+caddr_t arg;
+{
+       uint Host;
+
+       if ( copyin( (int)arg, (caddr_t)&IdRta, sizeof(IdRta) ) == COPYFAIL ) {
+               rio_dprint(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_dprint(RIO_DEBUG_CMD, ("IDENTIFY RTA\n"));
+
+                                               CmdBlkP = RIOGetCmdBlk();
+
+                                               if ( !CmdBlkP ) {
+                                                       rio_dprint(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_dprint(RIO_DEBUG_CMD, ("IDENTIFY RTA: Failed to queue command\n"));
+                                                       return EIO;
+                                               }
+                                               return 0;
+                                       }
+                               }
+                       }
+               }
+       } 
+       return ENOENT;
+}
+
+
+int
+RIOKillNeighbour(p, arg)
+struct rio_info *      p;
+caddr_t arg;
+{
+       uint Host;
+       uint ID;
+       struct Host *HostP;
+       struct CmdBlk *CmdBlkP;
+
+       rio_dprint(RIO_DEBUG_CMD, ("KILL HOST NEIGHBOUR\n"));
+
+       if ( copyin( (int)arg, (caddr_t)&KillUnit, 
+                                       sizeof(KillUnit) ) == COPYFAIL ) {
+               rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CMD, ("UFOAD: Failed queue command\n"));
+                                       return EIO;
+                               }
+                               return 0;
+                       }
+               }
+       }
+       RIOFreeCmdBlk( CmdBlkP );
+       return ENXIO;
+}
+
+int
+RIOSuspendBootRta(HostP, ID, Link)
+struct Host *HostP;
+int ID;
+int Link; 
+{
+       struct CmdBlk *CmdBlkP;
+
+       rio_dprint(RIO_DEBUG_CMD, ("SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link));
+
+       CmdBlkP = RIOGetCmdBlk();
+
+       if ( !CmdBlkP ) {
+               rio_dprint(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_dprint(RIO_DEBUG_CMD, ("SUSPEND BOOT ON RTA: Failed to queue iwait command\n"));
+               return EIO;
+       }
+       return 0;
+}
+
+int
+RIOFoadWakeup(p)
+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.
+*/
+int
+RIOCommandRup(p, Rup, HostP, PacketP)
+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;
+
+
+#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_dprint(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_dprint(RIO_DEBUG_CMD, ("OBSCURE ERROR!\n"));
+               rio_dprint(RIO_DEBUG_CMD, ("Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"));
+               rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: Host number %d, name ``%s''\n", 
+                                       HostP-p->RIOHosts, HostP->Name ));
+               rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: Rup number  0x%x\n", rup));
+
+               if ( Rup >= (ushort)MAX_RUP )
+                       rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: This is the RUP for RTA ``%s''\n",
+                                               HostP->Mapping[Rup].Name ));
+               else
+                       rio_dprint(RIO_DEBUG_CMD, ("CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", 'A' + Rup - MAX_RUP, HostP->Name ));
+
+               rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Destination 0x%x:0x%x\n",
+                                       PacketP->dest_unit, PacketP->dest_port ));
+               rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Source    0x%x:0x%x\n",
+                                       PacketP->src_unit, PacketP->src_port ));
+               rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Length    0x%x (%d)\n", PacketP->len,PacketP->len ));
+               rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Control  0x%x (%d)\n", PacketP->control, PacketP->control));
+               rio_dprint(RIO_DEBUG_CMD, ("PACKET information: Check      0x%x (%d)\n", PacketP->csum, PacketP->csum ));
+               rio_dprint(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 ];
+#if 0
+       ttyP = PortP->TtyP;
+#endif
+       rio_spin_lock_irqsave(&PortP->portSem, flags);
+       switch( RBYTE(PktCmdP->Command) ) {
+               case BREAK_RECEIVED:
+                       rio_dprint(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 */
+                       break;
+
+               case COMPLETE:
+                       rio_dprint(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_dprint(RIO_DEBUG_CMD, ("Memory dump cmd (0x%x) from addr 0x%x\n",
+                                               RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr)));
+                                       break;
+                               case READ_REGISTER :
+                                       rio_dprint(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_dprint(RIO_DEBUG_CMD, ("New status is 0x%x was 0x%x\n",
+                                        RBYTE(PktCmdP->PortStatus),PortP->PortState));
+                       if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) {
+                               rio_dprint(RIO_DEBUG_CMD, ("Mark status & wakeup\n"));
+                               PortP->PortState = RBYTE(PktCmdP->PortStatus);
+                               /* What should we do here ...
+                               wakeup( &PortP->PortState );
+                               */
+                       }
+                       else {
+                               rio_dprint(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_dprint(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_dprint(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(!(ttyP->t_cflag & CLOCAL) && 
+                                       ((PortP->State & (RIO_MOPEN|RIO_WOPEN))))
+                               {
+                       /*
+                       ** Is there a carrier?
+                       */
+                       if ( PortP->ModemState & MSVR1_CD )
+                       {
+                       /*
+                       ** Has carrier just appeared?
+                       */
+                       if (!(ttyP->t_state & CARR_ON))
+                       {
+                               rio_dprint(RIO_DEBUG_CMD, PortP,DBG_MODEM,"Carrier just came up.\n");
+                               ttyP->t_state |=CARR_ON;
+                               /*
+                               ** wakeup anyone in WOPEN
+                               */
+                               if ( ttyP->t_state & (ISOPEN|WOPEN) )
+                               wakeup((caddr_t)&ttyP->t_canq);
+#ifdef STATS
+                               PortP->Stat.ModemOnCnt++;
+#endif
+                       }
+                       }
+                       else
+                       {
+                       /*
+                       ** Has carrier just dropped?
+                       */
+                       if (ttyP->t_state & CARR_ON)
+                       {
+                               /*
+                               ** send SIGHUP to the process group
+                               */
+                               if ( ttyP->t_state & (ISOPEN|WOPEN) )
+                               {
+                               signal(ttyP->t_pgrp,SIGHUP);
+                               ttyflush(ttyP,(FREAD|FWRITE));
+                               }
+                               ttyP->t_state &= ~CARR_ON;
+                               wakeup( (caddr_t)&PortP->TxBufferOut );
+                               wakeup( (caddr_t)&PortP->TxBufferIn );
+                               rio_dprint(RIO_DEBUG_CMD, PortP,DBG_MODEM,"Carrier just went down.\n");
+#ifdef STATS
+                               PortP->Stat.ModemOffCnt++;
+#endif
+                       }
+                       }
+               }
+               }
+#endif
+                       }
+                       break;
+
+               default:
+                       rio_dprint(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);
+       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()
+{
+       struct CmdBlk *CmdBlkP;
+
+       CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk));
+       bzero(CmdBlkP, sizeof(struct CmdBlk));
+
+       return CmdBlkP;
+}
+
+/*
+** Return a block to the head of the free list.
+*/
+void
+RIOFreeCmdBlk(CmdBlkP)
+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(HostP, Rup, CmdBlkP)
+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
+
+       rio_dprint(RIO_DEBUG_CMD, ("RIOQueueCmdBlk(Host, Rup %d, 0x%x)\n", Rup, (int)CmdBlkP ));
+
+       if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) {
+               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CMD, ("RUP active - en-queing\n"));
+
+       if ( UnixRupP->CmdsWaitingP != NULL)
+               rio_dprint(RIO_DEBUG_CMD, ("Rup active - command waiting\n"));
+       if ( UnixRupP->CmdPendingP != NULL )
+               rio_dprint(RIO_DEBUG_CMD, ("Rup active - command pending\n"));
+       if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE )
+               rio_dprint(RIO_DEBUG_CMD, ("Rup active - command rup not ready\n"));
+
+       Base = &UnixRupP->CmdsWaitingP;
+
+       rio_dprint(RIO_DEBUG_CMD, ("First try to queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base));
+
+       while ( *Base ) {
+               rio_dprint(RIO_DEBUG_CMD, ("Command cmdblk 0x%x here\n",(int)(*Base)));
+               Base = &((*Base)->NextP);
+               rio_dprint(RIO_DEBUG_CMD, ("Now try to queue cmd cmdblk 0x%x at 0x%x\n",
+                      (int)CmdBlkP,(int)Base));
+       }
+
+       rio_dprint(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(p, HostP)
+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;
+
+                       /* rio_dprint(RIO_DEBUG_CMD, ("RIORupCmd( %d, %d )\n", HostP-p->RIOHosts, Rup )); */
+
+                       PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt));
+
+                       ShowPacket( DBG_CMD, PacketP );
+
+                       switch ( RBYTE(PacketP->dest_port) ) {
+                               case BOOT_RUP:
+                                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CMD, ("Unknown RUP %d\n", RBYTE(PacketP->dest_port)));
+                                       FreeMe = 1;
+                                       break;
+                       }
+
+                       if ( FreeMe ) {
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CMD, ("Free Boot %s Command Block '%x'\n", 
+                                               CmdBlkP->Packet.len & 0x80 ? "Command":"Data", 
+                                                       CmdBlkP->Packet.data[0] ));
+
+                       rio_dprint(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_dprint(RIO_DEBUG_CMD, ("Not ready to start command 0x%x\n",(int)CmdBlkP));
+                       }
+                       else {
+                               rio_dprint(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 );
+}
+
+
+/*
+** Return the length of the named string
+*/
+int
+RIOStrlen(Str)
+register char *Str;
+{
+       register int len = 0;
+
+       while ( *Str++ )
+               len++;
+       return len;
+}
+
+/*
+** compares s1 to s2 and return 0 if they match.
+*/
+int
+RIOStrCmp(s1, s2)
+register char *s1;
+register char *s2;
+{
+       while ( *s1 && *s2 && *s1==*s2 )
+               s1++, s2++;
+       return *s1-*s2;
+}
+
+/*
+** compares s1 to s2 for upto n bytes and return 0 if they match.
+*/
+int
+RIOStrnCmp(s1, s2, n)
+register char *s1;
+register char *s2;
+int n;
+{
+       while ( n && *s1 && *s2 && *s1==*s2 )
+               n--, s1++, s2++;
+       return n ? *s1!=*s2 : 0;
+}
+
+/*
+** copy up to 'len' bytes from 'from' to 'to'.
+*/
+void
+RIOStrNCpy(to, from, len)
+char *to;
+char *from;
+int len; 
+{
+       while ( len-- && (*to++ = *from++) )
+               ;
+       to[-1]='\0';
+}
+
+int
+RIOWFlushMark(iPortP, CmdBlkP)
+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(iPortP, CmdBlkP)
+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_dprint(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(iPortP, CmdBlkP)
+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_dprint(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(Flags, PacketP)
+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 (file)
index 0000000..27b4639
--- /dev/null
@@ -0,0 +1,1898 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/malloc.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/compatmac.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))
+
+#ifdef linux
+int copyin (int arg, caddr_t dp, int siz)
+{
+  int rv;
+
+  rio_dprint (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 < 0) return COPYFAIL;
+  else return rv;
+}
+
+
+int copyout (caddr_t dp, int arg, int siz)
+{
+  int rv;
+
+  rio_dprint (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 < 0) return COPYFAIL;
+  else return rv;
+}
+
+#else
+
+int
+copyin(arg, dp, siz)
+int arg;
+caddr_t dp;
+int siz; 
+{
+       if (rbounds ((unsigned long) arg) >= siz) {
+               bcopy ( arg, dp, siz );
+               return OK;
+       } else
+               return ( COPYFAIL );
+}
+
+int
+copyout (dp, arg, siz)
+caddr_t dp;
+int arg;
+int siz;
+{
+       if (wbounds ((unsigned long) arg) >=  siz ) {
+               bcopy ( dp, arg, siz );
+               return OK;
+       } else
+               return ( COPYFAIL );
+}
+#endif
+
+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;
+       
+       /* Confuse teh compiler to think that we've initialized these */
+       Host=0;
+       PortP = NULL;
+
+       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_FOAD_RTA\n"));
+                       return RIOCommandRta(p, (uint)arg, RIOFoadRta);
+
+               case RIO_ZOMBIE_RTA:
+                       rio_dprint(RIO_DEBUG_CTRL, ("RIO_ZOMBIE_RTA\n"));
+                       return RIOCommandRta(p, (uint)arg, RIOZombieRta);
+
+               case RIO_IDENTIFY_RTA:
+                       rio_dprint(RIO_DEBUG_CTRL, ("RIO_IDENTIFY_RTA\n"));
+                       return RIOIdentifyRta(p, arg);
+
+               case RIO_KILL_NEIGHBOUR:
+                       rio_dprint(RIO_DEBUG_CTRL, ("RIO_KILL_NEIGHBOUR\n"));
+                       return RIOKillNeighbour(p, arg);
+
+               case SPECIAL_RUP_CMD:
+                       {
+                               struct CmdBlk *CmdBlkP;
+
+                               rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD\n"));
+                               if (copyin((int)arg, (caddr_t)&SpecialRupCmd, 
+                                                       sizeof(SpecialRupCmd)) == COPYFAIL ) {
+                                       rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD copy failed\n"));
+                                       p->RIOError.Error = COPYIN_FAILED;
+                                       return EFAULT;
+                               }
+                               CmdBlkP = RIOGetCmdBlk();
+                               if ( !CmdBlkP ) {
+                                       rio_dprint(RIO_DEBUG_CTRL, ("SPECIAL_RUP_CMD GetCmdBlk failed\n"));
+                                       return ENXIO;
+                               }
+                               CmdBlkP->Packet = SpecialRupCmd.Packet;
+                               if ( SpecialRupCmd.Host >= p->RIONumHosts )
+                                       SpecialRupCmd.Host = 0;
+                                       rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_GET_TABLE copy failed\n"));
+                                       p->RIOError.Error = COPYOUT_FAILED;
+                                       return EFAULT;
+                               }
+
+                               {
+                                       int entry;
+                                       rio_dprint(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_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, (int)p->RIOConnectTable[entry].Flags ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.SysPort = 0x%x\n", entry, (int)p->RIOConnectTable[entry].SysPort ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
+                                               rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[4].Link = %x\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") );
+                               }
+                               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_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_TABLE\n"));
+
+                               if ( !su ) {
+                                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_GET_BINDINGS\n"));
+
+                               if ( !su )
+                               {
+                                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_PUT_BINDINGS\n"));
+
+                               if ( !su )
+                               {
+                                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_BIND_RTA\n"));
+
+                                       if ( !su ) {
+                                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("Adding Rta %x to p->RIOBindTab\n",
+                                                       (int) arg));
+                                       }
+                                       else {
+                                               rio_dprint(RIO_DEBUG_CTRL, ("p->RIOBindTab full! - Rta %x not added\n",
+                                                       (int) arg));
+                                               return 1;
+                                       }
+                                       return 0;
+                               }
+
+                       case RIO_RESUME :
+                               rio_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME\n"));
+                               port = (uint) arg;
+                               if ((port < 0) || (port > 511)) {
+                                       rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_RESUME failed\n"));
+                                       rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+                                       return EBUSY;
+                               }
+                               else {
+                                       rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_ASSIGN_RTA\n"));
+                               if ( !su ) {
+                                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_CHANGE_NAME\n"));
+                               if ( !su ) {
+                                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_DELETE_RTA\n"));
+                               if ( !su ) {
+                                       rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("Get module type for port %d\n", port));
+                               if ( port < 0 || port > 511 )
+                               {
+                                       rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("Setup ports\n"));
+                               if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) 
+                                               == COPYFAIL ) {
+                                        p->RIOError.Error = COPYIN_FAILED;
+                                        rio_dprint(RIO_DEBUG_CTRL, ("EFAULT"));
+                                        return EFAULT;
+                               }
+                               if ( PortSetup.From > PortSetup.To || 
+                                                               PortSetup.To >= RIO_PORTS ) {
+                                        p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+                                        rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("EINVAL"));
+                                        return EINVAL;
+                               }
+                               if ( !p->RIOPortp ) {
+                                        cprintf("No p->RIOPortp array!\n");
+                                        rio_dprint(RIO_DEBUG_CTRL, ("No p->RIOPortp array!\n"));
+                                        return EIO;
+                               }
+                               rio_dprint(RIO_DEBUG_CTRL, ("entering loop (%d %d)!\n", PortSetup.From, PortSetup.To));
+                               for (loop=PortSetup.From; loop<=PortSetup.To; loop++) {
+                               rio_dprint(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 setings 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_dprint(RIO_DEBUG_CTRL, ("after loop (%d)!\n", loop));
+                               rio_dprint(RIO_DEBUG_CTRL,  ("Retval:%x\n", retval ) );
+                               return retval;
+
+                       case RIO_GET_PORT_SETUP :
+                               rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_READ_LEVELS\n"));
+                                        for ( num=0; RIODbInf[num].Flag; num++ ) ;
+                                        rio_dprint(RIO_DEBUG_CTRL, ("%d levels to copy\n",num));
+                                        if (copyout((caddr_t)RIODbInf,(int)arg,
+                                               sizeof(struct DbInf)*(num+1))==COPYFAIL) {
+                                               rio_dprint(RIO_DEBUG_CTRL, ("ReadLevels Copy failed\n"));
+                                               p->RIOError.Error = COPYOUT_FAILED;
+                                               return EFAULT;
+                                        }
+                                        rio_dprint(RIO_DEBUG_CTRL, ("%d levels to copied\n",num));
+                                        return retval;
+                               }
+#endif
+
+                        case RIO_READ_CONFIG:
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_START_POLLER\n"));
+                               return EINVAL;
+
+                       case RIO_STOP_POLLER:
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("Set global debug to 0x%x set wait to 0x%x\n",
+                                                       p->rio_debug,p->RIODebugWait));
+                                       }
+                                       else {
+                                               rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_SETDEBUG 0x%x\n",
+                                                               p->RIOPortp[DebugCtrl.SysPort]->Debug));
+                               }
+                               else {
+                                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL,  ("RIO_VERSID\n") );
+                               if ( copyout(   (caddr_t)RIOVersid(),
+                                               (int)arg,
+                                               sizeof(struct rioVersion) ) == COPYFAIL )
+                               {
+                                        rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_NUM_HOSTS\n"));
+                               if (copyout((caddr_t)&p->RIONumHosts, (int)arg, 
+                                                       sizeof(p->RIONumHosts) )==COPYFAIL ) {
+                                        rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_FOAD %d\n", (int)arg));
+                               if ( !su ) {
+                                        rio_dprint(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
+                                       
+                                       p->RIOPortp[loop]->portSem = SPIN_LOCK_UNLOCKED;
+                                       p->RIOPortp[loop]->InUse = NOT_INUSE;
+                               }
+
+                               p->RIOSystemUp = 0;
+                               return retval;
+
+                       case RIO_DOWNLOAD:
+                               rio_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD\n"));
+                               if ( !su ) {
+                                        rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_DOWNLOAD: Copy in from user space failed\n"));
+                                        p->RIOError.Error = COPYIN_FAILED;
+                                        return EFAULT;
+                               }
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, (
+                                                       "RIO_HOST_REQ: Copy in from user space failed\n"));
+                                               p->RIOError.Error = COPYIN_FAILED;
+                                               return EFAULT;
+                                       }
+                                       /*
+                                       ** Fetch the parmmap
+                                       */
+                                       rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_PARMS: Copy out to user space failed\n"));
+                                               return EFAULT;
+                                       }
+                               }
+                               return retval;
+
+                       case RIO_HOST_REQ:
+                               rio_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ\n"));
+                               if (copyin((int)arg, (caddr_t)&HostReq, 
+                                                       sizeof(HostReq) )==COPYFAIL ) {
+                                        rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ: Illegal host number %d\n",
+                                                       HostReq.HostNum));
+                                        return ENXIO;
+                               }
+                               rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_REQ: Bad copy to user space\n"));
+                                       return EFAULT;
+                               }
+                               return retval;
+
+                        case RIO_HOST_DPRAM:
+                               rio_dprint(RIO_DEBUG_CTRL, ("Request for DPRAM\n"));
+                               if ( copyin( (int)arg, (caddr_t)&HostDpRam, 
+                                                               sizeof(HostDpRam) )==COPYFAIL ) {
+                                       rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Illegal host number %d\n",
+                                                                               HostDpRam.HostNum));
+                                       return ENXIO;
+                               }
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_DPRAM: Bad copy to user space\n"));
+                                        return EFAULT;
+                               }
+                               return retval;
+
+                        case RIO_SET_BUSY:
+                               rio_dprint(RIO_DEBUG_CTRL, ("RIO_SET_BUSY\n"));
+                               if ( (int)arg < 0 || (int)arg > 511 ) {
+                                        rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT\n"));
+                               if ( copyin((int)arg, (caddr_t)&PortReq, 
+                                       sizeof(PortReq) )==COPYFAIL ) {
+                                       rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_PORT: Illegal port number %d\n",
+                                                                                       PortReq.SysPort));
+                                        p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+                                        return ENXIO;
+                               }
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP\n"));
+                               if (copyin((int)arg, (caddr_t)&RupReq, 
+                                               sizeof(RupReq) )==COPYFAIL ) {
+                                        rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_RUP: Host %d not running\n",
+                                                       RupReq.HostNum));
+                                        p->RIOError.Error = HOST_NOT_RUNNING;
+                                        return EIO;
+                               }
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB\n"));
+                               if (copyin((int)arg, (caddr_t)&LpbReq, 
+                                       sizeof(LpbReq) )==COPYFAIL ) {
+                                        rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_HOST_LPB: Host %d not running\n",
+                                               LpbReq.Host));
+                                        p->RIOError.Error = HOST_NOT_RUNNING;
+                                        return EIO;
+                               }
+                               rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("Baud rate mapping\n"));
+                               port = (uint) arg;
+                               if ( port < 0 || port > 511 ) {
+                                        rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("RIO_STREAM_INFO\n"));
+                               return EINVAL;
+
+                       case RIO_SEND_PACKET:
+                               rio_dprint(RIO_DEBUG_CTRL, ("RIO_SEND_PACKET\n"));
+                               if ( copyin( (int)arg, (caddr_t)&SendPack,
+                                                                       sizeof(SendPack) )==COPYFAIL ) {
+                                        rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("Makedev printer 0x%x is 0x%x\n",port, (int)arg ));
+                                                       return (int)arg;
+                                       }
+                                       rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("Minor for device 0x%x: modem %d\n", dv, mino));
+                                               arg = (caddr_t)(mino | RIO_DEV_MODEM);
+                                       }
+                                       else {
+                                               rio_dprint(RIO_DEBUG_CTRL, ("Minor for device 0x%x: direct %d\n", dv, mino));
+                                               arg = (caddr_t)(mino | RIO_DEV_DIRECT);
+                                       }
+                                       return (int)arg;
+                               }
+       }
+       rio_dprint(RIO_DEBUG_CTRL, ("INVALID DAEMON IOCTL 0x%x\n",cmd));
+       p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+       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_dprint(RIO_DEBUG_CTRL, ("Preemptive command to deleted RTA ignored\n"));
+               return RIO_FAIL;
+       }
+
+       if (((int)((char)PortP->InUse) == -1) || ! (CmdBlkP = RIOGetCmdBlk()) ) {
+               rio_dprint(RIO_DEBUG_CTRL, ("Cannot allocate command block for command %d on port %d\n",
+                      Cmd, PortP->PortNum));
+               return RIO_FAIL;
+       }
+
+       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP));
+                       break;
+               case READ_REGISTER:
+                       rio_dprint(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_dprint(RIO_DEBUG_CTRL, ("Queue RESUME command blk 0x%x\n",(int)CmdBlkP));
+                       break;
+               case RFLUSH:
+                       rio_dprint(RIO_DEBUG_CTRL, ("Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP));
+                       CmdBlkP->PostFuncP = RIORFlushEnable;
+                       break;
+               case SUSPEND:
+                       rio_dprint(RIO_DEBUG_CTRL, ("Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP));
+                       break;
+
+               case MGET :
+                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_CTRL, ("Trashed WFLUSH, WflushFlag about to wrap!"));
+                               RIOFreeCmdBlk(CmdBlkP);
+                               return(RIO_FAIL);
+                       } else {
+                               rio_dprint(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 (file)
index 0000000..9a429e1
--- /dev/null
@@ -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          : 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
+
+#ifdef SCCS_LABELS
+static char *_riodrvr_h_sccs_ = "@(#)riodrvr.h 1.3";
+#endif
+
+#define MEMDUMP_SIZE   32
+#define HZ                             100
+#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 (file)
index 0000000..11bc3e5
--- /dev/null
@@ -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 - INTERUPT / 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 (file)
index 0000000..72e8632
--- /dev/null
@@ -0,0 +1,1652 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.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/compatmac.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"
+
+
+#undef bcopy
+#define bcopy rio_pcicopy
+
+int
+RIOPCIinit(struct rio_info *p, int Mode);
+
+
+#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_dprint(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 accomodate another host
+       */
+       if ( p->RIONumHosts >= RIO_HOSTS )
+       {
+               p->RIOFailed++;
+               return;
+       }
+
+       if ( info->bus & ISA_BUS )
+       {
+               rio_dprint(RIO_DEBUG_INIT,  ("initialising card %d (ISA)\n", p->RIONumHosts) );
+               RIOISAinit(p, p->mode);
+       }
+       else
+       {
+               rio_dprint(RIO_DEBUG_INIT,  ("initialising card %d (PCI)\n", p->RIONumHosts) );
+               RIOPCIinit(p, RIO_PCI_DEFAULT_MODE);
+       }
+
+       rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_INIT, ("RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum));
+
+       p->RIONumHosts++;
+       rio_dprint(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_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Ivec is %x\n",Ivec);
+
+               switch ( Ivec & McaIrqMask )
+               {
+               case McaIrq9:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ9\n");
+               break;
+               case McaIrq3:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ3\n");
+               break;
+               case McaIrq4:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ4\n");
+               break;
+               case McaIrq7:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ7\n");
+               break;
+               case McaIrq10:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ10\n");
+               break;
+               case McaIrq11:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ11\n");
+               break;
+               case McaIrq12:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ12\n");
+               break;
+               case McaIrq15:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"IRQ15\n");
+               break;
+               }
+
+               /*
+               ** If the card enable bit isn't set, then set it!
+               */
+               if ((Ivec & McaCardEnable) != McaCardEnable )
+               {
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"McaCardEnable not set - setting!\n");
+               outb(McaIrqEnable,Ivec|McaCardEnable);
+               }
+               else
+               {
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"McaCardEnable already set\n");
+               }
+
+               /*
+               ** Convert the IRQ enable mask into something useful
+               */
+               Ivec = RIOMcaToIvec[Ivec & McaIrqMask];
+
+               /*
+               ** Find the physical address
+               */
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"inb(McaMemory) is %x\n",inb(McaMemory));
+               Paddr = McaAddress(inb(McaMemory));
+
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(RIO_DEBUG_INIT, ("Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE,Paddr);
+                       continue;
+               }
+
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Board has passed test\n");
+                       rio_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(RIO_DEBUG_INIT, NULL,DBG_FAIL,"TEST FAILED\n");
+                       RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr );
+               }
+               }
+               else
+               {
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Slot %d - Paddr zero!\n",SlotNumber);
+               }
+       }
+       else
+       {
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Slot %d NOT RIO\n",SlotNumber);
+       }
+       }
+       /*
+       ** Now we have checked all the slots, turn off the MCA slot selector
+       */
+       outb(McaSlotSelect,0);
+       rio_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"RIOEISAinit() - already done, return.\n");
+               return(0);
+       }
+
+       EISADone++;
+
+       rio_dprint(RIO_DEBUG_INIT, NULL,DBG_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);
+
+       /* rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT, "Check EISA slot %d, ID=%x\n",EisaSlot,Ident); */
+
+       if ( Ident == RIO_EISA_IDENT )
+       {
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Found Specialix product\n");
+
+               if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
+               {
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"Not Specialix RIO - Product number %x\n",
+                                               INBZ(EisaSlot,EISA_PRODUCT_NUMBER));
+               continue;  /* next slot */
+               }
+               /*
+               ** Its a Specialix RIO!
+               */
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 3\n");
+               break;
+               case EISA_IRQ_4:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 4\n");
+               break;
+               case EISA_IRQ_5:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 5\n");
+               break;
+               case EISA_IRQ_6:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 6\n");
+               break;
+               case EISA_IRQ_7:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 7\n");
+               break;
+               case EISA_IRQ_9:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 9\n");
+               break;
+               case EISA_IRQ_10:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 10\n");
+               break;
+               case EISA_IRQ_11:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 11\n");
+               break;
+               case EISA_IRQ_12:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 12\n");
+               break;
+               case EISA_IRQ_14:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 14\n");
+               break;
+               case EISA_IRQ_15:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA IRQ 15\n");
+               break;
+               case EISA_POLLED:
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_INIT,"EISA POLLED\n");
+               break;
+               default:
+               rio_dprint(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_dprint(RIO_DEBUG_INIT, NULL, DBG_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_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT,"EISA card has Ivec %d Addr %x\n",Ivec,Paddr);
+
+               if ( Paddr == 0 )
+               {
+               rio_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT | DBG_FAIL,
+                "Board in slot %d configured for address zero!\n", EisaSlot);
+               continue;
+               }
+
+               /*
+               ** Tell the memory mapper that we want to talk to it
+               */
+               rio_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT,"About to map EISA card \n");
+
+               if (RIOMapin( Paddr, RIO_EISA_MEM_SIZE, &Caddr) == -1) {
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_FAIL,"Couldn't map %d bytes at %x\n",
+                                                       RIO_EISA_MEM_SIZE,Paddr);
+               continue;
+               }
+
+               rio_dprint(RIO_DEBUG_INIT, NULL, DBG_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_dprint(RIO_DEBUG_INIT, NULL, DBG_INIT,"Board has passed test\n");
+               rio_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(RIO_DEBUG_INIT, NULL,DBG_FAIL,"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_dprint(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_dprint(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_dprint(RIO_DEBUG_INIT,  ("Goofed up slot\n") );     /* what! */
+                               slot++;
+                               continue;
+                       }
+
+                       p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
+                       Ivec = (read_config(0,slot,0x3c) & 0xff);
+
+                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_INIT, ("Board has passed test\n"));
+                               rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_INIT, NULL,DBG_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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_INIT, ("RIO-init: RIOScrub band %d, op %d failed\n", 
+                                                       bank, op));
+                               return RIO_FAIL;
+                       }
+               }
+       }
+
+       rio_dprint(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.
+*/
+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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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.
+*/
+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.
+*/
+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
+               }
+       }
+}
+
+#if 0
+/*
+** 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_dprint(RIO_DEBUG_INIT, ("RIO-init: No memory for port structures\n"));
+               p->RIOFailed++;
+               return;
+       } 
+       bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS );
+       rio_dprint(RIO_DEBUG_INIT,  ("RIO-init: allocated and cleared memory for port structs\n") );
+       rio_dprint(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_dprint(RIO_DEBUG_INIT, ("RIO-init: No memory for host structures\n"));
+               p->RIOFailed++;
+               return;
+       }
+       bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS);
+       rio_dprint(RIO_DEBUG_INIT,  ("RIO-init: allocated and cleared memory for host structs\n"));
+       rio_dprint(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++ ) {
+               p->RIOHosts[host].HostLock = SPIN_LOCK_UNLOCKED; /* Let the first guy takes it */
+               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);
+                       }
+                       HostP->UnixRups[rup].RupLock = -1;
+               }
+       }
+}
+#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"
+
+int
+RIOReport(p)
+struct rio_info *      p;
+{
+       char *  RIORelease = RIO_RELEASE;
+       char *  RIORelID = RELEASE_ID;
+       int             host;
+
+       rio_dprint(RIO_DEBUG_INIT, ("RIO : Release: %s ID: %s\n", RIORelease, RIORelID));
+
+       if ( p->RIONumHosts==0 ) {
+               rio_dprint(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_dprint(RIO_DEBUG_INIT, ("AT BUS : found the card at 0x%x\n", HostP->PaddrP));
+               }
+       }
+       return 0;
+}
+
+/*
+** This function returns release/version information as used by ioctl() calls
+** It returns a MAX_VERSION_LEN byte string, null terminated.
+*/
+char *
+OLD_RIOVersid( void )
+{
+       static char     Info[MAX_VERSION_LEN];
+       char *  RIORelease = RIO_RELEASE;
+       char *  cp;
+       int             ct = 0;
+
+       for ( ct=0; RIORelease[ct] && ct<MAX_VERSION_LEN; ct++ )
+               Info[ct] = RIORelease[ct];
+       if ( ct>=MAX_VERSION_LEN ) {
+               Info[MAX_VERSION_LEN-1] = '\0';
+               return Info;
+       }
+       Info[ct++]=' ';
+       if ( ct>=MAX_VERSION_LEN ) {
+               Info[MAX_VERSION_LEN-1] = '\0';
+               return Info;
+       }
+
+       cp="";  /* Fill the RCS Id here */
+
+       while ( *cp && ct<MAX_VERSION_LEN )
+               Info[ct++] = *cp++;
+       if ( ct<MAX_VERSION_LEN-1 )
+               Info[ct] = '\0';
+       Info[MAX_VERSION_LEN-1] = '\0';
+       return Info;
+}
+
+
+static struct rioVersion       stVersion;
+
+struct rioVersion *
+RIOVersid(void)
+{
+    strncpy(stVersion.version, "RIO driver for linux V1.0", 255);
+    strncpy(stVersion.buildDate, __DATE__, 255);
+
+    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_dprint(RIO_DEBUG_INIT,  ("RIOHostReset: type 0x%x", Type ) );
+       switch ( Type ) {
+               case RIO_AT:
+                       rio_dprint(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_dprint(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_dprint(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_dprint(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 (file)
index 0000000..e926098
--- /dev/null
@@ -0,0 +1,1112 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/malloc.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/compatmac.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"
+
+
+
+
+/*
+** riopoll is called every clock tick. Once the /dev/rio device has been
+** opened, and polldistributed( ) has been called, this routine is called
+** every clock tick *by every cpu*. The 'interesting' piece of code that
+** manipulates 'RIONumCpus' and 'RIOCpuCountdown' is used to fair-share
+** the work between the CPUs. If there are 'N' cpus, then each poll time
+** we increment a counter, modulo 'N-1'. When this counter is 0, we call
+** the interrupt handler. This has the effect that polls are serviced
+** by processor 'N', 'N-1', 'N-2', ... '0', round and round. Neat.
+*/
+void
+riopoll(p)
+struct rio_info *      p;
+{
+       int   host;
+
+       /*
+       ** Here's the deal. We try to fair share as much as possible amongst
+       ** all the processors that are available. Since each processor 
+       ** should generate HZ ticks per second and since we only need HZ ticks
+       ** in total for proper operation we simply attempt to cycle round each
+       ** processor in turn, using RIOCpuCountdown to decide whether to call
+       ** the interrupt routine. ( In fact the count zeroes when it reaches
+       ** one less than the total number of processors - so e.g. on a two
+       ** processor system RIOService will get called 2*HZ times per second. )
+       ** this_cpu (cur_cpu()) tells us the number of the current processor
+       ** as follows:
+       **
+       **              0 - default CPU
+       **              1 - first extra CPU
+       **              2 - second extra CPU
+       **              etc.
+       */
+
+       /*
+       ** okay, we've got a cpu that hasn't had a go recently 
+       ** - lets check to see what needs doing.
+       */
+       for ( host=0; host<p->RIONumHosts; host++ ) {
+               struct Host *HostP = &p->RIOHosts[host];
+
+               rio_spin_lock( &HostP->HostLock );
+
+               if ( ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) ||
+                    HostP->InIntr ) {
+                       rio_spin_unlock (&HostP->HostLock); 
+                       continue;
+               }
+
+               if ( RWORD( HostP->ParmMapP->rup_intr ) ||
+                        RWORD( HostP->ParmMapP->rx_intr  ) ||
+                        RWORD( HostP->ParmMapP->tx_intr  ) ) {
+                       HostP->InIntr = 1;
+
+#ifdef FUTURE_RELEASE
+                       if( HostP->Type == RIO_EISA )
+                               INBZ( HostP->Slot, EISA_INTERRUPT_RESET );
+                       else
+#endif
+                               WBYTE( HostP->ResetInt , 0xff );
+
+                       rio_spin_lock(&HostP->HostLock); 
+
+                       p->_RIO_Polled++;
+                       RIOServiceHost(p, HostP, 'p' );
+                       rio_spin_lock( &HostP->HostLock); 
+                       HostP->InIntr = 0;
+                       rio_spin_unlock (&HostP->HostLock);
+               }
+       }
+       rio_spin_unlock (&p->RIOIntrSem); 
+}
+
+
+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_dprint (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_dprint (RIO_DEBUG_INTR, ("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_dprint (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_dprint (RIO_DEBUG_INTR, ("(%d/%d)\n",
+               PortP->gs.wakeup_chars, PortP->gs.xmit_cnt)); 
+    wake_up_interruptible(&PortP->gs.tty->write_wait);
+  }
+
+}
+
+
+/*
+** When a real-life interrupt comes in here, we try to find out
+** which host card it belongs to, and then service only that host
+** Notice the cunning way that, once we've found a candidate, we
+** continue just in case we are sharing interrupts.
+*/
+void
+riointr(p)
+struct rio_info *      p;
+{
+       int host;
+
+       for ( host=0; host<p->RIONumHosts; host++ ) {
+               struct Host *HostP = &p->RIOHosts[host];
+
+               rio_dprint(RIO_DEBUG_INTR,  ("riointr() doing host %d type %d\n", host, HostP->Type ) );
+
+               switch( HostP->Type ) {
+                       case RIO_AT:
+                       case RIO_MCA:
+                       case RIO_PCI:
+                               rio_spin_lock(&HostP->HostLock);
+                               WBYTE(HostP->ResetInt , 0xff);
+                               if ( !HostP->InIntr ) {
+                                       HostP->InIntr = 1;
+                                       rio_spin_unlock (&HostP->HostLock);
+                                       p->_RIO_Interrupted++;
+                                       RIOServiceHost(p, HostP, 'i');
+                                       rio_spin_lock(&HostP->HostLock);
+                                       HostP->InIntr = 0;
+                               }
+                               rio_spin_unlock(&HostP->HostLock); 
+                               break;
+#ifdef FUTURE_RELEASE
+               case RIO_EISA:
+                       if ( ivec == HostP->Ivec )
+                       {
+                               OldSpl = LOCKB( &HostP->HostLock );
+                               INBZ( HostP->Slot, EISA_INTERRUPT_RESET );
+                               if ( !HostP->InIntr )
+                               {
+                                       HostP->InIntr = 1;
+                                       UNLOCKB( &HostP->HostLock, OldSpl );
+                                       if ( this_cpu < RIO_CPU_LIMIT )
+                                       {
+                                               int intrSpl = LOCKB( &RIOIntrLock );
+                                               UNLOCKB( &RIOIntrLock, intrSpl );
+                                       }
+                                               p->_RIO_Interrupted++;
+                                       RIOServiceHost( HostP, 'i' );
+                                       OldSpl = LOCKB( &HostP->HostLock );
+                                       HostP->InIntr = 0;
+                               }
+                               UNLOCKB( &HostP->HostLock, OldSpl );
+                               done++;
+                       }
+                       break;
+#endif
+               }
+
+               HostP->IntSrvDone++;
+       }
+
+#ifdef FUTURE_RELEASE
+       if ( !done )
+       {
+               cmn_err( CE_WARN, "RIO: Interrupt received with vector 0x%x\n", ivec );
+               cmn_err( CE_CONT, "      Valid vectors are:\n");
+               for ( host=0; host<RIONumHosts; host++ )
+               {
+                       switch( RIOHosts[host].Type )
+                       {
+                               case RIO_AT:
+                               case RIO_MCA:
+                               case RIO_EISA:
+                                               cmn_err( CE_CONT, "0x%x ", RIOHosts[host].Ivec );
+                                               break;
+                               case RIO_PCI:
+                                               cmn_err( CE_CONT, "0x%x ", get_intr_arg( RIOHosts[host].PciDevInfo.busnum, IDIST_PCI_IRQ( RIOHosts[host].PciDevInfo.slotnum, RIOHosts[host].PciDevInfo.funcnum ) ));
+                                               break;
+                       }
+               }
+               cmn_err( CE_CONT, "\n" );
+       }
+#endif
+}
+
+/*
+** 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_dprint(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_dprint(RIO_DEBUG_INTR, ("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_dprint(RIO_DEBUG_INTR, ("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_dprint(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_dprint(RIO_DEBUG_INTR, ("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_dprint (RIO_DEBUG_INTR, ("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_dprint (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_dprint (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_dprint(RIO_DEBUG_INTR, ("Want to WFLUSH mark this port\n"));
+
+         if ( PortP->InUse )
+           rio_dprint(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_dprint(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_dprint(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.
+*/
+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_dprint (RIO_DEBUG_INTR, ("RIOReceive: tty is null. \n"));
+    return;
+  }
+
+  if (PortP->State & RIO_THROTTLE_RX) {
+    rio_dprint (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_dprint(RIO_DEBUG_INTR, ("RIO: unexpected command packet received on PHB\n"));
+           /*      rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */
+           rio_dprint(RIO_DEBUG_INTR, (" dest_unit = %d\n", PacketP->dest_unit));
+           rio_dprint(RIO_DEBUG_INTR, (" dest_port = %d\n", PacketP->dest_port));
+           rio_dprint(RIO_DEBUG_INTR, (" src_unit  = %d\n", PacketP->src_unit));
+           rio_dprint(RIO_DEBUG_INTR, (" src_port  = %d\n", PacketP->src_port));
+           rio_dprint(RIO_DEBUG_INTR, (" len      = %d\n", PacketP->len));
+           rio_dprint(RIO_DEBUG_INTR, (" control   = %d\n", PacketP->control));
+           rio_dprint(RIO_DEBUG_INTR, (" csum     = %d\n", PacketP->csum));
+           rio_dprint(RIO_DEBUG_INTR, ("        data bytes: "));
+           for ( DataCnt=0; DataCnt<PKT_MAX_DATA_LEN; DataCnt++ )
+             rio_dprint(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(PacketP->len & PKT_LEN_MASK,
+                          TTY_FLIPBUF_SIZE - TtyP->flip.count);
+         rio_dprint(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_dprint ( 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_dprint(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_dprint(RIO_DEBUG_INTR, ("RIO: NULL or BAD PhbP on sys port %d in proc routine\n",
+                                                       SysPort));
+               rio_dprint(RIO_DEBUG_INTR, ("    PortP = 0x%x\n",PortP));
+               rio_dprint(RIO_DEBUG_INTR, ("    PortP->PhbP = 0x%x\n",PortP->PhbP));
+               rio_dprint(RIO_DEBUG_INTR, ("    PortP->Caddr = 0x%x\n",PortP->PhbP));
+               rio_dprint(RIO_DEBUG_INTR, ("    PortP->HostPort = 0x%x\n",PortP->HostPort));
+               return 0;
+       }
+
+       switch(cmd) {
+               case T_WFLUSH:
+                       rio_dprint(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_dprint(RIO_DEBUG_INTR, ("WFLUSH on deleted RTA\n"));
+                               }
+                               else {
+                                       if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) {
+                                               rio_dprint(RIO_DEBUG_INTR, ("T_WFLUSH Command failed\n"));
+                                       }
+                                       else
+                                               rio_dprint(RIO_DEBUG_INTR, ("T_WFLUSH Command\n"));
+                               }
+                               /*
+                               ** WFLUSH operation - flush the data!
+                               */
+                               PortP->TxBufferIn = PortP->TxBufferOut = 0;
+                       }
+                       else {
+                               rio_dprint(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_dprint(RIO_DEBUG_INTR, ("T_RESUME\n"));
+                       /*
+                       ** send pre-emptive resume packet
+                       */
+                       if ( PortP->State & RIO_DELETED ) {
+                               rio_dprint(RIO_DEBUG_INTR, ("RESUME on deleted RTA\n"));
+                       }
+                       else {
+                               if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) {
+                                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_INTR, ("T_SUSPEND\n"));
+                       /*
+                       ** send a suspend pre-emptive packet.
+                       */
+                       if ( PortP->State & RIO_DELETED ) {
+                               rio_dprint(RIO_DEBUG_INTR, ("SUSPEND deleted RTA\n"));
+                       }
+                       else {
+                               if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) {
+                                       rio_dprint(RIO_DEBUG_INTR, ("T_SUSPEND Command failed\n"));
+                               }
+                       }
+                       /*
+                       ** done!
+                       */
+                       break;
+       
+               case T_BLOCK:
+                       rio_dprint(RIO_DEBUG_INTR, ("T_BLOCK\n"));
+                       break;
+       
+               case T_RFLUSH:
+                       rio_dprint(RIO_DEBUG_INTR, ("T_RFLUSH\n"));
+                       if ( PortP->State & RIO_DELETED ) {
+                               rio_dprint(RIO_DEBUG_INTR, ("RFLUSH on deleted RTA\n"));
+                               PortP->RxDataStart = 0;
+                       }
+                       else {
+                               if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) {
+                                       rio_dprint(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_dprint(RIO_DEBUG_INTR, ("Set receive handshake bit\n"));
+                                       PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET;
+                               }
+                       }
+                       break;
+                       /* FALLTHROUGH */
+               case T_UNBLOCK:
+                       rio_dprint(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_dprint(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_dprint(RIO_DEBUG_INTR, ("BREAK on deleted RTA\n"));
+                       }
+                       else {
+                               if (RIOShortCommand(PortP,SBREAK,2,
+                                                               p->RIOConf.BreakInterval)==RIO_FAIL) {
+                                       rio_dprint(RIO_DEBUG_INTR, ("SBREAK RIOShortCommand failed\n"));
+                               }
+                       }
+       
+                       /*
+                       ** done!
+                       */
+                       break;
+       
+               case T_INPUT:
+                       rio_dprint(RIO_DEBUG_INTR, ("Proc T_INPUT called - I don't know what to do!\n"));
+                       break;
+               case T_PARM:
+                       rio_dprint(RIO_DEBUG_INTR, ("Proc T_PARM called - I don't know what to do!\n"));
+                       break;
+       
+               case T_SWTCH:
+                       rio_dprint(RIO_DEBUG_INTR, ("Proc T_SWTCH called - I don't know what to do!\n"));
+                       break;
+       
+               default:
+                       rio_dprint(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 (file)
index 0000000..c3d6797
--- /dev/null
@@ -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 (file)
index 0000000..0e0cdac
--- /dev/null
@@ -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 (file)
index 0000000..550e2c1
--- /dev/null
@@ -0,0 +1,727 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/malloc.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/compatmac.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;
+
+       TtyP = PortP->gs.tty;
+
+       rio_dprint(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_dprint (RIO_DEBUG_PARAM, ("Can't call rioparam with null tty.\n"));
+         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_dprint(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_dprint(RIO_DEBUG_PARAM, ("Port IN_USE for pre-emptive command\n"));
+               }
+
+               if ( !res ) {
+                       rio_dprint(RIO_DEBUG_PARAM, ("Port has no space on transmit queue\n"));
+               }
+
+               if ( SleepFlag != OK_TO_SLEEP ) {
+                       rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+                       return RIO_FAIL;
+               }
+
+               rio_dprint(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_dprint(RIO_DEBUG_PARAM, ("wait for can_add_transmit broken by signal\n"));
+                       rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+                       pseterr(EINTR);
+                       return RIO_FAIL;
+               }
+               if ( PortP->State & RIO_DELETED ) {
+                       rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+                       return RIO_SUCCESS;
+               }
+       }
+
+       if (!res) {
+               rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+               return RIO_FAIL;
+       }
+
+       rio_dprint(RIO_DEBUG_PARAM, ("can_add_transmit() returns %x\n",res));
+       rio_dprint(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_dprint(RIO_DEBUG_PARAM, ("Parity checking on input enabled\n"));
+               Cor1 |= COR1_INPCK;
+       }
+#endif
+
+       switch ( TtyP->termios->c_cflag & CSIZE ) {
+               case CS5:
+               {
+                       rio_dprint(RIO_DEBUG_PARAM, ("5 bit data\n"));
+                       Cor1 |= COR1_5BITS;
+                       break;
+               }
+               case CS6:
+               {
+                       rio_dprint(RIO_DEBUG_PARAM, ("6 bit data\n"));
+                       Cor1 |= COR1_6BITS;
+                       break;
+               }
+               case CS7:
+               {
+                       rio_dprint(RIO_DEBUG_PARAM, ("7 bit data\n"));
+                       Cor1 |= COR1_7BITS;
+                       break;
+               }
+               case CS8:
+               {
+                       rio_dprint(RIO_DEBUG_PARAM, ("8 bit data\n"));
+                       Cor1 |= COR1_8BITS;
+                       break;
+               }
+       }
+
+       if ( TtyP->termios->c_cflag & CSTOPB ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("2 stop bits\n"));
+               Cor1 |= COR1_2STOP;
+       }
+       else {
+               rio_dprint(RIO_DEBUG_PARAM, ("1 stop bit\n"));
+               Cor1 |= COR1_1STOP;
+       }
+
+       if ( TtyP->termios->c_cflag & PARENB ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable parity\n"));
+               Cor1 |= COR1_NORMAL;
+       }
+       else {
+               rio_dprint(RIO_DEBUG_PARAM, ("Disable parity\n"));
+               Cor1 |= COR1_NOP;
+       }
+       if ( TtyP->termios->c_cflag & PARODD ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Odd parity\n"));
+               Cor1 |= COR1_ODD;
+       }
+       else {
+               rio_dprint(RIO_DEBUG_PARAM, ("Even parity\n"));
+               Cor1 |= COR1_EVEN; 
+       }
+
+       /*
+       ** COR 2
+       */
+       if ( TtyP->termios->c_iflag & IXON ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable start/stop output control\n"));
+               Cor2 |= COR2_IXON;
+       }
+       else {
+               if ( PortP->Config & RIO_IXON ) {
+                       rio_dprint(RIO_DEBUG_PARAM, ("Force enable start/stop output control\n"));
+                       Cor2 |= COR2_IXON;
+               }
+               else
+                       rio_dprint(RIO_DEBUG_PARAM, ("IXON has been disabled.\n"));
+       }
+
+       if (TtyP->termios->c_iflag & IXANY) {
+               if ( PortP->Config & RIO_IXANY ) {
+                       rio_dprint(RIO_DEBUG_PARAM, ("Enable any key to restart output\n"));
+                       Cor2 |= COR2_IXANY;
+               }
+               else
+                       rio_dprint(RIO_DEBUG_PARAM, ("IXANY has been disabled due to sanity reasons.\n"));
+       }
+
+       if ( TtyP->termios->c_iflag & IXOFF ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable start/stop input control 2\n"));
+               Cor2 |= COR2_IXOFF;
+       }
+
+       if ( TtyP->termios->c_cflag & HUPCL ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Hangup on last close\n"));
+               Cor2 |= COR2_HUPCL;
+       }
+
+       if ( C_CRTSCTS (TtyP)) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Rx hardware flow control enabled\n"));
+               Cor2 |= COR2_CTSFLOW;
+               Cor2 |= COR2_RTSFLOW;
+       } else {
+               rio_dprint(RIO_DEBUG_PARAM, ("Rx hardware flow control disabled\n"));
+               Cor2 &= ~COR2_CTSFLOW;
+               Cor2 &= ~COR2_RTSFLOW;
+       }
+
+
+       if ( TtyP->termios->c_cflag & CLOCAL ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Local line\n"));
+       }
+       else {
+               rio_dprint(RIO_DEBUG_PARAM, ("Possible Modem line\n"));
+       }
+
+       /*
+       ** COR 4 (there is no COR 3)
+       */
+       if ( TtyP->termios->c_iflag & IGNBRK ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Ignore break condition\n"));
+               Cor4 |= COR4_IGNBRK;
+       }
+       if ( !(TtyP->termios->c_iflag & BRKINT) ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Break generates NULL condition\n"));
+               Cor4 |= COR4_NBRKINT;
+       } else {
+               rio_dprint(RIO_DEBUG_PARAM, ("Interrupt on      break condition\n"));
+       }
+
+       if ( TtyP->termios->c_iflag & INLCR ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Map newline to carriage return on input\n"));
+               Cor4 |= COR4_INLCR;
+       }
+
+       if ( TtyP->termios->c_iflag & IGNCR ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Ignore carriage return on input\n"));
+               Cor4 |= COR4_IGNCR;
+       }
+
+       if ( TtyP->termios->c_iflag & ICRNL ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Map carriage return to newline on input\n"));
+               Cor4 |= COR4_ICRNL;
+       }
+       if ( TtyP->termios->c_iflag & IGNPAR ) {
+               rio_dprint(RIO_DEBUG_PARAM, ("Ignore characters with parity errors\n"));
+               Cor4 |= COR4_IGNPAR;
+       }
+       if ( TtyP->termios->c_iflag & PARMRK ) {
+               rio_dprint(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_dprint(RIO_DEBUG_PARAM, ("Strip input characters\n"));
+               if (! (PortP->State & RIO_TRIAD_MODE)) {
+                       Cor5 |= COR5_ISTRIP;
+               }
+       }
+
+       if ( TtyP->termios->c_oflag & ONLCR ) {
+               rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_PARAM, ("tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud));
+
+
+       /*
+       ** Leftovers
+       */
+       if ( TtyP->termios->c_cflag & CREAD )
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable receiver\n"));
+#ifdef RCV1EN
+       if ( TtyP->termios->c_cflag & RCV1EN )
+               rio_dprint(RIO_DEBUG_PARAM, ("RCV1EN (?)\n"));
+#endif
+#ifdef XMT1EN
+       if ( TtyP->termios->c_cflag & XMT1EN )
+               rio_dprint(RIO_DEBUG_PARAM, ("XMT1EN (?)\n"));
+#endif
+#if 0
+       if ( TtyP->termios->c_cflag & LOBLK )
+               rio_dprint(RIO_DEBUG_PARAM, ("LOBLK - JCL output blocks when not current\n"));
+#endif
+       if ( TtyP->termios->c_lflag & ISIG )
+               rio_dprint(RIO_DEBUG_PARAM, ("Input character signal generating enabled\n"));
+       if ( TtyP->termios->c_lflag & ICANON )
+               rio_dprint(RIO_DEBUG_PARAM, ("Canonical input: erase and kill enabled\n"));
+       if ( TtyP->termios->c_lflag & XCASE )
+               rio_dprint(RIO_DEBUG_PARAM, ("Canonical upper/lower presentation\n"));
+       if ( TtyP->termios->c_lflag & ECHO )
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable input echo\n"));
+       if ( TtyP->termios->c_lflag & ECHOE )
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable echo erase\n"));
+       if ( TtyP->termios->c_lflag & ECHOK )
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable echo kill\n"));
+       if ( TtyP->termios->c_lflag & ECHONL )
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable echo newline\n"));
+       if ( TtyP->termios->c_lflag & NOFLSH )
+               rio_dprint(RIO_DEBUG_PARAM, ("Disable flush after interrupt or quit\n"));
+#ifdef TOSTOP
+       if ( TtyP->termios->c_lflag & TOSTOP )
+               rio_dprint(RIO_DEBUG_PARAM, ("Send SIGTTOU for background output\n"));
+#endif
+#ifdef XCLUDE
+       if ( TtyP->termios->c_lflag & XCLUDE )
+               rio_dprint(RIO_DEBUG_PARAM, ("Exclusive use of this line\n"));
+#endif
+       if ( TtyP->termios->c_iflag & IUCLC )
+               rio_dprint(RIO_DEBUG_PARAM, ("Map uppercase to lowercase on input\n"));
+       if ( TtyP->termios->c_oflag & OPOST )
+               rio_dprint(RIO_DEBUG_PARAM, ("Enable output post-processing\n"));
+       if ( TtyP->termios->c_oflag & OLCUC )
+               rio_dprint(RIO_DEBUG_PARAM, ("Map lowercase to uppercase on output\n"));
+       if ( TtyP->termios->c_oflag & ONOCR )
+               rio_dprint(RIO_DEBUG_PARAM, ("No carriage return output at column 0\n"));
+       if ( TtyP->termios->c_oflag & ONLRET )
+               rio_dprint(RIO_DEBUG_PARAM, ("Newline performs carriage return function\n"));
+       if ( TtyP->termios->c_oflag & OFILL )
+               rio_dprint(RIO_DEBUG_PARAM, ("Use fill characters for delay\n"));
+       if ( TtyP->termios->c_oflag & OFDEL )
+               rio_dprint(RIO_DEBUG_PARAM, ("Fill character is DEL\n"));
+       if ( TtyP->termios->c_oflag & NLDLY )
+               rio_dprint(RIO_DEBUG_PARAM, ("Newline delay set\n"));
+       if ( TtyP->termios->c_oflag & CRDLY )
+               rio_dprint(RIO_DEBUG_PARAM, ("Carriage return delay set\n"));
+       if ( TtyP->termios->c_oflag & TABDLY )
+               rio_dprint(RIO_DEBUG_PARAM, ("Tab delay set\n"));
+#if 0
+       if ( TtyP->termios->c_oflag & BSDLY )
+               rio_dprint(RIO_DEBUG_PARAM, ("Back-space delay set\n"));
+       if ( TtyP->termios->c_oflag & VTDLY )
+               rio_dprint(RIO_DEBUG_PARAM, ("Vertical tab delay set\n"));
+       if ( TtyP->termios->c_oflag & FFDLY )
+               rio_dprint(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);
+               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_dprint(RIO_DEBUG_PARAM, ("add_transmit returned.\n"));
+       /*
+       ** job done.
+       */
+       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_dprint (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_dprint(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_dprint(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_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
+** relevent 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 (file)
index 0000000..2ea99a6
--- /dev/null
@@ -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 (file)
index 0000000..2f13eb2
--- /dev/null
@@ -0,0 +1,1233 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/malloc.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/compatmac.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"
+
+/*
+** 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_dprint(RIO_DEBUG_ROUTE, ("LIES! DAMN LIES! %d LIES!\n",Lies));
+      rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_ROUTE, ("Backplane type is %s (all ports)\n",
+     p->RIOModuleTypes[Mod1].Name ));
+  }
+  else
+  {
+    Mod2 = HINYBLE(Mod);
+    rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_ROUTE, ("Found unit 0x%x at slots %d+%d\n",
+                                           RtaUniq,ThisUnit,ThisUnit2));
+      }
+      else
+          rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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
+      ** relevent 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_dprint(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_dprint(RIO_DEBUG_ROUTE, ("Tx pkts not set up yet\n"));
+                                       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_dprint(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_dprint(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.
+*/
+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_dprint(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.
+*/
+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_dprint(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;
+}
+
+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_dprint(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_dprint(RIO_DEBUG_ROUTE, ("Unit type: Host\n"));
+                       return(TYPE_HOST);
+               case RIO_RTA_16:
+                       rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: 16 port RTA\n"));
+                       return(TYPE_RTA16);
+               case RIO_RTA:
+                       rio_dprint(RIO_DEBUG_ROUTE, ("Unit type: 8 port RTA\n"));
+                       return(TYPE_RTA8);
+               default :
+                       rio_dprint(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_dprint(RIO_DEBUG_ROUTE, ("Send SIG-HUP"));
+               /*
+               psignal( RIOSignalProcess, SIGHUP );
+               */
+       }
+       return(0);
+}
+
+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_dprint(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.
+*/
+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
+    ** its 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.
+*/
+int
+RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
+{
+    int                link;
+
+
+    rio_dprint(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_dprint(RIO_DEBUG_ROUTE, ("Just about to check LBOLT on entry %d\n",unit));
+    if (drv_getparm(LBOLT, (ulong_t *) &current_time))
+        rio_dprint(RIO_DEBUG_ROUTE, ("drv_getparm(LBOLT,....) Failed.\n"));
+
+    elapse_time = current_time - TentTime[unit];
+    rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_ROUTE, ("    Slot %d looks promising.\n",unit));
+
+           if(unit == *pID1)
+           {
+               rio_dprint(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_dprint(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_dprint(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_dprint(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 (file)
index 0000000..32b09b0
--- /dev/null
@@ -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 (file)
index 0000000..6329a6e
--- /dev/null
@@ -0,0 +1,1057 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/malloc.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/compatmac.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_dprint(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_dprint(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_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(3)\n"));
+               if ( !MapP->RtaUniqueNum && !MapP->HostUniqueNum ) { /* (3) */
+                       if ( MapP->ID || MapP->SysPort || MapP->Flags ) {
+                               rio_dprint(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_dprint(RIO_DEBUG_TABLE, ("!RIO: Daemon: test (3) passes\n"));
+                       continue;
+               }
+
+               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(5)\n")); 
+               if ( MapP->RtaUniqueNum ) { /* (5) */
+                       if ( !MapP->ID ) {
+                               rio_dprint(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_dprint(RIO_DEBUG_TABLE, ("RIO: RTA %s has been allocated an illegal 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_dprint(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_dprint(RIO_DEBUG_TABLE, ("RTA %s has duplicate unique number\n",MapP->Name));
+                                       rio_dprint(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_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(7a)\n")); 
+                       /* (7a) */
+                       if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort % PORTS_PER_RTA)) {
+                               rio_dprint(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_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(7b)\n")); 
+                       /* (7b) */
+                       if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort >= RIO_PORTS)) {
+                               rio_dprint(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_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(8)\n")); 
+                                       /* (8) */
+                                       if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort == 
+                                                                       p->RIOConnectTable[SubEnt].SysPort) ) {
+                                               rio_dprint(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_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(9)\n")); 
+                                       if (RIOStrCmp(MapP->Name,
+                                                       p->RIOConnectTable[SubEnt].Name)==0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */
+                                               rio_dprint(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_dprint(RIO_DEBUG_TABLE, ("RIONewTable: entering(6)\n")); 
+                       if ( MapP->ID ) {
+                               rio_dprint(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_dprint(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 its 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_dprint(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_dprint(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_dprint(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_dprint(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 (RIOStrCmp(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_dprint(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_dprint(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;
+       int oldspl;
+
+       disable(oldspl);                /* strange but true! */
+       rio_dprint(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_dprint(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 flags;
+
+       rio_dprint(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, flags );
+
+               if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+                       rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+                       continue;
+               }
+
+               for ( entry=0; entry<MAX_RUP; entry++ ) {
+                       if ( MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum ) {
+                               HostMapP = &HostP->Mapping[entry];
+                               rio_dprint(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_dprint(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, 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_dprint(RIO_DEBUG_TABLE, ("Unmap port\n"));
+
+                                               rio_spin_lock_irqsave( &PortP->portSem, flags );
+
+                                               PortP->Mapped = 0;
+
+                                               if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) {
+
+                                                       rio_dprint(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_dprint(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_dprint(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, flags);
+                                       }
+                               }
+                               rio_dprint(RIO_DEBUG_TABLE, ("Entry nulled.\n"));
+                               bzero((char *)HostMapP,sizeof(struct Map));
+                               work_done++;
+                       }
+               }
+               rio_spin_unlock_irqrestore(&HostP->HostLock, 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_dprint(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_dprint(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_dprint(RIO_DEBUG_TABLE, ("Bad ID in map entry!\n"));
+       p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+       return EINVAL;
+    }
+    if (MapP->RtaUniqueNum == 0)
+    {
+       rio_dprint(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_dprint(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_dprint(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_dprint(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 the entry does not already have one.
+           */
+           if (MapP->ID == (ushort)-1)
+           {
+               int nNewID;
+
+               rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_TABLE, ("Second map of RTA %s added to configuration\n",
+                p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name));
+           else
+               rio_dprint(RIO_DEBUG_TABLE, ("RTA %s added to configuration\n",MapP->Name));
+           return 0;
+       }
+    }
+    p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+    rio_dprint(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_dprint(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_dprint(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_dprint  (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_dprint (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_dprint(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;
+
+               /*
+               ** handle the xprint issues
+               */
+#ifdef XPRINT_SUPPORT
+               PortP->Xprint.XpActive  = 0;
+               PortP->Xprint.XttyP = &riox_tty[SysPort];
+               /*                              TO                              FROM                    MAXLEN */
+               RIOStrNCpy( PortP->Xprint.XpOn, RIOConf.XpOn,   MAX_XP_CTRL_LEN );
+               RIOStrNCpy( PortP->Xprint.XpOff, RIOConf.XpOff, MAX_XP_CTRL_LEN );
+               PortP->Xprint.XpCps = RIOConf.XpCps;
+               PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+
+                                                                       RIOStrlen(PortP->Xprint.XpOff);
+#endif
+
+               /*
+               ** 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_dprint(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_dprint(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_dprint(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_dprint(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 (file)
index 0000000..66d52bc
--- /dev/null
@@ -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 (file)
index 0000000..3e7236b
--- /dev/null
@@ -0,0 +1,1321 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  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__
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/malloc.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/compatmac.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);
+static int RIOShortCommand(struct rio_info *p, struct Port *PortP, 
+                          int command, int len, int arg);
+
+
+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;
+extern void rio_inc_mod_count (void);
+
+
+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;
+
+       SysPort = rio_minor (tty->device);
+       Modem   = rio_ismodem (tty->device);
+
+       if ( p->RIOFailed ) {
+               rio_dprint(RIO_DEBUG_TTY, ("System initialisation failed\n"));
+               pseterr(ENXIO);
+               return 0;
+       }
+
+       rio_dprint(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_dprint(RIO_DEBUG_TTY, ("Illegal port number %d\n",SysPort));
+               pseterr(ENXIO);
+               return 0;
+       }
+
+       /*
+       ** Grab pointer to the port stucture
+       */
+       PortP = p->RIOPortp[SysPort];   /* Get control struc */
+
+       if ( !PortP->Mapped ) { /* we aren't mapped yet! */
+               /*
+               ** The system doesn't know which RTA this port
+               ** corresponds to.
+               */
+               rio_dprint(RIO_DEBUG_TTY, ("port not mapped into system\n"));
+               pseterr(ENXIO);
+               return 0;
+       }
+
+       tty->driver_data = PortP;
+
+       PortP->gs.tty = tty;
+       PortP->gs.count++;
+       rio_dprint(RIO_DEBUG_TTY, ("%d bytes in tx buffer\n",
+                                  PortP->gs.xmit_cnt));
+       gs_init_port (&PortP->gs);
+
+       /*
+       ** If the host hasn't been booted yet, then 
+       ** fail
+       */
+       if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+               rio_dprint(RIO_DEBUG_TTY, ("Host not running\n"));
+               pseterr(ENXIO);
+               return 0;
+       }
+
+       /*
+       ** 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_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot\n"));
+                       do {
+                               if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+                                       rio_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n"));
+                                       return -EINTR;
+                               }
+                               if (repeat_this -- <= 0) {
+                                       rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n"));
+                                       RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+                                       pseterr(EINTR);
+                                       return -EIO;
+                               }
+                       } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
+                       rio_dprint(RIO_DEBUG_TTY, ("RTA has been booted\n"));
+               } else {
+                       rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n"));
+                       pseterr(ENXIO);
+                       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_dprint(RIO_DEBUG_TTY, ("Checking if RTA has booted... \n"));
+       while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
+         if (!PortP->WaitUntilBooted) {
+           rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n"));
+           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_dprint(RIO_DEBUG_TTY, ("RTA_wait_for_boot: EINTR in delay \n"));
+           return -EINTR;
+         }
+         if (repeat_this -- <= 0) {
+           rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n"));
+           return -EIO;
+         }
+       }
+       rio_dprint(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)
+         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_dprint(RIO_DEBUG_TTY, ("Waiting for RIO_CLOSING to go away\n"));
+               if (repeat_this -- <= 0) {
+                       rio_dprint(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_dprint(RIO_DEBUG_TTY, ("Port unmapped while closing!\n"));
+               rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+               retval = -ENXIO;
+               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_dprint(RIO_DEBUG_TTY, ("First open for this port\n"));
+               rio_inc_mod_count ();
+
+               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_dprint(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_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish broken by signal\n"));
+                               RIOPreemptiveCmd(p, PortP, FCLOSE );
+                               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_dprint(RIO_DEBUG_TTY, ("PORT_ISOPEN found\n"));
+       }
+
+#ifdef MODEM_SUPPORT 
+       if (Modem) {
+               rio_dprint(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 ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD))
+               {
+                       rio_dprint(RIO_DEBUG_TTY, (PortP,DBG_OPEN,"open(%d) Modem carr on\n",SysPort));
+                       tp->tm.c_state |= CARR_ON;
+                       wakeup((caddr_t) &tp->tm.c_canq);
+               }
+               else /* no carrier - wait for DCD */
+               {
+                       while (!(tp->tm.c_state&CARR_ON) && 
+                              !(filp->f_flags&O_NONBLOCK) && !p->RIOHalted )
+                       {
+                               rio_dprint(RIO_DEBUG_TTY, (PortP,DBG_OPEN,"open(%d) sleeping for carr on\n",SysPort));
+                               tp->tm.c_state |= WOPEN;
+                               PortP->State |= RIO_WOPEN;
+                               if ( sleep((caddr_t)&tp->tm.c_canq, TTIPRI|PCATCH))
+                               {
+                                       /*
+                                       ** ACTION: verify that this is a good thing
+                                       ** to do here. -- ???
+                                       ** I think it's OK. -- REW
+                                       */
+                                       rio_dprint(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);
+                                       return -EINTR;
+                               }
+                       }
+                       PortP->State &= ~RIO_WOPEN;
+               }
+               if ( RIOHalted )
+                       goto bombout;
+               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_dprint(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_dprint(RIO_DEBUG_TTY, ("Returning from open\n"));
+       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 = 25;
+       int     repeat_this = 0xff;
+       struct tty_struct * tty;
+       unsigned long flags;
+       int Modem;
+       int rv =0;
+       
+       rio_dprint(RIO_DEBUG_TTY, ("port close SysPort %d\n",PortP->PortNum));
+
+       /* PortP = p->RIOPortp[SysPort]; */
+       rio_dprint(RIO_DEBUG_TTY, ("Port is at address 0x%x\n",(int)PortP));
+       /* tp = PortP->TtyP;*/                  /* Get tty */
+       tty = PortP->gs.tty;
+       rio_dprint(RIO_DEBUG_TTY, ("TTY is at address 0x%x\n",(int)tty));
+       Modem = rio_ismodem(tty->device);
+#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_dprint(RIO_DEBUG_TTY, ("Close on deleted RTA\n"));
+               deleted = 1;
+       }
+       
+       if ( p->RIOHalted ) {
+               RIOClearUp( PortP );
+               rv = -EIO;
+               goto close_end;
+       }
+
+       rio_dprint(RIO_DEBUG_TTY, ("Clear bits\n"));
+       /*
+       ** clear the open bits for this device
+       */
+       PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN);
+
+       /*
+       ** 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_dprint(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_dprint(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_dprint(RIO_DEBUG_TTY, ("Timeout 1 starts\n"));
+
+#if 0
+       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_dprint(RIO_DEBUG_TTY, ("Waiting for not idle closed broken by signal\n"));
+                       RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+                       goto close_end;
+               }
+               rio_dprint(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_dprint(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);
+       }
+#endif
+       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_dprint(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 (try == 0) {
+                 rio_dprint(RIO_DEBUG_TTY, ("Run out of tries - force the bugger shut!\n" ));
+                 RIOPreemptiveCmd(p, PortP,FCLOSE);
+                 break;
+               }
+               rio_dprint(RIO_DEBUG_TTY, ("Close: PortState:ISOPEN is %d\n", 
+                                          PortP->PortState & PORT_ISOPEN));
+
+               if ( p->RIOHalted ) {
+                       RIOClearUp( PortP );
+                       goto close_end;
+               }
+               RIODelay_ni(PortP, HUNDRED_MS);
+       }
+       rio_spin_lock_irqsave(&PortP->portSem, flags);
+       rio_dprint(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_dprint(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.
+*/
+int
+RIOCookMode(struct ttystatics *tp)
+{
+       /*
+       ** We cant handle tm.c_mstate != 0 on SCO
+       ** We cant handle mapping
+       ** We cant handle non-ttwrite line disc.
+       ** We cant 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;
+}
+
+
+static void
+RIOClearUp(PortP)
+struct Port *PortP;
+{
+       rio_dprint(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.
+*/
+static 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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_TTY, ("Waiting to add short command to queue (%d)\n", retries));
+               rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+               if (retries-- <= 0) {
+                 rio_dprint(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(p, dev, cmd, arg)
+struct rio_info *              p;
+dev_t dev;
+register int cmd;
+register 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 = dev;
+       int                                     Modem = rio_ismodem(dev);
+       int                                     ioctl_processed;
+
+       rio_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_TTY, ("TCRIOSTATE\n"));
+                       if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL)
+                               rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(RIO_DEBUG_TTY, ("TCRIOXPON\n"));
+                       if ( copyin((int)arg, (caddr_t)PortP->Xprint.XpOn,
+                                               MAX_XP_CTRL_LEN)==COPYFAIL ) {
+                               rio_dprint(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 = RIOStrlen(PortP->Xprint.XpOn)+
+                                                                                               RIOStrlen(PortP->Xprint.XpOff);
+                       rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+                       return 0;
+
+               case TCRIOXPOFF: /* set Xprint OFF string */
+                       rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPOFF\n"));
+                       if ( copyin( (int)arg, (caddr_t)PortP->Xprint.XpOff,
+                                               MAX_XP_CTRL_LEN)==COPYFAIL ) {
+                               rio_dprint(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 = RIOStrlen(PortP->Xprint.XpOn)+
+                                                                               RIOStrlen(PortP->Xprint.XpOff);
+                       rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+                       return 0;
+
+               case TCRIOXPCPS: /* set Xprint CPS string */
+                       rio_dprint(RIO_DEBUG_TTY, ("TCRIOXPCPS\n"));
+                       if ( (uint)arg > p->RIOConf.MaxXpCps || 
+                                       (uint)arg < p->RIOConf.MinXpCps ) {
+                               rio_dprint(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_dprint(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_dprint(RIO_DEBUG_TTY, ("TCRIOIXANYON\n"));
+                       PortP->Config |= RIO_IXANY;
+                       rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+                       return 0;
+
+               case TCRIOIXANYOFF:
+                       rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXANYOFF\n"));
+                       PortP->Config &= ~RIO_IXANY;
+                       rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+                       return 0;
+
+               case TCRIOIXONON:
+                       rio_dprint(RIO_DEBUG_TTY, ("TCRIOIXONON\n"));
+                       PortP->Config |= RIO_IXON;
+                       rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+                       return 0;
+
+               case TCRIOIXONOFF:
+                       rio_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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_dprint(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 dependant 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 dependant 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 (file)
index 0000000..1c7c42c
--- /dev/null
@@ -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 (file)
index 0000000..18a4f14
--- /dev/null
@@ -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 (file)
index 0000000..7685cc1
--- /dev/null
@@ -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 (file)
index 0000000..ee79b8e
--- /dev/null
@@ -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 (file)
index 0000000..c42dbb9
--- /dev/null
@@ -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 (file)
index 0000000..0686011
--- /dev/null
@@ -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 (file)
index 0000000..b9d2bc0
--- /dev/null
@@ -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 (file)
index 0000000..b4aafaf
--- /dev/null
@@ -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 (file)
index 0000000..c1accb8
--- /dev/null
@@ -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 (file)
index 0000000..deae487
--- /dev/null
@@ -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 (file)
index 0000000..72398d3
--- /dev/null
@@ -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 (file)
index 0000000..fdc7313
--- /dev/null
@@ -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 (file)
index 0000000..11b3133
--- /dev/null
@@ -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 (file)
index 0000000..255c40d
--- /dev/null
@@ -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 (file)
index 0000000..2cb9dd6
--- /dev/null
@@ -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 (file)
index 0000000..13821a9
--- /dev/null
@@ -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__ */
index 071982e2b4393eb598bbfbf54a5ecf9707330d8a..4d104ec530f7bc475ef21d0291d83291128e1555 100644 (file)
@@ -1384,7 +1384,9 @@ init_dev_done:
            current->leader &&
            !current->tty &&
            tty->session == 0) {
+               task_lock(current);
                current->tty = tty;
+               task_unlock(current);
                current->tty_old_pgrp = 0;
                tty->session = current->session;
                tty->pgrp = current->pgrp;
@@ -1594,7 +1596,9 @@ static int tiocsctty(struct tty_struct *tty, int arg)
                } else
                        return -EPERM;
        }
+       task_lock(current);
        current->tty = tty;
+       task_unlock(current);
        current->tty_old_pgrp = 0;
        tty->session = current->session;
        tty->pgrp = current->pgrp;
@@ -1761,7 +1765,9 @@ int tty_ioctl(struct inode * inode, struct file * file,
                                return -ENOTTY;
                        if (current->leader)
                                disassociate_ctty(0);
+                       task_lock(current);
                        current->tty = NULL;
+                       task_unlock(current);
                        return 0;
                case TIOCSCTTY:
                        return tiocsctty(tty, arg);
@@ -1858,8 +1864,9 @@ void do_SAK( struct tty_struct *tty)
                        send_sig(SIGKILL, p, 1);
                else if (p->files) {
                        read_lock(&p->files->file_lock);
+                       /* FIXME: p->files could change */
                        for (i=0; i < p->files->max_fds; i++) {
-                               filp = fcheck_task(p, i);
+                               filp = fcheck_files(p->files, i);
                                if (filp && (filp->f_op == &tty_fops) &&
                                    (filp->private_data == tty)) {
                                        send_sig(SIGKILL, p, 1);
index 566e94b3b5179f3b079968748e7d00091e4b2bdc..c365b0a1200cceffeb533b0d10c9970e8697b6a6 100644 (file)
  *             Independent queues per IOP
  *             Support for dynamic device creation/deletion
  *             Code cleanup    
- *    Support for larger I/Os through merge* functions 
- *       (taken from DAC960 driver)
+ *             Support for larger I/Os through merge* functions 
+ *             (taken from DAC960 driver)
+ *     Boji T Kannanthanam:
+ *             Reduced the timeout during RAID 5 creation. 
+ *             This is to prevent race condition when a RAID volume
+ *             is created and immediately deleted.
  *
  *     To do:
  *             Serial number scanning to find duplicates for FC multipathing
+ *             Remove the random timeout in the code needed for RAID 5
+ *                     volume creation.
  */
 
 #include <linux/major.h>
@@ -1376,7 +1382,7 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
         * so we just sleep for a little while and let it do it's thing
         */
        current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(10*HZ);
+       schedule_timeout(3*HZ);
 
        if(i2o_claim_device(d, &i2o_block_handler))
        {
index 0202afb67a83fdef04c92ac4d494fc21297fc19c..5f51f6ca12ee145b8ea7b1c03440e5a6932a66d7 100644 (file)
@@ -515,7 +515,7 @@ int ioctl_html(unsigned long arg)
                msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
                msg[5] = 0x50000000|65536;
                msg[7] = 0xD4000000|(kcmd.qlen);
-               msg[8] = virt_to_phys(query);
+               msg[8] = virt_to_bus(query);
        }
 
        token = i2o_post_wait(c, msg, 9*4, 10);
@@ -592,7 +592,7 @@ int ioctl_swdl(unsigned long arg)
        msg[5]= swlen;
        msg[6]= kxfer.sw_id;
        msg[7]= (0xD0000000 | fragsize);
-       msg[8]= virt_to_phys(buffer);
+       msg[8]= virt_to_bus(buffer);
 
 //     printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
        status = i2o_post_wait(c, msg, sizeof(msg), 60);
index 05ed6d851a6117e543d52fd619e9344c29323f7e..80d0014680240188f18408a7fb0e8d782446c24d 100644 (file)
@@ -18,6 +18,7 @@
  *             Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> 
  *             Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> 
  *             Deepak Saxena <deepak@plexity.net> 
+ *             Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
  * 
  */
 
@@ -70,12 +71,11 @@ static int core_context = 0;
 /* Initialization && shutdown functions */
 static void i2o_sys_init(void);
 static void i2o_sys_shutdown(void);
-static int i2o_clear_controller(struct i2o_controller *);
+static int i2o_reset_controller(struct i2o_controller *);
 static int i2o_reboot_event(struct notifier_block *, unsigned long , void *);
 static int i2o_online_controller(struct i2o_controller *);
 static int i2o_init_outbound_q(struct i2o_controller *);
 static int i2o_post_outbound_messages(struct i2o_controller *);
-static int i2o_issue_claim(struct i2o_controller *, int, int, int, u32);
 
 /* Reply handler */
 static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
@@ -111,6 +111,14 @@ static struct i2o_sys_tbl *sys_tbl = NULL;
 static int sys_tbl_ind = 0;
 static int sys_tbl_len = 0;
 
+/*
+ * This spin lock is used to keep a device from being
+ * added and deleted concurrently across CPUs or interrupts.
+ * This can occur when a user creates a device and immediatelly
+ * deletes it before the new_dev_notify() handler is called.
+ */
+static spinlock_t i2o_dev_lock = SPIN_LOCK_UNLOCKED;
+
 #ifdef MODULE
 /* 
  * Function table to send to bus specific layers
@@ -214,24 +222,12 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
        u32 status;
        u32 context = msg[2];
 
-#if 0
-       i2o_report_status(KERN_INFO, "i2o_core", msg);
-#endif
-
-       if (msg[0] & (1<<13)) // Fail bit is set
+       if (msg[0] & MSG_FAIL) // Fail bit is set
        {
                u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]);
 
-//             i2o_report_failure(KERN_INFO, c, "i2o_core", msg);
-               printk(KERN_ERR "%s: Failed to process the msg:\n", c->name);
-               printk(KERN_ERR "  Cmd = 0x%02X, InitiatorTid = %d, TargetTid =% d\n",
-                       (msg[1] >> 24) & 0xFF, (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF);
-               printk(KERN_ERR "  FailureCode = 0x%02X\n  Severity = 0x%02X\n"
-                       "LowestVersion = 0x%02X\n  HighestVersion = 0x%02X\n",
-                       msg[4] >> 24, (msg[4] >> 16) & 0xFF,
-                       (msg[4] >> 8) & 0xFF, msg[4] & 0xFF);
-               printk(KERN_ERR "  FailingHostUnit = 0x%04X\n  FailingIOP = 0x%03X\n",
-                       msg[5] >> 16, msg[5] & 0xFFF);
+               i2o_report_status(KERN_INFO, "i2o_core", msg);
+               i2o_dump_message(preserved_msg);
 
                /* If the failed request needs special treatment,
                 * it should be done here. */
@@ -244,16 +240,18 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
                i2o_post_message(c, msg[7]);
 
                /* If reply to i2o_post_wait failed, return causes a timeout */
+
                return;
        }       
 
+#ifdef DRIVERDEBUG
+       i2o_report_status(KERN_INFO, "i2o_core", msg);
+#endif
+
        if(msg[2]&0x80000000)   // Post wait message
        {
                if (msg[4] >> 24)
-               {
-                       i2o_report_status(KERN_INFO, "i2o_core: post_wait reply", msg);
                        status = -(msg[4] & 0xFFFF);
-               }
                else
                        status = I2O_POST_WAIT_OK;
        
@@ -263,7 +261,7 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
 
        if(m->function == I2O_CMD_UTIL_EVT_REGISTER)
        {
-               memcpy(events[evt_in].msg, msg, MSG_FRAME_SIZE);
+               memcpy(events[evt_in].msg, msg, (msg[0]>>16)<<2);
                events[evt_in].iop = c;
 
                spin_lock(&i2o_evt_lock);
@@ -471,7 +469,7 @@ int i2o_delete_controller(struct i2o_controller *c)
        char name[16];
        int stat;
 
-       dprintk(KERN_INFO "Deleting controller iop%d\n", c->unit);
+       dprintk(KERN_INFO "Deleting controller %s\n", c->name);
 
        /*
         * Clear event registration as this can cause weird behavior
@@ -482,7 +480,7 @@ int i2o_delete_controller(struct i2o_controller *c)
        spin_lock(&i2o_configuration_lock);
        if((users=atomic_read(&c->users)))
        {
-               dprintk(KERN_INFO "I2O: %d users for controller iop%d\n", users,
+               dprintk(KERN_INFO "I2O: %d users for controller %s\n", users,
                        c->name);
                spin_unlock(&i2o_configuration_lock);
                return -EBUSY;
@@ -523,9 +521,8 @@ int i2o_delete_controller(struct i2o_controller *c)
        {
                if(*p==c)
                {
-                       /* Ask the IOP to switch to HOLD state */
-                       if (i2o_clear_controller(c) < 0)
-                               printk(KERN_ERR "Unable to clear iop%d\n", c->unit);
+                       /* Ask the IOP to switch to RESET state */
+                       i2o_reset_controller(c);
 
                        /* Release IRQ */
                        c->destructor(c);
@@ -578,7 +575,21 @@ struct i2o_controller *i2o_find_controller(int n)
        spin_unlock(&i2o_configuration_lock);
        return c;
 }
+
+/*
+ *     Issue UTIL_CLAIM or UTIL_RELEASE message
+ */
+static int i2o_issue_claim(u32 cmd, struct i2o_controller *c, int tid, u32 type)
+{
+       u32 msg[5];
+
+       msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+       msg[1] = cmd << 24 | HOST_TID<<12 | tid;
+       msg[3] = 0;
+       msg[4] = type;
        
+       return i2o_post_wait(c, msg, sizeof(msg), 60);
+}
 
 /*
  * Claim a device for use by an OSM
@@ -586,15 +597,15 @@ struct i2o_controller *i2o_find_controller(int n)
 int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h)
 {
        spin_lock(&i2o_configuration_lock);
-       if(d->owner)
-       {
-               printk(KERN_INFO "issue claim called, but dev as owner!");
+       if (d->owner) {
+               printk(KERN_INFO "Device claim called, but dev allready owned by %s!",
+                      h->name);
                spin_unlock(&i2o_configuration_lock);
                return -EBUSY;
        }
 
-       if(i2o_issue_claim(d->controller,d->lct_data.tid, h->context, 1,
-                I2O_CLAIM_PRIMARY))
+       if(i2o_issue_claim(I2O_CMD_UTIL_CLAIM ,d->controller,d->lct_data.tid, 
+                          I2O_CLAIM_PRIMARY))
        {
                spin_unlock(&i2o_configuration_lock);
                return -EBUSY;
@@ -606,21 +617,22 @@ int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h)
 }
 
 /*
- * Release a device that the OS is using
+ * Release a device that the OSM is using
  */
 int i2o_release_device(struct i2o_device *d, struct i2o_handler *h)
 {
        int err = 0;
 
        spin_lock(&i2o_configuration_lock);
-       if(d->owner != h)
-       {
+       if (d->owner != h) {
+               printk(KERN_INFO "Claim release called, but not owned by %s!",
+                      h->name);
                spin_unlock(&i2o_configuration_lock);
                return -ENOENT;
        }       
 
-       if(i2o_issue_claim(d->controller, d->lct_data.tid, h->context, 0,
-                       I2O_CLAIM_PRIMARY))
+       if(i2o_issue_claim(I2O_CMD_UTIL_RELEASE, d->controller, d->lct_data.tid, 
+                          I2O_CLAIM_PRIMARY))
        {
                err = -ENXIO;
        }
@@ -684,13 +696,13 @@ int i2o_event_register(struct i2o_controller *c, u32 tid,
                u32 init_context, u32 tr_context, u32 evt_mask)
 {
        u32 msg[5];     // Not performance critical, so we just 
-                                       // i2o_post_this it instead of building it
-                                       // in IOP memory
+                       // i2o_post_this it instead of building it
+                       // in IOP memory
        
        msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
        msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | tid;
-       msg[2] = (u32)init_context;
-       msg[3] = (u32)tr_context;
+       msg[2] = init_context;
+       msg[3] = tr_context;
        msg[4] = evt_mask;
 
        return i2o_post_this(c, msg, sizeof(msg));
@@ -703,6 +715,7 @@ int i2o_event_register(struct i2o_controller *c, u32 tid,
  * message and change the function code since that's what spec
  * describes an EventAck message looking like.
  */
 int i2o_event_ack(struct i2o_controller *c, u32 *msg)
 {
        struct i2o_message *m = (struct i2o_message *)msg;
@@ -819,7 +832,11 @@ static int i2o_core_evt(void *reply_data)
                                        if(i2o_handlers[i] && 
                                                i2o_handlers[i]->new_dev_notify &&
                                                (i2o_handlers[i]->class&d->lct_data.class_id))
+                                               {
+                                               spin_lock(&i2o_dev_lock);
                                                i2o_handlers[i]->new_dev_notify(c,d);
+                                               spin_unlock(&i2o_dev_lock);
+                                               }
                                }
                        
                                break;
@@ -855,7 +872,7 @@ static int i2o_core_evt(void *reply_data)
                                break;
        
                        default:
-                               printk(KERN_WARNING "%s: Unknown event (0x%08x)...check config\n", c->name, msg[4]);
+                               printk(KERN_WARNING "%s: No handler for event (0x%08x)\n", c->name, msg[4]);
                                break;
                }
        }
@@ -939,7 +956,9 @@ static int i2o_dyn_lct(void *foo)
                        if(!found) 
                        {
                                dprintk(KERN_INFO "Deleted device!\n"); 
+                               spin_lock(&i2o_dev_lock);
                                i2o_delete_device(d); 
+                               spin_unlock(&i2o_dev_lock);
                        } 
                        d = d1; 
                }
@@ -1114,29 +1133,6 @@ u32 i2o_wait_message(struct i2o_controller *c, char *why)
        }
        return m;
 }
-
-
-/*
- *     Wait up to timeout seconds for a reply to be available.
- */
-u32 i2o_wait_reply(struct i2o_controller *c, char *why, int timeout)
-{
-       u32 m;
-       long time=jiffies;
-       
-       while((m=I2O_REPLY_READ32(c))==0xFFFFFFFF)
-       {
-               if(jiffies-time >= timeout*HZ )
-               {
-                       dprintk(KERN_ERR "%s: timeout waiting for %s reply.\n",
-                               c->name, why);
-                       return 0xFFFFFFFF;
-               }
-               schedule();
-       }
-       return m;
-}
        
 /*
  *      Dump the information block associated with a given unit (TID)
@@ -1371,12 +1367,12 @@ int i2o_quiesce_controller(struct i2o_controller *c)
        /* Long timeout needed for quiesce if lots of devices */
 
        if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))
-               printk(KERN_INFO "%s: Unable to quiesce (status=%#10x).\n",
-                       c->name, ret);
+               printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n",
+                       c->name, -ret);
        else
                dprintk(KERN_INFO "%s: Quiesced.\n", c->name);
 
-       i2o_status_get(c); // Reread the Status Block
+       i2o_status_get(c); // Entered READY state
 
    return ret;
 
@@ -1402,12 +1398,12 @@ int i2o_enable_controller(struct i2o_controller *c)
    /* How long of a timeout do we need? */
 
        if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))
-               printk(KERN_ERR "%s: Could not enable (status=%#10x).\n",
-                       c->name, ret);
+               printk(KERN_ERR "%s: Could not enable (status=%#x).\n",
+                       c->name, -ret);
        else
                dprintk(KERN_INFO "%s: Enabled.\n", c->name);
 
-       i2o_status_get(c);
+       i2o_status_get(c); // entered OPERATIONAL state
 
        return ret;
 }
@@ -1434,8 +1430,8 @@ int i2o_clear_controller(struct i2o_controller *c)
        msg[3]=0;
 
        if ((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
-               printk(KERN_INFO "%s: Unable to clear (status=%#10x).\n",
-                       c->name, ret);
+               printk(KERN_INFO "%s: Unable to clear (status=%#x).\n",
+                       c->name, -ret);
        else
                dprintk(KERN_INFO "%s: Cleared.\n",c->name);
 
@@ -1470,7 +1466,6 @@ static int i2o_reset_controller(struct i2o_controller *c)
        for (iop = i2o_controller_chain; iop; iop = iop->next)
                i2o_quiesce_controller(iop);
 
-       /* Get a message */
        m=i2o_wait_message(c, "AdapterReset");
        if(m==0xFFFFFFFF)       
                return -ETIMEDOUT;
@@ -1489,7 +1484,7 @@ static int i2o_reset_controller(struct i2o_controller *c)
        msg[3]=0;
        msg[4]=0;
        msg[5]=0;
-       msg[6]=virt_to_phys(status);
+       msg[6]=virt_to_bus(status);
        msg[7]=0;       /* 64bit host FIXME */
 
        i2o_post_message(c,m);
@@ -1508,7 +1503,7 @@ static int i2o_reset_controller(struct i2o_controller *c)
                barrier();
        }
 
-       if (status[0]==0x01)
+       if (status[0]==I2O_CMD_IN_PROGRESS)
        { 
                /* 
                 * Once the reset is sent, the IOP goes into the INIT state 
@@ -1519,7 +1514,7 @@ static int i2o_reset_controller(struct i2o_controller *c)
                 * time, we assume the IOP could not reboot properly.  
                 */ 
 
-               dprintk(KERN_INFO "Reset succeeded...waiting for reboot\n"); 
+               dprintk(KERN_INFO "Reset in progress, waiting for reboot\n"); 
 
                time = jiffies; 
                m = I2O_POST_READ32(c); 
@@ -1534,21 +1529,21 @@ static int i2o_reset_controller(struct i2o_controller *c)
                        schedule(); 
                        barrier(); 
                        m = I2O_POST_READ32(c); 
-               } 
-
+               }
                i2o_flush_reply(c,m);
-
-               dprintk(KERN_INFO "%s: Reset completed.\n", c->name);
        }
 
        /* If IopReset was rejected or didn't perform reset, try IopClear */
 
        i2o_status_get(c);
-       if (status[0] == 0x02 || c->status_block->iop_state != ADAPTER_STATE_RESET)
+       if (status[0] == I2O_CMD_REJECTED || 
+               c->status_block->iop_state != ADAPTER_STATE_RESET)
        {
                printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",c->name);
                i2o_clear_controller(c);
        }
+       else
+               dprintk(KERN_INFO "%s: Reset completed.\n", c->name);
 
        /* Enable other IOPs */
 
@@ -1598,7 +1593,7 @@ int i2o_status_get(struct i2o_controller *c)
        msg[3]=0;
        msg[4]=0;
        msg[5]=0;
-       msg[6]=virt_to_phys(c->status_block);
+       msg[6]=virt_to_bus(c->status_block);
        msg[7]=0;   /* 64bit host FIXME */
        msg[8]=sizeof(i2o_status_block); /* always 88 bytes */
 
@@ -1618,9 +1613,6 @@ int i2o_status_get(struct i2o_controller *c)
                barrier();
        }
 
-       /* Ok the reply has arrived. Fill in the important stuff */
-       c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
-
 #ifdef DRIVERDEBUG
        printk(KERN_INFO "%s: State = ", c->name);
        switch (c->status_block->iop_state) {
@@ -1678,11 +1670,11 @@ int i2o_hrt_get(struct i2o_controller *c)
                msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
                msg[3]= 0;
                msg[4]= (0xD0000000 | size);    /* Simple transaction */
-               msg[5]= virt_to_phys(c->hrt);   /* Dump it here */
+               msg[5]= virt_to_bus(c->hrt);    /* Dump it here */
 
                if ((ret = i2o_post_wait(c, msg, sizeof(msg), 20))) {
-                       printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n",
-                               c->name, ret);  
+                       printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",
+                               c->name, -ret); 
                        return ret;
                }
 
@@ -1730,18 +1722,20 @@ static int i2o_systab_send(struct i2o_controller *iop)
         * Private i/o space declaration  
         */
        msg[6] = 0x54000000 | sys_tbl_len;
-       msg[7] = virt_to_phys(sys_tbl);
+       msg[7] = virt_to_bus(sys_tbl);
        msg[8] = 0x54000000 | 0;
-       msg[9] = virt_to_phys(privmem);
+       msg[9] = virt_to_bus(privmem);
        msg[10] = 0xD4000000 | 0;
-       msg[11] = virt_to_phys(privio);
+       msg[11] = virt_to_bus(privio);
 
        if ((ret=i2o_post_wait(iop, msg, sizeof(msg), 120)))
-               printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n", 
-                       iop->name, ret);
+               printk(KERN_INFO "%s: Unable to set SysTab (status=%#x).\n", 
+                       iop->name, -ret);
        else
                dprintk(KERN_INFO "%s: SysTab set.\n", iop->name);
 
+       i2o_status_get(iop); // Entered READY state
+
        return ret;     
 
  }
@@ -1761,7 +1755,8 @@ static void __init i2o_sys_init()
                dprintk(KERN_INFO "Calling i2o_activate_controller for %s\n", 
                        iop->name);
                niop = iop->next;
-               i2o_activate_controller(iop);
+               if (i2o_activate_controller(iop) < 0)
+                       i2o_delete_controller(iop);
        }
 
        /* Active IOPs in HOLD state */
@@ -1784,8 +1779,10 @@ rebuild_sys_tab:
        for (iop = i2o_controller_chain; iop; iop = niop) {
                niop = iop->next;
                dprintk(KERN_INFO "Calling i2o_online_controller for %s\n", iop->name);
-               if (i2o_online_controller(iop) < 0)
+               if (i2o_online_controller(iop) < 0) {
+                       i2o_delete_controller(iop);     
                        goto rebuild_sys_tab;
+               }
        }
        
        /* Active IOPs now in OPERATIONAL state */
@@ -1835,17 +1832,12 @@ int i2o_activate_controller(struct i2o_controller *iop)
 
        if (i2o_status_get(iop) < 0) {
                printk(KERN_INFO "Unable to obtain status of IOP, attempting a reset.\n");
-               i2o_reset_controller(iop);
-               if (i2o_status_get(iop) < 0) {
-                       printk(KERN_ERR "%s: IOP not responding.\n", iop->name);
-                       i2o_delete_controller(iop);
+               if (i2o_reset_controller(iop) < 0)
                        return -1;
-               }
        }
 
        if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) {
                printk(KERN_CRIT "%s: hardware fault\n", iop->name);
-               i2o_delete_controller(iop);
                return -1;
        }
 
@@ -1855,37 +1847,26 @@ int i2o_activate_controller(struct i2o_controller *iop)
            iop->status_block->iop_state == ADAPTER_STATE_FAILED)
        {
                u32 m[MSG_FRAME_SIZE];
-               dprintk(KERN_INFO "%s: already running...trying to reset\n",
+               dprintk(KERN_INFO "%s: Already running, trying to reset\n",
                        iop->name);
 
                i2o_init_outbound_q(iop);
-               I2O_REPLY_WRITE32(iop,virt_to_phys(m));
+               I2O_REPLY_WRITE32(iop,virt_to_bus(m));
 
-               i2o_reset_controller(iop);                      
-
-               if (i2o_status_get(iop) < 0 || 
-                       iop->status_block->iop_state != ADAPTER_STATE_RESET)
-               {
-                       printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name);
-                       i2o_delete_controller(iop);
+               if (i2o_reset_controller(iop) < 0)
                        return -1;
-               }
        }
 
-       if (i2o_init_outbound_q(iop) < 0) {
-               i2o_delete_controller(iop);
+       if (i2o_init_outbound_q(iop) < 0)
                return -1;
-       }
 
        if (i2o_post_outbound_messages(iop)) 
                return -1;
 
        /* In HOLD state */
        
-       if (i2o_hrt_get(iop) < 0) {
-               i2o_delete_controller(iop);
+       if (i2o_hrt_get(iop) < 0)
                return -1;
-       }
 
        return 0;
 }
@@ -1909,29 +1890,28 @@ int i2o_init_outbound_q(struct i2o_controller *c)
 
        status = kmalloc(4,GFP_KERNEL);
        if (status==NULL) {
-               printk(KERN_ERR "%s: IOP reset failed - no free memory.\n",
+               printk(KERN_ERR "%s: Outbound Queue initialization failed - no free memory.\n",
                        c->name);
                return -ENOMEM;
        }
        memset(status, 0, 4);
 
-
        msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
        msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
        msg[2]= core_context;
-       msg[3]= 0x0106;                                         /* Transaction context */
-       msg[4]= 4096;                                                   /* Host page frame size */
+       msg[3]= 0x0106;                         /* Transaction context */
+       msg[4]= 4096;                           /* Host page frame size */
        /* Frame size is in words. Pick 128, its what everyone elses uses and
                other sizes break some adapters. */
        msg[5]= MSG_FRAME_SIZE<<16|0x80;        /* Outbound msg frame size and Initcode */
-       msg[6]= 0xD0000004;                                     /* Simple SG LE, EOB */
+       msg[6]= 0xD0000004;                     /* Simple SG LE, EOB */
        msg[7]= virt_to_bus(status);
 
        i2o_post_message(c,m);
        
        barrier();
        time=jiffies;
-       while(status[0]<0x02)
+       while(status[0] < I2O_CMD_REJECTED)
        {
                if((jiffies-time)>=30*HZ)
                {
@@ -1948,7 +1928,7 @@ int i2o_init_outbound_q(struct i2o_controller *c)
                barrier();
        }  
 
-       if(status[0] != I2O_CMD_OUTBOUND_INIT_COMPLETE)
+       if(status[0] != I2O_CMD_COMPLETED)
        {
                printk(KERN_ERR "%s: IOP outbound initialise failed.\n", c->name);
                kfree(status);
@@ -1970,7 +1950,7 @@ int i2o_post_outbound_messages(struct i2o_controller *c)
                        c->name);
                return -ENOMEM;
        }
-       m=virt_to_phys(c->page_frame);
+       m=virt_to_bus(c->page_frame);
 
        /* Post frames */
 
@@ -2012,8 +1992,8 @@ int i2o_lct_get(struct i2o_controller *c)
                msg[7] = virt_to_bus(c->lct);
 
                if ((ret=i2o_post_wait(c, msg, sizeof(msg), 120))) {
-                       printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", 
-                               c->name, ret);  
+                       printk(KERN_ERR "%s: LCT Get failed (status=%#x.\n", 
+                               c->name, -ret); 
                        return ret;
                }
 
@@ -2057,26 +2037,20 @@ int i2o_lct_notify(struct i2o_controller *c)
  */
 int i2o_online_controller(struct i2o_controller *iop)
 {
-       if (i2o_systab_send(iop) < 0) {
-               i2o_delete_controller(iop);
+       if (i2o_systab_send(iop) < 0)
                return -1;
-       }
 
        /* In READY state */
 
        dprintk(KERN_INFO "Attempting to enable iop%d\n", iop->unit);
-       if (i2o_enable_controller(iop) < 0) {
-               i2o_delete_controller(iop);
+       if (i2o_enable_controller(iop) < 0)
                return -1;
-       }
 
        /* In OPERATIONAL state  */
 
        dprintk(KERN_INFO "Attempting to get/parse lct iop%d\n", iop->unit);
-       if (i2o_lct_get(iop) < 0){
-               i2o_delete_controller(iop);
+       if (i2o_lct_get(iop) < 0)
                return -1;
-       }
 
        return 0;
 }
@@ -2147,7 +2121,7 @@ static int i2o_build_sys_table(void)
                sys_tbl->iops[count].iop_capabilities = 
                                iop->status_block->iop_capabilities;
                sys_tbl->iops[count].inbound_low = 
-                               (u32)virt_to_phys(iop->post_port);
+                               (u32)virt_to_bus(iop->post_port);
                sys_tbl->iops[count].inbound_high = 0;  // TODO: 64-bit support
 
                count++;
@@ -2241,7 +2215,7 @@ int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
 
 #ifdef DRIVERDEBUG
        if(status == -ETIMEDOUT)
-               printk(KERN_INFO "POST WAIT TIMEOUT\n");
+               printk(KERN_INFO "%s: POST WAIT TIMEOUT\n",c->name);
 #endif
 
        /* 
@@ -2305,26 +2279,6 @@ static void i2o_post_wait_complete(u32 context, int status)
        printk(KERN_DEBUG "i2o_post_wait reply after timeout!\n");
 }
 
-/*
- *     Issue UTIL_CLAIM or UTIL_RELEASE messages
- */
-static int i2o_issue_claim(struct i2o_controller *c, int tid, int context, 
-                               int onoff, u32 type)
-{
-       u32 msg[5];
-
-       msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
-       if(onoff)
-               msg[1] = I2O_CMD_UTIL_CLAIM << 24 | HOST_TID<<12 | tid;
-       else    
-               msg[1] = I2O_CMD_UTIL_RELEASE << 24 | HOST_TID << 12 | tid;
-
-       msg[3] = 0;
-       msg[4] = type;
-       
-       return i2o_post_wait(c, msg, sizeof(msg), 30);
-}
-
 /*     Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
  *
  *     This function can be used for all UtilParamsGet/Set operations.
@@ -2541,44 +2495,69 @@ int i2o_row_add_table(struct i2o_controller *iop, int tid,
        return size;
 }
 
-/*
- *     Delete rows from a table group.
- */ 
-int i2o_row_delete_table(struct i2o_controller *iop, int tid,
-                   int group, int keycount, void *keys, int keyslen)
-{
-       u16 *opblk; 
-       u8  resblk[32]; /* min 8 bytes for header */
-       int size;
 
-       opblk = kmalloc(keyslen+64, GFP_KERNEL);
-       if (opblk == NULL)
-       {
-               printk(KERN_ERR "i2o: no memory for operation buffer.\n");
-               return -ENOMEM;
-       }
-
-       opblk[0] = 1;                   /* operation count */
-       opblk[1] = 0;                   /* pad */
-       opblk[2] = I2O_PARAMS_ROW_DELETE;
-       opblk[3] = group;       
-       opblk[4] = keycount;
-       memcpy(opblk+5, keys, keyslen);
-
-       size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid,
-                               opblk, 10+keyslen, resblk, sizeof(resblk));
+/*
+ * Used for error reporting/debugging purposes.
+ * Following fail status are common to all classes.
+ * The preserved message must be handled in the reply handler. 
+ */
+void i2o_report_fail_status(u8 req_status, u32* msg)
+{
+       static char *FAIL_STATUS[] = { 
+               "0x80",                         /* not used */
+               "SERVICE_SUSPENDED",            /* 0x81 */
+               "SERVICE_TERMINATED",           /* 0x82 */
+               "CONGESTION",
+               "FAILURE",
+               "STATE_ERROR",
+               "TIME_OUT",
+               "ROUTING_FAILURE",
+               "INVALID_VERSION",
+               "INVALID_OFFSET",
+               "INVALID_MSG_FLAGS",
+               "FRAME_TOO_SMALL",
+               "FRAME_TOO_LARGE",
+               "INVALID_TARGET_ID",
+               "INVALID_INITIATOR_ID",
+               "INVALID_INITIATOR_CONTEX",     /* 0x8F */
+               "UNKNOWN_FAILURE"               /* 0xFF */
+       };
 
-       kfree(opblk);
-       return size;
+       if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
+               printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.", req_status);
+       else
+               printk("TRANSPORT_%s.\n", FAIL_STATUS[req_status & 0x0F]);
+
+       /* Dump some details */
+
+       printk(KERN_ERR "  InitiatorId = %d, TargetId = %d\n",
+               (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF); 
+       printk(KERN_ERR "  LowestVersion = 0x%02X, HighestVersion = 0x%02X\n",
+               (msg[4] >> 8) & 0xFF, msg[4] & 0xFF);
+       printk(KERN_ERR "  FailingHostUnit = 0x%04X,  FailingIOP = 0x%03X\n",
+               msg[5] >> 16, msg[5] & 0xFFF);
+
+       printk(KERN_ERR "  Severity:  0x%02X ", (msg[4] >> 16) & 0xFF); 
+       if (msg[4] & (1<<16))
+               printk("(FormatError), "
+                       "this msg can never be delivered/processed.\n");
+       if (msg[4] & (1<<17))
+               printk("(PathError), "
+                       "this msg can no longer be delivered/processed.\n");
+       if (msg[4] & (1<<18))
+               printk("(PathState), "
+                       "the system state does not allow delivery.\n");
+       if (msg[4] & (1<<19))
+               printk("(Congestion), resources temporarily not available;"
+                       "do not retry immediately.\n");
 }
 
 /*
- * Used for error reporting/debugging purposes
+ * Used for error reporting/debugging purposes.
+ * Following reply status are common to all classes.
  */
 void i2o_report_common_status(u8 req_status)
 {
-       /* the following reply status strings are common to all classes */
-
        static char *REPLY_STATUS[] = { 
                "SUCCESS", 
                "ABORT_DIRTY", 
@@ -2595,23 +2574,18 @@ void i2o_report_common_status(u8 req_status)
        };
 
        if (req_status > I2O_REPLY_STATUS_PROGRESS_REPORT)
-               printk("%0#4x / ", req_status);
+               printk("RequestStatus = %0#2x", req_status);
        else
-               printk("%s / ", REPLY_STATUS[req_status]);
-       
-       return;
+               printk("%s", REPLY_STATUS[req_status]);
 }
 
 /*
- * Used for error reporting/debugging purposes
+ * Used for error reporting/debugging purposes.
+ * Following detailed status are valid  for executive class, 
+ * utility class, DDM class and for transaction error replies.
  */
 static void i2o_report_common_dsc(u16 detailed_status)
 {
-       /* The following detailed statuscodes are valid 
-          - for executive class, utility class, DDM class and
-          - for transaction error replies
-       */      
-
        static char *COMMON_DSC[] = { 
                "SUCCESS",
                "0x01",                         // not used
@@ -2645,11 +2619,9 @@ static void i2o_report_common_dsc(u16 detailed_status)
        };
 
        if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE)
-               printk("%0#4x.\n", detailed_status);
+               printk(" / DetailedStatus = %0#4x.\n", detailed_status);
        else
-               printk("%s.\n", COMMON_DSC[detailed_status]);
-
-       return;
+               printk(" / %s.\n", COMMON_DSC[detailed_status]);
 }
 
 /*
@@ -2680,11 +2652,9 @@ static void i2o_report_lan_dsc(u16 detailed_status)
        };
 
        if (detailed_status > I2O_DSC_INVALID_REQUEST)
-               printk("%0#4x.\n", detailed_status);
+               printk(" / %0#4x.\n", detailed_status);
        else
-               printk("%s.\n", LAN_DSC[detailed_status]);
-
-       return; 
+               printk(" / %s.\n", LAN_DSC[detailed_status]);
 }
 
 /*
@@ -2736,10 +2706,8 @@ static void i2o_report_util_cmd(u8 cmd)
                printk("UTIL_REPLY_FAULT_NOTIFY, ");
                break;
        default:
-               printk("%0#2x, ",cmd);  
+               printk("Cmd = %0#2x, ",cmd);    
        }
-
-       return; 
 }
 
 /*
@@ -2848,10 +2816,8 @@ static void i2o_report_exec_cmd(u8 cmd)
                printk("EXEC_SYS_TAB_SET, ");
                break;
        default:
-               printk("%02x, ",cmd);   
+               printk("Cmd = %#02x, ",cmd);    
        }
-
-       return; 
 }
 
 /*
@@ -2876,51 +2842,48 @@ static void i2o_report_lan_cmd(u8 cmd)
                printk("LAN_SUSPEND, ");
                break;
        default:
-               printk("%02x, ",cmd);   
+               printk("Cmd = %0#2x, ",cmd);    
        }       
-
-       return;
 }
 
 /*
- * Used for error reporting/debugging purposes
+ * Used for error reporting/debugging purposes.
+ * Report Cmd name, Request status, Detailed Status.
  */
-void i2o_report_status(const char *severity, const char *module, u32 *msg)
+void i2o_report_status(const char *severity, const char *str, u32 *msg)
 {
        u8 cmd = (msg[1]>>24)&0xFF;
        u8 req_status = (msg[4]>>24)&0xFF;
        u16 detailed_status = msg[4]&0xFFFF;
        struct i2o_handler *h = i2o_handlers[msg[2] & (MAX_I2O_MODULES-1)];
 
-       printk("%s%s: ", severity, module);
+       printk("%s%s: ", severity, str);
 
-       switch (h->class) {     
-               case I2O_CLASS_EXECUTIVE:
-                       if (cmd < 0x1F) {               // Utility cmd
-                               i2o_report_util_cmd(cmd);
-                               i2o_report_common_status(req_status);
-                               i2o_report_common_dsc(detailed_status);
-                       }
-                       if (cmd >= 0xA0 && cmd <= 0xEF) { // Executive cmd
-                               i2o_report_exec_cmd(cmd);
-                               i2o_report_common_status(req_status);
-                               i2o_report_common_dsc(detailed_status);
-                       }
-               break;
+       if (cmd < 0x1F)                         // Utility cmd
+               i2o_report_util_cmd(cmd);
+       
+       else if (cmd >= 0xA0 && cmd <= 0xEF)    // Executive cmd
+               i2o_report_exec_cmd(cmd);
+       
+       else if (h->class == I2O_CLASS_LAN && cmd >= 0x30 && cmd <= 0x3F)
+               i2o_report_lan_cmd(cmd);        // LAN cmd
+       else
+               printk("Cmd = %0#2x, ", cmd);   // Other cmds
 
-               case I2O_CLASS_LAN:
-                       i2o_report_lan_cmd(cmd);
-                       i2o_report_common_status(req_status);           
-                       i2o_report_lan_dsc(detailed_status);
-               break;
-/*
-               case I2O_CLASS_RANDOM_BLOCK_STORAGE:
-               break;
-*/     
-               default:        
-                       printk(KERN_INFO "%02x, %02x / %04x.\n", 
-                               cmd, req_status, detailed_status);
+       if (msg[0] & MSG_FAIL) {
+               i2o_report_fail_status(req_status, msg);
+               return;
        }
+       
+       i2o_report_common_status(req_status);
+
+       if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF))
+               i2o_report_common_dsc(detailed_status);
+               
+       if (h->class == I2O_CLASS_LAN && cmd >= 0x30 && cmd <= 0x3F)
+               i2o_report_lan_dsc(detailed_status);
+       else
+               printk(" / DetailedStatus = %0#4x.\n", detailed_status); 
 }
 
 /* Used to dump a message to syslog during debugging */
@@ -3005,7 +2968,6 @@ EXPORT_SYMBOL(i2o_set_scalar);
 EXPORT_SYMBOL(i2o_query_table);
 EXPORT_SYMBOL(i2o_clear_table);
 EXPORT_SYMBOL(i2o_row_add_table);
-EXPORT_SYMBOL(i2o_row_delete_table);
 EXPORT_SYMBOL(i2o_issue_params);
 
 EXPORT_SYMBOL(i2o_event_register);
@@ -3013,6 +2975,7 @@ EXPORT_SYMBOL(i2o_event_ack);
 
 EXPORT_SYMBOL(i2o_report_status);
 EXPORT_SYMBOL(i2o_dump_message);
+
 EXPORT_SYMBOL(i2o_get_class_name);
 
 MODULE_AUTHOR("Red Hat Software");
index 10b6821d91884110abdbecb7891643db986f1b67..90b252041ebc0bc60f28ae7a459a1321360d776c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     drivers/i2o/i2o_lan.c
  *
- *     I2O LAN CLASS OSM               April 3rd 2000
+ *     I2O LAN CLASS OSM               May  4th 2000
  *
  *     (C) Copyright 1999, 2000        University of Helsinki,
  *                                     Department of Computer Science
@@ -22,8 +22,7 @@
  *                     in Gigabit Eth environment (using SysKonnect's DDM)
  *                     in Fast Ethernet environment (using Intel 82558 DDM)
  *
- *     TODO:           check error checking / timeouts
- *                     code / test for other LAN classes
+ *     TODO:           tests for other LAN classes (Token Ring, Fibre Channel)
  */
 
 #include <linux/config.h>
@@ -62,8 +61,8 @@
 static u32 max_buckets_out = I2O_LAN_MAX_BUCKETS_OUT;
 static u32 bucket_thresh   = I2O_LAN_BUCKET_THRESH;
 static u32 rx_copybreak    = I2O_LAN_RX_COPYBREAK;
-static tx_batch_mode      = I2O_LAN_TX_BATCH_MODE;
-static i2o_event_mask      = I2O_LAN_EVENT_MASK;
+static u8  tx_batch_mode   = I2O_LAN_TX_BATCH_MODE;
+static u32 i2o_event_mask  = I2O_LAN_EVENT_MASK;
 
 #define MAX_LAN_CARDS 16
 static struct net_device *i2o_landevs[MAX_LAN_CARDS+1];
@@ -139,8 +138,7 @@ static void i2o_lan_handle_failure(struct net_device *dev, u32 *msg)
        struct sk_buff *skb = NULL;
        u8 le_flag;
 
-// To be added to i2o_core.c
-//     i2o_report_failure(KERN_INFO, iop, dev->name, msg);
+       i2o_report_status(KERN_INFO, dev->name, msg);
 
        /* If PacketSend failed, free sk_buffs reserved by upper layers */
 
@@ -190,8 +188,7 @@ static void i2o_lan_handle_transaction_error(struct net_device *dev, u32 *msg)
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
        struct sk_buff *skb;
 
-// To be added to i2o_core.c
-//     i2o_report_transaction_error(KERN_INFO, dev->name, msg);
+       i2o_report_status(KERN_INFO, dev->name, msg);
 
        /* If PacketSend was rejected, free sk_buff reserved by upper layers */
 
@@ -253,17 +250,15 @@ static void i2o_lan_send_post_reply(struct i2o_handler *h,
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
        u8 trl_count  = msg[3] & 0x000000FF;
 
-#ifdef DRIVERDEBUG
-       i2o_report_status(KERN_INFO, dev->name, msg);
-#endif
-
        if ((msg[4] >> 24) != I2O_REPLY_STATUS_SUCCESS) {
                if (i2o_lan_handle_status(dev, msg))
                        return;
-
-               /* Else we get pending transmit request(s) back */
        }
 
+#ifdef DRIVERDEBUG
+       i2o_report_status(KERN_INFO, dev->name, msg);
+#endif
+
        /* DDM has handled transmit request(s), free sk_buffs */
 
        while (trl_count) {
@@ -284,7 +279,7 @@ static void i2o_lan_send_post_reply(struct i2o_handler *h,
  * i2o_lan_receive_post_reply(): Callback function to process incoming packets.
  */
 static void i2o_lan_receive_post_reply(struct i2o_handler *h,
-                                      struct i2o_controller *iop, struct i2o_message *m)
+                       struct i2o_controller *iop, struct i2o_message *m)
 {
        u32 *msg = (u32 *)m;
        u8 unit  = (u8)(msg[2]>>16); // InitiatorContext
@@ -297,10 +292,6 @@ static void i2o_lan_receive_post_reply(struct i2o_handler *h,
        struct sk_buff *skb, *old_skb;
        unsigned long flags = 0;
 
-#ifdef DRIVERDEBUG
-       i2o_report_status(KERN_INFO, dev->name, msg);
-#endif
-
        if ((msg[4] >> 24) != I2O_REPLY_STATUS_SUCCESS) {
                if (i2o_lan_handle_status(dev, msg))
                        return;
@@ -313,44 +304,46 @@ static void i2o_lan_receive_post_reply(struct i2o_handler *h,
                        return;
                }
 
-               /* Which DetailedStatusCodes need special treatment? */
+               /* If other DetailedStatusCodes need special code, add it here */
        }
 
+#ifdef DRIVERDEBUG
+       i2o_report_status(KERN_INFO, dev->name, msg);
+#endif
+
        /* Else we are receiving incoming post. */
 
        while (trl_count--) {
                skb = (struct sk_buff *)bucket->context;
                packet = (struct i2o_packet_info *)bucket->packet_info;
                atomic_dec(&priv->buckets_out);
-#if 0
-/* Is this enough? If we get erroneous bucket, we can't assume that skb could
- * be reused, can we?
- */
 
-               /* Should we optimise these ifs away from the fast path? -taneli */
-               if (packet->flags & 0x0f) {
+               /* Sanity checks: Any weird characteristics in bucket? */
 
+               if (packet->flags & 0x0f || ! packet->flags & 0x40) {
                        if (packet->flags & 0x01)
-                               printk(KERN_WARNING "%s: packet with errors.\n", dev->name);
-                       if (packet->flags & 0x0c)
-                               /* This actually means that the hw is b0rken, since we
-                                  have asked it to not send fragmented packets. */
-                               printk(KERN_DEBUG "%s: multi-bucket packets not supported!\n", dev->name);
-                       bucket++;
-                       if (skb)
-                               dev_kfree_skb_irq(skb);
-                       continue;
-               }
+                               printk(KERN_WARNING "%s: packet with errors, error code=0x%02x.\n",
+                                       dev->name, packet->status & 0xff);
+
+                       /* The following shouldn't happen, unless parameters in
+                        * LAN_OPERATION group are changed during the run time.
+                        */
+                        if (packet->flags & 0x0c)
+                               printk(KERN_DEBUG "%s: multi-bucket packets not supported!\n", 
+                                       dev->name);
+                                       
+                       if (! packet->flags & 0x40)
+                               printk(KERN_DEBUG "%s: multiple packets in a bucket not supported!\n", 
+                                       dev->name);
+
+                       dev_kfree_skb_irq(skb);
 
-               if (packet->status & 0xff) {
-                       /* Silently discard, unless debugging. */
-                       dprintk(KERN_DEBUG "%s: toasted packet received.\n", dev->name);
                        bucket++;
-                       if (skb)
-                               dev_kfree_skb_irq(skb);
                        continue;
                }
-#endif
+
+               /* Copy short packet to a new skb */
+               
                if (packet->len < priv->rx_copybreak) {
                        old_skb = skb;
                        skb = (struct sk_buff *)dev_alloc_skb(packet->len+2);
@@ -366,13 +359,17 @@ static void i2o_lan_receive_post_reply(struct i2o_handler *h,
                                priv->i2o_fbl[++priv->i2o_fbl_tail] = old_skb;
                        else
                                dev_kfree_skb_irq(old_skb);
+
                        spin_unlock_irqrestore(&priv->fbl_lock, flags);
                } else
                        skb_put(skb, packet->len);
 
+               /* Deliver to upper layers */
+
                skb->dev = dev;
                skb->protocol = priv->type_trans(skb, dev);
                netif_rx(skb);
+
                dev->last_rx = jiffies;
 
                dprintk(KERN_INFO "%s: Incoming packet (%d bytes) delivered "
@@ -387,7 +384,7 @@ static void i2o_lan_receive_post_reply(struct i2o_handler *h,
                       dev->name, atomic_read(&priv->buckets_out));
 #endif
 
-       /* If DDM has already consumed bucket_tresh buckets, post new ones */
+       /* If DDM has already consumed bucket_thresh buckets, post new ones */
 
        if (atomic_read(&priv->buckets_out) <= priv->max_buckets_out - priv->bucket_thresh) {
                i2o_post_buckets_task.data = (void *)dev;
@@ -409,10 +406,6 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
        u8 unit  = (u8)(msg[2]>>16); // InitiatorContext
        struct net_device *dev = i2o_landevs[unit];
 
-#ifdef DRIVERDEBUG
-       i2o_report_status(KERN_INFO, dev->name, msg);
-#endif
-
        if ((msg[4] >> 24) != I2O_REPLY_STATUS_SUCCESS) {
                if (i2o_lan_handle_status(dev, msg))
                        return;
@@ -420,6 +413,10 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
                /* This should NOT be reached */
        }
 
+#ifdef DRIVERDEBUG
+       i2o_report_status(KERN_INFO, dev->name, msg);
+#endif
+
        switch (msg[1] >> 24) {
        case LAN_RESET:
        case LAN_SUSPEND:
@@ -465,6 +462,7 @@ static void i2o_lan_handle_event(struct net_device *dev, u32 *msg)
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
        struct i2o_device *i2o_dev = priv->i2o_dev;
        struct i2o_controller *iop = i2o_dev->controller;
+       u32 max_evt_data_size =iop->status_block->inbound_frame_size-5;
        struct i2o_reply {
                u8  version_offset;
                u8  msg_flags;
@@ -475,7 +473,7 @@ static void i2o_lan_handle_event(struct net_device *dev, u32 *msg)
                u32 initiator_context;
                u32 transaction_context;
                u32 evt_indicator;
-               u32 data[(iop->inbound_size - 20) / 4]; /* max */
+               u32 data[max_evt_data_size]; /* max */
        } *evt = (struct i2o_reply *)msg;
        int evt_data_len = (evt->msg_size - 5) * 4;     /* real */
 
@@ -534,8 +532,8 @@ static void i2o_lan_handle_event(struct net_device *dev, u32 *msg)
 
        case I2O_EVT_IND_FIELD_MODIFIED: {
                u16 *work16 = (u16 *)evt->data;
-               printk("Group 0x%04x, field %d changed.\n", work16[0],
-                      work16[1]);
+               printk("Group 0x%04x, field %d changed.\n", work16[0], work16[1]);
+
                break;
        }
 
@@ -564,7 +562,7 @@ static void i2o_lan_handle_event(struct net_device *dev, u32 *msg)
                break;
 
        default:
-               printk("Event Indicator = 0x%08x.\n", evt->evt_indicator);
+               printk("0x%08x. No handler.\n", evt->evt_indicator);
        }
 
        /* Note: EventAck necessary only for events that cause the device to
@@ -660,7 +658,7 @@ static int i2o_lan_reset(struct net_device *dev)
        msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid;
        msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
        msg[3] = 0;                              // TransactionContext
-       msg[4] = 0;                             // keep posted buckets
+       msg[4] = 0;                              // Keep posted buckets
 
        if (i2o_post_this(iop, msg, sizeof(msg)) < 0)
                return -ETIMEDOUT;
@@ -694,43 +692,22 @@ static int i2o_lan_suspend(struct net_device *dev)
 }
 
 /*
- * i2o_set_batch_mode(): Set DDM into batch mode.
+ * i2o_set_ddm_parameters:
+ * These settings are done to ensure proper initial values for DDM.
+ * They can be changed via proc file system or vai configuration utility.
  */
-static void i2o_set_batch_mode(struct net_device *dev)
+static void i2o_set_ddm_parameters(struct net_device *dev)
 {
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
        struct i2o_device *i2o_dev = priv->i2o_dev;
        struct i2o_controller *iop = i2o_dev->controller;
        u32 val;
 
-       /* Set defaults LAN_BATCH_CONTROL attributes */
-       /* May be changed via /proc or Configuration Utility */
-
-       val = 0x00000000; // enable batch mode, toggle automatically
-       if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0003, 0, &val, sizeof(val)) <0)
-               printk(KERN_WARNING "%s: Unable to enter I2O LAN batch mode.\n",
-                      dev->name);
-       else
-               dprintk(KERN_INFO "%s: I2O LAN batch mode enabled.\n", dev->name);
-
-       /* Set LAN_OPERATION attributes */
-
-#ifdef DRIVERDEBUG
-/* Added for testing: this will be removed */
-       val = 0x00000003;                       // 1 = UserFlags
-       if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0004, 1, &val, sizeof(val)) < 0)
-               printk(KERN_WARNING "%s: Can't enable ErrorReporting & BadPacketHandling.\n",
-                      dev->name);
-       else
-               dprintk(KERN_INFO "%s: ErrorReporting enabled, "
-                       "BadPacketHandling enabled.\n", dev->name);
-#endif /* DRIVERDEBUG */
-
        /*
-        * When PacketOrphanlimit is same as the maximum packet length,
+        * When PacketOrphanlimit is set to the maximum packet length,
         * the packets will never be split into two separate buckets
         */
-       val = dev->mtu + dev->hard_header_len; // 2 = PacketOrphanLimit
+       val = dev->mtu + dev->hard_header_len;
        if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0004, 2, &val, sizeof(val)) < 0)
                printk(KERN_WARNING "%s: Unable to set PacketOrphanLimit.\n",
                       dev->name);
@@ -738,6 +715,15 @@ static void i2o_set_batch_mode(struct net_device *dev)
                dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d.\n",
                        dev->name, val);
 
+       /* When RxMaxPacketsBucket = 1, DDM puts only one packet into bucket */
+
+       val = 1;
+       if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0008, 4, &val, sizeof(val)) <0)
+               printk(KERN_WARNING "%s: Unable to set RxMaxPacketsBucket.\n",
+                      dev->name);
+       else
+               dprintk(KERN_INFO "%s: RxMaxPacketsBucket set to &d.\n", 
+                       dev->name, val);
        return;
 }
 
@@ -779,7 +765,7 @@ static int i2o_lan_open(struct net_device *dev)
        priv->i2o_fbl_tail = -1;
        priv->send_active = 0;
 
-       i2o_set_batch_mode(dev);
+       i2o_set_ddm_parameters(dev);
        i2o_lan_receive_post(dev);
 
        netif_start_queue(dev);
@@ -795,9 +781,9 @@ static int i2o_lan_close(struct net_device *dev)
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
        struct i2o_device *i2o_dev = priv->i2o_dev;
        struct i2o_controller *iop = i2o_dev->controller;
+       int ret = 0;
 
        netif_stop_queue(dev);
-
        i2o_lan_suspend(dev);
 
        if (i2o_event_register(iop, i2o_dev->lct_data.tid,
@@ -805,19 +791,20 @@ static int i2o_lan_close(struct net_device *dev)
                printk(KERN_WARNING "%s: Unable to clear the event mask.\n",
                       dev->name);
 
+       while (priv->i2o_fbl_tail >= 0)
+               dev_kfree_skb(priv->i2o_fbl[priv->i2o_fbl_tail--]);
+
+       kfree(priv->i2o_fbl);
+
        if (i2o_release_device(i2o_dev, &i2o_lan_handler)) {
                printk(KERN_WARNING "%s: Unable to unclaim I2O LAN device "
                       "(tid=%d).\n", dev->name, i2o_dev->lct_data.tid);
-               return -EBUSY;
+               ret = -EBUSY;
        }
 
-       while (priv->i2o_fbl_tail >= 0)
-               dev_kfree_skb(priv->i2o_fbl[priv->i2o_fbl_tail--]);
-       kfree(priv->i2o_fbl);
-
        MOD_DEC_USE_COUNT;
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -829,12 +816,12 @@ static void i2o_lan_tx_timeout(struct net_device *dev)
                netif_start_queue(dev);
 }
 
-#define batching(x, cond) ( (x)->tx_batch_mode==1 || ((x)->tx_batch_mode==2 && (cond)) )
-
 /*
- * Batch send packets. Both i2o_lan_sdu_send and i2o_lan_packet_send
- * use this. I'm still not pleased. If you come up with
- * something better, please tell me. -taneli
+ * i2o_lan_batch_send(): Send packets in batch. 
+ * Both i2o_lan_sdu_send and i2o_lan_packet_send use this.
+ *
+ * This is a coarse first approximation for the tx_batching.
+ * If you come up with something better, please tell me. -taneli 
  */
 static void i2o_lan_batch_send(struct net_device *dev)
 {
@@ -848,20 +835,16 @@ static void i2o_lan_batch_send(struct net_device *dev)
                dprintk(KERN_DEBUG "%s: %d packets sent.\n", dev->name, priv->tx_count);
                priv->tx_count = 0;
        }
-       spin_unlock_irq(&priv->tx_lock);
-
        priv->send_active = 0;
+       spin_unlock_irq(&priv->tx_lock);
 }
 
+#ifdef CONFIG_NET_FC
 /*
  * i2o_lan_sdu_send(): Send a packet, MAC header added by the DDM.
  * Must be supported by Fibre Channel, optional for Ethernet/802.3,
  * Token Ring, FDDI
  */
-
-/*
- * This is a coarse first approximation. Needs testing. Any takers? -taneli
- */
 static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
 {
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -876,6 +859,16 @@ static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
        priv->tx_count++;
        atomic_inc(&priv->tx_out);
 
+       /* 
+        * If tx_batch_mode = 0x00 forced to immediate mode
+        * If tx_batch_mode = 0x01 forced to batch mode
+        * If tx_batch_mode = 0x10 switch automatically, current mode immediate
+        * If tx_batch_mode = 0x11 switch automatically, current mode batch
+        *      If gap between two packets is > 2 ticks, switch to immediate
+        */
+       if (priv->tx_batch_mode >> 1) // switch automatically
+               priv->tx_batch_mode = tickssofar ? 0x02 : 0x03;
+
        if (priv->tx_count == 1) {
                m = I2O_POST_READ32(iop);
                if (m == 0xFFFFFFFF) {
@@ -888,14 +881,15 @@ static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
                __raw_writel(NINE_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4, msg);
                __raw_writel(LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid, msg+1);
                __raw_writel(priv->unit << 16 | lan_send_context, msg+2); // InitiatorContext
-               __raw_writel(1 << 3, msg+3);                         // TransmitControlWord
+               __raw_writel(1 << 30 | 1 << 3, msg+3);                    // TransmitControlWord
 
                __raw_writel(0xD7000000 | skb->len, msg+4);          // MAC hdr included
                __raw_writel((u32)skb, msg+5);                       // TransactionContext
                __raw_writel(virt_to_bus(skb->data), msg+6);
                __raw_writel((u32)skb->mac.raw, msg+7);
                __raw_writel((u32)skb->mac.raw+4, msg+8);
-               if (batching(priv, !tickssofar) && !priv->send_active) {
+
+               if ((priv->tx_batch_mode & 0x01) && !priv->send_active) {
                        priv->send_active = 1;
                        queue_task(&priv->i2o_batch_send_task, &tq_scheduler);
                }
@@ -915,7 +909,7 @@ static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
 
        /* If tx not in batch mode or frame is full, send immediatelly */
 
-       if (!batching(priv, !tickssofar) || priv->tx_count == priv->sgl_max) {
+       if (!(priv->tx_batch_mode & 0x01) || priv->tx_count == priv->sgl_max) {
                dev->trans_start = jiffies;
                i2o_post_message(iop, priv->m);
                dprintk(KERN_DEBUG "%s: %d packets sent.\n", dev->name, priv->tx_count);
@@ -930,6 +924,7 @@ static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
        spin_unlock_irq(&priv->tx_lock);
        return 0;
 }
+#endif CONFIG_NET_FC
 
 /*
  * i2o_lan_packet_send(): Send a packet as is, including the MAC header.
@@ -951,6 +946,16 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
        priv->tx_count++;
        atomic_inc(&priv->tx_out);
 
+       /* 
+        * If tx_batch_mode = 0x00 forced to immediate mode
+        * If tx_batch_mode = 0x01 forced to batch mode
+        * If tx_batch_mode = 0x10 switch automatically, current mode immediate
+        * If tx_batch_mode = 0x11 switch automatically, current mode batch
+        *      If gap between two packets is > 0 ticks, switch to immediate
+        */
+       if (priv->tx_batch_mode >> 1) // switch automatically
+               priv->tx_batch_mode = tickssofar ? 0x02 : 0x03;
+
        if (priv->tx_count == 1) {
                m = I2O_POST_READ32(iop);
                if (m == 0xFFFFFFFF) {
@@ -963,12 +968,14 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
                __raw_writel(SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4, msg);
                __raw_writel(LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data.tid, msg+1);
                __raw_writel(priv->unit << 16 | lan_send_context, msg+2); // InitiatorContext
-               __raw_writel(1 << 3, msg+3);                         // TransmitControlWord
-
+               __raw_writel(1 << 30 | 1 << 3, msg+3);                    // TransmitControlWord
+                       // bit 30: reply as soon as transmission attempt is complete
+                       // bit 3: Supress CRC generation
                __raw_writel(0xD5000000 | skb->len, msg+4);          // MAC hdr included
                __raw_writel((u32)skb, msg+5);                       // TransactionContext
                __raw_writel(virt_to_bus(skb->data), msg+6);
-               if (batching(priv, !tickssofar) && !priv->send_active) {
+
+               if ((priv->tx_batch_mode & 0x01) && !priv->send_active) {
                        priv->send_active = 1;
                        queue_task(&priv->i2o_batch_send_task, &tq_scheduler);
                }
@@ -984,9 +991,9 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
                __raw_writel(virt_to_bus(skb->data), sgl_elem+2);
        }
 
-       /* If tx not in batch mode or frame is full, send immediatelly */
+       /* If tx is in immediate mode or frame is full, send now */
 
-       if (!batching(priv, !tickssofar) || priv->tx_count == priv->sgl_max) {
+       if (!(priv->tx_batch_mode & 0x01) || priv->tx_count == priv->sgl_max) {
                dev->trans_start = jiffies;
                i2o_post_message(iop, priv->m);
                dprintk(KERN_DEBUG"%s: %d packets sent.\n", dev->name, priv->tx_count);
@@ -1141,12 +1148,14 @@ static void i2o_lan_set_mc_list(struct net_device *dev)
        u32 max_size_mc_table;
        u32 mc_addr_group[64];
 
-// This isn't safe yet. Needs to be async.
+// This isn't safe yet in SMP. Needs to be async.
+// Seems to work in uniprocessor environment.
+
 return;
 
 //     read_lock_bh(&dev_mc_lock);
-//     spin_lock(&dev->xmit_lock);
-//     dev->xmit_lock_owner = smp_processor_id();
+       spin_lock(&dev->xmit_lock);
+       dev->xmit_lock_owner = smp_processor_id();
 
        if (i2o_query_scalar(iop, i2o_dev->lct_data.tid, 0x0001, -1,
                             &mc_addr_group, sizeof(mc_addr_group)) < 0 ) {
@@ -1212,15 +1221,13 @@ static struct tq_struct i2o_lan_set_mc_list_task = {
  *       Queue routine i2o_lan_set_mc_list() to be called later.
  *       Needs to be async.
  */
-
 static void i2o_lan_set_multicast_list(struct net_device *dev)
 {
-       if (!in_interrupt()) {
+       if (in_interrupt()) {
                i2o_lan_set_mc_list_task.data = (void *)dev;
                queue_task(&i2o_lan_set_mc_list_task, &tq_scheduler);
-       } else {
+       } else 
                i2o_lan_set_mc_list(dev);
-       }
 }
 
 /*
@@ -1236,10 +1243,20 @@ static int i2o_lan_change_mtu(struct net_device *dev, int new_mtu)
                             0x0000, 6, &max_pkt_size, 4) < 0)
                return -EFAULT;
 
-       if (new_mtu < 68 || max_pkt_size < new_mtu)
+       if (new_mtu < 68 || new_mtu > 9000 || new_mtu > max_pkt_size)
                return -EINVAL;
 
        dev->mtu = new_mtu;
+
+       i2o_lan_suspend(dev);           // to SUSPENDED state, return buckets
+
+       while (priv->i2o_fbl_tail >= 0) // free buffered buckets
+               dev_kfree_skb(priv->i2o_fbl[priv->i2o_fbl_tail--]);
+
+       i2o_lan_reset(dev);             // to OPERATIONAL state
+       i2o_set_ddm_parameters(dev);    // reset some parameters
+       i2o_lan_receive_post(dev);      // post new buckets (new size)
+
        return 0;
 }
 
@@ -1333,7 +1350,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
        priv = (struct i2o_lan_local *)dev->priv;
        priv->i2o_dev = i2o_dev;
        priv->type_trans = type_trans;
-       priv->sgl_max = (i2o_dev->controller->inbound_size - 16) / 12;
+       priv->sgl_max = (i2o_dev->controller->status_block->inbound_frame_size - 4) / 3;
        atomic_set(&priv->buckets_out, 0);
 
        /* Set default values for user configurable parameters */
@@ -1342,7 +1359,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
        priv->max_buckets_out = max_buckets_out;
        priv->bucket_thresh   = bucket_thresh;
        priv->rx_copybreak    = rx_copybreak;
-       priv->tx_batch_mode   = tx_batch_mode;
+       priv->tx_batch_mode   = tx_batch_mode & 0x03;
        priv->i2o_event_mask  = i2o_event_mask;
 
        priv->tx_lock         = SPIN_LOCK_UNLOCKED;
@@ -1360,7 +1377,6 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
                kfree(dev);
                return NULL;
        }
-
        dprintk(KERN_DEBUG "%s: hwaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
                dev->name, hw_addr[0], hw_addr[1], hw_addr[2], hw_addr[3],
                hw_addr[4], hw_addr[5]);
@@ -1415,9 +1431,9 @@ int __init i2o_lan_init(void)
        struct net_device *dev;
        int i;
 
-       printk(KERN_INFO "I2O LAN OSM (c) 1999 University of Helsinki.\n");
+       printk(KERN_INFO "I2O LAN OSM (C) 1999 University of Helsinki.\n");
 
-       /* Module params used as global defaults for private values */
+       /* Module params are used as global defaults for private values */
 
        if (max_buckets_out > I2O_LAN_MAX_BUCKETS_OUT)
                max_buckets_out = I2O_LAN_MAX_BUCKETS_OUT;
@@ -1547,7 +1563,7 @@ MODULE_PARM(bucket_thresh, "1-" __MODULE_STRING(I2O_LAN_MAX_BUCKETS_OUT) "i");
 MODULE_PARM_DESC(bucket_thresh, "Bucket post threshold (1-)");
 MODULE_PARM(rx_copybreak, "1-" "i");
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy only small frames (1-)");
-MODULE_PARM(tx_batch_mode, "0-1" "i");
-MODULE_PARM_DESC(tx_batch_mode, "0=Use immediate mode send, 1=Use batch mode send");
+MODULE_PARM(tx_batch_mode, "0-2" "i");
+MODULE_PARM_DESC(tx_batch_mode, "0=Send immediatelly, 1=Send in batches, 2=Switch automatically");
 
 #endif
index 72a87af2590af5ab1cf85c45a4a996f75e5088ce..17064a29a089eb6b4842d89667b2e62e2e905488 100644 (file)
 
 /* Default values for tunable parameters first */
 
-#define I2O_LAN_MAX_BUCKETS_OUT 256
+#define I2O_LAN_MAX_BUCKETS_OUT 96
 #define I2O_LAN_BUCKET_THRESH  18      /* 9 buckets in one message */
 #define I2O_LAN_RX_COPYBREAK   200
 #define I2O_LAN_TX_TIMEOUT     (1*HZ)
-#define I2O_LAN_TX_BATCH_MODE  1       /* 1=on, 0=off */
-#define I2O_LAN_EVENT_MASK     0       /* 0=None, 0xFFC00002=All */
+#define I2O_LAN_TX_BATCH_MODE  2       /* 2=automatic, 1=on, 0=off */
+#define I2O_LAN_EVENT_MASK     0;      /* 0=None, 0xFFC00002=All */
 
 /* LAN types */
 #define I2O_LAN_ETHERNET       0x0030
@@ -126,6 +126,7 @@ struct i2o_bucket_descriptor {
 struct i2o_lan_local {
        u8 unit;
        struct i2o_device *i2o_dev;
+
        struct fddi_statistics stats;   /* see also struct net_device_stats */
        unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
        atomic_t buckets_out;           /* nbr of unused buckets on DDM */
@@ -133,7 +134,7 @@ struct i2o_lan_local {
        u8 tx_count;                    /* packets in one TX message frame */
        u16 tx_max_out;                 /* DDM's Tx queue len */
        u8 sgl_max;                     /* max SGLs in one message frame */
-       u32 m;                          /* IOP address of msg frame */
+       u32 m;                          /* IOP address of the batch msg frame */
 
        struct tq_struct i2o_batch_send_task;
        int send_active;
index 16b8aaedc2b8ea084c12a555f13ef2df82907a32..0961d5624f7e1c1e4da057d7f5e3ec742023163e 100644 (file)
@@ -6,6 +6,7 @@
  *     
  *     Written by Alan Cox, Building Number Three Ltd
  *     Modified by Deepak Saxena <deepak@plexity.net>
+ *     Modified by Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -53,10 +54,10 @@ static void i2o_pci_dispose(struct i2o_controller *c)
        iounmap(((u8 *)c->post_port)-0x40);
 
 #ifdef CONFIG_MTRR
-       if(c->bus.pci.mtrr_reg0 > 0)
-               mtrr_del(c->bus.pci.mtrr_reg0, 0, 0);
-       if(c->bus.pci.mtrr_reg1 > 0)
-               mtrr_del(c->bus.pci.mtrr_reg1, 0, 0);
+       if(c->bus.pci.mtrr_reg0 > 0)
+               mtrr_del(c->bus.pci.mtrr_reg0, 0, 0);
+       if(c->bus.pci.mtrr_reg1 > 0)
+               mtrr_del(c->bus.pci.mtrr_reg1, 0, 0);
 #endif
 }
 
@@ -178,21 +179,21 @@ int __init i2o_pci_install(struct pci_dev *dev)
         * Enable Write Combining MTRR for IOP's memory region
         */
 #ifdef CONFIG_MTRR
-       c->bus.pci.mtrr_reg0 =
-                mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1);
+       c->bus.pci.mtrr_reg0 =
+               mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1);
 /*
 * If it is an INTEL i960 I/O processor then set the first 64K to Uncacheable
 * since the region contains the Messaging unit which shouldn't be cached.
 */
-       c->bus.pci.mtrr_reg1 = -1;
-       if(dev->vendor == PCI_VENDOR_ID_INTEL)
-        {
-       printk(KERN_INFO "i2o_pci: MTRR workaround for Intel i960 processor\n"); 
-       c->bus.pci.mtrr_reg1 =
-                mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
-        if(c->bus.pci.mtrr_reg1< 0)
-                        printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n");
-       }
+       c->bus.pci.mtrr_reg1 = -1;
+       if(dev->vendor == PCI_VENDOR_ID_INTEL)
+       {
+       printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n"); 
+       c->bus.pci.mtrr_reg1 =
+               mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
+       if(c->bus.pci.mtrr_reg1< 0)
+               printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n");
+       }
 
 #endif
 
index 8ae5d07ed434548bcf4c4c027218a34b25bc8a8c..ceddc07c3b91234917a58728486100eda5802862 100644 (file)
@@ -4356,12 +4356,11 @@ srom_command(u_int command, u_long addr)
 static void
 srom_address(u_int command, u_long addr, u_char offset)
 {
-    int i;
-    char a;
+    int i, a;
     
-    a = (char)(offset << 2);
+    a = offset << 2;
     for (i=0; i<6; i++, a <<= 1) {
-       srom_latch(command | ((a 0) ? DT_IN : 0), addr);
+       srom_latch(command | ((a & 0x80) ? DT_IN : 0), addr);
     }
     de4x5_us_delay(1);
     
index 3eb465eac53bfdb5f6f174d582a9ad3652196066..2aa2e5d1ac971ea0cae15080f336623209149a0b 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
index 739c3cf2fd4fa192fde08f9c4c918bd560a080f3..0fefb11ed4555e5cb414cacea106c5cfb1206c9e 100644 (file)
@@ -49,6 +49,7 @@ static const char *cardname = "smctr";
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/mca.h>
+#include <linux/delay.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 9d447dccfff557e2ec34f613db7bbbb97ff9742b..5d506258982ecef0a4efbee6ea85c3fd467bfff2 100644 (file)
@@ -1382,7 +1382,8 @@ routine */
  * Definitions for the field:
  * bic_type (Bus interface chip type)
  */
-#define BIC_NO_CHIP             0x0000  /* Bus interface chip not implemented */#define BIC_583_CHIP            0x0001  /* 83C583 bus interface chip */
+#define BIC_NO_CHIP             0x0000  /* Bus interface chip not implemented */
+#define BIC_583_CHIP            0x0001  /* 83C583 bus interface chip */
 #define BIC_584_CHIP            0x0002  /* 83C584 bus interface chip */
 #define BIC_585_CHIP            0x0003  /* 83C585 bus interface chip */
 #define BIC_593_CHIP            0x0004  /* 83C593 bus interface chip */
@@ -1486,7 +1487,8 @@ routine */
 
 #define MAX_8023_SIZE           1500    /* Max 802.3 size of frame. */
 #define DEFAULT_ERX_VALUE       4       /* Number of 16-byte blocks for 790B early Rx. */
-#define DEFAULT_ETX_VALUE       32      /* Number of bytes for 790B early Tx. */#define DEFAULT_TX_RETRIES      3       /* Number of transmit retries */
+#define DEFAULT_ETX_VALUE       32      /* Number of bytes for 790B early Tx. */
+#define DEFAULT_TX_RETRIES      3       /* Number of transmit retries */
 #define LPBK_FRAME_SIZE         1024    /* Default loopback frame for Rx calibration test. */
 #define MAX_LOOKAHEAD_SIZE      252     /* Max lookahead size for ethernet. */
 
index c48445d65b0bf022a057465536e204daaff32222..cac8329c3a68b4530bf80e1dced4d62bdc814823 100644 (file)
@@ -563,14 +563,10 @@ static volatile int main_running = 0;
 
 static __inline__ void run_main(void)
 {
-       unsigned long flags;
-       save_flags(flags);
-       cli();
        if (!main_running) {
                main_running = 1;
                NCR5380_main();
        }
-       restore_flags(flags);
 }
 
 #ifdef USLEEP
@@ -1224,7 +1220,6 @@ int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) {
         * sense data is only guaranteed to be valid while the condition exists.
         */
 
-       cli();
        if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
                LIST(cmd, hostdata->issue_queue);
                cmd->host_scribble = (unsigned char *) hostdata->issue_queue;
index 9cbab294901c5237bac5cd830ff815c1f00dd51b..e44bc79297a10df36582cdca45d5469786ba889c 100644 (file)
@@ -403,28 +403,28 @@ int i91u_detect(Scsi_Host_Template * tpnt)
                /* Initial tulip chip           */
                switch (i) {
                case 0:
-                       ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+                       ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
                        break;
                case 1:
-                       ok = request_irq(pHCB->HCS_Intr, i91u_intr1, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+                       ok = request_irq(pHCB->HCS_Intr, i91u_intr1, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
                        break;
                case 2:
-                       ok = request_irq(pHCB->HCS_Intr, i91u_intr2, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+                       ok = request_irq(pHCB->HCS_Intr, i91u_intr2, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
                        break;
                case 3:
-                       ok = request_irq(pHCB->HCS_Intr, i91u_intr3, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+                       ok = request_irq(pHCB->HCS_Intr, i91u_intr3, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
                        break;
                case 4:
-                       ok = request_irq(pHCB->HCS_Intr, i91u_intr4, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+                       ok = request_irq(pHCB->HCS_Intr, i91u_intr4, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
                        break;
                case 5:
-                       ok = request_irq(pHCB->HCS_Intr, i91u_intr5, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+                       ok = request_irq(pHCB->HCS_Intr, i91u_intr5, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
                        break;
                case 6:
-                       ok = request_irq(pHCB->HCS_Intr, i91u_intr6, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+                       ok = request_irq(pHCB->HCS_Intr, i91u_intr6, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
                        break;
                case 7:
-                       ok = request_irq(pHCB->HCS_Intr, i91u_intr7, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+                       ok = request_irq(pHCB->HCS_Intr, i91u_intr7, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg);
                        break;
                default:
                        i91u_panic("i91u: Too many host adapters\n");
index 5d9f2320189e89a3b03e4c73b3d49e567023d159..11fff73da0702f0dc695255654d8ca08044b2ab5 100644 (file)
@@ -71,7 +71,7 @@ obj-$(CONFIG_SOUND_MSNDCLAS)  += msnd.o msnd_classic.o
 obj-$(CONFIG_SOUND_MSNDPIN)    += msnd.o msnd_pinnacle.o
 obj-$(CONFIG_SOUND_VWSND)      += vwsnd.o
 obj-$(CONFIG_SOUND_NM256)      += nm256_audio.o ac97.o
-obj-$(CONFIG_SOUND_ICH)                += i810_audio.o ac97.o
+obj-$(CONFIG_SOUND_ICH)                += i810_audio.o ac97_codec.o
 obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
 obj-$(CONFIG_SOUND_CMPCI)      += cmpci.o
 obj-$(CONFIG_SOUND_ES1370)     += es1370.o
index ae866148bb7e053ef00b906e9f7b64397860bc6e..13e588c98530738e040f7634bb0bb5bc447f16e1 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/bitops.h>
 #include <linux/ac97_codec.h>
 #include <asm/uaccess.h>
 
index c96397ab2e0fd05b623432a0358c6cebf29660c8..76bfcc3c058098387edc62ee60c60673ab2281d3 100644 (file)
@@ -924,7 +924,10 @@ static void i810_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        status = inl(card->iobase + GLOB_STA);
        if(!(status & INT_MASK)) 
+       {
+               spin_unlock(&card->lock);
                return;  /* not for us */
+       }
 
 //     printk("Interrupt %X: ", status);
        if(status & (INT_PO|INT_PI|INT_MC))
index 5ba9236a325c7b7947c24958f5ce04a1183bf3bf..5290b42ed373834b1532116be32d54cc65d22bca 100644 (file)
@@ -643,10 +643,10 @@ static int __init probe_mad16(struct address_info *hw_config)
 static void __init attach_mad16(struct address_info *hw_config)
 {
 
-       static char     interrupt_bits[12] = {
+       static signed char     interrupt_bits[12] = {
                -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
        };
-       char bits;
+       signed char bits;
 
        static char     dma_bits[4] = {
                1, 2, 0, 3
index 13e45611173d2dd2f9f9d777efdb93944b83ad03..427167b3d759f27b89974115ab5c7c755e4e66b4 100644 (file)
@@ -40,6 +40,8 @@
  *  Thanks to Gaël Quéri and Alessandro Zummo for testing and fixes.
  *  Paul E. Laufer <pelaufer@csupomona.edu>
  *
+ * 06-05-2000 added another card. Daniel M. Newman <dmnewman@pobox.com>
+ *
  */
 
 #include <linux/config.h>
@@ -262,6 +264,11 @@ static struct {
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
                0,0,0,0,
                0,1,1,-1},
+       {"Sound Blaster 16",
+               ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
+               ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
+               0,0,0,0,
+               0,1,1,-1},
        {"Sound Blaster 16", 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
                ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
@@ -435,6 +442,11 @@ static struct {
                ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
                ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
                1,0,0,0},
+       {"Creative SB16 PnP", 
+               ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a), 
+               ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
+               0,0,0,0,
+               0,1,1,-1},
        {0}
 };
 
index 75b78a8b91614be7c29f94a4b5b7583b00a4844b..a1f462f3b34da4092ef72d387f8689a61df6f3dd 100644 (file)
 #include <linux/ac97_codec.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
+#include <linux/bitops.h>
 
 #include "trident.h"
 
index 98654440162871f2e84ccbdb0a1e5521041e19c9..c1d71750e53813b4b28814886fb8b17f8ebf728b 100644 (file)
@@ -276,7 +276,7 @@ static int __init probe_trix_sb(struct address_info *hw_config)
 
        int tmp;
        unsigned char conf;
-       static char irq_translate[] = {
+       static signed char irq_translate[] = {
                -1, -1, -1, 0, 1, 2, -1, 3
        };
 
@@ -346,7 +346,7 @@ static void __init attach_trix_mpu(struct address_info *hw_config)
 static int __init probe_trix_mpu(struct address_info *hw_config)
 {
        unsigned char conf;
-       static char irq_bits[] = {
+       static int irq_bits[] = {
                -1, -1, -1, 1, 2, 3, -1, 4, -1, 5
        };
 
index 4abff232c887feb21264ee787202c38dd0785305..49d818e21e71a071a2baa4c6b1b20ec02b192464 100644 (file)
@@ -363,20 +363,24 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        goto beyond_if;
                }
 
+               down(&current->mm->mmap_sem);
                error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
                        PROT_READ | PROT_EXEC,
                        MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
                        fd_offset);
+               up(&current->mm->mmap_sem);
 
                if (error != N_TXTADDR(ex)) {
                        send_sig(SIGKILL, current, 0);
                        return error;
                }
 
+               down(&current->mm->mmap_sem);
                error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
                                PROT_READ | PROT_WRITE | PROT_EXEC,
                                MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
                                fd_offset + ex.a_text);
+               up(&current->mm->mmap_sem);
                if (error != N_DATADDR(ex)) {
                        send_sig(SIGKILL, current, 0);
                        return error;
index 9c423c467e2ec96a86bbaf91bc79f756f41e43ae..39279c752d0735ef39cafc68c84f2dfb85eb73fc 100644 (file)
@@ -261,12 +261,14 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
            if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
                elf_type |= MAP_FIXED;
 
+           down(&current->mm->mmap_sem);
            map_addr = do_mmap(interpreter,
                            load_addr + ELF_PAGESTART(vaddr),
                            eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr),
                            elf_prot,
                            elf_type,
                            eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
+           up(&current->mm->mmap_sem);
            if (map_addr > -1024UL) /* Real error */
                goto out_close;
 
@@ -612,11 +614,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        elf_flags |= MAP_FIXED;
                }
 
+               down(&current->mm->mmap_sem);
                error = do_mmap(bprm->file, ELF_PAGESTART(load_bias + vaddr),
                                (elf_ppnt->p_filesz +
                                ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
                                elf_prot, elf_flags, (elf_ppnt->p_offset -
                                ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
+               up(&current->mm->mmap_sem);
 
                if (!load_addr_set) {
                        load_addr_set = 1;
@@ -726,8 +730,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                   Since we do not have the power to recompile these, we
                   emulate the SVr4 behavior.  Sigh.  */
                /* N.B. Shouldn't the size here be PAGE_SIZE?? */
+               down(&current->mm->mmap_sem);
                error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
                                MAP_FIXED | MAP_PRIVATE, 0);
+               up(&current->mm->mmap_sem);
        }
 
 #ifdef ELF_PLAT_INIT
index 63613b8293a6f3604aa25003deee7215762f80b8..4a2ee972bfc004f6ba6ffd4e87ccca9e56773b1b 100644 (file)
@@ -2111,6 +2111,31 @@ out:
        return 0;
 }
 
+/*
+ * Sync all the buffers on one page..
+ *
+ * If we have old buffers that are locked, we'll
+ * wait on them, but we won't wait on the new ones
+ * we're writing out now.
+ *
+ * This all is required so that we can free up memory
+ * later.
+ */
+static void sync_page_buffers(struct buffer_head *bh)
+{
+       struct buffer_head * tmp;
+
+       tmp = bh;
+       do {
+               struct buffer_head *p = tmp;
+               tmp = tmp->b_this_page;
+               if (buffer_locked(p))
+                       __wait_on_buffer(p);
+               else if (buffer_dirty(p))
+                       ll_rw_block(WRITE, 1, &p);
+       } while (tmp != bh);
+}
+
 /*
  * Can the buffer be thrown out?
  */
@@ -2130,16 +2155,15 @@ out:
  */
 int try_to_free_buffers(struct page * page)
 {
-       struct buffer_head * tmp, * p, * bh = page->buffers;
+       struct buffer_head * tmp, * bh = page->buffers;
        int index = BUFSIZE_INDEX(bh->b_size);
-       int ret;
 
        spin_lock(&lru_list_lock);
        write_lock(&hash_table_lock);
        spin_lock(&free_list[index].lock);
        tmp = bh;
        do {
-               p = tmp;
+               struct buffer_head *p = tmp;
 
                tmp = tmp->b_this_page;
                if (buffer_busy(p))
@@ -2169,19 +2193,18 @@ int try_to_free_buffers(struct page * page)
        /* And free the page */
        page->buffers = NULL;
        __free_page(page);
-       ret = 1;
-out:
        spin_unlock(&free_list[index].lock);
        write_unlock(&hash_table_lock);
        spin_unlock(&lru_list_lock);
-       return ret;
+       return 1;
 
 busy_buffer_page:
        /* Uhhuh, start writeback so that we don't end up with all dirty pages */
-       if (buffer_dirty(p))
-               wakeup_bdflush(0);
-       ret = 0;
-       goto out;
+       spin_unlock(&free_list[index].lock);
+       write_unlock(&hash_table_lock);
+       spin_unlock(&lru_list_lock);    
+       sync_page_buffers(bh);
+       return 0;
 }
 
 /* ================== Debugging =================== */
index cc12ccaef6f320d382e017bbf3935ff02c526cde..1a7fb195ce210c04a5361bee4c9c25105fd4b261 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/list.h>
+#include <linux/smp_lock.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -144,7 +145,9 @@ static ssize_t coda_psdev_write(struct file *file, const char *buf,
                        return -EFAULT;
 
                /* what downcall errors does Venus handle ? */
+               lock_kernel();
                error = coda_downcall(hdr.opcode, dcbuf, sb);
+               unlock_kernel();
 
                if ( error) {
                        printk("psdev_write: coda_downcall error: %d\n", 
index 5329d7be4fc654eca170e3b7706b71df2b0521ac..992bbd6aa8a72f4e6727f92120c4d30f78eb767b 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -379,8 +379,10 @@ static int exec_mmap(void)
                struct mm_struct *active_mm = current->active_mm;
 
                init_new_context(current, mm);
+               task_lock(current);
                current->mm = mm;
                current->active_mm = mm;
+               task_unlock(current);
                activate_mm(active_mm, mm);
                mm_release();
                if (old_mm) {
@@ -413,7 +415,9 @@ static inline int make_private_signals(void)
        spin_lock_init(&newsig->siglock);
        atomic_set(&newsig->count, 1);
        memcpy(newsig->action, current->sig->action, sizeof(newsig->action));
+       spin_lock_irq(&current->sigmask_lock);
        current->sig = newsig;
+       spin_unlock_irq(&current->sigmask_lock);
        return 0;
 }
        
@@ -466,7 +470,6 @@ int flush_old_exec(struct linux_binprm * bprm)
        /*
         * Make sure we have a private signal table
         */
-       task_lock(current);
        oldsig = current->sig;
        retval = make_private_signals();
        if (retval) goto flush_failed;
@@ -505,16 +508,16 @@ int flush_old_exec(struct linux_binprm * bprm)
                        
        flush_signal_handlers(current);
        flush_old_files(current->files);
-       task_unlock(current);
 
        return 0;
 
 mmap_failed:
+flush_failed:
+       spin_lock_irq(&current->sigmask_lock);
        if (current->sig != oldsig)
                kfree(current->sig);
-flush_failed:
        current->sig = oldsig;
-       task_unlock(current);
+       spin_unlock_irq(&current->sigmask_lock);
        return retval;
 }
 
index f9c9ab87f4f79bcf7683d8d71dd883d4248a40b5..6df134ed80e108c7f944a1e705fb8207999adc3c 100644 (file)
@@ -306,6 +306,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
        char state;
        int res;
        pid_t ppid;
+       int tty_nr;
        struct mm_struct *mm;
 
        state = *get_task_state(task);
@@ -332,10 +333,13 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
 
        collect_sigign_sigcatch(task, &sigign, &sigcatch);
 
+       task_lock(task);
        if (task->tty)
                tty_pgrp = task->tty->pgrp;
        else
                tty_pgrp = -1;
+       tty_nr = task->tty ? kdev_t_to_nr(task->tty->device) : 0;
+       task_unlock(task);
 
        /* scale priority and nice values from timeslices to -20..20 */
        /* to make it look like a "normal" Unix priority/nice value  */
@@ -356,7 +360,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
                ppid,
                task->pgrp,
                task->session,
-               task->tty ? kdev_t_to_nr(task->tty->device) : 0,
+               tty_nr,
                tty_pgrp,
                task->flags,
                task->min_flt,
index 792632994fa69ac0698232896308f767d0b0a5bc..2e83c6a4ec50e2e9c7dc548e4ada236e32cbf73c 100644 (file)
@@ -121,6 +121,7 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
                *mnt = mntget(fs->rootmnt);
                *dentry = dget(fs->root);
                result = 0;
+               put_fs_struct(fs);
        }
        return result;
 }
@@ -258,18 +259,6 @@ static ssize_t proc_info_read(struct file * file, char * buf,
        if (!(page = __get_free_page(GFP_KERNEL)))
                return -ENOMEM;
 
-       /* FIXME: check that all proc_read function
-        *      handle a dying task gracefully.
-        *      The memory for the task structure
-        *      won't be freed, we've called get_task_struct().
-        */
-#if 0
-       if (!task->p_pptr) {
-               free_page(page);
-               return -EIO;
-       }
-#endif
-       
        length = inode->u.proc_i.op.proc_read(task, (char*)page);
 
        if (length < 0) {
@@ -446,18 +435,19 @@ static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen)
 {
        int error;
        struct inode *inode = dentry->d_inode;
-       struct vfsmount *mnt;
+       struct dentry *de;
+       struct vfsmount *mnt = NULL;
 
        error = proc_permission(inode, MAY_EXEC);
        if (error)
                goto out;
 
-       error = inode->u.proc_i.op.proc_get_link(inode, &dentry, &mnt);
+       error = inode->u.proc_i.op.proc_get_link(inode, &de, &mnt);
        if (error)
                goto out;
 
-       error = do_proc_readlink(dentry, mnt, buffer, buflen);
-       dput(dentry);
+       error = do_proc_readlink(de, mnt, buffer, buflen);
+       dput(de);
        mntput(mnt);
 out:
        return error;
@@ -521,6 +511,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
        unsigned int fd, pid, ino;
        int retval;
        char buf[NUMBUF];
+       struct files_struct * files;
 
        retval = 0;
        pid = p->pid;
@@ -537,12 +528,19 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
                                goto out;
                        filp->f_pos++;
                default:
+                       task_lock(p);
+                       files = p->files;
+                       if (files)
+                               atomic_inc(&files->count);
+                       task_unlock(p);
+                       if (!files)
+                               goto out;
                        for (fd = filp->f_pos-2;
-                            p->p_pptr && p->files && fd < p->files->max_fds;
+                            fd < files->max_fds;
                             fd++, filp->f_pos++) {
                                unsigned int i,j;
 
-                               if (!fcheck_task(p, fd))
+                               if (!fcheck_files(files, fd))
                                        continue;
 
                                j = NUMBUF;
@@ -556,8 +554,8 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
                                ino = fake_ino(pid, PROC_PID_FD_DIR + fd);
                                if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0)
                                        break;
-
                        }
+                       put_files_struct(files);
        }
 out:
        return retval;
@@ -713,16 +711,20 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
        inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd);
        if (!inode)
                goto out;
-       /* FIXME */
+       task_lock(task);
        files = task->files;
-       if (!files)     /* can we ever get here if that's the case? */
+       if (files)
+               atomic_inc(&files->count);
+       task_unlock(task);
+       if (!files)
                goto out_unlock;
        read_lock(&files->file_lock);
-       file = inode->u.proc_i.file = fcheck_task(task, fd);
+       file = inode->u.proc_i.file = fcheck_files(files, fd);
        if (!file)
                goto out_unlock2;
        get_file(file);
        read_unlock(&files->file_lock);
+       put_files_struct(files);
        inode->i_op = &proc_pid_link_inode_operations;
        inode->i_size = 64;
        inode->i_mode = S_IFLNK;
@@ -736,6 +738,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
        return NULL;
 
 out_unlock2:
+       put_files_struct(files);
        read_unlock(&files->file_lock);
 out_unlock:
        iput(inode);
index a7ccf492d152c606635c6e31517e248e90b7f7c2..1bf7e10676e584d549b11f3aedadeb465c213263 100644 (file)
@@ -949,7 +949,7 @@ static int do_umount(struct vfsmount *mnt, int umount_root, int flags)
        }
 
        if (mnt->mnt_instances.next != mnt->mnt_instances.prev) {
-               if (sb->s_type->fs_flags && FS_SINGLE)
+               if (sb->s_type->fs_flags & FS_SINGLE)
                        put_filesystem(sb->s_type);
                mntput(mnt);
                remove_vfsmnt(mnt);
index 687470bfccd497bcc6e2fee4ba840dcefb4aaeae..8c38883c018a3a6c4bef7b7378110a7c10ad856c 100644 (file)
@@ -397,7 +397,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
        int c = 1;
        int lbcount = 0, b_off = 0, offset = 0;
        Uint32 newblocknum, newblock;
-       char etype;
+       int etype;
        int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
        char lastblock = 0;
 
@@ -1885,7 +1885,7 @@ int udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
        struct buffer_head *obh;
        lb_addr obloc;
        int oextoffset, adsize;
-       char type;
+       int type;
        struct AllocExtDesc *aed;
 
        if (!(nbh))
index 354561d2c389011cf317e4c3dff5e911edc265b3..8ac96f57438896dea03fedad7e55d4ffb9ff3f11 100644 (file)
@@ -7,16 +7,12 @@
 
 extern void _fput(struct file *);
 
-/*
- * Check whether the specified task has the fd open. Since the task
- * may not have a files_struct, we must test for p->files != NULL.
- */
-static inline struct file * fcheck_task(struct task_struct *p, unsigned int fd)
+static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
 {
        struct file * file = NULL;
 
-       if (fd < p->files->max_fds)
-               file = p->files->fd[fd];
+       if (fd < files->max_fds)
+               file = files->fd[fd];
        return file;
 }
 
@@ -100,4 +96,6 @@ static inline void fd_install(unsigned int fd, struct file * file)
                fput(result);
 }
 
+void put_files_struct(struct files_struct *fs);
+
 #endif /* __LINUX_FILE_H */
index f55c5de88de197002f49256b59cb198456b5e087..c15faa66fb3ae550ef59bd04eeb67615b5b72949 100644 (file)
@@ -142,7 +142,6 @@ struct i2o_controller
        void (*bus_disable)(struct i2o_controller *c);
 
        void *page_frame;               /* Message buffers */
-       int inbound_size;               /* Inbound queue size */
 };
 
 /*
@@ -304,8 +303,6 @@ extern int i2o_query_table(int, struct i2o_controller *, int, int, int, void *,
 extern int i2o_clear_table(struct i2o_controller *, int, int); 
 extern int i2o_row_add_table(struct i2o_controller *, int, int, int, void *,
                             int);
-extern int i2o_row_delete_table(struct i2o_controller *, int, int, int, void *,
-                               int);
 extern int i2o_issue_params(int, struct i2o_controller *, int, void *,
                            int, void *, int); 
 
@@ -401,13 +398,12 @@ extern int i2o_delete_controller(struct i2o_controller *);
 
 #define I2O_PRIVATE_MSG                        0xFF
 
-/*
- *     Init Outbound Q status 
- */
-#define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS      0x01
-#define I2O_CMD_OUTBOUND_INIT_REJECTED         0x02
-#define I2O_CMD_OUTBOUND_INIT_FAILED           0x03
-#define I2O_CMD_OUTBOUND_INIT_COMPLETE         0x04
+/* Command status values  */
+
+#define I2O_CMD_IN_PROGRESS    0x01
+#define I2O_CMD_REJECTED       0x02
+#define I2O_CMD_FAILED         0x03
+#define I2O_CMD_COMPLETED      0x04
 
 /* I2O API function return values */
 
@@ -490,6 +486,25 @@ extern int i2o_delete_controller(struct i2o_controller *);
 #define I2O_DSC_DEVICE_BUSY                    0x001B
 #define I2O_DSC_DEVICE_NOT_AVAILABLE           0x001C
 
+/* FailureStatusCodes, Table 3-3 Message Failure Codes */
+
+#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED             0x81
+#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED            0x82
+#define I2O_FSC_TRANSPORT_CONGESTION                    0x83
+#define I2O_FSC_TRANSPORT_FAILURE                       0x84
+#define I2O_FSC_TRANSPORT_STATE_ERROR                   0x85
+#define I2O_FSC_TRANSPORT_TIME_OUT                      0x86
+#define I2O_FSC_TRANSPORT_ROUTING_FAILURE               0x87
+#define I2O_FSC_TRANSPORT_INVALID_VERSION               0x88
+#define I2O_FSC_TRANSPORT_INVALID_OFFSET                0x89
+#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS             0x8A
+#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL               0x8B
+#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE               0x8C
+#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID             0x8D
+#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID          0x8E
+#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT     0x8F
+#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE               0xFF
+
 /* Device Claim Types */
 #define        I2O_CLAIM_PRIMARY                                       0x01000000
 #define        I2O_CLAIM_MANAGEMENT                                    0x02000000
@@ -526,7 +541,7 @@ extern int i2o_delete_controller(struct i2o_controller *);
 #define MSG_64BIT_CNTXT        0x0200
 #define MSG_MULTI_TRANS        0x1000
 #define MSG_FAIL       0x2000
-#define MSG_LAST       0x4000
+#define MSG_FINAL      0x4000
 #define MSG_REPLY      0x8000
 
  /* minimum size msg */
index 7b4398701623c4ec69ded5579118764870984814..4497f6468a8ac26466e6ed291b43dfb8de34e5e7 100644 (file)
@@ -345,7 +345,7 @@ struct task_struct {
 /* Thread group tracking */
        u32 parent_exec_id;
        u32 self_exec_id;
-/* Protection of (de-)allocation: mm, files, fs */
+/* Protection of (de-)allocation: mm, files, fs, tty */
        spinlock_t alloc_lock;
 };
 
index ef76f54c7a2d32ffb4ba722dd717664d0b186451..6a10e4b83e4755d3ab2dd4c3d491251f4c9f184f 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -740,8 +740,9 @@ static int newseg (key_t key, const char *name, int namelen,
        if (shm_tot + numpages >= shm_ctlall)
                return -ENOSPC;
 
-       if (!(shp = seg_alloc(numpages, namelen ? namelen : SHM_FMT_LEN + 1)))
-               return -ENOMEM;
+       shp = seg_alloc(numpages, namelen ? namelen : SHM_FMT_LEN + 1);
+       if (IS_ERR(shp))
+               return PTR_ERR(shp);
        id = shm_addid(shp);
        if(id == -1) {
                seg_free(shp, 1);
@@ -1428,6 +1429,7 @@ static int shm_swap_core(struct shmid_kernel *shp, unsigned long idx, swp_entry_
        if (page_count(page_map) != 1)
                return RETRY;
 
+       lock_page(page_map);
        if (!(page_map = prepare_highmem_swapout(page_map)))
                return FAILED;
        SHM_ENTRY (shp, idx) = swp_entry_to_pte(swap_entry);
@@ -1437,7 +1439,6 @@ static int shm_swap_core(struct shmid_kernel *shp, unsigned long idx, swp_entry_
           reading a not yet uptodate block from disk.
           NOTE: we just accounted the swap space reference for this
           swap cache page at __get_swap_page() time. */
-       lock_page(page_map);
        add_to_swap_cache(*outpage = page_map, swap_entry);
        return OKAY;
 }
index 46a7443f134cad8c94fea5f4cddba4ba2177942d..4060c802ac9b4138ba1aaea30d0be77c1cdb6fc5 100644 (file)
@@ -110,9 +110,16 @@ void __set_personality(unsigned long personality)
        if (it) {
                if (atomic_read(&current->fs->count) != 1) {
                        struct fs_struct *new = copy_fs_struct(current->fs);
-                       if (!new)
+                       struct fs_struct *old;
+                       if (!new) {
+                               put_exec_domain(it);
                                return;
-                       put_fs_struct(xchg(&current->fs,new));
+                       }
+                       task_lock(current);
+                       old = current->fs;
+                       current->fs = new;
+                       task_unlock(current);
+                       put_fs_struct(old);
                }
                /*
                 * At that point we are guaranteed to be the sole owner of
index c7fd6814d55e70e823cfb694a936a1b94c647f91..96c7efb1dc2d97d3ced30b8be63331a6eaa027b9 100644 (file)
@@ -182,24 +182,32 @@ static inline void close_files(struct files_struct * files)
 
 extern kmem_cache_t *files_cachep;  
 
+void put_files_struct(struct files_struct *files)
+{
+       if (atomic_dec_and_test(&files->count)) {
+               close_files(files);
+               /*
+                * Free the fd and fdset arrays if we expanded them.
+                */
+               if (files->fd != &files->fd_array[0])
+                       free_fd_array(files->fd, files->max_fds);
+               if (files->max_fdset > __FD_SETSIZE) {
+                       free_fdset(files->open_fds, files->max_fdset);
+                       free_fdset(files->close_on_exec, files->max_fdset);
+               }
+               kmem_cache_free(files_cachep, files);
+       }
+}
+
 static inline void __exit_files(struct task_struct *tsk)
 {
-       struct files_struct * files = xchg(&tsk->files, NULL);
+       struct files_struct * files = tsk->files;
 
        if (files) {
-               if (atomic_dec_and_test(&files->count)) {
-                       close_files(files);
-                       /*
-                        * Free the fd and fdset arrays if we expanded them.
-                        */
-                       if (files->fd != &files->fd_array[0])
-                               free_fd_array(files->fd, files->max_fds);
-                       if (files->max_fdset > __FD_SETSIZE) {
-                               free_fdset(files->open_fds, files->max_fdset);
-                               free_fdset(files->close_on_exec, files->max_fdset);
-                       }
-                       kmem_cache_free(files_cachep, files);
-               }
+               task_lock(tsk);
+               tsk->files = NULL;
+               task_unlock(tsk);
+               put_files_struct(files);
        }
 }
 
@@ -232,7 +240,9 @@ static inline void __exit_fs(struct task_struct *tsk)
        struct fs_struct * fs = tsk->fs;
 
        if (fs) {
+               task_lock(tsk);
                tsk->fs = NULL;
+               task_unlock(tsk);
                __put_fs_struct(fs);
        }
 }
@@ -247,11 +257,9 @@ static inline void __exit_sighand(struct task_struct *tsk)
        struct signal_struct * sig = tsk->sig;
 
        if (sig) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&tsk->sigmask_lock, flags);
+               spin_lock_irq(&tsk->sigmask_lock);
                tsk->sig = NULL;
-               spin_unlock_irqrestore(&tsk->sigmask_lock, flags);
+               spin_unlock_irq(&tsk->sigmask_lock);
                if (atomic_dec_and_test(&sig->count))
                        kfree(sig);
        }
@@ -302,7 +310,10 @@ static inline void __exit_mm(struct task_struct * tsk)
                atomic_inc(&mm->mm_count);
                mm_release();
                if (mm != tsk->active_mm) BUG();
+               /* more a memory barrier than a real lock */
+               task_lock(tsk);
                tsk->mm = NULL;
+               task_unlock(tsk);
                enter_lazy_tlb(mm, current, smp_processor_id());
                mmput(mm);
        }
@@ -429,7 +440,6 @@ fake_volatile:
 #ifdef CONFIG_BSD_PROCESS_ACCT
        acct_process(code);
 #endif
-       task_lock(tsk);
        sem_exit();
        __exit_mm(tsk);
        __exit_files(tsk);
@@ -439,7 +449,6 @@ fake_volatile:
        tsk->state = TASK_ZOMBIE;
        tsk->exit_code = code;
        exit_notify();
-       task_unlock(tsk);
        put_exec_domain(tsk->exec_domain);
        if (tsk->binfmt && tsk->binfmt->module)
                __MOD_DEC_USE_COUNT(tsk->binfmt->module);
index a75f0f8de5e99b912176ca3c05aec219e75378bf..17bef2520ae85e9c53a21317520f67ba900c3695 100644 (file)
@@ -236,9 +236,7 @@ repeat:
 int shrink_mmap(int priority, int gfp_mask)
 {
        int ret = 0, count;
-       LIST_HEAD(young);
        LIST_HEAD(old);
-       LIST_HEAD(forget);
        struct list_head * page_lru, * dispose;
        struct page * page = NULL;
        
@@ -334,7 +332,6 @@ int shrink_mmap(int priority, int gfp_mask)
                        goto cache_unlock_continue;
                }
 
-               dispose = &forget;
                printk(KERN_ERR "shrink_mmap: unknown LRU page!\n");
 
 cache_unlock_continue:
@@ -359,7 +356,6 @@ made_buffer_progress:
        nr_lru_pages--;
 
 out:
-       list_splice(&young, &lru_cache);
        list_splice(&old, lru_cache.prev);
 
        spin_unlock(&pagemap_lru_lock);
index 34c6be735735d1ef07828cd307243bfa58ca94ac..c3ea96efc4ba9d555840f0feec14cf5aad9aaa72 100644 (file)
@@ -272,7 +272,7 @@ struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order)
                int gfp_mask = zonelist->gfp_mask;
                if (!try_to_free_pages(gfp_mask)) {
                        if (!(gfp_mask & __GFP_HIGH))
-                               return NULL;
+                               goto fail;
                }
        }
 
@@ -291,6 +291,7 @@ struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order)
                        return page;
        }
 
+fail:
        /* No luck.. */
        return NULL;
 }
index 121bad277cc18cd8c9309aed081d41d66c0fc713..230342c7a2035cb882812e5e1e811b039cf66fcf 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -682,6 +682,9 @@ kmem_cache_create(const char *name, size_t size, size_t offset,
        size_t          left_over;
        size_t          align;
 
+#if SLAB_DEBUG_SUPPORT
+       flags |= SLAB_POISON;
+#endif
        /* Sanity checks... */
 #if    SLAB_MGMT_CHECKS
        if (!name) {
index c410c92c67db321a62d18e428f1691dc8214bd68..db7e61e0058c18c045858cbac03ee4a01b651432 100644 (file)
@@ -48,7 +48,6 @@ static int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, un
        if ((page-mem_map >= max_mapnr) || PageReserved(page))
                goto out_failed;
 
-       mm->swap_cnt--;
        /* Don't look at this pte if it's been accessed recently. */
        if (pte_young(pte)) {
                /*
@@ -77,6 +76,7 @@ static int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, un
                set_pte(page_table, swp_entry_to_pte(entry));
 drop_pte:
                UnlockPage(page);
+               mm->swap_cnt--;
                vma->vm_mm->rss--;
                flush_tlb_page(vma, address);
                __free_page(page);
@@ -142,6 +142,7 @@ drop_pte:
                struct file *file = vma->vm_file;
                if (file) get_file(file);
                pte_clear(page_table);
+               mm->swap_cnt--;
                vma->vm_mm->rss--;
                flush_tlb_page(vma, address);
                vmlist_access_unlock(vma->vm_mm);
@@ -173,6 +174,7 @@ drop_pte:
        add_to_swap_cache(page, entry);
 
        /* Put the swap entry into the pte after the page is in swapcache */
+       mm->swap_cnt--;
        vma->vm_mm->rss--;
        set_pte(page_table, swp_entry_to_pte(entry));
        flush_tlb_page(vma, address);
@@ -362,7 +364,7 @@ static int swap_out(unsigned int priority, int gfp_mask)
         * Think of swap_cnt as a "shadow rss" - it tells us which process
         * we want to page out (always try largest first).
         */
-       counter = (nr_threads << 1) >> (priority >> 1);
+       counter = nr_threads / (priority+1);
        if (counter < 1)
                counter = 1;
 
@@ -423,14 +425,18 @@ out:
  * now we need this so that we can do page allocations
  * without holding the kernel lock etc.
  *
- * We want to try to free "count" pages, and we need to 
- * cluster them so that we get good swap-out behaviour. See
- * the "free_memory()" macro for details.
+ * We want to try to free "count" pages, and we want to 
+ * cluster them so that we get good swap-out behaviour.
+ *
+ * Don't try _too_ hard, though. We don't want to have bad
+ * latency.
  */
+#define FREE_COUNT     8
+#define SWAP_COUNT     8
 static int do_try_to_free_pages(unsigned int gfp_mask)
 {
        int priority;
-       int count = SWAP_CLUSTER_MAX;
+       int count = FREE_COUNT;
 
        /* Always trim SLAB caches when memory gets low. */
        kmem_cache_reap(gfp_mask);
@@ -460,12 +466,27 @@ static int do_try_to_free_pages(unsigned int gfp_mask)
                        }
                }
 
-               /* Then, try to page stuff out.. */
-               while (swap_out(priority, gfp_mask)) {
-                       if (!--count)
-                               goto done;
+               /*
+                * Then, try to page stuff out..
+                *
+                * This will not actually free any pages (they get
+                * put in the swap cache), so we must not count this
+                * as a "count" success.
+                */
+               {
+                       int swap_count = SWAP_COUNT;
+                       while (swap_out(priority, gfp_mask))
+                               if (--swap_count < 0)
+                                       break;
                }
        } while (--priority >= 0);
+
+       /* Always end on a shrink_mmap.. */
+       while (shrink_mmap(0, gfp_mask)) {
+               if (!--count)
+                       goto done;
+       }
+
        return 0;
 
 done: