## Automatically generated incremental diff
## From:   linux-2.0.37-pre10
## To:     linux-2.0.37-pre11
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.0.37-pre10/arch/alpha/defconfig linux-2.0.37-pre11/arch/alpha/defconfig
--- linux-2.0.37-pre10/arch/alpha/defconfig	1998-06-03 15:17:46.000000000 -0700
+++ linux-2.0.37-pre11/arch/alpha/defconfig	2003-08-15 15:04:47.000000000 -0700
@@ -159,7 +159,7 @@
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
+CONFIG_NET_PCI=y
 # CONFIG_APRICOT is not set
 CONFIG_DE4X5=y
 # CONFIG_DEC_ELCP is not set
@@ -220,7 +220,6 @@
 # CONFIG_UMISC is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_FTAPE is not set
-# CONFIG_APM is not set
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
 
diff -urN linux-2.0.37-pre10/arch/i386/boot/setup.S linux-2.0.37-pre11/arch/i386/boot/setup.S
--- linux-2.0.37-pre10/arch/i386/boot/setup.S	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/arch/i386/boot/setup.S	2003-08-15 15:04:47.000000000 -0700
@@ -18,7 +18,7 @@
 ! March 1993/June 1994 (Christoph.Niemann@linux.org)
 !
 ! add APM BIOS checking by Stephen Rothwell, May 1994
-! (Stephen.Rothwell@pd.necisa.oz.au)
+! (Stephen.Rothwell@canb.auug.org.au)
 !
 ! High load stuff, initrd support and position independency
 ! by Hans Lermen & Werner Almesberger, February 1996
@@ -331,7 +331,7 @@
 
 #ifdef CONFIG_APM
 ! check for APM BIOS
-		! NOTE:	DS is pointing to the bootsector
+		! NOTE:	DS is pointing to the boot sector
 		!
 	mov	[64],#0		! version == 0 means no APM BIOS
 
diff -urN linux-2.0.37-pre10/arch/i386/config.in linux-2.0.37-pre11/arch/i386/config.in
--- linux-2.0.37-pre10/arch/i386/config.in	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/arch/i386/config.in	2003-08-15 15:04:47.000000000 -0700
@@ -63,6 +63,16 @@
   bool 'Handle buggy SMP BIOSes with bad MTRR setup' CONFIG_MTRR
 fi
 
+bool 'Advanced Power Management BIOS support' CONFIG_APM
+if [ "$CONFIG_APM" = "y" ]; then
+  bool '   Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
+  bool '   Enable PM at boot time' CONFIG_APM_DO_ENABLE
+  bool '   Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
+  bool '   Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
+  bool '   Power off on shutdown' CONFIG_APM_POWER_OFF
+  bool '   Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+fi
+
 endmenu
 
 source drivers/block/Config.in
diff -urN linux-2.0.37-pre10/arch/i386/kernel/apm.c linux-2.0.37-pre11/arch/i386/kernel/apm.c
--- linux-2.0.37-pre10/arch/i386/kernel/apm.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.0.37-pre11/arch/i386/kernel/apm.c	2003-08-15 15:04:47.000000000 -0700
@@ -0,0 +1,1269 @@
+/* -*- linux-c -*-
+ * APM BIOS driver for Linux
+ * Copyright 1994-1999 Stephen Rothwell
+ *                     (Stephen.Rothwell@canb.auug.org.au)
+ * Development of this driver was funded by NEC Australia P/L
+ *	and NEC Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * October 1995, Rik Faith (faith@cs.unc.edu):
+ *    Minor enhancements and updates (to the patch set) for 1.3.x
+ *    Documentation
+ * January 1996, Rik Faith (faith@cs.unc.edu):
+ *    Make /proc/apm easy to format (bump driver version)
+ * March 1996, Rik Faith (faith@cs.unc.edu):
+ *    Prohibit APM BIOS calls unless apm_enabled.
+ *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
+ * April 1996, Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
+ *    Version 1.0 and 1.1
+ * May 1996, Version 1.2
+ *
+ * History:
+ *    0.6b: first version in official kernel, Linux 1.3.46
+ *    0.7: changed /proc/apm format, Linux 1.3.58
+ *    0.8: fixed gcc 2.7.[12] compilation problems, Linux 1.3.59
+ *    0.9: only call bios if bios is present, Linux 1.3.72
+ *    1.0: use fixed device number, consolidate /proc/apm into this file,
+ *         Linux 1.3.85
+ *    1.1: support user-space standby and suspend, power off after system
+ *         halted, Linux 1.3.98
+ *    1.2: When resetting RTC after resume, take care so that the time
+ *         is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
+ *         <jtoth@princeton.edu>); improve interaction between
+ *         screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
+ *    1.2a: Fix OOPs on power off with no APM BIOS
+ *         Jan Echternach <echter@informatik.uni-rostock.de>
+ *
+ * Reference:
+ *
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.1, September 1993.
+ *   Intel Order Number 241704-001.  Microsoft Part Number 781-110-X01.
+ *
+ * [This document is available free from Intel by calling 800.628.8686 (fax
+ * 916.356.6100) or 800.548.4725; or via anonymous ftp from
+ * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc.  It is also
+ * available from Microsoft by calling 206.882.8080.]
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/timer.h>
+#include <linux/fcntl.h>
+#include <linux/malloc.h>
+#include <linux/linkage.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#endif
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+
+static struct symbol_table	apm_syms = {
+#include <linux/symtab_begin.h>
+	X(apm_register_callback),
+	X(apm_unregister_callback),
+#include <linux/symtab_end.h>
+};
+
+extern unsigned long get_cmos_time(void);
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define	APM_MINOR_DEV	134
+
+/* Configurable options:
+ *  
+ * CONFIG_APM_IGNORE_USER_SUSPEND: define to ignore USER SUSPEND requests.
+ * This is necessary on the NEC Versa M series, which generates these when
+ * resuming from SYSTEM SUSPEND.  However, enabling this on other laptops
+ * will cause the laptop to generate a CRITICAL SUSPEND when an appropriate
+ * USER SUSPEND is ignored -- this may prevent the APM driver from updating
+ * the system time on a RESUME.
+ *
+ * CONFIG_APM_DO_ENABLE: enable APM features at boot time.  From page 36 of
+ * the specification: "When disabled, the APM BIOS does not automatically
+ * power manage devices, enter the Standby State, enter the Suspend State,
+ * or take power saving steps in response to CPU Idle calls."  This driver
+ * will make CPU Idle calls when Linux is idle (unless this feature is
+ * turned off -- see below).  This should always save battery power, but
+ * more complicated APM features will be dependent on your BIOS
+ * implementation.  You may need to turn this option off if your computer
+ * hangs at boot time when using APM support, or if it beeps continuously
+ * instead of suspending.  Turn this off if you have a NEC UltraLite Versa
+ * 33/C or a Toshiba T400CDT.  This is off by default since most machines
+ * do fine without this feature.
+ *
+ * CONFIG_APM_CPU_IDLE: enable calls to APM CPU Idle/CPU Busy inside the
+ * idle loop.  On some machines, this can activate improved power savings,
+ * such as a slowed CPU clock rate, when the machine is idle.  These idle
+ * call is made after the idle loop has run for some length of time (e.g.,
+ * 333 mS).  On some machines, this will cause a hang at boot time or
+ * whenever the CPU becomes idle.
+ *
+ * CONFIG_APM_DISPLAY_BLANK: enable console blanking using the APM.  Some
+ * laptops can use this to turn of the LCD backlight when the VC screen
+ * blanker blanks the screen.  Note that this is only used by the VC screen
+ * blanker, and probably won't turn off the backlight when using X11.  Some
+ * problems have been reported when using this option with gpm (if you'd
+ * like to debug this, please do so).
+ *
+ * CONFIG_APM_IGNORE_MULTIPLE_SUSPEND: The IBM TP560 bios seems to insist
+ * on returning multiple suspend/standby events whenever one occurs.  We
+ * really only need one at a time, so just ignore any beyond the first.
+ * This is probably safe on most laptops.
+ *
+ * If you are debugging the APM support for your laptop, note that code for
+ * all of these options is contained in this file, so you can #define or
+ * #undef these on the next line to avoid recompiling the whole kernel.
+ *
+ */
+
+/* KNOWN PROBLEM MACHINES:
+ *
+ * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
+ *                         [Confirmed by TI representative]
+ * U: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
+ *                    [Confirmed by BIOS disassembly]
+ * P: Toshiba 1950S: battery life information only gets updated after resume
+ *
+ * Legend: U = unusable with APM patches
+ *         P = partially usable with APM patches
+ */
+
+/*
+ * Define to have debug messages.
+ */
+#undef APM_DEBUG
+
+/*
+ * Define to always call the APM BIOS busy routine even if the clock was
+ * not slowed by the idle routine.
+ */
+#define ALWAYS_CALL_BUSY
+
+/*
+ * Define to disable interrupts in APM BIOS calls (the CPU Idle BIOS call
+ * should turn interrupts on before it does a 'hlt').
+ */
+#define APM_NOINTS
+
+/*
+ * Define to make the APM BIOS calls zero all data segment registers (do
+ * that if an incorrect BIOS implementation will cause a kernel panic if it
+ * tries to write to arbitrary memory).
+ */
+#define APM_ZERO_SEGS
+
+/*
+ * Define to make all set_limit calls use 64k limits.  The APM 1.1 BIOS is
+ * supposed to provide limit information that it recognizes.  Many machines
+ * do this correctly, but many others do not restrict themselves to their
+ * claimed limit.  When this happens, they will cause a segmentation
+ * violation in the kernel at boot time.  Most BIOS's, however, will
+ * respect a 64k limit, so we use that.  If you want to be pedantic and
+ * hold your BIOS to its claims, then undefine this.
+ */
+#define APM_RELAX_SEGMENTS
+
+/*
+ * Need to poll the APM BIOS every second
+ */
+#define APM_CHECK_TIMEOUT	(HZ)
+
+/*
+ * These are the actual BIOS calls in assembler.  Depending on
+ * APM_ZERO_SEGS and APM_NOINTS, we are being really paranoid here!  Not
+ * only are interrupts disabled, but all the segment registers (except SS)
+ * are saved and zeroed this means that if the BIOS tries to reference any
+ * data without explicitly loading the segment registers, the kernel will
+ * fault immediately rather than have some unforeseen circumstances for the
+ * rest of the kernel.  And it will be very obvious!  :-) Doing this
+ * depends on CS referring to the same physical memory as DS so that DS can
+ * be zeroed before the call. Unfortunately, we can't do anything about the
+ * stack segment/pointer.  Also, we tell the compiler that everything could
+ * change.
+ */
+#ifdef APM_NOINTS
+#	define APM_DO_CLI	"cli\n\t"
+#else
+#	define APM_DO_CLI
+#endif
+#ifdef APM_ZERO_SEGS
+#	define APM_DO_ZERO_SEGS	\
+		"pushl %%ds\n\t" \
+		"pushl %%es\n\t" \
+		"pushl %%fs\n\t" \
+		"pushl %%gs\n\t" \
+		"xorl %%edx, %%edx\n\t" \
+		"mov %%dx, %%ds\n\t" \
+		"mov %%dx, %%es\n\t" \
+		"mov %%dx, %%fs\n\t" \
+		"mov %%dx, %%gs\n\t"
+#	define APM_DO_RESTORE_SEGS	\
+		"popl %%gs\n\t" \
+		"popl %%fs\n\t" \
+		"popl %%es\n\t" \
+		"popl %%ds\n\t"
+#else
+#	define APM_DO_ZERO_SEGS
+#	define APM_DO_RESTORE_SEGS
+#endif
+
+#define APM_BIOS_CALL(error_reg) \
+	__asm__ __volatile__( \
+		APM_DO_ZERO_SEGS \
+		"pushfl\n\t" \
+		APM_DO_CLI \
+		"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t" \
+		"setc %%" # error_reg "\n\t" \
+		"popfl\n\t" \
+		APM_DO_RESTORE_SEGS
+#define APM_BIOS_CALL_END \
+		: "ax", "bx", "cx", "dx", "si", "di", "bp", "memory")
+
+#ifdef CONFIG_APM_CPU_IDLE
+#define APM_SET_CPU_IDLE(error) \
+	APM_BIOS_CALL(al) \
+	: "=a" (error) \
+	: "a" (0x5305) \
+	APM_BIOS_CALL_END
+#endif
+
+#define APM_SET_CPU_BUSY(error) \
+	APM_BIOS_CALL(al) \
+	: "=a" (error) \
+	: "a" (0x5306) \
+	APM_BIOS_CALL_END
+
+#define APM_SET_POWER_STATE(state, error) \
+	APM_BIOS_CALL(al) \
+	: "=a" (error) \
+	: "a" (0x5307), "b" (0x0001), "c" (state) \
+	APM_BIOS_CALL_END
+
+#ifdef CONFIG_APM_DISPLAY_BLANK
+#define APM_SET_DISPLAY_POWER_STATE(state, error) \
+	APM_BIOS_CALL(al) \
+	: "=a" (error) \
+	: "a" (0x5307), "b" (0x01ff), "c" (state) \
+	APM_BIOS_CALL_END
+#endif
+
+#ifdef CONFIG_APM_DO_ENABLE
+#define APM_ENABLE_POWER_MANAGEMENT(device, error) \
+	APM_BIOS_CALL(al) \
+	: "=a" (error) \
+	: "a" (0x5308), "b" (device), "c" (1) \
+	APM_BIOS_CALL_END
+#endif
+
+#define APM_GET_POWER_STATUS(bx, cx, dx, error) \
+	APM_BIOS_CALL(al) \
+	: "=a" (error), "=b" (bx), "=c" (cx), "=d" (dx) \
+	: "a" (0x530a), "b" (1) \
+	APM_BIOS_CALL_END
+
+#define APM_GET_EVENT(event, error)	\
+	APM_BIOS_CALL(al) \
+	: "=a" (error), "=b" (event) \
+	: "a" (0x530b) \
+	APM_BIOS_CALL_END
+
+#define APM_DRIVER_VERSION(ver, ax, error) \
+	APM_BIOS_CALL(bl) \
+	: "=a" (ax), "=b" (error) \
+	: "a" (0x530e), "b" (0), "c" (ver) \
+	APM_BIOS_CALL_END
+
+#define APM_ENGAGE_POWER_MANAGEMENT(device, error) \
+	APM_BIOS_CALL(al) \
+	: "=a" (error) \
+	: "a" (0x530f), "b" (device), "c" (1) \
+	APM_BIOS_CALL_END
+
+/*
+ * Forward declarations
+ */
+static void	suspend(void);
+static void	standby(void);
+static void	set_time(void);
+
+static void	check_events(void);
+static void	do_apm_timer(unsigned long);
+
+static int	do_open(struct inode *, struct file *);
+static void	do_release(struct inode *, struct file *);
+static int	do_read(struct inode *, struct file *, char *, int);
+static int	do_select(struct inode *, struct file *, int,
+			  select_table *);
+static int	do_ioctl(struct inode *, struct file *, u_int, u_long);
+
+#ifdef CONFIG_PROC_FS
+static int	apm_get_info(char *, char **, off_t, int, int);
+#endif
+
+extern int	apm_register_callback(int (*)(apm_event_t));
+extern void	apm_unregister_callback(int (*)(apm_event_t));
+
+/*
+ * Local variables
+ */
+static asmlinkage struct {
+	unsigned long	offset;
+	unsigned short	segment;
+}				apm_bios_entry;
+static int			apm_enabled = 0;
+#ifdef CONFIG_APM_CPU_IDLE
+static int			clock_slowed = 0;
+#endif
+static int			suspends_pending = 0;
+static int			standbys_pending = 0;
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+static int			waiting_for_resume = 0;
+#endif
+
+static long			clock_cmos_diff;
+static int			got_clock_diff = 0;
+
+static struct wait_queue *	process_list = NULL;
+static struct apm_bios_struct *	user_list = NULL;
+
+static struct timer_list	apm_timer;
+
+static char			driver_version[] = "1.2";/* no spaces */
+
+#ifdef APM_DEBUG
+static char *	apm_event_name[] = {
+	"system standby",
+	"system suspend",
+	"normal resume",
+	"critical resume",
+	"low battery",
+	"power status change",
+	"update time",
+	"critical suspend",
+	"user standby",
+	"user suspend",
+	"system standby resume"
+};
+#define NR_APM_EVENT_NAME	\
+		(sizeof(apm_event_name) / sizeof(apm_event_name[0]))
+#endif
+
+static struct file_operations apm_bios_fops = {
+	NULL,		/* lseek */
+	do_read,
+	NULL,		/* write */
+	NULL,		/* readdir */
+	do_select,
+	do_ioctl,
+	NULL,		/* mmap */
+	do_open,
+	do_release,
+	NULL,		/* fsync */
+	NULL		/* fasync */
+};
+
+static struct miscdevice apm_device = {
+	APM_MINOR_DEV,
+	"apm",
+	&apm_bios_fops
+};
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry	apm_proc_entry = {
+        0, 3, "apm", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, apm_get_info
+};
+#endif
+
+typedef struct callback_list_t {
+	int (*				callback)(apm_event_t);
+	struct callback_list_t *	next;
+} callback_list_t;
+
+static callback_list_t *	callback_list = NULL;
+
+typedef struct lookup_t {
+	int	key;
+	char *	msg;
+} lookup_t;
+
+static const lookup_t error_table[] = {
+/* N/A	{ APM_SUCCESS,		"Operation succeeded" }, */
+	{ APM_DISABLED,		"Power management disabled" },
+	{ APM_CONNECTED,	"Real mode interface already connected" },
+	{ APM_NOT_CONNECTED,	"Interface not connected" },
+	{ APM_16_CONNECTED,	"16 bit interface already connected" },
+/* N/A	{ APM_16_UNSUPPORTED,	"16 bit interface not supported" }, */
+	{ APM_32_CONNECTED,	"32 bit interface already connected" },
+	{ APM_32_UNSUPPORTED,	"32 bit interface not supported" },
+	{ APM_BAD_DEVICE,	"Unrecognized device ID" },
+	{ APM_BAD_PARAM,	"Parameter out of range" },
+	{ APM_NOT_ENGAGED,	"Interface not engaged" },
+	{ APM_BAD_STATE,	"Unable to enter requested state" },
+/* N/A	{ APM_NO_EVENTS,	"No events pending" }, */
+	{ APM_NOT_PRESENT,	"No APM present" }
+};
+#define ERROR_COUNT	(sizeof(error_table)/sizeof(lookup_t))
+
+static int apm_driver_version(u_short *val)
+{
+	u_short	error;
+
+	APM_DRIVER_VERSION(*val, *val, error);
+
+	if (error & 0xff)
+		return (*val >> 8);
+	return APM_SUCCESS;
+}
+
+static int apm_get_event(apm_event_t *event)
+{
+	u_short	error;
+
+	APM_GET_EVENT(*event, error);
+	if (error & 0xff)
+		return (error >> 8);
+	return APM_SUCCESS;
+}
+
+static int apm_set_power_state(u_short state)
+{
+	u_short	error;
+	
+	APM_SET_POWER_STATE(state, error);
+	if (error & 0xff)
+		return (error >> 8);
+	return APM_SUCCESS;
+}
+
+#ifdef CONFIG_APM_POWER_OFF
+void apm_power_off(void)
+{
+	if (apm_enabled)
+		(void) apm_set_power_state(APM_STATE_OFF);
+}
+#endif
+
+#ifdef CONFIG_APM_DISPLAY_BLANK
+/* Called by apm_display_blank and apm_display_unblank when apm_enabled. */
+static int apm_set_display_power_state(u_short state)
+{
+	u_short	error;
+
+	APM_SET_DISPLAY_POWER_STATE(state, error);
+	if (error & 0xff)
+		return (error >> 8);
+	return APM_SUCCESS;
+}
+#endif
+
+#ifdef CONFIG_APM_DO_ENABLE
+/* Called by apm_setup if apm_enabled will be true. */
+static int apm_enable_power_management(void)
+{
+	u_short	error;
+
+	APM_ENABLE_POWER_MANAGEMENT((apm_bios_info.version > 0x100)
+				    ? 0x0001 : 0xffff,
+				    error);
+	if (error & 0xff)
+		return (error >> 8);
+	return APM_SUCCESS;
+}
+#endif
+
+static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
+{
+	u_short	error;
+
+	APM_GET_POWER_STATUS(*status, *bat, *life, error);
+	if (error & 0xff)
+		return (error >> 8);
+	return APM_SUCCESS;
+}
+
+static int apm_engage_power_management(u_short device)
+{
+	u_short	error;
+
+	APM_ENGAGE_POWER_MANAGEMENT(device, error);
+	if (error & 0xff)
+		return (error >> 8);
+	return APM_SUCCESS;
+}
+
+static void apm_error(char *str, int err)
+{
+	int	i;
+
+	for (i = 0; i < ERROR_COUNT; i++)
+		if (error_table[i].key == err) break;
+	if (i < ERROR_COUNT)
+		printk("apm_bios: %s: %s\n", str, error_table[i].msg);
+	else
+		printk("apm_bios: %s: unknown error code %#2.2x\n", str, err);
+}
+
+/* Called from console driver -- must make sure apm_enabled. */
+int apm_display_blank(void)
+{
+#ifdef CONFIG_APM_DISPLAY_BLANK
+	int	error;
+
+	if (!apm_enabled)
+		return 0;
+	error = apm_set_display_power_state(APM_STATE_STANDBY);
+	if (error == APM_SUCCESS)
+		return 1;
+	apm_error("set display standby", error);
+#endif
+	return 0;
+}
+
+/* Called from console driver -- must make sure apm_enabled. */
+int apm_display_unblank(void)
+{
+#ifdef CONFIG_APM_DISPLAY_BLANK
+	int error;
+
+	if (!apm_enabled)
+		return 0;
+	error = apm_set_display_power_state(APM_STATE_READY);
+	if (error == APM_SUCCESS)
+		return 1;
+	apm_error("set display ready", error);
+#endif
+	return 0;
+}
+
+int apm_register_callback(int (*callback)(apm_event_t))
+{
+	callback_list_t *	new;
+
+	new = kmalloc(sizeof(callback_list_t), GFP_KERNEL);
+	if (new == NULL)
+		return -ENOMEM;
+	new->callback = callback;
+	new->next = callback_list;
+	callback_list = new;
+	return 0;
+}
+
+void apm_unregister_callback(int (*callback)(apm_event_t))
+{
+	callback_list_t **	ptr;
+	callback_list_t *	old;
+
+	ptr = &callback_list;
+	for (ptr = &callback_list; *ptr != NULL; ptr = &(*ptr)->next)
+		if ((*ptr)->callback == callback)
+			break;
+	old = *ptr;
+	*ptr = old->next;
+	kfree_s(old, sizeof(callback_list_t));
+}
+	
+static int queue_empty(struct apm_bios_struct * as)
+{
+	return as->event_head == as->event_tail;
+}
+
+static apm_event_t get_queued_event(struct apm_bios_struct * as)
+{
+	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+	return as->events[as->event_tail];
+}
+
+static int queue_event(apm_event_t event, struct apm_bios_struct *sender)
+{
+	struct apm_bios_struct *	as;
+	
+	if (user_list == NULL)
+		return 0;
+	for (as = user_list; as != NULL; as = as->next) {
+		if (as == sender)
+			continue;
+		as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
+		if (as->event_head == as->event_tail) {
+			static int notified;
+
+			if (notified == 0) {
+			    printk( "apm_bios: an event queue overflowed\n" );
+			    notified = 1;
+			}
+			as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+		}
+		as->events[as->event_head] = event;
+		if (!as->suser)
+			continue;
+		switch (event) {
+		case APM_SYS_SUSPEND:
+		case APM_USER_SUSPEND:
+			as->suspends_pending++;
+			suspends_pending++;
+			break;
+
+		case APM_SYS_STANDBY:
+		case APM_USER_STANDBY:
+			as->standbys_pending++;
+			standbys_pending++;
+			break;
+		}
+	}
+	wake_up_interruptible(&process_list);
+	return 1;
+}
+
+static void set_time(void)
+{
+	unsigned long	flags;
+
+	if (!got_clock_diff)	/* Don't know time zone, can't set clock */
+		return;
+
+	save_flags(flags);
+	cli();
+	CURRENT_TIME = get_cmos_time() + clock_cmos_diff;
+	restore_flags(flags);
+}
+
+static void suspend(void)
+{
+	unsigned long	flags;
+	int		err;
+
+				/* Estimate time zone so that set_time can
+                                   update the clock */
+	save_flags(flags);
+	clock_cmos_diff = -get_cmos_time();
+	cli();
+	clock_cmos_diff += CURRENT_TIME;
+	got_clock_diff = 1;
+	restore_flags(flags);
+	
+	err = apm_set_power_state(APM_STATE_SUSPEND);
+	if (err)
+		apm_error("suspend", err);
+	set_time();
+}
+
+static void standby(void)
+{
+	int	err;
+
+	err = apm_set_power_state(APM_STATE_STANDBY);
+	if (err)
+		apm_error("standby", err);
+}
+
+static apm_event_t get_event(void)
+{
+	int		error;
+	apm_event_t	event;
+
+	static int notified = 0;
+
+	error = apm_get_event(&event);
+	if (error == APM_SUCCESS)
+		return event;
+
+	if ((error != APM_NO_EVENTS) && (notified++ == 0))
+		apm_error("get_event", error);
+
+	return 0;
+}
+
+static void send_event(apm_event_t event, apm_event_t undo,
+		       struct apm_bios_struct *sender)
+{
+	callback_list_t *	call;
+	callback_list_t *	fix;
+    
+	for (call = callback_list; call != NULL; call = call->next) {
+		if (call->callback(event) && undo) {
+			for (fix = callback_list; fix != call; fix = fix->next)
+				fix->callback(undo);
+			if (apm_bios_info.version > 0x100)
+				apm_set_power_state(APM_STATE_REJECT);
+			return;
+		}
+	}
+
+	queue_event(event, sender);
+}
+
+static void check_events(void)
+{
+	apm_event_t	event;
+
+	while ((event = get_event()) != 0) {
+#ifdef APM_DEBUG
+		if (event <= NR_APM_EVENT_NAME)
+			printk("APM BIOS received %s notify\n",
+			       apm_event_name[event - 1]);
+		else
+			printk("APM BIOS received unknown event 0x%02x\n",
+			       event);
+#endif
+		switch (event) {
+		case APM_SYS_STANDBY:
+		case APM_USER_STANDBY:
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+			if (waiting_for_resume) {
+			    return;
+			}
+			waiting_for_resume = 1;
+#endif
+			send_event(event, APM_STANDBY_RESUME, NULL);
+			if (standbys_pending <= 0)
+				standby();
+			break;
+
+		case APM_USER_SUSPEND:
+#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
+			if (apm_bios_info.version > 0x100)
+				apm_set_power_state(APM_STATE_REJECT);
+			break;
+#endif
+		case APM_SYS_SUSPEND:
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+			if (waiting_for_resume) {
+			    return;
+			}
+			waiting_for_resume = 1;
+#endif
+			send_event(event, APM_NORMAL_RESUME, NULL);
+			if (suspends_pending <= 0)
+				suspend();
+			break;
+
+		case APM_NORMAL_RESUME:
+		case APM_CRITICAL_RESUME:
+		case APM_STANDBY_RESUME:
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+			waiting_for_resume = 0;
+#endif
+			set_time();
+			send_event(event, 0, NULL);
+			break;
+
+		case APM_LOW_BATTERY:
+		case APM_POWER_STATUS_CHANGE:
+			send_event(event, 0, NULL);
+			break;
+
+		case APM_UPDATE_TIME:
+			set_time();
+			break;
+
+		case APM_CRITICAL_SUSPEND:
+			suspend();
+			break;
+		}
+	}
+}
+
+static void do_apm_timer(unsigned long unused)
+{
+	int	err;
+
+	static int	pending_count = 0;
+
+	if (((standbys_pending > 0) || (suspends_pending > 0))
+	    && (apm_bios_info.version > 0x100)
+	    && (pending_count-- <= 0)) {
+		pending_count = 4;
+
+		err = apm_set_power_state(APM_STATE_BUSY);
+		if (err)
+			apm_error("busy", err);
+	}
+
+	if (!(((standbys_pending > 0) || (suspends_pending > 0))
+	      && (apm_bios_info.version == 0x100)))
+		check_events();
+
+	init_timer(&apm_timer);
+	apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
+	add_timer(&apm_timer);
+}
+
+/* Called from sys_idle, must make sure apm_enabled. */
+int apm_do_idle(void)
+{
+#ifdef CONFIG_APM_CPU_IDLE
+	unsigned short	error;
+
+	if (!apm_enabled)
+		return 0;
+
+	APM_SET_CPU_IDLE(error);
+	if (error & 0xff)
+		return 0;
+
+	clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+/* Called from sys_idle, must make sure apm_enabled. */
+void apm_do_busy(void)
+{
+#ifdef CONFIG_APM_CPU_IDLE
+	unsigned short	error;
+
+	if (!apm_enabled)
+		return;
+	
+#ifndef ALWAYS_CALL_BUSY
+	if (!clock_slowed)
+		return;
+#endif
+
+	APM_SET_CPU_BUSY(error);
+
+	clock_slowed = 0;
+#endif
+}
+
+static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
+{
+	if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
+		printk("apm_bios: %s passed bad filp", func);
+		return 1;
+	}
+	return 0;
+}
+
+static int do_read(struct inode *inode, struct file *fp, char *buf, int count)
+{
+	struct apm_bios_struct *	as;
+	int			i;
+	apm_event_t		event;
+	struct wait_queue	wait = { current,	NULL };
+
+	as = fp->private_data;
+	if (check_apm_bios_struct(as, "read"))
+		return -EIO;
+	if (count < sizeof(apm_event_t))
+		return -EINVAL;
+	if (queue_empty(as)) {
+		if (fp->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		add_wait_queue(&process_list, &wait);
+repeat:
+		current->state = TASK_INTERRUPTIBLE;
+		if (queue_empty(as)
+		    && !(current->signal & ~current->blocked)) {
+			schedule();
+			goto repeat;
+		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&process_list, &wait);
+	}
+	i = count;
+	while ((i >= sizeof(event)) && !queue_empty(as)) {
+		event = get_queued_event(as);
+		memcpy_tofs(buf, &event, sizeof(event));
+		switch (event) {
+		case APM_SYS_SUSPEND:
+		case APM_USER_SUSPEND:
+			as->suspends_read++;
+			break;
+
+		case APM_SYS_STANDBY:
+		case APM_USER_STANDBY:
+			as->standbys_read++;
+			break;
+		}
+		buf += sizeof(event);
+		i -= sizeof(event);
+	}
+	if (i < count)
+		return count - i;
+	if (current->signal & ~current->blocked)
+		return -ERESTARTSYS;
+	return 0;
+}
+
+static int do_select(struct inode *inode, struct file *fp, int sel_type,
+		     select_table * wait)
+{
+	struct apm_bios_struct *	as;
+
+	as = fp->private_data;
+	if (check_apm_bios_struct(as, "select"))
+		return 0;
+	if (sel_type != SEL_IN)
+		return 0;
+	if (!queue_empty(as))
+		return 1;
+	select_wait(&process_list, wait);
+	return 0;
+}
+
+static int do_ioctl(struct inode * inode, struct file *filp,
+		    u_int cmd, u_long arg)
+{
+	struct apm_bios_struct *	as;
+
+	as = filp->private_data;
+	if (check_apm_bios_struct(as, "ioctl"))
+		return -EIO;
+	if (!as->suser)
+		return -EPERM;
+	switch (cmd) {
+	case APM_IOC_STANDBY:
+		if (as->standbys_read > 0) {
+			as->standbys_read--;
+			as->standbys_pending--;
+			standbys_pending--;
+		}
+		else
+			send_event(APM_USER_STANDBY, APM_STANDBY_RESUME, as);
+		if (standbys_pending <= 0)
+			standby();
+		break;
+	case APM_IOC_SUSPEND:
+		if (as->suspends_read > 0) {
+			as->suspends_read--;
+			as->suspends_pending--;
+			suspends_pending--;
+		}
+		else
+			send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME, as);
+		if (suspends_pending <= 0)
+			suspend();
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void do_release(struct inode * inode, struct file * filp)
+{
+	struct apm_bios_struct *	as;
+
+	as = filp->private_data;
+	filp->private_data = NULL;
+	if (check_apm_bios_struct(as, "release"))
+		return;
+	if (as->standbys_pending > 0) {
+		standbys_pending -= as->standbys_pending;
+		if (standbys_pending <= 0)
+			standby();
+	}
+	if (as->suspends_pending > 0) {
+		suspends_pending -= as->suspends_pending;
+		if (suspends_pending <= 0)
+			suspend();
+	}
+	if (user_list == as)
+		user_list = as->next;
+	else {
+		struct apm_bios_struct *	as1;
+
+		for (as1 = user_list;
+		     (as1 != NULL) && (as1->next != as);
+		     as1 = as1->next)
+			;
+		if (as1 == NULL)
+			printk("apm_bios: filp not in user list");
+		else
+			as1->next = as->next;
+	}
+	kfree_s(as, sizeof(*as));
+}
+
+static int do_open(struct inode * inode, struct file * filp)
+{
+	struct apm_bios_struct *	as;
+
+	as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL);
+	if (as == NULL) {
+		printk("apm_bios: cannot allocate struct of size %d bytes",
+		       sizeof(*as));
+		return -ENOMEM;
+	}
+	as->magic = APM_BIOS_MAGIC;
+	as->event_tail = as->event_head = 0;
+	as->suspends_pending = as->standbys_pending = 0;
+	as->suspends_read = as->standbys_read = 0;
+	as->suser = suser();
+	as->next = user_list;
+	user_list = as;
+	filp->private_data = as;
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
+{
+	char *		p;
+	unsigned short	bx;
+	unsigned short	cx;
+	unsigned short	dx;
+	unsigned short	error;
+	unsigned short  ac_line_status = 0xff;
+	unsigned short  battery_status = 0xff;
+	unsigned short  battery_flag   = 0xff;
+	int		percentage     = -1;
+	int             time_units     = -1;
+	char            *units         = "?";
+
+	if (!apm_enabled)
+		return 0;
+	p = buf;
+
+	if (!(error = apm_get_power_status(&bx, &cx, &dx))) {
+		ac_line_status = (bx >> 8) & 0xff;
+		battery_status = bx & 0xff;
+		if ((cx & 0xff) != 0xff)
+			percentage = cx & 0xff;
+
+		if (apm_bios_info.version > 0x100) {
+			battery_flag = (cx >> 8) & 0xff;
+			if (dx != 0xffff) {
+				if ((dx & 0x8000) == 0x8000) {
+					units = "min";
+					time_units = dx & 0x7ffe;
+				} else {
+					units = "sec";
+					time_units = dx & 0x7fff;
+				}
+			}
+		}
+	}
+	/* Arguments, with symbols from linux/apm_bios.h.  Information is
+	   from the Get Power Status (0x0a) call unless otherwise noted.
+
+	   0) Linux driver version (this will change if format changes)
+	   1) APM BIOS Version.  Usually 1.0 or 1.1.
+	   2) APM flags from APM Installation Check (0x00):
+	      bit 0: APM_16_BIT_SUPPORT
+	      bit 1: APM_32_BIT_SUPPORT
+	      bit 2: APM_IDLE_SLOWS_CLOCK
+	      bit 3: APM_BIOS_DISABLED
+	      bit 4: APM_BIOS_DISENGAGED
+	   3) AC line status
+	      0x00: Off-line
+	      0x01: On-line
+	      0x02: On backup power (APM BIOS 1.1 only)
+	      0xff: Unknown
+	   4) Battery status
+	      0x00: High
+	      0x01: Low
+	      0x02: Critical
+	      0x03: Charging
+	      0xff: Unknown
+	   5) Battery flag
+	      bit 0: High
+	      bit 1: Low
+	      bit 2: Critical
+	      bit 3: Charging
+	      bit 7: No system battery
+	      0xff: Unknown
+	   6) Remaining battery life (percentage of charge):
+	      0-100: valid
+	      -1: Unknown
+	   7) Remaining battery life (time units):
+	      Number of remaining minutes or seconds
+	      -1: Unknown
+	   8) min = minutes; sec = seconds */
+	    
+	p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+		     driver_version,
+		     (apm_bios_info.version >> 8) & 0xff,
+		     apm_bios_info.version & 0xff,
+		     apm_bios_info.flags,
+		     ac_line_status,
+		     battery_status,
+		     battery_flag,
+		     percentage,
+		     time_units,
+		     units);
+
+	return p - buf;
+}
+#endif
+
+static int apm_disabled = 0;
+
+void apm_setup(char *str, int *ints)
+{
+	if(strcmp(str,"off")==0)
+		apm_disabled=1;
+	if(strcmp(str,"on")==0)
+		apm_disabled=0;
+}
+
+void apm_bios_init(void)
+{
+	unsigned short	bx;
+	unsigned short	cx;
+	unsigned short	dx;
+	unsigned short	error;
+	char *		power_stat;
+	char *		bat_stat;
+	
+	if (apm_disabled == 1)
+	{
+		printk("APM disabled.\n");
+		return;
+	}
+
+	if (apm_bios_info.version == 0) {
+		printk("APM BIOS not found.\n");
+		return;
+	}
+	printk("APM BIOS version %c.%c Flags 0x%02x (Driver version %s)\n",
+	       ((apm_bios_info.version >> 8) & 0xff) + '0',
+	       (apm_bios_info.version & 0xff) + '0',
+	       apm_bios_info.flags,
+	       driver_version);
+	if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
+		printk("    No 32 bit BIOS support\n");
+		return;
+	}
+
+	/*
+	 * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
+	 * but is reportedly a 1.0 BIOS.
+	 */
+	if (apm_bios_info.version == 0x001)
+		apm_bios_info.version = 0x100;
+
+	printk("    Entry %x:%lx cseg16 %x dseg %x",
+	       apm_bios_info.cseg, apm_bios_info.offset,
+	       apm_bios_info.cseg_16, apm_bios_info.dseg);
+	if (apm_bios_info.version > 0x100)
+		printk(" cseg len %x, dseg len %x",
+		       apm_bios_info.cseg_len, apm_bios_info.dseg_len);
+	printk("\n");
+
+	apm_bios_entry.offset = apm_bios_info.offset;
+	apm_bios_entry.segment = APM_CS;
+	set_base(gdt[APM_CS >> 3],
+		 __PAGE_OFFSET + ((unsigned long)apm_bios_info.cseg << 4));
+	set_base(gdt[APM_CS_16 >> 3],
+		 __PAGE_OFFSET + ((unsigned long)apm_bios_info.cseg_16 << 4));
+	set_base(gdt[APM_DS >> 3],
+		 __PAGE_OFFSET + ((unsigned long)apm_bios_info.dseg << 4));
+	if (apm_bios_info.version == 0x100) {
+		set_limit(gdt[APM_CS >> 3], 64 * 1024);
+		set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
+		set_limit(gdt[APM_DS >> 3], 64 * 1024);
+	} else {
+#ifdef APM_RELAX_SEGMENTS
+		/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
+		set_limit(gdt[APM_CS >> 3], 64 * 1024);
+		/* For some unknown machine. */
+		set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
+		/* For the DEC Hinote Ultra CT475 (and others?) */
+		set_limit(gdt[APM_DS >> 3], 64 * 1024);
+#else
+		set_limit(gdt[APM_CS >> 3], apm_bios_info.cseg_len);
+		set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
+		set_limit(gdt[APM_DS >> 3], apm_bios_info.dseg_len);
+#endif
+		apm_bios_info.version = 0x0101;
+		error = apm_driver_version(&apm_bios_info.version);
+		if (error != 0)
+			apm_bios_info.version = 0x100;
+		else {
+			apm_engage_power_management(0x0001);
+			printk( "    Connection version %d.%d\n",
+				(apm_bios_info.version >> 8) & 0xff,
+				apm_bios_info.version & 0xff );
+			apm_bios_info.version = 0x0101;
+		}
+	}
+
+	error = apm_get_power_status(&bx, &cx, &dx);
+	if (error)
+		printk("    Power status not available\n");
+	else {
+		switch ((bx >> 8) & 0xff) {
+		case 0: power_stat = "off line"; break;
+		case 1: power_stat = "on line"; break;
+		case 2: power_stat = "on backup power"; break;
+		default: power_stat = "unknown"; break;
+		}
+		switch (bx & 0xff) {
+		case 0: bat_stat = "high"; break;
+		case 1: bat_stat = "low"; break;
+		case 2: bat_stat = "critical"; break;
+		case 3: bat_stat = "charging"; break;
+		default: bat_stat = "unknown"; break;
+		}
+		printk("    AC %s, battery status %s, battery life ",
+		       power_stat, bat_stat);
+		if ((cx & 0xff) == 0xff)
+			printk("unknown\n");
+		else
+			printk("%d%%\n", cx & 0xff);
+		if (apm_bios_info.version > 0x100) {
+			printk("    battery flag 0x%02x, battery life ",
+			       (cx >> 8) & 0xff);
+			if (dx == 0xffff)
+				printk("unknown\n");
+			else {
+				if ((dx & 0x8000)) 
+					printk("%d minutes\n", dx & 0x7ffe );
+				else
+					printk("%d seconds\n", dx & 0x7fff );
+			}
+		}
+	}
+
+#ifdef CONFIG_APM_DO_ENABLE
+	/*
+	 * This call causes my NEC UltraLite Versa 33/C to hang if it is
+	 * booted with PM disabled but not in the docking station.
+	 * Unfortunate ...
+	 */
+	error = apm_enable_power_management();
+	if (error)
+		apm_error("enable power management", error);
+	if (error == APM_DISABLED)
+		return;
+#endif
+
+	init_timer(&apm_timer);
+	apm_timer.function = do_apm_timer;
+	apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
+	add_timer(&apm_timer);
+
+	register_symtab(&apm_syms);
+
+#ifdef CONFIG_PROC_FS
+	proc_register_dynamic(&proc_root, &apm_proc_entry);
+#endif
+
+	misc_register(&apm_device);
+
+	apm_enabled = 1;
+}
diff -urN linux-2.0.37-pre10/arch/i386/kernel/Makefile linux-2.0.37-pre11/arch/i386/kernel/Makefile
--- linux-2.0.37-pre10/arch/i386/kernel/Makefile	1998-11-15 10:32:46.000000000 -0800
+++ linux-2.0.37-pre11/arch/i386/kernel/Makefile	2003-08-15 15:04:47.000000000 -0700
@@ -23,6 +23,11 @@
 O_TARGET := kernel.o
 O_OBJS   := process.o signal.o entry.o traps.o irq.o vm86.o bios32.o \
             ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o ksyms.o
+OX_OBJS  :=
+
+ifdef CONFIG_APM
+OX_OBJS += apm.o
+endif
 
 ifdef SMP
 
diff -urN linux-2.0.37-pre10/arch/i386/kernel/setup.c linux-2.0.37-pre11/arch/i386/kernel/setup.c
--- linux-2.0.37-pre10/arch/i386/kernel/setup.c	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/arch/i386/kernel/setup.c	2003-08-15 15:04:47.000000000 -0700
@@ -98,9 +98,7 @@
 #ifndef STANDARD_MEMORY_BIOS_CALL
 #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
 #endif
-#ifdef CONFIG_APM
-#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64))
-#endif
+#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
 #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
 #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
diff -urN linux-2.0.37-pre10/arch/i386/kernel/sys_i386.c linux-2.0.37-pre11/arch/i386/kernel/sys_i386.c
--- linux-2.0.37-pre10/arch/i386/kernel/sys_i386.c	1996-04-11 23:49:30.000000000 -0700
+++ linux-2.0.37-pre11/arch/i386/kernel/sys_i386.c	2003-08-15 15:04:47.000000000 -0700
@@ -48,19 +48,23 @@
 	int error;
 	unsigned long flags;
 	struct file * file = NULL;
+	unsigned long b[6];
 
 	error = verify_area(VERIFY_READ, buffer, 6*sizeof(long));
 	if (error)
 		return error;
-	flags = get_user(buffer+3);
+	memcpy_fromfs(&b[0], buffer, 6*sizeof(long));
+	flags = b[3];
 	if (!(flags & MAP_ANONYMOUS)) {
-		unsigned long fd = get_user(buffer+4);
+		unsigned long fd = b[4];
 		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 			return -EBADF;
 	}
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	return do_mmap(file, get_user(buffer), get_user(buffer+1),
-		       get_user(buffer+2), flags, get_user(buffer+5));
+	down(&current->mm->mmap_sem);
+	error = do_mmap(file, b[0], b[1], b[2], flags, b[5]);
+	up(&current->mm->mmap_sem);
+	return error;
 }
 
 extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
diff -urN linux-2.0.37-pre10/arch/i386/kernel/time.c linux-2.0.37-pre11/arch/i386/kernel/time.c
--- linux-2.0.37-pre10/arch/i386/kernel/time.c	1998-06-03 15:17:47.000000000 -0700
+++ linux-2.0.37-pre11/arch/i386/kernel/time.c	2003-08-15 15:04:47.000000000 -0700
@@ -424,6 +424,7 @@
 	  )*60 + sec; /* finally seconds */
 }
 
+/* not static: needed by APM */
 unsigned long get_cmos_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
diff -urN linux-2.0.37-pre10/arch/mips/defconfig linux-2.0.37-pre11/arch/mips/defconfig
--- linux-2.0.37-pre10/arch/mips/defconfig	1997-09-05 20:43:58.000000000 -0700
+++ linux-2.0.37-pre11/arch/mips/defconfig	2003-08-15 15:04:47.000000000 -0700
@@ -75,7 +75,6 @@
 # CONFIG_MS_BUSMOUSE is not set
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
 # CONFIG_SERIAL is not set
 
 #
diff -urN linux-2.0.37-pre10/CREDITS linux-2.0.37-pre11/CREDITS
--- linux-2.0.37-pre10/CREDITS	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/CREDITS	2003-08-15 15:04:47.000000000 -0700
@@ -1192,10 +1192,12 @@
 
 N: Stephen Rothwell
 E: Stephen.Rothwell@canb.auug.org.au
+W: http://www.canb.auug.org.au/~sfr
+P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B  91 88 FA D9 C8 40 AA 02
 D: Boot/setup/build work for setup > 2K
 D: Author, APM driver
-S: 59 Bugden Avenue
-S: Gowrie ACT 2904
+S: 66 Maltby Circuit
+S: Wanniassa ACT 2903
 S: Australia
 
 N: Gerard Roudier
diff -urN linux-2.0.37-pre10/Documentation/Changes linux-2.0.37-pre11/Documentation/Changes
--- linux-2.0.37-pre10/Documentation/Changes	1998-11-15 10:32:41.000000000 -0800
+++ linux-2.0.37-pre11/Documentation/Changes	2003-08-15 15:04:47.000000000 -0700
@@ -513,7 +513,7 @@
 as well.  APM, which is primarily of use in laptops, provides access to
 battery status information and may help to conserve battery power.  The
 support files can be found in
-ftp://tsx-11.mit.edu/pub/linux/packages/laptops/apm/apmd-2.4.tar.gz
+http://www.worldvisions.ca/~apenwarr/apmd/
 
 iBCS and Dosemu
 ===============
diff -urN linux-2.0.37-pre10/drivers/block/cpqarray.c linux-2.0.37-pre11/drivers/block/cpqarray.c
--- linux-2.0.37-pre10/drivers/block/cpqarray.c	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/drivers/block/cpqarray.c	2003-08-15 15:04:47.000000000 -0700
@@ -45,7 +45,7 @@
 #define MOD_DEC_USE_COUNT
 #endif
 
-#define DRIVER_NAME "Compaq SMART2 Driver (v 0.9.8)"
+#define DRIVER_NAME "Compaq SMART2 Driver (v 1.0)"
 
 #define MAJOR_NR COMPAQ_SMART2_MAJOR
 #include <linux/blk.h>
@@ -57,7 +57,7 @@
 #include "ida_ioctl.h"
 
 #define READ_AHEAD	128
-#define NR_CMDS	64
+#define NR_CMDS	128 /* This can probably go as high as ~400 */
 
 #define MAX_CTLR	8
 #define CTLR_SHIFT	8
@@ -79,6 +79,7 @@
 	"SMART-2SL",
 	"SMART-3200",
 	"SMART-3100ES",
+	"SMART-221",
 };
 
 static struct hd_struct * ida;
@@ -112,7 +113,7 @@
 static int pollcomplete(int ctlr);
 static void getgeometry(int ctlr);
 
-static cmdlist_t * cmd_alloc(ctlr_info_t *h, int intr);
+static cmdlist_t * cmd_alloc(ctlr_info_t *h);
 static void cmd_free(ctlr_info_t *h, cmdlist_t *c);
 
 static int sendcmd(
@@ -173,17 +174,14 @@
  */
 #ifdef CONFIG_BLK_CPQ_DA_PCI
 #	ifdef CONFIG_BLK_CPQ_DA_EISA
-#		warning "SMART2: EISA+PCI"
 #		define smart2_read(h, offset)  ( ((h)->vaddr) ? readl((h)->vaddr+(offset)) : inl((h)->ioaddr+(offset)) )
 #		define smart2_write(p, h, offset) ( ((h)->vaddr) ? writel((p), (h)->vaddr+(offset)) : outl((p), (h)->ioaddr+(offset)) )
 #	else
-#		warning "SMART2: PCI"
 #		define smart2_read(h, offset)  readl((h)->vaddr+(offset))
 #		define smart2_write(p, h, offset) writel((p), (h)->vaddr+(offset))
 #	endif
 #else
 #	ifdef CONFIG_BLK_CPQ_DA_EISA
-#		warning "SMART2: EISA"
 #		define smart2_read(h, offset)  inl((h)->vaddr+(offset))
 #		define smart2_write(p, h, offset) outl((p), (h)->vaddr+(offset))
 #	else
@@ -234,8 +232,9 @@
 
 
 /*
- * Place some files in /proc/array/* that contain some information about
- * each controller.  There really isn't much useful in there now.
+ * Get us a file in /proc that says something about each controller.  Right
+ * now, we add entries to /proc, but in the future we should probably get
+ * our own subdir in /proc (/proc/array/ida) and put our stuff in there.
  */
 extern struct inode_operations proc_diskarray_inode_operations;
 struct proc_dir_entry *proc_array = NULL;
@@ -795,7 +794,7 @@
 		goto doreq_done;
 	}
 
-	if ((c = cmd_alloc(h, 1)) == NULL)
+	if ((c = cmd_alloc(h)) == NULL)
 		goto doreq_done;
 
 	blk_dev[MAJOR_NR+ctlr].current_request = creq->next;
@@ -805,15 +804,10 @@
 
 	c->ctlr = ctlr;
 	c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
-	c->hdr.prio = 0;
 	c->hdr.size = sizeof(rblk_t) >> 2;
 	c->size += sizeof(rblk_t);
 
-	c->req.hdr.next = 0;
-	c->req.hdr.rcode = 0;
-	c->req.bp = 0;
 	c->req.hdr.sg_cnt = creq->nr_segments;
-	c->req.hdr.reserved = 0;
 	c->req.hdr.blk = ida[(ctlr<<CTLR_SHIFT) + MINOR(creq->rq_dev)].start_sect + creq->sector;
 	c->req.hdr.blk_cnt = creq->nr_sectors;
 	c->bh = bh;
@@ -1097,21 +1091,12 @@
 	int error;
 
 	DBGINFO(printk("ida_ctlr_ioctl %d %x %p\n", ctlr, dsk, io));
-	if ((c = cmd_alloc(h, 0)) == NULL)
+	if ((c = cmd_alloc(NULL)) == NULL)
 		return -ENOMEM;
 	c->ctlr = ctlr;
 	c->hdr.unit = (io->unit & UNITVALID) ? io->unit &0x7f : dsk;
-	c->hdr.prio = 0;
 	c->hdr.size = sizeof(rblk_t) >> 2;
 	c->size += sizeof(rblk_t);
-
-	c->req.hdr.next = 0;
-	c->req.hdr.rcode = 0;
-	c->req.bp = 0;
-	c->req.hdr.reserved = 0;
-
-	c->req.hdr.blk = 0;
-	c->req.hdr.blk_cnt = 0;
 	c->req.hdr.cmd = io->cmd;
 	c->type = CMD_IOCTL_PEND;
 
@@ -1142,6 +1127,7 @@
 		break;
 	case IDA_WRITE:
 	case IDA_WRITE_MEDIA:
+	case DIAG_PASS_THRU:
 		error = verify_area(VERIFY_READ,
 				(void*)io->sg[0].addr, io->sg[0].size);
 		if (error) goto ioctl_err_exit;
@@ -1174,6 +1160,7 @@
 	switch(io->cmd) {
 	case PASSTHRU_A:
 	case IDA_READ:
+	case DIAG_PASS_THRU:
 		memcpy_tofs((void*)io->sg[0].addr, p, io->sg[0].size);
 		/* fall through and free p */
 	case IDA_WRITE:
@@ -1187,37 +1174,49 @@
 	io->rcode = c->req.hdr.rcode;
 	error = 0;
 ioctl_err_exit:
-	cmd_free(h, c);
+	cmd_free(NULL, c);
 	return error;
 }
 
 /*
- * Sooner or later we'll want to maintain our own cache of
- * commands.  For now, just use kmalloc to get them
+ * Commands are pre-allocated in a large block.  Here we use a simple bitmap
+ * scheme to suballocte them to the driver.  Operations that are not time
+ * critical (and can wait for kmalloc and possibly sleep) can pass in NULL
+ * as the first argument to get a new command.
  */
-cmdlist_t * cmd_alloc(ctlr_info_t *h, int intr)
+cmdlist_t * cmd_alloc(ctlr_info_t *h)
 {
 	cmdlist_t * c;
 	int i;
 
-	do {
-		i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
-		if (i == NR_CMDS)
-			return NULL;
-	} while(set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
+	if (h == NULL) {
+		c = (cmdlist_t*)kmalloc(sizeof(cmdlist_t), GFP_KERNEL);
+	} else {
+		do {
+			i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
+			if (i == NR_CMDS)
+				return NULL;
+		} while(set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
+		c = h->cmd_pool + i;
+		h->nr_allocs++;
+	}
 
-	c = h->cmd_pool + i;
 	memset(c, 0, sizeof(cmdlist_t));
 	c->busaddr = virt_to_bus(c);
-	h->nr_allocs++;
 	return c;
 }
 
 void cmd_free(ctlr_info_t *h, cmdlist_t *c)
 {
-	int i = c - h->cmd_pool;
-	clear_bit(i%32, h->cmd_pool_bits+(i/32));
-	h->nr_frees++;
+	int i;
+
+	if (h == NULL) {
+		kfree(c);
+	} else {
+		i = c - h->cmd_pool;
+		clear_bit(i%32, h->cmd_pool_bits+(i/32));
+		h->nr_frees++;
+	}
 }
 
 /***********************************************************************
@@ -1242,7 +1241,7 @@
 	unsigned long i;
 	ctlr_info_t *info_p = hba[ctlr];
 
-	c = cmd_alloc(info_p, 0);
+	c = cmd_alloc(info_p);
 	c->ctlr = ctlr;
 	c->hdr.unit = log_unit;
 	c->hdr.prio = 0;
@@ -1559,6 +1558,9 @@
 		case 0x40330E11: /* SMART-3100ES */
 			info_p->product = 5;
 			break;
+		case 0x40340E11: /* SMART-221 */
+			info_p->product = 6;
+			break;
 		default:  
 			/*
 			 * Well, its a SMART-2 or better, don't know which
diff -urN linux-2.0.37-pre10/drivers/block/cpqarray.h linux-2.0.37-pre11/drivers/block/cpqarray.h
--- linux-2.0.37-pre10/drivers/block/cpqarray.h	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/drivers/block/cpqarray.h	2003-08-15 15:04:47.000000000 -0700
@@ -55,6 +55,7 @@
 	int usage_count;
 } drv_info_t;
 
+#ifdef __KERNEL__
 typedef struct {
 	int	ctlr;
 	char	devname[8];
@@ -92,5 +93,6 @@
 	struct timer_list timer;
 	unsigned int misc_tflags;
 } ctlr_info_t;
+#endif
 
 #endif /* CPQARRAY_H */
diff -urN linux-2.0.37-pre10/drivers/block/README.smart2 linux-2.0.37-pre11/drivers/block/README.smart2
--- linux-2.0.37-pre10/drivers/block/README.smart2	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/drivers/block/README.smart2	2003-08-15 15:04:47.000000000 -0700
@@ -3,10 +3,7 @@
 WARNING:
 --------
 
-This is still development code.  It seems to work fine for me, but I haven't
-done any real hardcore testing against this driver.  Also, things are likely
-to change, such as the major number used by the device driver as well as the
-names of the /dev entries.
+This code is distributed without warranty.  Use at your own risk.
 
 Installing:
 -----------
diff -urN linux-2.0.37-pre10/drivers/char/apm_bios.c linux-2.0.37-pre11/drivers/char/apm_bios.c
--- linux-2.0.37-pre10/drivers/char/apm_bios.c	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/drivers/char/apm_bios.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,1269 +0,0 @@
-/* -*- linux-c -*-
- * APM BIOS driver for Linux
- * Copyright 1994, 1995, 1996 Stephen Rothwell
- *                           (Stephen.Rothwell@canb.auug.org.au)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * $Id: apm_bios.c,v 0.22 1995/03/09 14:12:02 sfr Exp $
- *
- * October 1995, Rik Faith (faith@cs.unc.edu):
- *    Minor enhancements and updates (to the patch set) for 1.3.x
- *    Documentation
- * January 1996, Rik Faith (faith@cs.unc.edu):
- *    Make /proc/apm easy to format (bump driver version)
- * March 1996, Rik Faith (faith@cs.unc.edu):
- *    Prohibit APM BIOS calls unless apm_enabled.
- *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
- * April 1996, Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
- *    Version 1.0 and 1.1
- * May 1996, Version 1.2
- *
- * History:
- *    0.6b: first version in official kernel, Linux 1.3.46
- *    0.7: changed /proc/apm format, Linux 1.3.58
- *    0.8: fixed gcc 2.7.[12] compilation problems, Linux 1.3.59
- *    0.9: only call bios if bios is present, Linux 1.3.72
- *    1.0: use fixed device number, consolidate /proc/apm into this file,
- *         Linux 1.3.85
- *    1.1: support user-space standby and suspend, power off after system
- *         halted, Linux 1.3.98
- *    1.2: When resetting RTC after resume, take care so that the time
- *         is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
- *         <jtoth@princeton.edu>); improve interaction between
- *         screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
- *    1.2a: Fix OOPs on power off with no APM BIOS
- *         Jan Echternach <echter@informatik.uni-rostock.de>
- *
- * Reference:
- *
- *   Intel Corporation, Microsoft Corporation. Advanced Power Management
- *   (APM) BIOS Interface Specification, Revision 1.1, September 1993.
- *   Intel Order Number 241704-001.  Microsoft Part Number 781-110-X01.
- *
- * [This document is available free from Intel by calling 800.628.8686 (fax
- * 916.356.6100) or 800.548.4725; or via anonymous ftp from
- * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc.  It is also
- * available from Microsoft by calling 206.882.8080.]
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-
-#include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/timer.h>
-#include <linux/fcntl.h>
-#include <linux/malloc.h>
-#include <linux/linkage.h>
-#ifdef CONFIG_PROC_FS
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#endif
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-
-static struct symbol_table	apm_syms = {
-#include <linux/symtab_begin.h>
-	X(apm_register_callback),
-	X(apm_unregister_callback),
-#include <linux/symtab_end.h>
-};
-
-extern unsigned long get_cmos_time(void);
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define	APM_MINOR_DEV	134
-
-/* Configurable options:
- *  
- * CONFIG_APM_IGNORE_USER_SUSPEND: define to ignore USER SUSPEND requests.
- * This is necessary on the NEC Versa M series, which generates these when
- * resuming from SYSTEM SUSPEND.  However, enabling this on other laptops
- * will cause the laptop to generate a CRITICAL SUSPEND when an appropriate
- * USER SUSPEND is ignored -- this may prevent the APM driver from updating
- * the system time on a RESUME.
- *
- * CONFIG_APM_DO_ENABLE: enable APM features at boot time.  From page 36 of
- * the specification: "When disabled, the APM BIOS does not automatically
- * power manage devices, enter the Standby State, enter the Suspend State,
- * or take power saving steps in response to CPU Idle calls."  This driver
- * will make CPU Idle calls when Linux is idle (unless this feature is
- * turned off -- see below).  This should always save battery power, but
- * more complicated APM features will be dependent on your BIOS
- * implementation.  You may need to turn this option off if your computer
- * hangs at boot time when using APM support, or if it beeps continuously
- * instead of suspending.  Turn this off if you have a NEC UltraLite Versa
- * 33/C or a Toshiba T400CDT.  This is off by default since most machines
- * do fine without this feature.
- *
- * CONFIG_APM_CPU_IDLE: enable calls to APM CPU Idle/CPU Busy inside the
- * idle loop.  On some machines, this can activate improved power savings,
- * such as a slowed CPU clock rate, when the machine is idle.  These idle
- * call is made after the idle loop has run for some length of time (e.g.,
- * 333 mS).  On some machines, this will cause a hang at boot time or
- * whenever the CPU becomes idle.
- *
- * CONFIG_APM_DISPLAY_BLANK: enable console blanking using the APM.  Some
- * laptops can use this to turn of the LCD backlight when the VC screen
- * blanker blanks the screen.  Note that this is only used by the VC screen
- * blanker, and probably won't turn off the backlight when using X11.  Some
- * problems have been reported when using this option with gpm (if you'd
- * like to debug this, please do so).
- *
- * CONFIG_APM_IGNORE_MULTIPLE_SUSPEND: The IBM TP560 bios seems to insist
- * on returning multiple suspend/standby events whenever one occurs.  We
- * really only need one at a time, so just ignore any beyond the first.
- * This is probably safe on most laptops.
- *
- * If you are debugging the APM support for your laptop, note that code for
- * all of these options is contained in this file, so you can #define or
- * #undef these on the next line to avoid recompiling the whole kernel.
- *
- */
-
-/* KNOWN PROBLEM MACHINES:
- *
- * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
- *                         [Confirmed by TI representative]
- * U: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
- *                    [Confirmed by BIOS disassembly]
- * P: Toshiba 1950S: battery life information only gets updated after resume
- *
- * Legend: U = unusable with APM patches
- *         P = partially usable with APM patches
- */
-
-/*
- * Define to have debug messages.
- */
-#undef APM_DEBUG
-
-/*
- * Define to always call the APM BIOS busy routine even if the clock was
- * not slowed by the idle routine.
- */
-#define ALWAYS_CALL_BUSY
-
-/*
- * Define to disable interrupts in APM BIOS calls (the CPU Idle BIOS call
- * should turn interrupts on before it does a 'hlt').
- */
-#define APM_NOINTS
-
-/*
- * Define to make the APM BIOS calls zero all data segment registers (do
- * that if an incorrect BIOS implementation will cause a kernel panic if it
- * tries to write to arbitrary memory).
- */
-#define APM_ZERO_SEGS
-
-/*
- * Define to make all set_limit calls use 64k limits.  The APM 1.1 BIOS is
- * supposed to provide limit information that it recognizes.  Many machines
- * do this correctly, but many others do not restrict themselves to their
- * claimed limit.  When this happens, they will cause a segmentation
- * violation in the kernel at boot time.  Most BIOS's, however, will
- * respect a 64k limit, so we use that.  If you want to be pedantic and
- * hold your BIOS to its claims, then undefine this.
- */
-#define APM_RELAX_SEGMENTS
-
-/*
- * Need to poll the APM BIOS every second
- */
-#define APM_CHECK_TIMEOUT	(HZ)
-
-/*
- * These are the actual BIOS calls in assembler.  Depending on
- * APM_ZERO_SEGS and APM_NOINTS, we are being really paranoid here!  Not
- * only are interrupts disabled, but all the segment registers (except SS)
- * are saved and zeroed this means that if the BIOS tries to reference any
- * data without explicitly loading the segment registers, the kernel will
- * fault immediately rather than have some unforeseen circumstances for the
- * rest of the kernel.  And it will be very obvious!  :-) Doing this
- * depends on CS referring to the same physical memory as DS so that DS can
- * be zeroed before the call. Unfortunately, we can't do anything about the
- * stack segment/pointer.  Also, we tell the compiler that everything could
- * change.
- */
-#ifdef APM_NOINTS
-#	define APM_DO_CLI	"cli\n\t"
-#else
-#	define APM_DO_CLI
-#endif
-#ifdef APM_ZERO_SEGS
-#	define APM_DO_ZERO_SEGS	\
-		"pushl %%ds\n\t" \
-		"pushl %%es\n\t" \
-		"pushl %%fs\n\t" \
-		"pushl %%gs\n\t" \
-		"xorl %%edx, %%edx\n\t" \
-		"mov %%dx, %%ds\n\t" \
-		"mov %%dx, %%es\n\t" \
-		"mov %%dx, %%fs\n\t" \
-		"mov %%dx, %%gs\n\t"
-#	define APM_DO_RESTORE_SEGS	\
-		"popl %%gs\n\t" \
-		"popl %%fs\n\t" \
-		"popl %%es\n\t" \
-		"popl %%ds\n\t"
-#else
-#	define APM_DO_ZERO_SEGS
-#	define APM_DO_RESTORE_SEGS
-#endif
-
-#define APM_BIOS_CALL(error_reg) \
-	__asm__ __volatile__( \
-		APM_DO_ZERO_SEGS \
-		"pushfl\n\t" \
-		APM_DO_CLI \
-		"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t" \
-		"setc %%" # error_reg "\n\t" \
-		"popfl\n\t" \
-		APM_DO_RESTORE_SEGS
-#define APM_BIOS_CALL_END \
-		: "ax", "bx", "cx", "dx", "si", "di", "bp", "memory")
-
-#ifdef CONFIG_APM_CPU_IDLE
-#define APM_SET_CPU_IDLE(error) \
-	APM_BIOS_CALL(al) \
-	: "=a" (error) \
-	: "a" (0x5305) \
-	APM_BIOS_CALL_END
-#endif
-
-#define APM_SET_CPU_BUSY(error) \
-	APM_BIOS_CALL(al) \
-	: "=a" (error) \
-	: "a" (0x5306) \
-	APM_BIOS_CALL_END
-
-#define APM_SET_POWER_STATE(state, error) \
-	APM_BIOS_CALL(al) \
-	: "=a" (error) \
-	: "a" (0x5307), "b" (0x0001), "c" (state) \
-	APM_BIOS_CALL_END
-
-#ifdef CONFIG_APM_DISPLAY_BLANK
-#define APM_SET_DISPLAY_POWER_STATE(state, error) \
-	APM_BIOS_CALL(al) \
-	: "=a" (error) \
-	: "a" (0x5307), "b" (0x01ff), "c" (state) \
-	APM_BIOS_CALL_END
-#endif
-
-#ifdef CONFIG_APM_DO_ENABLE
-#define APM_ENABLE_POWER_MANAGEMENT(device, error) \
-	APM_BIOS_CALL(al) \
-	: "=a" (error) \
-	: "a" (0x5308), "b" (device), "c" (1) \
-	APM_BIOS_CALL_END
-#endif
-
-#define APM_GET_POWER_STATUS(bx, cx, dx, error) \
-	APM_BIOS_CALL(al) \
-	: "=a" (error), "=b" (bx), "=c" (cx), "=d" (dx) \
-	: "a" (0x530a), "b" (1) \
-	APM_BIOS_CALL_END
-
-#define APM_GET_EVENT(event, error)	\
-	APM_BIOS_CALL(al) \
-	: "=a" (error), "=b" (event) \
-	: "a" (0x530b) \
-	APM_BIOS_CALL_END
-
-#define APM_DRIVER_VERSION(ver, ax, error) \
-	APM_BIOS_CALL(bl) \
-	: "=a" (ax), "=b" (error) \
-	: "a" (0x530e), "b" (0), "c" (ver) \
-	APM_BIOS_CALL_END
-
-#define APM_ENGAGE_POWER_MANAGEMENT(device, error) \
-	APM_BIOS_CALL(al) \
-	: "=a" (error) \
-	: "a" (0x530f), "b" (device), "c" (1) \
-	APM_BIOS_CALL_END
-
-/*
- * Forward declarations
- */
-static void	suspend(void);
-static void	standby(void);
-static void	set_time(void);
-
-static void	check_events(void);
-static void	do_apm_timer(unsigned long);
-
-static int	do_open(struct inode *, struct file *);
-static void	do_release(struct inode *, struct file *);
-static int	do_read(struct inode *, struct file *, char *, int);
-static int	do_select(struct inode *, struct file *, int,
-			  select_table *);
-static int	do_ioctl(struct inode *, struct file *, u_int, u_long);
-
-#ifdef CONFIG_PROC_FS
-static int	apm_get_info(char *, char **, off_t, int, int);
-#endif
-
-extern int	apm_register_callback(int (*)(apm_event_t));
-extern void	apm_unregister_callback(int (*)(apm_event_t));
-
-/*
- * Local variables
- */
-static asmlinkage struct {
-	unsigned long	offset;
-	unsigned short	segment;
-}				apm_bios_entry;
-static int			apm_enabled = 0;
-#ifdef CONFIG_APM_CPU_IDLE
-static int			clock_slowed = 0;
-#endif
-static int			suspends_pending = 0;
-static int			standbys_pending = 0;
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-static int			waiting_for_resume = 0;
-#endif
-
-static long			clock_cmos_diff;
-static int			got_clock_diff = 0;
-
-static struct wait_queue *	process_list = NULL;
-static struct apm_bios_struct *	user_list = NULL;
-
-static struct timer_list	apm_timer;
-
-static char			driver_version[] = "1.2";/* no spaces */
-
-#ifdef APM_DEBUG
-static char *	apm_event_name[] = {
-	"system standby",
-	"system suspend",
-	"normal resume",
-	"critical resume",
-	"low battery",
-	"power status change",
-	"update time",
-	"critical suspend",
-	"user standby",
-	"user suspend",
-	"system standby resume"
-};
-#define NR_APM_EVENT_NAME	\
-		(sizeof(apm_event_name) / sizeof(apm_event_name[0]))
-#endif
-
-static struct file_operations apm_bios_fops = {
-	NULL,		/* lseek */
-	do_read,
-	NULL,		/* write */
-	NULL,		/* readdir */
-	do_select,
-	do_ioctl,
-	NULL,		/* mmap */
-	do_open,
-	do_release,
-	NULL,		/* fsync */
-	NULL		/* fasync */
-};
-
-static struct miscdevice apm_device = {
-	APM_MINOR_DEV,
-	"apm",
-	&apm_bios_fops
-};
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry	apm_proc_entry = {
-        0, 3, "apm", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, apm_get_info
-};
-#endif
-
-typedef struct callback_list_t {
-	int (*				callback)(apm_event_t);
-	struct callback_list_t *	next;
-} callback_list_t;
-
-static callback_list_t *	callback_list = NULL;
-
-typedef struct lookup_t {
-	int	key;
-	char *	msg;
-} lookup_t;
-
-static const lookup_t error_table[] = {
-/* N/A	{ APM_SUCCESS,		"Operation succeeded" }, */
-	{ APM_DISABLED,		"Power management disabled" },
-	{ APM_CONNECTED,	"Real mode interface already connected" },
-	{ APM_NOT_CONNECTED,	"Interface not connected" },
-	{ APM_16_CONNECTED,	"16 bit interface already connected" },
-/* N/A	{ APM_16_UNSUPPORTED,	"16 bit interface not supported" }, */
-	{ APM_32_CONNECTED,	"32 bit interface already connected" },
-	{ APM_32_UNSUPPORTED,	"32 bit interface not supported" },
-	{ APM_BAD_DEVICE,	"Unrecognized device ID" },
-	{ APM_BAD_PARAM,	"Parameter out of range" },
-	{ APM_NOT_ENGAGED,	"Interface not engaged" },
-	{ APM_BAD_STATE,	"Unable to enter requested state" },
-/* N/A	{ APM_NO_EVENTS,	"No events pending" }, */
-	{ APM_NOT_PRESENT,	"No APM present" }
-};
-#define ERROR_COUNT	(sizeof(error_table)/sizeof(lookup_t))
-
-static int apm_driver_version(u_short *val)
-{
-	u_short	error;
-
-	APM_DRIVER_VERSION(*val, *val, error);
-
-	if (error & 0xff)
-		return (*val >> 8);
-	return APM_SUCCESS;
-}
-
-static int apm_get_event(apm_event_t *event)
-{
-	u_short	error;
-
-	APM_GET_EVENT(*event, error);
-	if (error & 0xff)
-		return (error >> 8);
-	return APM_SUCCESS;
-}
-
-static int apm_set_power_state(u_short state)
-{
-	u_short	error;
-	
-	APM_SET_POWER_STATE(state, error);
-	if (error & 0xff)
-		return (error >> 8);
-	return APM_SUCCESS;
-}
-
-#ifdef CONFIG_APM_POWER_OFF
-void apm_power_off(void)
-{
-	if (apm_enabled)
-		(void) apm_set_power_state(APM_STATE_OFF);
-}
-#endif
-
-#ifdef CONFIG_APM_DISPLAY_BLANK
-/* Called by apm_display_blank and apm_display_unblank when apm_enabled. */
-static int apm_set_display_power_state(u_short state)
-{
-	u_short	error;
-
-	APM_SET_DISPLAY_POWER_STATE(state, error);
-	if (error & 0xff)
-		return (error >> 8);
-	return APM_SUCCESS;
-}
-#endif
-
-#ifdef CONFIG_APM_DO_ENABLE
-/* Called by apm_setup if apm_enabled will be true. */
-static int apm_enable_power_management(void)
-{
-	u_short	error;
-
-	APM_ENABLE_POWER_MANAGEMENT((apm_bios_info.version > 0x100)
-				    ? 0x0001 : 0xffff,
-				    error);
-	if (error & 0xff)
-		return (error >> 8);
-	return APM_SUCCESS;
-}
-#endif
-
-static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
-{
-	u_short	error;
-
-	APM_GET_POWER_STATUS(*status, *bat, *life, error);
-	if (error & 0xff)
-		return (error >> 8);
-	return APM_SUCCESS;
-}
-
-static int apm_engage_power_management(u_short device)
-{
-	u_short	error;
-
-	APM_ENGAGE_POWER_MANAGEMENT(device, error);
-	if (error & 0xff)
-		return (error >> 8);
-	return APM_SUCCESS;
-}
-
-static void apm_error(char *str, int err)
-{
-	int	i;
-
-	for (i = 0; i < ERROR_COUNT; i++)
-		if (error_table[i].key == err) break;
-	if (i < ERROR_COUNT)
-		printk("apm_bios: %s: %s\n", str, error_table[i].msg);
-	else
-		printk("apm_bios: %s: unknown error code %#2.2x\n", str, err);
-}
-
-/* Called from console driver -- must make sure apm_enabled. */
-int apm_display_blank(void)
-{
-#ifdef CONFIG_APM_DISPLAY_BLANK
-	int	error;
-
-	if (!apm_enabled)
-		return 0;
-	error = apm_set_display_power_state(APM_STATE_STANDBY);
-	if (error == APM_SUCCESS)
-		return 1;
-	apm_error("set display standby", error);
-#endif
-	return 0;
-}
-
-/* Called from console driver -- must make sure apm_enabled. */
-int apm_display_unblank(void)
-{
-#ifdef CONFIG_APM_DISPLAY_BLANK
-	int error;
-
-	if (!apm_enabled)
-		return 0;
-	error = apm_set_display_power_state(APM_STATE_READY);
-	if (error == APM_SUCCESS)
-		return 1;
-	apm_error("set display ready", error);
-#endif
-	return 0;
-}
-
-int apm_register_callback(int (*callback)(apm_event_t))
-{
-	callback_list_t *	new;
-
-	new = kmalloc(sizeof(callback_list_t), GFP_KERNEL);
-	if (new == NULL)
-		return -ENOMEM;
-	new->callback = callback;
-	new->next = callback_list;
-	callback_list = new;
-	return 0;
-}
-
-void apm_unregister_callback(int (*callback)(apm_event_t))
-{
-	callback_list_t **	ptr;
-	callback_list_t *	old;
-
-	ptr = &callback_list;
-	for (ptr = &callback_list; *ptr != NULL; ptr = &(*ptr)->next)
-		if ((*ptr)->callback == callback)
-			break;
-	old = *ptr;
-	*ptr = old->next;
-	kfree_s(old, sizeof(callback_list_t));
-}
-	
-static int queue_empty(struct apm_bios_struct * as)
-{
-	return as->event_head == as->event_tail;
-}
-
-static apm_event_t get_queued_event(struct apm_bios_struct * as)
-{
-	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-	return as->events[as->event_tail];
-}
-
-static int queue_event(apm_event_t event, struct apm_bios_struct *sender)
-{
-	struct apm_bios_struct *	as;
-	
-	if (user_list == NULL)
-		return 0;
-	for (as = user_list; as != NULL; as = as->next) {
-		if (as == sender)
-			continue;
-		as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
-		if (as->event_head == as->event_tail) {
-			static int notified;
-
-			if (notified == 0) {
-			    printk( "apm_bios: an event queue overflowed\n" );
-			    notified = 1;
-			}
-			as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-		}
-		as->events[as->event_head] = event;
-		if (!as->suser)
-			continue;
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			as->suspends_pending++;
-			suspends_pending++;
-			break;
-
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			as->standbys_pending++;
-			standbys_pending++;
-			break;
-		}
-	}
-	wake_up_interruptible(&process_list);
-	return 1;
-}
-
-static void set_time(void)
-{
-	unsigned long	flags;
-
-	if (!got_clock_diff)	/* Don't know time zone, can't set clock */
-		return;
-
-	save_flags(flags);
-	cli();
-	CURRENT_TIME = get_cmos_time() + clock_cmos_diff;
-	restore_flags(flags);
-}
-
-static void suspend(void)
-{
-	unsigned long	flags;
-	int		err;
-
-				/* Estimate time zone so that set_time can
-                                   update the clock */
-	save_flags(flags);
-	clock_cmos_diff = -get_cmos_time();
-	cli();
-	clock_cmos_diff += CURRENT_TIME;
-	got_clock_diff = 1;
-	restore_flags(flags);
-	
-	err = apm_set_power_state(APM_STATE_SUSPEND);
-	if (err)
-		apm_error("suspend", err);
-	set_time();
-}
-
-static void standby(void)
-{
-	int	err;
-
-	err = apm_set_power_state(APM_STATE_STANDBY);
-	if (err)
-		apm_error("standby", err);
-}
-
-static apm_event_t get_event(void)
-{
-	int		error;
-	apm_event_t	event;
-
-	static int notified = 0;
-
-	error = apm_get_event(&event);
-	if (error == APM_SUCCESS)
-		return event;
-
-	if ((error != APM_NO_EVENTS) && (notified++ == 0))
-		apm_error("get_event", error);
-
-	return 0;
-}
-
-static void send_event(apm_event_t event, apm_event_t undo,
-		       struct apm_bios_struct *sender)
-{
-	callback_list_t *	call;
-	callback_list_t *	fix;
-    
-	for (call = callback_list; call != NULL; call = call->next) {
-		if (call->callback(event) && undo) {
-			for (fix = callback_list; fix != call; fix = fix->next)
-				fix->callback(undo);
-			if (apm_bios_info.version > 0x100)
-				apm_set_power_state(APM_STATE_REJECT);
-			return;
-		}
-	}
-
-	queue_event(event, sender);
-}
-
-static void check_events(void)
-{
-	apm_event_t	event;
-
-	while ((event = get_event()) != 0) {
-#ifdef APM_DEBUG
-		if (event <= NR_APM_EVENT_NAME)
-			printk("APM BIOS received %s notify\n",
-			       apm_event_name[event - 1]);
-		else
-			printk("APM BIOS received unknown event 0x%02x\n",
-			       event);
-#endif
-		switch (event) {
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-			if (waiting_for_resume) {
-			    return;
-			}
-			waiting_for_resume = 1;
-#endif
-			send_event(event, APM_STANDBY_RESUME, NULL);
-			if (standbys_pending <= 0)
-				standby();
-			break;
-
-		case APM_USER_SUSPEND:
-#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
-			if (apm_bios_info.version > 0x100)
-				apm_set_power_state(APM_STATE_REJECT);
-			break;
-#endif
-		case APM_SYS_SUSPEND:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-			if (waiting_for_resume) {
-			    return;
-			}
-			waiting_for_resume = 1;
-#endif
-			send_event(event, APM_NORMAL_RESUME, NULL);
-			if (suspends_pending <= 0)
-				suspend();
-			break;
-
-		case APM_NORMAL_RESUME:
-		case APM_CRITICAL_RESUME:
-		case APM_STANDBY_RESUME:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-			waiting_for_resume = 0;
-#endif
-			set_time();
-			send_event(event, 0, NULL);
-			break;
-
-		case APM_LOW_BATTERY:
-		case APM_POWER_STATUS_CHANGE:
-			send_event(event, 0, NULL);
-			break;
-
-		case APM_UPDATE_TIME:
-			set_time();
-			break;
-
-		case APM_CRITICAL_SUSPEND:
-			suspend();
-			break;
-		}
-	}
-}
-
-static void do_apm_timer(unsigned long unused)
-{
-	int	err;
-
-	static int	pending_count = 0;
-
-	if (((standbys_pending > 0) || (suspends_pending > 0))
-	    && (apm_bios_info.version > 0x100)
-	    && (pending_count-- <= 0)) {
-		pending_count = 4;
-
-		err = apm_set_power_state(APM_STATE_BUSY);
-		if (err)
-			apm_error("busy", err);
-	}
-
-	if (!(((standbys_pending > 0) || (suspends_pending > 0))
-	      && (apm_bios_info.version == 0x100)))
-		check_events();
-
-	init_timer(&apm_timer);
-	apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
-	add_timer(&apm_timer);
-}
-
-/* Called from sys_idle, must make sure apm_enabled. */
-int apm_do_idle(void)
-{
-#ifdef CONFIG_APM_CPU_IDLE
-	unsigned short	error;
-
-	if (!apm_enabled)
-		return 0;
-
-	APM_SET_CPU_IDLE(error);
-	if (error & 0xff)
-		return 0;
-
-	clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
-	return 1;
-#else
-	return 0;
-#endif
-}
-
-/* Called from sys_idle, must make sure apm_enabled. */
-void apm_do_busy(void)
-{
-#ifdef CONFIG_APM_CPU_IDLE
-	unsigned short	error;
-
-	if (!apm_enabled)
-		return;
-	
-#ifndef ALWAYS_CALL_BUSY
-	if (!clock_slowed)
-		return;
-#endif
-
-	APM_SET_CPU_BUSY(error);
-
-	clock_slowed = 0;
-#endif
-}
-
-static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
-{
-	if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-		printk("apm_bios: %s passed bad filp", func);
-		return 1;
-	}
-	return 0;
-}
-
-static int do_read(struct inode *inode, struct file *fp, char *buf, int count)
-{
-	struct apm_bios_struct *	as;
-	int			i;
-	apm_event_t		event;
-	struct wait_queue	wait = { current,	NULL };
-
-	as = fp->private_data;
-	if (check_apm_bios_struct(as, "read"))
-		return -EIO;
-	if (count < sizeof(apm_event_t))
-		return -EINVAL;
-	if (queue_empty(as)) {
-		if (fp->f_flags & O_NONBLOCK)
-			return -EAGAIN;
-		add_wait_queue(&process_list, &wait);
-repeat:
-		current->state = TASK_INTERRUPTIBLE;
-		if (queue_empty(as)
-		    && !(current->signal & ~current->blocked)) {
-			schedule();
-			goto repeat;
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&process_list, &wait);
-	}
-	i = count;
-	while ((i >= sizeof(event)) && !queue_empty(as)) {
-		event = get_queued_event(as);
-		memcpy_tofs(buf, &event, sizeof(event));
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			as->suspends_read++;
-			break;
-
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			as->standbys_read++;
-			break;
-		}
-		buf += sizeof(event);
-		i -= sizeof(event);
-	}
-	if (i < count)
-		return count - i;
-	if (current->signal & ~current->blocked)
-		return -ERESTARTSYS;
-	return 0;
-}
-
-static int do_select(struct inode *inode, struct file *fp, int sel_type,
-		     select_table * wait)
-{
-	struct apm_bios_struct *	as;
-
-	as = fp->private_data;
-	if (check_apm_bios_struct(as, "select"))
-		return 0;
-	if (sel_type != SEL_IN)
-		return 0;
-	if (!queue_empty(as))
-		return 1;
-	select_wait(&process_list, wait);
-	return 0;
-}
-
-static int do_ioctl(struct inode * inode, struct file *filp,
-		    u_int cmd, u_long arg)
-{
-	struct apm_bios_struct *	as;
-
-	as = filp->private_data;
-	if (check_apm_bios_struct(as, "ioctl"))
-		return -EIO;
-	if (!as->suser)
-		return -EPERM;
-	switch (cmd) {
-	case APM_IOC_STANDBY:
-		if (as->standbys_read > 0) {
-			as->standbys_read--;
-			as->standbys_pending--;
-			standbys_pending--;
-		}
-		else
-			send_event(APM_USER_STANDBY, APM_STANDBY_RESUME, as);
-		if (standbys_pending <= 0)
-			standby();
-		break;
-	case APM_IOC_SUSPEND:
-		if (as->suspends_read > 0) {
-			as->suspends_read--;
-			as->suspends_pending--;
-			suspends_pending--;
-		}
-		else
-			send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME, as);
-		if (suspends_pending <= 0)
-			suspend();
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void do_release(struct inode * inode, struct file * filp)
-{
-	struct apm_bios_struct *	as;
-
-	as = filp->private_data;
-	filp->private_data = NULL;
-	if (check_apm_bios_struct(as, "release"))
-		return;
-	if (as->standbys_pending > 0) {
-		standbys_pending -= as->standbys_pending;
-		if (standbys_pending <= 0)
-			standby();
-	}
-	if (as->suspends_pending > 0) {
-		suspends_pending -= as->suspends_pending;
-		if (suspends_pending <= 0)
-			suspend();
-	}
-	if (user_list == as)
-		user_list = as->next;
-	else {
-		struct apm_bios_struct *	as1;
-
-		for (as1 = user_list;
-		     (as1 != NULL) && (as1->next != as);
-		     as1 = as1->next)
-			;
-		if (as1 == NULL)
-			printk("apm_bios: filp not in user list");
-		else
-			as1->next = as->next;
-	}
-	kfree_s(as, sizeof(*as));
-}
-
-static int do_open(struct inode * inode, struct file * filp)
-{
-	struct apm_bios_struct *	as;
-
-	as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL);
-	if (as == NULL) {
-		printk("apm_bios: cannot allocate struct of size %d bytes",
-		       sizeof(*as));
-		return -ENOMEM;
-	}
-	as->magic = APM_BIOS_MAGIC;
-	as->event_tail = as->event_head = 0;
-	as->suspends_pending = as->standbys_pending = 0;
-	as->suspends_read = as->standbys_read = 0;
-	as->suser = suser();
-	as->next = user_list;
-	user_list = as;
-	filp->private_data = as;
-	return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
-{
-	char *		p;
-	unsigned short	bx;
-	unsigned short	cx;
-	unsigned short	dx;
-	unsigned short	error;
-	unsigned short  ac_line_status = 0xff;
-	unsigned short  battery_status = 0xff;
-	unsigned short  battery_flag   = 0xff;
-	int		percentage     = -1;
-	int             time_units     = -1;
-	char            *units         = "?";
-
-	if (!apm_enabled)
-		return 0;
-	p = buf;
-
-	if (!(error = apm_get_power_status(&bx, &cx, &dx))) {
-		ac_line_status = (bx >> 8) & 0xff;
-		battery_status = bx & 0xff;
-		if ((cx & 0xff) != 0xff)
-			percentage = cx & 0xff;
-
-		if (apm_bios_info.version > 0x100) {
-			battery_flag = (cx >> 8) & 0xff;
-			if (dx != 0xffff) {
-				if ((dx & 0x8000) == 0x8000) {
-					units = "min";
-					time_units = dx & 0x7ffe;
-				} else {
-					units = "sec";
-					time_units = dx & 0x7fff;
-				}
-			}
-		}
-	}
-	/* Arguments, with symbols from linux/apm_bios.h.  Information is
-	   from the Get Power Status (0x0a) call unless otherwise noted.
-
-	   0) Linux driver version (this will change if format changes)
-	   1) APM BIOS Version.  Usually 1.0 or 1.1.
-	   2) APM flags from APM Installation Check (0x00):
-	      bit 0: APM_16_BIT_SUPPORT
-	      bit 1: APM_32_BIT_SUPPORT
-	      bit 2: APM_IDLE_SLOWS_CLOCK
-	      bit 3: APM_BIOS_DISABLED
-	      bit 4: APM_BIOS_DISENGAGED
-	   3) AC line status
-	      0x00: Off-line
-	      0x01: On-line
-	      0x02: On backup power (APM BIOS 1.1 only)
-	      0xff: Unknown
-	   4) Battery status
-	      0x00: High
-	      0x01: Low
-	      0x02: Critical
-	      0x03: Charging
-	      0xff: Unknown
-	   5) Battery flag
-	      bit 0: High
-	      bit 1: Low
-	      bit 2: Critical
-	      bit 3: Charging
-	      bit 7: No system battery
-	      0xff: Unknown
-	   6) Remaining battery life (percentage of charge):
-	      0-100: valid
-	      -1: Unknown
-	   7) Remaining battery life (time units):
-	      Number of remaining minutes or seconds
-	      -1: Unknown
-	   8) min = minutes; sec = seconds */
-	    
-	p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-		     driver_version,
-		     (apm_bios_info.version >> 8) & 0xff,
-		     apm_bios_info.version & 0xff,
-		     apm_bios_info.flags,
-		     ac_line_status,
-		     battery_status,
-		     battery_flag,
-		     percentage,
-		     time_units,
-		     units);
-
-	return p - buf;
-}
-#endif
-
-static int apm_disabled = 0;
-
-void apm_setup(char *str, int *ints)
-{
-	if(strcmp(str,"off")==0)
-		apm_disabled=1;
-	if(strcmp(str,"on")==0)
-		apm_disabled=0;
-}
-
-void apm_bios_init(void)
-{
-	unsigned short	bx;
-	unsigned short	cx;
-	unsigned short	dx;
-	unsigned short	error;
-	char *		power_stat;
-	char *		bat_stat;
-	
-	if (apm_disabled == 1)
-	{
-		printk("APM disabled.\n");
-		return;
-	}
-
-	if (apm_bios_info.version == 0) {
-		printk("APM BIOS not found.\n");
-		return;
-	}
-	printk("APM BIOS version %c.%c Flags 0x%02x (Driver version %s)\n",
-	       ((apm_bios_info.version >> 8) & 0xff) + '0',
-	       (apm_bios_info.version & 0xff) + '0',
-	       apm_bios_info.flags,
-	       driver_version);
-	if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
-		printk("    No 32 bit BIOS support\n");
-		return;
-	}
-
-	/*
-	 * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
-	 * but is reportedly a 1.0 BIOS.
-	 */
-	if (apm_bios_info.version == 0x001)
-		apm_bios_info.version = 0x100;
-
-	printk("    Entry %x:%lx cseg16 %x dseg %x",
-	       apm_bios_info.cseg, apm_bios_info.offset,
-	       apm_bios_info.cseg_16, apm_bios_info.dseg);
-	if (apm_bios_info.version > 0x100)
-		printk(" cseg len %x, dseg len %x",
-		       apm_bios_info.cseg_len, apm_bios_info.dseg_len);
-	printk("\n");
-
-	apm_bios_entry.offset = apm_bios_info.offset;
-	apm_bios_entry.segment = APM_CS;
-	set_base(gdt[APM_CS >> 3],
-		 __PAGE_OFFSET + ((unsigned long)apm_bios_info.cseg << 4));
-	set_base(gdt[APM_CS_16 >> 3],
-		 __PAGE_OFFSET + ((unsigned long)apm_bios_info.cseg_16 << 4));
-	set_base(gdt[APM_DS >> 3],
-		 __PAGE_OFFSET + ((unsigned long)apm_bios_info.dseg << 4));
-	if (apm_bios_info.version == 0x100) {
-		set_limit(gdt[APM_CS >> 3], 64 * 1024);
-		set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
-		set_limit(gdt[APM_DS >> 3], 64 * 1024);
-	} else {
-#ifdef APM_RELAX_SEGMENTS
-		/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
-		set_limit(gdt[APM_CS >> 3], 64 * 1024);
-		/* For some unknown machine. */
-		set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
-		/* For the DEC Hinote Ultra CT475 (and others?) */
-		set_limit(gdt[APM_DS >> 3], 64 * 1024);
-#else
-		set_limit(gdt[APM_CS >> 3], apm_bios_info.cseg_len);
-		set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
-		set_limit(gdt[APM_DS >> 3], apm_bios_info.dseg_len);
-#endif
-		apm_bios_info.version = 0x0101;
-		error = apm_driver_version(&apm_bios_info.version);
-		if (error != 0)
-			apm_bios_info.version = 0x100;
-		else {
-			apm_engage_power_management(0x0001);
-			printk( "    Connection version %d.%d\n",
-				(apm_bios_info.version >> 8) & 0xff,
-				apm_bios_info.version & 0xff );
-			apm_bios_info.version = 0x0101;
-		}
-	}
-
-	error = apm_get_power_status(&bx, &cx, &dx);
-	if (error)
-		printk("    Power status not available\n");
-	else {
-		switch ((bx >> 8) & 0xff) {
-		case 0: power_stat = "off line"; break;
-		case 1: power_stat = "on line"; break;
-		case 2: power_stat = "on backup power"; break;
-		default: power_stat = "unknown"; break;
-		}
-		switch (bx & 0xff) {
-		case 0: bat_stat = "high"; break;
-		case 1: bat_stat = "low"; break;
-		case 2: bat_stat = "critical"; break;
-		case 3: bat_stat = "charging"; break;
-		default: bat_stat = "unknown"; break;
-		}
-		printk("    AC %s, battery status %s, battery life ",
-		       power_stat, bat_stat);
-		if ((cx & 0xff) == 0xff)
-			printk("unknown\n");
-		else
-			printk("%d%%\n", cx & 0xff);
-		if (apm_bios_info.version > 0x100) {
-			printk("    battery flag 0x%02x, battery life ",
-			       (cx >> 8) & 0xff);
-			if (dx == 0xffff)
-				printk("unknown\n");
-			else {
-				if ((dx & 0x8000)) 
-					printk("%d minutes\n", dx & 0x7ffe );
-				else
-					printk("%d seconds\n", dx & 0x7fff );
-			}
-		}
-	}
-
-#ifdef CONFIG_APM_DO_ENABLE
-	/*
-	 * This call causes my NEC UltraLite Versa 33/C to hang if it is
-	 * booted with PM disabled but not in the docking station.
-	 * Unfortunate ...
-	 */
-	error = apm_enable_power_management();
-	if (error)
-		apm_error("enable power management", error);
-	if (error == APM_DISABLED)
-		return;
-#endif
-
-	init_timer(&apm_timer);
-	apm_timer.function = do_apm_timer;
-	apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
-	add_timer(&apm_timer);
-
-	register_symtab(&apm_syms);
-
-#ifdef CONFIG_PROC_FS
-	proc_register_dynamic(&proc_root, &apm_proc_entry);
-#endif
-
-	misc_register(&apm_device);
-
-	apm_enabled = 1;
-}
diff -urN linux-2.0.37-pre10/drivers/char/Config.in linux-2.0.37-pre11/drivers/char/Config.in
--- linux-2.0.37-pre10/drivers/char/Config.in	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/drivers/char/Config.in	2003-08-15 15:04:47.000000000 -0700
@@ -58,15 +58,6 @@
   comment 'Set IObase/IRQ/DMA for ftape in ./drivers/char/ftape/Makefile'
 fi
 
-bool 'Advanced Power Management BIOS support' CONFIG_APM
-if [ "$CONFIG_APM" = "y" ]; then
-  bool '   Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
-  bool '   Enable PM at boot time' CONFIG_APM_DO_ENABLE
-  bool '   Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
-  bool '   Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
-  bool '   Power off on shutdown' CONFIG_APM_POWER_OFF
-  bool '   Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-fi
 if [ "$CONFIG_ALPHA_BOOK1" = "y" ]; then
   bool 'Tadpole ANA H8 Support'	CONFIG_H8
 fi
diff -urN linux-2.0.37-pre10/drivers/char/Makefile linux-2.0.37-pre11/drivers/char/Makefile
--- linux-2.0.37-pre10/drivers/char/Makefile	1998-11-15 10:32:53.000000000 -0800
+++ linux-2.0.37-pre11/drivers/char/Makefile	2003-08-15 15:04:47.000000000 -0700
@@ -200,7 +200,6 @@
 endif
 
 ifdef CONFIG_APM
-LX_OBJS += apm_bios.o
 M = y
 endif
 
diff -urN linux-2.0.37-pre10/drivers/char/tty_io.c linux-2.0.37-pre11/drivers/char/tty_io.c
--- linux-2.0.37-pre10/drivers/char/tty_io.c	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/drivers/char/tty_io.c	2003-08-15 15:04:47.000000000 -0700
@@ -1932,8 +1932,9 @@
 {
 	int	retval;
 	struct tty_driver *p;
-	int	found = 0;
+	int	i, found = 0;
 	const char *othername = NULL;
+	struct termios *tp;
 	
 	if (*driver->refcount)
 		return -EBUSY;
@@ -1963,6 +1964,18 @@
 	if (driver->next)
 		driver->next->prev = driver->prev;
 
+	for (i = 0; i < driver->num; i++) {
+		tp = driver->termios[i];
+		if (tp != NULL) {
+			kfree_s(tp, sizeof(struct termios));
+			driver->termios[i] = NULL;
+		}
+		tp = driver->termios_locked[i];
+		if (tp != NULL) {
+			kfree_s(tp, sizeof(struct termios));
+			driver->termios_locked[i] = NULL;
+		}
+	}
 	return 0;
 }
 
diff -urN linux-2.0.37-pre10/drivers/net/eql.c linux-2.0.37-pre11/drivers/net/eql.c
--- linux-2.0.37-pre10/drivers/net/eql.c	1998-06-03 15:17:47.000000000 -0700
+++ linux-2.0.37-pre11/drivers/net/eql.c	2003-08-15 15:04:47.000000000 -0700
@@ -426,9 +426,9 @@
 		if (slave_dev->hard_header == NULL
 		|| slave_dev->hard_header(skb,slave_dev,
 			ETH_P_IP,NULL,NULL,skb->len) >= 0) {
+			slave->bytes_queued += skb->len; 
 			dev_queue_xmit (skb, slave_dev, 1);
 			eql->stats->tx_packets++;
-			slave->bytes_queued += skb->len; 
 			/* dev_kfree_skb(skb, FREE_WRITE); */
 			return 0;
 		}
diff -urN linux-2.0.37-pre10/drivers/net/ne.c linux-2.0.37-pre11/drivers/net/ne.c
--- linux-2.0.37-pre10/drivers/net/ne.c	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/drivers/net/ne.c	2003-08-15 15:04:47.000000000 -0700
@@ -43,6 +43,7 @@
 #include <linux/bios32.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <linux/delay.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff -urN linux-2.0.37-pre10/fs/open.c linux-2.0.37-pre11/fs/open.c
--- linux-2.0.37-pre10/fs/open.c	1996-11-30 02:21:19.000000000 -0800
+++ linux-2.0.37-pre11/fs/open.c	2003-08-15 15:04:47.000000000 -0700
@@ -68,6 +68,11 @@
 	int error;
 	struct iattr newattrs;
 
+
+        /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
+        if ((off_t) length < 0)
+        	return -EINVAL;
+
 	down(&inode->i_sem);
 	newattrs.ia_size = length;
 	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
diff -urN linux-2.0.37-pre10/include/linux/apm_bios.h linux-2.0.37-pre11/include/linux/apm_bios.h
--- linux-2.0.37-pre10/include/linux/apm_bios.h	1998-11-15 10:33:16.000000000 -0800
+++ linux-2.0.37-pre11/include/linux/apm_bios.h	2003-08-15 15:04:47.000000000 -0700
@@ -3,7 +3,7 @@
 
 /*
  * Include file for the interface to an APM BIOS
- * Copyright 1994, 1995 Stephen Rothwell (Stephen.Rothwell@pd.necisa.oz.au)
+ * Copyright 1994-1999 Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
  *
  * 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
@@ -14,8 +14,6 @@
  * 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.
- *
- * $Id: apm_bios.h,v 0.9 1995/03/09 13:50:05 sfr Exp $
  */
 
 typedef unsigned short	apm_event_t;
@@ -79,6 +77,7 @@
 extern struct apm_bios_info	apm_bios_info;
 
 extern void		apm_bios_init(void);
+extern void		apm_setup(char *, int *);
 
 extern int		apm_register_callback(int (*callback)(apm_event_t));
 extern void		apm_unregister_callback(int (*callback)(apm_event_t));
diff -urN linux-2.0.37-pre10/init/main.c linux-2.0.37-pre11/init/main.c
--- linux-2.0.37-pre10/init/main.c	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/init/main.c	2003-08-15 15:04:47.000000000 -0700
@@ -39,6 +39,9 @@
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
 
 #include <asm/bugs.h>
 
@@ -481,9 +484,6 @@
 #ifdef CONFIG_BAYCOM
 	{ "baycom=", baycom_setup },
 #endif
-#ifdef CONFIG_APM
-	{ "apm=", apm_setup },
-#endif
 #ifdef CONFIG_BLK_CPQ_DA
 #ifdef CONFIG_BLK_CPQ_DA_EISA
        { "smart2=", cpqarray_setup },
@@ -509,6 +509,9 @@
 #ifdef CONFIG_PARIDE_PG
        { "pg.", pg_setup },
 #endif
+#ifdef CONFIG_APM
+	{ "apm=", apm_setup },
+#endif
        { 0, 0 }
 } ;
 
diff -urN linux-2.0.37-pre10/linux/Documentation/README.DAC960 linux-2.0.37-pre11/linux/Documentation/README.DAC960
--- linux-2.0.37-pre10/linux/Documentation/README.DAC960	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/linux/Documentation/README.DAC960	1969-12-31 16:00:00.000000000 -0800
@@ -1,670 +0,0 @@
-	   Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
-
-			Version 2.0.0 for Linux 2.0.36
-			Version 2.2.0 for Linux 2.2.3
-
-			      PRODUCTION RELEASE
-
-				 23 March 1999
-
-			       Leonard N. Zubkoff
-			       Dandelion Digital
-			       lnz@dandelion.com
-
-	 Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-
-
-				 INTRODUCTION
-
-Mylex, Inc. designs and manufactures a variety of high performance PCI RAID
-controllers.  Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont,
-California 94555, USA and can be reached at 510/796-6100 or on the World Wide
-Web at http://www.mylex.com.  Mylex RAID Technical Support can be reached by
-electronic mail at support@mylex.com (for eXtremeRAID 1100 and older DAC960
-models) or techsup@mylex.com (for AcceleRAID models), by voice at 510/608-2400,
-or by FAX at 510/745-7715.  Contact information for offices in Europe and Japan
-is available on the Web site.
-
-The latest information on Linux support for DAC960 PCI RAID Controllers, as
-well as the most recent release of this driver, will always be available from
-my Linux Home Page at URL "http://www.dandelion.com/Linux/".  The Linux DAC960
-driver supports all current DAC960 PCI family controllers including the
-AcceleRAID models, as well as the eXtremeRAID 1100; see below for a complete
-list.  For simplicity, in most places this documentation refers to DAC960
-generically rather than explicitly listing all the models.
-
-Bug reports should be sent via electronic mail to "lnz@dandelion.com".  Please
-include with the bug report the complete configuration messages reported by the
-driver at startup, along with any subsequent system messages relevant to the
-controller's operation, and a detailed description of your system's hardware
-configuration.
-
-Please consult the DAC960 RAID controller documentation for detailed
-information regarding installation and configuration of the controllers.  This
-document primarily provides information specific to the Linux DAC960 support.
-
-
-				DRIVER FEATURES
-
-The DAC960 RAID controllers are supported solely as high performance RAID
-controllers, not as interfaces to arbitrary SCSI devices.  The Linux DAC960
-driver operates at the block device level, the same level as the SCSI and IDE
-drivers.  Unlike other RAID controllers currently supported on Linux, the
-DAC960 driver is not dependent on the SCSI subsystem, and hence avoids all the
-complexity and unnecessary code that would be associated with an implementation
-as a SCSI driver.  The DAC960 driver is designed for as high a performance as
-possible with no compromises or extra code for compatibility with lower
-performance devices.  The DAC960 driver includes extensive error logging and
-online configuration management capabilities.  Except for initial configuration
-of the controller and adding new disk drives, most everything can be handled
-from Linux while the system is operational.
-
-The DAC960 driver is architected to support up to 8 controllers per system.
-Each DAC960 controller can support up to 15 disk drives per channel, for a
-maximum of 45 drives on a three channel controller.  The drives installed on a
-controller are divided into one or more "Drive Groups", and then each Drive
-Group is subdivided further into 1 to 32 "Logical Drives".  Each Logical Drive
-has a specific RAID Level and caching policy associated with it, and it appears
-to Linux as a single block device.  Logical Drives are further subdivided into
-up to 7 partitions through the normal Linux and PC disk partitioning schemes.
-Logical Drives are also known as "System Drives", and Drive Groups are also
-called "Packs".  Both terms are in use in the Mylex documentation; I have
-chosen to standardize on the more generic "Logical Drive" and "Drive Group".
-
-DAC960 RAID disk devices are named in the style of the Device File System
-(DEVFS).  The device corresponding to Logical Drive D on Controller C is
-referred to as /dev/rd/cCdD, and the partitions are called /dev/rd/cCdDp1
-through /dev/rd/cCdDp7.  For example, partition 3 of Logical Drive 5 on
-Controller 2 is referred to as /dev/rd/c2d5p3.  Note that unlike with SCSI
-disks the device names will not change in the event of a disk drive failure.
-The DAC960 driver is assigned major numbers 48 - 55 with one major number per
-controller.  The 8 bits of minor number are divided into 5 bits for the Logical
-Drive and 3 bits for the partition.
-
-
-		 SUPPORTED DAC960/DAC1100 PCI RAID CONTROLLERS
-
-The following list comprises the supported DAC960 and DAC1100 PCI RAID
-Controllers as of the date of this document.  It is recommended that anyone
-purchasing a Mylex PCI RAID Controller not in the following table contact the
-author beforehand to verify that it is or will be supported.
-
-eXtremeRAID 1100 (DAC1164P)
-	    3 Wide Ultra-2/LVD SCSI channels
-	    233MHz StrongARM SA 110 Processor
-	    64 Bit PCI (backward compatible with 32 Bit PCI slots)
-	    16MB/32MB/64MB Parity SDRAM Memory with Battery Backup
-
-AcceleRAID 250 (DAC960PTL1)
-	    Uses onboard Symbios SCSI chips on certain motherboards
-	    Also includes one onboard Wide Ultra-2/LVD SCSI Channel
-	    66MHz Intel i960RD RISC Processor
-	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
-
-AcceleRAID 200 (DAC960PTL0)
-	    Uses onboard Symbios SCSI chips on certain motherboards
-	    Includes no onboard SCSI Channels
-	    66MHz Intel i960RD RISC Processor
-	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
-
-AcceleRAID 150 (DAC960PRL)
-	    Uses onboard Symbios SCSI chips on certain motherboards
-	    Also includes one onboard Wide Ultra-2/LVD SCSI Channel
-	    33MHz Intel i960RP RISC Processor
-	    4MB Parity EDO Memory
-
-DAC960PJ    1/2/3 Wide Ultra SCSI-3 Channels
-	    66MHz Intel i960RD RISC Processor
-	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
-
-DAC960PG    1/2/3 Wide Ultra SCSI-3 Channels
-	    33MHz Intel i960RP RISC Processor
-	    4MB/8MB ECC EDO Memory
-
-DAC960PU    1/2/3 Wide Ultra SCSI-3 Channels
-	    Intel i960CF RISC Processor
-	    4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
-
-DAC960PD    1/2/3 Wide Fast SCSI-2 Channels
-	    Intel i960CF RISC Processor
-	    4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
-
-DAC960PL    1/2/3 Wide Fast SCSI-2 Channels
-	    Intel i960 RISC Processor
-	    2MB/4MB/8MB/16MB/32MB DRAM Memory
-
-For the eXtremeRAID 1100, firmware version 5.06-0-52 or above is required.
-
-For the AcceleRAID 250, 200, and 150, firmware version 4.06-0-57 or above is
-required.
-
-For the DAC960PJ and DAC960PG, firmware version 4.06-0-00 or above is required.
-
-For the DAC960PU, DAC960PD, and DAC960PL, firmware version 3.51-0-04 or above
-is required.
-
-Note that earlier revisions of the DAC960PU, DAC960PD, and DAC960PL controllers
-were delivered with version 2.xx firmware.  Version 2.xx firmware is not
-supported by this driver and no support is envisioned.  Contact Mylex RAID
-Technical Support to inquire about upgrading controllers with version 2.xx
-firmware to version 3.51-0-04.  Upgrading to version 3.xx firmware requires
-installation of higher capacity Flash ROM chips, and not all DAC960PD and
-DAC960PL controllers can be upgraded.
-
-Please note that not all SCSI disk drives are suitable for use with DAC960
-controllers, and only particular firmware versions of any given model may
-actually function correctly.  Similarly, not all motherboards have a BIOS that
-properly initializes the AcceleRAID 250, AcceleRAID 200, AcceleRAID 150,
-DAC960PJ, and DAC960PG because the Intel i960RD/RP is a multi-function device.
-If in doubt, contact Mylex RAID Technical Support (support@mylex.com) to verify
-compatibility.  Mylex makes available a hard disk compatibility list by FTP at
-ftp://ftp.mylex.com/pub/dac960/diskcomp.html.
-
-
-			      DRIVER INSTALLATION
-
-This distribution was prepared for Linux kernel version 2.0.36 or 2.2.3.
-
-To install the DAC960 RAID driver, you may use the following commands,
-replacing "/usr/src" with wherever you keep your Linux kernel source tree:
-
-  cd /usr/src
-  tar -xvzf DAC960-2.0.0.tar.gz (or DAC960-2.2.0.tar.gz)
-  mv README.DAC960 linux/Documentation
-  mv DAC960.[ch] linux/drivers/block
-  patch -p0 < DAC960.patch
-  cd linux
-  make config
-  make depend
-  make bzImage (or zImage)
-
-Then install "arch/i386/boot/bzImage" or "arch/i386/boot/zImage" as your
-standard kernel, run lilo if appropriate, and reboot.
-
-To create the necessary devices in /dev, the "make_rd" script included in
-"DAC960-Utilities.tar.gz" from http://www.dandelion.com/Linux/ may be used.
-LILO 21 and FDISK v2.9 include DAC960 support; also included in this archive
-are patches to LILO 20 and FDISK v2.8 that add DAC960 support, along with
-statically linked executables of LILO and FDISK.  This modified version of LILO
-will allow booting from a DAC960 controller and/or mounting the root file
-system from a DAC960.  Unfortunately, installing directly onto a DAC960 will be
-problematic until the various Linux distribution vendors update their
-installation utilities.  VA Research Linux Systems (http://www.varesearch.com)
-has created an installation CD capable of installing its modified Red Hat 5.2
-environment directly onto DAC960 controllers, and copies of this CD are being
-made available to owners of supported Mylex RAID products by VA Research in
-cooperation with Mylex.  Please see http://www.mylex.com/support/prsfrm.html to
-request an installation CD.
-
-
-			      INSTALLATION NOTES
-
-Before installing Linux or adding DAC960 logical drives to an existing Linux
-system, the controller must first be configured to provide one or more logical
-drives using the BIOS Configuration Utility or DACCF.  Please note that since
-there are only at most 6 usable partitions on each logical drive, systems
-requiring more partitions should subdivide a drive group into multiple logical
-drives, each of which can have up to 6 partitions.  Also, note that with large
-disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63) rather
-than accepting the default 2GB BIOS Geometry (128/32); failing to so do will
-cause the logical drive geometry to have more than 65535 cylinders which will
-make it impossible for FDISK to be used properly.  The 8GB BIOS Geometry can be
-enabled by configuring the DAC960 BIOS, which is accessible via Alt-M during
-the BIOS initialization sequence.
-
-For maximum performance and the most efficient E2FSCK performance, it is
-recommended that EXT2 file systems be built with a 4KB block size and 16 block
-stride to match the DAC960 controller's 64KB default stripe size.  The command
-"mke2fs -b 4096 -R stride=16 <device>" is appropriate.
-
-
-		      DAC960 ANNOUNCEMENTS MAILING LIST
-
-The DAC960 Announcements Mailing List provides a forum for informing Linux
-users of new driver releases and other announcements regarding Linux support
-for DAC960 PCI RAID Controllers.  To join the mailing list, send a message to
-"dac960-announce-request@dandelion.com" with the line "subscribe" in the
-message body.
-
-
-		CONTROLLER CONFIGURATION AND STATUS MONITORING
-
-The DAC960 RAID controllers running firmware 4.06 or above include a Background
-Initialization facility so that system downtime is minimized both for initial
-installation and subsequent configuration of additional storage.  The BIOS
-Configuration Utility (accessible via Alt-R during the BIOS initialization
-sequence) is used to quickly configure the controller, and then the logical
-drives that have been created are available for immediate use even while they
-are still being initialized by the controller.  The primary need for online
-configuration and status monitoring is then to avoid system downtime when disk
-drives fail and must be replaced.  Note that with a SAF-TE (SCSI Accessed
-Fault-Tolerant Enclosure) enclosure, the controller is able to rebuild failed
-drives automatically as soon as a drive replacement is made available.
-
-The primary interfaces for controller configuration and status monitoring are
-special files created in the /proc/rd/... hierarchy along with the normal
-system console logging mechanism.  Whenever the system is operating, the DAC960
-driver queries each controller for status information every 10 seconds, and
-checks for additional conditions every 60 seconds.  The initial status of each
-controller is always available for controller N in /proc/rd/cN/initial_status,
-and the current status as of the last status monitoring query is available in
-/proc/rd/cN/current_status.  In addition, status changes are also logged by the
-driver to the system console and will appear in the log files maintained by
-syslog.  The progress of asynchronous rebuild or consistency check operations
-is also available in /proc/rd/cN/current_status, and progress messages are
-logged to the system console at most every 60 seconds.
-
-To simplify the monitoring process for custom software, the special file
-/proc/rd/status returns "OK" when all DAC960 controllers in the system are
-operating normally and no failures have occurred, or "ALERT" if any logical
-drives are offline or critical or any non-standby physical drives are dead.
-
-Configuration commands for controller N are available via the special file
-/proc/rd/cN/user_command.  A human readable command can be written to this
-special file to initiate a configuration operation, and the results of the
-operation can then be read back from the special file in addition to being
-logged to the system console.  The shell command sequence
-
-  echo "<configuration-command>" > /proc/rd/c0/user_command
-  cat /proc/rd/c0/user_command
-
-is typically used to execute configuration commands.  The configuration
-commands are:
-
-  flush-cache
-
-    The "flush-cache" command flushes the controller's cache.  The system
-    automatically flushes the cache at shutdown or if the driver module is
-    unloaded, so this command is only needed to be certain a write back cache
-    is flushed to disk before the system is powered off by a command to a UPS.
-    Note that the flush-cache command also stops an asynchronous rebuild or
-    consistency check, so it should not be used except when the system is being
-    halted.
-
-  kill <channel>:<target-id>
-
-    The "kill" command marks the physical drive <channel>:<target-id> as DEAD.
-    This command is provided primarily for testing, and should not be used
-    during normal system operation.
-
-  make-online <channel>:<target-id>
-
-    The "make-online" command changes the physical drive <channel>:<target-id>
-    from status DEAD to status ONLINE.  In cases where multiple physical drives
-    have been killed simultaneously, this command may be used to bring them
-    back online, after which a consistency check is advisable.
-
-    Warning: make-online should only be used on a dead physical drive that is
-    an active part of a drive group, never on a standby drive.
-
-  make-standby <channel>:<target-id>
-
-    The "make-standby" command changes physical drive <channel>:<target-id>
-    from status DEAD to status STANDBY.  It should only be used in cases where
-    a dead drive was replaced after an automatic rebuild was performed onto a
-    standby drive.  It cannot be used to add a standby drive to the controller
-    configuration if one was not created initially; the BIOS Configuration
-    Utility must be used for that currently.
-
-  rebuild <channel>:<target-id>
-
-    The "rebuild" command initiates an asynchronous rebuild onto physical drive
-    <channel>:<target-id>.  It should only be used when a dead drive has been
-    replaced.
-
-  check-consistency <logical-drive-number>
-
-    The "check-consistency" command initiates an asynchronous consistency check
-    of <logical-drive-number> with automatic restoration.  It can be used
-    whenever it is desired to verify the consistency of the redundancy
-    information.
-
-  cancel-rebuild
-  cancel-consistency-check
-
-    The "cancel-rebuild" and "cancel-consistency-check" commands cancel any
-    rebuild or consistency check operations previously initiated.
-
-
-	       EXAMPLE I - DRIVE FAILURE WITHOUT A STANDBY DRIVE
-
-The following annotated logs demonstrate the controller configuration and and
-online status monitoring capabilities of the Linux DAC960 Driver.  The test
-configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
-DAC960PJ controller.  The physical drives are configured into a single drive
-group without a standby drive, and the drive group has been configured into two
-logical drives, one RAID-5 and one RAID-6.  First, here is the current status
-of the RAID configuration:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
-Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-Configuring Mylex DAC960PJ PCI RAID Controller
-  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
-  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
-  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
-  Controller Queue Depth: 128, Maximum Blocks per Command: 128
-  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
-  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Online, 2201600 blocks
-    1:2 - Disk: Online, 2201600 blocks
-    1:3 - Disk: Online, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
-  No Rebuild or Consistency Check in Progress
-
-gwynedd:/u/lnz# cat /proc/rd/status
-OK
-
-The above messages indicate that everything is healthy, and /proc/rd/status
-returns "OK" indicating that there are no problems with any DAC960 controller
-in the system.  For demonstration purposes, while I/O is active Physical Drive
-1:1 is now disconnected, simulating a drive failure.  The failure is noted by
-the driver within 10 seconds of the controller's having detected it, and the
-driver logs the following console status messages indicating that Logical
-Drives 0 and 1 are now CRITICAL as a result of Physical Drive 1:1 being DEAD:
-
-DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
-DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
-DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
-DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
-DAC960#0: Physical Drive 1:1 killed because of timeout on SCSI command
-DAC960#0: Physical Drive 1:1 is now DEAD
-
-The Sense Keys logged here are just Check Condition / Unit Attention conditions
-arising from a SCSI bus reset that is forced by the controller during its error
-recovery procedures.  Concurrently with the above, the driver status available
-from /proc/rd also reflects the drive failure.  The status message in
-/proc/rd/status has changed from "OK" to "ALERT":
-
-gwynedd:/u/lnz# cat /proc/rd/status
-ALERT
-
-and /proc/rd/c0/current_status has been updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-  ...
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Dead, 2201600 blocks
-    1:2 - Disk: Online, 2201600 blocks
-    1:3 - Disk: Online, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
-  No Rebuild or Consistency Check in Progress
-
-Since there are no standby drives configured, the system can continue to access
-the logical drives in a performance degraded mode until the failed drive is
-replaced and a rebuild operation completed to restore the redundancy of the
-logical drives.  Once Physical Drive 1:1 is replaced with a properly
-functioning drive, or if the physical drive was killed without having failed
-(e.g., due to electrical problems on the SCSI bus), the user can instruct the
-controller to initiate a rebuild operation onto the newly replaced drive:
-
-gwynedd:/u/lnz# echo "rebuild 1:1" > /proc/rd/c0/user_command
-gwynedd:/u/lnz# cat /proc/rd/c0/user_command
-Rebuild of Physical Drive 1:1 Initiated
-
-The echo command instructs the controller to initiate an asynchronous rebuild
-operation onto Physical Drive 1:1, and the status message that results from the
-operation is then available for reading from /proc/rd/c0/user_command, as well
-as being logged to the console by the driver.
-
-Within 10 seconds of this command the driver logs the initiation of the
-asynchronous rebuild operation:
-
-DAC960#0: Rebuild of Physical Drive 1:1 Initiated
-DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
-DAC960#0: Physical Drive 1:1 is now WRITE-ONLY
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 1% completed
-
-and /proc/rd/c0/current_status is updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-  ...
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Write-Only, 2201600 blocks
-    1:2 - Disk: Online, 2201600 blocks
-    1:3 - Disk: Online, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
-  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 6% completed
-
-As the rebuild progresses, the current status in /proc/rd/c0/current_status is
-updated every 10 seconds:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-  ...
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Write-Only, 2201600 blocks
-    1:2 - Disk: Online, 2201600 blocks
-    1:3 - Disk: Online, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
-  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 15% completed
-
-and every minute a progress message is logged to the console by the driver:
-
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 32% completed
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 63% completed
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 94% completed
-DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 94% completed
-
-Finally, the rebuild completes successfully.  The driver logs the status of the 
-logical and physical drives and the rebuild completion:
-
-DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
-DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
-DAC960#0: Physical Drive 1:1 is now ONLINE
-DAC960#0: Rebuild Completed Successfully
-
-/proc/rd/c0/current_status is updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-  ...
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Online, 2201600 blocks
-    1:2 - Disk: Online, 2201600 blocks
-    1:3 - Disk: Online, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
-  Rebuild Completed Successfully
-
-and /proc/rd/status indicates that everything is healthy once again:
-
-gwynedd:/u/lnz# cat /proc/rd/status
-OK
-
-
-		EXAMPLE II - DRIVE FAILURE WITH A STANDBY DRIVE
-
-The following annotated logs demonstrate the controller configuration and and
-online status monitoring capabilities of the Linux DAC960 Driver.  The test
-configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
-DAC960PJ controller.  The physical drives are configured into a single drive
-group with a standby drive, and the drive group has been configured into two
-logical drives, one RAID-5 and one RAID-6.  First, here is the current status
-of the RAID configuration:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
-Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-Configuring Mylex DAC960PJ PCI RAID Controller
-  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
-  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
-  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
-  Controller Queue Depth: 128, Maximum Blocks per Command: 128
-  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
-  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Online, 2201600 blocks
-    1:2 - Disk: Online, 2201600 blocks
-    1:3 - Disk: Standby, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
-  No Rebuild or Consistency Check in Progress
-
-gwynedd:/u/lnz# cat /proc/rd/status
-OK
-
-The above messages indicate that everything is healthy, and /proc/rd/status
-returns "OK" indicating that there are no problems with any DAC960 controller
-in the system.  For demonstration purposes, while I/O is active Physical Drive
-1:2 is now disconnected, simulating a drive failure.  The failure is noted by
-the driver within 10 seconds of the controller's having detected it, and the
-driver logs the following console status messages:
-
-DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
-DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
-DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
-DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
-DAC960#0: Physical Drive 1:2 killed because of timeout on SCSI command
-DAC960#0: Physical Drive 1:2 is now DEAD
-DAC960#0: Physical Drive 1:2 killed because it was removed
-
-Since a standby drive is configured, the controller automatically begins
-rebuilding onto the standby drive:
-
-DAC960#0: Physical Drive 1:3 is now WRITE-ONLY
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
-
-Concurrently with the above, the driver status available from /proc/rd also
-reflects the drive failure and automatic rebuild.  The status message in
-/proc/rd/status has changed from "OK" to "ALERT":
-
-gwynedd:/u/lnz# cat /proc/rd/status
-ALERT
-
-and /proc/rd/c0/current_status has been updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-  ...
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Online, 2201600 blocks
-    1:2 - Disk: Dead, 2201600 blocks
-    1:3 - Disk: Write-Only, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
-  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
-
-As the rebuild progresses, the current status in /proc/rd/c0/current_status is
-updated every 10 seconds:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-  ...
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Online, 2201600 blocks
-    1:2 - Disk: Dead, 2201600 blocks
-    1:3 - Disk: Write-Only, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
-  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
-
-and every minute a progress message is logged on the console by the driver:
-
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
-DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 76% completed
-DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 66% completed
-DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 84% completed
-
-Finally, the rebuild completes successfully.  The driver logs the status of the 
-logical and physical drives and the rebuild completion:
-
-DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
-DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
-DAC960#0: Physical Drive 1:3 is now ONLINE
-DAC960#0: Rebuild Completed Successfully
-
-/proc/rd/c0/current_status is updated:
-
-***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
-Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-Configuring Mylex DAC960PJ PCI RAID Controller
-  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
-  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
-  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
-  Controller Queue Depth: 128, Maximum Blocks per Command: 128
-  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
-  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Online, 2201600 blocks
-    1:2 - Disk: Dead, 2201600 blocks
-    1:3 - Disk: Online, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
-  Rebuild Completed Successfully
-
-and /proc/rd/status indicates that everything is healthy once again:
-
-gwynedd:/u/lnz# cat /proc/rd/status
-OK
-
-Note that the absence of a viable standby drive does not create an "ALERT"
-status.  Once dead Physical Drive 1:2 has been replaced, the controller must be
-told that this has occurred and that the newly replaced drive should become the
-new standby drive:
-
-gwynedd:/u/lnz# echo "make-standby 1:2" > /proc/rd/c0/user_command
-gwynedd:/u/lnz# cat /proc/rd/c0/user_command
-Make Standby of Physical Drive 1:2 Succeeded
-
-The echo command instructs the controller to make Physical Drive 1:2 into a
-standby drive, and the status message that results from the operation is then
-available for reading from /proc/rd/c0/user_command, as well as being logged to
-the console by the driver.  Within 60 seconds of this command the driver logs:
-
-DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
-DAC960#0: Physical Drive 1:2 is now STANDBY
-DAC960#0: Make Standby of Physical Drive 1:2 Succeeded
-
-and /proc/rd/c0/current_status is updated:
-
-gwynedd:/u/lnz# cat /proc/rd/c0/current_status
-  ...
-  Physical Devices:
-    0:1 - Disk: Online, 2201600 blocks
-    0:2 - Disk: Online, 2201600 blocks
-    0:3 - Disk: Online, 2201600 blocks
-    1:1 - Disk: Online, 2201600 blocks
-    1:2 - Disk: Standby, 2201600 blocks
-    1:3 - Disk: Online, 2201600 blocks
-  Logical Drives:
-    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
-    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
-  Rebuild Completed Successfully
diff -urN linux-2.0.37-pre10/linux/drivers/block/DAC960.c linux-2.0.37-pre11/linux/drivers/block/DAC960.c
--- linux-2.0.37-pre10/linux/drivers/block/DAC960.c	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/linux/drivers/block/DAC960.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,3013 +0,0 @@
-/*
-
-  Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers
-
-  Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-
-  This program is free software; you may redistribute and/or modify it under
-  the terms of the GNU General Public License Version 2 as published by the
-  Free Software Foundation.
-
-  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 complete details.
-
-  The author respectfully requests that any modifications to this software be
-  sent directly to him for evaluation and testing.
-
-*/
-
-
-#define DAC960_DriverVersion			"2.0.0"
-#define DAC960_DriverDate			"23 March 1999"
-
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/blk.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/hdreg.h>
-#include <linux/ioport.h>
-#include <linux/locks.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <linux/proc_fs.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/bios32.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/segment.h>
-#include "DAC960.h"
-
-
-/*
-  DAC960_ControllerCount is the number of DAC960 Controllers detected.
-*/
-
-static int
-  DAC960_ControllerCount =			0;
-
-
-/*
-  DAC960_ActiveControllerCount is the number of Active DAC960 Controllers
-  detected.
-*/
-
-static int
-  DAC960_ActiveControllerCount =		0;
-
-
-/*
-  DAC960_Controllers is an array of pointers to the DAC960 Controller
-  structures.
-*/
-
-static DAC960_Controller_T
-  *DAC960_Controllers[DAC960_MaxControllers] =	{ NULL };
-
-
-/*
-  DAC960_FileOperations is the File Operations structure for DAC960 Logical
-  Disk Devices.
-*/
-
-static FileOperations_T
-  DAC960_FileOperations =
-    { lseek:		    NULL,
-      read:		    block_read,
-      write:		    block_write,
-      readdir:		    NULL,
-      select:		    NULL,
-      ioctl:		    DAC960_Ioctl,
-      mmap:		    NULL,
-      open:		    DAC960_Open,
-      release:		    DAC960_Release,
-      fsync:		    block_fsync,
-      fasync:		    NULL,
-      check_media_change:   NULL,
-      revalidate:	    NULL };
-
-
-/*
-  DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry.
-*/
-
-static PROC_DirectoryEntry_T
-  DAC960_ProcDirectoryEntry;
-
-
-/*
-  DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name,
-  Copyright Notice, and Electronic Mail Address.
-*/
-
-static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller)
-{
-  DAC960_Announce("***** DAC960 RAID Driver Version "
-		  DAC960_DriverVersion " of "
-		  DAC960_DriverDate " *****\n", Controller);
-  DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff "
-		  "<lnz@dandelion.com>\n", Controller);
-}
-
-
-/*
-  DAC960_Failure prints a standardized error message, and then returns false.
-*/
-
-static boolean DAC960_Failure(DAC960_Controller_T *Controller,
-			      char *ErrorMessage)
-{
-  DAC960_Error("While configuring DAC960 PCI RAID Controller at\n",
-	       Controller);
-  if (Controller->IO_Address == 0)
-    DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
-		 "PCI Address 0x%X\n", Controller,
-		 Controller->Bus, Controller->Device,
-		 Controller->Function, Controller->PCI_Address);
-  else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
-		    "0x%X PCI Address 0x%X\n", Controller,
-		    Controller->Bus, Controller->Device,
-		    Controller->Function, Controller->IO_Address,
-		    Controller->PCI_Address);
-  DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage);
-  return false;
-}
-
-
-/*
-  DAC960_ClearCommand clears critical fields of Command.
-*/
-
-static inline void DAC960_ClearCommand(DAC960_Command_T *Command)
-{
-  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-  CommandMailbox->Words[0] = 0;
-  CommandMailbox->Words[1] = 0;
-  CommandMailbox->Words[2] = 0;
-  CommandMailbox->Words[3] = 0;
-  Command->CommandStatus = 0;
-}
-
-
-/*
-  DAC960_AllocateCommand allocates a Command structure from Controller's
-  free list.
-*/
-
-static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T
-						       *Controller)
-{
-  DAC960_Command_T *Command = Controller->FreeCommands;
-  if (Command == NULL) return NULL;
-  Controller->FreeCommands = Command->Next;
-  Command->Next = NULL;
-  return Command;
-}
-
-
-/*
-  DAC960_DeallocateCommand deallocates Command, returning it to Controller's
-  free list.
-*/
-
-static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
-{
-  DAC960_Controller_T *Controller = Command->Controller;
-  Command->Next = Controller->FreeCommands;
-  Controller->FreeCommands = Command;
-}
-
-
-/*
-  DAC960_QueueCommand queues Command.
-*/
-
-static void DAC960_QueueCommand(DAC960_Command_T *Command)
-{
-  DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-  DAC960_CommandMailbox_T *NextCommandMailbox;
-  CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands;
-  switch (Controller->ControllerType)
-    {
-    case DAC960_V5_Controller:
-      NextCommandMailbox = Controller->NextCommandMailbox;
-      DAC960_V5_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
-      if (Controller->PreviousCommandMailbox1->Words[0] == 0 ||
-	  Controller->PreviousCommandMailbox2->Words[0] == 0)
-	if (Controller->DualModeMemoryMailboxInterface)
-	  DAC960_V5_MemoryMailboxNewCommand(ControllerBaseAddress);
-	else DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress);
-      Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1;
-      Controller->PreviousCommandMailbox1 = NextCommandMailbox;
-      if (++NextCommandMailbox > Controller->LastCommandMailbox)
-	NextCommandMailbox = Controller->FirstCommandMailbox;
-      Controller->NextCommandMailbox = NextCommandMailbox;
-      break;
-    case DAC960_V4_Controller:
-      NextCommandMailbox = Controller->NextCommandMailbox;
-      DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
-      if (Controller->PreviousCommandMailbox1->Words[0] == 0 ||
-	  Controller->PreviousCommandMailbox2->Words[0] == 0)
-	if (Controller->DualModeMemoryMailboxInterface)
-	  DAC960_V4_MemoryMailboxNewCommand(ControllerBaseAddress);
-	else DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress);
-      Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1;
-      Controller->PreviousCommandMailbox1 = NextCommandMailbox;
-      if (++NextCommandMailbox > Controller->LastCommandMailbox)
-	NextCommandMailbox = Controller->FirstCommandMailbox;
-      Controller->NextCommandMailbox = NextCommandMailbox;
-      break;
-    case DAC960_V3_Controller:
-      while (DAC960_V3_MailboxFullP(ControllerBaseAddress))
-	udelay(1);
-      DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox);
-      DAC960_V3_NewCommand(ControllerBaseAddress);
-      break;
-    }
-}
-
-
-/*
-  DAC960_ExecuteCommand executes Command and waits for completion.  It
-  returns true on success and false on failure.
-*/
-
-static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command)
-{
-  DAC960_Controller_T *Controller = Command->Controller;
-  Semaphore_T Semaphore = MUTEX_LOCKED;
-  unsigned long ProcessorFlags;
-  Command->Semaphore = &Semaphore;
-  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-  DAC960_QueueCommand(Command);
-  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-  down(&Semaphore);
-  return Command->CommandStatus == DAC960_NormalCompletion;
-}
-
-
-/*
-  DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for
-  completion.  It returns true on success and false on failure.
-*/
-
-static boolean DAC960_ExecuteType3(DAC960_Controller_T *Controller,
-				   DAC960_CommandOpcode_T CommandOpcode,
-				   void *DataPointer)
-{
-  DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
-  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-  boolean Result;
-  DAC960_ClearCommand(Command);
-  Command->CommandType = DAC960_ImmediateCommand;
-  CommandMailbox->Type3.CommandOpcode = CommandOpcode;
-  CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer);
-  Result = DAC960_ExecuteCommand(Command);
-  DAC960_DeallocateCommand(Command);
-  return Result;
-}
-
-
-/*
-  DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for
-  completion.  It returns true on success and false on failure.
-*/
-
-static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller,
-				    DAC960_CommandOpcode_T CommandOpcode,
-				    unsigned char Channel,
-				    unsigned char TargetID,
-				    void *DataPointer)
-{
-  DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
-  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-  boolean Result;
-  DAC960_ClearCommand(Command);
-  Command->CommandType = DAC960_ImmediateCommand;
-  CommandMailbox->Type3D.CommandOpcode = CommandOpcode;
-  CommandMailbox->Type3D.Channel = Channel;
-  CommandMailbox->Type3D.TargetID = TargetID;
-  CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer);
-  Result = DAC960_ExecuteCommand(Command);
-  DAC960_DeallocateCommand(Command);
-  return Result;
-}
-
-
-/*
-  DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface.
-*/
-
-static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T
-						   *Controller)
-{
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  DAC960_CommandMailbox_T *CommandMailboxesMemory;
-  DAC960_StatusMailbox_T *StatusMailboxesMemory;
-  DAC960_CommandMailbox_T CommandMailbox;
-  DAC960_CommandStatus_T CommandStatus;
-  void *SavedMemoryMailboxesAddress = NULL;
-  short NextCommandMailboxIndex = 0;
-  short NextStatusMailboxIndex = 0;
-  long TimeoutCounter = 1000000;
-  int i;
-  if (Controller->ControllerType == DAC960_V5_Controller)
-    DAC960_V5_RestoreMemoryMailboxInfo(Controller,
-				       &SavedMemoryMailboxesAddress,
-				       &NextCommandMailboxIndex,
-				       &NextStatusMailboxIndex);
-  else DAC960_V4_RestoreMemoryMailboxInfo(Controller,
-					  &SavedMemoryMailboxesAddress,
-					  &NextCommandMailboxIndex,
-					  &NextStatusMailboxIndex);
-  if (SavedMemoryMailboxesAddress == NULL)
-    CommandMailboxesMemory =
-      (DAC960_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1, 0);
-  else CommandMailboxesMemory = SavedMemoryMailboxesAddress;
-  memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1);
-  Controller->FirstCommandMailbox = CommandMailboxesMemory;
-  CommandMailboxesMemory += DAC960_CommandMailboxCount - 1;
-  Controller->LastCommandMailbox = CommandMailboxesMemory;
-  Controller->NextCommandMailbox =
-    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
-  if (--NextCommandMailboxIndex < 0)
-    NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1;
-  Controller->PreviousCommandMailbox1 =
-    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
-  if (--NextCommandMailboxIndex < 0)
-    NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1;
-  Controller->PreviousCommandMailbox2 =
-    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
-  StatusMailboxesMemory =
-    (DAC960_StatusMailbox_T *) (CommandMailboxesMemory + 1);
-  Controller->FirstStatusMailbox = StatusMailboxesMemory;
-  StatusMailboxesMemory += DAC960_StatusMailboxCount - 1;
-  Controller->LastStatusMailbox = StatusMailboxesMemory;
-  Controller->NextStatusMailbox =
-    &Controller->FirstStatusMailbox[NextStatusMailboxIndex];
-  if (SavedMemoryMailboxesAddress != NULL) return true;
-  /* Enable the Memory Mailbox Interface. */
-  CommandMailbox.TypeX.CommandOpcode = 0x2B;
-  CommandMailbox.TypeX.CommandIdentifier = 0;
-  CommandMailbox.TypeX.CommandOpcode2 = 0x10;
-  CommandMailbox.TypeX.CommandMailboxesBusAddress =
-    Virtual_to_Bus(Controller->FirstCommandMailbox);
-  CommandMailbox.TypeX.StatusMailboxesBusAddress =
-    Virtual_to_Bus(Controller->FirstStatusMailbox);
-  for (i = 0; i < 2; i++)
-    switch (Controller->ControllerType)
-      {
-      case DAC960_V5_Controller:
-	while (--TimeoutCounter >= 0)
-	  {
-	    if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress))
-	      break;
-	    udelay(1);
-	  }
-	if (TimeoutCounter < 0) return false;
-	DAC960_V5_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
-	DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress);
-	while (--TimeoutCounter >= 0)
-	  {
-	    if (DAC960_V5_HardwareMailboxStatusAvailableP(
-		  ControllerBaseAddress))
-	      break;
-	    udelay(1);
-	  }
-	if (TimeoutCounter < 0) return false;
-	CommandStatus = DAC960_V5_ReadStatusRegister(ControllerBaseAddress);
-	DAC960_V5_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
-	DAC960_V5_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
-	if (CommandStatus == DAC960_NormalCompletion) return true;
-	Controller->DualModeMemoryMailboxInterface = true;
-	CommandMailbox.TypeX.CommandOpcode2 = 0x14;
-	break;
-      case DAC960_V4_Controller:
-	while (--TimeoutCounter >= 0)
-	  {
-	    if (!DAC960_V4_HardwareMailboxFullP(ControllerBaseAddress))
-	      break;
-	    udelay(1);
-	  }
-	if (TimeoutCounter < 0) return false;
-	DAC960_V4_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
-	DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress);
-	while (--TimeoutCounter >= 0)
-	  {
-	    if (DAC960_V4_HardwareMailboxStatusAvailableP(
-		  ControllerBaseAddress))
-	      break;
-	    udelay(1);
-	  }
-	if (TimeoutCounter < 0) return false;
-	CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress);
-	DAC960_V4_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
-	DAC960_V4_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
-	if (CommandStatus == DAC960_NormalCompletion) return true;
-	Controller->DualModeMemoryMailboxInterface = true;
-	CommandMailbox.TypeX.CommandOpcode2 = 0x14;
-	break;
-      default:
-	break;
-      }
-  return false;
-}
-
-
-/*
-  DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating
-  the PCI Configuration Space for Controller Type.
-*/
-
-static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType)
-{
-  unsigned short VendorID = 0, DeviceID = 0, Index = 0;
-  unsigned char Bus, DeviceFunction, IRQ_Channel;
-  unsigned int BaseAddress0, BaseAddress1;
-  unsigned int MemoryWindowSize = 0;
-  switch (ControllerType)
-    {
-    case DAC960_V5_Controller:
-      VendorID = PCI_VENDOR_ID_DEC;
-      DeviceID = PCI_DEVICE_ID_DEC_21285;
-      MemoryWindowSize = DAC960_V5_RegisterWindowSize;
-      break;
-    case DAC960_V4_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V4;
-      MemoryWindowSize = DAC960_V4_RegisterWindowSize;
-      break;
-    case DAC960_V3_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V3;
-      MemoryWindowSize = DAC960_V3_RegisterWindowSize;
-      break;
-    }
-  while (pcibios_find_device(VendorID, DeviceID,
-			     Index++, &Bus, &DeviceFunction) == 0)
-    {
-      DAC960_Controller_T *Controller = (DAC960_Controller_T *)
-	kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
-      DAC960_IO_Address_T IO_Address = 0;
-      DAC960_PCI_Address_T PCI_Address = 0;
-      unsigned char Device = DeviceFunction >> 3;
-      unsigned char Function = DeviceFunction & 0x7;
-      unsigned short SubsystemVendorID, SubsystemDeviceID;
-      pcibios_read_config_dword(Bus, DeviceFunction,
-				PCI_BASE_ADDRESS_0, &BaseAddress0);
-      pcibios_read_config_dword(Bus, DeviceFunction,
-				PCI_BASE_ADDRESS_1, &BaseAddress1);
-      pcibios_read_config_word(Bus, DeviceFunction,
-			       PCI_SUBSYSTEM_VENDOR_ID, &SubsystemVendorID);
-      pcibios_read_config_word(Bus, DeviceFunction,
-			       PCI_SUBSYSTEM_ID, &SubsystemDeviceID);
-      pcibios_read_config_byte(Bus, DeviceFunction,
-			       PCI_INTERRUPT_LINE, &IRQ_Channel);
-      switch (ControllerType)
-	{
-	case DAC960_V5_Controller:
-	  if (!(SubsystemVendorID == PCI_VENDOR_ID_MYLEX &&
-		SubsystemDeviceID == PCI_DEVICE_ID_MYLEX_DAC960P_V5))
-	    goto Ignore;
-	  PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
-	  break;
-	case DAC960_V4_Controller:
-	  PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
-	  break;
-	case DAC960_V3_Controller:
-	  IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
-	  PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
-	  break;
-	}
-      if (DAC960_ControllerCount == DAC960_MaxControllers)
-	{
-	  DAC960_Error("More than %d DAC960 Controllers detected - "
-		       "ignoring from Controller at\n",
-		       NULL, DAC960_MaxControllers);
-	  goto Ignore;
-	}
-      if (Controller == NULL)
-	{
-	  DAC960_Error("Unable to allocate Controller structure for "
-		       "Controller at\n", NULL);
-	  goto Ignore;
-	}
-      memset(Controller, 0, sizeof(DAC960_Controller_T));
-      Controller->ControllerNumber = DAC960_ControllerCount;
-      DAC960_Controllers[DAC960_ControllerCount++] = Controller;
-      DAC960_AnnounceDriver(Controller);
-      Controller->ControllerType = ControllerType;
-      Controller->IO_Address = IO_Address;
-      Controller->PCI_Address = PCI_Address;
-      Controller->Bus = Bus;
-      Controller->Device = Device;
-      Controller->Function = Function;
-      sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
-      /*
-	Acquire shared access to the IRQ Channel.
-      */
-      if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS)
-	{
-	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure;
-	}
-      strcpy(Controller->FullModelName, "DAC960");
-      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
-		      SA_INTERRUPT | SA_SHIRQ, Controller->FullModelName,
-		      Controller) < 0)
-	{
-	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure;
-	}
-      Controller->IRQ_Channel = IRQ_Channel;
-      /*
-	Map the Controller Register Window.
-      */
-      if (MemoryWindowSize < PAGE_SIZE)
-	MemoryWindowSize = PAGE_SIZE;
-      Controller->MemoryMappedAddress =
-	ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize);
-      Controller->BaseAddress =
-	Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK);
-      if (Controller->MemoryMappedAddress == NULL)
-	{
-	  DAC960_Error("Unable to map Controller Register Window for "
-		       "Controller at\n", Controller);
-	  goto Failure;
-	}
-      switch (ControllerType)
-	{
-	case DAC960_V5_Controller:
-	  DAC960_V5_DisableInterrupts(Controller->BaseAddress);
-	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
-	    {
-	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
-			   "for Controller at\n", Controller);
-	      goto Failure;
-	    }
-	  DAC960_V5_EnableInterrupts(Controller->BaseAddress);
-	  break;
-	case DAC960_V4_Controller:
-	  DAC960_V4_DisableInterrupts(Controller->BaseAddress);
-	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
-	    {
-	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
-			   "for Controller at\n", Controller);
-	      goto Failure;
-	    }
-	  DAC960_V4_EnableInterrupts(Controller->BaseAddress);
-	  break;
-	case DAC960_V3_Controller:
-	  request_region(Controller->IO_Address, 0x80,
-			 Controller->FullModelName);
-	  DAC960_V3_EnableInterrupts(Controller->BaseAddress);
-	  break;
-	}
-      DAC960_ActiveControllerCount++;
-      Controller->Commands[0].Controller = Controller;
-      Controller->Commands[0].Next = NULL;
-      Controller->FreeCommands = &Controller->Commands[0];
-      continue;
-    Failure:
-      if (IO_Address == 0)
-	DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
-		     "PCI Address 0x%X\n", Controller,
-		     Bus, Device, Function, PCI_Address);
-      else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
-			"0x%X PCI Address 0x%X\n", Controller,
-			Bus, Device, Function, IO_Address, PCI_Address);
-      if (Controller == NULL) break;
-      if (Controller->IRQ_Channel > 0)
-	free_irq(IRQ_Channel, Controller);
-      if (Controller->MemoryMappedAddress != NULL)
-	iounmap(Controller->MemoryMappedAddress);
-      DAC960_Controllers[Controller->ControllerNumber] = NULL;
-    Ignore:
-      kfree(Controller);
-    }
-}
-
-
-/*
-  DAC960_ReadControllerConfiguration reads the Configuration Information
-  from Controller and initializes the Controller structure.
-*/
-
-static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T
-						  *Controller)
-{
-  DAC960_Enquiry2_T Enquiry2;
-  DAC960_Config2_T Config2;
-  int LogicalDriveNumber, Channel, TargetID;
-  if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry,
-			   &Controller->Enquiry[0]))
-    return DAC960_Failure(Controller, "ENQUIRY");
-  if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2))
-    return DAC960_Failure(Controller, "ENQUIRY2");
-  if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2))
-    return DAC960_Failure(Controller, "READ CONFIG2");
-  if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation,
-			   &Controller->LogicalDriveInformation[0]))
-    return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION");
-  for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++)
-    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
-      if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState,
-				Channel, TargetID,
-				&Controller->DeviceState[0][Channel][TargetID]))
-	  return DAC960_Failure(Controller, "GET DEVICE STATE");
-  /*
-    Initialize the Controller Model Name and Full Model Name fields.
-  */
-  switch (Enquiry2.HardwareID.SubModel)
-    {
-    case DAC960_P_PD_PU:
-      if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra)
-	strcpy(Controller->ModelName, "DAC960PU");
-      else strcpy(Controller->ModelName, "DAC960PD");
-      break;
-    case DAC960_PL:
-      strcpy(Controller->ModelName, "DAC960PL");
-      break;
-    case DAC960_PG:
-      strcpy(Controller->ModelName, "DAC960PG");
-      break;
-    case DAC960_PJ:
-      strcpy(Controller->ModelName, "DAC960PJ");
-      break;
-    case DAC960_PR:
-      strcpy(Controller->ModelName, "DAC960PR");
-      break;
-    case DAC960_PT:
-      strcpy(Controller->ModelName, "DAC960PT");
-      break;
-    case DAC960_PTL0:
-      strcpy(Controller->ModelName, "DAC960PTL0");
-      break;
-    case DAC960_PRL:
-      strcpy(Controller->ModelName, "DAC960PRL");
-      break;
-    case DAC960_PTL1:
-      strcpy(Controller->ModelName, "DAC960PTL1");
-      break;
-    case DAC1164_P:
-      strcpy(Controller->ModelName, "DAC1164P");
-      break;
-    default:
-      return DAC960_Failure(Controller, "MODEL VERIFICATION");
-    }
-  strcpy(Controller->FullModelName, "Mylex ");
-  strcat(Controller->FullModelName, Controller->ModelName);
-  /*
-    Initialize the Controller Firmware Version field and verify that it
-    is a supported firmware version.  The supported firmware versions are:
-
-    DAC1164P		5.06 and above
-    DAC960PTL/PJ/PG	4.06 and above
-    DAC960PU/PD/PL	3.51 and above
-  */
-  sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
-	  Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
-	  Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
-  if (!((Controller->FirmwareVersion[0] == '5' &&
-	 strcmp(Controller->FirmwareVersion, "5.06") >= 0) ||
-	(Controller->FirmwareVersion[0] == '4' &&
-	 strcmp(Controller->FirmwareVersion, "4.06") >= 0) ||
-	(Controller->FirmwareVersion[0] == '3' &&
-	 strcmp(Controller->FirmwareVersion, "3.51") >= 0)))
-    {
-      DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
-      DAC960_Error("Firmware Version = '%s'\n", Controller,
-		   Controller->FirmwareVersion);
-      return false;
-    }
-  /*
-    Initialize the Controller Channels, Memory Size, and SAF-TE Fault
-    Management Enabled fields.
-  */
-  Controller->Channels = Enquiry2.ActualChannels;
-  Controller->MemorySize = Enquiry2.MemorySize >> 20;
-  Controller->SAFTE_FaultManagementEnabled =
-    Enquiry2.FaultManagementType == DAC960_SAFTE;
-  /*
-    Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive
-    Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments.
-    The Driver Queue Depth must be at most one less than the Controller Queue
-    Depth to allow for an automatic drive rebuild operation.
-  */
-  Controller->ControllerQueueDepth = Controller->Enquiry[0].MaxCommands;
-  Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1;
-  Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives;
-  Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand;
-  Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries;
-  /*
-    Initialize the Stripe Size, Segment Size, and Geometry Translation.
-  */
-  Controller->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor
-			   >> (10 - DAC960_BlockSizeBits);
-  Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor
-			    >> (10 - DAC960_BlockSizeBits);
-  switch (Config2.DriveGeometry)
-    {
-    case DAC960_Geometry_128_32:
-      Controller->GeometryTranslationHeads = 128;
-      Controller->GeometryTranslationSectors = 32;
-      break;
-    case DAC960_Geometry_255_63:
-      Controller->GeometryTranslationHeads = 255;
-      Controller->GeometryTranslationSectors = 63;
-      break;
-    default:
-      return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
-    }
-  /*
-    Initialize the Logical Drive Initial State.
-  */
-  for (LogicalDriveNumber = 0;
-       LogicalDriveNumber < Controller->LogicalDriveCount;
-       LogicalDriveNumber++)
-    Controller->LogicalDriveInitialState[LogicalDriveNumber] =
-      Controller->LogicalDriveInformation[0]
-		  [LogicalDriveNumber].LogicalDriveState;
-  return true;
-}
-
-
-/*
-  DAC960_ReportControllerConfiguration reports the configuration of
-  Controller.
-*/
-
-static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
-						    *Controller)
-{
-  int LogicalDriveNumber, Channel, TargetID;
-  DAC960_Info("Configuring Mylex %s PCI RAID Controller\n",
-	      Controller, Controller->ModelName);
-  DAC960_Info("  Firmware Version: %s, Channels: %d, Memory Size: %dMB\n",
-	      Controller, Controller->FirmwareVersion,
-	      Controller->Channels, Controller->MemorySize);
-  DAC960_Info("  PCI Bus: %d, Device: %d, Function: %d, I/O Address: ",
-	      Controller, Controller->Bus,
-	      Controller->Device, Controller->Function);
-  if (Controller->IO_Address == 0)
-    DAC960_Info("Unassigned\n", Controller);
-  else DAC960_Info("0x%X\n", Controller, Controller->IO_Address);
-  DAC960_Info("  PCI Address: 0x%X mapped at 0x%lX, IRQ Channel: %d\n",
-	      Controller, Controller->PCI_Address,
-	      (unsigned long) Controller->BaseAddress,
-	      Controller->IRQ_Channel);
-  DAC960_Info("  Controller Queue Depth: %d, "
-	      "Maximum Blocks per Command: %d\n",
-	      Controller, Controller->ControllerQueueDepth,
-	      Controller->MaxBlocksPerCommand);
-  DAC960_Info("  Driver Queue Depth: %d, "
-	      "Maximum Scatter/Gather Segments: %d\n",
-	      Controller, Controller->DriverQueueDepth,
-	      Controller->MaxScatterGatherSegments);
-  DAC960_Info("  Stripe Size: %dKB, Segment Size: %dKB, "
-	      "BIOS Geometry: %d/%d\n", Controller,
-	      Controller->StripeSize,
-	      Controller->SegmentSize,
-	      Controller->GeometryTranslationHeads,
-	      Controller->GeometryTranslationSectors);
-  if (Controller->SAFTE_FaultManagementEnabled)
-    DAC960_Info("  SAF-TE Fault Management Enabled\n", Controller);
-  DAC960_Info("  Physical Devices:\n", Controller);
-  for (Channel = 0; Channel < Controller->Channels; Channel++)
-    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
-      {
-	DAC960_DeviceState_T *DeviceState =
-	  &Controller->DeviceState[Controller->DeviceStateIndex]
-				  [Channel][TargetID];
-	if (!DeviceState->Present) continue;
-	switch (DeviceState->DeviceType)
-	  {
-	  case DAC960_OtherType:
-	    DAC960_Info("    %d:%d - Other\n", Controller, Channel, TargetID);
-	    break;
-	  case DAC960_DiskType:
-	    DAC960_Info("    %d:%d - Disk: %s, %d blocks\n", Controller,
-			Channel, TargetID,
-			(DeviceState->DeviceState == DAC960_Device_Dead
-			 ? "Dead"
-			 : DeviceState->DeviceState == DAC960_Device_WriteOnly
-			   ? "Write-Only"
-			   : DeviceState->DeviceState == DAC960_Device_Online
-			     ? "Online" : "Standby"),
-			DeviceState->DiskSize);
-	    break;
-	  case DAC960_SequentialType:
-	    DAC960_Info("    %d:%d - Sequential\n", Controller,
-			Channel, TargetID);
-	    break;
-	  case DAC960_CDROM_or_WORM_Type:
-	    DAC960_Info("    %d:%d - CD-ROM or WORM\n", Controller,
-			Channel, TargetID);
-	    break;
-	  }
-
-      }
-  DAC960_Info("  Logical Drives:\n", Controller);
-  for (LogicalDriveNumber = 0;
-       LogicalDriveNumber < Controller->LogicalDriveCount;
-       LogicalDriveNumber++)
-    {
-      DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
-	&Controller->LogicalDriveInformation
-	   [Controller->LogicalDriveInformationIndex][LogicalDriveNumber];
-      DAC960_Info("    /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n",
-		  Controller, Controller->ControllerNumber, LogicalDriveNumber,
-		  LogicalDriveInformation->RAIDLevel,
-		  (LogicalDriveInformation->LogicalDriveState ==
-		     DAC960_LogicalDrive_Online
-		   ? "Online"
-		   : LogicalDriveInformation->LogicalDriveState ==
-		     DAC960_LogicalDrive_Critical
-		     ? "Critical" : "Offline"),
-		  LogicalDriveInformation->LogicalDriveSize,
-		  (LogicalDriveInformation->WriteBack
-		   ? "Write Back" : "Write Thru"));
-    }
-  return true;
-}
-
-
-/*
-  DAC960_RegisterBlockDevice registers the Block Device structures
-  associated with Controller.
-*/
-
-static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
-{
-  static void (*RequestFunctions[DAC960_MaxControllers])(void) =
-    { DAC960_RequestFunction0, DAC960_RequestFunction1,
-      DAC960_RequestFunction2, DAC960_RequestFunction3,
-      DAC960_RequestFunction4, DAC960_RequestFunction5,
-      DAC960_RequestFunction6, DAC960_RequestFunction7 };
-  int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
-  GenericDiskInfo_T *GenericDiskInfo;
-  int MinorNumber;
-  /*
-    Register the Block Device Major Number for this DAC960 Controller.
-  */
-  if (register_blkdev(MajorNumber, "rd", &DAC960_FileOperations) < 0)
-    {
-      DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
-		   Controller, MajorNumber);
-      return false;
-    }
-  /*
-    Initialize the I/O Request Function.
-  */
-  blk_dev[MajorNumber].request_fn =
-    RequestFunctions[Controller->ControllerNumber];
-  /*
-    Initialize the Disk Partitions array, Partition Sizes array, Block Sizes
-    array, Max Sectors per Request array, and Max Segments per Request array.
-  */
-  for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++)
-    {
-      Controller->BlockSizes[MinorNumber] = BLOCK_SIZE;
-      Controller->MaxSectorsPerRequest[MinorNumber] =
-	Controller->MaxBlocksPerCommand;
-      Controller->MaxSegmentsPerRequest[MinorNumber] =
-	Controller->MaxScatterGatherSegments;
-    }
-  Controller->GenericDiskInfo.part = Controller->DiskPartitions;
-  Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
-  blksize_size[MajorNumber] = Controller->BlockSizes;
-  max_sectors[MajorNumber] = Controller->MaxSectorsPerRequest;
-  max_segments[MajorNumber] = Controller->MaxSegmentsPerRequest;
-  /*
-    Initialize Read Ahead to 128 sectors.
-  */
-  read_ahead[MajorNumber] = 128;
-  /*
-    Complete initialization of the Generic Disk Information structure.
-  */
-  Controller->GenericDiskInfo.major = MajorNumber;
-  Controller->GenericDiskInfo.major_name = "rd";
-  Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
-  Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
-  Controller->GenericDiskInfo.max_nr = DAC960_MaxLogicalDrives;
-  Controller->GenericDiskInfo.init = DAC960_InitializeGenericDiskInfo;
-  Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount;
-  Controller->GenericDiskInfo.real_devices = Controller;
-  Controller->GenericDiskInfo.next = NULL;
-  /*
-    Install the Generic Disk Information structure at the end of the list.
-  */
-  if ((GenericDiskInfo = gendisk_head) != NULL)
-    {
-      while (GenericDiskInfo->next != NULL)
-	GenericDiskInfo = GenericDiskInfo->next;
-      GenericDiskInfo->next = &Controller->GenericDiskInfo;
-    }
-  else gendisk_head = &Controller->GenericDiskInfo;
-  /*
-    Indicate the Block Device Registration completed successfully,
-  */
-  return true;
-}
-
-
-/*
-  DAC960_UnregisterBlockDevice unregisters the Block Device structures
-  associated with Controller.
-*/
-
-static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
-{
-  int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
-  /*
-    Unregister the Block Device Major Number for this DAC960 Controller.
-  */
-  unregister_blkdev(MajorNumber, "rd");
-  /*
-    Remove the I/O Request Function.
-  */
-  blk_dev[MajorNumber].request_fn = NULL;
-  /*
-    Remove the Disk Partitions array, Partition Sizes array, Block Sizes
-    array, Max Sectors per Request array, and Max Segments per Request array.
-  */
-  Controller->GenericDiskInfo.part = NULL;
-  Controller->GenericDiskInfo.sizes = NULL;
-  blk_size[MajorNumber] = NULL;
-  blksize_size[MajorNumber] = NULL;
-  max_sectors[MajorNumber] = NULL;
-  max_segments[MajorNumber] = NULL;
-  /*
-    Remove the Generic Disk Information structure from the list.
-  */
-  if (gendisk_head != &Controller->GenericDiskInfo)
-    {
-      GenericDiskInfo_T *GenericDiskInfo = gendisk_head;
-      while (GenericDiskInfo != NULL &&
-	     GenericDiskInfo->next != &Controller->GenericDiskInfo)
-	GenericDiskInfo = GenericDiskInfo->next;
-      if (GenericDiskInfo != NULL)
-	GenericDiskInfo->next = GenericDiskInfo->next->next;
-    }
-  else gendisk_head = Controller->GenericDiskInfo.next;
-}
-
-
-/*
-  DAC960_InitializeController initializes Controller.
-*/
-
-static void DAC960_InitializeController(DAC960_Controller_T *Controller)
-{
-  if (DAC960_ReadControllerConfiguration(Controller) &&
-      DAC960_ReportControllerConfiguration(Controller) &&
-      DAC960_RegisterBlockDevice(Controller))
-    {
-      /*
-	Initialize the Command structures.
-      */
-      DAC960_Command_T *Commands = Controller->Commands;
-      int CommandIdentifier;
-      Controller->FreeCommands = NULL;
-      for (CommandIdentifier = 0;
-	   CommandIdentifier < Controller->DriverQueueDepth;
-	   CommandIdentifier++)
-	{
-	  Commands[CommandIdentifier].Controller = Controller;
-	  Commands[CommandIdentifier].Next = Controller->FreeCommands;
-	  Controller->FreeCommands = &Commands[CommandIdentifier];
-	}
-      /*
-	Initialize the Monitoring Timer.
-      */
-      init_timer(&Controller->MonitoringTimer);
-      Controller->MonitoringTimer.expires =
-	jiffies + DAC960_MonitoringTimerInterval;
-      Controller->MonitoringTimer.data = (unsigned long) Controller;
-      Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction;
-      add_timer(&Controller->MonitoringTimer);
-      Controller->ControllerInitialized = true;
-    }
-  else DAC960_FinalizeController(Controller);
-}
-
-
-/*
-  DAC960_FinalizeController finalizes Controller.
-*/
-
-static void DAC960_FinalizeController(DAC960_Controller_T *Controller)
-{
-  if (Controller->ControllerInitialized)
-    {
-      del_timer(&Controller->MonitoringTimer);
-      DAC960_Notice("Flushing Cache...", Controller);
-      DAC960_ExecuteType3(Controller, DAC960_Flush, NULL);
-      DAC960_Notice("done\n", Controller);
-      switch (Controller->ControllerType)
-	{
-	case DAC960_V5_Controller:
-	  if (!Controller->DualModeMemoryMailboxInterface)
-	    DAC960_V5_SaveMemoryMailboxInfo(Controller);
-	  break;
-	case DAC960_V4_Controller:
-	  if (!Controller->DualModeMemoryMailboxInterface)
-	    DAC960_V4_SaveMemoryMailboxInfo(Controller);
-	  break;
-	case DAC960_V3_Controller:
-	  break;
-	}
-    }
-  free_irq(Controller->IRQ_Channel, Controller);
-  iounmap(Controller->MemoryMappedAddress);
-  if (Controller->IO_Address > 0)
-    release_region(Controller->IO_Address, 0x80);
-  DAC960_UnregisterBlockDevice(Controller);
-  DAC960_Controllers[Controller->ControllerNumber] = NULL;
-  kfree(Controller);
-}
-
-
-/*
-  DAC960_Initialize initializes the DAC960 Driver.
-*/
-
-void DAC960_Initialize(void)
-{
-  int ControllerNumber;
-  DAC960_DetectControllers(DAC960_V5_Controller);
-  DAC960_DetectControllers(DAC960_V4_Controller);
-  DAC960_DetectControllers(DAC960_V3_Controller);
-  if (DAC960_ActiveControllerCount == 0) return;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    if (DAC960_Controllers[ControllerNumber] != NULL)
-      DAC960_InitializeController(DAC960_Controllers[ControllerNumber]);
-  DAC960_CreateProcEntries();
-}
-
-
-/*
-  DAC960_Finalize finalizes the DAC960 Driver.
-*/
-
-void DAC960_Finalize(void)
-{
-  int ControllerNumber;
-  if (DAC960_ActiveControllerCount == 0) return;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    if (DAC960_Controllers[ControllerNumber] != NULL)
-      DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]);
-  DAC960_DestroyProcEntries();
-}
-
-
-/*
-  DAC960_ProcessRequest attempts to remove one I/O Request from Controller's
-  I/O Request Queue and queues it to the Controller.  WaitForCommand is true if
-  this function should wait for a Command to become available if necessary.
-  This function returns true if an I/O Request was queued and false otherwise.
-*/
-
-static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
-				     boolean WaitForCommand)
-{
-  IO_Request_T **RequestQueuePointer =
-    &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].current_request;
-  IO_Request_T *Request;
-  DAC960_Command_T *Command;
-  char *RequestBuffer;
-  while (true)
-    {
-      Request = *RequestQueuePointer;
-      if (Request == NULL || Request->rq_status == RQ_INACTIVE) return false;
-      Command = DAC960_AllocateCommand(Controller);
-      if (Command != NULL) break;
-      if (!WaitForCommand) return false;
-      sleep_on(&Controller->CommandWaitQueue);
-    }
-  DAC960_ClearCommand(Command);
-  if (Request->cmd == READ)
-    Command->CommandType = DAC960_ReadCommand;
-  else Command->CommandType = DAC960_WriteCommand;
-  Command->Semaphore = Request->sem;
-  Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev);
-  Command->BlockNumber =
-    Request->sector
-    + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect;
-  Command->BlockCount = Request->nr_sectors;
-  Command->SegmentCount = Request->nr_segments;
-  Command->BufferHeader = Request->bh;
-  RequestBuffer = Request->buffer;
-  Request->rq_status = RQ_INACTIVE;
-  *RequestQueuePointer = Request->next;
-  wake_up(&wait_for_request);
-  if (Command->SegmentCount == 1)
-    {
-      DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-      if (Command->CommandType == DAC960_ReadCommand)
-	CommandMailbox->Type5.CommandOpcode = DAC960_Read;
-      else CommandMailbox->Type5.CommandOpcode = DAC960_Write;
-      CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
-      CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
-      CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
-      CommandMailbox->Type5.BusAddress = Virtual_to_Bus(RequestBuffer);
-    }
-  else
-    {
-      DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-      DAC960_ScatterGatherSegment_T
-	*ScatterGatherList = Command->ScatterGatherList;
-      BufferHeader_T *BufferHeader = Command->BufferHeader;
-      char *LastDataEndPointer = NULL;
-      int SegmentNumber = 0;
-      if (Command->CommandType == DAC960_ReadCommand)
-	CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather;
-      else
-	CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather;
-      CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
-      CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
-      CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
-      CommandMailbox->Type5.BusAddress = Virtual_to_Bus(ScatterGatherList);
-      CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
-      while (BufferHeader != NULL)
-	{
-	  if (BufferHeader->b_data == LastDataEndPointer)
-	    {
-	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
-		BufferHeader->b_size;
-	      LastDataEndPointer += BufferHeader->b_size;
-	    }
-	  else
-	    {
-	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus(BufferHeader->b_data);
-	      ScatterGatherList[SegmentNumber].SegmentByteCount =
-		BufferHeader->b_size;
-	      LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
-	      if (SegmentNumber++ > Controller->MaxScatterGatherSegments)
-		panic("DAC960: Scatter/Gather Segment Overflow\n");
-	    }
-	  BufferHeader = BufferHeader->b_reqnext;
-	}
-      if (SegmentNumber != Command->SegmentCount)
-	panic("DAC960: SegmentNumber != SegmentCount\n");
-    }
-  DAC960_QueueCommand(Command);
-  return true;
-}
-
-
-/*
-  DAC960_ProcessRequests attempts to remove as many I/O Requests as possible
-  from Controller's I/O Request Queue and queue them to the Controller.
-*/
-
-static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller)
-{
-  int Counter = 0;
-  while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ;
-}
-
-
-/*
-  DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0.
-*/
-
-static void DAC960_RequestFunction0(void)
-{
-  DAC960_Controller_T *Controller = DAC960_Controllers[0];
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
-  /*
-    Process I/O Requests for Controller.
-  */
-  DAC960_ProcessRequests(Controller);
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1.
-*/
-
-static void DAC960_RequestFunction1(void)
-{
-  DAC960_Controller_T *Controller = DAC960_Controllers[1];
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
-  /*
-    Process I/O Requests for Controller.
-  */
-  DAC960_ProcessRequests(Controller);
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2.
-*/
-
-static void DAC960_RequestFunction2(void)
-{
-  DAC960_Controller_T *Controller = DAC960_Controllers[2];
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
-  /*
-    Process I/O Requests for Controller.
-  */
-  DAC960_ProcessRequests(Controller);
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3.
-*/
-
-static void DAC960_RequestFunction3(void)
-{
-  DAC960_Controller_T *Controller = DAC960_Controllers[3];
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
-  /*
-    Process I/O Requests for Controller.
-  */
-  DAC960_ProcessRequests(Controller);
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4.
-*/
-
-static void DAC960_RequestFunction4(void)
-{
-  DAC960_Controller_T *Controller = DAC960_Controllers[4];
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
-  /*
-    Process I/O Requests for Controller.
-  */
-  DAC960_ProcessRequests(Controller);
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5.
-*/
-
-static void DAC960_RequestFunction5(void)
-{
-  DAC960_Controller_T *Controller = DAC960_Controllers[5];
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
-  /*
-    Process I/O Requests for Controller.
-  */
-  DAC960_ProcessRequests(Controller);
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6.
-*/
-
-static void DAC960_RequestFunction6(void)
-{
-  DAC960_Controller_T *Controller = DAC960_Controllers[6];
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
-  /*
-    Process I/O Requests for Controller.
-  */
-  DAC960_ProcessRequests(Controller);
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7.
-*/
-
-static void DAC960_RequestFunction7(void)
-{
-  DAC960_Controller_T *Controller = DAC960_Controllers[7];
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
-  /*
-    Process I/O Requests for Controller.
-  */
-  DAC960_ProcessRequests(Controller);
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_ReadWriteError prints an appropriate error message for Command when
-  an error occurs on a Read or Write operation.
-*/
-
-static void DAC960_ReadWriteError(DAC960_Command_T *Command)
-{
-  DAC960_Controller_T *Controller = Command->Controller;
-  char *CommandName = "UNKNOWN";
-  switch (Command->CommandType)
-    {
-    case DAC960_ReadCommand:
-    case DAC960_ReadRetryCommand:
-      CommandName = "READ";
-      break;
-    case DAC960_WriteCommand:
-    case DAC960_WriteRetryCommand:
-      CommandName = "WRITE";
-      break;
-    case DAC960_MonitoringCommand:
-    case DAC960_ImmediateCommand:
-      break;
-    }
-  switch (Command->CommandStatus)
-    {
-    case DAC960_IrrecoverableDataError:
-      DAC960_Error("Irrecoverable Data Error on %s:\n",
-		   Controller, CommandName);
-      break;
-    case DAC960_LogicalDriveNonexistentOrOffline:
-      DAC960_Error("Logical Drive Nonexistent or Offline on %s:\n",
-		   Controller, CommandName);
-      break;
-    case DAC960_AccessBeyondEndOfLogicalDrive:
-      DAC960_Error("Attempt to Access Beyond End of Logical Drive "
-		   "on %s:\n", Controller, CommandName);
-      break;
-    case DAC960_BadDataEncountered:
-      DAC960_Error("Bad Data Encountered on %s:\n", Controller, CommandName);
-      break;
-    default:
-      DAC960_Error("Unexpected Error Status %04X on %s:\n",
-		   Controller, Command->CommandStatus, CommandName);
-      break;
-    }
-  DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %d..%d\n",
-	       Controller, Controller->ControllerNumber,
-	       Command->LogicalDriveNumber, Command->BlockNumber,
-	       Command->BlockNumber + Command->BlockCount - 1);
-  if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
-    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
-		 Controller, Controller->ControllerNumber,
-		 Command->LogicalDriveNumber,
-		 DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
-		 Command->BufferHeader->b_rsector,
-		 Command->BufferHeader->b_rsector + Command->BlockCount - 1);
-}
-
-
-/*
-  DAC960_ProcessCompletedBuffer performs completion processing for an
-  individual Buffer.
-*/
-
-static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
-						 boolean SuccessfulIO)
-{
-  mark_buffer_uptodate(BufferHeader, SuccessfulIO);
-  unlock_buffer(BufferHeader);
-}
-
-
-/*
-  DAC960_ProcessCompletedCommand performs completion processing for Command.
-*/
-
-static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command)
-{
-  DAC960_Controller_T *Controller = Command->Controller;
-  DAC960_CommandType_T CommandType = Command->CommandType;
-  DAC960_CommandStatus_T CommandStatus = Command->CommandStatus;
-  BufferHeader_T *BufferHeader = Command->BufferHeader;
-  if (CommandType == DAC960_ReadCommand ||
-      CommandType == DAC960_WriteCommand)
-    {
-      if (CommandStatus == DAC960_NormalCompletion)
-	{
-	  /*
-	    Perform completion processing for all buffers in this I/O Request.
-	  */
-	  while (BufferHeader != NULL)
-	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-	      BufferHeader->b_reqnext = NULL;
-	      DAC960_ProcessCompletedBuffer(BufferHeader, true);
-	      BufferHeader = NextBufferHeader;
-	    }
-	  /*
-	    Wake up requestor for swap file paging requests.
-	  */
-	  if (Command->Semaphore != NULL)
-	    {
-	      up(Command->Semaphore);
-	      Command->Semaphore = NULL;
-	    }
-	  add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber);
-	}
-      else if ((CommandStatus == DAC960_IrrecoverableDataError ||
-		CommandStatus == DAC960_BadDataEncountered) &&
-	       BufferHeader != NULL &&
-	       BufferHeader->b_reqnext != NULL)
-	{
-	  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-	  if (CommandType == DAC960_ReadCommand)
-	    {
-	      Command->CommandType = DAC960_ReadRetryCommand;
-	      CommandMailbox->Type5.CommandOpcode = DAC960_Read;
-	    }
-	  else
-	    {
-	      Command->CommandType = DAC960_WriteRetryCommand;
-	      CommandMailbox->Type5.CommandOpcode = DAC960_Write;
-	    }
-	  Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits;
-	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
-	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus(BufferHeader->b_data);
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
-      else
-	{
-	  if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline)
-	    DAC960_ReadWriteError(Command);
-	  /*
-	    Perform completion processing for all buffers in this I/O Request.
-	  */
-	  while (BufferHeader != NULL)
-	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-	      BufferHeader->b_reqnext = NULL;
-	      DAC960_ProcessCompletedBuffer(BufferHeader, false);
-	      BufferHeader = NextBufferHeader;
-	    }
-	  /*
-	    Wake up requestor for swap file paging requests.
-	  */
-	  if (Command->Semaphore != NULL)
-	    {
-	      up(Command->Semaphore);
-	      Command->Semaphore = NULL;
-	    }
-	}
-    }
-  else if (CommandType == DAC960_ReadRetryCommand ||
-	   CommandType == DAC960_WriteRetryCommand)
-    {
-      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-      BufferHeader->b_reqnext = NULL;
-      /*
-	Perform completion processing for this single buffer.
-      */
-      if (CommandStatus == DAC960_NormalCompletion)
-	DAC960_ProcessCompletedBuffer(BufferHeader, true);
-      else
-	{
-	  if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline)
-	    DAC960_ReadWriteError(Command);
-	  DAC960_ProcessCompletedBuffer(BufferHeader, false);
-	}
-      if (NextBufferHeader != NULL)
-	{
-	  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-	  Command->BlockNumber +=
-	    BufferHeader->b_size >> DAC960_BlockSizeBits;
-	  Command->BlockCount =
-	    NextBufferHeader->b_size >> DAC960_BlockSizeBits;
-	  Command->BufferHeader = NextBufferHeader;
-	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
-	  CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
-	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus(NextBufferHeader->b_data);
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
-    }
-  else if (CommandType == DAC960_MonitoringCommand)
-    {
-      DAC960_CommandOpcode_T CommandOpcode =
-	Command->CommandMailbox.Common.CommandOpcode;
-      unsigned int OldCriticalLogicalDriveCount = 0;
-      unsigned int NewCriticalLogicalDriveCount = 0;
-      if (CommandOpcode == DAC960_Enquiry)
-	{
-	  DAC960_Enquiry_T *OldEnquiry =
-	    &Controller->Enquiry[Controller->EnquiryIndex];
-	  DAC960_Enquiry_T *NewEnquiry =
-	    &Controller->Enquiry[Controller->EnquiryIndex ^= 1];
-	  OldCriticalLogicalDriveCount = OldEnquiry->CriticalLogicalDriveCount;
-	  NewCriticalLogicalDriveCount = NewEnquiry->CriticalLogicalDriveCount;
-	  if (NewEnquiry->StatusFlags.DeferredWriteError !=
-	      OldEnquiry->StatusFlags.DeferredWriteError)
-	    DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
-			    (NewEnquiry->StatusFlags.DeferredWriteError
-			     ? "TRUE" : "FALSE"));
-	  if ((NewCriticalLogicalDriveCount > 0 ||
-	       NewCriticalLogicalDriveCount != OldCriticalLogicalDriveCount) ||
-	      (NewEnquiry->OfflineLogicalDriveCount > 0 ||
-	       NewEnquiry->OfflineLogicalDriveCount !=
-	       OldEnquiry->OfflineLogicalDriveCount) ||
-	      (NewEnquiry->DeadDriveCount > 0 ||
-	       NewEnquiry->DeadDriveCount !=
-	       OldEnquiry->DeadDriveCount) ||
-	      (NewEnquiry->EventLogSequenceNumber !=
-	       OldEnquiry->EventLogSequenceNumber) ||
-	      Controller->MonitoringTimerCount == 0 ||
-	      (jiffies - Controller->SecondaryMonitoringTime
-	       >= DAC960_SecondaryMonitoringInterval))
-	    {
-	      Controller->NeedLogicalDriveInformation = true;
-	      Controller->NewEventLogSequenceNumber =
-		NewEnquiry->EventLogSequenceNumber;
-	      Controller->NeedErrorTableInformation = true;
-	      Controller->NeedDeviceStateInformation = true;
-	      Controller->DeviceStateChannel = 0;
-	      Controller->DeviceStateTargetID = 0;
-	      Controller->SecondaryMonitoringTime = jiffies;
-	    }
-	  if (NewEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress ||
-	      NewEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress ||
-	      OldEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress ||
-	      OldEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress)
-	    Controller->NeedRebuildProgress = true;
-	  if (OldEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
-	    switch (NewEnquiry->RebuildFlag)
-	      {
-	      case DAC960_NoStandbyRebuildOrCheckInProgress:
-		DAC960_Progress("Consistency Check Completed Successfully\n",
-				Controller);
-		break;
-	      case DAC960_StandbyRebuildInProgress:
-	      case DAC960_BackgroundRebuildInProgress:
-		break;
-	      case DAC960_BackgroundCheckInProgress:
-		Controller->NeedConsistencyCheckProgress = true;
-		break;
-	      case DAC960_StandbyRebuildCompletedWithError:
-		DAC960_Progress("Consistency Check Completed with Error\n",
-				Controller);
-		break;
-	      case DAC960_BackgroundRebuildOrCheckFailed_DriveFailed:
-		DAC960_Progress("Consistency Check Failed - "
-				"Physical Drive Failed\n", Controller);
-		break;
-	      case DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed:
-		DAC960_Progress("Consistency Check Failed - "
-				"Logical Drive Failed\n", Controller);
-		break;
-	      case DAC960_BackgroundRebuildOrCheckFailed_OtherCauses:
-		DAC960_Progress("Consistency Check Failed - Other Causes\n",
-				Controller);
-		break;
-	      case DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated:
-		DAC960_Progress("Consistency Check Successfully Terminated\n",
-				Controller);
-		break;
-	      }
-	  else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
-	    Controller->NeedConsistencyCheckProgress = true;
-	}
-      else if (CommandOpcode == DAC960_GetLogicalDriveInformation)
-	{
-	  int LogicalDriveNumber;
-	  for (LogicalDriveNumber = 0;
-	       LogicalDriveNumber < Controller->LogicalDriveCount;
-	       LogicalDriveNumber++)
-	    {
-	      DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation =
-		&Controller->LogicalDriveInformation
-			     [Controller->LogicalDriveInformationIndex]
-			     [LogicalDriveNumber];
-	      DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation =
-		&Controller->LogicalDriveInformation
-			     [Controller->LogicalDriveInformationIndex ^ 1]
-			     [LogicalDriveNumber];
-	      if (NewLogicalDriveInformation->LogicalDriveState !=
-		  OldLogicalDriveInformation->LogicalDriveState)
-		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
-				"is now %s\n", Controller,
-				LogicalDriveNumber,
-				Controller->ControllerNumber,
-				LogicalDriveNumber,
-				(NewLogicalDriveInformation->LogicalDriveState
-				 == DAC960_LogicalDrive_Online
-				 ? "ONLINE"
-				 : NewLogicalDriveInformation->LogicalDriveState
-				 == DAC960_LogicalDrive_Critical
-				 ? "CRITICAL" : "OFFLINE"));
-	      if (NewLogicalDriveInformation->WriteBack !=
-		  OldLogicalDriveInformation->WriteBack)
-		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
-				"is now %s\n", Controller,
-				LogicalDriveNumber,
-				Controller->ControllerNumber,
-				LogicalDriveNumber,
-				(NewLogicalDriveInformation->WriteBack
-				 ? "WRITE BACK" : "WRITE THRU"));
-	    }
-	  Controller->LogicalDriveInformationIndex ^= 1;
-	}
-      else if (CommandOpcode == DAC960_PerformEventLogOperation)
-	{
-	  DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry;
-	  if (EventLogEntry->SequenceNumber ==
-	      Controller->OldEventLogSequenceNumber)
-	    {
-	      unsigned char SenseKey = EventLogEntry->SenseKey;
-	      unsigned char AdditionalSenseCode =
-		EventLogEntry->AdditionalSenseCode;
-	      unsigned char AdditionalSenseCodeQualifier =
-		EventLogEntry->AdditionalSenseCodeQualifier;
-	      if (SenseKey == 9 &&
-		  AdditionalSenseCode == 0x80 &&
-		  AdditionalSenseCodeQualifier < DAC960_EventMessagesCount)
-		DAC960_Critical("Physical Drive %d:%d %s\n", Controller,
-				EventLogEntry->Channel,
-				EventLogEntry->TargetID,
-				DAC960_EventMessages[
-				  AdditionalSenseCodeQualifier]);
-	      else if (!((SenseKey == 2 &&
-			  AdditionalSenseCode == 0x04 &&
-			  (AdditionalSenseCodeQualifier == 0x01 ||
-			   AdditionalSenseCodeQualifier == 0x02)) ||
-			 (SenseKey == 6 && AdditionalSenseCode == 0x29 &&
-			  Controller->MonitoringTimerCount == 0)))
-		DAC960_Critical("Physical Drive %d:%d Error Log: "
-				"Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
-				Controller,
-				EventLogEntry->Channel,
-				EventLogEntry->TargetID,
-				SenseKey,
-				AdditionalSenseCode,
-				AdditionalSenseCodeQualifier);
-	    }
-	  Controller->OldEventLogSequenceNumber++;
-	}
-      else if (CommandOpcode == DAC960_GetErrorTable)
-	{
-	  DAC960_ErrorTable_T *OldErrorTable =
-	    &Controller->ErrorTable[Controller->ErrorTableIndex];
-	  DAC960_ErrorTable_T *NewErrorTable =
-	    &Controller->ErrorTable[Controller->ErrorTableIndex ^= 1];
-	  int Channel, TargetID;
-	  for (Channel = 0; Channel < Controller->Channels; Channel++)
-	    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
-	      {
-		DAC960_ErrorTableEntry_T *NewErrorEntry =
-		  &NewErrorTable->ErrorTableEntries[Channel][TargetID];
-		DAC960_ErrorTableEntry_T *OldErrorEntry =
-		  &OldErrorTable->ErrorTableEntries[Channel][TargetID];
-		if ((NewErrorEntry->ParityErrorCount !=
-		     OldErrorEntry->ParityErrorCount) ||
-		    (NewErrorEntry->SoftErrorCount !=
-		     OldErrorEntry->SoftErrorCount) ||
-		    (NewErrorEntry->HardErrorCount !=
-		     OldErrorEntry->HardErrorCount) ||
-		    (NewErrorEntry->MiscErrorCount !=
-		     OldErrorEntry->MiscErrorCount))
-		  DAC960_Critical("Physical Drive %d:%d Errors: "
-				  "Parity = %d, Soft = %d, "
-				  "Hard = %d, Misc = %d\n",
-				  Controller, Channel, TargetID,
-				  NewErrorEntry->ParityErrorCount,
-				  NewErrorEntry->SoftErrorCount,
-				  NewErrorEntry->HardErrorCount,
-				  NewErrorEntry->MiscErrorCount);
-	      }
-	}
-      else if (CommandOpcode == DAC960_GetDeviceState)
-	{
-	  DAC960_DeviceState_T *OldDeviceState =
-	    &Controller->DeviceState[Controller->DeviceStateIndex]
-				    [Controller->DeviceStateChannel]
-				    [Controller->DeviceStateTargetID];
-	  DAC960_DeviceState_T *NewDeviceState =
-	    &Controller->DeviceState[Controller->DeviceStateIndex ^ 1]
-				    [Controller->DeviceStateChannel]
-				    [Controller->DeviceStateTargetID];
-	  if (NewDeviceState->DeviceState != OldDeviceState->DeviceState)
-	    DAC960_Critical("Physical Drive %d:%d is now %s\n", Controller,
-			    Controller->DeviceStateChannel,
-			    Controller->DeviceStateTargetID,
-			    (NewDeviceState->DeviceState == DAC960_Device_Dead
-			     ? "DEAD"
-			     : NewDeviceState->DeviceState
-			       == DAC960_Device_WriteOnly
-			       ? "WRITE-ONLY"
-			       : NewDeviceState->DeviceState
-				 == DAC960_Device_Online
-				 ? "ONLINE" : "STANDBY"));
-	  if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
-	    {
-	      Controller->DeviceStateChannel++;
-	      Controller->DeviceStateTargetID = 0;
-	    }
-	}
-      else if (CommandOpcode == DAC960_GetRebuildProgress)
-	{
-	  unsigned int LogicalDriveNumber =
-	    Controller->RebuildProgress.LogicalDriveNumber;
-	  unsigned int LogicalDriveSize =
-	    Controller->RebuildProgress.LogicalDriveSize;
-	  unsigned int BlocksCompleted =
-	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
-	  switch (CommandStatus)
-	    {
-	    case DAC960_NormalCompletion:
-	      Controller->EphemeralProgressMessage = true;
-	      DAC960_Progress("Rebuild in Progress: "
-			      "Logical Drive %d (/dev/rd/c%dd%d) "
-			      "%d%% completed\n",
-			      Controller, LogicalDriveNumber,
-			      Controller->ControllerNumber,
-			      LogicalDriveNumber,
-			      (100 * (BlocksCompleted >> 7))
-			      / (LogicalDriveSize >> 7));
-	      Controller->EphemeralProgressMessage = false;
-	      break;
-	    case DAC960_RebuildFailed_LogicalDriveFailure:
-	      DAC960_Progress("Rebuild Failed due to "
-			      "Logical Drive Failure\n", Controller);
-	      break;
-	    case DAC960_RebuildFailed_BadBlocksOnOther:
-	      DAC960_Progress("Rebuild Failed due to "
-			      "Bad Blocks on Other Drives\n", Controller);
-	      break;
-	    case DAC960_RebuildFailed_NewDriveFailed:
-	      DAC960_Progress("Rebuild Failed due to "
-			      "Failure of Drive Being Rebuilt\n", Controller);
-	      break;
-	    case DAC960_RebuildSuccessful:
-	    case DAC960_NoRebuildOrCheckInProgress:
-	      DAC960_Progress("Rebuild Completed Successfully\n", Controller);
-	      break;
-	    }
-	}
-      else if (CommandOpcode == DAC960_RebuildStat)
-	{
-	  unsigned int LogicalDriveNumber =
-	    Controller->RebuildProgress.LogicalDriveNumber;
-	  unsigned int LogicalDriveSize =
-	    Controller->RebuildProgress.LogicalDriveSize;
-	  unsigned int BlocksCompleted =
-	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
-	  if (CommandStatus == DAC960_NormalCompletion)
-	    {
-	      Controller->EphemeralProgressMessage = true;
-	      DAC960_Progress("Consistency Check in Progress: "
-			      "Logical Drive %d (/dev/rd/c%dd%d) "
-			      "%d%% completed\n",
-			      Controller, LogicalDriveNumber,
-			      Controller->ControllerNumber,
-			      LogicalDriveNumber,
-			      (100 * (BlocksCompleted >> 7))
-			      / (LogicalDriveSize >> 7));
-	      Controller->EphemeralProgressMessage = false;
-	    }
-	}
-      if (Controller->NeedLogicalDriveInformation &&
-	  NewCriticalLogicalDriveCount >= OldCriticalLogicalDriveCount)
-	{
-	  Controller->NeedLogicalDriveInformation = false;
-	  Command->CommandMailbox.Type3.CommandOpcode =
-	    DAC960_GetLogicalDriveInformation;
-	  Command->CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(
-	      &Controller->LogicalDriveInformation
-			   [Controller->LogicalDriveInformationIndex ^ 1]);
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
-      if (Controller->NewEventLogSequenceNumber
-	  - Controller->OldEventLogSequenceNumber > 0)
-	{
-	  Command->CommandMailbox.Type3E.CommandOpcode =
-	    DAC960_PerformEventLogOperation;
-	  Command->CommandMailbox.Type3E.OperationType =
-	    DAC960_GetEventLogEntry;
-	  Command->CommandMailbox.Type3E.OperationQualifier = 1;
-	  Command->CommandMailbox.Type3E.SequenceNumber =
-	    Controller->OldEventLogSequenceNumber;
-	  Command->CommandMailbox.Type3E.BusAddress =
-	    Virtual_to_Bus(&Controller->EventLogEntry);
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
-      if (Controller->NeedErrorTableInformation)
-	{
-	  Controller->NeedErrorTableInformation = false;
-	  Command->CommandMailbox.Type3.CommandOpcode = DAC960_GetErrorTable;
-	  Command->CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(
-	      &Controller->ErrorTable[Controller->ErrorTableIndex ^ 1]);
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
-      if (Controller->NeedDeviceStateInformation)
-	{
-	  while (Controller->DeviceStateChannel < Controller->Channels)
-	    {
-	      DAC960_DeviceState_T *OldDeviceState =
-		&Controller->DeviceState[Controller->DeviceStateIndex]
-					[Controller->DeviceStateChannel]
-					[Controller->DeviceStateTargetID];
-	      if (OldDeviceState->Present &&
-		  OldDeviceState->DeviceType == DAC960_DiskType)
-		{
-		  Command->CommandMailbox.Type3D.CommandOpcode =
-		    DAC960_GetDeviceState;
-		  Command->CommandMailbox.Type3D.Channel =
-		    Controller->DeviceStateChannel;
-		  Command->CommandMailbox.Type3D.TargetID =
-		    Controller->DeviceStateTargetID;
-		  Command->CommandMailbox.Type3D.BusAddress =
-		    Virtual_to_Bus(&Controller->DeviceState
-				      [Controller->DeviceStateIndex ^ 1]
-				      [Controller->DeviceStateChannel]
-				      [Controller->DeviceStateTargetID]);
-		  DAC960_QueueCommand(Command);
-		  return;
-		}
-	      if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
-		{
-		  Controller->DeviceStateChannel++;
-		  Controller->DeviceStateTargetID = 0;
-		}
-	    }
-	  Controller->NeedDeviceStateInformation = false;
-	  Controller->DeviceStateIndex ^= 1;
-	}
-      if (Controller->NeedRebuildProgress)
-	{
-	  Controller->NeedRebuildProgress = false;
-	  Command->CommandMailbox.Type3.CommandOpcode =
-	    DAC960_GetRebuildProgress;
-	  Command->CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(&Controller->RebuildProgress);
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
-      if (Controller->NeedConsistencyCheckProgress)
-	{
-	  Controller->NeedConsistencyCheckProgress = false;
-	  Command->CommandMailbox.Type3.CommandOpcode = DAC960_RebuildStat;
-	  Command->CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(&Controller->RebuildProgress);
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
-      if (Controller->NeedLogicalDriveInformation &&
-	  NewCriticalLogicalDriveCount < OldCriticalLogicalDriveCount)
-	{
-	  Controller->NeedLogicalDriveInformation = false;
-	  Command->CommandMailbox.Type3.CommandOpcode =
-	    DAC960_GetLogicalDriveInformation;
-	  Command->CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(
-	      &Controller->LogicalDriveInformation
-			   [Controller->LogicalDriveInformationIndex ^ 1]);
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
-      Controller->MonitoringTimerCount++;
-      Controller->MonitoringTimer.expires =
-	jiffies + DAC960_MonitoringTimerInterval;
-      add_timer(&Controller->MonitoringTimer);
-    }
-  else if (CommandType == DAC960_ImmediateCommand)
-    {
-      up(Command->Semaphore);
-      Command->Semaphore = NULL;
-      return;
-    }
-  else panic("DAC960: Unknown Command Type %d\n", CommandType);
-  /*
-    Queue a Status Monitoring Command to the Controller using the just
-    completed Command if one was deferred previously due to lack of a
-    free Command when the Monitoring Timer Function was called.
-  */
-  if (Controller->MonitoringCommandDeferred)
-    {
-      Controller->MonitoringCommandDeferred = false;
-      DAC960_QueueMonitoringCommand(Command);
-      return;
-    }
-  /*
-    Execute a User Command using the just completed Command if one was
-    deferred previously due to lack of a free Command.
-  */
-  if (Controller->UserCommandDeferred)
-    {
-      Controller->UserCommandDeferred = false;
-      Controller->UserCommand = Command;
-      up(Controller->UserCommandSemaphore);
-      return;
-    }
-  /*
-    Deallocate the Command, and wake up any processes waiting on a free Command.
-  */
-  DAC960_DeallocateCommand(Command);
-  wake_up(&Controller->CommandWaitQueue);
-}
-
-
-/*
-  DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers.
-*/
-
-static void DAC960_InterruptHandler(int IRQ_Channel,
-				    void *DeviceIdentifier,
-				    Registers_T *InterruptRegisters)
-{
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  DAC960_StatusMailbox_T *NextStatusMailbox;
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags);
-  /*
-    Process Hardware Interrupts for Controller.
-  */
-  switch (Controller->ControllerType)
-    {
-    case DAC960_V5_Controller:
-      DAC960_V5_AcknowledgeInterrupt(ControllerBaseAddress);
-      NextStatusMailbox = Controller->NextStatusMailbox;
-      while (NextStatusMailbox->Fields.Valid)
-	{
-	  DAC960_CommandIdentifier_T CommandIdentifier =
-	    NextStatusMailbox->Fields.CommandIdentifier;
-	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
-	  Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
-	  NextStatusMailbox->Word = 0;
-	  if (++NextStatusMailbox > Controller->LastStatusMailbox)
-	    NextStatusMailbox = Controller->FirstStatusMailbox;
-	  DAC960_ProcessCompletedCommand(Command);
-	}
-      Controller->NextStatusMailbox = NextStatusMailbox;
-      break;
-    case DAC960_V4_Controller:
-      DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress);
-      NextStatusMailbox = Controller->NextStatusMailbox;
-      while (NextStatusMailbox->Fields.Valid)
-	{
-	  DAC960_CommandIdentifier_T CommandIdentifier =
-	    NextStatusMailbox->Fields.CommandIdentifier;
-	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
-	  Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
-	  NextStatusMailbox->Word = 0;
-	  if (++NextStatusMailbox > Controller->LastStatusMailbox)
-	    NextStatusMailbox = Controller->FirstStatusMailbox;
-	  DAC960_ProcessCompletedCommand(Command);
-	}
-      Controller->NextStatusMailbox = NextStatusMailbox;
-      break;
-    case DAC960_V3_Controller:
-      while (DAC960_V3_StatusAvailableP(ControllerBaseAddress))
-	{
-	  DAC960_CommandIdentifier_T CommandIdentifier =
-	    DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress);
-	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
-	  Command->CommandStatus =
-	    DAC960_V3_ReadStatusRegister(ControllerBaseAddress);
-	  DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress);
-	  DAC960_V3_AcknowledgeStatus(ControllerBaseAddress);
-	  DAC960_ProcessCompletedCommand(Command);
-	}
-      break;
-    }
-  /*
-    Attempt to remove additional I/O Requests from the Controller's
-    I/O Request Queue and queue them to the Controller.
-  */
-  while (DAC960_ProcessRequest(Controller, false)) ;
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller.
-*/
-
-static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command)
-{
-  DAC960_Controller_T *Controller = Command->Controller;
-  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-  DAC960_ClearCommand(Command);
-  Command->CommandType = DAC960_MonitoringCommand;
-  CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry;
-  CommandMailbox->Type3.BusAddress =
-    Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]);
-  DAC960_QueueCommand(Command);
-}
-
-
-/*
-  DAC960_MonitoringTimerFunction is the timer function for monitoring
-  the status of DAC960 Controllers.
-*/
-
-static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
-{
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData;
-  DAC960_Command_T *Command;
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-  /*
-    Queue a Status Monitoring Command to Controller.
-  */
-  Command = DAC960_AllocateCommand(Controller);
-  if (Command != NULL)
-    DAC960_QueueMonitoringCommand(Command);
-  else Controller->MonitoringCommandDeferred = true;
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_Open is the Device Open Function for the DAC960 Driver.
-*/
-
-static int DAC960_Open(Inode_T *Inode, File_T *File)
-{
-  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
-  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
-  DAC960_Controller_T *Controller;
-  if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
-    return -ENXIO;
-  Controller = DAC960_Controllers[ControllerNumber];
-  if (Controller == NULL ||
-      LogicalDriveNumber > Controller->LogicalDriveCount - 1)
-    return -ENXIO;
-  if (Controller->LogicalDriveInformation
-		  [Controller->LogicalDriveInformationIndex]
-		  [LogicalDriveNumber].LogicalDriveState
-      == DAC960_LogicalDrive_Offline)
-    return -ENXIO;
-  if (Controller->LogicalDriveInitialState[LogicalDriveNumber]
-      == DAC960_LogicalDrive_Offline)
-    {
-      Controller->LogicalDriveInitialState[LogicalDriveNumber] =
-	DAC960_LogicalDrive_Online;
-      DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
-      resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
-    }
-  if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
-    return -ENXIO;
-  /*
-    Increment Controller and Logical Drive Usage Counts.
-  */
-  Controller->ControllerUsageCount++;
-  Controller->LogicalDriveUsageCount[LogicalDriveNumber]++;
-  return 0;
-}
-
-
-/*
-  DAC960_Release is the Device Release Function for the DAC960 Driver.
-*/
-
-static void DAC960_Release(Inode_T *Inode, File_T *File)
-{
-  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
-  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
-  DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-  /*
-    Force any buffered data to be written.
-  */
-  fsync_dev(Inode->i_rdev);
-  /*
-    Decrement the Logical Drive and Controller Usage Counts.
-  */
-  Controller->LogicalDriveUsageCount[LogicalDriveNumber]--;
-  Controller->ControllerUsageCount--;
-}
-
-
-/*
-  DAC960_Ioctl is the Device Ioctl Function for the DAC960 Driver.
-*/
-
-static int DAC960_Ioctl(Inode_T *Inode, File_T *File,
-			unsigned int Request, unsigned long Argument)
-{
-  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
-  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
-  int PartitionNumber, ErrorCode;
-  unsigned short Cylinders;
-  DiskGeometry_T *Geometry;
-  DAC960_Controller_T *Controller;
-  if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
-    return -ENXIO;
-  Controller = DAC960_Controllers[ControllerNumber];
-  if (Controller == NULL ||
-      LogicalDriveNumber > Controller->LogicalDriveCount - 1)
-    return -ENXIO;
-  switch (Request)
-    {
-    case HDIO_GETGEO:
-      /* Get BIOS Disk Geometry. */
-      Geometry = (DiskGeometry_T *) Argument;
-      if (Geometry == NULL) return -EINVAL;
-      ErrorCode = verify_area(VERIFY_WRITE, Geometry, sizeof(DiskGeometry_T));
-      if (ErrorCode != 0) return ErrorCode;
-      Cylinders =
-	Controller->LogicalDriveInformation
-		    [Controller->LogicalDriveInformationIndex]
-		    [LogicalDriveNumber].LogicalDriveSize
-	/ (Controller->GeometryTranslationHeads *
-	   Controller->GeometryTranslationSectors);
-      put_user(Controller->GeometryTranslationHeads, &Geometry->heads);
-      put_user(Controller->GeometryTranslationSectors, &Geometry->sectors);
-      put_user(Cylinders, &Geometry->cylinders);
-      put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
-					  .start_sect, &Geometry->start);
-      return 0;
-    case BLKGETSIZE:
-      /* Get Device Size. */
-      if ((long *) Argument == NULL) return -EINVAL;
-      ErrorCode = verify_area(VERIFY_WRITE, (long *) Argument, sizeof(long));
-      if (ErrorCode != 0) return ErrorCode;
-      put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].nr_sects,
-	       (long *) Argument);
-      return 0;
-    case BLKRAGET:
-      /* Get Read-Ahead. */
-      if ((int *) Argument == NULL) return -EINVAL;
-      ErrorCode = verify_area(VERIFY_WRITE, (int *) Argument, sizeof(int));
-      if (ErrorCode != 0) return ErrorCode;
-      put_user(read_ahead[MAJOR(Inode->i_rdev)], (int *) Argument);
-      return 0;
-    case BLKRASET:
-      /* Set Read-Ahead. */
-      if (!suser()) return -EACCES;
-      if (Argument > 256) return -EINVAL;
-      read_ahead[MAJOR(Inode->i_rdev)] = Argument;
-      return 0;
-    case BLKFLSBUF:
-      /* Flush Buffers. */
-      if (!suser()) return -EACCES;
-      fsync_dev(Inode->i_rdev);
-      invalidate_buffers(Inode->i_rdev);
-      return 0;
-    case BLKRRPART:
-      /* Re-Read Partition Table. */
-      if (!suser()) return -EACCES;
-      if (Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 1)
-	return -EBUSY;
-      for (PartitionNumber = 0;
-	   PartitionNumber < DAC960_MaxPartitions;
-	   PartitionNumber++)
-	{
-	  KernelDevice_T Device = DAC960_KernelDevice(ControllerNumber,
-						      LogicalDriveNumber,
-						      PartitionNumber);
-	  int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber,
-					       PartitionNumber);
-	  if (Controller->GenericDiskInfo.part[MinorNumber].nr_sects == 0)
-	    continue;
-	  /*
-	    Flush all changes and invalidate buffered state.
-	  */
-	  sync_dev(Device);
-	  invalidate_inodes(Device);
-	  invalidate_buffers(Device);
-	  /*
-	    Clear existing partition sizes.
-	  */
-	  if (PartitionNumber > 0)
-	    {
-	      Controller->GenericDiskInfo.part[MinorNumber].start_sect = 0;
-	      Controller->GenericDiskInfo.part[MinorNumber].nr_sects = 0;
-	    }
-	  /*
-	    Reset the Block Size so that the partition table can be read.
-	  */
-	  set_blocksize(Device, BLOCK_SIZE);
-	}
-      resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
-      return 0;
-    }
-  return -EINVAL;
-}
-
-
-/*
-  DAC960_GenericDiskInit is the Generic Disk Information Initialization
-  Function for the DAC960 Driver.
-*/
-
-static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo)
-{
-  DAC960_Controller_T *Controller =
-    (DAC960_Controller_T *) GenericDiskInfo->real_devices;
-  DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
-    Controller->LogicalDriveInformation
-		[Controller->LogicalDriveInformationIndex];
-  int LogicalDriveNumber;
-  for (LogicalDriveNumber = 0;
-       LogicalDriveNumber < Controller->LogicalDriveCount;
-       LogicalDriveNumber++)
-    GenericDiskInfo->part[DAC960_MinorNumber(LogicalDriveNumber, 0)].nr_sects =
-      LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize;
-}
-
-
-/*
-  DAC960_Message prints Driver Messages.
-*/
-
-static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
-			   char *Format,
-			   DAC960_Controller_T *Controller,
-			   ...)
-{
-  static char Buffer[DAC960_LineBufferSize];
-  static boolean BeginningOfLine = true;
-  va_list Arguments;
-  int Length = 0;
-  va_start(Arguments, Controller);
-  Length = vsprintf(Buffer, Format, Arguments);
-  va_end(Arguments);
-  if (Controller == NULL)
-    printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
-	   DAC960_ControllerCount, Buffer);
-  else if (MessageLevel == DAC960_AnnounceLevel ||
-	   MessageLevel == DAC960_InfoLevel)
-    {
-      if (!Controller->ControllerInitialized)
-	{
-	  strcpy(&Controller->InitialStatusBuffer[
-		    Controller->InitialStatusLength], Buffer);
-	  Controller->InitialStatusLength += Length;
-	  if (MessageLevel == DAC960_AnnounceLevel)
-	    {
-	      static int AnnouncementLines = 0;
-	      if (++AnnouncementLines <= 2)
-		printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel],
-		       Buffer);
-	    }
-	  else
-	    {
-	      if (BeginningOfLine)
-		{
-		  if (Buffer[0] != '\n' || Length > 1)
-		    printk("%sDAC960#%d: %s",
-			   DAC960_MessageLevelMap[MessageLevel],
-			   Controller->ControllerNumber, Buffer);
-		}
-	      else printk("%s", Buffer);
-	    }
-	}
-      else
-	{
-	  strcpy(&Controller->CurrentStatusBuffer[
-		    Controller->CurrentStatusLength], Buffer);
-	  Controller->CurrentStatusLength += Length;
-	}
-    }
-  else if (MessageLevel == DAC960_ProgressLevel)
-    {
-      strcpy(Controller->RebuildProgressBuffer, Buffer);
-      Controller->RebuildProgressLength = Length;
-      if (Controller->EphemeralProgressMessage)
-	{
-	  if (jiffies - Controller->LastProgressReportTime
-	      >= DAC960_ProgressReportingInterval)
-	    {
-	      printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
-		     Controller->ControllerNumber, Buffer);
-	      Controller->LastProgressReportTime = jiffies;
-	    }
-	}
-      else printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
-		  Controller->ControllerNumber, Buffer);
-    }
-  else if (MessageLevel == DAC960_UserCriticalLevel)
-    {
-      strcpy(&Controller->UserStatusBuffer[Controller->UserStatusLength],
-	     Buffer);
-      Controller->UserStatusLength += Length;
-      if (Buffer[0] != '\n' || Length > 1)
-	printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
-	       Controller->ControllerNumber, Buffer);
-    }
-  else
-    {
-      if (BeginningOfLine)
-	printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
-	       Controller->ControllerNumber, Buffer);
-      else printk("%s", Buffer);
-    }
-  BeginningOfLine = (Buffer[Length-1] == '\n');
-}
-
-
-/*
-  DAC960_AllocateUserCommand allocates a Command structure for a User Command.
-  If a User Command is already active, NULL is returned.
-*/
-
-static DAC960_Command_T *DAC960_AllocateUserCommand(DAC960_Controller_T
-						    *Controller)
-{
-  Semaphore_T Semaphore = MUTEX_LOCKED;
-  DAC960_Command_T *Command = NULL;
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-  /*
-    Acquire exclusive access to the User Command facility.
-  */
-  if (Controller->UserCommandActive) goto Done;
-  Controller->UserCommandActive = true;
-  /*
-    Allocate a Command.  If none is available, set the User Command Deferred
-    flag to tell the Interrupt Handler to save the next Command completed.
-  */
-  Command = DAC960_AllocateCommand(Controller);
-  if (Command == NULL)
-    {
-      Controller->UserCommandDeferred = true;
-      Controller->UserCommandSemaphore = &Semaphore;
-      DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-      down(&Semaphore);
-      DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-      Command = Controller->UserCommand;
-      Controller->UserCommand = NULL;
-    }
-  /*
-    Initialize the Command.
-  */
-  DAC960_ClearCommand(Command);
-  Command->CommandType = DAC960_ImmediateCommand;
-  /*
-    Release exclusive access to Controller.
-  */
- Done:
-  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-  return Command;
-}
-
-
-/*
-  DAC960_DeallocateUserCommand deallocates a User Command.
-*/
-
-static void DAC960_DeallocateUserCommand(DAC960_Command_T *Command)
-{
-  DAC960_Controller_T *Controller = Command->Controller;
-  ProcessorFlags_T ProcessorFlags;
-  /*
-    Acquire exclusive access to Controller.
-  */
-  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-  /*
-    Deallocate the Command.
-  */
-  DAC960_DeallocateCommand(Command);
-  /*
-    Release exclusive access to the User Command facility.
-  */
-  Controller->UserCommandActive = false;
-  /*
-    Release exclusive access to Controller.
-  */
-  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-}
-
-
-/*
-  DAC960_ParsePhysicalDrive parses spaces followed by a Physical Drive
-  Channel:TargetID specification from a User Command string.  It updates
-  Channel and TargetID and returns true on success and returns false otherwise.
-*/
-
-static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller,
-					 char *UserCommandString,
-					 unsigned char *Channel,
-					 unsigned char *TargetID)
-{
-  char *NewUserCommandString = UserCommandString;
-  unsigned long XChannel, XTargetID;
-  while (*UserCommandString == ' ') UserCommandString++;
-  if (UserCommandString == NewUserCommandString)
-    return false;
-  XChannel = simple_strtoul(UserCommandString, &NewUserCommandString, 10);
-  if (NewUserCommandString == UserCommandString ||
-      *NewUserCommandString != ':' ||
-      XChannel >= Controller->Channels)
-    return false;
-  UserCommandString = ++NewUserCommandString;
-  XTargetID = simple_strtoul(UserCommandString, &NewUserCommandString, 10);
-  if (NewUserCommandString == UserCommandString ||
-      *NewUserCommandString != '\0' ||
-      XTargetID >= DAC960_MaxTargets)
-    return false;
-  *Channel = XChannel;
-  *TargetID = XTargetID;
-  return true;
-}
-
-
-/*
-  DAC960_ParseLogicalDrive parses spaces followed by a Logical Drive Number
-  specification from a User Command string.  It updates LogicalDriveNumber and
-  returns true on success and returns false otherwise.
-*/
-
-static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller,
-					char *UserCommandString,
-					unsigned char *LogicalDriveNumber)
-{
-  char *NewUserCommandString = UserCommandString;
-  unsigned long XLogicalDriveNumber;
-  while (*UserCommandString == ' ') UserCommandString++;
-  if (UserCommandString == NewUserCommandString)
-    return false;
-  XLogicalDriveNumber =
-    simple_strtoul(UserCommandString, &NewUserCommandString, 10);
-  if (NewUserCommandString == UserCommandString ||
-      *NewUserCommandString != '\0' ||
-      XLogicalDriveNumber >= Controller->LogicalDriveCount)
-    return false;
-  *LogicalDriveNumber = XLogicalDriveNumber;
-  return true;
-}
-
-
-/*
-  DAC960_SetDeviceState sets the Device State for a Physical Drive.
-*/
-
-static void DAC960_SetDeviceState(DAC960_Controller_T *Controller,
-				  DAC960_Command_T *Command,
-				  unsigned char Channel,
-				  unsigned char TargetID,
-				  DAC960_PhysicalDeviceState_T DeviceState,
-				  const char *DeviceStateString)
-{
-  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
-  CommandMailbox->Type3D.CommandOpcode = DAC960_StartDevice;
-  CommandMailbox->Type3D.Channel = Channel;
-  CommandMailbox->Type3D.TargetID = TargetID;
-  CommandMailbox->Type3D.DeviceState = DeviceState;
-  CommandMailbox->Type3D.Modifier = 0;
-  DAC960_ExecuteCommand(Command);
-  switch (Command->CommandStatus)
-    {
-    case DAC960_NormalCompletion:
-      DAC960_UserCritical("%s of Physical Drive %d:%d Succeeded\n", Controller,
-			  DeviceStateString, Channel, TargetID);
-      break;
-    case DAC960_UnableToStartDevice:
-      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
-			  "Unable to Start Device\n", Controller,
-			  DeviceStateString, Channel, TargetID);
-      break;
-    case DAC960_NoDeviceAtAddress:
-      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
-			  "No Device at Address\n", Controller,
-			  DeviceStateString, Channel, TargetID);
-      break;
-    case DAC960_InvalidChannelOrTargetOrModifier:
-      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
-			  "Invalid Channel or Target or Modifier\n",
-			  Controller, DeviceStateString, Channel, TargetID);
-      break;
-    case DAC960_ChannelBusy:
-      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
-			  "Channel Busy\n", Controller,
-			  DeviceStateString, Channel, TargetID);
-      break;
-    default:
-      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
-			  "Unexpected Status %04X\n", Controller,
-			  DeviceStateString, Channel, TargetID,
-			  Command->CommandStatus);
-      break;
-    }
-}
-
-
-/*
-  DAC960_ExecuteUserCommand executes a User Command.
-*/
-
-static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller,
-					 char *UserCommand)
-{
-  DAC960_Command_T *Command;
-  DAC960_CommandMailbox_T *CommandMailbox;
-  unsigned char Channel, TargetID, LogicalDriveNumber;
-  Command = DAC960_AllocateUserCommand(Controller);
-  if (Command == NULL) return false;
-  CommandMailbox = &Command->CommandMailbox;
-  Controller->UserStatusLength = 0;
-  if (strcmp(UserCommand, "flush-cache") == 0)
-    {
-      CommandMailbox->Type3.CommandOpcode = DAC960_Flush;
-      DAC960_ExecuteCommand(Command);
-      DAC960_UserCritical("Cache Flush Completed\n", Controller);
-    }
-  else if (strncmp(UserCommand, "kill", 4) == 0 &&
-	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[4],
-				     &Channel, &TargetID))
-    {
-      DAC960_DeviceState_T *DeviceState =
-	&Controller->DeviceState[Controller->DeviceStateIndex]
-				[Channel][TargetID];
-      if (DeviceState->Present &&
-	  DeviceState->DeviceType == DAC960_DiskType &&
-	  DeviceState->DeviceState != DAC960_Device_Dead)
-	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
-			      DAC960_Device_Dead, "Kill");
-      else DAC960_UserCritical("Kill of Physical Drive %d:%d Illegal\n",
-			       Controller, Channel, TargetID);
-    }
-  else if (strncmp(UserCommand, "make-online", 11) == 0 &&
-	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[11],
-				     &Channel, &TargetID))
-    {
-      DAC960_DeviceState_T *DeviceState =
-	&Controller->DeviceState[Controller->DeviceStateIndex]
-				[Channel][TargetID];
-      if (DeviceState->Present &&
-	  DeviceState->DeviceType == DAC960_DiskType &&
-	  DeviceState->DeviceState == DAC960_Device_Dead)
-	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
-			      DAC960_Device_Online, "Make Online");
-      else DAC960_UserCritical("Make Online of Physical Drive %d:%d Illegal\n",
-			       Controller, Channel, TargetID);
-
-    }
-  else if (strncmp(UserCommand, "make-standby", 12) == 0 &&
-	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[12],
-				     &Channel, &TargetID))
-    {
-      DAC960_DeviceState_T *DeviceState =
-	&Controller->DeviceState[Controller->DeviceStateIndex]
-				[Channel][TargetID];
-      if (DeviceState->Present &&
-	  DeviceState->DeviceType == DAC960_DiskType &&
-	  DeviceState->DeviceState == DAC960_Device_Dead)
-	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
-			      DAC960_Device_Standby, "Make Standby");
-      else DAC960_UserCritical("Make Standby of Physical Drive %d:%d Illegal\n",
-			       Controller, Channel, TargetID);
-    }
-  else if (strncmp(UserCommand, "rebuild", 7) == 0 &&
-	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[7],
-				     &Channel, &TargetID))
-    {
-      CommandMailbox->Type3D.CommandOpcode = DAC960_RebuildAsync;
-      CommandMailbox->Type3D.Channel = Channel;
-      CommandMailbox->Type3D.TargetID = TargetID;
-      DAC960_ExecuteCommand(Command);
-      switch (Command->CommandStatus)
-	{
-	case DAC960_NormalCompletion:
-	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Initiated\n",
-			      Controller, Channel, TargetID);
-	  break;
-	case DAC960_AttemptToRebuildOnlineDrive:
-	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
-			      "Attempt to Rebuild Online or "
-			      "Unresponsive Drive\n",
-			      Controller, Channel, TargetID);
-	  break;
-	case DAC960_NewDiskFailedDuringRebuild:
-	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
-			      "New Disk Failed During Rebuild\n",
-			      Controller, Channel, TargetID);
-	  break;
-	case DAC960_InvalidDeviceAddress:
-	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
-			      "Invalid Device Address\n",
-			      Controller, Channel, TargetID);
-	  break;
-	case DAC960_RebuildOrCheckAlreadyInProgress:
-	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
-			      "Rebuild or Consistency Check Already "
-			      "in Progress\n", Controller, Channel, TargetID);
-	  break;
-	default:
-	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
-			      "Unexpected Status %04X\n", Controller,
-			      Channel, TargetID, Command->CommandStatus);
-	  break;
-	}
-    }
-  else if (strncmp(UserCommand, "check-consistency", 17) == 0 &&
-	   DAC960_ParseLogicalDrive(Controller, &UserCommand[17],
-				    &LogicalDriveNumber))
-    {
-      CommandMailbox->Type3C.CommandOpcode = DAC960_CheckConsistencyAsync;
-      CommandMailbox->Type3C.LogicalDriveNumber = LogicalDriveNumber;
-      CommandMailbox->Type3C.AutoRestore = true;
-      DAC960_ExecuteCommand(Command);
-      switch (Command->CommandStatus)
-	{
-	case DAC960_NormalCompletion:
-	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
-			      "(/dev/rd/c%dd%d) Initiated\n",
-			      Controller, LogicalDriveNumber,
-			      Controller->ControllerNumber,
-			      LogicalDriveNumber);
-	  break;
-	case DAC960_DependentDiskIsDead:
-	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
-			      "(/dev/rd/c%dd%d) Failed - "
-			      "Dependent Physical Drive is DEAD\n",
-			      Controller, LogicalDriveNumber,
-			      Controller->ControllerNumber,
-			      LogicalDriveNumber);
-	  break;
-	case DAC960_InvalidOrNonredundantLogicalDrive:
-	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
-			      "(/dev/rd/c%dd%d) Failed - "
-			      "Invalid or Nonredundant Logical Drive\n",
-			      Controller, LogicalDriveNumber,
-			      Controller->ControllerNumber,
-			      LogicalDriveNumber);
-	  break;
-	case DAC960_RebuildOrCheckAlreadyInProgress:
-	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
-			      "(/dev/rd/c%dd%d) Failed - Rebuild or "
-			      "Consistency Check Already in Progress\n",
-			      Controller, LogicalDriveNumber,
-			      Controller->ControllerNumber,
-			      LogicalDriveNumber);
-	  break;
-	default:
-	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
-			      "(/dev/rd/c%dd%d) Failed - "
-			      "Unexpected Status %04X\n",
-			      Controller, LogicalDriveNumber,
-			      Controller->ControllerNumber,
-			      LogicalDriveNumber, Command->CommandStatus);
-	  break;
-	}
-    }
-  else if (strcmp(UserCommand, "cancel-rebuild") == 0 ||
-	   strcmp(UserCommand, "cancel-consistency-check") == 0)
-    {
-      unsigned char OldRebuildRateConstant;
-      CommandMailbox->Type3R.CommandOpcode = DAC960_RebuildControl;
-      CommandMailbox->Type3R.RebuildRateConstant = 0xFF;
-      CommandMailbox->Type3R.BusAddress =
-	Virtual_to_Bus(&OldRebuildRateConstant);
-      DAC960_ExecuteCommand(Command);
-      switch (Command->CommandStatus)
-	{
-	case DAC960_NormalCompletion:
-	  DAC960_UserCritical("Rebuild or Consistency Check Cancelled\n",
-			      Controller);
-	  break;
-	default:
-	  DAC960_UserCritical("Cancellation of Rebuild or "
-			      "Consistency Check Failed - "
-			      "Unexpected Status %04X\n",
-			      Controller, Command->CommandStatus);
-	  break;
-	}
-    }
-  else DAC960_UserCritical("Illegal User Command: '%s'\n",
-			   Controller, UserCommand);
-  DAC960_DeallocateUserCommand(Command);
-  return true;
-}
-
-
-/*
-  DAC960_ProcReadStatus implements reading /proc/rd/status.
-*/
-
-static int DAC960_ProcReadStatus(Inode_T *Inode, File_T *File,
-				 char *Buffer, int Count)
-{
-  char *StatusMessage = "OK\n";
-  int StatusMessageOffset, BytesAvailable;
-  int ControllerNumber;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      DAC960_Enquiry_T *Enquiry;
-      if (Controller == NULL) continue;
-      Enquiry = &Controller->Enquiry[Controller->EnquiryIndex];
-      if (Enquiry->CriticalLogicalDriveCount > 0 ||
-	  Enquiry->OfflineLogicalDriveCount > 0 ||
-	  Enquiry->DeadDriveCount > 0)
-	{
-	  StatusMessage = "ALERT\n";
-	  break;
-	}
-    }
-  StatusMessageOffset = File->f_pos;
-  BytesAvailable = strlen(StatusMessage) - StatusMessageOffset;
-  if (Count > BytesAvailable) Count = BytesAvailable;
-  if (Count <= 0) return 0;
-  memcpy_tofs(Buffer, &StatusMessage[StatusMessageOffset], Count);
-  File->f_pos += Count;
-  return Count;
-}
-
-
-/*
-  DAC960_ProcReadInitialStatus implements reading /proc/rd/cN/initial_status.
-*/
-
-static int DAC960_ProcReadInitialStatus(Inode_T *Inode, File_T *File,
-					char *Buffer, int Count)
-{
-  DAC960_Controller_T *Controller = NULL;
-  int InitialStatusOffset, BytesAvailable;
-  int ControllerNumber;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      Controller = DAC960_Controllers[ControllerNumber];
-      if (Controller == NULL) continue;
-      if (Controller->InitialStatusProcEntry.low_ino == Inode->i_ino) break;
-    }
-  InitialStatusOffset = File->f_pos;
-  BytesAvailable = Controller->InitialStatusLength - InitialStatusOffset;
-  if (Count > BytesAvailable) Count = BytesAvailable;
-  if (Count <= 0) return 0;
-  memcpy_tofs(Buffer,
-	      &Controller->InitialStatusBuffer[InitialStatusOffset], Count);
-  File->f_pos += Count;
-  return Count;
-}
-
-
-/*
-  DAC960_ProcReadCurrentStatus implements reading /proc/rd/cN/current_status.
-*/
-
-static int DAC960_ProcReadCurrentStatus(Inode_T *Inode, File_T *File,
-					char *Buffer, int Count)
-{
-  DAC960_Controller_T *Controller = NULL;
-  int CurrentStatusOffset, BytesAvailable;
-  int ControllerNumber;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      Controller = DAC960_Controllers[ControllerNumber];
-      if (Controller == NULL) continue;
-      if (Controller->CurrentStatusProcEntry.low_ino == Inode->i_ino) break;
-    }
-  Controller->CurrentStatusLength = 0;
-  DAC960_AnnounceDriver(Controller);
-  DAC960_ReportControllerConfiguration(Controller);
-  Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
-  Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
-  if (Controller->RebuildProgressLength > 0)
-    {
-      strcpy(&Controller->CurrentStatusBuffer[Controller->CurrentStatusLength],
-	     Controller->RebuildProgressBuffer);
-      Controller->CurrentStatusLength += Controller->RebuildProgressLength;
-    }
-  else
-    {
-      char *StatusMessage = "No Rebuild or Consistency Check in Progress\n";
-      strcpy(&Controller->CurrentStatusBuffer[Controller->CurrentStatusLength],
-	     StatusMessage);
-      Controller->CurrentStatusLength += strlen(StatusMessage);
-    }
-  CurrentStatusOffset = File->f_pos;
-  BytesAvailable = Controller->CurrentStatusLength - CurrentStatusOffset;
-  if (Count > BytesAvailable) Count = BytesAvailable;
-  if (Count <= 0) return 0;
-  memcpy_tofs(Buffer,
-	      &Controller->CurrentStatusBuffer[CurrentStatusOffset], Count);
-  File->f_pos += Count;
-  return Count;
-}
-
-
-/*
-  DAC960_ProcReadUserCommand implements reading /proc/rd/cN/user_command.
-*/
-
-static int DAC960_ProcReadUserCommand(Inode_T *Inode, File_T *File,
-				      char *Buffer, int Count)
-{
-  DAC960_Controller_T *Controller = NULL;
-  int UserStatusOffset, BytesAvailable;
-  int ControllerNumber;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      Controller = DAC960_Controllers[ControllerNumber];
-      if (Controller == NULL) continue;
-      if (Controller->UserCommandProcEntry.low_ino == Inode->i_ino) break;
-    }
-  UserStatusOffset = File->f_pos;
-  BytesAvailable = Controller->UserStatusLength - UserStatusOffset;
-  if (Count > BytesAvailable) Count = BytesAvailable;
-  if (Count <= 0) return 0;
-  memcpy_tofs(Buffer, &Controller->UserStatusBuffer[UserStatusOffset], Count);
-  File->f_pos += Count;
-  return Count;
-}
-
-
-/*
-  DAC960_ProcWriteUserCommand implements writing /proc/rd/cN/user_command.
-*/
-
-static int DAC960_ProcWriteUserCommand(Inode_T *Inode, File_T *File,
-				       const char *Buffer, int Count)
-{
-  DAC960_Controller_T *Controller = NULL;
-  char CommandBuffer[80];
-  int ControllerNumber, Length;
-  if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
-  memcpy_fromfs(CommandBuffer, Buffer, Count);
-  CommandBuffer[Count] = '\0';
-  Length = strlen(CommandBuffer);
-  if (CommandBuffer[Length-1] == '\n')
-    CommandBuffer[--Length] = '\0';
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      Controller = DAC960_Controllers[ControllerNumber];
-      if (Controller == NULL) continue;
-      if (Controller->UserCommandProcEntry.low_ino == Inode->i_ino) break;
-    }
-  return (DAC960_ExecuteUserCommand(Controller, CommandBuffer)
-	  ? Count : -EBUSY);
-}
-
-
-/*
-  DAC960_CreateProcEntries creates the /proc/rd/... entries for the DAC960
-  Driver.
-*/
-
-static void DAC960_CreateProcEntries(void)
-{
-  static PROC_DirectoryEntry_T StatusProcEntry;
-  static FileOperations_T
-    StatusFileOperations = { read: DAC960_ProcReadStatus };
-  static InodeOperations_T
-    StatusInodeOperations = { &StatusFileOperations };
-  static FileOperations_T
-    InitialStatusFileOperations = { read: DAC960_ProcReadInitialStatus };
-  static InodeOperations_T
-    InitialStatusInodeOperations = { &InitialStatusFileOperations };
-  static FileOperations_T
-    CurrentStatusFileOperations = { read: DAC960_ProcReadCurrentStatus };
-  static InodeOperations_T
-    CurrentStatusInodeOperations = { &CurrentStatusFileOperations };
-  static FileOperations_T
-    UserCommandFileOperations = { read: DAC960_ProcReadUserCommand,
-				  write: DAC960_ProcWriteUserCommand };
-  static InodeOperations_T
-    UserCommandInodeOperations = { &UserCommandFileOperations };
-  int ControllerNumber;
-  DAC960_ProcDirectoryEntry.name = "rd";
-  DAC960_ProcDirectoryEntry.namelen = strlen(DAC960_ProcDirectoryEntry.name);
-  DAC960_ProcDirectoryEntry.mode = S_IFDIR | S_IRUGO | S_IXUGO;
-  DAC960_ProcDirectoryEntry.ops = &proc_dir_inode_operations;
-  proc_register_dynamic(&proc_root, &DAC960_ProcDirectoryEntry);
-  StatusProcEntry.name = "status";
-  StatusProcEntry.namelen = strlen(StatusProcEntry.name);
-  StatusProcEntry.mode = S_IFREG | S_IRUGO;
-  StatusProcEntry.ops = &StatusInodeOperations;
-  proc_register_dynamic(&DAC960_ProcDirectoryEntry, &StatusProcEntry);
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      PROC_DirectoryEntry_T *ControllerProcEntry, *InitialStatusProcEntry;
-      PROC_DirectoryEntry_T *CurrentStatusProcEntry, *UserCommandProcEntry;
-      if (Controller == NULL) continue;
-      ControllerProcEntry = &Controller->ControllerProcEntry;
-      ControllerProcEntry->name = Controller->ControllerName;
-      ControllerProcEntry->namelen = strlen(ControllerProcEntry->name);
-      ControllerProcEntry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
-      ControllerProcEntry->ops = &proc_dir_inode_operations;
-      proc_register_dynamic(&DAC960_ProcDirectoryEntry, ControllerProcEntry);
-      InitialStatusProcEntry = &Controller->InitialStatusProcEntry;
-      InitialStatusProcEntry->name = "initial_status";
-      InitialStatusProcEntry->namelen = strlen(InitialStatusProcEntry->name);
-      InitialStatusProcEntry->mode = S_IFREG | S_IRUGO;
-      InitialStatusProcEntry->ops = &InitialStatusInodeOperations;
-      proc_register_dynamic(ControllerProcEntry, InitialStatusProcEntry);
-      CurrentStatusProcEntry = &Controller->CurrentStatusProcEntry;
-      CurrentStatusProcEntry->name = "current_status";
-      CurrentStatusProcEntry->namelen = strlen(CurrentStatusProcEntry->name);
-      CurrentStatusProcEntry->mode = S_IFREG | S_IRUGO;
-      CurrentStatusProcEntry->ops = &CurrentStatusInodeOperations;
-      proc_register_dynamic(ControllerProcEntry, CurrentStatusProcEntry);
-      UserCommandProcEntry = &Controller->UserCommandProcEntry;
-      UserCommandProcEntry->name = "user_command";
-      UserCommandProcEntry->namelen = strlen(UserCommandProcEntry->name);
-      UserCommandProcEntry->mode = S_IFREG | S_IWUSR | S_IRUSR;
-      UserCommandProcEntry->ops = &UserCommandInodeOperations;
-      proc_register_dynamic(ControllerProcEntry, UserCommandProcEntry);
-    }
-}
-
-
-/*
-  DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the DAC960
-  Driver.
-*/
-
-static void DAC960_DestroyProcEntries(void)
-{
-  proc_unregister(&proc_root, DAC960_ProcDirectoryEntry.low_ino);
-}
diff -urN linux-2.0.37-pre10/linux/drivers/block/DAC960.h linux-2.0.37-pre11/linux/drivers/block/DAC960.h
--- linux-2.0.37-pre10/linux/drivers/block/DAC960.h	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/linux/drivers/block/DAC960.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,2071 +0,0 @@
-/*
-
-  Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers
-
-  Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
-
-  This program is free software; you may redistribute and/or modify it under
-  the terms of the GNU General Public License Version 2 as published by the
-  Free Software Foundation.
-
-  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 complete details.
-
-  The author respectfully requests that any modifications to this software be
-  sent directly to him for evaluation and testing.
-
-*/
-
-
-/*
-  DAC960_DriverVersion protects the private portion of this file.
-*/
-
-#ifdef DAC960_DriverVersion
-
-
-/*
-  Define the maximum number of DAC960 Controllers supported by this driver.
-*/
-
-#define DAC960_MaxControllers			8
-
-
-/*
-  Define the maximum number of Controller Channels supported by this driver.
-*/
-
-#define DAC960_MaxChannels			3
-
-
-/*
-  Define the maximum number of Targets per Channel supported by this driver.
-*/
-
-#define DAC960_MaxTargets			16
-
-
-/*
-  Define the maximum number of Logical Drives supported by any DAC960 model.
-*/
-
-#define DAC960_MaxLogicalDrives			32
-
-
-/*
-  Define the maximum number of Partitions allowed for each Logical Drive.
-*/
-
-#define DAC960_MaxPartitions			8
-#define DAC960_MaxPartitionsBits		3
-
-
-/*
-  Define the maximum Driver Queue Depth and Controller Queue Depth supported
-  by any DAC960 model.
-*/
-
-#define DAC960_MaxDriverQueueDepth		127
-#define DAC960_MaxControllerQueueDepth		128
-
-
-/*
-  Define the maximum number of Scatter/Gather Segments supported by any
-  DAC960 model.
-*/
-
-#define DAC960_MaxScatterGatherSegments		33
-
-
-/*
-  Define the DAC960 Controller Monitoring Timer Interval.
-*/
-
-#define DAC960_MonitoringTimerInterval		(10 * HZ)
-
-
-/*
-  Define the DAC960 Controller Secondary Monitoring Interval.
-*/
-
-#define DAC960_SecondaryMonitoringInterval	(60 * HZ)
-
-
-/*
-  Define the DAC960 Controller Progress Reporting Interval.
-*/
-
-#define DAC960_ProgressReportingInterval	(60 * HZ)
-
-
-/*
-  Define the number of Command Mailboxes and Status Mailboxes used by the
-  Memory Mailbox Interface.
-*/
-
-#define DAC960_CommandMailboxCount		256
-#define DAC960_StatusMailboxCount		1024
-
-
-/*
-  Define macros to extract the Controller Number, Logical Drive Number, and
-  Partition Number from a Kernel Device, and to construct a Major Number, Minor
-  Number, and Kernel Device from the Controller Number, Logical Drive Number,
-  and Partition Number.  There is one Major Number assigned to each Controller.
-  The associated Minor Number is divided into the Logical Drive Number and
-  Partition Number.
-*/
-
-#define DAC960_ControllerNumber(Device) \
-  (MAJOR(Device) - DAC960_MAJOR)
-
-#define DAC960_LogicalDriveNumber(Device) \
-  (MINOR(Device) >> DAC960_MaxPartitionsBits)
-
-#define DAC960_PartitionNumber(Device) \
-  (MINOR(Device) & (DAC960_MaxPartitions - 1))
-
-#define DAC960_MajorNumber(ControllerNumber) \
-  (DAC960_MAJOR + (ControllerNumber))
-
-#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \
-   (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber))
-
-#define DAC960_MinorCount			(DAC960_MaxLogicalDrives \
-						 * DAC960_MaxPartitions)
-
-#define DAC960_KernelDevice(ControllerNumber,				       \
-			    LogicalDriveNumber,				       \
-			    PartitionNumber)				       \
-   MKDEV(DAC960_MajorNumber(ControllerNumber),				       \
-	 DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber))
-
-
-/*
-  Define the DAC960 Controller fixed Block Size and Block Size Bits.
-*/
-
-#define DAC960_BlockSize			512
-#define DAC960_BlockSizeBits			9
-
-
-/*
-  Define the Controller Line, Status Buffer, Rebuild Progress, and
-  User Message Sizes.
-*/
-
-#define DAC960_LineBufferSize			100
-#define DAC960_StatusBufferSize			5000
-#define DAC960_RebuildProgressSize		200
-#define DAC960_UserMessageSize			200
-
-
-/*
-  Define the Driver Message Levels.
-*/
-
-typedef enum DAC960_MessageLevel
-{
-  DAC960_AnnounceLevel =			0,
-  DAC960_InfoLevel =				1,
-  DAC960_NoticeLevel =				2,
-  DAC960_WarningLevel =				3,
-  DAC960_ErrorLevel =				4,
-  DAC960_ProgressLevel =			5,
-  DAC960_CriticalLevel =			6,
-  DAC960_UserCriticalLevel =			7
-}
-DAC960_MessageLevel_T;
-
-static char
-  *DAC960_MessageLevelMap[] =
-    { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING,
-      KERN_ERR, KERN_CRIT, KERN_CRIT, KERN_CRIT };
-
-
-/*
-  Define Driver Message macros.
-*/
-
-#define DAC960_Announce(Format, Arguments...) \
-  DAC960_Message(DAC960_AnnounceLevel, Format, ##Arguments)
-
-#define DAC960_Info(Format, Arguments...) \
-  DAC960_Message(DAC960_InfoLevel, Format, ##Arguments)
-
-#define DAC960_Notice(Format, Arguments...) \
-  DAC960_Message(DAC960_NoticeLevel, Format, ##Arguments)
-
-#define DAC960_Warning(Format, Arguments...) \
-  DAC960_Message(DAC960_WarningLevel, Format, ##Arguments)
-
-#define DAC960_Error(Format, Arguments...) \
-  DAC960_Message(DAC960_ErrorLevel, Format, ##Arguments)
-
-#define DAC960_Progress(Format, Arguments...) \
-  DAC960_Message(DAC960_ProgressLevel, Format, ##Arguments)
-
-#define DAC960_Critical(Format, Arguments...) \
-  DAC960_Message(DAC960_CriticalLevel, Format, ##Arguments)
-
-#define DAC960_UserCritical(Format, Arguments...) \
-  DAC960_Message(DAC960_UserCriticalLevel, Format, ##Arguments)
-
-
-/*
-  Define the types of DAC960 Controllers that are supported.
-*/
-
-typedef enum
-{
-  DAC960_V5_Controller =			1,	/* DAC1164P */
-  DAC960_V4_Controller =			2,	/* DAC960PTL/PJ/PG */
-  DAC960_V3_Controller =			3	/* DAC960PU/PD/PL */
-}
-DAC960_ControllerType_T;
-
-
-/*
-  Define a Boolean data type.
-*/
-
-typedef enum { false, true } __attribute__ ((packed)) boolean;
-
-
-/*
-  Define a 32 bit I/O Address data type.
-*/
-
-typedef unsigned int DAC960_IO_Address_T;
-
-
-/*
-  Define a 32 bit PCI Bus Address data type.
-*/
-
-typedef unsigned int DAC960_PCI_Address_T;
-
-
-/*
-  Define a 32 bit Bus Address data type.
-*/
-
-typedef unsigned int DAC960_BusAddress_T;
-
-
-/*
-  Define a 32 bit Byte Count data type.
-*/
-
-typedef unsigned int DAC960_ByteCount_T;
-
-
-/*
-  Define types for some of the structures that interface with the rest
-  of the Linux Kernel and I/O Subsystem.
-*/
-
-typedef struct buffer_head BufferHeader_T;
-typedef struct file File_T;
-typedef struct file_operations FileOperations_T;
-typedef struct gendisk GenericDiskInfo_T;
-typedef struct hd_geometry DiskGeometry_T;
-typedef struct hd_struct DiskPartition_T;
-typedef struct inode Inode_T;
-typedef struct inode_operations InodeOperations_T;
-typedef kdev_t KernelDevice_T;
-typedef struct proc_dir_entry PROC_DirectoryEntry_T;
-typedef unsigned long ProcessorFlags_T;
-typedef struct pt_regs Registers_T;
-typedef struct request IO_Request_T;
-typedef struct semaphore Semaphore_T;
-typedef struct timer_list Timer_T;
-typedef struct wait_queue WaitQueue_T;
-
-
-/*
-  Define the DAC960 V5 Controller Interface Register Offsets.
-*/
-
-#define DAC960_V5_RegisterWindowSize		0x80
-
-typedef enum
-{
-  DAC960_V5_InboundDoorBellRegisterOffset =	0x60,
-  DAC960_V5_OutboundDoorBellRegisterOffset =	0x61,
-  DAC960_V5_InterruptMaskRegisterOffset =	0x34,
-  DAC960_V5_CommandOpcodeRegisterOffset =	0x50,
-  DAC960_V5_CommandIdentifierRegisterOffset =	0x51,
-  DAC960_V5_MailboxRegister2Offset =		0x52,
-  DAC960_V5_MailboxRegister3Offset =		0x53,
-  DAC960_V5_MailboxRegister4Offset =		0x54,
-  DAC960_V5_MailboxRegister5Offset =		0x55,
-  DAC960_V5_MailboxRegister6Offset =		0x56,
-  DAC960_V5_MailboxRegister7Offset =		0x57,
-  DAC960_V5_MailboxRegister8Offset =		0x58,
-  DAC960_V5_MailboxRegister9Offset =		0x59,
-  DAC960_V5_MailboxRegister10Offset =		0x5A,
-  DAC960_V5_MailboxRegister11Offset =		0x5B,
-  DAC960_V5_MailboxRegister12Offset =		0x5C,
-  DAC960_V5_StatusCommandIdentifierRegOffset =	0x5D,
-  DAC960_V5_StatusRegisterOffset =		0x5E
-}
-DAC960_V5_RegisterOffsets_T;
-
-
-/*
-  Define the structure of the DAC960 V5 Inbound Door Bell Register.
-*/
-
-typedef union DAC960_V5_InboundDoorBellRegister
-{
-  unsigned char All;
-  struct {
-    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
-    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
-    boolean GenerateInterrupt:1;			/* Bit 2 */
-    boolean ControllerReset:1;				/* Bit 3 */
-    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
-    unsigned char :3;					/* Bits 5-7 */
-  } Write;
-  struct {
-    boolean HardwareMailboxEmpty:1;			/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
-  } Read;
-}
-DAC960_V5_InboundDoorBellRegister_T;
-
-
-/*
-  Define the structure of the DAC960 V5 Outbound Door Bell Register.
-*/
-
-typedef union DAC960_V5_OutboundDoorBellRegister
-{
-  unsigned char All;
-  struct {
-    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
-    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
-    unsigned char :6;					/* Bits 2-7 */
-  } Write;
-  struct {
-    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
-    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
-    unsigned char :6;					/* Bits 2-7 */
-  } Read;
-}
-DAC960_V5_OutboundDoorBellRegister_T;
-
-
-/*
-  Define the structure of the DAC960 V5 Interrupt Mask Register.
-*/
-
-typedef union DAC960_V5_InterruptMaskRegister
-{
-  unsigned char All;
-  struct {
-    unsigned char :2;					/* Bits 0-1 */
-    boolean DisableInterrupts:1;			/* Bit 2 */
-    unsigned char :5;					/* Bits 3-7 */
-  } Bits;
-}
-DAC960_V5_InterruptMaskRegister_T;
-
-
-/*
-  Define the DAC960 V4 Controller Interface Register Offsets.
-*/
-
-#define DAC960_V4_RegisterWindowSize		0x2000
-
-typedef enum
-{
-  DAC960_V4_InboundDoorBellRegisterOffset =	0x0020,
-  DAC960_V4_OutboundDoorBellRegisterOffset =	0x002C,
-  DAC960_V4_InterruptMaskRegisterOffset =	0x0034,
-  DAC960_V4_CommandOpcodeRegisterOffset =	0x1000,
-  DAC960_V4_CommandIdentifierRegisterOffset =	0x1001,
-  DAC960_V4_MailboxRegister2Offset =		0x1002,
-  DAC960_V4_MailboxRegister3Offset =		0x1003,
-  DAC960_V4_MailboxRegister4Offset =		0x1004,
-  DAC960_V4_MailboxRegister5Offset =		0x1005,
-  DAC960_V4_MailboxRegister6Offset =		0x1006,
-  DAC960_V4_MailboxRegister7Offset =		0x1007,
-  DAC960_V4_MailboxRegister8Offset =		0x1008,
-  DAC960_V4_MailboxRegister9Offset =		0x1009,
-  DAC960_V4_MailboxRegister10Offset =		0x100A,
-  DAC960_V4_MailboxRegister11Offset =		0x100B,
-  DAC960_V4_MailboxRegister12Offset =		0x100C,
-  DAC960_V4_StatusCommandIdentifierRegOffset =	0x1018,
-  DAC960_V4_StatusRegisterOffset =		0x101A
-}
-DAC960_V4_RegisterOffsets_T;
-
-
-/*
-  Define the structure of the DAC960 V4 Inbound Door Bell Register.
-*/
-
-typedef union DAC960_V4_InboundDoorBellRegister
-{
-  unsigned int All;
-  struct {
-    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
-    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
-    boolean GenerateInterrupt:1;			/* Bit 2 */
-    boolean ControllerReset:1;				/* Bit 3 */
-    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
-    unsigned int :27;					/* Bits 5-31 */
-  } Write;
-  struct {
-    boolean HardwareMailboxFull:1;			/* Bit 0 */
-    unsigned int :31;					/* Bits 1-31 */
-  } Read;
-}
-DAC960_V4_InboundDoorBellRegister_T;
-
-
-/*
-  Define the structure of the DAC960 V4 Outbound Door Bell Register.
-*/
-
-typedef union DAC960_V4_OutboundDoorBellRegister
-{
-  unsigned int All;
-  struct {
-    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
-    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
-    unsigned int :30;					/* Bits 2-31 */
-  } Write;
-  struct {
-    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
-    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
-    unsigned int :30;					/* Bits 2-31 */
-  } Read;
-}
-DAC960_V4_OutboundDoorBellRegister_T;
-
-
-/*
-  Define the structure of the DAC960 V4 Interrupt Mask Register.
-*/
-
-typedef union DAC960_V4_InterruptMaskRegister
-{
-  unsigned int All;
-  struct {
-    unsigned int MessageUnitInterruptMask1:2;		/* Bits 0-1 */
-    boolean DisableInterrupts:1;			/* Bit 2 */
-    unsigned int MessageUnitInterruptMask2:5;		/* Bits 3-7 */
-    unsigned int Reserved0:24;				/* Bits 8-31 */
-  } Bits;
-}
-DAC960_V4_InterruptMaskRegister_T;
-
-
-/*
-  Define the DAC960 V3 Controller Interface Register Offsets.
-*/
-
-#define DAC960_V3_RegisterWindowSize		0x80
-
-typedef enum
-{
-  DAC960_V3_CommandOpcodeRegisterOffset =	0x00,
-  DAC960_V3_CommandIdentifierRegisterOffset =	0x01,
-  DAC960_V3_MailboxRegister2Offset =		0x02,
-  DAC960_V3_MailboxRegister3Offset =		0x03,
-  DAC960_V3_MailboxRegister4Offset =		0x04,
-  DAC960_V3_MailboxRegister5Offset =		0x05,
-  DAC960_V3_MailboxRegister6Offset =		0x06,
-  DAC960_V3_MailboxRegister7Offset =		0x07,
-  DAC960_V3_MailboxRegister8Offset =		0x08,
-  DAC960_V3_MailboxRegister9Offset =		0x09,
-  DAC960_V3_MailboxRegister10Offset =		0x0A,
-  DAC960_V3_MailboxRegister11Offset =		0x0B,
-  DAC960_V3_MailboxRegister12Offset =		0x0C,
-  DAC960_V3_StatusCommandIdentifierRegOffset =	0x0D,
-  DAC960_V3_StatusRegisterOffset =		0x0E,
-  DAC960_V3_InboundDoorBellRegisterOffset =	0x40,
-  DAC960_V3_OutboundDoorBellRegisterOffset =	0x41,
-  DAC960_V3_InterruptEnableRegisterOffset =	0x43
-}
-DAC960_V3_RegisterOffsets_T;
-
-
-/*
-  Define the structure of the DAC960 V3 Inbound Door Bell Register.
-*/
-
-typedef union DAC960_V3_InboundDoorBellRegister
-{
-  unsigned char All;
-  struct {
-    boolean NewCommand:1;				/* Bit 0 */
-    boolean AcknowledgeStatus:1;			/* Bit 1 */
-    boolean GenerateInterrupt:1;			/* Bit 2 */
-    boolean ControllerReset:1;				/* Bit 3 */
-    unsigned char :4;					/* Bits 4-7 */
-  } Write;
-  struct {
-    boolean MailboxFull:1;				/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
-  } Read;
-}
-DAC960_V3_InboundDoorBellRegister_T;
-
-
-/*
-  Define the structure of the DAC960 V3 Outbound Door Bell Register.
-*/
-
-typedef union DAC960_V3_OutboundDoorBellRegister
-{
-  unsigned char All;
-  struct {
-    boolean AcknowledgeInterrupt:1;			/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
-  } Write;
-  struct {
-    boolean StatusAvailable:1;				/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
-  } Read;
-}
-DAC960_V3_OutboundDoorBellRegister_T;
-
-
-/*
-  Define the structure of the DAC960 V3 Interrupt Enable Register.
-*/
-
-typedef union DAC960_V3_InterruptEnableRegister
-{
-  unsigned char All;
-  struct {
-    boolean EnableInterrupts:1;				/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
-  } Bits;
-}
-DAC960_V3_InterruptEnableRegister_T;
-
-
-/*
-  Define the DAC960 Command Identifier type.
-*/
-
-typedef unsigned char DAC960_CommandIdentifier_T;
-
-
-/*
-  Define the DAC960 Command Opcodes.
-*/
-
-typedef enum
-{
-  /* I/O Commands */
-  DAC960_ReadExtended =				0x33,
-  DAC960_WriteExtended =			0x34,
-  DAC960_ReadAheadExtended =			0x35,
-  DAC960_ReadExtendedWithScatterGather =	0xB3,
-  DAC960_WriteExtendedWithScatterGather =	0xB4,
-  DAC960_Read =					0x36,
-  DAC960_ReadWithOldScatterGather =		0xB6,
-  DAC960_Write =				0x37,
-  DAC960_WriteWithOldScatterGather =		0xB7,
-  DAC960_DCDB =					0x04,
-  DAC960_DCDBWithScatterGather =		0x84,
-  DAC960_Flush =				0x0A,
-  /* Controller Status Related Commands */
-  DAC960_Enquiry =				0x53,
-  DAC960_Enquiry2 =				0x1C,
-  DAC960_GetLogicalDriveElement =		0x55,
-  DAC960_GetLogicalDriveInformation =		0x19,
-  DAC960_IOPortRead =				0x39,
-  DAC960_IOPortWrite =				0x3A,
-  DAC960_GetSDStats =				0x3E,
-  DAC960_GetPDStats =				0x3F,
-  DAC960_PerformEventLogOperation =		0x72,
-  /* Device Related Commands */
-  DAC960_StartDevice =				0x10,
-  DAC960_GetDeviceState =			0x50,
-  DAC960_StopChannel =				0x13,
-  DAC960_StartChannel =				0x12,
-  DAC960_ResetChannel =				0x1A,
-  /* Commands Associated with Data Consistency and Errors */
-  DAC960_Rebuild =				0x09,
-  DAC960_RebuildAsync =				0x16,
-  DAC960_CheckConsistency =			0x0F,
-  DAC960_CheckConsistencyAsync =		0x1E,
-  DAC960_RebuildStat =				0x0C,
-  DAC960_GetRebuildProgress =			0x27,
-  DAC960_RebuildControl =			0x1F,
-  DAC960_ReadBadBlockTable =			0x0B,
-  DAC960_ReadBadDataTable =			0x25,
-  DAC960_ClearBadDataTable =			0x26,
-  DAC960_GetErrorTable =			0x17,
-  DAC960_AddCapacityAsync =			0x2A,
-  /* Configuration Related Commands */
-  DAC960_ReadConfig2 =				0x3D,
-  DAC960_WriteConfig2 =				0x3C,
-  DAC960_ReadConfigurationOnDisk =		0x4A,
-  DAC960_WriteConfigurationOnDisk =		0x4B,
-  DAC960_ReadConfiguration =			0x4E,
-  DAC960_ReadBackupConfiguration =		0x4D,
-  DAC960_WriteConfiguration =			0x4F,
-  DAC960_AddConfiguration =			0x4C,
-  DAC960_ReadConfigurationLabel =		0x48,
-  DAC960_WriteConfigurationLabel =		0x49,
-  /* Firmware Upgrade Related Commands */
-  DAC960_LoadImage =				0x20,
-  DAC960_StoreImage =				0x21,
-  DAC960_ProgramImage =				0x22,
-  /* Diagnostic Commands */
-  DAC960_SetDiagnosticMode =			0x31,
-  DAC960_RunDiagnostic =			0x32,
-  /* Subsystem Service Commands */
-  DAC960_GetSubsystemData =			0x70,
-  DAC960_SetSubsystemParameters =		0x71
-}
-__attribute__ ((packed))
-DAC960_CommandOpcode_T;
-
-
-/*
-  Define the DAC960 Command Status Codes.
-*/
-
-#define DAC960_NormalCompletion			0x0000	/* Common */
-#define DAC960_CheckConditionReceived		0x0002	/* Common */
-#define DAC960_NoDeviceAtAddress		0x0102	/* Common */
-#define DAC960_InvalidDeviceAddress		0x0105	/* Common */
-#define DAC960_InvalidParameter			0x0105	/* Common */
-#define DAC960_IrrecoverableDataError		0x0001	/* I/O */
-#define DAC960_LogicalDriveNonexistentOrOffline	0x0002	/* I/O */
-#define DAC960_AccessBeyondEndOfLogicalDrive	0x0105	/* I/O */
-#define DAC960_BadDataEncountered		0x010C	/* I/O */
-#define DAC960_DeviceBusy			0x0008	/* DCDB */
-#define DAC960_DeviceNonresponsive		0x000E	/* DCDB */
-#define DAC960_CommandTerminatedAbnormally	0x000F	/* DCDB */
-#define DAC960_UnableToStartDevice		0x0002	/* Device */
-#define DAC960_InvalidChannelOrTargetOrModifier	0x0105	/* Device */
-#define DAC960_ChannelBusy			0x0106	/* Device */
-#define DAC960_ChannelNotStopped		0x0002	/* Device */
-#define DAC960_AttemptToRebuildOnlineDrive	0x0002	/* Consistency */
-#define DAC960_RebuildBadBlocksEncountered	0x0003	/* Consistency */
-#define DAC960_NewDiskFailedDuringRebuild	0x0004	/* Consistency */
-#define DAC960_RebuildOrCheckAlreadyInProgress	0x0106	/* Consistency */
-#define DAC960_DependentDiskIsDead		0x0002	/* Consistency */
-#define DAC960_InconsistentBlocksFound		0x0003	/* Consistency */
-#define DAC960_InvalidOrNonredundantLogicalDrive 0x0105	/* Consistency */
-#define DAC960_NoRebuildOrCheckInProgress	0x0105	/* Consistency */
-#define DAC960_RebuildInProgress_DataValid	0x0000	/* Consistency */
-#define DAC960_RebuildFailed_LogicalDriveFailure 0x0002	/* Consistency */
-#define DAC960_RebuildFailed_BadBlocksOnOther	0x0003	/* Consistency */
-#define DAC960_RebuildFailed_NewDriveFailed	0x0004	/* Consistency */
-#define DAC960_RebuildSuccessful		0x0100	/* Consistency */
-#define DAC960_AddCapacityInProgress		0x0004	/* Consistency */
-#define DAC960_AddCapacityFailedOrSuspended	0x00F4	/* Consistency */
-#define DAC960_Config2ChecksumError		0x0002	/* Configuration */
-#define DAC960_ConfigurationSuspended		0x0106	/* Configuration */
-#define DAC960_FailedToConfigureNVRAM		0x0105	/* Configuration */
-#define DAC960_ConfigurationNotSavedStateChange	0x0106	/* Configuration */
-#define DAC960_SubsystemNotInstalled		0x0001	/* Subsystem */
-#define DAC960_SubsystemFailed			0x0002	/* Subsystem */
-#define DAC960_SubsystemBusy			0x0106	/* Subsystem */
-
-typedef unsigned short DAC960_CommandStatus_T;
-
-
-/*
-  Define the Enquiry reply structure.
-*/
-
-typedef struct DAC960_Enquiry
-{
-  unsigned char NumberOfLogicalDrives;			/* Byte 0 */
-  unsigned int :24;					/* Bytes 1-3 */
-  unsigned int LogicalDriveSizes[32];			/* Bytes 4-131 */
-  unsigned short FlashAge;				/* Bytes 132-133 */
-  struct {
-    boolean DeferredWriteError:1;			/* Byte 134 Bit 0 */
-    boolean BatteryLow:1;				/* Byte 134 Bit 1 */
-    unsigned char :6;					/* Byte 134 Bits 2-7 */
-  } StatusFlags;
-  unsigned char :8;					/* Byte 135 */
-  unsigned char MinorFirmwareVersion;			/* Byte 136 */
-  unsigned char MajorFirmwareVersion;			/* Byte 137 */
-  enum {
-    DAC960_NoStandbyRebuildOrCheckInProgress =			0x00,
-    DAC960_StandbyRebuildInProgress =				0x01,
-    DAC960_BackgroundRebuildInProgress =			0x02,
-    DAC960_BackgroundCheckInProgress =				0x03,
-    DAC960_StandbyRebuildCompletedWithError =			0xFF,
-    DAC960_BackgroundRebuildOrCheckFailed_DriveFailed =		0xF0,
-    DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed =	0xF1,
-    DAC960_BackgroundRebuildOrCheckFailed_OtherCauses =		0xF2,
-    DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated =	0xF3
-  } __attribute__ ((packed)) RebuildFlag;		/* Byte 138 */
-  unsigned char MaxCommands;				/* Byte 139 */
-  unsigned char OfflineLogicalDriveCount;		/* Byte 140 */
-  unsigned char :8;					/* Byte 141 */
-  unsigned short EventLogSequenceNumber;		/* Bytes 142-143 */
-  unsigned char CriticalLogicalDriveCount;		/* Byte 144 */
-  unsigned int :24;					/* Bytes 145-147 */
-  unsigned char DeadDriveCount;				/* Byte 148 */
-  unsigned char :8;					/* Byte 149 */
-  unsigned char RebuildCount;				/* Byte 150 */
-  struct {
-    unsigned char :3;					/* Byte 151 Bits 0-2 */
-    boolean BatteryBackupUnitPresent:1;			/* Byte 151 Bit 3 */
-    unsigned char :3;					/* Byte 151 Bits 4-6 */
-    unsigned char :1;					/* Byte 151 Bit 7 */
-  } MiscFlags;
-  struct {
-    unsigned char TargetID;
-    unsigned char Channel;
-  } DeadDrives[21];					/* Bytes 152-194 */
-  unsigned char Reserved[62];				/* Bytes 195-255 */
-}
-__attribute__ ((packed))
-DAC960_Enquiry_T;
-
-
-/*
-  Define the Enquiry2 reply structure.
-*/
-
-typedef struct DAC960_Enquiry2
-{
-  struct {
-    enum {
-      DAC960_P_PD_PU =				0x01,
-      DAC960_PL =				0x02,
-      DAC960_PG =				0x10,
-      DAC960_PJ =				0x11,
-      DAC960_PR =				0x12,
-      DAC960_PT =				0x13,
-      DAC960_PTL0 =				0x14,
-      DAC960_PRL =				0x15,
-      DAC960_PTL1 =				0x16,
-      DAC1164_P =				0x20
-    } __attribute__ ((packed)) SubModel;		/* Byte 0 */
-    unsigned char ActualChannels;			/* Byte 1 */
-    enum {
-      DAC960_FiveChannelBoard =			0x01,
-      DAC960_ThreeChannelBoard =		0x02,
-      DAC960_TwoChannelBoard =			0x03,
-      DAC960_ThreeChannelASIC_DAC =		0x04
-    } __attribute__ ((packed)) Model;			/* Byte 2 */
-    enum {
-      DAC960_EISA_Controller =			0x01,
-      DAC960_MicroChannel_Controller =		0x02,
-      DAC960_PCI_Controller =			0x03,
-      DAC960_SCSItoSCSI_Controller =		0x08
-    } __attribute__ ((packed)) ProductFamily;		/* Byte 3 */
-  } HardwareID;						/* Bytes 0-3 */
-  /* MajorVersion.MinorVersion-FirmwareType-TurnID */
-  struct {
-    unsigned char MajorVersion;				/* Byte 4 */
-    unsigned char MinorVersion;				/* Byte 5 */
-    unsigned char TurnID;				/* Byte 6 */
-    char FirmwareType;					/* Byte 7 */
-  } FirmwareID;						/* Bytes 4-7 */
-  unsigned char :8;					/* Byte 8 */
-  unsigned int :24;					/* Bytes 9-11 */
-  unsigned char ConfiguredChannels;			/* Byte 12 */
-  unsigned char ActualChannels;				/* Byte 13 */
-  unsigned char MaxTargets;				/* Byte 14 */
-  unsigned char MaxTags;				/* Byte 15 */
-  unsigned char MaxLogicalDrives;			/* Byte 16 */
-  unsigned char MaxArms;				/* Byte 17 */
-  unsigned char MaxSpans;				/* Byte 18 */
-  unsigned char :8;					/* Byte 19 */
-  unsigned int :32;					/* Bytes 20-23 */
-  unsigned int MemorySize;				/* Bytes 24-27 */
-  unsigned int CacheSize;				/* Bytes 28-31 */
-  unsigned int FlashMemorySize;				/* Bytes 32-35 */
-  unsigned int NonVolatileMemorySize;			/* Bytes 36-39 */
-  struct {
-    enum {
-      DAC960_DRAM =				0x00,
-      DAC960_EDO =				0x01,
-      DAC960_SDRAM =				0x02
-    } __attribute__ ((packed)) RamType:3;		/* Byte 40 Bits 0-2 */
-    enum {
-      DAC960_None =				0x00,
-      DAC960_Parity =				0x01,
-      DAC960_ECC =				0x02
-    } __attribute__ ((packed)) ErrorCorrection:3;	/* Byte 40 Bits 3-5 */
-    boolean FastPageMode:1;				/* Byte 40 Bit 6 */
-    boolean LowPowerMemory:1;				/* Byte 40 Bit 7 */
-    unsigned char :8;					/* Bytes 41 */
-  } MemoryType;
-  unsigned short ClockSpeed;				/* Bytes 42-43 */
-  unsigned short MemorySpeed;				/* Bytes 44-45 */
-  unsigned short HardwareSpeed;				/* Bytes 46-47 */
-  unsigned int :32;					/* Bytes 48-51 */
-  unsigned int :32;					/* Bytes 52-55 */
-  unsigned char :8;					/* Byte 56 */
-  unsigned char :8;					/* Byte 57 */
-  unsigned short :16;					/* Bytes 58-59 */
-  unsigned short MaxCommands;				/* Bytes 60-61 */
-  unsigned short MaxScatterGatherEntries;		/* Bytes 62-63 */
-  unsigned short MaxDriveCommands;			/* Bytes 64-65 */
-  unsigned short MaxIODescriptors;			/* Bytes 66-67 */
-  unsigned short MaxCombinedSectors;			/* Bytes 68-69 */
-  unsigned char Latency;				/* Byte 70 */
-  unsigned char :8;					/* Byte 71 */
-  unsigned char SCSITimeout;				/* Byte 72 */
-  unsigned char :8;					/* Byte 73 */
-  unsigned short MinFreeLines;				/* Bytes 74-75 */
-  unsigned int :32;					/* Bytes 76-79 */
-  unsigned int :32;					/* Bytes 80-83 */
-  unsigned char RebuildRateConstant;			/* Byte 84 */
-  unsigned char :8;					/* Byte 85 */
-  unsigned char :8;					/* Byte 86 */
-  unsigned char :8;					/* Byte 87 */
-  unsigned int :32;					/* Bytes 88-91 */
-  unsigned int :32;					/* Bytes 92-95 */
-  unsigned short PhysicalDriveBlockSize;		/* Bytes 96-97 */
-  unsigned short LogicalDriveBlockSize;			/* Bytes 98-99 */
-  unsigned short MaxBlocksPerCommand;			/* Bytes 100-101 */
-  unsigned short BlockFactor;				/* Bytes 102-103 */
-  unsigned short CacheLineSize;				/* Bytes 104-105 */
-  struct {
-    enum {
-      DAC960_Narrow_8bit =			0x00,
-      DAC960_Wide_16bit =			0x01,
-      DAC960_Wide_32bit =			0x02
-    } __attribute__ ((packed)) BusWidth:2;		/* Byte 106 Bits 0-1 */
-    enum {
-      DAC960_Fast =				0x00,
-      DAC960_Ultra =				0x01,
-      DAC960_Ultra2 =				0x02
-    } __attribute__ ((packed)) BusSpeed:2;		/* Byte 106 Bits 2-3 */
-    boolean Differential:1;				/* Byte 106 Bit 4 */
-    unsigned char :3;					/* Byte 106 Bits 5-7 */
-  } SCSICapability;
-  unsigned char :8;					/* Byte 107 */
-  unsigned int :32;					/* Bytes 108-111 */
-  unsigned short FirmwareBuildNumber;			/* Bytes 112-113 */
-  enum {
-    DAC960_AEMI =				0x01,
-    DAC960_OEM1 =				0x02,
-    DAC960_OEM2 =				0x04,
-    DAC960_OEM3 =				0x08,
-    DAC960_Conner =				0x10,
-    DAC960_SAFTE =				0x20
-  } __attribute__ ((packed)) FaultManagementType;	/* Byte 114 */
-  unsigned char :8;					/* Byte 115 */
-  struct {
-    boolean Clustering:1;				/* Byte 116 Bit 0 */
-    boolean MylexOnlineRAIDExpansion:1;			/* Byte 116 Bit 1 */
-    unsigned int :30;					/* Bytes 116-119 */
-  } FirmwareFeatures;
-  unsigned int :32;					/* Bytes 120-123 */
-  unsigned int :32;					/* Bytes 124-127 */
-}
-DAC960_Enquiry2_T;
-
-
-/*
-  Define the Logical Drive State type.
-*/
-
-typedef enum
-{
-    DAC960_LogicalDrive_Online =		0x03,
-    DAC960_LogicalDrive_Critical =		0x04,
-    DAC960_LogicalDrive_Offline =		0xFF
-}
-__attribute__ ((packed))
-DAC960_LogicalDriveState_T;
-
-
-/*
-  Define the Get Logical Drive Information reply structure.
-*/
-
-typedef struct DAC960_LogicalDriveInformation
-{
-  unsigned int LogicalDriveSize;			/* Bytes 0-3 */
-  DAC960_LogicalDriveState_T LogicalDriveState;		/* Byte 4 */
-  unsigned char RAIDLevel:7;				/* Byte 5 Bits 0-6 */
-  boolean WriteBack:1;					/* Byte 5 Bit 7 */
-  unsigned int :16;					/* Bytes 6-7 */
-}
-DAC960_LogicalDriveInformation_T;
-
-
-/*
-  Define the Perform Event Log Operation Types.
-*/
-
-typedef enum
-{
-  DAC960_GetEventLogEntry =			0x00
-}
-__attribute__ ((packed))
-DAC960_PerformEventLogOpType_T;
-
-
-/*
-  Define the Get Event Log Entry reply structure.
-*/
-
-typedef struct DAC960_EventLogEntry
-{
-  unsigned char MessageType;				/* Byte 0 */
-  unsigned char MessageLength;				/* Byte 1 */
-  unsigned char TargetID:5;				/* Byte 2 Bits 0-4 */
-  unsigned char Channel:3;				/* Byte 2 Bits 5-7 */
-  unsigned char LogicalUnit:6;				/* Byte 3 Bits 0-5 */
-  unsigned char :2;					/* Byte 3 Bits 6-7 */
-  unsigned short SequenceNumber;			/* Bytes 4-5 */
-  unsigned char ErrorCode:7;				/* Byte 6 Bits 0-6 */
-  boolean Valid:1;					/* Byte 6 Bit 7 */
-  unsigned char SegmentNumber;				/* Byte 7 */
-  unsigned char SenseKey:4;				/* Byte 8 Bits 0-3 */
-  unsigned char :1;					/* Byte 8 Bit 4 */
-  boolean ILI:1;					/* Byte 8 Bit 5 */
-  boolean EOM:1;					/* Byte 8 Bit 6 */
-  boolean Filemark:1;					/* Byte 8 Bit 7 */
-  unsigned char Information[4];				/* Bytes 9-12 */
-  unsigned char AdditionalSenseLength;			/* Byte 13 */
-  unsigned char CommandSpecificInformation[4];		/* Bytes 14-17 */
-  unsigned char AdditionalSenseCode;			/* Byte 18 */
-  unsigned char AdditionalSenseCodeQualifier;		/* Byte 19 */
-  unsigned char Dummy[12];				/* Bytes 20-31 */
-}
-DAC960_EventLogEntry_T;
-
-#define DAC960_EventMessagesCount		13
-
-static char
-  *DAC960_EventMessages[DAC960_EventMessagesCount] =
-     { "killed because write recovery failed",
-       "killed because of SCSI bus reset failure",
-       "killed because of double check condition",
-       "killed because it was removed",
-       "killed because of gross error on SCSI chip",
-       "killed because of bad tag returned from drive",
-       "killed because of timeout on SCSI command",
-       "killed because of reset SCSI command issued from system",
-       "killed because busy or parity error count exceeded limit",
-       "killed because of 'kill drive' command from system",
-       "killed because of selection timeout",
-       "killed due to SCSI phase sequence error",
-       "killed due to unknown status" };
-
-
-/*
-  Define the Physical Device State type.
-*/
-
-typedef enum
-{
-    DAC960_Device_Dead =			0x00,
-    DAC960_Device_WriteOnly =			0x02,
-    DAC960_Device_Online =			0x03,
-    DAC960_Device_Standby =			0x10
-}
-__attribute__ ((packed))
-DAC960_PhysicalDeviceState_T;
-
-
-/*
-  Define the Get Device State reply structure.
-*/
-
-typedef struct DAC960_DeviceState
-{
-  boolean Present:1;					/* Byte 0 Bit 0 */
-  unsigned char :7;					/* Byte 0 Bits 1-7 */
-  enum {
-    DAC960_OtherType =				0x00,
-    DAC960_DiskType =				0x01,
-    DAC960_SequentialType =			0x02,
-    DAC960_CDROM_or_WORM_Type =			0x03
-    } __attribute__ ((packed)) DeviceType:2;		/* Byte 1 Bits 0-1 */
-  boolean :1;						/* Byte 1 Bit 2 */
-  boolean Fast20:1;					/* Byte 1 Bit 3 */
-  boolean Sync:1;					/* Byte 1 Bit 4 */
-  boolean Fast:1;					/* Byte 1 Bit 5 */
-  boolean Wide:1;					/* Byte 1 Bit 6 */
-  boolean TaggedQueuingSupported:1;			/* Byte 1 Bit 7 */
-  DAC960_PhysicalDeviceState_T DeviceState;		/* Byte 2 */
-  unsigned char :8;					/* Byte 3 */
-  unsigned char SynchronousMultiplier;			/* Byte 4 */
-  unsigned char SynchronousOffset:5;			/* Byte 5 Bits 0-4 */
-  unsigned char :3;					/* Byte 5 Bits 5-7 */
-  unsigned long DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
-}
-DAC960_DeviceState_T;
-
-
-/*
-  Define the Get Rebuild Progress reply structure.
-*/
-
-typedef struct DAC960_RebuildProgress
-{
-  unsigned int LogicalDriveNumber;			/* Bytes 0-3 */
-  unsigned int LogicalDriveSize;			/* Bytes 4-7 */
-  unsigned int RemainingBlocks;				/* Bytes 8-11 */
-}
-DAC960_RebuildProgress_T;
-
-
-/*
-  Define the Error Table Entry and Get Error Table reply structure.
-*/
-
-typedef struct DAC960_ErrorTableEntry
-{
-  unsigned char ParityErrorCount;			/* Byte 0 */
-  unsigned char SoftErrorCount;				/* Byte 1 */
-  unsigned char HardErrorCount;				/* Byte 2 */
-  unsigned char MiscErrorCount;				/* Byte 3 */
-}
-DAC960_ErrorTableEntry_T;
-
-
-/*
-  Define the Get Error Table reply structure.
-*/
-
-typedef struct DAC960_ErrorTable
-{
-  DAC960_ErrorTableEntry_T
-    ErrorTableEntries[DAC960_MaxChannels][DAC960_MaxTargets];
-}
-DAC960_ErrorTable_T;
-
-
-/*
-  Define the Config2 reply structure.
-*/
-
-typedef struct DAC960_Config2
-{
-  unsigned char :1;					/* Byte 0 Bit 0 */
-  boolean ActiveNegationEnabled:1;			/* Byte 0 Bit 1 */
-  unsigned char :5;					/* Byte 0 Bits 2-6 */
-  boolean NoRescanIfResetReceivedDuringScan:1;		/* Byte 0 Bit 7 */
-  boolean StorageWorksSupportEnabled:1;			/* Byte 1 Bit 0 */
-  boolean HewlettPackardSupportEnabled:1;		/* Byte 1 Bit 1 */
-  boolean NoDisconnectOnFirstCommand:1;			/* Byte 1 Bit 2 */
-  unsigned char :2;					/* Byte 1 Bits 3-4 */
-  boolean AEMI_ARM:1;					/* Byte 1 Bit 5 */
-  boolean AEMI_OFM:1;					/* Byte 1 Bit 6 */
-  unsigned char :1;					/* Byte 1 Bit 7 */
-  enum {
-    DAC960_OEMID_Mylex =			0x00,
-    DAC960_OEMID_IBM =				0x08,
-    DAC960_OEMID_HP =				0x0A,
-    DAC960_OEMID_DEC =				0x0C,
-    DAC960_OEMID_Siemens =			0x10,
-    DAC960_OEMID_Intel =			0x12
-  } __attribute__ ((packed)) OEMID;			/* Byte 2 */
-  unsigned char OEMModelNumber;				/* Byte 3 */
-  unsigned char PhysicalSector;				/* Byte 4 */
-  unsigned char LogicalSector;				/* Byte 5 */
-  unsigned char BlockFactor;				/* Byte 6 */
-  boolean ReadAheadEnabled:1;				/* Byte 7 Bit 0 */
-  boolean LowBIOSDelay:1;				/* Byte 7 Bit 1 */
-  unsigned char :2;					/* Byte 7 Bits 2-3 */
-  boolean ReassignRestrictedToOneSector:1;		/* Byte 7 Bit 4 */
-  unsigned char :1;					/* Byte 7 Bit 5 */
-  boolean ForceUnitAccessDuringWriteRecovery:1;		/* Byte 7 Bit 6 */
-  boolean EnableLeftSymmetricRAID5Algorithm:1;		/* Byte 7 Bit 7 */
-  unsigned char DefaultRebuildRate;			/* Byte 8 */
-  unsigned char :8;					/* Byte 9 */
-  unsigned char BlocksPerCacheLine;			/* Byte 10 */
-  unsigned char BlocksPerStripe;			/* Byte 11 */
-  struct {
-    enum {
-      DAC960_Async =				0x00,
-      DAC960_Sync_8MHz =			0x01,
-      DAC960_Sync_5MHz =			0x02,
-      DAC960_Sync_10or20MHz =			0x03	/* Bits 0-1 */
-    } __attribute__ ((packed)) Speed:2;
-    boolean Force8Bit:1;				/* Bit 2 */
-    boolean DisableFast20:1;				/* Bit 3 */
-    unsigned char :3;					/* Bits 4-6 */
-    boolean EnableTaggedQueuing:1;			/* Bit 7 */
-  } __attribute__ ((packed)) ChannelParameters[6];	/* Bytes 12-17 */
-  unsigned char SCSIInitiatorID;			/* Byte 18 */
-  unsigned char :8;					/* Byte 19 */
-  enum {
-    DAC960_StartupMode_ControllerSpinUp =	0x00,
-    DAC960_StartupMode_PowerOnSpinUp =		0x01
-  } __attribute__ ((packed)) StartupMode;		/* Byte 20 */
-  unsigned char SimultaneousDeviceSpinUpCount;		/* Byte 21 */
-  unsigned char SecondsDelayBetweenSpinUps;		/* Byte 22 */
-  unsigned char Reserved1[29];				/* Bytes 23-51 */
-  boolean BIOSDisabled:1;				/* Byte 52 Bit 0 */
-  boolean CDROMBootEnabled:1;				/* Byte 52 Bit 1 */
-  unsigned char :3;					/* Byte 52 Bits 2-4 */
-  enum {
-    DAC960_Geometry_128_32 =			0x00,
-    DAC960_Geometry_255_63 =			0x01,
-    DAC960_Geometry_Reserved1 =			0x02,
-    DAC960_Geometry_Reserved2 =			0x03
-  } __attribute__ ((packed)) DriveGeometry:2;		/* Byte 52 Bits 5-6 */
-  unsigned char :1;					/* Byte 52 Bit 7 */
-  unsigned char Reserved2[9];				/* Bytes 53-61 */
-  unsigned short Checksum;				/* Bytes 62-63 */
-}
-DAC960_Config2_T;
-
-
-/*
-  Define the Scatter/Gather List Type 1 32 Bit Address 32 Bit Byte Count
-  structure.
-*/
-
-typedef struct DAC960_ScatterGatherSegment
-{
-  DAC960_BusAddress_T SegmentDataPointer;		/* Bytes 0-3 */
-  DAC960_ByteCount_T SegmentByteCount;			/* Bytes 4-7 */
-}
-DAC960_ScatterGatherSegment_T;
-
-
-/*
-  Define the 13 Byte DAC960 Command Mailbox structure.  Bytes 13-15 are
-  not used.  The Command Mailbox structure is padded to 16 bytes for
-  efficient access.
-*/
-
-typedef union DAC960_CommandMailbox
-{
-  unsigned int Words[4];				/* Words 0-3 */
-  unsigned char Bytes[16];				/* Bytes 0-15 */
-  struct {
-    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
-    unsigned char Dummy[14];				/* Bytes 2-15 */
-  } __attribute__ ((packed)) Common;
-  struct {
-    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
-    unsigned char Dummy1[6];				/* Bytes 2-7 */
-    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
-    unsigned char Dummy2[4];				/* Bytes 12-15 */
-  } __attribute__ ((packed)) Type3;
-  struct {
-    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
-    unsigned char Dummy1[5];				/* Bytes 2-6 */
-    unsigned char LogicalDriveNumber:6;			/* Byte 7 Bits 0-6 */
-    boolean AutoRestore:1;				/* Byte 7 Bit 7 */
-    unsigned char Dummy2[8];				/* Bytes 8-15 */
-  } __attribute__ ((packed)) Type3C;
-  struct {
-    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
-    unsigned char Channel;				/* Byte 2 */
-    unsigned char TargetID;				/* Byte 3 */
-    DAC960_PhysicalDeviceState_T DeviceState:5;		/* Byte 4 Bits 0-4 */
-    unsigned char Modifier:3;				/* Byte 4 Bits 5-7 */
-    unsigned char Dummy1[3];				/* Bytes 5-7 */
-    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
-    unsigned char Dummy2[4];				/* Bytes 12-15 */
-  } __attribute__ ((packed)) Type3D;
-  struct {
-    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
-    DAC960_PerformEventLogOpType_T OperationType;	/* Byte 2 */
-    unsigned char OperationQualifier;			/* Byte 3 */
-    unsigned short SequenceNumber;			/* Bytes 4-5 */
-    unsigned char Dummy1[2];				/* Bytes 6-7 */
-    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
-    unsigned char Dummy2[4];				/* Bytes 12-15 */
-  } __attribute__ ((packed)) Type3E;
-  struct {
-    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
-    unsigned char Dummy1[2];				/* Bytes 2-3 */
-    unsigned char RebuildRateConstant;			/* Byte 4 */
-    unsigned char Dummy2[3];				/* Bytes 5-7 */
-    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
-    unsigned char Dummy3[4];				/* Bytes 12-15 */
-  } __attribute__ ((packed)) Type3R;
-  struct {
-    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
-    struct {
-      unsigned short TransferLength:11;			/* Bytes 2-3 */
-      unsigned char LogicalDriveNumber:5;		/* Byte 3 Bits 3-7 */
-    } __attribute__ ((packed)) LD;
-    unsigned int LogicalBlockAddress;			/* Bytes 4-7 */
-    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
-    unsigned char ScatterGatherCount:6;			/* Byte 12 Bits 0-5 */
-    enum {
-      DAC960_ScatterGather_32BitAddress_32BitByteCount =	0x0,
-      DAC960_ScatterGather_32BitAddress_16BitByteCount =	0x1,
-      DAC960_ScatterGather_32BitByteCount_32BitAddress =	0x2,
-      DAC960_ScatterGather_16BitByteCount_32BitAddress =	0x3
-    } __attribute__ ((packed)) ScatterGatherType:2;	/* Byte 12 Bits 6-7 */
-    unsigned char Dummy[3];				/* Bytes 13-15 */
-  } __attribute__ ((packed)) Type5;
-  struct {
-    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
-    unsigned char CommandOpcode2;			/* Byte 2 */
-    unsigned char :8;					/* Byte 3 */
-    DAC960_BusAddress_T CommandMailboxesBusAddress;	/* Bytes 4-7 */
-    DAC960_BusAddress_T StatusMailboxesBusAddress;	/* Bytes 8-11 */
-    unsigned char Dummy[4];				/* Bytes 12-15 */
-  } __attribute__ ((packed)) TypeX;
-}
-DAC960_CommandMailbox_T;
-
-
-/*
-  Define the DAC960 Controller Status Mailbox structure.
-*/
-
-typedef union DAC960_StatusMailbox
-{
-  unsigned int Word;					/* Bytes 0-3 */
-  struct {
-    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 0 */
-    unsigned char :7;					/* Byte 1 Bits 0-6 */
-    boolean Valid:1;					/* Byte 1 Bit 7 */
-    DAC960_CommandStatus_T CommandStatus;		/* Bytes 2-3 */
-  } Fields;
-}
-DAC960_StatusMailbox_T;
-
-
-/*
-  Define the DAC960 Driver Command Types.
-*/
-
-typedef enum
-{
-  DAC960_ReadCommand =				1,
-  DAC960_WriteCommand =				2,
-  DAC960_ReadRetryCommand =			3,
-  DAC960_WriteRetryCommand =			4,
-  DAC960_MonitoringCommand =			5,
-  DAC960_ImmediateCommand =			6
-}
-DAC960_CommandType_T;
-
-
-/*
-  Define the DAC960 Driver Command structure.
-*/
-
-typedef struct DAC960_Command
-{
-  DAC960_CommandType_T CommandType;
-  DAC960_CommandMailbox_T CommandMailbox;
-  DAC960_CommandStatus_T CommandStatus;
-  struct DAC960_Controller *Controller;
-  struct DAC960_Command *Next;
-  Semaphore_T *Semaphore;
-  unsigned int LogicalDriveNumber;
-  unsigned int BlockNumber;
-  unsigned int BlockCount;
-  unsigned int SegmentCount;
-  BufferHeader_T *BufferHeader;
-  DAC960_ScatterGatherSegment_T
-    ScatterGatherList[DAC960_MaxScatterGatherSegments];
-}
-DAC960_Command_T;
-
-
-/*
-  Define the DAC960 Driver Controller structure.
-*/
-
-typedef struct DAC960_Controller
-{
-  void *BaseAddress;
-  void *MemoryMappedAddress;
-  DAC960_ControllerType_T ControllerType;
-  DAC960_IO_Address_T IO_Address;
-  DAC960_PCI_Address_T PCI_Address;
-  unsigned char ControllerNumber;
-  unsigned char ControllerName[4];
-  unsigned char ModelName[12];
-  unsigned char FullModelName[18];
-  unsigned char FirmwareVersion[14];
-  unsigned char Bus;
-  unsigned char Device;
-  unsigned char Function;
-  unsigned char IRQ_Channel;
-  unsigned char Channels;
-  unsigned char MemorySize;
-  unsigned char LogicalDriveCount;
-  unsigned char GeometryTranslationHeads;
-  unsigned char GeometryTranslationSectors;
-  unsigned short ControllerQueueDepth;
-  unsigned short DriverQueueDepth;
-  unsigned short MaxBlocksPerCommand;
-  unsigned short MaxScatterGatherSegments;
-  unsigned short StripeSize;
-  unsigned short SegmentSize;
-  unsigned short NewEventLogSequenceNumber;
-  unsigned short OldEventLogSequenceNumber;
-  unsigned short InitialStatusLength;
-  unsigned short CurrentStatusLength;
-  unsigned short UserStatusLength;
-  unsigned short RebuildProgressLength;
-  unsigned int ControllerUsageCount;
-  unsigned int EnquiryIndex;
-  unsigned int LogicalDriveInformationIndex;
-  unsigned int ErrorTableIndex;
-  unsigned int DeviceStateIndex;
-  unsigned int DeviceStateChannel;
-  unsigned int DeviceStateTargetID;
-  unsigned long MonitoringTimerCount;
-  unsigned long SecondaryMonitoringTime;
-  unsigned long LastProgressReportTime;
-  boolean DualModeMemoryMailboxInterface;
-  boolean SAFTE_FaultManagementEnabled;
-  boolean ControllerInitialized;
-  boolean UserCommandActive;
-  boolean UserCommandDeferred;
-  boolean MonitoringCommandDeferred;
-  boolean NeedLogicalDriveInformation;
-  boolean NeedErrorTableInformation;
-  boolean NeedDeviceStateInformation;
-  boolean NeedRebuildProgress;
-  boolean NeedConsistencyCheckProgress;
-  boolean EphemeralProgressMessage;
-  Timer_T MonitoringTimer;
-  Semaphore_T *UserCommandSemaphore;
-  GenericDiskInfo_T GenericDiskInfo;
-  DAC960_Command_T *FreeCommands;
-  DAC960_Command_T *UserCommand;
-  DAC960_CommandMailbox_T *FirstCommandMailbox;
-  DAC960_CommandMailbox_T *LastCommandMailbox;
-  DAC960_CommandMailbox_T *NextCommandMailbox;
-  DAC960_CommandMailbox_T *PreviousCommandMailbox1;
-  DAC960_CommandMailbox_T *PreviousCommandMailbox2;
-  DAC960_StatusMailbox_T *FirstStatusMailbox;
-  DAC960_StatusMailbox_T *LastStatusMailbox;
-  DAC960_StatusMailbox_T *NextStatusMailbox;
-  PROC_DirectoryEntry_T ControllerProcEntry;
-  PROC_DirectoryEntry_T InitialStatusProcEntry;
-  PROC_DirectoryEntry_T CurrentStatusProcEntry;
-  PROC_DirectoryEntry_T UserCommandProcEntry;
-  WaitQueue_T *CommandWaitQueue;
-  DAC960_Enquiry_T Enquiry[2];
-  DAC960_ErrorTable_T ErrorTable[2];
-  DAC960_EventLogEntry_T EventLogEntry;
-  DAC960_RebuildProgress_T RebuildProgress;
-  DAC960_LogicalDriveInformation_T
-    LogicalDriveInformation[2][DAC960_MaxLogicalDrives];
-  DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives];
-  DAC960_DeviceState_T DeviceState[2][DAC960_MaxChannels][DAC960_MaxTargets];
-  DAC960_Command_T Commands[DAC960_MaxDriverQueueDepth];
-  DiskPartition_T DiskPartitions[DAC960_MinorCount];
-  int LogicalDriveUsageCount[DAC960_MaxLogicalDrives];
-  int PartitionSizes[DAC960_MinorCount];
-  int BlockSizes[DAC960_MinorCount];
-  int MaxSectorsPerRequest[DAC960_MinorCount];
-  int MaxSegmentsPerRequest[DAC960_MinorCount];
-  char InitialStatusBuffer[DAC960_StatusBufferSize];
-  char CurrentStatusBuffer[DAC960_StatusBufferSize];
-  char UserStatusBuffer[DAC960_UserMessageSize];
-  char RebuildProgressBuffer[DAC960_RebuildProgressSize];
-}
-DAC960_Controller_T;
-
-
-/*
-  DAC960_AcquireControllerLock acquires exclusive access to Controller.
-*/
-
-static inline
-void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
-				  ProcessorFlags_T *ProcessorFlags)
-{
-  save_flags(*ProcessorFlags);
-  cli();
-}
-
-
-/*
-  DAC960_ReleaseControllerLock releases exclusive access to Controller.
-*/
-
-static inline
-void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
-				  ProcessorFlags_T *ProcessorFlags)
-{
-  restore_flags(*ProcessorFlags);
-}
-
-
-/*
-  DAC960_AcquireControllerLockRF acquires exclusive access to Controller,
-  but is only called from the request function when interrupts are disabled.
-*/
-
-static inline
-void DAC960_AcquireControllerLockRF(DAC960_Controller_T *Controller,
-				    ProcessorFlags_T *ProcessorFlags)
-{
-}
-
-
-/*
-  DAC960_ReleaseControllerLockRF releases exclusive access to Controller,
-  but is only called from the request function when interrupts are disabled.
-*/
-
-static inline
-void DAC960_ReleaseControllerLockRF(DAC960_Controller_T *Controller,
-				    ProcessorFlags_T *ProcessorFlags)
-{
-}
-
-
-/*
-  DAC960_AcquireControllerLockIH acquires exclusive access to Controller,
-  but is only called from the interrupt handler when interrupts are disabled.
-*/
-
-static inline
-void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
-				    ProcessorFlags_T *ProcessorFlags)
-{
-}
-
-
-/*
-  DAC960_ReleaseControllerLockIH releases exclusive access to Controller,
-  but is only called from the interrupt handler when interrupts are disabled.
-*/
-
-static inline
-void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
-				    ProcessorFlags_T *ProcessorFlags)
-{
-}
-
-
-/*
-  Define inline functions to provide an abstraction for reading and writing the
-  DAC960 V5 Controller Interface Registers.
-*/
-
-static inline
-void DAC960_V5_HardwareMailboxNewCommand(void *ControllerBaseAddress)
-{
-  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V5_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
-{
-  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V5_GenerateInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.GenerateInterrupt = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V5_ControllerReset(void *ControllerBaseAddress)
-{
-  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.ControllerReset = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V5_MemoryMailboxNewCommand(void *ControllerBaseAddress)
-{
-  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-}
-
-static inline
-boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress)
-{
-  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All =
-    readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-  return InboundDoorBellRegister.Read.HardwareMailboxEmpty;
-}
-
-static inline
-void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All = 0;
-  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
-  writeb(OutboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V5_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All = 0;
-  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
-  writeb(OutboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V5_AcknowledgeInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All = 0;
-  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
-  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
-  writeb(OutboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
-}
-
-static inline
-boolean DAC960_V5_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
-{
-  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All =
-    readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
-  return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
-}
-
-static inline
-boolean DAC960_V5_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
-{
-  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All =
-    readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
-  return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
-}
-
-static inline
-void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress)
-{
-  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
-  InterruptMaskRegister.Bits.DisableInterrupts = false;
-  writeb(InterruptMaskRegister.All,
-	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
-}
-
-static inline
-void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress)
-{
-  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
-  InterruptMaskRegister.Bits.DisableInterrupts = true;
-  writeb(InterruptMaskRegister.All,
-	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
-}
-
-static inline
-boolean DAC960_V5_InterruptsEnabledP(void *ControllerBaseAddress)
-{
-  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All =
-    readb(ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
-  return !InterruptMaskRegister.Bits.DisableInterrupts;
-}
-
-static inline
-void DAC960_V5_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox,
-				   DAC960_CommandMailbox_T *CommandMailbox)
-{
-  NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
-  NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
-  NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
-  NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
-}
-
-static inline
-void DAC960_V5_WriteHardwareMailbox(void *ControllerBaseAddress,
-				    DAC960_CommandMailbox_T *CommandMailbox)
-{
-  writel(CommandMailbox->Words[0],
-	 ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
-  writel(CommandMailbox->Words[1],
-	 ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
-  writel(CommandMailbox->Words[2],
-	 ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
-  writeb(CommandMailbox->Bytes[12],
-	 ControllerBaseAddress + DAC960_V5_MailboxRegister12Offset);
-}
-
-static inline DAC960_CommandIdentifier_T
-DAC960_V5_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
-{
-  return readb(ControllerBaseAddress
-	       + DAC960_V5_StatusCommandIdentifierRegOffset);
-}
-
-static inline DAC960_CommandStatus_T
-DAC960_V5_ReadStatusRegister(void *ControllerBaseAddress)
-{
-  return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset);
-}
-
-static inline
-void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
-{
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0x743C485E,
-	 ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
-  writel((unsigned long) Controller->FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
-  writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
-  writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox,
-	 ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset);
-}
-
-static inline
-void DAC960_V5_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
-					void **MemoryMailboxAddress,
-					short *NextCommandMailboxIndex,
-					short *NextStatusMailboxIndex)
-{
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  if (readl(ControllerBaseAddress
-	    + DAC960_V5_CommandOpcodeRegisterOffset) != 0x743C485E)
-    return;
-  *MemoryMailboxAddress =
-    (void *) readl(ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
-  *NextCommandMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
-  *NextStatusMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset);
-}
-
-
-/*
-  Define inline functions to provide an abstraction for reading and writing the
-  DAC960 V4 Controller Interface Registers.
-*/
-
-static inline
-void DAC960_V4_HardwareMailboxNewCommand(void *ControllerBaseAddress)
-{
-  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
-  writel(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V4_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
-{
-  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
-  writel(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V4_GenerateInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.GenerateInterrupt = true;
-  writel(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V4_ControllerReset(void *ControllerBaseAddress)
-{
-  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.ControllerReset = true;
-  writel(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V4_MemoryMailboxNewCommand(void *ControllerBaseAddress)
-{
-  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
-  writel(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
-}
-
-static inline
-boolean DAC960_V4_HardwareMailboxFullP(void *ControllerBaseAddress)
-{
-  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All =
-    readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
-  return InboundDoorBellRegister.Read.HardwareMailboxFull;
-}
-
-static inline
-void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All = 0;
-  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
-  writel(OutboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V4_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All = 0;
-  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
-  writel(OutboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V4_AcknowledgeInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All = 0;
-  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
-  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
-  writel(OutboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
-}
-
-static inline
-boolean DAC960_V4_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
-{
-  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All =
-    readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
-  return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
-}
-
-static inline
-boolean DAC960_V4_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
-{
-  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All =
-    readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
-  return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
-}
-
-static inline
-void DAC960_V4_EnableInterrupts(void *ControllerBaseAddress)
-{
-  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
-  InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3;
-  InterruptMaskRegister.Bits.DisableInterrupts = false;
-  InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F;
-  writel(InterruptMaskRegister.All,
-	 ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
-}
-
-static inline
-void DAC960_V4_DisableInterrupts(void *ControllerBaseAddress)
-{
-  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
-  InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3;
-  InterruptMaskRegister.Bits.DisableInterrupts = true;
-  InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F;
-  writel(InterruptMaskRegister.All,
-	 ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
-}
-
-static inline
-boolean DAC960_V4_InterruptsEnabledP(void *ControllerBaseAddress)
-{
-  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All =
-    readl(ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
-  return !InterruptMaskRegister.Bits.DisableInterrupts;
-}
-
-static inline
-void DAC960_V4_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox,
-				   DAC960_CommandMailbox_T *CommandMailbox)
-{
-  NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
-  NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
-  NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
-  NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
-}
-
-static inline
-void DAC960_V4_WriteHardwareMailbox(void *ControllerBaseAddress,
-				    DAC960_CommandMailbox_T *CommandMailbox)
-{
-  writel(CommandMailbox->Words[0],
-	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
-  writel(CommandMailbox->Words[1],
-	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
-  writel(CommandMailbox->Words[2],
-	 ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
-  writeb(CommandMailbox->Bytes[12],
-	 ControllerBaseAddress + DAC960_V4_MailboxRegister12Offset);
-}
-
-static inline DAC960_CommandIdentifier_T
-DAC960_V4_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
-{
-  return readb(ControllerBaseAddress
-	       + DAC960_V4_StatusCommandIdentifierRegOffset);
-}
-
-static inline DAC960_CommandStatus_T
-DAC960_V4_ReadStatusRegister(void *ControllerBaseAddress)
-{
-  return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset);
-}
-
-static inline
-void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
-{
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0xAABBFFFF,
-	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
-  writel((unsigned long) Controller->FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
-  writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
-  writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox,
-	 ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset);
-}
-
-static inline
-void DAC960_V4_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
-					void **MemoryMailboxAddress,
-					short *NextCommandMailboxIndex,
-					short *NextStatusMailboxIndex)
-{
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  if (readl(ControllerBaseAddress
-	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF)
-    return;
-  *MemoryMailboxAddress =
-    (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
-  *NextCommandMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
-  *NextStatusMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset);
-}
-
-
-/*
-  Define inline functions to provide an abstraction for reading and writing the
-  DAC960 V3 Controller Interface Registers.
-*/
-
-static inline
-void DAC960_V3_NewCommand(void *ControllerBaseAddress)
-{
-  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.NewCommand = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V3_AcknowledgeStatus(void *ControllerBaseAddress)
-{
-  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.AcknowledgeStatus = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V3_GenerateInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.GenerateInterrupt = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
-}
-
-static inline
-void DAC960_V3_ControllerReset(void *ControllerBaseAddress)
-{
-  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All = 0;
-  InboundDoorBellRegister.Write.ControllerReset = true;
-  writeb(InboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
-}
-
-static inline
-boolean DAC960_V3_MailboxFullP(void *ControllerBaseAddress)
-{
-  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
-  InboundDoorBellRegister.All =
-    readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
-  return InboundDoorBellRegister.Read.MailboxFull;
-}
-
-static inline
-void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress)
-{
-  DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All = 0;
-  OutboundDoorBellRegister.Write.AcknowledgeInterrupt = true;
-  writeb(OutboundDoorBellRegister.All,
-	 ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset);
-}
-
-static inline
-boolean DAC960_V3_StatusAvailableP(void *ControllerBaseAddress)
-{
-  DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
-  OutboundDoorBellRegister.All =
-    readb(ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset);
-  return OutboundDoorBellRegister.Read.StatusAvailable;
-}
-
-static inline
-void DAC960_V3_EnableInterrupts(void *ControllerBaseAddress)
-{
-  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
-  InterruptEnableRegister.All = 0;
-  InterruptEnableRegister.Bits.EnableInterrupts = true;
-  writeb(InterruptEnableRegister.All,
-	 ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
-}
-
-static inline
-void DAC960_V3_DisableInterrupts(void *ControllerBaseAddress)
-{
-  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
-  InterruptEnableRegister.All = 0;
-  InterruptEnableRegister.Bits.EnableInterrupts = false;
-  writeb(InterruptEnableRegister.All,
-	 ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
-}
-
-static inline
-boolean DAC960_V3_InterruptsEnabledP(void *ControllerBaseAddress)
-{
-  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
-  InterruptEnableRegister.All =
-    readb(ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
-  return InterruptEnableRegister.Bits.EnableInterrupts;
-}
-
-static inline
-void DAC960_V3_WriteCommandMailbox(void *ControllerBaseAddress,
-				   DAC960_CommandMailbox_T *CommandMailbox)
-{
-  writel(CommandMailbox->Words[0],
-	 ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset);
-  writel(CommandMailbox->Words[1],
-	 ControllerBaseAddress + DAC960_V3_MailboxRegister4Offset);
-  writel(CommandMailbox->Words[2],
-	 ControllerBaseAddress + DAC960_V3_MailboxRegister8Offset);
-  writeb(CommandMailbox->Bytes[12],
-	 ControllerBaseAddress + DAC960_V3_MailboxRegister12Offset);
-}
-
-static inline DAC960_CommandIdentifier_T
-DAC960_V3_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
-{
-  return readb(ControllerBaseAddress
-	       + DAC960_V3_StatusCommandIdentifierRegOffset);
-}
-
-static inline DAC960_CommandStatus_T
-DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress)
-{
-  return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset);
-}
-
-
-/*
-  Virtual_to_Bus and Bus_to_Virtual map between Kernel Virtual Addresses
-  and PCI Bus Addresses.
-*/
-
-static inline DAC960_BusAddress_T Virtual_to_Bus(void *VirtualAddress)
-{
-  return (DAC960_BusAddress_T) virt_to_bus(VirtualAddress);
-}
-
-static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress)
-{
-  return (void *) bus_to_virt(BusAddress);
-}
-
-
-/*
-  Define compatibility macros between Linux 2.0 and Linux 2.1.
-*/
-
-#if LINUX_VERSION_CODE < 0x20100
-
-#define MODULE_PARM(Variable, Type)
-#define ioremap_nocache(Offset, Size)	vremap(Offset, Size)
-#define iounmap(Address)		vfree(Address)
-
-#endif
-
-
-/*
-  Define prototypes for the forward referenced DAC960 Driver Internal Functions.
-*/
-
-static void DAC960_FinalizeController(DAC960_Controller_T *);
-static void DAC960_RequestFunction0(void);
-static void DAC960_RequestFunction1(void);
-static void DAC960_RequestFunction2(void);
-static void DAC960_RequestFunction3(void);
-static void DAC960_RequestFunction4(void);
-static void DAC960_RequestFunction5(void);
-static void DAC960_RequestFunction6(void);
-static void DAC960_RequestFunction7(void);
-static void DAC960_InterruptHandler(int, void *, Registers_T *);
-static void DAC960_QueueMonitoringCommand(DAC960_Command_T *);
-static void DAC960_MonitoringTimerFunction(unsigned long);
-static int DAC960_Open(Inode_T *, File_T *);
-static void DAC960_Release(Inode_T *, File_T *);
-static int DAC960_Ioctl(Inode_T *, File_T *, unsigned int, unsigned long);
-static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *);
-static void DAC960_Message(DAC960_MessageLevel_T, char *,
-			   DAC960_Controller_T *, ...);
-static void DAC960_CreateProcEntries(void);
-static void DAC960_DestroyProcEntries(void);
-
-
-#endif /* DAC960_DriverVersion */
diff -urN linux-2.0.37-pre10/MAINTAINERS linux-2.0.37-pre11/MAINTAINERS
--- linux-2.0.37-pre10/MAINTAINERS	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/MAINTAINERS	2003-08-15 15:04:47.000000000 -0700
@@ -123,8 +123,8 @@
 S:      Maintained
 
 APM DRIVER
-P:	Rik Faith & Stephen Rothwell
-M:	faith@cs.unc.edu, Stephen.Rothwell@canb.auug.org.au
+P:	Stephen Rothwell
+M:	Stephen.Rothwell@canb.auug.org.au
 L:	linux-laptop@vger.rutgers.edu
 S:	Maintained
 
diff -urN linux-2.0.37-pre10/mm/mmap.c linux-2.0.37-pre11/mm/mmap.c
--- linux-2.0.37-pre10/mm/mmap.c	1998-11-15 10:33:20.000000000 -0800
+++ linux-2.0.37-pre11/mm/mmap.c	2003-08-15 15:04:47.000000000 -0700
@@ -69,20 +69,21 @@
 	unsigned long newbrk, oldbrk;
 	struct mm_struct *mm = current->mm;
 
+	down(&mm->mmap_sem);
+
 	if (brk < mm->end_code)
-		return mm->brk;
+		goto out;
 	newbrk = PAGE_ALIGN(brk);
 	oldbrk = PAGE_ALIGN(mm->brk);
 	if (oldbrk == newbrk)
-		return mm->brk = brk;
+		goto set_brk;
 
 	/*
 	 * Always allow shrinking brk
 	 */
 	if (brk <= mm->brk) {
-		mm->brk = brk;
 		do_munmap(newbrk, oldbrk-newbrk);
-		return brk;
+		goto set_brk;
 	}
 	/*
 	 * Check against rlimit and stack..
@@ -91,19 +92,19 @@
 	if (rlim >= RLIM_INFINITY)
 		rlim = ~0;
 	if (brk - mm->end_code > rlim)
-		return mm->brk;
+		goto out;
 
 	/*
 	 * Check against existing mmap mappings.
 	 */
 	if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
-		return mm->brk;
+		goto out;
 
 	/*
 	 * Check if we have enough memory..
 	 */
 	if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT))
-		return mm->brk;
+		goto out;
 
 	/*
 	 * Ok, looks good - let it rip.
@@ -111,8 +112,12 @@
 	if(do_mmap(NULL, oldbrk, newbrk-oldbrk,
 		PROT_READ|PROT_WRITE|PROT_EXEC,
 		   MAP_FIXED|MAP_PRIVATE, 0) != oldbrk)
-		return mm->brk;
-	return mm->brk = brk;
+		goto out;
+set_brk:
+	mm->brk = brk;
+out:
+	up(&mm->mmap_sem);
+	return mm->brk;
 }
 
 /*
@@ -784,7 +789,12 @@
 
 asmlinkage int sys_munmap(unsigned long addr, size_t len)
 {
-	return do_munmap(addr, len);
+	int ret;
+
+	down(&current->mm->mmap_sem);
+	ret = do_munmap(addr, len);
+	up(&current->mm->mmap_sem);
+	return ret;
 }
 
 /*
@@ -796,7 +806,7 @@
 int do_munmap(unsigned long addr, size_t len)
 {
 	struct vm_area_struct *mpnt, *prev, *next, **npp, *free;
-
+	
 	if ((addr & ~PAGE_MASK) || addr > MAX_USER_ADDR || len > MAX_USER_ADDR-addr)
 		return -EINVAL;
 
@@ -854,7 +864,6 @@
 	} while (free);
 
 	/* we could zap the page tables here too.. */
-
 	return 0;
 }
 
@@ -980,10 +989,9 @@
 {
 	struct vm_area_struct *prev, *mpnt, *next;
 
-	down(&mm->mmap_sem);
 	mpnt = find_vma(mm, start_addr);
 	if (!mpnt)
-		goto no_vma;
+		return;
 
 	avl_neighbours(mpnt, mm->mmap_avl, &prev, &next);
 	/* we have  prev->vm_next == mpnt && mpnt->vm_next = next */
@@ -1043,6 +1051,4 @@
 		kfree_s(mpnt, sizeof(*mpnt));
 		mpnt = prev;
 	}
-no_vma:
-	up(&mm->mmap_sem);
 }
diff -urN linux-2.0.37-pre10/net/netlink.c linux-2.0.37-pre11/net/netlink.c
--- linux-2.0.37-pre10/net/netlink.c	1997-10-15 14:47:26.000000000 -0700
+++ linux-2.0.37-pre11/net/netlink.c	2003-08-15 15:04:47.000000000 -0700
@@ -198,6 +198,7 @@
 	if(active_map&(1<<unit))
 		return -EBUSY;
 	active_map|=(1<<unit);
+	open_map&=~(1<<unit);	
 	netlink_handler[unit]=function;
 	return 0;
 }
@@ -206,6 +207,7 @@
 {
 	active_map&=~(1<<unit);
 	netlink_handler[unit]=netlink_err;
+	open_map&=~(1<<unit);	
 }
 
 int netlink_post(int unit, struct sk_buff *skb)
diff -urN linux-2.0.37-pre10/net/netsyms.c linux-2.0.37-pre11/net/netsyms.c
--- linux-2.0.37-pre10/net/netsyms.c	2003-08-15 15:04:47.000000000 -0700
+++ linux-2.0.37-pre11/net/netsyms.c	2003-08-15 15:04:47.000000000 -0700
@@ -111,6 +111,8 @@
 	X(ip_id_count),
 	X(ip_send_check),
 	X(ip_forward),
+	X(ip_queue_xmit),
+	X(ip_fragment),
 	X(sysctl_ip_forward),
 
 #if	defined(CONFIG_ULTRA)	||	defined(CONFIG_WD80x3)		|| \
