]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.81 2.1.81
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:14:34 +0000 (15:14 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:14:34 +0000 (15:14 -0500)
93 files changed:
Documentation/00-INDEX
Documentation/binfmt_misc.txt
Documentation/java.txt
Documentation/smart-config.txt [new file with mode: 0644]
Makefile
arch/alpha/kernel/irq.c
arch/alpha/lib/csum_partial_copy.c
arch/i386/kernel/entry.S
arch/i386/kernel/i386_ksyms.c
arch/i386/kernel/irq.c
arch/i386/kernel/irq.h
arch/i386/lib/usercopy.c
drivers/block/floppy.c
drivers/block/genhd.c
drivers/block/md.c
drivers/block/ps2esdi.c
drivers/cdrom/cdu31a.c
drivers/char/bttv.c
drivers/char/busmouse.c
drivers/char/bw-qcam.c
drivers/char/c-qcam.c
drivers/char/ftape/lowlevel/fdc-io.c
drivers/char/ftape/lowlevel/ftape-ctl.c
drivers/char/ftape/lowlevel/ftape-init.h
drivers/char/ftape/lowlevel/ftape-rw.c
drivers/char/ftape/lowlevel/ftape-tracing.h
drivers/char/ftape/zftape/zftape-init.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/pms.c
drivers/char/tpqic02.c
drivers/char/videodev.c
drivers/isdn/hisax/avm_a1.c
drivers/isdn/hisax/elsa.c
drivers/isdn/hisax/ix1_micro.c
drivers/isdn/hisax/teles0.c
drivers/isdn/hisax/teles3.c
drivers/misc/parport_init.c
drivers/net/3c59x.c
drivers/net/dgrs.c
drivers/net/lance.c
drivers/net/sdla_fr.c
drivers/scsi/53c7,8xx.c
drivers/scsi/Makefile
drivers/scsi/NCR5380.c
drivers/scsi/NCR53c406a.c
drivers/scsi/advansys.c
drivers/scsi/advansys.h
drivers/scsi/pci2000.h
drivers/scsi/pci2220i.h
drivers/scsi/pluto.c [new file with mode: 0644]
drivers/scsi/pluto.h [new file with mode: 0644]
drivers/scsi/psi240i.h
drivers/scsi/scsi.c
drivers/scsi/t128.c
drivers/sound/audio.c
drivers/sound/dev_table.c
drivers/sound/gus_card.c
drivers/sound/gus_midi.c
drivers/sound/gus_vol.c
drivers/sound/gus_wave.c
drivers/sound/soundcard.c
fs/dcache.c
fs/fat/buffer.c
fs/fat/cache.c
fs/fat/dir.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/misc.c
fs/fat/mmap.c
fs/msdos/namei.c
fs/nfsd/export.c
fs/nfsd/nfsfh.c
fs/nfsd/nfssvc.c
fs/ntfs/fs.c
fs/open.c
fs/proc/root.c
fs/vfat/namei.c
include/asm-i386/hardirq.h
include/asm-i386/softirq.h
include/asm-i386/uaccess.h
include/asm-i386/unistd.h
include/asm-mips/ioctls.h
include/linux/blk.h
include/linux/msdos_fs_i.h
include/linux/nfsd/nfsfh.h
include/linux/signal.h
include/linux/tty.h
include/linux/videodev.h
kernel/acct.c
kernel/printk.c
kernel/softirq.c
scripts/Menuconfig

index d4727eae0231fa186ff7144b4e2245cdad442228..7408fb62cf2a4f65681c6ad245753fa495cdfa43 100644 (file)
@@ -80,6 +80,8 @@ rtc.txt
        - notes on how to use the Real Time Clock (aka CMOS clock) driver.
 scsi.txt
        - short blurb on using SCSI support as a module.
+smart-config.txt
+       - description of the Smart Config makefile feature.
 smp.tex
        - TeX document describing implementation of Multiprocessor Linux
 svga.txt
index 0adcf7185dfb6de4a7dc3684b3ea5931ea712bc5..6a8b87aff9e1c3f7885329daf7902b1d687a21d0 100644 (file)
@@ -54,10 +54,10 @@ A few examples (assumed you are in /proc/sys/fs/binfmt_misc):
 - enable support for packed DOS applications (pre-configured dosemu hdimages):
   echo ':DEXE:M::\x0eDEX::/usr/bin/dosexec:' > register
 
-- enable support for DOS/Windows executables (using mzloader and dosemu/wine):
-  echo ':DOSWin:M::MZ::/usr/sbin/mzloader:' > register
-  echo ':DOScom:E::com::/usr/sbin/mzloader:' > register
-  echo ':DOSexe:E::exe::/usr/sbin/mzloader:' > register
+- enable support for Windows executables using wine:
+  echo ':DOSWin:M::MZ::/usr/local/bin/wine:' > register
+
+For java support see Documentation/java.txt
 
 
 You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable)
@@ -68,73 +68,12 @@ You can remove one entry or all entries by echoing -1 to /proc/.../the_name
 or /proc/sys/fs/binfmt_misc/status.
 
 
-Emulating binfmt_java:
-======================
-
-To emulate binfmt_java the following register-strings could be used: 
-for compiled Java programs use
-  ':Java:M::\xca\xfe\xba\xbe::/usr/local/java/bin/javawrapper:'
-for simple applet support use
-  ':Applet:E::html::/usr/local/java/bin/appletviewer:'
-for more selective applet support (like binfmt_java) use
-  ':Applet:M::<!--applet::/usr/local/java/bin/appletviewer:'
-
-Note, that for the more selective applet support you have to modify
-existing html-files to contain <!--applet--> in the first line to
-let this work!
-
-For the compiled Java programs you need a wrapper script like the
-following (this is because Java is broken in case of the filename
-handling):
-
-====================== Cut here ===================
-#!/bin/bash
-# /usr/local/java/bin/javawrapper - the wrapper for binfmt_misc/java
-CLASS=$1
-
-# if classname is a link, we follow it (this could be done easier - how?)
-if [ -L "$1" ] ; then
-       CLASS=`ls --color=no -l $1 | tr -s '\t ' '  ' | cut -d ' ' -f 11` 
-fi
-CLASSN=`basename $CLASS .class`
-CLASSP=`dirname $CLASS`
-
-FOO=$PATH
-PATH=$CLASSPATH
-if [ -z "`type -p -a $CLASSN.class`" ] ; then
-       # class is not in CLASSPATH
-       if [ -e "$CLASSP/$CLASSN.class" ] ; then
-               # append dir of class to CLASSPATH
-               if [ -z "${CLASSPATH}" ] ; then
-                       export CLASSPATH=$CLASSP
-               else
-                       export CLASSPATH=$CLASSP:$CLASSPATH
-               fi
-       else
-               # uh! now we would have to create a symbolic link - really
-               # ugly, i.e. print a message that one has to change the setup
-               echo "Hey! This is not a good setup to run $1 !"
-               exit 1
-       fi
-fi
-PATH=$FOO
-
-shift
-/usr/local/java/bin/java $CLASSN $@
-====================== Cut here ===================
-
-To add a Java program to your path best put a symbolic link to the main
-.class file into /usr/bin (or another place you like) omitting the .class
-extension. The directory containing the original .class file will be
-added to your CLASSPATH during execution.
-
-
-
 HINTS:
 ======
 
 If you want to pass special arguments to your interpreter, you can
-write a wrapper script for it.
+write a wrapper script for it. See Documentation/java.txt for an
+example.
 
 Your interpreter should NOT look in the PATH for the filename; the
 kernel passes it the full filename to use.  Using the PATH can cause
index f5205b1a477cbe7bb07aa48da562b30eb6a4f6e6..a5439f730ec28f799348b85b01c9b5d256ba1d65 100644 (file)
@@ -4,45 +4,92 @@
 Linux beats them ALL! While all other OS's are TALKING about direct
 support of Java Binaries in the OS, Linux is doing it!
 
-You execute Java classes as you would any other executable, after a few
-small details:
-
-       1) You MUST FIRST install the Java Developers Kit for Linux.
-          The Java on Linux HOWTO gives the details on getting and
-          installing this. This HOWTO can be found at:
-
-               ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Java-HOWTO
-
-          If you install the JDK in a location other than /usr/bin/java,
-          then you will need to tell the kernel where you put the Java
-          interpreter.  
-           There are two ways to do this.
-           One, edit fs/binfmt_java.c file and make the needed change to 
-          the _PATH_JAVA definition at the top of that file.  
-           Two, as root, issue the command:
-        echo "/path/to/java/interpreter" > /proc/sys/kernel/java-interpreter
-          (Currently, this does not work if you're using a module for
-           Java support.)
-
-       2) You must chmod the '*.class' files you wish to execute with
-          the execute bit. This is not normally (till now) done with
-          '.class' files.
-
-       3) You must optionally export a CLASSPATH environment variable,
-          if you plan to use Java applications installed outside of
-          /usr/local/java/classes/*.
-
-       4) Either compile your kernel with Java support builtin, or
-          as a loadable module. If a module, load it with insmod or
-          kerneld.
-
-       5) A caveat.  When executing a java file, the java interpreter is
-          invoked only with the class name, not with the complete file path.
-          Therefore it is possible that the file the shell finds with PATH
-          is not the same file the java interpreter finds with CLASSPATH.
-          The recommended solution is to make symbolic links from a directory
-          in PATH to the actual class file in CLASSPATH, e.g.,
-          /usr/local/bin/myapp -> /usr/local/java/classes/myapp.class.
+You can execute Java applications and Java Applets just like any
+other program after you have done the following:
+
+1) You MUST FIRST install the Java Developers Kit for Linux.
+   The Java on Linux HOWTO gives the details on getting and
+   installing this. This HOWTO can be found at:
+
+       ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Java-HOWTO
+
+   You should also set up a reasonable CLASSPATH environment
+   variable to use Java applications that make use of any
+   nonstandard classes (not included in the same directory
+   as the application itself).
+
+2) You have to compile BINFMT_MISC either as module or into
+   the kernel (CONFIG_BINFMT_MISC) and set it up properly.
+   If you choose to compile it as a module, you will have
+   to insert it manually with modprobe/insmod, as kerneld
+   can not easy be supported with binfmt_misc. 
+   Read the file 'binfmt_misc.txt' in this directory to know
+   more about the configuration process.
+
+3) Add the following configuration items to binfmt_misc
+   (you should really have read binfmt_misc.txt now):
+   support for Java applications:
+     ':Java:M::\xca\xfe\xba\xbe::/usr/local/java/bin/javawrapper:'
+   support for Java Applets:
+     ':Applet:E::html::/usr/local/java/bin/appletviewer:'
+   or the following, if you want to be more selective:
+     ':Applet:M::<!--applet::/usr/local/java/bin/appletviewer:'
+
+   Of cause you have to fix the path names, if you installed the JDK
+   at another place than /usr/local/java.
+
+   Note, that for the more selective applet support you have to modify
+   existing html-files to contain <!--applet--> in the first line
+   ('<' has to be the first character!) to let this work!
+
+   For the compiled Java programs you need a wrapper script like the
+   following (this is because Java is broken in case of the filename
+   handling), again fix the path names, both in the script and in the
+   above given configuration string:
+
+====================== Cut here ===================
+#!/bin/bash
+# /usr/local/java/bin/javawrapper - the wrapper for binfmt_misc/java
+CLASS=$1
+
+# if classname is a link, we follow it (this could be done easier - how?)
+if [ -L "$1" ] ; then
+        CLASS=`ls --color=no -l $1 | tr -s '\t ' '  ' | cut -d ' ' -f 11`
+fi
+CLASSN=`basename $CLASS .class`
+CLASSP=`dirname $CLASS`
+
+FOO=$PATH
+PATH=$CLASSPATH
+if [ -z "`type -p -a $CLASSN.class`" ] ; then
+        # class is not in CLASSPATH
+        if [ -e "$CLASSP/$CLASSN.class" ] ; then
+                # append dir of class to CLASSPATH
+                if [ -z "${CLASSPATH}" ] ; then
+                        export CLASSPATH=$CLASSP
+                else
+                        export CLASSPATH=$CLASSP:$CLASSPATH
+                fi
+        else
+                # uh! now we would have to create a symbolic link - really
+                # ugly, i.e. print a message that one has to change the setup
+                echo "Hey! This is not a good setup to run $1 !"
+                exit 1
+        fi
+fi
+PATH=$FOO
+
+shift
+/usr/local/java/bin/java $CLASSN "$@"
+====================== Cut here ===================
+
+
+Now simply chmod +x the .class and/or .html files you want to execute.
+To add a Java program to your path best put a symbolic link to the main
+.class file into /usr/bin (or another place you like) omitting the .class
+extension. The directory containing the original .class file will be
+added to your CLASSPATH during execution.
+
 
 To test your new setup, enter in the following simple Java app, and name
 it "HelloWorld.java":
@@ -53,59 +100,20 @@ it "HelloWorld.java":
                }
        }
 
-
 Now compile the application with:
-
-       /usr/local/java/bin/javac HelloWorld.java
+       javac HelloWorld.java
 
 Set the executable permissions of the binary file, with:
-
        chmod 755 HelloWorld.class
 
 And then execute it:
-
        ./HelloWorld.class
 
 
-Yes, it's JUST THAT EASY! ;-)
-
------------------------------------------------------------------
-
-Nope, I didn't forget about Java Applets! ;-)
-
-While this may not be the best way to do this, it works!
-
-Take any html file used with the Java appletviewer (like the
-demo/Blink/example1.html file), and:
-
-       1) Insert a new first line of:
-
-               <!--applet-->
-
-          Make sure the '<' is the first character in the file. This
-          will be treated as a valid HTML comment outside of this
-          Java Applet support, so the modified file can still be used
-          with all known browsers.
-
-       2) If you install the applet viewer in a location other than
-          /usr/bin/appletviewer, then you will need to tell the
-          kernel where you put the Java appletviewer.  
-           There are two ways to do this.
-           One, edit fs/binfmt_java.c file and make the needed change to 
-          the _PATH_APPLET definition at the top of that file.  
-           Two, as root, issue the command:
-       echo "/path/to/java/appletviewer" > /proc/sys/kernel/java-appletviewer
-          (Currently, this does not work if you're using a module for
-           Java support.)
-
-       3) You must chmod the '*.html' files you wish to execute with
-          the execute bit. This is not normally (till now) done with
-          '.html' files.
-
-       4) And then execute it.
-
+To execute Java Applets, simple chmod the *.html files to include
+the execution bit, then just do
+       ./Applet.html
 
-Brian A. Lantz
-brian@lantz.com
-(/proc/sys/kernel/java-* support by Mike Shaver (shaver@ingenia.com))
 
+originally by Brian A. Lantz, brian@lantz.com
+heavily edited for binfmt_misc by Richard Günther.
diff --git a/Documentation/smart-config.txt b/Documentation/smart-config.txt
new file mode 100644 (file)
index 0000000..eda5c3d
--- /dev/null
@@ -0,0 +1,103 @@
+Smart CONFIG_* Dependencies
+Fri 2 Dec 1997
+
+Michael Chastain   <mec@shout.net>
+Werner Almesberger <almesber@lrc.di.epfl.ch>
+Martin von Loewis  <martin@mira.isdn.cs.tu-berlin.de>
+
+Here is the problem:
+
+    Suppose that drivers/net/foo.c has the following lines:
+
+       #include <linux/config.h>
+
+       ...
+
+       #ifdef CONFIG_FOO_AUTOFROB
+           /* Code for auto-frobbing */
+       #else
+           /* Manual frobbing only */
+       #endif
+
+       ...
+
+       #ifdef CONFIG_FOO_MODEL_TWO
+           /* Code for model two */
+       #endif
+
+    Now suppose the user (the person building kernels) reconfigures the
+    kernel to change some unrelated setting.  This will regenerate the
+    file include/linux/autoconf.h, which will cause include/linux/config.h
+    to be out of date, which will cause drivers/net/foo.c to be recompiled.
+
+    Most kernel sources, perhaps 80% of them, have at least one CONFIG_*
+    dependency somewhere.  So changing _any_ CONFIG_* setting requires
+    almost _all_ of the kernel to be recompiled.
+
+Here is the solution:
+
+    We've made the dependency generator, mkdep.c, smarter.  Instead of
+    generating this dependency:
+
+       drivers/net/foo.c: include/linux/config.h
+
+    It now generates these dependencies:
+
+       drivers/net/foo.c: \
+           include/config/foo_autofrob.h \
+           include/config/foo_model_two.h
+
+    So drivers/net/foo.c depends only on the CONFIG_* lines that
+    it actually uses.
+
+    A new program, split-include.c, runs at the end of make config (also
+    make oldconfig, make menuconfig, and make xconfig).  split-include
+    reads include/linux/autoconf.h and updates the include/linux/*.h
+    directory, writing one file per option.  It updates only the files
+    that changed.
+
+    mkdep.c also generates much better warning messages for missing
+    or unneeded <linux/config.h> lines.  In fact, you can get these
+    messages without generating dependencies with the new top-level
+    target 'make checkconfig'.
+
+Flag Dependencies
+
+    Martin Von Loewis contributed another feature to this patch:
+    'flag dependencies'.  The idea is that a .o file depends on
+    the compilation flags used to build it.  The file foo.o has
+    its flags stored in .flags.foo.o.
+
+    Suppose the user changes the foo driver from resident to
+    modular, 'make' will notice that the foo.o was not compiled
+    with -DMODULE and will recompile foo.c.
+
+    Flag dependencies also work with per-source-file flags such
+    as those in drivers/net/CONFIG.
+
+    All .a and .o files made from C source or with 'ld' or 'ar'
+    have flag dependencies.  .S files do not have flag dependencies.
+
+Per-source-file Flags
+
+    You can specify compilation flags for individual source files
+    like this:
+
+       CFLAGS_foo.o = -DSPECIAL_FOO_DEFINE
+
+    This helps clean up drivers/net/Makefile, drivers/scsi/Makefile,
+    and several other Makefiles.
+
+Credit
+
+    Werner Almesberger had the original idea and wrote the first
+    version of this patch.
+    
+    Michael Chastain picked it up and continued development.  He is
+    now the principal author and maintainer.  Report bugs to him,
+    or to all three people together.
+
+    Martin von Loewis wrote flag dependencies, with some modifications
+    by Michael Chastain.
+
+    Thanks to all of the beta testers.
index 8ab1b6a9b256fd0fbe151d2694f6963bf83b0496..cbd64778738ce9674507d69daeae49904940868c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 80
+SUBLEVEL = 81
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
@@ -346,7 +346,6 @@ clean:      archclean
        rm -f core `find . -name '*.[oas]' ! -regex '.*lxdialog/.*' -print`
        rm -f core `find . -type f -name 'core' -print`
        rm -f core `find . -name '.*.flags' -print`
-       rm -f core `find . -size 0`
        rm -f vmlinux System.map
        rm -f .tmp*
        rm -f drivers/char/consolemap_deftbl.c drivers/char/conmakehash
@@ -371,6 +370,7 @@ mrproper: clean
        rm -f include/asm
        rm -rf include/config
        rm -f .depend `find . -name .depend -print`
+       rm -f core `find . -size 0 -print`
        rm -f .hdepend scripts/mkdep scripts/split-include
        rm -f $(TOPDIR)/include/linux/modversions.h
        rm -rf $(TOPDIR)/include/linux/modules
index ea3522f93d05d430f1aa7cd6d9d0a7992956f2d1..f94915bb29a4b9bb9418178be751460a3d09c9ad 100644 (file)
@@ -373,7 +373,7 @@ int get_irq_list(char *buf)
                if (!action) 
                        continue;
                len += sprintf(buf+len, "%2d: %10u %c %s",
-                              i, kstat.interrupts[i],
+                              i, kstat.interrupts[0][i],
                               (action->flags & SA_INTERRUPT) ? '+' : ' ',
                               action->name);
                for (action=action->next; action; action = action->next) {
@@ -567,7 +567,7 @@ static inline void handle_irq(int irq, struct pt_regs * regs)
        int cpu = smp_processor_id();
 
        irq_enter(cpu, irq);
-       kstat.interrupts[irq]++;
+       kstat.interrupts[0][irq] += 1;
        if (!action) {
                unexpected_irq(irq, regs);
        } else {
@@ -590,7 +590,7 @@ static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
        }
 
        irq_enter(cpu, irq);
-       kstat.interrupts[irq]++;
+       kstat.interrupts[0][irq] += 1;
        action = irq_action[irq];
        /*
         * For normal interrupts, we mask it out, and then ACK it.
@@ -1050,7 +1050,6 @@ unsigned long probe_irq_on(void)
  */
 int probe_irq_off(unsigned long irqs)
 {
-       unsigned long delay;
        int i;
        
         irqs &= irq_mask;
index 24a45e7aa887187f5a876a5c17cac92e2be8239a..1328eeabadefb2d1eb9ee1d52d89b5aabf165552 100644 (file)
@@ -112,7 +112,7 @@ csum_partial_cfu_aligned(const unsigned long *src, unsigned long *dst,
  * easy.
  */
 static inline unsigned long
-csum_partial_cfu_dest_aligned(unsigned long *src, unsigned long *dst,
+csum_partial_cfu_dest_aligned(const unsigned long *src, unsigned long *dst,
                              unsigned long soff,
                              long len, unsigned long checksum,
                              int *errp)
index fd71492ad7b1da480948d5a59ba659dcc64c9f13..a13a96dab026714837643e7f00bf46acb0cd7c17 100644 (file)
@@ -532,7 +532,8 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_rt_sigsuspend)
        .long SYMBOL_NAME(sys_pread)            /* 180 */
        .long SYMBOL_NAME(sys_pwrite)
+       .long SYMBOL_NAME(sys_lchown);
        
-       .rept NR_syscalls-181
+       .rept NR_syscalls-182
                .long SYMBOL_NAME(sys_ni_syscall)
        .endr
index 393b070aa5b965d9bc054489b2a5a2cd09f3e50a..ab85b2df407fcdb6ed13a5a1f8c27f5891676c46 100644 (file)
@@ -39,7 +39,7 @@ EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
-EXPORT_SYMBOL(__intel_bh_counter);
+EXPORT_SYMBOL(global_bh_lock);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 /* Delay loops */
index 67f24e734a84c5a44c9e0bf1efe16eb793bcf0a6..ac83e4c7d6c288a7e3d05c1f34d9e802e559a7b5 100644 (file)
 # define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
 #endif
 
+unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
-#ifdef __SMP__
-atomic_t __intel_bh_counter;
-#else
-int __intel_bh_counter;
-#endif
 
 atomic_t nmi_counter;
 
@@ -129,53 +125,27 @@ static int irq_owner [NR_IRQS] = { NO_PROC_ID, };
    *  - explicitly use irq 16-19 depending on which PCI irq
    *    line your PCI controller uses.
    */
-  unsigned int io_apic_irqs = 0xFF0000;
+  unsigned int io_apic_irqs = 0xff0000;
 #endif
 
-static inline int ack_irq(int irq)
+static inline void mask_8259A(int irq)
 {
-       /*
-        * The IO-APIC part will be moved to assembly, nested
-        * interrupts will be ~5 instructions from entry to iret ...
-        */
-       int should_handle_irq = 0;
-       int cpu = smp_processor_id();
-
-       /*
-        * We always call this with local irqs disabled
-        */
-       spin_lock(&irq_controller_lock);
-
-       if (!irq_events[irq]++ && !disabled_irq[irq]) {
-               should_handle_irq = 1;
-#ifdef __SMP__
-               irq_owner[irq] = cpu;
-#endif
-               hardirq_enter(cpu);
+       cached_irq_mask |= 1 << irq;
+       if (irq & 8) {
+               outb(cached_A1,0xA1);
+       } else {
+               outb(cached_21,0x21);
        }
+}
 
-       if (IO_APIC_IRQ(irq))
-               ack_APIC_irq ();
-       else {
-       /*
-        * 8259-triggered INTA-cycle interrupt
-        */
-               if (should_handle_irq)
-                       mask_irq(irq);
-                       
-               if (irq & 8) {
-                       inb(0xA1);      /* DUMMY */
-                       outb(0x62,0x20);        /* Specific EOI to cascade */
-                       outb(0x20,0xA0);
-               } else {
-                       inb(0x21);      /* DUMMY */
-                       outb(0x20,0x20);
-               }
+static inline void unmask_8259A(int irq)
+{
+       cached_irq_mask &= ~(1 << irq);
+       if (irq & 8) {
+               outb(cached_A1,0xA1);
+       } else {
+               outb(cached_21,0x21);
        }
-
-       spin_unlock(&irq_controller_lock);
-
-       return (should_handle_irq);
 }
 
 void set_8259A_irq_mask(int irq)
@@ -393,8 +363,8 @@ unsigned char global_irq_holder = NO_PROC_ID;
 unsigned volatile int global_irq_lock;
 atomic_t global_irq_count;
 
-#define irq_active(cpu) \
-       (global_irq_count != local_irq_count[cpu])
+atomic_t global_bh_count;
+atomic_t global_bh_lock;
 
 /*
  * "global_cli()" is a special case, in that it can hold the
@@ -412,35 +382,56 @@ static inline void check_smp_invalidate(int cpu)
        }
 }
 
-static unsigned long previous_irqholder;
+static void show(char * str)
+{
+       int i;
+       unsigned long *stack;
+       int cpu = smp_processor_id();
+
+       printk("\n%s, CPU %d:\n", str, cpu);
+       printk("irq:  %d [%d %d]\n",
+               atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
+       printk("bh:   %d [%d %d]\n",
+               atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
+       stack = (unsigned long *) &str;
+       for (i = 40; i ; i--) {
+               unsigned long x = *++stack;
+               if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) {
+                       printk("<[%08lx]> ", x);
+               }
+       }
+}
+       
+
+#define MAXCOUNT 100000000
 
-static inline void wait_on_irq(int cpu, unsigned long where)
+static inline void wait_on_bh(void)
 {
-       int local_count = local_irq_count[cpu];
-
-       /* Are we the only one in an interrupt context? */
-       while (local_count != atomic_read(&global_irq_count)) {
-               /*
-                * No such luck. Now we need to release the lock,
-                * _and_ release our interrupt context, because
-                * otherwise we'd have dead-locks and live-locks
-                * and other fun things.
-                */
-               atomic_sub(local_count, &global_irq_count);
-               global_irq_holder = NO_PROC_ID;
-               global_irq_lock = 0;
-
-               /*
-                * Wait for everybody else to go away and release
-                * their things before trying to get the lock again.
-                */
+       int count = MAXCOUNT;
+       do {
+               if (!--count) {
+                       show("wait_on_bh");
+                       count = ~0;
+               }
+               /* nothing .. wait for the other bh's to go away */
+       } while (atomic_read(&global_bh_count) != 0);
+}
+
+static inline void wait_on_irq(int cpu)
+{
+       int count = MAXCOUNT;
+
+       while (atomic_read(&global_irq_count)) {
+               clear_bit(0,&global_irq_lock);
+
                for (;;) {
-                       atomic_add(local_count, &global_irq_count);
+                       if (!--count) {
+                               show("wait_on_irq");
+                               count = ~0;
+                       }
                        __sti();
                        SYNC_OTHER_CORES(cpu);
                        __cli();
-                       atomic_sub(local_count, &global_irq_count);
-                       SYNC_OTHER_CORES(cpu);
                        check_smp_invalidate(cpu);
                        if (atomic_read(&global_irq_count))
                                continue;
@@ -449,8 +440,24 @@ static inline void wait_on_irq(int cpu, unsigned long where)
                        if (!test_and_set_bit(0,&global_irq_lock))
                                break;
                }
-               atomic_add(local_count, &global_irq_count);
-               global_irq_holder = cpu;
+       }
+}
+
+/*
+ * This is called when we want to synchronize with
+ * bottom half handlers. We need to wait until
+ * no other CPU is executing any bottom half handler.
+ *
+ * Don't wait if we're already running in an interrupt
+ * context or are inside a bh handler.
+ */
+void synchronize_bh(void)
+{
+       if (atomic_read(&global_bh_count)) {
+               int cpu = smp_processor_id();
+               if (!local_irq_count[cpu] && !local_bh_count[cpu]) {
+                       wait_on_bh();
+               }
        }
 }
 
@@ -460,37 +467,15 @@ static inline void wait_on_irq(int cpu, unsigned long where)
  * stop sending interrupts: but to make sure there
  * are no interrupts that are executing on another
  * CPU we need to call this function.
- *
- * We have to give pending interrupts a chance to
- * arrive (ie. let them get until hard_irq_enter()),
- * even if they are arriving to another CPU.
- *
- * On UP this is a no-op.
- *
- * UPDATE: this method is not quite safe, as it wont
- * catch irq handlers polling for the irq lock bit
- * in __global_cli():get_interrupt_lock():wait_on_irq().
- * drivers should rather use disable_irq()/enable_irq()
- * and/or synchronize_one_irq()
  */
 void synchronize_irq(void)
 {
-       int local_count = local_irq_count[smp_processor_id()];
-
-       if (local_count != atomic_read(&global_irq_count)) {
-               int i;
-
-               /* The very stupid way to do this */
-               for (i=0; i<NR_IRQS; i++) {
-                       disable_irq(i);
-                       enable_irq(i);
-               }
-               cli();
-               sti();
-       }
+       /* Stupid approach */
+       cli();
+       sti();
 }
 
-static inline void get_irqlock(int cpu, unsigned long where)
+static inline void get_irqlock(int cpu)
 {
        if (test_and_set_bit(0,&global_irq_lock)) {
                /* do we already hold the lock? */
@@ -503,34 +488,40 @@ static inline void get_irqlock(int cpu, unsigned long where)
                        } while (test_bit(0,&global_irq_lock));
                } while (test_and_set_bit(0,&global_irq_lock));         
        }
-       /*
-        * Ok, we got the lock bit.
-        * But that's actually just the easy part.. Now
-        * we need to make sure that nobody else is running
+       /* 
+        * We also to make sure that nobody else is running
         * in an interrupt context. 
         */
-       wait_on_irq(cpu, where);
+       wait_on_irq(cpu);
 
        /*
-        * Finally.
+        * Ok, finally..
         */
        global_irq_holder = cpu;
-       previous_irqholder = where;
 }
 
+/*
+ * A global "cli()" while in an interrupt context
+ * turns into just a local cli(). Interrupts
+ * should use spinlocks for the (very unlikely)
+ * case that they ever want to protect against
+ * each other.
+ */
 void __global_cli(void)
 {
        int cpu = smp_processor_id();
-       unsigned long where;
 
-       __asm__("movl 16(%%esp),%0":"=r" (where));
        __cli();
-       get_irqlock(cpu, where);
+       if (!local_irq_count[cpu])
+               get_irqlock(cpu);
 }
 
 void __global_sti(void)
 {
-       release_irqlock(smp_processor_id());
+       int cpu = smp_processor_id();
+
+       if (!local_irq_count[cpu])
+               release_irqlock(cpu);
        __sti();
 }
 
@@ -543,8 +534,7 @@ void __global_restore_flags(unsigned long flags)
 {
        switch (flags) {
        case 0:
-               release_irqlock(smp_processor_id());
-               __sti();
+               __global_sti();
                break;
        case 1:
                __global_cli();
@@ -555,56 +545,19 @@ void __global_restore_flags(unsigned long flags)
        }
 }
 
-void synchronize_one_irq(unsigned int irq)
-{
-       int cpu = smp_processor_id(), owner;
-       int local_count = local_irq_count[cpu];
-       unsigned long flags;
-
-       __save_flags(flags);
-       __cli();
-       release_irqlock(cpu);
-       atomic_sub(local_count, &global_irq_count);
-
-repeat:        
-       spin_lock(&irq_controller_lock);
-       owner = irq_owner[irq];
-       spin_unlock(&irq_controller_lock);
-
-       if ((owner != NO_PROC_ID) && (owner != cpu)) {
-               atomic_add(local_count, &global_irq_count);
-               __sti();
-               SYNC_OTHER_CORES(cpu);
-               __cli();
-               atomic_sub(local_count, &global_irq_count);
-               SYNC_OTHER_CORES(cpu);
-               goto repeat;
-       }
-
-       if (!disabled_irq[irq])
-               printk("\n...WHAT??.#1...\n");
-
-       atomic_add(local_count, &global_irq_count);
-       __restore_flags(flags);
-}
-
 #endif
 
-static void handle_IRQ_event(int irq, struct pt_regs * regs)
+static int handle_IRQ_event(int irq, struct pt_regs * regs)
 {
        struct irqaction * action;
-       int status, cpu = smp_processor_id();
-
-again:
-#ifdef __SMP__
-       while (test_bit(0,&global_irq_lock)) mb();
-#endif
+       int status;
 
-       kstat.irqs[cpu][irq]++;
        status = 0;
        action = *(irq + irq_action);
 
        if (action) {
+               status |= 1;
+
                if (!(action->flags & SA_INTERRUPT))
                        __sti();
 
@@ -618,23 +571,7 @@ again:
                __cli();
        }
 
-       spin_lock(&irq_controller_lock);
-
-#ifdef __SMP__
-       release_irqlock(cpu);
-#endif
-
-       if ((--irq_events[irq]) && (!disabled_irq[irq])) {
-               spin_unlock(&irq_controller_lock);
-               goto again;
-       }
-#ifdef __SMP__
-       /* FIXME: move this into hardirq.h */
-       irq_owner[irq] = NO_PROC_ID;
-#endif
-       hardirq_exit(cpu);
-
-       spin_unlock(&irq_controller_lock);
+       return status;
 }
 
 
@@ -644,94 +581,103 @@ again:
  */
 void disable_irq(unsigned int irq)
 {
-#ifdef __SMP__
-       int cpu = smp_processor_id();
-#endif
-       unsigned long f, flags;
-
-       save_flags(flags);
-       __save_flags(f);
-       __cli();
-       spin_lock(&irq_controller_lock);
+       unsigned long flags;
 
+       spin_lock_irqsave(&irq_controller_lock, flags);
        disabled_irq[irq]++;
+       mask_irq(irq);
+       spin_unlock_irqrestore(&irq_controller_lock, flags);
 
-#ifdef __SMP__
-       /*
-        * We have to wait for all irq handlers belonging to this IRQ
-        * vector to finish executing.
-        */
-       if ((irq_owner[irq] == NO_PROC_ID) || (irq_owner[irq] == cpu) ||
-               (disabled_irq[irq] > 1)) {
-
-               spin_unlock(&irq_controller_lock);
-               __restore_flags(f);
-               restore_flags(flags);
-               if (disabled_irq[irq] > 100)
-                       printk("disable_irq(%d), infinit recursion!\n",irq);
-               return;
-       }
-#endif
-
-       spin_unlock(&irq_controller_lock);
-
-#ifdef __SMP__
-       synchronize_one_irq(irq);
-#endif
-
-       __restore_flags(f);
-       restore_flags(flags);
+       synchronize_irq();
 }
 
 void enable_irq(unsigned int irq)
 {
        unsigned long flags;
-       int cpu = smp_processor_id();
 
-       spin_lock_irqsave(&irq_controller_lock,flags);
+       spin_lock_irqsave(&irq_controller_lock, flags);
+       disabled_irq[irq]--;
+       unmask_irq(irq);
+       spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
 
-       if (!disabled_irq[irq]) {
-               spin_unlock_irqrestore(&irq_controller_lock,flags);
-               printk("more enable_irq(%d)'s than disable_irq(%d)'s!!",irq,irq);
-               return;
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+static inline void mask_and_ack_8259A(int irq_nr)
+{
+       spin_lock(&irq_controller_lock);
+       cached_irq_mask |= 1 << irq_nr;
+       if (irq_nr & 8) {
+               inb(0xA1);      /* DUMMY */
+               outb(cached_A1,0xA1);
+               outb(0x62,0x20);        /* Specific EOI to cascade */
+               outb(0x20,0xA0);
+       } else {
+               inb(0x21);      /* DUMMY */
+               outb(cached_21,0x21);
+               outb(0x20,0x20);
        }
+       spin_unlock(&irq_controller_lock);
+}
 
-       disabled_irq[irq]--;
+static void do_8259A_IRQ(int irq, int cpu, struct pt_regs * regs)
+{
+       mask_and_ack_8259A(irq);
 
-#ifndef __SMP__
-       if (disabled_irq[irq]) {
-               spin_unlock_irqrestore(&irq_controller_lock,flags);
-               return;
-       }
-#else
-       if (disabled_irq[irq] || (irq_owner[irq] != NO_PROC_ID)) {
-               spin_unlock_irqrestore(&irq_controller_lock,flags);
-               return;
+       irq_enter(cpu, irq);
+
+       if (handle_IRQ_event(irq, regs)) {
+               spin_lock(&irq_controller_lock);
+               unmask_8259A(irq);
+               spin_unlock(&irq_controller_lock);
        }
-#endif
 
-       /*
-        * Nobody is executing this irq handler currently, lets check
-        * wether we have outstanding events to be handled.
-        */
+       irq_exit(cpu, irq);
+}
 
-       if (irq_events[irq]) {
-               struct pt_regs regs;
+/*
+ * FIXME! This is completely broken.
+ */
+static void do_ioapic_IRQ(int irq, int cpu, struct pt_regs * regs)
+{
+       int should_handle_irq;
 
-#ifdef __SMP__
+       spin_lock(&irq_controller_lock);
+       should_handle_irq = 0;
+       if (!irq_events[irq]++ && !disabled_irq[irq]) {
+               should_handle_irq = 1;
                irq_owner[irq] = cpu;
-#endif
                hardirq_enter(cpu);
-#ifdef __SMP__
-               release_irqlock(cpu);
-#endif
-               spin_unlock(&irq_controller_lock);
+       }
 
-               handle_IRQ_event(irq,&regs);
-               __restore_flags(flags);
-               return;
+       ack_APIC_irq();
+
+       spin_unlock(&irq_controller_lock);
+       
+       if (should_handle_irq) {
+again:
+               if (!handle_IRQ_event(irq, regs))
+                       disabled_irq[irq] = 1;
+
+       }
+
+       spin_lock(&irq_controller_lock);
+       release_irqlock(cpu);
+
+       if ((--irq_events[irq]) && (!disabled_irq[irq]) && should_handle_irq) {
+               spin_unlock(&irq_controller_lock);
+               goto again;
        }
-       spin_unlock_irqrestore(&irq_controller_lock,flags);
+
+       irq_owner[irq] = NO_PROC_ID;
+       hardirq_exit(cpu);
+       spin_unlock(&irq_controller_lock);
+
+       enable_IO_APIC_irq(irq);
 }
 
 /*
@@ -749,7 +695,9 @@ void enable_irq(unsigned int irq)
  * overlapping ... i saw no driver problem so far.
  */
 asmlinkage void do_IRQ(struct pt_regs regs)
-{
+{      
+       void (*do_lowlevel_IRQ)(int, int, struct pt_regs *);
+
        /* 
         * We ack quickly, we don't want the irq controller
         * thinking we're snobs just because some other CPU has
@@ -761,16 +709,15 @@ asmlinkage void do_IRQ(struct pt_regs regs)
         * handled by some other CPU. (or is disabled)
         */
        int irq = regs.orig_eax & 0xff;
+       int cpu = smp_processor_id();
 
-/*
-       printk("<%d>",irq);
- */
-       if (!ack_irq(irq))
-               return;
-
-       handle_IRQ_event(irq,&regs);
+       kstat.irqs[cpu][irq]++;
 
-       unmask_irq(irq);
+       do_lowlevel_IRQ = do_8259A_IRQ;
+       if (IO_APIC_IRQ(irq))
+               do_lowlevel_IRQ = do_ioapic_IRQ;
+       
+       do_lowlevel_IRQ(irq, cpu, &regs);
 
        /*
         * This should be conditional: we should really get
index b7a4dc472868a6bf73c65a3f2d5ae770fea77145..f1e2edea530cdb387fe3eaed1c01c610beb0d5fb 100644 (file)
@@ -42,6 +42,8 @@ extern spinlock_t irq_controller_lock; /*
 
 #ifdef __SMP__
 
+#include <asm/atomic.h>
+
 static inline void irq_enter(int cpu, int irq)
 {
        hardirq_enter(cpu);
index 24b080f73d5c3cefb1240f0a0820c0b4735b878f..6b313d99c3a9d64882779884046174e8a339cba4 100644 (file)
@@ -89,7 +89,7 @@ strncpy_from_user(char *dst, const char *src, long count)
                "       .long 0b,3b\n"                                  \
                "       .long 1b,2b\n"                                  \
                ".previous"                                             \
-               : "=c"(size)                                            \
+               : "=&c"(size)                                           \
                : "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0)       \
                : "di")
 
index 6628aa99e2fa57206ea00a97fa7cb7b015228945..94b90dd94231322afeab66f3111433481fa5396c 100644 (file)
@@ -1710,10 +1710,11 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
        }
        if (handler) {
-               if(softirq_trylock()) {
+               int cpu = smp_processor_id();
+               if(softirq_trylock(cpu)) {
                        /* got the lock, call the handler immediately */
                        handler();
-                       softirq_endlock();
+                       softirq_endlock(cpu);
                } else
                        /* we interrupted a bottom half. Defer handler */
                        schedule_bh( (void *)(void *) handler);
index 6b39919f270b7d825dea9c5a085000fc146fc64a..966a4031e25d63690d1a5627dd356aa64c16547f 100644 (file)
@@ -776,7 +776,9 @@ static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
        int blk, blocks_in_map;
        int dev_bsize, dev_pos, pos;
        unsigned secsize;
+#ifdef CONFIG_PMAC
        int first_bootable = 1;
+#endif
        struct mac_partition *part;
        struct mac_driver_desc *md;
 
index 789b8e04d1aca2bcf77eb958e86d028ba395cc22..8c592c7518cf9f531724cddb72a961ff1836b401 100644 (file)
@@ -493,7 +493,7 @@ static int do_md_stop (int minor, struct inode *inode)
                /*
                 * ioctl : one open channel
                 */
-               printk ("STOP_MD md%x failed : i_count=%ld, busy=%d\n",
+               printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n",
                                minor, inode->i_count, md_dev[minor].busy);
                return -EBUSY;
        }
@@ -846,6 +846,7 @@ EXPORT_SYMBOL(md_do_sync);
 static struct proc_dir_entry proc_md = {
        PROC_MD, 6, "mdstat",
        S_IFREG | S_IRUGO, 1, 0, 0,
+       0, &proc_array_inode_operations,
 };
 
 static void md_geninit (struct gendisk *gdisk)
index b4d5146de3aef11eacb6f16fb487cba4b3eee303..b109192fbd0e62a2271ed614a56f1cfb7e309235 100644 (file)
@@ -1038,14 +1038,9 @@ static void dump_cmd_complete_status(u_int int_ret_code)
 }
 
 
-
 static int ps2esdi_open(struct inode *inode, struct file *file)
 {
-       int dev = DEVICE_NR(MINOR(inode->i_rdev));
-
-#if 0
-       printk("%s: dev= %d\n", DEVICE_NAME, dev);
-#endif
+       int dev = DEVICE_NR(inode->i_rdev);
 
        if (dev < ps2esdi_drives) {
                while (!ps2esdi_valid[dev])
@@ -1062,7 +1057,7 @@ static int ps2esdi_open(struct inode *inode, struct file *file)
 
 static int ps2esdi_release(struct inode *inode, struct file *file)
 {
-       int dev = DEVICE_NR(MINOR(inode->i_rdev));
+       int dev = DEVICE_NR(inode->i_rdev);
 
        if (dev < ps2esdi_drives) {
                sync_dev(dev);
@@ -1078,7 +1073,7 @@ static int ps2esdi_ioctl(struct inode *inode,
 {
 
        struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
-       int dev = DEVICE_NR(MINOR(inode->i_rdev)), err;
+       int dev = DEVICE_NR(inode->i_rdev), err;
 
        if (inode && (dev < ps2esdi_drives))
                switch (cmd) {
@@ -1133,7 +1128,7 @@ static int ps2esdi_ioctl(struct inode *inode,
 
 static int ps2esdi_reread_partitions(int dev)
 {
-       int target = DEVICE_NR(MINOR(dev));
+       int target = DEVICE_NR(dev);
        int start = target << ps2esdi_gendisk.minor_shift;
        int partition;
 
@@ -1145,15 +1140,20 @@ static int ps2esdi_reread_partitions(int dev)
 
        for (partition = ps2esdi_gendisk.max_p - 1;
             partition >= 0; partition--) {
-               sync_dev(MAJOR_NR << 8 | start | partition);
-               invalidate_inodes(MAJOR_NR << 8 | start | partition);
-               invalidate_buffers(MAJOR_NR << 8 | start | partition);
+               int minor = (start | partition);
+               kdev_t devp = MKDEV(MAJOR_NR, minor);
+               struct super_block * sb = get_super(devp);
+               
+               sync_dev(devp);
+               if (sb)
+                       invalidate_inodes(sb);
+               invalidate_buffers(devp);
                ps2esdi_gendisk.part[start + partition].start_sect = 0;
                ps2esdi_gendisk.part[start + partition].nr_sects = 0;
-       };
+       }
 
        ps2esdi_gendisk.part[start].nr_sects = ps2esdi_info[target].head *
-           ps2esdi_info[target].cyl * ps2esdi_info[target].sect;
+               ps2esdi_info[target].cyl * ps2esdi_info[target].sect;
        resetup_one_dev(&ps2esdi_gendisk, target);
 
        ps2esdi_valid[target] = 1;
index 7434242585bb209b2b948e2a62b40289bd17cdd9..9a7b268716cddc0ece32748911bd339c2fd7d98d 100644 (file)
@@ -1242,6 +1242,7 @@ size_to_buf(unsigned int size,
    buf[2] = size % 256;
 }
 
+#if 0
 /* Uniform cdrom interface function.
    Return the status of the current disc:
    If it is recognized as CD-I -> return XA Mode 2 Form 2
@@ -1268,6 +1269,7 @@ static int scd_disc_status(struct cdrom_device_info *cdi)
   } else 
     return CDS_NO_INFO;
 }
+#endif
 
 /* Starts a read operation. Returns 0 on success and 1 on failure. 
    The read operation used here allows multiple sequential sectors 
index 414918727d2b6219a7a3a054842cfa7b40d0423d..cd821406f510c08e4b404a4546560df6b0330ba2 100644 (file)
@@ -129,16 +129,22 @@ static int I2CRead(struct bttv *btv, int addr)
        btwrite(BT848_INT_I2CDONE, BT848_INT_STAT);
   
        btwrite(((addr & 0xff) << 24) | I2C_COMMAND, BT848_I2C);
-  
-       for (i=0x7fffffff; i; i--)
+
+       /*
+        * Timeout for I2CRead is 1 second (this should be enough, really!)
+        */
+       for (i=1000; i; i--)
        {
                stat=btread(BT848_INT_STAT);
                if (stat & BT848_INT_I2CDONE)
                        break;
+               udelay(1000); /* 1ms, as I2C is 1kHz (?) */
        }
   
-       if (!i)
+       if (!i) {
+               printk(KERN_DEBUG "bttv: I2CRead timeout\n");
                return -1;
+       }
        if (!(stat & BT848_INT_RACK))
                return -2;
   
@@ -167,15 +173,18 @@ static int I2CWrite(struct bttv *btv, unchar addr, unchar b1,
   
        btwrite(data, BT848_I2C);
 
-       for (i=0x7fffffff; i; i--)
+       for (i=1000; i; i--)
        {
                stat=btread(BT848_INT_STAT);
                if (stat & BT848_INT_I2CDONE)
                        break;
+               udelay(1000);
        }
   
-       if (!i)
+       if (!i) {
+               printk(KERN_DEBUG "bttv: I2CWrite timeout\n");
                return -1;
+       }
        if (!(stat & BT848_INT_RACK))
                return -2;
   
@@ -772,7 +781,7 @@ static void write_risc_data(struct bttv *btv, struct video_clip *vp, int count)
        /*
         *      32bit depth frame buffers need extra flags setting
         */
-        
+
        if (depth==4)
                mask=BT848_RISC_BYTE3;
        else
@@ -1093,13 +1102,13 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                case VIDIOCGPICT:
                {
                        struct video_picture p=btv->picture;
-                       if(btv->win.bpp==8)
+                       if(btv->win.bpp==1)
                                p.palette=VIDEO_PALETTE_HI240;
-                       if(btv->win.bpp==16)
+                       if(btv->win.bpp==2)
                                p.palette=VIDEO_PALETTE_RGB565;
-                       if(btv->win.bpp==24)
+                       if(btv->win.bpp==3)
                                p.palette=VIDEO_PALETTE_RGB24;
-                       if(btv->win.bpp==32)
+                       if(btv->win.bpp==4)
                                p.palette=VIDEO_PALETTE_RGB32;
                        if(copy_to_user(arg, &p, sizeof(p)))
                                return -EFAULT;
index a33a6a8c22f735776f9b8a41eb769d2a8d267343..82a8765fa11b94f0b667f0ae7e6397ae18c9e238 100644 (file)
@@ -109,7 +109,6 @@ static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static int fasync_mouse(struct file *filp, int on)
 {
        int retval;
-       struct inode *inode = filp->f_dentry->d_inode;
 
        retval = fasync_helper(filp, on, &mouse.fasyncptr);
        if (retval < 0)
index a64b98a242e5dc91c760ba7469676b3464a9eb9d..0ba7df6b7edca74d4930759272c8ef176ba21fd5 100644 (file)
@@ -923,11 +923,12 @@ void cleanup_module(void)
                close_bwqcam(qcams[i]);
 }
 #else
-__initfunc(int init_bwqcams(struct video_init *unused))
+__initfunc(int init_bw_qcams(struct video_init *unused))
 {
        struct parport *port;
 
        for (port = parport_enumerate(); port; port=port->next)
                init_bwqcam(port);
+       return 0;
 }
 #endif
index c2eb77040f138f22d536e9570c733155dbe69552..df12a34131da384046ac4df1af6819c2a9e1e709 100644 (file)
@@ -771,5 +771,6 @@ __initfunc(int init_colour_qcams(struct video_init *unused))
 
        for (port = parport_enumerate(); port; port=port->next)
                init_cqcam(port);
+       return 0;
 }
 #endif
index 47229c5b4e621fd4adf433c2d5e3806f4ec94177..fd1ac0cd7135e9a661a17bfaa900645d53a9e462 100644 (file)
@@ -385,7 +385,7 @@ int fdc_issue_command(const __u8 * out_data, int out_count,
 int fdc_interrupt_wait(unsigned int time)
 {
        struct wait_queue wait = {current, NULL};
-       int current_blocked = current->blocked;
+       sigset_t old_sigmask;   
        static int resetting = 0;
        TRACE_FUN(ft_t_fdc_dma);
 
@@ -401,14 +401,23 @@ int fdc_interrupt_wait(unsigned int time)
        /* timeout time will be up to USPT microseconds too long ! */
        current->timeout = jiffies + (1000 * time + FT_USPT - 1) / FT_USPT;
        current->state = TASK_INTERRUPTIBLE;
-       current->blocked = _BLOCK_ALL; /* isn't this already set by the
-                                       * high level routines?
-                                       */
+
+       spin_lock_irq(&current->sigmask_lock);
+        old_sigmask = current->blocked;
+        siginitset(&current->blocked, _BLOCK_ALL);
+        recalc_sigpending(current);
+        spin_unlock_irq(&current->sigmask_lock);
+
        add_wait_queue(&ftape_wait_intr, &wait);
        while (!ft_interrupt_seen && current->state != TASK_RUNNING) {
                schedule();     /* sets TASK_RUNNING on timeout */
         }
-       current->blocked = current_blocked;     /* restore */
+
+       spin_lock_irq(&current->sigmask_lock);
+        current->blocked = old_sigmask;
+        recalc_sigpending(current);
+        spin_unlock_irq(&current->sigmask_lock);
+       
        remove_wait_queue(&ftape_wait_intr, &wait);
        /*  the following IS necessary. True: as well
         *  wake_up_interruptible() as the schedule() set TASK_RUNNING
index 1ce4c28436073a7b25a6da1f993135f5e7329e51..05f1f61466934b94b929b717db98a787e3498a37 100644 (file)
@@ -794,8 +794,8 @@ void ftape_disable(void)
                              i, *ft_buffer[i]->address);
                }
        }
-       if ((current->signal & _DONT_BLOCK) && 
-           !(current->signal & _NEVER_BLOCK) &&
+       if (sigtestsetmask(&current->signal, _DONT_BLOCK) && 
+           !(sigtestsetmask(&current->signal, _NEVER_BLOCK)) &&
            ftape_tape_running) {
                TRACE(ft_t_warn,
                      "Interrupted by fatal signal and tape still running");
index eae86b3dce57d5159fa41fc44d95d557604aaf2c..35ae7f94da285915bd08d1bd42970f7e6dc7527d 100644 (file)
 #include <linux/linkage.h>
 #include <linux/signal.h>
 
-#define _S(nr) (1<<((nr)-1))
-#define _NEVER_BLOCK    (_S(SIGKILL)|_S(SIGSTOP))
-#define _DONT_BLOCK     (_NEVER_BLOCK|_S(SIGINT))
-#define _DO_BLOCK       (_S(SIGPIPE))
-#define _BLOCK_ALL      (0xffffffffL)
-
+#define _NEVER_BLOCK    (sigmask(SIGKILL) | sigmask(SIGSTOP))
+#define _DONT_BLOCK     (_NEVER_BLOCK | sigmask(SIGINT))
+#define _DO_BLOCK       (sigmask(SIGPIPE))
 
 #ifndef QIC117_TAPE_MAJOR
 #define QIC117_TAPE_MAJOR 27
index e3e0243f00337208a56eba8b59c0ece37e8556c9..2ae96344e4e18167ccf07d691bb4ed6e994496d6 100644 (file)
@@ -432,7 +432,8 @@ int ftape_dumb_stop(void)
                         */
                        result = ftape_ready_wait(ftape_timeout.pause,&status);
                }
-       } while (ftape_tape_running && (current->signal & _NEVER_BLOCK) == 0);
+       } while (ftape_tape_running
+                && !(sigtestsetmask(&current->signal, _NEVER_BLOCK)));
 #ifndef TESTING
        ft_location.known = 0;
 #endif
@@ -660,7 +661,7 @@ static int seek_forward(int segment_id, int fast)
                 *  to find a way to skip an EMPTY_SEGMENT. !!! FIXME !!!
                 */
                if (ftape_read_id() < 0 || !ft_location.known ||
-                   (current->signal & _DONT_BLOCK)) {
+                   sigtestsetmask(&current->signal, _DONT_BLOCK)) {
                        ft_location.known = 0;
                        if (!ftape_tape_running ||
                            ++failures > FT_SECTORS_PER_SEGMENT) {
@@ -775,7 +776,7 @@ static int skip_reverse(int segment_id, int *pstatus)
                fast_seek(count, 1);
                logical_forward();
                if (ftape_read_id() < 0 || !ft_location.known ||
-                   (current->signal & _DONT_BLOCK)) {
+                   (sigtestsetmask(&current->signal, _DONT_BLOCK))) {
                        if ((!ftape_tape_running && !ft_location.known) ||
                            ++failures > FT_SECTORS_PER_SEGMENT) {
                                TRACE_ABORT(-EIO, ft_t_err,
@@ -1001,7 +1002,7 @@ int ftape_start_tape(int segment_id, int sector_offset)
        while (result < 0     &&
               retry++ <= 5   &&
               !ft_failure &&
-              (current->signal & _DONT_BLOCK) == 0) {
+              !(sigtestsetmask(&current->signal, _DONT_BLOCK))) {
                
                if (retry && start_offset < 5) {
                        start_offset ++;
index ac675568a86fcd4b69f8c361dd3e046804983f88..7f93942a572e72dadbf1864b08d04ebfe535710c 100644 (file)
@@ -171,7 +171,7 @@ extern void ftape_trace_log (const char *file, const char *name);
  *  but rather into ftape-rw.h (maybe)
  */
 #define FT_SIGNAL_EXIT(sig_mask)                                       \
-       if (current->signal & (sig_mask)) {                             \
+       if (sigtestsetmask(&current->signal, sig_mask)) {               \
                TRACE_ABORT(-EINTR,                                     \
                            ft_t_warn,                                  \
                            "interrupted by non-blockable signal");     \
index c6a4f450646980f46f4a07999f3f2e35193e13af..0cb9f018f9a30ba87fe2e3f6df42920124b1001a 100644 (file)
@@ -73,7 +73,7 @@ const ftape_info *zft_status;
 /*      Local vars.
  */
 static int busy_flag = 0;
-static int orig_sigmask;
+static sigset_t orig_sigmask;
 
 /*  the interface to the kernel vfs layer
  */
@@ -171,7 +171,7 @@ static int zft_open(struct inode *ino, struct file *filep)
                TRACE_ABORT(-ENXIO, ft_t_err, "failed: illegal unit nr");
        }
        orig_sigmask = current->blocked;
-       current->blocked = _BLOCK_ALL;
+       sigfillset(&current->blocked);
        result = _zft_open(MINOR(ino->i_rdev), filep->f_flags & O_ACCMODE);
        if (result < 0) {
                current->blocked = orig_sigmask; /* restore mask */
@@ -186,18 +186,15 @@ static int zft_open(struct inode *ino, struct file *filep)
                /* Mask signals that will disturb proper operation of the
                 * program that is calling.
                 */
-               current->blocked = orig_sigmask | _DO_BLOCK;
+               current->blocked = orig_sigmask;
+               sigaddsetmask (&current->blocked, _DO_BLOCK);
                TRACE_EXIT 0;
        }
 }
 
 /*      Close floppy tape device
  */
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,31)
 static int zft_close(struct inode *ino, struct file *filep)
-#else
-static void zft_close(struct inode *ino, struct file *filep)
-#endif
 {
        int result;
        TRACE_FUN(ft_t_flow);
@@ -210,7 +207,7 @@ static void zft_close(struct inode *ino, struct file *filep)
                TRACE_EXIT; /* keep busy_flag !(?) */
 #endif
        }
-       current->blocked = _BLOCK_ALL;
+       sigfillset(&current->blocked);
        result = _zft_close();
        if (result < 0) {
                TRACE(ft_t_err, "_zft_close failed");
@@ -235,7 +232,7 @@ static int zft_ioctl(struct inode *ino, struct file *filep,
                     unsigned int command, unsigned long arg)
 {
        int result = -EIO;
-       int old_sigmask;
+       sigset_t old_sigmask;
        TRACE_FUN(ft_t_flow);
 
        if (!busy_flag || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
@@ -243,7 +240,7 @@ static int zft_ioctl(struct inode *ino, struct file *filep,
                            "failed: not busy, failure or wrong unit");
        }
        old_sigmask = current->blocked; /* save mask */
-       current->blocked = _BLOCK_ALL;
+       sigfillset(&current->blocked);
        /* This will work as long as sizeof(void *) == sizeof(long) */
        result = _zft_ioctl(command, (void *) arg);
        current->blocked = old_sigmask; /* restore mask */
@@ -261,7 +258,7 @@ static int zft_mmap(struct inode *ino,
 #endif
 {
        int result = -EIO;
-       int old_sigmask;
+       sigset_t old_sigmask;
        TRACE_FUN(ft_t_flow);
 
        if (!busy_flag || 
@@ -276,7 +273,7 @@ static int zft_mmap(struct inode *ino,
                            "failed: not busy, failure or wrong unit");
        }
        old_sigmask = current->blocked; /* save mask */
-       current->blocked = _BLOCK_ALL;
+       sigfillset(&current->blocked);
        if ((result = ftape_mmap(vma)) >= 0) {
 #ifndef MSYNC_BUG_WAS_FIXED
                static struct vm_operations_struct dummy = { NULL, };
@@ -307,7 +304,7 @@ static int  zft_read(struct inode *ino, struct file *fp, char *buff,
 #endif
 {
        int result = -EIO;
-       int old_sigmask;
+       sigset_t old_sigmask;
 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,60)
        struct inode *ino = fp->f_dentry->d_inode;
 #endif
@@ -319,7 +316,7 @@ static int  zft_read(struct inode *ino, struct file *fp, char *buff,
                            "failed: not busy, failure or wrong unit");
        }
        old_sigmask = current->blocked; /* save mask */
-       current->blocked = _BLOCK_ALL;
+       sigfillset(&current->blocked);
        result = _zft_read(buff, req_len);
        current->blocked = old_sigmask; /* restore mask */
        TRACE(ft_t_data_flow, "return with count: %d", result);
@@ -343,7 +340,7 @@ static int  zft_write(struct inode *ino, struct file *fp, char *buff,
 #endif
 {
        int result = -EIO;
-       int old_sigmask;
+       sigset_t old_sigmask;
 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,60)
        struct inode *ino = fp->f_dentry->d_inode;
 #endif
@@ -355,7 +352,7 @@ static int  zft_write(struct inode *ino, struct file *fp, char *buff,
                            "failed: not busy, failure or wrong unit");
        }
        old_sigmask = current->blocked; /* save mask */
-       current->blocked = _BLOCK_ALL;
+       sigfillset(&current->blocked);
        result = _zft_write(buff, req_len);
        current->blocked = old_sigmask; /* restore mask */
        TRACE(ft_t_data_flow, "return with count: %d", result);
index 3b9f3bf5a97e0105c6837847e4b35a0a4e62dcb0..5aacad35712857d7d95f1ac9f439038034596358 100644 (file)
 void soundcard_init(void);
 #endif
 #ifdef CONFIG_ISDN
-void isdn_init(void);
+int isdn_init(void);
 #endif
 #ifdef CONFIG_PCWATCHDOG
-void pcwatchdog_init(void);
+int pcwatchdog_init(void);
+#endif
+#ifdef CONFIG_VIDEO_DEV
+extern int videodev_init(void);
 #endif
 
 static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
index fed2005cd8c3445cd498a97519342457860c912a..98b74551c363c6340fd0512315e29076a5db4be8 100644 (file)
@@ -78,6 +78,9 @@ extern int dsp56k_init(void);
 extern int nvram_init(void);
 extern int radio_init(void);
 extern void hfmodem_init(void);
+#ifdef CONFIG_PC110_PAD
+extern int pc110pad_init(void);
+#endif
 
 #ifdef CONFIG_PROC_FS
 static int misc_read_proc(char *buf, char **start, off_t offset,
index d87e436a634a5f7e5ba16e1bd8262af6d646a226..2ef2f5ccb07eedce5d6f7259065a42ae2bee38d0 100644 (file)
@@ -610,7 +610,7 @@ static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count)
 {
        int y;
        int dw = 2*dev->width;
-       char *src = (char *)bus_to_virt((void *)mem_base);
+       char *src = (char *)bus_to_virt(mem_base);
 
        char tmp[dw+32]; /* using a temp buffer is faster than direct  */
        int cnt = 0;
index df4dff23fed1d2b33ae5bc9b509c37b517c323b9..461e58165407abe0ad5c637e8345c2ea253465ce 100644 (file)
@@ -1766,8 +1766,10 @@ static ssize_t qic02_tape_read(struct file * filp, char * buf, size_t count, lof
 
     if (TP_DIAGS(current_tape_dev))
       /* can't print a ``long long'' (for filp->f_pos), so chop it */
-      printk(TPQIC02_NAME ": request READ, minor=%x, buf=%p, count=%lx, pos=%lx, flags=%x\n",
-            MINOR(dev), buf, count, (unsigned long) filp->f_pos, flags);
+      printk(TPQIC02_NAME ": request READ, minor=%x, buf=%p, count=%lx"
+                         ", pos=%lx, flags=%x\n",
+            MINOR(dev), buf, (long) count,
+            (unsigned long) filp->f_pos, flags);
     
     if (count % TAPE_BLKSIZE)  /* Only allow mod 512 bytes at a time. */
     {
@@ -1980,8 +1982,10 @@ static ssize_t qic02_tape_write( struct file * filp,  const char * buf,
     if (TP_DIAGS(current_tape_dev))
     {
        /* can't print a ``long long'' (for filp->f_pos), so chop it */
-       printk(TPQIC02_NAME ": request WRITE, minor=%x, buf=%p, count=%lx, pos=%lx, flags=%x\n",
-              MINOR(dev), buf, count, (unsigned long) filp->f_pos, flags);
+       printk(TPQIC02_NAME ": request WRITE, minor=%x, buf=%p"
+                           ", count=%lx, pos=%lx, flags=%x\n",
+              MINOR(dev), buf,
+              (long) count, (unsigned long) filp->f_pos, flags);
     }
     
     if (count % TAPE_BLKSIZE)  /* only allow mod 512 bytes at a time */
@@ -2128,7 +2132,9 @@ static ssize_t qic02_tape_write( struct file * filp,  const char * buf,
     tpqputs(TPQD_ALWAYS, "write request for <0 bytes");
     if (TPQDBG(DEBUG))
     {
-       printk(TPQIC02_NAME ": status_bytes_wr %x, buf %p, total_bytes_done %lx, count %lx\n", status_bytes_wr, buf, total_bytes_done, count);
+       printk(TPQIC02_NAME ": status_bytes_wr %x, buf %p"
+                           ", total_bytes_done %lx, count %lx\n",
+              status_bytes_wr, buf, total_bytes_done, (long) count);
     }
     return -EINVAL;
 } /* qic02_tape_write */
@@ -2865,7 +2871,7 @@ static int qic02_get_resources(void)
     return 0;
 } /* qic02_get_resources */
 
-__initfunc(static int qic02_tape_init(void))
+__initfunc(int qic02_tape_init(void))
 {
     if (TPSTATSIZE != 6)
     {
index c5a15294eaa43d2c41b6a40945a63fec18be3a9b..9fd8b17f16025398977c9fd34f63f985a3484c50 100644 (file)
  
 static struct video_device *video_device[VIDEO_NUM_DEVICES];
 
-/*
- *     Initialiser list
- */
-struct video_init
-{
-       char *name;
-       int (*init)(struct video_init *);
-};
-
+#ifdef CONFIG_VIDEO_BT848
 extern int init_bttv_cards(struct video_init *);
+#endif
+#ifdef CONFIG_VIDEO_CQCAM
+extern int init_colour_qcams(struct video_init *);
+#endif
+#ifdef CONFIG_VIDEO_BWQCAM
+extern int init_bw_qcams(struct video_init *);
+#endif
 
 static struct video_init video_init_list[]={
 #ifdef CONFIG_VIDEO_BT848
@@ -59,7 +57,7 @@ static struct video_init video_init_list[]={
        {"bw-qcam", init_bw_qcams},
 #endif 
 #ifdef CONFIG_VIDEO_PMS
-       {"PMS", init_pms_cards},
+       {"PMS", init_pms_cards},        /* not defined anywhere */
 #endif 
        {"end", NULL}
 };
@@ -72,7 +70,6 @@ static struct video_init video_init_list[]={
 static ssize_t video_read(struct file *file,
        char *buf, size_t count, loff_t *ppos)
 {
-       int err;
        struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
        return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
 }
@@ -85,7 +82,6 @@ static ssize_t video_read(struct file *file,
 static ssize_t video_write(struct file *file, const char *buf, 
        size_t count, loff_t *ppos)
 {
-       int err;
        struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
        return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
 }
index 8b5bea45d3d0406cb33180f530d71bf4be061899..a35d1c71f5597fa2eea832f1818c55c9e6d9e35e 100644 (file)
@@ -772,7 +772,7 @@ initavm_a1(struct IsdnCardState *sp)
        int loop = 0;
        char tmp[40];
 
-       sp->counter = kstat.interrupts[sp->irq];
+       sp->counter = kstat_irqs(sp->irq);
        sprintf(tmp, "IRQ %d count %d", sp->irq, sp->counter);
        debugl1(sp, tmp);
        clear_pending_ints(sp);
@@ -785,16 +785,16 @@ initavm_a1(struct IsdnCardState *sp)
                        /* At least 1-3 irqs must happen
                         * (one from HSCX A, one from HSCX B, 3rd from ISAC)
                         */
-                       if (kstat.interrupts[sp->irq] > sp->counter)
+                       if (kstat_irqs(sp->irq) > sp->counter)
                                break;
                        current->state = TASK_INTERRUPTIBLE;
                        current->timeout = jiffies + 1;
                        schedule();
                }
                sprintf(tmp, "IRQ %d count %d", sp->irq,
-                       kstat.interrupts[sp->irq]);
+                       kstat_irqs(sp->irq));
                debugl1(sp, tmp);
-               if (kstat.interrupts[sp->irq] == sp->counter) {
+               if (kstat_irqs(sp->irq) == sp->counter) {
                        printk(KERN_WARNING
                               "AVM A1: IRQ(%d) getting no interrupts during init\n",
                               sp->irq);
index 28db3323531627ce73caccef8e8e177b93805d78..430d2409c5a7e31f3ed2b6f430afc13736b234c6 100644 (file)
@@ -1180,7 +1180,7 @@ initelsa(struct IsdnCardState *sp)
        int ret, irq_cnt, cnt = 3;
        long flags;
 
-       irq_cnt = kstat.interrupts[sp->irq];
+       irq_cnt = kstat_irqs(sp->irq);
        printk(KERN_INFO "Elsa: IRQ %d count %d\n", sp->irq, irq_cnt);
        ret = get_irq(sp->cardnr, &elsa_interrupt);
 #ifdef CONFIG_HISAX_ELSA_PCC
@@ -1213,8 +1213,8 @@ initelsa(struct IsdnCardState *sp)
                }
 #endif
                printk(KERN_INFO "Elsa: IRQ %d count %d\n", sp->irq,
-                      kstat.interrupts[sp->irq]);
-               if (kstat.interrupts[sp->irq] == irq_cnt) {
+                      kstat_irqs(sp->irq));
+               if (kstat_irqs(sp->irq) == irq_cnt) {
                        printk(KERN_WARNING
                               "Elsa: IRQ(%d) getting no interrupts during init %d\n",
                               sp->irq, 4 - cnt);
index 707635261d8fbe5541559e106314c6b0078bfa8a..bd595d0c8449f0567be0d005058e9f4752e24236 100644 (file)
@@ -841,7 +841,7 @@ initix1micro(struct IsdnCardState *sp)
        int loop = 0;
        char tmp[40];
 
-       sp->counter = kstat.interrupts[sp->irq];
+       sp->counter = kstat_irqs(sp->irq);
        sprintf(tmp, "IRQ %d count %d", sp->irq, sp->counter);
        debugl1(sp, tmp);
        clear_pending_ints(sp);
@@ -854,16 +854,16 @@ initix1micro(struct IsdnCardState *sp)
                        /* At least 1-3 irqs must happen
                         * (one from HSCX A, one from HSCX B, 3rd from ISAC)
                         */
-                       if (kstat.interrupts[sp->irq] > sp->counter)
+                       if (kstat_irqs(sp->irq) > sp->counter)
                                break;
                        current->state = TASK_INTERRUPTIBLE;
                        current->timeout = jiffies + 1;
                        schedule();
                }
                sprintf(tmp, "IRQ %d count %d", sp->irq,
-                       kstat.interrupts[sp->irq]);
+                       kstat_irqs(sp->irq));
                debugl1(sp, tmp);
-               if (kstat.interrupts[sp->irq] == sp->counter) {
+               if (kstat_irqs(sp->irq) == sp->counter) {
                        printk(KERN_WARNING
                               "ix1-Micro: IRQ(%d) getting no interrupts during init\n",
                               sp->irq);
index 0560eff88f91824fa8db0a6fdf0fc20ea92e732c..e14c01c09fb80adfeec028c66116f7575cb5ba3f 100644 (file)
@@ -802,7 +802,7 @@ initteles0(struct IsdnCardState *sp)
        int loop = 0;
        char tmp[40];
 
-       sp->counter = kstat.interrupts[sp->irq];
+       sp->counter = kstat_irqs(sp->irq);
        sprintf(tmp, "IRQ %d count %d", sp->irq, sp->counter);
        debugl1(sp, tmp);
        clear_pending_ints(sp);
@@ -815,16 +815,16 @@ initteles0(struct IsdnCardState *sp)
                        /* At least 1-3 irqs must happen
                         * (one from HSCX A, one from HSCX B, 3rd from ISAC)
                         */
-                       if (kstat.interrupts[sp->irq] > sp->counter)
+                       if (kstat_irqs(sp->irq) > sp->counter)
                                break;
                        current->state = TASK_INTERRUPTIBLE;
                        current->timeout = jiffies + 1;
                        schedule();
                }
                sprintf(tmp, "IRQ %d count %d", sp->irq,
-                       kstat.interrupts[sp->irq]);
+                       kstat_irqs(sp->irq));
                debugl1(sp, tmp);
-               if (kstat.interrupts[sp->irq] == sp->counter) {
+               if (kstat_irqs(sp->irq) == sp->counter) {
                        printk(KERN_WARNING
                               "Teles0: IRQ(%d) getting no interrupts during init\n",
                               sp->irq);
index c83a009581ad054a507cab692637eded378b7595..22254604c96fffb88a405734cc33a0b4ac59a8c7 100644 (file)
@@ -801,7 +801,7 @@ initteles3(struct IsdnCardState *sp)
        int loop = 0;
        char tmp[40];
 
-       sp->counter = kstat.interrupts[sp->irq];
+       sp->counter = kstat_irqs(sp->irq);
        sprintf(tmp, "IRQ %d count %d", sp->irq, sp->counter);
        debugl1(sp, tmp);
        clear_pending_ints(sp);
@@ -816,16 +816,16 @@ initteles3(struct IsdnCardState *sp)
                        /* At least 1-3 irqs must happen
                         * (one from HSCX A, one from HSCX B, 3rd from ISAC)
                         */
-                       if (kstat.interrupts[sp->irq] > sp->counter)
+                       if (kstat_irqs(sp->irq) > sp->counter)
                                break;
                        current->state = TASK_INTERRUPTIBLE;
                        current->timeout = jiffies + 1;
                        schedule();
                }
                sprintf(tmp, "IRQ %d count %d loop %d", sp->irq,
-                       kstat.interrupts[sp->irq], loop);
+                       kstat_irqs(sp->irq), loop);
                debugl1(sp, tmp);
-               if (kstat.interrupts[sp->irq] <= sp->counter) {
+               if (kstat_irqs(sp->irq) <= sp->counter) {
                        printk(KERN_WARNING
                               "Teles3: IRQ(%d) getting no interrupts during init\n",
                               sp->irq);
index dbe4dd354737b9bc4600991cad40e23706375751..1ccb67d3262ce8fc21dde439c65629527bc0ebb1 100644 (file)
@@ -68,8 +68,6 @@ void cleanup_module(void)
 #else
 __initfunc(int parport_init(void))
 {
-       struct parport *pb;
-
        if (io[0] == PARPORT_DISABLE) 
                return 1;
 
index efcaf39cdbb50e81a7d61553423779f9c975590d..65d6f8b6b494713fb474979d396d6191a1f23d02 100644 (file)
@@ -482,9 +482,11 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
 /* Note: this is the only limit on the number of cards supported!! */
 static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,};
+#ifdef MODULE
 static int full_duplex[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
 /* A list of all installed Vortex devices, for removing the driver module. */
 static struct device *root_vortex_dev = NULL;
+#endif
 
 #ifdef MODULE
 /* Variables to work-around the Compaq PCI BIOS32 problem. */
index 1b0d3aae2f2b513d1a3e3cc5985ba373659f483e..4e29cb6abc21262e3880ae764f0d34787df04058 100644 (file)
@@ -1250,12 +1250,12 @@ dgrs_found_device(
 ))
 {
        DGRS_PRIV       *priv;
-       int             i;
 
        #ifdef MODULE
        {
                /* Allocate and fill new device structure. */
                int dev_size = sizeof(struct device) + sizeof(DGRS_PRIV);
+               int i;
 
                dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
                memset(dev, 0, dev_size);
index 97d0f27d6578d1d461eeb870e67c764bdca38ed5..f7df41bb52242b1dde5bc7960357cc816ff49caf 100644 (file)
@@ -611,7 +611,7 @@ __initfunc(void lance_probe1(int ioaddr))
                   can watch the LEDs even if the board isn't opened. */
                outw(0x0002, ioaddr+LANCE_ADDR);
                /* set autoselect and clean xmausel */
-               outw(inw(ioaddr+LANCE_BUS_IF) & 0xfffe | 0x0002, ioaddr+LANCE_BUS_IF);
+               outw((inw(ioaddr+LANCE_BUS_IF) & 0xfffe) | 0x0002, ioaddr+LANCE_BUS_IF);
        }
 
        if (lance_debug > 0  &&  did_version++ == 0)
@@ -667,7 +667,7 @@ lance_open(struct device *dev)
                /* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */
                outw(0x0002, ioaddr+LANCE_ADDR);
                /* set autoselect and clean xmausel */
-               outw(inw(ioaddr+LANCE_BUS_IF) & 0xfffe | 0x0002, ioaddr+LANCE_BUS_IF);
+               outw((inw(ioaddr+LANCE_BUS_IF) & 0xfffe) | 0x0002, ioaddr+LANCE_BUS_IF);
        }
 
        if (lance_debug > 1)
index d11e088b780926d026adbc87133fbbab66b62b9d..77e338537518f428cf2c08b721b5dc96acc4c9de 100644 (file)
@@ -1,4 +1,4 @@
-
+/****************************************************************************
 * sdla_fr.c    WANPIPE(tm) Multiprotocol WAN Link Driver. Frame relay module.
 *
 * Author(s):   Gene Kozin      
index 5f1a4d8da25a50813b0d0e1e171d1bbf0b8172f1..092b8500a7bbc4e00602ffcdbcdcdb12b9a2d994 100644 (file)
@@ -5958,7 +5958,7 @@ print_queues (struct Scsi_Host *host) {
                    host->host_no, cmd->pid);
            /* print_dsa does sanity check on address, no need to check */
            else
-               print_dsa (host, le32_to_cpu(((struct NCR53c7x0_cmd *) cmd->host_scribble)-> dsa), "");
+               print_dsa (host, bus_to_virt(le32_to_cpu(((struct NCR53c7x0_cmd *) cmd->host_scribble)-> dsa)), "");
        } else 
            printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n",
                host->host_no, cmd->pid, cmd->target, cmd->lun);
index 36e04de28178ae61370882918cc06d193a177baf..11e0b203a9e526f341f2fd0fc0ff049092a0d407 100644 (file)
@@ -430,6 +430,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_PLUTO),y)
+L_OBJS += pluto.o
+else
+  ifeq ($(CONFIG_SCSI_PLUTO),m)
+  M_OBJS += pluto.o
+  endif
+endif
+
 ifeq ($(CONFIG_SCSI_EATA),y)
 L_OBJS += eata.o
 else
index 6ecc0f1aa33bfb13f81cec9772b528e0a0d1675c..6eccb24c75dbc081a88f22a1d0a6cd12749f838d 100644 (file)
@@ -625,7 +625,7 @@ static inline void NCR5380_all_init (void) {
  */
 
 
-static int probe_irq __initdata;
+static int probe_irq __initdata ;
 __initfunc(static void probe_intr (int irq, void *dev_id, struct pt_regs * regs)) {
     probe_irq = irq;
 };
index e29af7ad8556ac02f80273ad3a4ebaa151b9c9af..d2529b17e0ad8146bf66cbf9142ebfcdfbcf02bd 100644 (file)
@@ -1012,7 +1012,7 @@ static void chip_init()
     outb(SYNC_MODE, SYNCOFF);   /* synchronous mode */  
 }
 
-__initfunc(void calc_port_addr())
+__initfunc(void calc_port_addr(void))
 {
     /* Control Register Set 0 */
     TC_LSB             = (port_base+0x00);
index 667b2148259bf2dd28e6c5d3167f22484c08a80d..ff07954d8c352af5acfa91d254ee075dbc992078 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: advansys.c,v 1997/05/28 00:06:55 bobf Exp bobf $ */
-#define ASC_VERSION "2.8"    /* AdvanSys Driver Version */
+/* $Id: advansys.c,v 1.49 1998/01/22 20:19:25 bobf Exp bobf $ */
+#define ASC_VERSION "3.1D"    /* AdvanSys Driver Version */
 
 /*
  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
  * 
- * Copyright (c) 1995-1997 Advanced System Products, Inc.
+ * Copyright (c) 1995-1998 Advanced System Products, Inc.
  * All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *  http://www.advansys.com/linux.html
  *
  * The latest version of the AdvanSys driver is available at:
- *  ftp://ftp.advansys.com/pub/linux
+ *  ftp://ftp.advansys.com/pub/linux/linux.tgz
  *
  * Please send questions, comments, bug reports to:
- * bobf@advansys.com (Bob Frey)
+ *  bobf@advansys.com (Bob Frey)
  */
 
-
 /*
 
   Documentation for the AdvanSys Driver
@@ -43,7 +42,7 @@
   A. Linux Kernel Testing
 
      This driver has been tested in the following Linux kernels: v1.2.13,
-     v1.3.57, v2.0.30, v2.1.40. These kernel versions are major releases
+     v1.3.57, v2.0.33, v2.1.77. These kernel versions are major releases
      of Linux or the latest Linux kernel versions available when this version
      of the driver was released. The driver should also work in earlier
      versions of the Linux kernel. Beginning with v1.3.58 the AdvanSys driver
   B. Adapters Supported by this Driver
  
      AdvanSys (Advanced System Products, Inc.) manufactures the following
-     Bus-Mastering SCSI-2 Host Adapters for the ISA, EISA, VL, and PCI
-     buses. This Linux driver supports all of these adapters.
+     RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow
+     (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI
+     buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit
+     transfer) SCSI Host Adapters for the PCI bus.
      
      The CDB counts below indicate the number of SCSI CDB (Command
      Descriptor Block) requests that can be stored in the RISC chip
@@ -72,7 +73,7 @@
         ABP930U - Bus-Master PCI Ultra (16 CDB)
         ABP930UA - Bus-Master PCI Ultra (16 CDB)
         ABP960 - Bus-Master PCI MAC/PC (16 CDB) (Footnote 2)
-        ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB)
+        ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) (Footnote 2)
      
      Single Channel Products:
         ABP542 - Bus-Master ISA with floppy (240 CDB)
         ABP940U - Bus-Master PCI Ultra (240 CDB)
         ABP970 - Bus-Master PCI MAC/PC (240 CDB)
         ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB)
+        ABP940UW - Bus-Master PCI Ultra-Wide (240 CDB)
      
-     Dual Channel Products:
+     Multi Channel Products:
         ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
         ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel)
         ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel)
+        ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel)
+        ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel)
      
      Footnotes:
        1. This board has been shipped by HP with the 4020i CD-R drive.
            --- Driver Options
            --- Debugging Header
            --- Asc Library Constants and Macros
+           --- Adv Library Constants and Macros
            --- Driver Constants and Macros
            --- Driver Structures
            --- Driver Data
            --- Loadable Driver Support
            --- Miscellaneous Driver Functions
            --- Functions Required by the Asc Library
+           --- Functions Required by the Adv Library
            --- Tracing and Debugging Functions
            --- Asc Library Functions
+           --- Adv Library Functions
  
      3. The string 'XXX' is used to flag code that needs to be re-written
         or that contains a problem that needs to be addressed.
  
      4. I have stripped comments from and reformatted the source for the
-        Asc Library which is included in this file. I haven't done this
-        to obfuscate the code. Actually I have done this to deobfuscate
-        the code. The Asc Library source can be found under the following
-        headings.
+        Asc Library and Adv Library to reduce the size of this file. This
+        source can be found under the following headings. The Asc Library
+        is used to support Narrow Boards. The Adv Library is used to
+        support Wide Boards.
  
            --- Asc Library Constants and Macros
+           --- Adv Library Constants and Macros
            --- Asc Library Functions
+           --- Adv Library Functions
  
   G. Driver Compile Time Options and Debugging
  
 
         Enabling this option adds tracing functions to the driver and
         the ability to set a driver tracing level at boot time. This
-        option will also symbols not required outside the driver to
+        option will also export symbols not required outside the driver to
         the kernel name space. This option is very useful for debugging
         the driver, but it will add to the size of the driver execution
         image and add overhead to the execution of the driver.
         
         If the driver is loaded at boot time and the LILO Driver Option
         is included in the system, the debug level can be changed by
-        specifying a 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port. The
+        specifying a 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. The
         first three hex digits of the pseudo I/O Port must be set to
         'deb' and the fourth hex digit specifies the debug level: 0 - F.
         The following command line will look for an adapter at 0x330
         I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c
         prevents most level 1 debug messages from being lost.
 
-        this constant for debugging purposes, but for normal use of
-        the driver the constant should not be defined. This option
-        does not add overhead to the driver, but it does add unnecessary
-        symbols to the kernel name space.
      3. ADVANSYS_STATS - Enable statistics (Def: Enabled >= v1.3.0)
  
         Enabling this option adds statistics collection and display
         When ADVANSYS_STATS is not defined the AdvanSys /proc files only
         contain adapter and device configuration information.
 
-
   H. Driver LILO Option
  
      If init/main.c is modified as described in the 'Directions for Adding
 
            insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
 
-     If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_BOARD_SUPPORTED + 1)
+     If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_IOPORT_PROBE + 1)
      I/O Port may be added to specify the driver debug level. Refer to
      the 'Driver Compile Time Options and Debugging' section above for
      more information.
             repeat busy or QUEUE FULL status returned by a device.
          2. Incorporate miscellaneous Asc Library bug fixes.
          3. To allow the driver to work in kernels with broken module
-            support set 'cmd_per_lun' if the driver is compile as a
+            support set 'cmd_per_lun' if the driver is compiled as a
             module. This change affects kernels v1.3.89 to present.
          4. Remove PCI BIOS address from the driver banner. The PCI BIOS
             is relocated by the motherboard BIOS and its new address can
             option is enabled by default.
 
      2.8 (5/26/97):
-         1. Change version number to 2.8, skipping 2.3 through 2.7, in
-            order to synchronize the Linux driver version numbering with
-            other AdvanSys drivers.
-         2. Reformat source files without tabs to give everyone everyone
-            the same view of the file regardless of the tab setting used.
+         1. Change version number to 2.8 to synchronize the Linux driver
+            version numbering with other AdvanSys drivers.
+         2. Reformat source files without tabs to present the same view
+            of the file to everyone regardless of the editor tab setting
+            being used.
          3. Add Asc Library bug fixes.
 
+     3.1A (1/8/98):
+         1. Change version number to 3.1 to indicate that support for
+            Ultra-Wide adapters (ABP-940UW) is included in this release.
+         2. Add Asc Library (Narrow Board) bug fixes.
+         3. Report an underrun condition with the host status byte set
+            to DID_UNDERRUN. Currently DID_UNDERRUN is defined to 0 which
+            causes the underrun condition to be ignored. When Linux defines
+            its own DID_UNDERRUN the constant defined in this file can be
+            removed.
+         4. Add patch to AscWaitTixISRDone().
+         5. Add support for up to 16 different AdvanSys host adapter SCSI
+            channels in one system. This allows four cards with four channels
+            to be used in one system.
+
+     3.1B (1/9/98):
+         1. Handle that PCI register base addresses are not always page
+            aligned even though ioremap() requires that the address argument
+            be page aligned.
+
+     3.1C (1/10/98):
+         1. Update latest BIOS version to 3.1E.
+         2. Don't set microcode SDTR variable at initialization. Instead
+            wait until device capabilities have been detected from an Inquiry
+            command.
+
+     3.1D (1/21/98):
+         1. Improve performance when the driver is compiled as module by
+            allowing up to 64 scatter-gather elements instead of 8.
+
   J. Known Problems or Issues
 
          1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around
      Thomas E Zerucha <zerucha@shell.portal.com> pointed out a bug
      in advansys_biosparam() which was fixed in the 1.3 release.
 
-     Erik Ratcliffe <erik@caldera.com> has done a lot of testing of
-     the AdvanSys driver in the Caldera releases.
+     Erik Ratcliffe <erik@caldera.com> has done testing of the
+     AdvanSys driver in the Caldera releases.
+
+     Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to
+     AscWaitTixISRDone() which he found necessary to make the
+     driver work with a SCSI-1 disk.
+
+     Mark Moran <mmoran@mmoran.com> has helped test Ultra-Wide
+     support in the 3.1A driver.
 
   L. AdvanSys Contact Information
  
      Tech Support:           1-800-525-7440/1-408-467-2930
      BBS:                    1-408-383-9540 (14400,N,8,1)
      Interactive FAX:        1-408-383-9753
-     Customer Direct Sales:  1-800-883-1099/1-408-383-5777
+     Customer Direct Sales:  1-800-525-7443/1-408-383-5777
      Tech Support E-Mail:    support@advansys.com
      FTP Site:               ftp.advansys.com (login: anonymous)
      Web Site:               http://www.advansys.com
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/malloc.h>
+#include <linux/mm.h>
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
 #include <linux/proc_fs.h>
 #endif /* version >= v1.3.0 */
 #include "sd.h"
 #include "advansys.h"
 
+/*
+ * If Linux eventually defines a DID_UNDERRUN, the constant here can be
+ * removed. The current value of zero for DID_UNDERRUN results in underrun
+ * conditions being ignored.
+ */
+#define DID_UNDERRUN 0
+
 
 /*
  * --- Driver Options
 
 /*
  * Because of no /proc to display them, statistics are disabled
- * for version prior to v1.3.0.
+ * for versions prior to v1.3.0.
  */
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
 #undef ADVANSYS_STATS /* Disable statistics */
 
 #define ASC_LIB_VERSION_MAJOR  1
 #define ASC_LIB_VERSION_MINOR  22
-#define ASC_LIB_SERIAL_NUMBER  105
+#define ASC_LIB_SERIAL_NUMBER  111
 
 typedef unsigned char uchar;
 
@@ -769,27 +816,6 @@ typedef unsigned char uchar;
 #define ASC_MAX_SG_QUEUE    7
 #define ASC_MAX_SG_LIST     SG_ALL
 
-#define CC_CLEAR_LRAM_SRB_PTR           FALSE
-#define CC_VERIFY_LRAM_COPY             FALSE
-#define CC_DEBUG_SG_LIST                FALSE
-#define CC_FAST_STRING_IO               FALSE
-#define CC_WRITE_IO_COUNT               FALSE
-#define CC_CLEAR_DMA_REMAIN             FALSE
-#define CC_DISABLE_PCI_PARITY_INT       TRUE
-#define CC_LITTLE_ENDIAN_HOST           TRUE
-#define CC_STRUCT_ALIGNED               TRUE
-#define CC_MEMORY_MAPPED_IO             FALSE
-#define CC_INCLUDE_EEP_CONFIG           TRUE
-#define CC_PCI_ULTRA                    TRUE
-#define CC_ASC_SCSI_Q_USRDEF            FALSE
-#define CC_ASC_SCSI_REQ_Q_USRDEF        FALSE
-#define CC_ASCISR_CHECK_INT_PENDING     TRUE
-#define CC_CHK_FIX_EEP_CONTENT          TRUE
-#define CC_INCLUDE_EEP_CONFIG           TRUE
-#define CC_PLEXTOR_VL                   FALSE
-#define CC_TMP_USE_EEP_SDTR             FALSE
-#define CC_CHK_COND_REDO_SDTR           TRUE
-
 #define ASC_CS_TYPE  unsigned short
 #ifndef asc_ptr_type
 #define asc_ptr_type
@@ -840,27 +866,6 @@ typedef unsigned char uchar;
 #define ASC_MAX_ISA_DMA_COUNT   (0x00FFFFFFL)
 #define ASC_MAX_EISA_DMA_ADDR   (0x07FFFFFFL)
 #define ASC_MAX_EISA_DMA_COUNT  (0x07FFFFFFL)
-#if !CC_STRUCT_ALIGNED
-#define DvcGetQinfo(iop_base, s_addr, outbuf, words)  \
-AscMemWordCopyFromLram(iop_base, s_addr, outbuf, words)
-#define DvcPutScsiQ(iop_base, s_addr, outbuf, words) \
-AscMemWordCopyToLram(iop_base, s_addr, outbuf, words)
-#endif
-#ifdef ASC_CHIP_VERSION
-#endif
-#if CC_MEMORY_MAPPED_IO
-#define inp(port)            *((uchar *)(port))
-#define outp(port, data)     *((uchar *)(port)) = (uchar)(data)
-#if CC_LITTLE_ENDIAN_HOST
-#define inpw(port)              *((ushort *)(port))
-#define outpw(port, data)       *((ushort *)(port)) = (ushort)(data)
-#else
-#define inpw(port)             EndianSwap16Bit((*((ushort *)(port))))
-#define outpw(port, data)      *((ushort *)(port)) = EndianSwap16Bit((ushort)(data))
-#define inpw_noswap(port)          *((ushort *)(port))
-#define outpw_noswap(port, data)   *((ushort *)(port)) = (ushort)(data)
-#endif
-#endif
 #ifndef inpw_noswap
 #define inpw_noswap(port)         inpw(port)
 #endif
@@ -901,6 +906,7 @@ AscMemWordCopyToLram(iop_base, s_addr, outbuf, words)
 #define ASC_MAX_SENSE_LEN   32
 #define ASC_MIN_SENSE_LEN   14
 #define ASC_MAX_CDB_LEN     12
+#define ASC_SCSI_RESET_HOLD_TIME_US  60
 #define SCSICMD_TestUnitReady     0x00
 #define SCSICMD_Rewind            0x01
 #define SCSICMD_Rezero            0x01
@@ -963,6 +969,7 @@ AscMemWordCopyToLram(iop_base, s_addr, outbuf, words)
 #define SCSI_SENKEY_VOL_OVERFLOW  0x0D
 #define SCSI_SENKEY_MISCOMP       0x0E
 #define SCSI_SENKEY_RESERVED      0x0F
+#define SCSI_ASC_NOMEDIA          0x3A
 #define ASC_SRB_HOST(x)  ((uchar)((uchar)(x) >> 4))
 #define ASC_SRB_TID(x)   ((uchar)((uchar)(x) & (uchar)0x0F))
 #define ASC_SRB_LUN(x)   ((uchar)((uint)(x) >> 13))
@@ -1005,48 +1012,22 @@ AscMemWordCopyToLram(iop_base, s_addr, outbuf, words)
 #define M2_QTAG_MSG_ORDERED     0x22
 #define M2_IGNORE_WIDE_RESIDUE  0x23
 
-#if CC_LITTLE_ENDIAN_HOST
 typedef struct {
     uchar               peri_dvc_type:5;
     uchar               peri_qualifier:3;
 } ASC_SCSI_INQ0;
 
-#else
-typedef struct {
-    uchar               peri_qualifier:3;
-    uchar               peri_dvc_type:5;
-} ASC_SCSI_INQ0;
-
-#endif
-#if CC_LITTLE_ENDIAN_HOST
 typedef struct {
     uchar               dvc_type_modifier:7;
     uchar               rmb:1;
 } ASC_SCSI_INQ1;
 
-#else
-typedef struct {
-    uchar               rmb:1;
-    uchar               dvc_type_modifier:7;
-} ASC_SCSI_INQ1;
-
-#endif
-#if CC_LITTLE_ENDIAN_HOST
 typedef struct {
     uchar               ansi_apr_ver:3;
     uchar               ecma_ver:3;
     uchar               iso_ver:2;
 } ASC_SCSI_INQ2;
 
-#else
-typedef struct {
-    uchar               iso_ver:2;
-    uchar               ecma_ver:3;
-    uchar               ansi_apr_ver:3;
-} ASC_SCSI_INQ2;
-
-#endif
-#if CC_LITTLE_ENDIAN_HOST
 typedef struct {
     uchar               rsp_data_fmt:4;
     uchar               res:2;
@@ -1054,16 +1035,6 @@ typedef struct {
     uchar               aenc:1;
 } ASC_SCSI_INQ3;
 
-#else
-typedef struct {
-    uchar               aenc:1;
-    uchar               TemIOP:1;
-    uchar               res:2;
-    uchar               rsp_data_fmt:4;
-} ASC_SCSI_INQ3;
-
-#endif
-#if CC_LITTLE_ENDIAN_HOST
 typedef struct {
     uchar               StfRe:1;
     uchar               CmdQue:1;
@@ -1075,19 +1046,6 @@ typedef struct {
     uchar               RelAdr:1;
 } ASC_SCSI_INQ7;
 
-#else
-typedef struct {
-    uchar               RelAdr:1;
-    uchar               WBus32:1;
-    uchar               WBus16:1;
-    uchar               Sync:1;
-    uchar               Linked:1;
-    uchar               Reserved:1;
-    uchar               CmdQue:1;
-    uchar               StfRe:1;
-} ASC_SCSI_INQ7;
-
-#endif
 typedef struct {
     ASC_SCSI_INQ0       byte0;
     ASC_SCSI_INQ1       byte1;
@@ -1102,7 +1060,6 @@ typedef struct {
     uchar               product_rev_level[4];
 } ASC_SCSI_INQUIRY;
 
-#if CC_LITTLE_ENDIAN_HOST
 typedef struct asc_req_sense {
     uchar               err_code:7;
     uchar               info_valid:1;
@@ -1126,31 +1083,6 @@ typedef struct asc_req_sense {
     uchar               info2[4];
 } ASC_REQ_SENSE;
 
-#else
-typedef struct asc_req_sense {
-    uchar               info_valid:1;
-    uchar               err_code:7;
-    uchar               segment_no;
-    uchar               file_mark:1;
-    uchar               sense_EOM:1;
-    uchar               sense_ILI:1;
-    uchar               reserved_bit:1;
-    uchar               sense_key:4;
-    uchar               info1[4];
-    uchar               add_sense_len;
-    uchar               cmd_sp_info[4];
-    uchar               asc;
-    uchar               ascq;
-    uchar               fruc;
-    uchar               sks_valid:1;
-    uchar               sks_byte0:7;
-    uchar               sks_bytes[2];
-    uchar               notused[2];
-    uchar               ex_sense_code;
-    uchar               info2[4];
-} ASC_REQ_SENSE;
-
-#endif
 #define ASC_SG_LIST_PER_Q   7
 #define QS_FREE        0x00
 #define QS_READY       0x01
@@ -1348,9 +1280,6 @@ typedef struct asc_scsi_q {
     ASC_SCSIQ_2         q2;
     uchar               *cdbptr;
     ASC_SG_HEAD         *sg_head;
-#if CC_ASC_SCSI_Q_USRDEF
-    ASC_SCSI_Q_USR      usr;
-#endif
 } ASC_SCSI_Q;
 
 typedef struct asc_scsi_req_q {
@@ -1362,9 +1291,6 @@ typedef struct asc_scsi_req_q {
     ASC_SCSIQ_3         r3;
     uchar               cdb[ASC_MAX_CDB_LEN];
     uchar               sense[ASC_MIN_SENSE_LEN];
-#if CC_ASC_SCSI_REQ_Q_USRDEF
-    ASC_SCSI_REQ_Q_USR  usr;
-#endif
 } ASC_SCSI_REQ_Q;
 
 typedef struct asc_scsi_bios_req_q {
@@ -1569,9 +1495,10 @@ typedef struct asc_dvc_cfg {
     ushort              mcode_date;
     ushort              mcode_version;
     uchar               max_tag_qng[ASC_MAX_TID + 1];
-    uchar       *overrun_buf;
+    uchar               *overrun_buf;
     uchar               sdtr_period_offset[ASC_MAX_TID + 1];
     ushort              pci_slot_info;
+    uchar               adapter_info[6];
 } ASC_DVC_CFG;
 
 #define ASC_DEF_DVC_CNTL       0xFFFF
@@ -1856,7 +1783,7 @@ typedef struct asceep_config {
 #define ASC_CFG0_SCSI_PARITY_ON 0x0800
 #define ASC_CFG1_SCSI_TARGET_ON 0x0080
 #define ASC_CFG1_LRAM_8BITS_ON  0x0800
-#define ASC_CFG_MSW_CLR_MASK    0x30C0
+#define ASC_CFG_MSW_CLR_MASK    0x3080
 #define CSW_TEST1             (ASC_CS_TYPE)0x8000
 #define CSW_AUTO_CONFIG       (ASC_CS_TYPE)0x4000
 #define CSW_RESERVED1         (ASC_CS_TYPE)0x2000
@@ -2000,7 +1927,7 @@ STATIC void      AscAckInterrupt(PortAddr);
 STATIC void      AscDisableInterrupt(PortAddr);
 STATIC void      AscEnableInterrupt(PortAddr);
 STATIC void      AscSetBank(PortAddr, uchar);
-STATIC int       AscResetChipAndScsiBus(PortAddr);
+STATIC int       AscResetChipAndScsiBus(ASC_DVC_VAR *);
 STATIC ushort    AscGetIsaDmaChannel(PortAddr);
 STATIC ushort    AscSetIsaDmaChannel(PortAddr, ushort);
 STATIC uchar     AscSetIsaDmaSpeed(PortAddr, uchar);
@@ -2143,8896 +2070,13784 @@ STATIC ulong     AscGetMaxDmaCount(ushort);
 
 
 /*
- * --- Driver Constants and Macros
+ * --- Adv Library Constants and Macros
  */
 
-#define ASC_NUM_BOARD_SUPPORTED 4
-#define ASC_NUM_BUS             4
+#define ADV_LIB_VERSION_MAJOR  3
+#define ADV_LIB_VERSION_MINOR  34
 
-/* Reference Scsi_Host hostdata */
-#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
+/* d_os_dep.h */
+#define ADV_OS_LINUX
 
-/* asc_board_t flags */
-#define ASC_HOST_IN_RESET       0x01
-#define ASC_HOST_IN_ABORT       0x02
+/*
+ * Define Adv Library required special types.
+ */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+#define AdvPortAddr  unsigned short     /* I/O Port address size */
+#else /* version >= v1,3,0 */
+#define AdvPortAddr  unsigned long      /* Virtual memory address size */
+#endif /* version >= v1,3,0 */
 
-#define NO_ISA_DMA              0xff        /* No ISA DMA Channel Used */
+/*
+ * Define Adv Library required memory access macros.
+ */
+#define ADV_MEM_READB(addr) readb(addr)
+#define ADV_MEM_READW(addr) readw(addr)
+#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
+#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
 
 /*
- * If the Linux kernel version supports throwing away initialization code
- * and data after loading, define macros for this purpose. These macros
- * are not used when the driver is built as a module, cf. linux/init.h.
+ * The I/O memory mapping function names changed in 2.1.X.
  */
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,23)
-#define ASC_INITFUNC(func)      __initfunc(func)
-#define ASC_INITDATA            __initdata
-#define ASC_INIT                __init
-#else /* version >= v2.1.23 */
-#define ASC_INITFUNC(func)      func
-#define ASC_INITDATA
-#define ASC_INIT
-#endif /* version >= v2.1.23 */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+#define ioremap vremap
+#define iounmap vfree
+#endif /* version < v2.1.0 */
 
-#define ASC_INFO_SIZE           128            /* advansys_info() line size */
+/*
+ * Define total number of simultaneous maximum element scatter-gather
+ * requests, i.e. ADV_TOT_SG_LIST * ADV_MAX_SG_LIST is the total number
+ * of simultaneous scatter-gather elements supported per wide adapter.
+ */
+#define ADV_TOT_SG_LIST         64
 
-/* /proc/scsi/advansys/[0...] related definitions */
-#define ASC_PRTBUF_SIZE         2048
-#define ASC_PRTLINE_SIZE        160
+/*
+ * Define Adv Library required per request scatter-gather element limit.
+ */
+#define ADV_MAX_SG_LIST         64
 
-#define ASC_PRT_NEXT() \
-    if (cp) { \
-        totlen += len; \
-        leftlen -= len; \
-        if (leftlen == 0) { \
-            return totlen; \
-        } \
-        cp += len; \
-    }
+/*
+ * Scatter-Gather Definitions per request.
+ *
+ * Because SG block memory is allocated in virtual memory but is
+ * referenced by the microcode as physical memory, we need to do
+ * calculations to insure there will be enough physically contiguous
+ * memory to support ADV_MAX_SG_LIST SG entries.
+ */
 
-#define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
+/* Number of SG blocks needed. */
+#define ADV_NUM_SG_BLOCK \
+     ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
 
-/* Asc Library return codes */
-#define ASC_TRUE        1
-#define ASC_FALSE       0
-#define ASC_NOERROR     1
-#define ASC_BUSY        0
-#define ASC_ERROR       (-1)
+/* Total contiguous memory needed for SG blocks. */
+#define ADV_SG_TOTAL_MEM_SIZE \
+    (sizeof(ADV_SG_BLOCK) *  ADV_NUM_SG_BLOCK)
 
-/* Scsi_Cmnd function return codes */
-#define STATUS_BYTE(byte)   (byte)
-#define MSG_BYTE(byte)      ((byte) << 8)
-#define HOST_BYTE(byte)     ((byte) << 16)
-#define DRIVER_BYTE(byte)   ((byte) << 24)
+#define ASC_PAGE_SIZE PAGE_SIZE
 
 /*
- * The following definitions and macros are OS independent interfaces to
- * the queue functions:
- *  REQ - SCSI request structure
- *  REQP - pointer to SCSI request structure
- *  REQPTID(reqp) - reqp's target id
- *  REQPNEXT(reqp) - reqp's next pointer
- *  REQPNEXTP(reqp) - pointer to reqp's next pointer
- *  REQPTIME(reqp) - reqp's time stamp value
- *  REQTIMESTAMP() - system time stamp value
+ * Number of page crossings possible for the total contiguous virtual memory
+ * needed for SG blocks.
+ *
+ * We need to allocate this many additional SG blocks in virtual memory to
+ * insure there will be space for ADV_NUM_SG_BLOCK physically contiguous
+ * scatter-gather blocks.
  */
-typedef Scsi_Cmnd            REQ, *REQP;
-#define REQPNEXT(reqp)        ((REQP) ((reqp)->host_scribble))
-#define REQPNEXTP(reqp)        ((REQP *) &((reqp)->host_scribble))
-#define REQPTID(reqp)        ((reqp)->target)
-#define REQPTIME(reqp)        ((reqp)->SCp.this_residual)
-#define REQTIMESTAMP()        (jiffies)
+#define ADV_NUM_PAGE_CROSSING \
+    ((ADV_SG_TOTAL_MEM_SIZE + (ASC_PAGE_SIZE - 1))/ASC_PAGE_SIZE)
 
-#define REQTIMESTAT(function, ascq, reqp, tid) \
-{ \
-    /*
-     * If the request time stamp is less than the system time stamp, then \
-     * maybe the system time stamp wrapped. Set the request time to zero.\
-     */ \
-    if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
-        REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
-    } else { \
-        /* Indicate an error occurred with the assertion. */ \
-        ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
-        REQPTIME(reqp) = 0; \
-    } \
-    /* Handle first minimum time case without external initialization. */ \
-    if (((ascq)->q_tot_cnt[tid] == 1) ||  \
-        (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
-            (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
-            ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
-                (function), (tid), (ascq)->q_min_tim[tid]); \
-        } \
-    if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
-        (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
-        ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
-            (function), tid, (ascq)->q_max_tim[tid]); \
-    } \
-    (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
-    /* Reset the time stamp field. */ \
-    REQPTIME(reqp) = 0; \
-}
+/*
+ * Define Adv Library Assertion Macro.
+ */
 
-/* asc_enqueue() flags */
-#define ASC_FRONT        1
-#define ASC_BACK        2
+#define ADV_ASSERT(a) ASC_ASSERT(a)
 
-/* asc_dequeue_list() argument */
-#define ASC_TID_ALL        (-1)
+/* a_condor.h */
+#define ADV_PCI_VENDOR_ID               0x10CD
+#define ADV_PCI_DEVICE_ID_REV_A         0x2300
 
-/* Return non-zero, if the queue is empty. */
-#define ASC_QUEUE_EMPTY(ascq)    ((ascq)->q_tidmask == 0)
+#define ASC_EEP_DVC_CFG_BEGIN           (0x00)
+#define ASC_EEP_DVC_CFG_END             (0x15)
+#define ASC_EEP_DVC_CTL_BEGIN           (0x16)  /* location of OEM name */
+#define ASC_EEP_MAX_WORD_ADDR           (0x1E)
 
-/* PCI configuration declarations */
+#define ASC_EEP_DELAY_MS                100
 
-#define PCI_BASE_CLASS_PREDEFINED               0x00
-#define PCI_BASE_CLASS_MASS_STORAGE             0x01
-#define PCI_BASE_CLASS_NETWORK                  0x02
-#define PCI_BASE_CLASS_DISPLAY                  0x03
-#define PCI_BASE_CLASS_MULTIMEDIA               0x04
-#define PCI_BASE_CLASS_MEMORY_CONTROLLER        0x05
-#define PCI_BASE_CLASS_BRIDGE_DEVICE            0x06
+/*
+ * EEPROM bits reference by the RISC after initialization.
+ */
+#define ADV_EEPROM_BIG_ENDIAN          0x8000   /* EEPROM Bit 15 */
+#define ADV_EEPROM_BIOS_ENABLE         0x4000   /* EEPROM Bit 14 */
+#define ADV_EEPROM_TERM_POL            0x2000   /* EEPROM Bit 13 */
 
-/* MASS STORAGE */
-#define PCI_SUB_CLASS_SCSI_CONTROLLER           0x00
-#define PCI_SUB_CLASS_IDE_CONTROLLER            0x01
-#define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER    0x02
-#define PCI_SUB_CLASS_IPI_BUS_CONTROLLER        0x03
-#define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER     0x80
+/*
+ * EEPROM configuration format
+ *
+ * Field naming convention: 
+ *
+ *  *_enable indicates the field enables or disables the feature. The
+ *  value is never reset.
+ *
+ *  *_able indicates both whether a feature should be enabled or disabled
+ *  and whether a device isi capable of the feature. At initialization
+ *  this field may be set, but later if a device is found to be incapable
+ *  of the feature, the field is cleared.
+ *
+ * Default values are maintained in a_init.c in the structure
+ * Default_EEPROM_Config.
+ */
+typedef struct adveep_config
+{                              
+                                /* Word Offset, Description */
+
+  ushort cfg_lsw;               /* 00 power up initialization */
+                                /*  bit 13 set - Term Polarity Control */
+                                /*  bit 14 set - BIOS Enable */
+                                /*  bit 15 set - Big Endian Mode */
+  ushort cfg_msw;               /* 01 unused      */
+  ushort disc_enable;           /* 02 disconnect enable */         
+  ushort wdtr_able;             /* 03 Wide DTR able */
+  ushort sdtr_able;             /* 04 Synchronous DTR able */
+  ushort start_motor;           /* 05 send start up motor */      
+  ushort tagqng_able;           /* 06 tag queuing able */
+  ushort bios_scan;             /* 07 BIOS device control */   
+  ushort scam_tolerant;         /* 08 no scam */  
+  uchar  adapter_scsi_id;       /* 09 Host Adapter ID */
+  uchar  bios_boot_delay;       /*    power up wait */
+  uchar  scsi_reset_delay;      /* 10 reset delay */
+  uchar  bios_id_lun;           /*    first boot device scsi id & lun */
+                                /*    high nibble is lun */  
+                                /*    low nibble is scsi id */
+
+  uchar  termination;           /* 11 0 - automatic */
+                                /*    1 - low off / high off */
+                                /*    2 - low off / high on */
+                                /*    3 - low on  / high on */
+                                /*    There is no low on  / high off */
+
+  uchar  reserved1;             /*    reserved byte (not used) */                                  
+
+  ushort bios_ctrl;             /* 12 BIOS control bits */
+                                /*  bit 0  set: BIOS don't act as initiator. */
+                                /*  bit 1  set: BIOS > 1 GB support */
+                                /*  bit 2  set: BIOS > 2 Disk Support */
+                                /*  bit 3  set: BIOS don't support removables */
+                                /*  bit 4  set: BIOS support bootable CD */
+                                /*  bit 5  set: */
+                                /*  bit 6  set: BIOS support multiple LUNs */
+                                /*  bit 7  set: BIOS display of message */
+                                /*  bit 8  set: */
+                                /*  bit 9  set: Reset SCSI bus during init. */
+                                /*  bit 10 set: */
+                                /*  bit 11 set: No verbose initialization. */
+                                /*  bit 12 set: SCSI parity enabled */
+                                /*  bit 13 set: */
+                                /*  bit 14 set: */
+                                /*  bit 15 set: */
+  ushort  ultra_able;           /* 13 ULTRA speed able */ 
+  ushort  reserved2;            /* 14 reserved */
+  uchar   max_host_qng;         /* 15 maximum host queuing */
+  uchar   max_dvc_qng;          /*    maximum per device queuing */
+  ushort  dvc_cntl;             /* 16 control bit for driver */
+  ushort  bug_fix;              /* 17 control bit for bug fix */
+  ushort  serial_number_word1;  /* 18 Board serial number word 1 */  
+  ushort  serial_number_word2;  /* 19 Board serial number word 2 */  
+  ushort  serial_number_word3;  /* 20 Board serial number word 3 */
+  ushort  check_sum;            /* 21 EEP check sum */
+  uchar   oem_name[16];         /* 22 OEM name */
+  ushort  dvc_err_code;         /* 30 last device driver error code */
+  ushort  adv_err_code;         /* 31 last uc and Adv Lib error code */
+  ushort  adv_err_addr;         /* 32 last uc error address */
+  ushort  saved_dvc_err_code;   /* 33 saved last dev. driver error code   */
+  ushort  saved_adv_err_code;   /* 34 saved last uc and Adv Lib error code */
+  ushort  saved_adv_err_addr;   /* 35 saved last uc error address         */  
+  ushort  num_of_err;           /* 36 number of error */
+} ADVEEP_CONFIG; 
 
-/* NETWORK CONTROLLER */
-#define PCI_SUB_CLASS_ETHERNET_CONTROLLER       0x00
-#define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER     0x01
-#define PCI_SUB_CLASS_FDDI_CONTROLLER           0x02
-#define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER  0x80
+/*
+ * EEPROM Commands
+ */
+#define ASC_EEP_CMD_DONE             0x0200
+#define ASC_EEP_CMD_DONE_ERR         0x0001
+
+/* cfg_word */
+#define EEP_CFG_WORD_BIG_ENDIAN      0x8000
+
+/* bios_ctrl */
+#define BIOS_CTRL_BIOS               0x0001
+#define BIOS_CTRL_EXTENDED_XLAT      0x0002
+#define BIOS_CTRL_GT_2_DISK          0x0004
+#define BIOS_CTRL_BIOS_REMOVABLE     0x0008
+#define BIOS_CTRL_BOOTABLE_CD        0x0010
+#define BIOS_CTRL_MULTIPLE_LUN       0x0040
+#define BIOS_CTRL_DISPLAY_MSG        0x0080
+#define BIOS_CTRL_NO_SCAM            0x0100
+#define BIOS_CTRL_RESET_SCSI_BUS     0x0200
+#define BIOS_CTRL_INIT_VERBOSE       0x0800
+#define BIOS_CTRL_SCSI_PARITY        0x1000
 
-/* DISPLAY CONTROLLER */
-#define PCI_SUB_CLASS_VGA_CONTROLLER            0x00
-#define PCI_SUB_CLASS_XGA_CONTROLLER            0x01
-#define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER  0x80
+/*
+ * ASC 3550 Internal Memory Size - 8KB
+ */
+#define ADV_CONDOR_MEMSIZE   0x2000     /* 8 KB Internal Memory */
 
-/* MULTIMEDIA CONTROLLER */
-#define PCI_SUB_CLASS_VIDEO_DEVICE              0x00
-#define PCI_SUB_CLASS_AUDIO_DEVICE              0x01
-#define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE   0x80
+/*
+ * ASC 3550 I/O Length - 64 bytes
+ */
+#define ADV_CONDOR_IOLEN     0x40       /* I/O Port Range in bytes */
 
-/* MEMORY CONTROLLER */
-#define PCI_SUB_CLASS_RAM_CONTROLLER            0x00
-#define PCI_SUB_CLASS_FLASH_CONTROLLER          0x01
-#define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER   0x80
+/*
+ * Byte I/O register address from base of 'iop_base'.
+ */
+#define IOPB_INTR_STATUS_REG    0x00
+#define IOPB_CHIP_ID_1          0x01
+#define IOPB_INTR_ENABLES       0x02
+#define IOPB_CHIP_TYPE_REV      0x03
+#define IOPB_RES_ADDR_4         0x04
+#define IOPB_RES_ADDR_5         0x05
+#define IOPB_RAM_DATA           0x06
+#define IOPB_RES_ADDR_7         0x07
+#define IOPB_FLAG_REG           0x08
+#define IOPB_RES_ADDR_9         0x09
+#define IOPB_RISC_CSR           0x0A
+#define IOPB_RES_ADDR_B         0x0B
+#define IOPB_RES_ADDR_C         0x0C
+#define IOPB_RES_ADDR_D         0x0D
+#define IOPB_RES_ADDR_E         0x0E
+#define IOPB_RES_ADDR_F         0x0F
+#define IOPB_MEM_CFG            0x10
+#define IOPB_RES_ADDR_11        0x11
+#define IOPB_RES_ADDR_12        0x12
+#define IOPB_RES_ADDR_13        0x13
+#define IOPB_FLASH_PAGE         0x14
+#define IOPB_RES_ADDR_15        0x15
+#define IOPB_RES_ADDR_16        0x16
+#define IOPB_RES_ADDR_17        0x17
+#define IOPB_FLASH_DATA         0x18
+#define IOPB_RES_ADDR_19        0x19
+#define IOPB_RES_ADDR_1A        0x1A
+#define IOPB_RES_ADDR_1B        0x1B
+#define IOPB_RES_ADDR_1C        0x1C
+#define IOPB_RES_ADDR_1D        0x1D
+#define IOPB_RES_ADDR_1E        0x1E
+#define IOPB_RES_ADDR_1F        0x1F
+#define IOPB_DMA_CFG0           0x20
+#define IOPB_DMA_CFG1           0x21
+#define IOPB_TICKLE             0x22
+#define IOPB_DMA_REG_WR         0x23
+#define IOPB_SDMA_STATUS        0x24
+#define IOPB_SCSI_BYTE_CNT      0x25
+#define IOPB_HOST_BYTE_CNT      0x26
+#define IOPB_BYTE_LEFT_TO_XFER  0x27
+#define IOPB_BYTE_TO_XFER_0     0x28
+#define IOPB_BYTE_TO_XFER_1     0x29
+#define IOPB_BYTE_TO_XFER_2     0x2A
+#define IOPB_BYTE_TO_XFER_3     0x2B
+#define IOPB_ACC_GRP            0x2C
+#define IOPB_RES_ADDR_2D        0x2D
+#define IOPB_DEV_ID             0x2E
+#define IOPB_RES_ADDR_2F        0x2F
+#define IOPB_SCSI_DATA          0x30
+#define IOPB_RES_ADDR_31        0x31
+#define IOPB_RES_ADDR_32        0x32
+#define IOPB_SCSI_DATA_HSHK     0x33
+#define IOPB_SCSI_CTRL          0x34
+#define IOPB_RES_ADDR_35        0x35
+#define IOPB_RES_ADDR_36        0x36
+#define IOPB_RES_ADDR_37        0x37
+#define IOPB_RES_ADDR_38        0x38
+#define IOPB_RES_ADDR_39        0x39
+#define IOPB_RES_ADDR_3A        0x3A
+#define IOPB_RES_ADDR_3B        0x3B
+#define IOPB_RFIFO_CNT          0x3C
+#define IOPB_RES_ADDR_3D        0x3D
+#define IOPB_RES_ADDR_3E        0x3E
+#define IOPB_RES_ADDR_3F        0x3F
 
-/* BRIDGE CONTROLLER */
-#define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER    0x00
-#define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER     0x01
-#define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER    0x02
-#define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER      0x03
-#define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER    0x04
-#define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER  0x05
-#define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER   0x80
+/*
+ * Word I/O register address from base of 'iop_base'.
+ */
+#define IOPW_CHIP_ID_0          0x00  /* CID0  */
+#define IOPW_CTRL_REG           0x02  /* CC    */
+#define IOPW_RAM_ADDR           0x04  /* LA    */
+#define IOPW_RAM_DATA           0x06  /* LD    */
+#define IOPW_RES_ADDR_08        0x08
+#define IOPW_RISC_CSR           0x0A  /* CSR   */
+#define IOPW_SCSI_CFG0          0x0C  /* CFG0  */
+#define IOPW_SCSI_CFG1          0x0E  /* CFG1  */
+#define IOPW_RES_ADDR_10        0x10
+#define IOPW_SEL_MASK           0x12  /* SM    */
+#define IOPW_RES_ADDR_14        0x14
+#define IOPW_FLASH_ADDR         0x16  /* FA    */
+#define IOPW_RES_ADDR_18        0x18
+#define IOPW_EE_CMD             0x1A  /* EC    */
+#define IOPW_EE_DATA            0x1C  /* ED    */
+#define IOPW_SFIFO_CNT          0x1E  /* SFC   */
+#define IOPW_RES_ADDR_20        0x20
+#define IOPW_Q_BASE             0x22  /* QB    */
+#define IOPW_QP                 0x24  /* QP    */
+#define IOPW_IX                 0x26  /* IX    */
+#define IOPW_SP                 0x28  /* SP    */
+#define IOPW_PC                 0x2A  /* PC    */
+#define IOPW_RES_ADDR_2C        0x2C
+#define IOPW_RES_ADDR_2E        0x2E
+#define IOPW_SCSI_DATA          0x30  /* SD    */
+#define IOPW_SCSI_DATA_HSHK     0x32  /* SDH   */
+#define IOPW_SCSI_CTRL          0x34  /* SC    */
+#define IOPW_HSHK_CFG           0x36  /* HCFG  */
+#define IOPW_SXFR_STATUS        0x36  /* SXS   */
+#define IOPW_SXFR_CNTL          0x38  /* SXL   */
+#define IOPW_SXFR_CNTH          0x3A  /* SXH   */
+#define IOPW_RES_ADDR_3C        0x3C
+#define IOPW_RFIFO_DATA         0x3E  /* RFD   */
 
-#define PCI_MAX_SLOT            0x1F
-#define PCI_MAX_BUS             0xFF
-#define PCI_IOADDRESS_MASK      0xFFFE
-#define ASC_PCI_VENDORID        0x10CD
-#define ASC_PCI_DEVICE_ID_1100  0x1100
-#define ASC_PCI_DEVICE_ID_1200  0x1200
-#define ASC_PCI_DEVICE_ID_1300  0x1300
+/*
+ * Doubleword I/O register address from base of 'iop_base'.
+ */
+#define IOPDW_RES_ADDR_0         0x00
+#define IOPDW_RAM_DATA           0x04
+#define IOPDW_RES_ADDR_8         0x08
+#define IOPDW_RES_ADDR_C         0x0C
+#define IOPDW_RES_ADDR_10        0x10
+#define IOPDW_RES_ADDR_14        0x14
+#define IOPDW_RES_ADDR_18        0x18
+#define IOPDW_RES_ADDR_1C        0x1C
+#define IOPDW_SDMA_ADDR0         0x20
+#define IOPDW_SDMA_ADDR1         0x24
+#define IOPDW_SDMA_COUNT         0x28
+#define IOPDW_SDMA_ERROR         0x2C
+#define IOPDW_RDMA_ADDR0         0x30
+#define IOPDW_RDMA_ADDR1         0x34
+#define IOPDW_RDMA_COUNT         0x38
+#define IOPDW_RDMA_ERROR         0x3C
+
+#define ADV_CHIP_ID_BYTE         0x25
+#define ADV_CHIP_ID_WORD         0x04C1
+
+#define ADV_SC_SCSI_BUS_RESET    0x2000
+
+#define ADV_INTR_ENABLE_HOST_INTR                   0x01
+#define ADV_INTR_ENABLE_SEL_INTR                    0x02
+#define ADV_INTR_ENABLE_DPR_INTR                    0x04
+#define ADV_INTR_ENABLE_RTA_INTR                    0x08
+#define ADV_INTR_ENABLE_RMA_INTR                    0x10
+#define ADV_INTR_ENABLE_RST_INTR                    0x20
+#define ADV_INTR_ENABLE_DPE_INTR                    0x40
+#define ADV_INTR_ENABLE_GLOBAL_INTR                 0x80
+
+#define ADV_INTR_STATUS_INTRA            0x01
+#define ADV_INTR_STATUS_INTRB            0x02
+#define ADV_INTR_STATUS_INTRC            0x04
+
+#define ADV_RISC_CSR_STOP           (0x0000)
+#define ADV_RISC_TEST_COND          (0x2000)
+#define ADV_RISC_CSR_RUN            (0x4000)
+#define ADV_RISC_CSR_SINGLE_STEP    (0x8000)
+
+#define ADV_CTRL_REG_HOST_INTR      0x0100
+#define ADV_CTRL_REG_SEL_INTR       0x0200
+#define ADV_CTRL_REG_DPR_INTR       0x0400
+#define ADV_CTRL_REG_RTA_INTR       0x0800
+#define ADV_CTRL_REG_RMA_INTR       0x1000
+#define ADV_CTRL_REG_RES_BIT14      0x2000
+#define ADV_CTRL_REG_DPE_INTR       0x4000
+#define ADV_CTRL_REG_POWER_DONE     0x8000
+#define ADV_CTRL_REG_ANY_INTR       0xFF00
+
+#define ADV_CTRL_REG_CMD_RESET             0x00C6
+#define ADV_CTRL_REG_CMD_WR_IO_REG         0x00C5
+#define ADV_CTRL_REG_CMD_RD_IO_REG         0x00C4
+#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE  0x00C3
+#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE  0x00C2
+
+#define ADV_SCSI_CTRL_RSTOUT        0x2000
+
+#define AdvIsIntPending(port)  \
+    (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
 
-/* PCI IO Port Addresses to generate special cycle */
+/*
+ * SCSI_CFG0 Register bit definitions
+ */
+#define TIMER_MODEAB    0xC000  /* Watchdog, Second, and Select. Timer Ctrl. */
+#define PARITY_EN       0x2000  /* Enable SCSI Parity Error detection */
+#define EVEN_PARITY     0x1000  /* Select Even Parity */
+#define WD_LONG         0x0800  /* Watchdog Interval, 1: 57 min, 0: 13 sec */
+#define QUEUE_128       0x0400  /* Queue Size, 1: 128 byte, 0: 64 byte */
+#define PRIM_MODE       0x0100  /* Primitive SCSI mode */
+#define SCAM_EN         0x0080  /* Enable SCAM selection */
+#define SEL_TMO_LONG    0x0040  /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
+#define CFRM_ID         0x0020  /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
+#define OUR_ID_EN       0x0010  /* Enable OUR_ID bits */
+#define OUR_ID          0x000F  /* SCSI ID */
 
-#define PCI_CONFIG_ADDRESS_MECH1          0x0CF8
-#define PCI_CONFIG_DATA_MECH1             0x0CFC
+/*
+ * SCSI_CFG1 Register bit definitions
+ */
+#define BIG_ENDIAN      0x8000  /* Enable Big Endian Mode MIO:15, EEP:15 */
+#define TERM_POL        0x2000  /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
+#define SLEW_RATE       0x1000  /* SCSI output buffer slew rate */
+#define FILTER_SEL      0x0C00  /* Filter Period Selection */
+#define  FLTR_DISABLE    0x0000  /* Input Filtering Disabled */
+#define  FLTR_11_TO_20NS 0x0800  /* Input Filtering 11ns to 20ns */          
+#define  FLTR_21_TO_39NS 0x0C00  /* Input Filtering 21ns to 39ns */          
+#define ACTIVE_DBL      0x0200  /* Disable Active Negation */
+#define DIFF_MODE       0x0100  /* SCSI differential Mode (Read-Only) */
+#define DIFF_SENSE      0x0080  /* 1: No SE cables, 0: SE cable (Read-Only) */
+#define TERM_CTL_SEL    0x0040  /* Enable TERM_CTL_H and TERM_CTL_L */
+#define TERM_CTL        0x0030  /* External SCSI Termination Bits */
+#define  TERM_CTL_H      0x0020  /* Enable External SCSI Upper Termination */
+#define  TERM_CTL_L      0x0010  /* Enable External SCSI Lower Termination */
+#define CABLE_DETECT    0x000F  /* External SCSI Cable Connection Status */
+
+#define CABLE_ILLEGAL_A 0x7
+    /* x 0 0 0  | on  on | Illegal (all 3 connectors are used) */
+
+#define CABLE_ILLEGAL_B 0xB
+    /* 0 x 0 0  | on  on | Illegal (all 3 connectors are used) */
 
-#define PCI_CONFIG_FORWARD_REGISTER       0x0CFA    /* 0=type 0; 1=type 1; */
+/*
+   The following table details the SCSI_CFG1 Termination Polarity,
+   Termination Control and Cable Detect bits.
+
+   Cable Detect | Termination
+   Bit 3 2 1 0  | 5   4  | Notes
+   _____________|________|____________________
+       1 1 1 0  | on  on | Internal wide only
+       1 1 0 1  | on  on | Internal narrow only
+       1 0 1 1  | on  on | External narrow only
+       0 x 1 1  | on  on | External wide only
+       1 1 0 0  | on  off| Internal wide and internal narrow
+       1 0 1 0  | on  off| Internal wide and external narrow
+       0 x 1 0  | off off| Internal wide and external wide
+       1 0 0 1  | on  off| Internal narrow and external narrow
+       0 x 0 1  | on  off| Internal narrow and external wide
+       1 1 1 1  | on  on | No devices are attached
+       x 0 0 0  | on  on | Illegal (all 3 connectors are used)
+       0 x 0 0  | on  on | Illegal (all 3 connectors are used)
+  
+       x means don't-care (either '0' or '1')
+  
+       If term_pol (bit 13) is '0' (active-low terminator enable), then:
+           'on' is '0' and 'off' is '1'.
+  
+       If term_pol bit is '1' (meaning active-hi terminator enable), then:
+           'on' is '1' and 'off' is '0'.
+ */
 
-#define PCI_CONFIG_BUS_NUMBER_MASK        0x00FF0000
-#define PCI_CONFIG_DEVICE_FUNCTION_MASK   0x0000FF00
-#define PCI_CONFIG_REGISTER_NUMBER_MASK   0x000000F8
+/*
+ * MEM_CFG Register bit definitions
+ */
+#define BIOS_EN         0x40    /* BIOS Enable MIO:14,EEP:14 */
+#define FAST_EE_CLK     0x20    /* Diagnostic Bit */
+#define RAM_SZ          0x1C    /* Specify size of RAM to RISC */
+#define  RAM_SZ_2KB      0x00    /* 2 KB */
+#define  RAM_SZ_4KB      0x04    /* 4 KB */
+#define  RAM_SZ_8KB      0x08    /* 8 KB */
+#define  RAM_SZ_16KB     0x0C    /* 16 KB */
+#define  RAM_SZ_32KB     0x10    /* 32 KB */
+#define  RAM_SZ_64KB     0x14    /* 64 KB */
 
-#define PCI_DEVICE_FOUND                0x0000
-#define PCI_DEVICE_NOT_FOUND            0xffff
+/*
+ * DMA_CFG0 Register bit definitions
+ *
+ * This register is only accessible to the host.
+ */
+#define BC_THRESH_ENB   0x80    /* PCI DMA Start Conditions */
+#define FIFO_THRESH     0x70    /* PCI DMA FIFO Threshold */
+#define  FIFO_THRESH_16B  0x00   /* 16 bytes */
+#define  FIFO_THRESH_32B  0x20   /* 32 bytes */
+#define  FIFO_THRESH_48B  0x30   /* 48 bytes */
+#define  FIFO_THRESH_64B  0x40   /* 64 bytes */
+#define  FIFO_THRESH_80B  0x50   /* 80 bytes (default) */
+#define  FIFO_THRESH_96B  0x60   /* 96 bytes */
+#define  FIFO_THRESH_112B 0x70   /* 112 bytes */
+#define START_CTL       0x0C    /* DMA start conditions */
+#define  START_CTL_TH    0x00    /* Wait threshold level (default) */
+#define  START_CTL_ID    0x04    /* Wait SDMA/SBUS idle */
+#define  START_CTL_THID  0x08    /* Wait threshold and SDMA/SBUS idle */
+#define  START_CTL_EMFU  0x0C    /* Wait SDMA FIFO empty/full */
+#define READ_CMD        0x03    /* Memory Read Method */
+#define  READ_CMD_MR     0x00    /* Memory Read */
+#define  READ_CMD_MRL    0x02    /* Memory Read Long */
+#define  READ_CMD_MRM    0x03    /* Memory Read Multiple (default) */
+
+/* a_advlib.h */
 
-#define SUBCLASS_OFFSET         0x0A
-#define CLASSCODE_OFFSET        0x0B
-#define VENDORID_OFFSET         0x00
-#define DEVICEID_OFFSET         0x02
+/*
+ * Adv Library Status Definitions
+ */
+#define ADV_TRUE        1
+#define ADV_FALSE       0
+#define ADV_NOERROR     1
+#define ADV_SUCCESS     1
+#define ADV_BUSY        0
+#define ADV_ERROR       (-1)
 
-#ifndef ADVANSYS_STATS
-#define ASC_STATS(shp, counter)
-#define ASC_STATS_ADD(shp, counter, count)
-#else /* ADVANSYS_STATS */
-#define ASC_STATS(shp, counter) \
-    (ASC_BOARDP(shp)->asc_stats.counter++)
 
-#define ASC_STATS_ADD(shp, counter, count) \
-    (ASC_BOARDP(shp)->asc_stats.counter += (count))
-#endif /* ADVANSYS_STATS */
+/*
+ * ASC_DVC_VAR 'warn_code' values
+ */
+#define ASC_WARN_EEPROM_CHKSUM          0x0002 /* EEP check sum error */
+#define ASC_WARN_EEPROM_TERMINATION     0x0004 /* EEP termination bad field */
+#define ASC_WARN_SET_PCI_CONFIG_SPACE   0x0080 /* PCI config space set error */
+#define ASC_WARN_ERROR                  0xFFFF /* ADV_ERROR return */
 
-#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
+#define ADV_MAX_TID                     15 /* max. target identifier */
+#define ADV_MAX_LUN                     7  /* max. logical unit number */
 
-/* If the result wraps when calculating tenths, return 0. */
-#define ASC_TENTHS(num, den) \
-    (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
-    0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
 
 /*
- * Display a message to the console.
+ * AscInitGetConfig() and AscInitAsc1000Driver() Definitions
+ *
+ * Error code values are set in ASC_DVC_VAR 'err_code'.
  */
-#define ASC_PRINT(s) \
-    { \
-        printk("advansys: "); \
-        printk(s); \
-    }
+#define ASC_IERR_WRITE_EEPROM       0x0001 /* write EEPROM error */
+#define ASC_IERR_MCODE_CHKSUM       0x0002 /* micro code check sum error */
+#define ASC_IERR_START_STOP_CHIP    0x0008 /* start/stop chip failed */
+#define ASC_IERR_CHIP_VERSION       0x0040 /* wrong chip version */
+#define ASC_IERR_SET_SCSI_ID        0x0080 /* set SCSI ID failed */
+#define ASC_IERR_BAD_SIGNATURE      0x0200 /* signature not found */
+#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
+#define ASC_IERR_SINGLE_END_DEVICE  0x0800 /* Single-end used w/differential */
+#define ASC_IERR_REVERSED_CABLE     0x1000 /* Narrow flat cable reversed */
+#define ASC_IERR_RW_LRAM            0x8000 /* read/write local RAM error */
 
-#define ASC_PRINT1(s, a1) \
-    { \
-        printk("advansys: "); \
-        printk((s), (a1)); \
-    }
+/*
+ * Fixed locations of microcode operating variables.
+ */
+#define ASC_MC_CODE_BEGIN_ADDR          0x0028 /* microcode start address */
+#define ASC_MC_CODE_END_ADDR            0x002A /* microcode end address */
+#define ASC_MC_CODE_CHK_SUM             0x002C /* microcode code checksum */
+#define ASC_MC_STACK_BEGIN              0x002E /* microcode stack begin */
+#define ASC_MC_STACK_END                0x0030 /* microcode stack end */
+#define ASC_MC_VERSION_DATE             0x0038 /* microcode version */
+#define ASC_MC_VERSION_NUM              0x003A /* microcode number */
+#define ASCV_VER_SERIAL_W               0x003C /* used in dos_init */
+#define ASC_MC_BIOSMEM                  0x0040 /* BIOS RISC Memory Start */
+#define ASC_MC_BIOSLEN                  0x0050 /* BIOS RISC Memory Length */
+#define ASC_MC_HALTCODE                 0x0094 /* microcode halt code */
+#define ASC_MC_CALLERPC                 0x0096 /* microcode halt caller PC */
+#define ASC_MC_ADAPTER_SCSI_ID          0x0098 /* one ID byte + reserved */
+#define ASC_MC_ULTRA_ABLE               0x009C
+#define ASC_MC_SDTR_ABLE                0x009E
+#define ASC_MC_TAGQNG_ABLE              0x00A0
+#define ASC_MC_DISC_ENABLE              0x00A2
+#define ASC_MC_IDLE_CMD                 0x00A6
+#define ASC_MC_IDLE_PARA_STAT           0x00A8
+#define ASC_MC_DEFAULT_SCSI_CFG0        0x00AC
+#define ASC_MC_DEFAULT_SCSI_CFG1        0x00AE
+#define ASC_MC_DEFAULT_MEM_CFG          0x00B0
+#define ASC_MC_DEFAULT_SEL_MASK         0x00B2
+#define ASC_MC_RISC_NEXT_READY          0x00B4
+#define ASC_MC_RISC_NEXT_DONE           0x00B5
+#define ASC_MC_SDTR_DONE                0x00B6
+#define ASC_MC_NUMBER_OF_QUEUED_CMD     0x00C0
+#define ASC_MC_NUMBER_OF_MAX_CMD        0x00D0
+#define ASC_MC_DEVICE_HSHK_CFG_TABLE    0x0100
+#define ASC_MC_WDTR_ABLE                0x0120 /* Wide Transfer TID bitmask. */
+#define ASC_MC_CONTROL_FLAG             0x0122 /* Microcode control flag. */
+#define ASC_MC_WDTR_DONE                0x0124
+#define ASC_MC_HOST_NEXT_READY          0x0128 /* Host Next Ready RQL Entry. */
+#define ASC_MC_HOST_NEXT_DONE           0x0129 /* Host Next Done RQL Entry. */
 
-#define ASC_PRINT2(s, a1, a2) \
-    { \
-        printk("advansys: "); \
-        printk((s), (a1), (a2)); \
-    }
+/*
+ * BIOS LRAM variable absolute offsets.
+ */
+#define BIOS_CODESEG    0x54
+#define BIOS_CODELEN    0x56
+#define BIOS_SIGNATURE  0x58
+#define BIOS_VERSION    0x5A
+#define BIOS_SIGNATURE  0x58
 
-#define ASC_PRINT3(s, a1, a2, a3) \
-    { \
-        printk("advansys: "); \
-        printk((s), (a1), (a2), (a3)); \
-    }
+/*
+ * Microcode Control Flags
+ *
+ * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
+ * and handled by the microcode.
+ */
+#define CONTROL_FLAG_IGNORE_PERR        0x0001 /* Ignore DMA Parity Errors */
 
-#define ASC_PRINT4(s, a1, a2, a3, a4) \
-    { \
-        printk("advansys: "); \
-        printk((s), (a1), (a2), (a3), (a4)); \
-    }
+/*
+ * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
+ */
+#define HSHK_CFG_WIDE_XFR       0x8000
+#define HSHK_CFG_RATE           0x0F00
+#define HSHK_CFG_OFFSET         0x001F
 
+/*
+ * LRAM RISC Queue Lists (LRAM addresses 0x1200 - 0x19FF)
+ *
+ * Each of the 255 Adv Library/Microcode RISC queue lists or mailboxes 
+ * starting at LRAM address 0x1200 is 8 bytes and has the following
+ * structure. Only 253 of these are actually used for command queues.
+ */
 
-#ifndef ADVANSYS_DEBUG
+#define ASC_MC_RISC_Q_LIST_BASE         0x1200
+#define ASC_MC_RISC_Q_LIST_SIZE         0x0008
+#define ASC_MC_RISC_Q_TOTAL_CNT         0x00FF /* Num. queue slots in LRAM. */
+#define ASC_MC_RISC_Q_FIRST             0x0001
+#define ASC_MC_RISC_Q_LAST              0x00FF
+
+#define ASC_DEF_MAX_HOST_QNG    0xFD /* Max. number of host commands (253) */
+#define ASC_DEF_MIN_HOST_QNG    0x10 /* Min. number of host commands (16) */
+#define ASC_DEF_MAX_DVC_QNG     0x3F /* Max. number commands per device (63) */
+#define ASC_DEF_MIN_DVC_QNG     0x04 /* Min. number commands per device (4) */
+
+/* RISC Queue List structure - 8 bytes */
+#define RQL_FWD     0     /* forward pointer (1 byte) */
+#define RQL_BWD     1     /* backward pointer (1 byte) */
+#define RQL_STATE   2     /* state byte - free, ready, done, aborted (1 byte) */
+#define RQL_TID     3     /* request target id (1 byte) */
+#define RQL_PHYADDR 4     /* request physical pointer (4 bytes) */
+     
+/* RISC Queue List state values */
+#define ASC_MC_QS_FREE                  0x00
+#define ASC_MC_QS_READY                 0x01
+#define ASC_MC_QS_DONE                  0x40
+#define ASC_MC_QS_ABORTED               0x80
 
-#define ASC_DBG(lvl, s)
-#define ASC_DBG1(lvl, s, a1)
-#define ASC_DBG2(lvl, s, a1, a2)
-#define ASC_DBG3(lvl, s, a1, a2, a3)
-#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
-#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
-#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
-#define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp)
-#define ASC_DBG_PRT_QDONE_INFO(lvl, qdone)
-#define ASC_DBG_PRT_HEX(lvl, name, start, length)
-#define ASC_DBG_PRT_CDB(lvl, cdb, len)
-#define ASC_DBG_PRT_SENSE(lvl, sense, len)
-#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
+/* RISC Queue List pointer values */
+#define ASC_MC_NULL_Q                   0x00            /* NULL_Q == 0   */
+#define ASC_MC_BIOS_Q                   0xFF            /* BIOS_Q = 255  */
+
+/* ASC_SCSI_REQ_Q 'cntl' field values */
+#define ASC_MC_QC_START_MOTOR           0x02     /* Issue start motor. */
+#define ASC_MC_QC_NO_OVERRUN            0x04     /* Don't report overrun. */
+#define ASC_MC_QC_FIRST_DMA             0x08     /* Internal microcode flag. */
+#define ASC_MC_QC_ABORTED               0x10     /* Request aborted by host. */
+#define ASC_MC_QC_REQ_SENSE             0x20     /* Auto-Request Sense. */
+#define ASC_MC_QC_DOS_REQ               0x80     /* Request issued by DOS. */
 
-#else /* ADVANSYS_DEBUG */
 
 /*
- * Debugging Message Levels:
- * 0: Errors Only
- * 1: High-Level Tracing
- * 2-N: Verbose Tracing
+ * ASC_SCSI_REQ_Q 'a_flag' definitions
+ *
+ * The Adv Library should limit use to the lower nibble (4 bits) of
+ * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
  */
+#define ADV_POLL_REQUEST                0x01   /* poll for request completion */
+#define ADV_SCSIQ_DONE                  0x02   /* request done */
 
-#define ASC_DBG(lvl, s) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk(s); \
-        } \
-    }
-
-#define ASC_DBG1(lvl, s, a1) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk((s), (a1)); \
-        } \
-    }
-
-#define ASC_DBG2(lvl, s, a1, a2) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk((s), (a1), (a2)); \
-        } \
-    }
+/*
+ * Adapter temporary configuration structure
+ *
+ * This structure can be discarded after initialization. Don't add
+ * fields here needed after initialization.
+ *
+ * Field naming convention: 
+ *
+ *  *_enable indicates the field enables or disables a feature. The
+ *  value of the field is never reset.
+ */
+typedef struct adv_dvc_cfg {
+  ushort disc_enable;       /* enable disconnection */
+  uchar  chip_version;      /* chip version */
+  uchar  termination;       /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
+  ushort pci_device_id;     /* PCI device code number */
+  ushort lib_version;       /* Adv Library version number */
+  ushort control_flag;      /* Microcode Control Flag */
+  ushort mcode_date;        /* Microcode date */
+  ushort mcode_version;     /* Microcode version */
+  ushort pci_slot_info;     /* high byte device/function number */
+                            /* bits 7-3 device num., bits 2-0 function num. */
+                            /* low byte bus num. */
+  ushort bios_boot_wait;    /* BIOS boot time delay */
+  ushort serial1;           /* EEPROM serial number word 1 */
+  ushort serial2;           /* EEPROM serial number word 2 */
+  ushort serial3;           /* EEPROM serial number word 3 */
+} ADV_DVC_CFG; 
 
-#define ASC_DBG3(lvl, s, a1, a2, a3) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk((s), (a1), (a2), (a3)); \
-        } \
-    }
+/*
+ * Adapter operation variable structure.
+ *
+ * One structure is required per host adapter.
+ *
+ * Field naming convention: 
+ *
+ *  *_able indicates both whether a feature should be enabled or disabled
+ *  and whether a device isi capable of the feature. At initialization
+ *  this field may be set, but later if a device is found to be incapable
+ *  of the feature, the field is cleared.
+ */
+typedef struct adv_dvc_var {
+  AdvPortAddr iop_base;   /* I/O port address */
+  ushort err_code;        /* fatal error code */
+  ushort bios_ctrl;       /* BIOS control word, EEPROM word 12 */
+  Ptr2Func isr_callback;  /* pointer to function, called in AdvISR() */
+  Ptr2Func sbreset_callback;  /* pointer to function, called in AdvISR() */
+  ushort wdtr_able;       /* try WDTR for a device */
+  ushort sdtr_able;       /* try SDTR for a device */
+  ushort ultra_able;      /* try SDTR Ultra speed for a device */
+  ushort tagqng_able;     /* try tagged queuing with a device */
+  uchar  max_dvc_qng;     /* maximum number of tagged commands per device */
+  ushort start_motor;     /* start motor command allowed */
+  uchar  scsi_reset_wait; /* delay in seconds after scsi bus reset */
+  uchar  chip_no;         /* should be assigned by caller */
+  uchar  max_host_qng;    /* maximum number of Q'ed command allowed */
+  uchar  cur_host_qng;    /* total number of queue command */
+  uchar  irq_no;          /* IRQ number */
+  ushort no_scam;         /* scam_tolerant of EEPROM */
+  ushort idle_cmd_done;   /* microcode idle command done set by AdvISR() */
+  ulong  drv_ptr;         /* driver pointer to private structure */
+  uchar  chip_scsi_id;    /* chip SCSI target ID */
+ /*
+  * Note: The following fields will not be used after initialization. The
+  * driver may discard the buffer after initialization is done.
+  */
+  ADV_DVC_CFG *cfg; /* temporary configuration structure  */
+} ADV_DVC_VAR; 
+
+#define NO_OF_SG_PER_BLOCK              15
+
+typedef struct asc_sg_block {
+    uchar reserved1; 
+    uchar reserved2; 
+    uchar first_entry_no;             /* starting entry number */
+    uchar last_entry_no;              /* last entry number */
+    struct asc_sg_block *sg_ptr; /* links to the next sg block */
+    struct  {
+        ulong sg_addr;                /* SG element address */
+        ulong sg_count;               /* SG element count */
+    } sg_list[NO_OF_SG_PER_BLOCK];
+} ADV_SG_BLOCK;
 
-#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            printk((s), (a1), (a2), (a3), (a4)); \
-        } \
-    }
+/*
+ * ASC_SCSI_REQ_Q - microcode request structure
+ *
+ * All fields in this structure up to byte 60 are used by the microcode.
+ * The microcode makes assumptions about the size and ordering of fields
+ * in this structure. Do not change the structure definition here without
+ * coordinating the change with the microcode.
+ */
+typedef struct adv_scsi_req_q {
+    uchar       cntl;           /* Ucode flags and state (ASC_MC_QC_*). */
+    uchar       sg_entry_cnt;   /* SG element count. Zero for no SG. */
+    uchar       target_id;      /* Device target identifier. */
+    uchar       target_lun;     /* Device target logical unit number. */
+    ulong       data_addr;      /* Data buffer physical address. */
+    ulong       data_cnt;       /* Data count. Ucode sets to residual. */
+    ulong       sense_addr;     /* Sense buffer physical address. */
+    ulong       srb_ptr;        /* Driver request pointer. */
+    uchar       a_flag;         /* Adv Library flag field. */
+    uchar       sense_len;      /* Auto-sense length. Ucode sets to residual. */
+    uchar       cdb_len;        /* SCSI CDB length. */
+    uchar       tag_code;       /* SCSI-2 Tag Queue Code: 00, 20-22. */
+    uchar       done_status;    /* Completion status. */
+    uchar       scsi_status;    /* SCSI status byte. */
+    uchar       host_status;    /* Ucode host status. */
+    uchar       ux_sg_ix;       /* Ucode working SG variable. */
+    uchar       cdb[12];        /* SCSI command block. */
+    ulong       sg_real_addr;   /* SG list physical address. */
+    struct adv_scsi_req_q *free_scsiq_link;
+    ulong       ux_wk_data_cnt; /* Saved data count at disconnection. */
+    struct adv_scsi_req_q *scsiq_ptr;
+    ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
+    /*
+     * End of microcode structure - 60 bytes. The rest of the structure
+     * is used by the Adv Library and ignored by the microcode.
+     */
+    ulong       vsense_addr;    /* Sense buffer virtual address. */
+    ulong       vdata_addr;     /* Data buffer virtual address. */
+    uchar       orig_sense_len; /* Original length of sense buffer. */
+} ADV_SCSI_REQ_Q; /* BIOS - 70 bytes, DOS - 76 bytes, W95, WNT - 69 bytes */
 
-#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            asc_prt_scsi_host(s); \
-        } \
-    }
+/*
+ * Microcode idle loop commands
+ */
+#define IDLE_CMD_COMPLETED           0
+#define IDLE_CMD_STOP_CHIP           0x0001
+#define IDLE_CMD_STOP_CHIP_SEND_INT  0x0002
+#define IDLE_CMD_SEND_INT            0x0004
+#define IDLE_CMD_ABORT               0x0008
+#define IDLE_CMD_DEVICE_RESET        0x0010
+#define IDLE_CMD_SCSI_RESET          0x0020
 
-#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            asc_prt_scsi_cmnd(s); \
-        } \
-    }
+/*
+ * AdvSendIdleCmd() flag definitions.
+ */
+#define ADV_NOWAIT     0x01
 
-#define ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            asc_prt_scsi_q(scsiqp); \
-        } \
-    }
+/*
+ * Wait loop time out values.
+ */
+#define SCSI_WAIT_10_SEC             10         /* 10 seconds */
+#define SCSI_MS_PER_SEC              1000       /* milliseconds per second */
 
-#define ASC_DBG_PRT_QDONE_INFO(lvl, qdone) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            asc_prt_qdone_info(qdone); \
-        } \
-    }
+/*
+ * Device drivers must define the following functions.
+ */
+STATIC int   DvcEnterCritical(void);
+STATIC void  DvcLeaveCritical(int);
+STATIC void  DvcSleepMilliSecond(ulong);
+STATIC uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort);
+STATIC void  DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar);
+STATIC ulong DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
+                uchar *, long *, int);
+STATIC void  DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
 
-#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
-    { \
-        if (asc_dbglvl >= (lvl)) { \
-            asc_prt_hex((name), (start), (length)); \
-        } \
-    }
+/*
+ * Adv Library functions available to drivers.
+ */
+STATIC int     AdvExeScsiQueue(ADV_DVC_VAR *,
+                         ADV_SCSI_REQ_Q *);
+STATIC int     AdvISR(ADV_DVC_VAR *);
+STATIC int     AdvInitGetConfig(ADV_DVC_VAR *);
+STATIC int     AdvInitAsc3550Driver(ADV_DVC_VAR *);
+STATIC int     AdvResetSB(ADV_DVC_VAR *);
 
-#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
-        ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
+/*
+ * Internal Adv Library functions.
+ */
+STATIC int    AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ulong, int);
+STATIC void   AdvResetChip(ADV_DVC_VAR *);
+STATIC int    AdvSendScsiCmd(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
+STATIC void   AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
+STATIC int    AdvInitFromEEP(ADV_DVC_VAR *);
+STATIC ushort AdvGetEEPConfig(AdvPortAddr, ADVEEP_CONFIG *);
+STATIC void   AdvSetEEPConfig(AdvPortAddr, ADVEEP_CONFIG *);
+STATIC void   AdvWaitEEPCmd(AdvPortAddr);
+STATIC ushort AdvReadEEPWord(AdvPortAddr, int);
+STATIC void   AdvResetSCSIBus(ADV_DVC_VAR *);
 
-#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
-        ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
+/*
+ * PCI Bus Definitions
+ */
+#define AscPCICmdRegBits_BusMastering     0x0007
+#define AscPCICmdRegBits_ParErrRespCtrl   0x0040
 
-#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
-        ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
-#endif /* ADVANSYS_DEBUG */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
 
-#ifndef ADVANSYS_ASSERT
-#define ASC_ASSERT(a)
-#else /* ADVANSYS_ASSERT */
+/* Read byte from a register. */
+#define AdvReadByteRegister(iop_base, reg_off) \
+     (inp((iop_base) + (reg_off)))
+
+/* Write byte to a register. */
+#define AdvWriteByteRegister(iop_base, reg_off, byte) \
+     (outp((iop_base) + (reg_off), (byte)))
+
+/* Read word (2 bytes) from a register. */
+#define AdvReadWordRegister(iop_base, reg_off) \
+     (inpw((iop_base) + (reg_off)))
+
+/* Write word (2 bytes) to a register. */
+#define AdvWriteWordRegister(iop_base, reg_off, word) \
+     (outpw((iop_base) + (reg_off), (word)))
+
+/* Read byte from LRAM. */
+#define AdvReadByteLram(iop_base, addr, byte) \
+do { \
+    outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \
+    (byte) = inp((iop_base) + IOPB_RAM_DATA); \
+} while (0)
+
+/* Write byte to LRAM. */
+#define AdvWriteByteLram(iop_base, addr, byte) \
+    (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
+     outp((iop_base) + IOPB_RAM_DATA, (byte)))
+
+/* Read word (2 bytes) from LRAM. */
+#define AdvReadWordLram(iop_base, addr, word) \
+do { \
+    outpw((iop_base) + IOPW_RAM_ADDR, (addr));  \
+    (word) = inpw((iop_base) + IOPW_RAM_DATA); \
+} while (0)
+
+/* Write word (2 bytes) to LRAM. */
+#define AdvWriteWordLram(iop_base, addr, word) \
+    (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
+     outpw((iop_base) + IOPW_RAM_DATA, (word)))
+
+/* Write double word (4 bytes) to LRAM */
+/* Because of unspecified C language ordering don't use auto-increment. */
+#define AdvWriteDWordLram(iop_base, addr, dword) \
+    ((outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \
+      outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword) & 0xFFFF))), \
+     (outpw((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
+      outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword >> 16) & 0xFFFF))))
+
+/* Read word (2 bytes) from LRAM assuming that the address is already set. */
+#define AdvReadWordAutoIncLram(iop_base) \
+     (inpw((iop_base) + IOPW_RAM_DATA))
+
+/* Write word (2 bytes) to LRAM assuming that the address is already set. */
+#define AdvWriteWordAutoIncLram(iop_base, word) \
+     (outpw((iop_base) + IOPW_RAM_DATA, (word)))
+
+#else /* version >= v1,3,0 */
+
+/* Read byte from a register. */
+#define AdvReadByteRegister(iop_base, reg_off) \
+     (ADV_MEM_READB((iop_base) + (reg_off)))
+
+/* Write byte to a register. */
+#define AdvWriteByteRegister(iop_base, reg_off, byte) \
+     (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
+
+/* Read word (2 bytes) from a register. */
+#define AdvReadWordRegister(iop_base, reg_off) \
+     (ADV_MEM_READW((iop_base) + (reg_off)))
+
+/* Write word (2 bytes) to a register. */
+#define AdvWriteWordRegister(iop_base, reg_off, word) \
+     (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
+
+/* Read byte from LRAM. */
+#define AdvReadByteLram(iop_base, addr, byte) \
+do { \
+    ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
+    (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
+} while (0)
+
+/* Write byte to LRAM. */
+#define AdvWriteByteLram(iop_base, addr, byte) \
+    (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
+     ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
+
+/* Read word (2 bytes) from LRAM. */
+#define AdvReadWordLram(iop_base, addr, word) \
+do { \
+    ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
+    (word) = ADV_MEM_READW((iop_base) + IOPW_RAM_DATA); \
+} while (0)
+
+/* Write word (2 bytes) to LRAM. */
+#define AdvWriteWordLram(iop_base, addr, word) \
+    (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
+     ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
+
+/* Write double word (4 bytes) to LRAM */
+/* Because of unspecified C language ordering don't use auto-increment. */
+#define AdvWriteDWordLram(iop_base, addr, dword) \
+    ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
+      ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
+                     (ushort) ((dword) & 0xFFFF))), \
+     (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
+      ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
+                     (ushort) ((dword >> 16) & 0xFFFF))))
+
+/* Read word (2 bytes) from LRAM assuming that the address is already set. */
+#define AdvReadWordAutoIncLram(iop_base) \
+     (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
+
+/* Write word (2 bytes) to LRAM assuming that the address is already set. */
+#define AdvWriteWordAutoIncLram(iop_base, word) \
+     (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
+
+#endif /* version >= v1,3,0 */
 
-#define ASC_ASSERT(a) \
-    { \
-        if (!(a)) { \
-            printk("ASC_ASSERT() Failure: file %s, line %d\n", \
-                __FILE__, __LINE__); \
-        } \
-    }
+/*
+ * Define macro to check for Condor signature.
+ *
+ * Evaluate to ADV_TRUE if a Condor chip is found the specified port
+ * address 'iop_base'. Otherwise evalue to ADV_FALSE.
+ */
+#define AdvFindSignature(iop_base) \
+    (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
+    ADV_CHIP_ID_BYTE) && \
+     (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
+    ADV_CHIP_ID_WORD)) ?  ADV_TRUE : ADV_FALSE)
 
-#endif /* ADVANSYS_ASSERT */
+/*
+ * Define macro to Return the version number of the chip at 'iop_base'.
+ *
+ * The second parameter 'bus_type' is currently unused.
+ */
+#define AdvGetChipVersion(iop_base, bus_type) \
+    AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
 
+/*
+ * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
+ * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
+ * 
+ * If the request has not yet been sent to the device it will simply be
+ * aborted from RISC memory. If the request is disconnected it will be
+ * aborted on reselection by sending an Abort Message to the target ID.
+ *
+ * Return value:
+ *      ADV_TRUE(1) - Queue was successfully aborted.
+ *      ADV_FALSE(0) - Queue was not found on the active queue list.
+ */
+#define AdvAbortSRB(asc_dvc, srb_ptr) \
+    AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
+                (ulong) (srb_ptr), 0)
 
 /*
- * --- Driver Structures
+ * Send a Bus Device Reset Message to the specified target ID.
+ *
+ * All outstanding commands will be purged if sending the
+ * Bus Device Reset Message is successful.
+ *
+ * Return Value:
+ *      ADV_TRUE(1) - All requests on the target are purged.
+ *      ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
+ *                     are not purged.
  */
+#define AdvResetDevice(asc_dvc, target_id) \
+        AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
+                    (ulong) (target_id), 0)
 
-#ifdef ADVANSYS_STATS
+/*
+ * SCSI Wide Type definition.
+ */
+#define ADV_SCSI_BIT_ID_TYPE   ushort
 
-/* Per board statistics structure */
-struct asc_stats {
-    /* Driver Entrypoint Statistics */
-    ulong     command;         /* # calls to advansys_command() */
-    ulong     queuecommand;    /* # calls to advansys_queuecommand() */
-    ulong     abort;           /* # calls to advansys_abort() */
-    ulong     reset;           /* # calls to advansys_reset() */
-    ulong     biosparam;       /* # calls to advansys_biosparam() */
-    ulong     check_interrupt; /* # advansys_interrupt() check pending calls */
-    ulong     interrupt;       /* # advansys_interrupt() interrupts */
-    ulong     callback;        /* # calls asc_isr_callback() */
-    ulong     done;            /* # calls request scsi_done */
-    /* AscExeScsiQueue() Statistics */
-    ulong     asc_noerror;     /* # AscExeScsiQueue() ASC_NOERROR returns. */
-    ulong     asc_busy;        /* # AscExeScsiQueue() ASC_BUSY returns. */
-    ulong     asc_error;       /* # AscExeScsiQueue() ASC_ERROR returns. */
-    ulong     asc_unknown;     /* # AscExeScsiQueue() unknown returns. */
-    /* Data Transfer Statistics */
-    ulong     cont_cnt;        /* # non-scatter-gather I/O requests received */
-    ulong     cont_xfer;       /* # contiguous transfer 512-bytes */
-    ulong     sg_cnt;          /* # scatter-gather I/O requests received */
-    ulong     sg_elem;         /* # scatter-gather elements */
-    ulong     sg_xfer;         /* # scatter-gather transfer 512-bytes */
-};
-#endif /* ADVANSYS_STATS */
+/*
+ * AdvInitScsiTarget() 'cntl_flag' options.
+ */
+#define ADV_SCAN_LUN           0x01
+#define ADV_CAPINFO_NOLUN      0x02
 
 /*
- * Request queuing structure
+ * Convert target id to target id bit mask.
  */
-typedef struct asc_queue {
-    ASC_SCSI_BIT_ID_TYPE  q_tidmask;                /* queue mask */
-    REQP                  q_first[ASC_MAX_TID+1];   /* first queued request */
-    REQP                  q_last[ASC_MAX_TID+1];    /* last queued request */
-#ifdef ADVANSYS_STATS
-    short                 q_cur_cnt[ASC_MAX_TID+1]; /* current queue count */
-    short                 q_max_cnt[ASC_MAX_TID+1]; /* maximum queue count */
-    ulong                 q_tot_cnt[ASC_MAX_TID+1]; /* total enqueue count */
-    ulong                 q_tot_tim[ASC_MAX_TID+1]; /* total time queued */
-    ushort                q_max_tim[ASC_MAX_TID+1]; /* maximum time queued */
-    ushort                q_min_tim[ASC_MAX_TID+1]; /* minimum time queued */
-#endif /* ADVANSYS_STATS */
-} asc_queue_t;
+#define ADV_TID_TO_TIDMASK(tid)   (0x01 << ((tid) & ADV_MAX_TID))
 
 /*
- * Structure allocated for each board.
- *
- * This structure is allocated by scsi_register() at the end
- * of the 'Scsi_Host' structure starting at the 'hostdata'
- * field. It is guaranteed to be allocated from DMA-able memory.
+ * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
  */
-typedef struct asc_board {
-    int                  id;                     /* Board Id */
-    uint                 flags;                  /* Board flags */
-    ASC_DVC_VAR          asc_dvc_var;            /* Board configuration */
-    ASC_DVC_CFG          asc_dvc_cfg;            /* Device configuration */
-    asc_queue_t          active;                 /* Active command queue */
-    asc_queue_t          waiting;                /* Waiting command queue */
-    asc_queue_t          done;                   /* Done command queue */
-    ASC_SCSI_BIT_ID_TYPE init_tidmask;           /* Target initialized mask */
-    /* The following three structures must be in DMA-able memory. */
-    ASC_SCSI_REQ_Q       scsireqq;
-    ASC_CAP_INFO         cap_info;
-    ASC_SCSI_INQUIRY     inquiry;
-    Scsi_Device          *device[ASC_MAX_TID+1]; /* Mid-Level Scsi Device */
-    ushort               reqcnt[ASC_MAX_TID+1];  /* Starvation request count */
-    uchar                sdtr_data[ASC_MAX_TID+1]; /* SDTR information */
-#if ASC_QUEUE_FLOW_CONTROL
-    ushort               nerrcnt[ASC_MAX_TID+1]; /* No error request count */
-#endif /* ASC_QUEUE_FLOW_CONTROL */
-    ASC_SCSI_BIT_ID_TYPE queue_full;             /* Queue full mask */
-    ushort    queue_full_cnt[ASC_MAX_TID+1];     /* Queue full count */
-    ASCEEP_CONFIG        eep_config;             /* EEPROM configuration */
-    ulong                last_reset;             /* Saved last reset time */
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-    /* /proc/scsi/advansys/[0...] */
-    char                 *prtbuf;                /* Statistics Print Buffer */
-#endif /* version >= v1.3.0 */
-#ifdef ADVANSYS_STATS
-    struct asc_stats     asc_stats;              /* Board statistics */
-#endif /* ADVANSYS_STATS */
-} asc_board_t;
 
-/*
- * PCI configuration structures
- */
-typedef struct _PCI_DATA_
-{
-    uchar    type;
-    uchar    bus;
-    uchar    slot;
-    uchar    func;
-    uchar    offset;
-} PCI_DATA;
+#define QD_NO_STATUS         0x00       /* Request not completed yet. */
+#define QD_NO_ERROR          0x01
+#define QD_ABORTED_BY_HOST   0x02
+#define QD_WITH_ERROR        0x04
 
-typedef struct _PCI_DEVICE_
-{
-    ushort   vendorID;
-    ushort   deviceID;
-    ushort   slotNumber;
-    ushort   slotFound;
-    uchar    busNumber;
-    uchar    maxBusNumber;
-    uchar    devFunc;
-    ushort   startSlot;
-    ushort   endSlot;
-    uchar    bridge;
-    uchar    type;
-} PCI_DEVICE;
+#define QHSTA_NO_ERROR              0x00
+#define QHSTA_M_SEL_TIMEOUT         0x11
+#define QHSTA_M_DATA_OVER_RUN       0x12
+#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
+#define QHSTA_M_QUEUE_ABORTED       0x15
+#define QHSTA_M_SXFR_SDMA_ERR       0x16 /* SXFR_STATUS SCSI DMA Error */
+#define QHSTA_M_SXFR_SXFR_PERR      0x17 /* SXFR_STATUS SCSI Bus Parity Error */
+#define QHSTA_M_RDMA_PERR           0x18 /* RISC PCI DMA parity error */
+#define QHSTA_M_SXFR_OFF_UFLW       0x19 /* SXFR_STATUS Offset Underflow */
+#define QHSTA_M_SXFR_OFF_OFLW       0x20 /* SXFR_STATUS Offset Overflow */
+#define QHSTA_M_SXFR_WD_TMO         0x21 /* SXFR_STATUS Watchdog Timeout */
+#define QHSTA_M_SXFR_DESELECTED     0x22 /* SXFR_STATUS Deselected */
+/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
+#define QHSTA_M_SXFR_XFR_OFLW       0x12 /* SXFR_STATUS Transfer Overflow */
+#define QHSTA_M_SXFR_XFR_PH_ERR     0x24 /* SXFR_STATUS Transfer Phase Error */
+#define QHSTA_M_SXFR_UNKNOWN_ERROR  0x25 /* SXFR_STATUS Unknown Error */
+#define QHSTA_M_WTM_TIMEOUT         0x41
+#define QHSTA_M_BAD_CMPL_STATUS_IN  0x42
+#define QHSTA_M_NO_AUTO_REQ_SENSE   0x43
+#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
+#define QHSTA_M_INVALID_DEVICE      0x45 /* Bad target ID */
 
-typedef struct _PCI_CONFIG_SPACE_
-{
-    ushort   vendorID;
-    ushort   deviceID;
-    ushort   command;
-    ushort   status;
-    uchar    revision;
-    uchar    classCode[3];
-    uchar    cacheSize;
-    uchar    latencyTimer;
-    uchar    headerType;
-    uchar    bist;
-    ulong    baseAddress[6];
-    ushort   reserved[4];
-    ulong    optionRomAddr;
-    ushort   reserved2[4];
-    uchar    irqLine;
-    uchar    irqPin;
-    uchar    minGnt;
-    uchar    maxLatency;
-} PCI_CONFIG_SPACE;
+typedef int (* ADV_ISR_CALLBACK)
+    (ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
 
+typedef int (* ADV_SBRESET_CALLBACK)
+    (ADV_DVC_VAR *);
 
 /*
- * --- Driver Data
+ * Default EEPROM Configuration structure defined in a_init.c.
  */
+extern ADVEEP_CONFIG Default_EEPROM_Config;
 
-/* Note: All driver global data should be initialized. */
+/*
+ * DvcGetPhyAddr() flag arguments
+ */
+#define ADV_IS_SCSIQ_FLAG       0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
+#define ADV_ASCGETSGLIST_VADDR  0x02 /* 'addr' is AscGetSGList() virtual addr */
+#define ADV_IS_SENSE_FLAG       0x04 /* 'addr' is sense virtual pointer */
+#define ADV_IS_DATA_FLAG        0x08 /* 'addr' is data virtual pointer */
+#define ADV_IS_SGLIST_FLAG      0x10 /* 'addr' is sglist virtual pointer */
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-struct proc_dir_entry proc_scsi_advansys =
-{
-    PROC_SCSI_ADVANSYS,                /* unsigned short low_ino */
-    8,                                /* unsigned short namelen */
-    "advansys",                        /* const char *name */
-    S_IFDIR | S_IRUGO | S_IXUGO,    /* mode_t mode */
-    2                                /* nlink_t nlink */
-};
-#endif /* version >= v1.3.0 */
+/* 'IS_SCSIQ_FLAG is now obsolete; Instead use ADV_IS_SCSIQ_FLAG. */
+#define IS_SCSIQ_FLAG           ADV_IS_SCSIQ_FLAQ
 
-/* Number of boards detected in system. */
-STATIC int asc_board_count = 0;
-STATIC struct Scsi_Host    *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
 
-/* Overrun buffer shared between all boards. */
-STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
+/* Return the address that is aligned at the next doubleword >= to 'addr'. */
+#define ADV_DWALIGN(addr)       (((ulong) (addr) + 0x3) & ~0x3)
 
 /*
- * Global structures required to issue a command.
+ * Total contiguous memory needed for driver SG blocks.
+ *
+ * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
+ * number of scatter-gather elements the driver supports in a
+ * single request.
  */
-STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } };
-STATIC ASC_SG_HEAD asc_sg_head = { 0 };
 
-/* List of supported bus types. */
-STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = {
-    ASC_IS_ISA,
-    ASC_IS_VL,
-    ASC_IS_EISA,
-    ASC_IS_PCI,
-};
+#ifndef ADV_MAX_SG_LIST
+Forced Error: Driver must define ADV_MAX_SG_LIST.
+#endif /* ADV_MAX_SG_LIST */
 
-STATIC int pci_scan_method ASC_INITDATA = -1;
+#define ADV_SG_LIST_MAX_BYTE_SIZE \
+         (sizeof(ADV_SG_BLOCK) * \
+          ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
 
 /*
- * Used with the LILO 'advansys' option to eliminate or
- * limit I/O port probing at boot time, cf. advansys_setup().
+ * A driver may optionally define the assertion macro ADV_ASSERT() in
+ * its d_os_dep.h file. If the macro has not already been defined,
+ * then define the macro to a no-op.
  */
-STATIC int asc_iopflag = ASC_FALSE;
-STATIC int asc_ioport[ASC_NUM_BOARD_SUPPORTED] = { 0, 0, 0, 0 };
-
-#ifdef ADVANSYS_DEBUG
-STATIC char *
-asc_bus_name[ASC_NUM_BUS] = {
-    "ASC_IS_ISA",
-    "ASC_IS_VL",
-    "ASC_IS_EISA",
-    "ASC_IS_PCI",
-};
-
-STATIC int          asc_dbglvl = 0;
-#endif /* ADVANSYS_DEBUG */
-
-/* Declaration for Asc Library internal data referenced by driver. */
-STATIC PortAddr     _asc_def_iop_base[];
+#ifndef ADV_ASSERT
+#define ADV_ASSERT(a)
+#endif /* ADV_ASSERT */
 
 
 /*
- * --- Driver Function Prototypes
- *
- * advansys.h contains function prototypes for functions global to Linux.
+ * --- Driver Constants and Macros
  */
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-STATIC int          asc_proc_copy(off_t, off_t, char *, int , char *, int);
-#endif /* version >= v1.3.0 */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
-STATIC void         advansys_interrupt(int, struct pt_regs *);
-#else /* version >= v1.3.70 */
-STATIC void         advansys_interrupt(int, void *, struct pt_regs *);
-#endif /* version >= v1.3.70 */
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-STATIC void         advansys_select_queue_depths(struct Scsi_Host *,
-                                                Scsi_Device *);
-#endif /* version >= v1.3.89 */
-STATIC void         advansys_command_done(Scsi_Cmnd *);
-STATIC void         asc_scsi_done_list(Scsi_Cmnd *);
-STATIC int          asc_execute_scsi_cmnd(Scsi_Cmnd *);
-STATIC void         asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
-STATIC int          asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *);
-STATIC int          asc_srch_pci_dev(PCI_DEVICE *);
-STATIC uchar        asc_scan_method(void);
-STATIC int          asc_pci_find_dev(PCI_DEVICE *);
-STATIC void         asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *);
-STATIC ushort       asc_get_cfg_word(PCI_DATA *);
-STATIC uchar        asc_get_cfg_byte(PCI_DATA *);
-STATIC void         asc_put_cfg_byte(PCI_DATA *, uchar);
-STATIC void         asc_enqueue(asc_queue_t *, REQP, int);
-STATIC REQP         asc_dequeue(asc_queue_t *, int);
-STATIC REQP         asc_dequeue_list(asc_queue_t *, REQP *, int);
-STATIC int          asc_rmqueue(asc_queue_t *, REQP);
-STATIC int          asc_isqueued(asc_queue_t *, REQP);
-STATIC void         asc_execute_queue(asc_queue_t *);
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-STATIC int            asc_prt_board_devices(struct Scsi_Host *, char *, int);
-STATIC int            asc_prt_board_eeprom(struct Scsi_Host *, char *, int);
-STATIC int            asc_prt_driver_conf(struct Scsi_Host *, char *, int);
-STATIC int            asc_prt_board_info(struct Scsi_Host *, char *, int);
-STATIC int            asc_prt_line(char *, int, char *fmt, ...);
-#endif /* version >= v1.3.0 */
-
-/* Declaration for Asc Library internal functions reference by driver. */
-STATIC int            AscFindSignature(PortAddr);
-STATIC ushort         AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
+#define ASC_NUM_BOARD_SUPPORTED 16
+#define ASC_NUM_IOPORT_PROBE    4
+#define ASC_NUM_BUS             4
 
-#ifdef ADVANSYS_STATS
-STATIC int            asc_prt_board_stats(struct Scsi_Host *, char *, int);
-#endif /* ADVANSYS_STATS */
+/* Reference Scsi_Host hostdata */
+#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
 
-#ifdef ADVANSYS_DEBUG
-STATIC void         asc_prt_scsi_host(struct Scsi_Host *);
-STATIC void         asc_prt_scsi_cmnd(Scsi_Cmnd *);
-STATIC void         asc_prt_dvc_cfg(ASC_DVC_CFG *);
-STATIC void         asc_prt_dvc_var(ASC_DVC_VAR *);
-STATIC void         asc_prt_scsi_q(ASC_SCSI_Q *);
-STATIC void         asc_prt_qdone_info(ASC_QDONE_INFO *);
-STATIC void         asc_prt_hex(char *f, uchar *, int);
-#endif /* ADVANSYS_DEBUG */
+/* asc_board_t flags */
+#define ASC_HOST_IN_RESET       0x01
+#define ASC_HOST_IN_ABORT       0x02
+#define ASC_IS_WIDE_BOARD       0x04    /* AdvanSys Wide Board */
+#define ASC_SELECT_QUEUE_DEPTHS 0x08
 
-#ifdef ADVANSYS_ASSERT
-STATIC int             interrupts_enabled(void);
-#endif /* ADVANSYS_ASSERT */
+#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
+#define ASC_WIDE_BOARD(boardp)   ((boardp)->flags & ASC_IS_WIDE_BOARD)
 
+#define NO_ISA_DMA              0xff        /* No ISA DMA Channel Used */
 
 /*
- * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
+ * If the Linux kernel version supports freeing initialization code
+ * and data after loading, define macros for this purpose. These macros
+ * are not used when the driver is built as a module, cf. linux/init.h.
  */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,23)
+#define ASC_INITFUNC(func)      func
+#define ASC_INITDATA
+#define ASC_INIT
+#else /* version >= v2.1.23 */
+#define ASC_INITFUNC(func)      __initfunc(func)
+#define ASC_INITDATA            __initdata
+#define ASC_INIT                __init
+#endif /* version >= v2.1.23 */
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-/*
- * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
- *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset into a /proc/scsi/advansys/[0...] file
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
- *
- * Return the number of bytes read from or written to a
- * /proc/scsi/advansys/[0...] file.
- *
- * Note: This function uses the per board buffer 'prtbuf' which is
- * allocated when the board is initialized in advansys_detect(). The
- * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
- * used to write to the buffer. The way asc_proc_copy() is written
- * if 'prtbuf' is too small it will not be overwritten. Instead the
- * user just won't get all the available statistics.
- */
-int
-advansys_proc_info(char *buffer, char **start, off_t offset, int length, 
-                   int hostno, int inout)
-{
-    struct Scsi_Host    *shp;
-    asc_board_t         *boardp;
-    int                 i;
-    char                *cp;
-    int                 cplen;
-    int                 cnt;
-    int                 totcnt;
-    int                 leftlen;
-    char                *curbuf;
-    off_t               advoffset;
-    Scsi_Device         *scd = NULL;
+#define ASC_INFO_SIZE           128            /* advansys_info() line size */
 
-    ASC_DBG(1, "advansys_proc_info: begin\n");
+/* /proc/scsi/advansys/[0...] related definitions */
+#define ASC_PRTBUF_SIZE         2048
+#define ASC_PRTLINE_SIZE        160
 
-    /*
-     * User write not supported.
-     */
-    if (inout == TRUE) {
-        return(-ENOSYS);
+#define ASC_PRT_NEXT() \
+    if (cp) { \
+        totlen += len; \
+        leftlen -= len; \
+        if (leftlen == 0) { \
+            return totlen; \
+        } \
+        cp += len; \
     }
 
-    /*
-     * User read of /proc/scsi/advansys/[0...] file.
-     */
-
-    /* Find the specified board. */
-    for (i = 0; i < asc_board_count; i++) {
-        if (asc_host[i]->host_no == hostno) {
-            break;
-        }
-    }
-    if (i == asc_board_count) {
-        return(-ENOENT);
-    }
+#define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
 
-    shp = asc_host[i];
-    boardp = ASC_BOARDP(shp);
+/* Asc Library return codes */
+#define ASC_TRUE        1
+#define ASC_FALSE       0
+#define ASC_NOERROR     1
+#define ASC_BUSY        0
+#define ASC_ERROR       (-1)
 
-    /* Copy read data starting at the beginning of the buffer. */
-    *start = buffer;
-    curbuf = buffer;
-    advoffset = 0;
-    totcnt = 0;
-    leftlen = length;
+/* Scsi_Cmnd function return codes */
+#define STATUS_BYTE(byte)   (byte)
+#define MSG_BYTE(byte)      ((byte) << 8)
+#define HOST_BYTE(byte)     ((byte) << 16)
+#define DRIVER_BYTE(byte)   ((byte) << 24)
 
-    /*
-     * Get board configuration information.
-     *
-     * advansys_info() returns the board string from its own static buffer.
-     */
-    cp = (char *) advansys_info(shp);
-    strcat(cp, "\n");
-    cplen = strlen(cp);
-    /* Copy board information. */
-    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-    totcnt += cnt;
-    leftlen -= cnt;
-    if (leftlen == 0) {
-        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
-        return totcnt;
-    }
-    advoffset += cplen;
-    curbuf += cnt;
+/*
+ * The following definitions and macros are OS independent interfaces to
+ * the queue functions:
+ *  REQ - SCSI request structure
+ *  REQP - pointer to SCSI request structure
+ *  REQPTID(reqp) - reqp's target id
+ *  REQPNEXT(reqp) - reqp's next pointer
+ *  REQPNEXTP(reqp) - pointer to reqp's next pointer
+ *  REQPTIME(reqp) - reqp's time stamp value
+ *  REQTIMESTAMP() - system time stamp value
+ */
+typedef Scsi_Cmnd            REQ, *REQP;
+#define REQPNEXT(reqp)       ((REQP) ((reqp)->host_scribble))
+#define REQPNEXTP(reqp)      ((REQP *) &((reqp)->host_scribble))
+#define REQPTID(reqp)        ((reqp)->target)
+#define REQPTIME(reqp)       ((reqp)->SCp.this_residual)
+#define REQTIMESTAMP()       (jiffies)
 
+#define REQTIMESTAT(function, ascq, reqp, tid) \
+{ \
     /*
-     * Display driver information for each device attached to the board.
-     */
-    cp = boardp->prtbuf;
-    cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE);
-    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-    totcnt += cnt;
-    leftlen -= cnt;
-    if (leftlen == 0) {
-        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
-        return totcnt;
-    }
-    advoffset += cplen;
-    curbuf += cnt;
+     * If the request time stamp is less than the system time stamp, then \
+     * maybe the system time stamp wrapped. Set the request time to zero.\
+     */ \
+    if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
+        REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
+    } else { \
+        /* Indicate an error occurred with the assertion. */ \
+        ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
+        REQPTIME(reqp) = 0; \
+    } \
+    /* Handle first minimum time case without external initialization. */ \
+    if (((ascq)->q_tot_cnt[tid] == 1) ||  \
+        (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
+            (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
+            ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
+                (function), (tid), (ascq)->q_min_tim[tid]); \
+        } \
+    if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
+        (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
+        ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
+            (function), tid, (ascq)->q_max_tim[tid]); \
+    } \
+    (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
+    /* Reset the time stamp field. */ \
+    REQPTIME(reqp) = 0; \
+}
 
-    /*
-     * Display target driver information for each device attached
-     * to the board.
-     */
-    for (scd = scd->host->host_queue; scd; scd = scd->next) {
-            cp = boardp->prtbuf;
-            /*
-             * Note: If proc_print_scsidevice() writes more than
-             * ASC_PRTBUF_SIZE bytes, it will overrun 'prtbuf'.
-             */
-            proc_print_scsidevice(scd, cp, &cplen, 0);
-            ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-            cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-            totcnt += cnt;
-            leftlen -= cnt;
-            if (leftlen == 0) {
-                ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
-                return totcnt;
-            }
-            advoffset += cplen;
-            curbuf += cnt;
-    }
-    
-    /*
-     * Display EEPROM configuration for the board.
-     */
-    cp = boardp->prtbuf;
-    cplen = asc_prt_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
-    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-    totcnt += cnt;
-    leftlen -= cnt;
-    if (leftlen == 0) {
-        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
-        return totcnt;
-    }
-    advoffset += cplen;
-    curbuf += cnt;
+/* asc_enqueue() flags */
+#define ASC_FRONT       1
+#define ASC_BACK        2
 
-    /*
-     * Display driver configuration and information for the board.
-     */
-    cp = boardp->prtbuf;
-    cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE);
-    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-    totcnt += cnt;
-    leftlen -= cnt;
-    if (leftlen == 0) {
-        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
-        return totcnt;
-    }
-    advoffset += cplen;
-    curbuf += cnt;
+/* asc_dequeue_list() argument */
+#define ASC_TID_ALL        (-1)
 
-#ifdef ADVANSYS_STATS
-    /*
-     * Display driver statistics for the board.
-     */
-    cp = boardp->prtbuf;
-    cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE);
-    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-    totcnt += cnt;
-    leftlen -= cnt;
-    if (leftlen == 0) {
-        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
-        return totcnt;
-    }
-    advoffset += cplen;
-    curbuf += cnt;
-#endif /* ADVANSYS_STATS */
+/* Return non-zero, if the queue is empty. */
+#define ASC_QUEUE_EMPTY(ascq)    ((ascq)->q_tidmask == 0)
 
-    /*
-     * Display Asc Library dynamic configuration information
-     * for the board.
-     */
-    cp = boardp->prtbuf;
-    cplen = asc_prt_board_info(shp, cp, ASC_PRTBUF_SIZE);
-    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
-    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
-    totcnt += cnt;
-    leftlen -= cnt;
-    if (leftlen == 0) {
-        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
-        return totcnt;
-    }
-    advoffset += cplen;
-    curbuf += cnt;
+/* PCI configuration declarations */
 
-    ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+#define PCI_BASE_CLASS_PREDEFINED               0x00
+#define PCI_BASE_CLASS_MASS_STORAGE             0x01
+#define PCI_BASE_CLASS_NETWORK                  0x02
+#define PCI_BASE_CLASS_DISPLAY                  0x03
+#define PCI_BASE_CLASS_MULTIMEDIA               0x04
+#define PCI_BASE_CLASS_MEMORY_CONTROLLER        0x05
+#define PCI_BASE_CLASS_BRIDGE_DEVICE            0x06
 
-    return totcnt;
-}
-#endif /* version >= v1.3.0 */
+/* MASS STORAGE */
+#define PCI_SUB_CLASS_SCSI_CONTROLLER           0x00
+#define PCI_SUB_CLASS_IDE_CONTROLLER            0x01
+#define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER    0x02
+#define PCI_SUB_CLASS_IPI_BUS_CONTROLLER        0x03
+#define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER     0x80
 
+/* NETWORK CONTROLLER */
+#define PCI_SUB_CLASS_ETHERNET_CONTROLLER       0x00
+#define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER     0x01
+#define PCI_SUB_CLASS_FDDI_CONTROLLER           0x02
+#define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER  0x80
 
-/*
- * advansys_detect()
- *
- * Detect function for AdvanSys adapters.
- *
- * Argument is a pointer to the host driver's scsi_hosts entry.
- *
- * Return number of adapters found.
- *
- * Note: Because this function is called during system initialization
- * it must not call SCSI mid-level functions including scsi_malloc()
- * and scsi_free().
- */
-ASC_INITFUNC(
-int
-advansys_detect(Scsi_Host_Template *tpnt)
-)
-{
-    static int          detect_called = ASC_FALSE;
-    int                 iop;
-    int                 bus;
-    struct Scsi_Host    *shp;
-    asc_board_t         *boardp;
-    ASC_DVC_VAR         *asc_dvc_varp;
-    int                 ioport = 0;
-    int                 share_irq = FALSE;
-    PCI_DEVICE          pciDevice;
-    PCI_CONFIG_SPACE    pciConfig;
-    int                 ret;
+/* DISPLAY CONTROLLER */
+#define PCI_SUB_CLASS_VGA_CONTROLLER            0x00
+#define PCI_SUB_CLASS_XGA_CONTROLLER            0x01
+#define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER  0x80
 
-    if (detect_called == ASC_FALSE) {
-        detect_called = ASC_TRUE;
-    } else {
-        printk("AdvanSys SCSI: advansys_detect() mulitple calls ignored\n");
-        return 0;
-    }
+/* MULTIMEDIA CONTROLLER */
+#define PCI_SUB_CLASS_VIDEO_DEVICE              0x00
+#define PCI_SUB_CLASS_AUDIO_DEVICE              0x01
+#define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE   0x80
 
-    ASC_DBG(1, "advansys_detect: begin\n");
+/* MEMORY CONTROLLER */
+#define PCI_SUB_CLASS_RAM_CONTROLLER            0x00
+#define PCI_SUB_CLASS_FLASH_CONTROLLER          0x01
+#define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER   0x80
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-    tpnt->proc_dir = &proc_scsi_advansys;
-#endif /* version >= v1.3.0 */
+/* BRIDGE CONTROLLER */
+#define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER    0x00
+#define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER     0x01
+#define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER    0x02
+#define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER      0x03
+#define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER    0x04
+#define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER  0x05
+#define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER   0x80
 
-    asc_board_count = 0;
+#define PCI_MAX_SLOT            0x1F
+#define PCI_MAX_BUS             0xFF
+#define PCI_IOADDRESS_MASK      0xFFFE
+#define ASC_PCI_VENDORID        0x10CD
+#define ASC_PCI_DEVICE_ID_1100  0x1100
+#define ASC_PCI_DEVICE_ID_1200  0x1200
+#define ASC_PCI_DEVICE_ID_1300  0x1300
+#define ASC_PCI_DEVICE_ID_2300  0x2300
 
-    /*
-     * If I/O port probing has been modified, then verify and
-     * clean-up the 'asc_ioport' list.
-     */
-    if (asc_iopflag == ASC_TRUE) {
-        for (ioport = 0; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) {
-            ASC_DBG2(1, "advansys_detect: asc_ioport[%d] %x\n",
-                ioport, asc_ioport[ioport]);
-            if (asc_ioport[ioport] != 0) {
-                for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
-                    if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
-                        break;
-                    }
-                }
-                if (iop == ASC_IOADR_TABLE_MAX_IX) {
-                    printk("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
-                        asc_ioport[ioport]);
-                    asc_ioport[ioport] = 0;
-                }
-            }
-        }
-        ioport = 0;
-    }
+/* PCI IO Port Addresses to generate special cycle */
 
-    memset(&pciDevice, 0, sizeof(PCI_DEVICE));
-    memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
-    pciDevice.maxBusNumber = PCI_MAX_BUS;
-    pciDevice.endSlot = PCI_MAX_SLOT;
+#define PCI_CONFIG_ADDRESS_MECH1          0x0CF8
+#define PCI_CONFIG_DATA_MECH1             0x0CFC
 
-    for (bus = 0; bus < ASC_NUM_BUS; bus++) {
+#define PCI_CONFIG_FORWARD_REGISTER       0x0CFA    /* 0=type 0; 1=type 1; */
 
-        ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
-            bus, asc_bus_name[bus]);
-        iop = 0;
+#define PCI_CONFIG_BUS_NUMBER_MASK        0x00FF0000
+#define PCI_CONFIG_DEVICE_FUNCTION_MASK   0x0000FF00
+#define PCI_CONFIG_REGISTER_NUMBER_MASK   0x000000F8
 
-        while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
+#define PCI_DEVICE_FOUND                0x0000
+#define PCI_DEVICE_NOT_FOUND            0xffff
 
-            ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
-                asc_board_count);
+#define SUBCLASS_OFFSET         0x0A
+#define CLASSCODE_OFFSET        0x0B
+#define VENDORID_OFFSET         0x00
+#define DEVICEID_OFFSET         0x02
 
-            switch (asc_bus[bus]) {
-            case ASC_IS_ISA:
-            case ASC_IS_VL:
-                if (asc_iopflag == ASC_FALSE) {
-                    iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
-                } else {
-                    /*
-                     * ISA and VL I/O port scanning has either been
-                     * eliminated or limited to selected ports on
-                     * the LILO command line, /etc/lilo.conf, or
-                     * by setting variables when the module was loaded.
-                     */
-                    ASC_DBG(1, "advansys_detect: I/O port scanning modified\n");
-                ioport_try_again:
-                    iop = 0;
-                    for (; ioport < ASC_NUM_BOARD_SUPPORTED; ioport++) {
-                        if ((iop = asc_ioport[ioport]) != 0) {
-                            break;
-                        }
-                    }
-                    if (iop) {
-                        ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n",
-                            iop);
-                        if (check_region(iop, ASC_IOADR_GAP) != 0) {
-                            printk("AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
-                            /* Don't try this I/O port twice. */
-                            asc_ioport[ioport] = 0;
-                            goto ioport_try_again;
-                        } else if (AscFindSignature(iop) == ASC_FALSE) {
-                            printk("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
-                            /* Don't try this I/O port twice. */
-                            asc_ioport[ioport] = 0;
-                            goto ioport_try_again;
-                        } else {
-                            /*
-                             * If this isn't an ISA board, then it must be
-                             * a VL board. If currently looking an ISA
-                             * board is being looked for then try for
-                             * another ISA board in 'asc_ioport'.
-                             */
-                            if (asc_bus[bus] == ASC_IS_ISA &&
-                                (AscGetChipVersion(iop, ASC_IS_ISA) &
-                                 ASC_CHIP_VER_ISA_BIT) == 0) {
-                                 /*
-                                 * Don't clear 'asc_ioport[ioport]'. Try
-                                 * this board again for VL. Increment
-                                 * 'ioport' past this board.
-                                 */
-                                 ioport++;
-                                 goto ioport_try_again;
-                            }
-                        }
-                        /*
-                         * This board appears good, don't try the I/O port
-                         * again by clearing its value. Increment 'ioport'
-                         * for the next iteration.
-                         */
-                        asc_ioport[ioport++] = 0;
-                    }
-                }
-                break;
+#ifndef ADVANSYS_STATS
+#define ASC_STATS(shp, counter)
+#define ASC_STATS_ADD(shp, counter, count)
+#else /* ADVANSYS_STATS */
+#define ASC_STATS(shp, counter) \
+    (ASC_BOARDP(shp)->asc_stats.counter++)
 
-            case ASC_IS_EISA:
-                iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
-                break;
+#define ASC_STATS_ADD(shp, counter, count) \
+    (ASC_BOARDP(shp)->asc_stats.counter += (count))
+#endif /* ADVANSYS_STATS */
 
-            case ASC_IS_PCI:
-                    if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
-                        iop = 0;
-                    } else {
-                        ASC_DBG2(2,
-                            "advansys_detect: slotFound %d, busNumber %d\n",
-                            pciDevice.slotFound, pciDevice.busNumber);
-                        asc_get_pci_cfg(&pciDevice, &pciConfig);
-                        iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
-                        ASC_DBG2(2, "advansys_detect: iop %x, irqLine %d\n",
-                            iop, pciConfig.irqLine);
-                    }
-                break;
+#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
 
-            default:
-                ASC_PRINT1("advansys_detect: unknown bus type: %d\n",
-                    asc_bus[bus]);
-                break;
-            }
-            ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
+/* If the result wraps when calculating tenths, return 0. */
+#define ASC_TENTHS(num, den) \
+    (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
+    0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
 
-            /*
-             * Adapter not found, try next bus type.
-             */
-            if (iop == 0) {
-                break;
-            }
+/*
+ * Display a message to the console.
+ */
+#define ASC_PRINT(s) \
+    { \
+        printk("advansys: "); \
+        printk(s); \
+    }
 
-            /*
-             * Adapter found.
-             *
-             * Register the adapter, get its configuration, and
-             * initialize it.
-             */
-            ASC_DBG(2, "advansys_detect: scsi_register()\n");
-            shp = scsi_register(tpnt, sizeof(asc_board_t));
+#define ASC_PRINT1(s, a1) \
+    { \
+        printk("advansys: "); \
+        printk((s), (a1)); \
+    }
 
-            /* Save a pointer to the Scsi_host of each board found. */
-            asc_host[asc_board_count++] = shp;
+#define ASC_PRINT2(s, a1, a2) \
+    { \
+        printk("advansys: "); \
+        printk((s), (a1), (a2)); \
+    }
 
-            /* Initialize private per board data */
-            boardp = ASC_BOARDP(shp);
-            memset(boardp, 0, sizeof(asc_board_t));
-            boardp->id = asc_board_count - 1;
-            asc_dvc_varp = &boardp->asc_dvc_var;
-            asc_dvc_varp->drv_ptr = (ulong) boardp;
-            asc_dvc_varp->cfg = &boardp->asc_dvc_cfg;
-            asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
-            asc_dvc_varp->iop_base = iop;
+#define ASC_PRINT3(s, a1, a2, a3) \
+    { \
+        printk("advansys: "); \
+        printk((s), (a1), (a2), (a3)); \
+    }
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-            if ((boardp->prtbuf =
-                kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
-                ASC_PRINT3(
-"advansys_detect: board %d: kmalloc(%d, %d) returned NULL\n",
-                    boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
-                scsi_unregister(shp);
-                asc_board_count--;
-                continue;
-            }
-#endif /* version >= v1.3.0 */
+#define ASC_PRINT4(s, a1, a2, a3, a4) \
+    { \
+        printk("advansys: "); \
+        printk((s), (a1), (a2), (a3), (a4)); \
+    }
 
-            /*
-             * Set the board bus type and PCI IRQ for AscInitGetConfig().
-             */
-            asc_dvc_varp->bus_type = asc_bus[bus];
-            switch (asc_dvc_varp->bus_type) {
-            case ASC_IS_ISA:
-                shp->unchecked_isa_dma = TRUE;
-                share_irq = FALSE;
-                break;
-            case ASC_IS_VL:
-                shp->unchecked_isa_dma = FALSE;
-                share_irq = FALSE;
-                break;
-            case ASC_IS_EISA:
-                shp->unchecked_isa_dma = FALSE;
-                share_irq = TRUE;
-                break;
-            case ASC_IS_PCI:
-                shp->irq = asc_dvc_varp->irq_no = pciConfig.irqLine;
-                asc_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
-                asc_dvc_varp->cfg->pci_slot_info =
-                        ASC_PCI_MKID(pciDevice.busNumber,
-                                     pciDevice.slotFound,
-                                     pciDevice.devFunc);
-                shp->unchecked_isa_dma = FALSE;
-                share_irq = TRUE;
-                break;
-            default:
-                ASC_PRINT2(
-"advansys_detect: board %d: unknown adapter type: %d",
-                    boardp->id, asc_dvc_varp->bus_type);
-                shp->unchecked_isa_dma = TRUE;
-                share_irq = FALSE;
-                break;
-            }
 
-            /*
-             * Get the board configuration.
-             *
-             * NOTE: AscInitGetConfig() may change the board's bus_type
-             * value. The asc_bus[bus] value should no longer be used. If
-             * the bus_type field must be referenced only use the bit-wise
-             * AND operator "&".
-             */
-            ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
-            switch(ret = AscInitGetConfig(asc_dvc_varp)) {
-            case 0:    /* No error */
-                break;
-            case ASC_WARN_IO_PORT_ROTATE:
-                ASC_PRINT1(
-"AscInitGetConfig: board %d: I/O port address modified\n",
-                    boardp->id);
-                break;
-            case ASC_WARN_AUTO_CONFIG:
-                ASC_PRINT1(
-"AscInitGetConfig: board %d: I/O port increment switch enabled\n",
-                    boardp->id);
-                break;
-            case ASC_WARN_EEPROM_CHKSUM:
-                ASC_PRINT1(
-"AscInitGetConfig: board %d: EEPROM checksum error\n",
-                    boardp->id);
-                break;
-            case ASC_WARN_IRQ_MODIFIED:
-                ASC_PRINT1(
-"AscInitGetConfig: board %d: IRQ modified\n",
-                    boardp->id);
-                break;
-            case ASC_WARN_CMD_QNG_CONFLICT:
-                ASC_PRINT1(
-"AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
-                    boardp->id);
-                break;
-            default:
-                ASC_PRINT2(
-"AscInitGetConfig: board %d: unknown warning: %x\n",
-                    boardp->id, ret);
-                break;
-            }
-            if (asc_dvc_varp->err_code != 0) {
-                ASC_PRINT3(
-"AscInitGetConfig: board %d error: init_state %x, err_code %x\n",
-                    boardp->id, asc_dvc_varp->init_state,
-                    asc_dvc_varp->err_code);
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-                kfree(boardp->prtbuf);
-#endif /* version >= v1.3.0 */
-                scsi_unregister(shp);
-                asc_board_count--;
-                continue;
-            }
+#ifndef ADVANSYS_DEBUG
 
-            /*
-             * Set the adapter's target id bit in the init_tidmask field.
-             */
-            boardp->init_tidmask |=
-                ASC_TIX_TO_TARGET_ID(asc_dvc_varp->cfg->chip_scsi_id);
+#define ASC_DBG(lvl, s)
+#define ASC_DBG1(lvl, s, a1)
+#define ASC_DBG2(lvl, s, a1, a2)
+#define ASC_DBG3(lvl, s, a1, a2, a3)
+#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
+#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
+#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
+#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
+#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
+#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
+#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
+#define ASC_DBG_PRT_HEX(lvl, name, start, length)
+#define ASC_DBG_PRT_CDB(lvl, cdb, len)
+#define ASC_DBG_PRT_SENSE(lvl, sense, len)
+#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
 
-            /*
-             * Save EEPROM settings for the board.
-             */
-            boardp->eep_config.init_sdtr = asc_dvc_varp->init_sdtr;
-            boardp->eep_config.disc_enable = asc_dvc_varp->cfg->disc_enable;
-            boardp->eep_config.use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
-            boardp->eep_config.isa_dma_speed = asc_dvc_varp->cfg->isa_dma_speed;
-            boardp->eep_config.start_motor = asc_dvc_varp->start_motor;
-            boardp->eep_config.cntl = asc_dvc_varp->dvc_cntl;
-            boardp->eep_config.no_scam = asc_dvc_varp->no_scam;
-            boardp->eep_config.max_total_qng = asc_dvc_varp->max_total_qng;
-            boardp->eep_config.chip_scsi_id = asc_dvc_varp->cfg->chip_scsi_id;
-            /* 'max_tag_qng' is set to the same value for every device. */
-            boardp->eep_config.max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
+#else /* ADVANSYS_DEBUG */
 
-            /*
-             * Modify board configuration.
-             */
-            asc_dvc_varp->isr_callback = (Ptr2Func) asc_isr_callback;
-            asc_dvc_varp->exe_callback = (Ptr2Func) NULL;
+/*
+ * Debugging Message Levels:
+ * 0: Errors Only
+ * 1: High-Level Tracing
+ * 2-N: Verbose Tracing
+ */
 
-            ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
-            switch (ret = AscInitSetConfig(asc_dvc_varp)) {
-            case 0:    /* No error. */
-                break;
-            case ASC_WARN_IO_PORT_ROTATE:
-                ASC_PRINT1(
-"AscInitSetConfig: board %d: I/O port address modified\n",
-                    boardp->id);
-                break;
-            case ASC_WARN_AUTO_CONFIG:
-                ASC_PRINT1(
-"AscInitSetConfig: board %d: I/O port increment switch enabled\n",
-                    boardp->id);
-                break;
-            case ASC_WARN_EEPROM_CHKSUM:
-                ASC_PRINT1(
-"AscInitSetConfig: board %d: EEPROM checksum error\n",
-                    boardp->id);
-                break;
-            case ASC_WARN_IRQ_MODIFIED:
-                ASC_PRINT1(
-"AscInitSetConfig: board %d: IRQ modified\n",
-                    boardp->id);
-                break;
-            case ASC_WARN_CMD_QNG_CONFLICT:
-                ASC_PRINT1(
-"AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
-                    boardp->id);
-                break;
-            default:
-                ASC_PRINT2(
-"AscInitSetConfig: board %d: unknown warning: %x\n",
-                    boardp->id, ret);
-                break;
-            }
-            if (asc_dvc_varp->err_code != 0) {
-                ASC_PRINT3(
-"AscInitSetConfig: board %d error: init_state %x, err_code %x\n",
-                    boardp->id, asc_dvc_varp->init_state,
-                    asc_dvc_varp->err_code);
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-                kfree(boardp->prtbuf);
-#endif /* version >= v1.3.0 */
-                scsi_unregister(shp);
-                asc_board_count--;
-                continue;
-            }
+#define ASC_DBG(lvl, s) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            printk(s); \
+        } \
+    }
 
-            /*
-             * Finish initializing the 'Scsi_Host' structure.
-             */
+#define ASC_DBG1(lvl, s, a1) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            printk((s), (a1)); \
+        } \
+    }
 
-            /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
-            if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
-                shp->irq = asc_dvc_varp->irq_no;
-            }
+#define ASC_DBG2(lvl, s, a1, a2) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            printk((s), (a1), (a2)); \
+        } \
+    }
 
-            /*
-             * One host supports one channel. There are two different
-             * hosts for each channel of a dual channel board.
-             */
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-            shp->max_channel = 0;
-#endif /* version >= v1.3.89 */
-            shp->max_id = ASC_MAX_TID + 1;
-            shp->max_lun = ASC_MAX_LUN + 1;
+#define ASC_DBG3(lvl, s, a1, a2, a3) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            printk((s), (a1), (a2), (a3)); \
+        } \
+    }
 
-            shp->io_port = asc_dvc_varp->iop_base;
-            shp->n_io_port = ASC_IOADR_GAP;
-            shp->this_id = asc_dvc_varp->cfg->chip_scsi_id;
+#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            printk((s), (a1), (a2), (a3), (a4)); \
+        } \
+    }
 
-            /* Maximum number of queues this adapter can handle. */
-            shp->can_queue = asc_dvc_varp->max_total_qng;
+#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            asc_prt_scsi_host(s); \
+        } \
+    }
 
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
-            /*
-             * Set a conservative 'cmd_per_lun' value to prevent memory
-             * allocation failures.
-             */
-#ifdef MODULE
-            shp->cmd_per_lun = 1;
-#else /* MODULE */
-            shp->cmd_per_lun = 4;
-#endif /* MODULE */
-            ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
-#else /* version >= v1.3.89 */
-            /*
-             * Use the host 'select_queue_depths' function to determine
-             * the number of commands to queue per device.
-             */
-            shp->select_queue_depths = advansys_select_queue_depths;
+#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            asc_prt_scsi_cmnd(s); \
+        } \
+    }
 
-#ifdef MODULE
-           /*
-            * FIXME(eric) - this is completely bogus.  We need to
-            * figure out what exactly the real problem is and deal
-            * with it.
-            */
-           /*
-            * Following v1.3.89, 'cmd_per_lun' is no longer needed
-            * and should be set to zero. But because of a bug introduced
-            * in v1.3.89 if the driver is compiled as a module and
-            * 'cmd_per_lun' is zero, the Mid-Level SCSI function
-            * 'scsi_allocate_device' will panic. To allow the driver to
-            * work as a module in these kernels set 'cmd_per_lun' to 1.
-            */
-           shp->cmd_per_lun = 1;
-#else /* MODULE */
-            shp->cmd_per_lun = 0;
-#endif /* MODULE */
-#endif /* version >= v1.3.89 */
+#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            asc_prt_asc_scsi_q(scsiqp); \
+        } \
+    }
 
-            /*
-             * Set the maximum number of scatter-gather elements adapter
-             * can handle.
-             */
+#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            asc_prt_asc_qdone_info(qdone); \
+        } \
+    }
 
-#ifdef MODULE
-            /*
-             * If the driver is compiled as a module, set a conservative
-             * 'sg_tablesize' value to prevent memory allocation failures.
-             * Memory allocation errors are more likely to occur at module
-             * load time, then at driver initialization time.
-             */
-            shp->sg_tablesize = 8;
-#else /* MODULE */
-            /*
-             * Allow two commands with 'sg_tablesize' scatter-gather
-             * elements to be executed simultaneously. This value is
-             * the theoretical hardware limit. It may be decreased
-             * below.
-             */
-            shp->sg_tablesize =
-                (((asc_dvc_varp->max_total_qng - 2) / 2) *
-                ASC_SG_LIST_PER_Q) + 1;
-#endif /* MODULE */
+#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            asc_prt_adv_scsi_req_q(scsiqp); \
+        } \
+    }
 
-            /*
-             * The value of 'sg_tablesize' can not exceed the SCSI
-             * mid-level driver definition of SG_ALL. SG_ALL also
-             * must not be exceeded, because it is used to define the
-             * size of the scatter-gather table in 'struct asc_sg_head'.
-             */
-            if (shp->sg_tablesize > SG_ALL) {
-                shp->sg_tablesize = SG_ALL;
-            }
+#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
+    { \
+        if (asc_dbglvl >= (lvl)) { \
+            asc_prt_hex((name), (start), (length)); \
+        } \
+    }
 
-            ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
-                shp->sg_tablesize);
+#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
+        ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
 
-            /* BIOS start address. */
-            shp->base = (char *) ((ulong) AscGetChipBiosAddress(
-                                                asc_dvc_varp->iop_base,
-                                                asc_dvc_varp->bus_type));
+#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
+        ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
 
-            /*
-             * Register Board Resources - I/O Port, DMA, IRQ
-             */
+#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
+        ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
+#endif /* ADVANSYS_DEBUG */
 
-            /* Register I/O port range */
-            ASC_DBG(2, "advansys_detect: request_region()\n");
-            request_region(shp->io_port, shp->n_io_port, "advansys");
+#ifndef ADVANSYS_ASSERT
+#define ASC_ASSERT(a)
+#else /* ADVANSYS_ASSERT */
 
-            /* Register DMA channel for ISA bus. */
-            if ((asc_dvc_varp->bus_type & ASC_IS_ISA) == 0) {
-                shp->dma_channel = NO_ISA_DMA;
-            } else {
-                shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
-                if ((ret = request_dma(shp->dma_channel, "advansys")) != 0) {
-                    ASC_PRINT3(
-"advansys_detect: board %d: request_dma() %d failed %d\n",
-                        boardp->id, shp->dma_channel, ret);
-                    release_region(shp->io_port, shp->n_io_port);
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-                    kfree(boardp->prtbuf);
-#endif /* version >= v1.3.0 */
-                    scsi_unregister(shp);
-                    asc_board_count--;
-                    continue;
-                }
-                AscEnableIsaDma(shp->dma_channel);
-            }
+#define ASC_ASSERT(a) \
+    { \
+        if (!(a)) { \
+            printk("ASC_ASSERT() Failure: file %s, line %d\n", \
+                __FILE__, __LINE__); \
+        } \
+    }
 
-            /* Register IRQ Number. */
-            ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
-            if ((ret = request_irq(shp->irq, advansys_interrupt,
-                            SA_INTERRUPT, "advansys")) != 0) {
-#else /* version >= v1.3.70 */
-            if ((ret = request_irq(shp->irq, advansys_interrupt,
-                            SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
-                            "advansys", boardp)) != 0) {
-#endif /* version >= v1.3.70 */
-                ASC_PRINT2(
-"advansys_detect: board %d: request_irq() failed %d\n",
-                    boardp->id, ret);
-                release_region(shp->io_port, shp->n_io_port);
-                if (shp->dma_channel != NO_ISA_DMA) {
-                    free_dma(shp->dma_channel);
-                }
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-                kfree(boardp->prtbuf);
-#endif /* version >= v1.3.0 */
-                scsi_unregister(shp);
-                asc_board_count--;
-                continue;
-            }
+#endif /* ADVANSYS_ASSERT */
 
-            /*
-             * Initialize board RISC chip and enable interrupts.
-             */
-            ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
-            if (AscInitAsc1000Driver(asc_dvc_varp)) {
-                ASC_PRINT3(
-"AscInitAsc1000Driver: board %d: error: init_state %x, err_code %x\n",
-                    boardp->id, asc_dvc_varp->init_state,
-                    asc_dvc_varp->err_code);
-                release_region(shp->io_port, shp->n_io_port);
-                if (shp->dma_channel != NO_ISA_DMA) {
-                    free_dma(shp->dma_channel);
-                }
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-                kfree(boardp->prtbuf);
-#endif /* version >= v1.3.0 */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
-                free_irq(shp->irq);
-#else /* version >= v1.3.70 */
-                free_irq(shp->irq, boardp);
-#endif /* version >= v1.3.70 */
-                scsi_unregister(shp);
-                asc_board_count--;
-                continue;
-            }
-            ASC_DBG_PRT_SCSI_HOST(2, shp);
-        }
-    }
-    ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
-    return asc_board_count;
-}
 
 /*
- * advansys_release()
- *
- * Release resources allocated for a single AdvanSys adapter.
+ * --- Driver Structures
  */
-int
-advansys_release(struct Scsi_Host *shp)
-{
-    asc_board_t    *boardp;
 
-    ASC_DBG(1, "advansys_release: begin\n");
-    boardp = ASC_BOARDP(shp);
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
-    free_irq(shp->irq);
-#else /* version >= v1.3.70 */
-    free_irq(shp->irq, boardp);
-#endif /* version >= v1.3.70 */
-    if (shp->dma_channel != NO_ISA_DMA) {
-        ASC_DBG(1, "advansys_release: free_dma()\n");
-        free_dma(shp->dma_channel);
-    }
-    release_region(shp->io_port, shp->n_io_port);
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-    ASC_ASSERT(boardp->prtbuf != NULL);
-    kfree(boardp->prtbuf);
-#endif /* version >= v1.3.0 */
-    scsi_unregister(shp);
-    ASC_DBG(1, "advansys_release: end\n");
-    return 0;
-}
+#ifdef ADVANSYS_STATS
+
+/* Per board statistics structure */
+struct asc_stats {
+    /* Driver Entrypoint Statistics */
+    ulong     command;         /* # calls to advansys_command() */
+    ulong     queuecommand;    /* # calls to advansys_queuecommand() */
+    ulong     abort;           /* # calls to advansys_abort() */
+    ulong     reset;           /* # calls to advansys_reset() */
+    ulong     biosparam;       /* # calls to advansys_biosparam() */
+    ulong     interrupt;       /* # advansys_interrupt() calls */
+    ulong     callback;        /* # calls to asc/adv_isr_callback() */
+    ulong     done;            /* # calls to request's scsi_done function */
+    ulong     build_error;     /* # asc/adv_build_req() ASC_ERROR returns. */
+    ulong     adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
+    ulong     adv_build_nosg;  /* # adv_build_req() adv_sgblk_t alloc. fail. */
+    /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
+    ulong     exe_noerror;     /* # ASC_NOERROR returns. */
+    ulong     exe_busy;        /* # ASC_BUSY returns. */
+    ulong     exe_error;       /* # ASC_ERROR returns. */
+    ulong     exe_unknown;     /* # unknown returns. */
+    /* Data Transfer Statistics */
+    ulong     cont_cnt;        /* # non-scatter-gather I/O requests received */
+    ulong     cont_xfer;       /* # contiguous transfer 512-bytes */
+    ulong     sg_cnt;          /* # scatter-gather I/O requests received */
+    ulong     sg_elem;         /* # scatter-gather elements */
+    ulong     sg_xfer;         /* # scatter-gather transfer 512-bytes */
+};
+#endif /* ADVANSYS_STATS */
 
 /*
- * advansys_info()
- *
- * Return suitable for printing on the console with the argument
- * adapter's configuration information.
- *
- * Note: The information line should not exceed ASC_INFO_SIZE bytes,
- * otherwise the static 'info' array will be overrun.
+ * Request queuing structure
  */
-const char *
-advansys_info(struct Scsi_Host *shp)
-{
-    static char     info[ASC_INFO_SIZE];
-    asc_board_t     *boardp;
-    ASC_DVC_VAR     *asc_dvc_varp;
-    char            *busname;
-
-    boardp = ASC_BOARDP(shp);
-    asc_dvc_varp = &boardp->asc_dvc_var;
-    ASC_DBG(1, "advansys_info: begin\n");
-    if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
-        if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) {
-            busname = "ISA PnP";
-        } else {
-            busname = "ISA";
-        }
-        sprintf(info,
-            "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X-%X, IRQ %u, DMA %u",
-            ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
-            (unsigned) shp->base, shp->io_port,
-            shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel);
-    } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
-        if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
-            == ASC_IS_PCI_ULTRA) {
-            busname = "PCI Ultra";
-        } else {
-            busname = "PCI";
-        }
-        sprintf(info,
-            "AdvanSys SCSI %s: %s %u CDB: IO %X-%X, IRQ %u",
-            ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
-            shp->io_port, shp->io_port + (shp->n_io_port - 1), shp->irq);
-    } else {
-        if (asc_dvc_varp->bus_type & ASC_IS_VL) {
-            busname = "VL";
-        } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
-            busname = "EISA";
-        } else {
-            busname = "?";
-            ASC_PRINT2(
-"advansys_info: board %d: unknown bus type %d\n",
-                boardp->id, asc_dvc_varp->bus_type);
-        }
-        sprintf(info,
-            "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X-%X, IRQ %u",
-            ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
-            (unsigned) shp->base, shp->io_port,
-            shp->io_port + (shp->n_io_port - 1), shp->irq);
-    }
-    ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
-    ASC_DBG(1, "advansys_info: end\n");
-    return info;
-}
+typedef struct asc_queue {
+    ADV_SCSI_BIT_ID_TYPE  q_tidmask;                /* queue mask */
+    REQP                  q_first[ADV_MAX_TID+1];   /* first queued request */
+    REQP                  q_last[ADV_MAX_TID+1];    /* last queued request */
+#ifdef ADVANSYS_STATS
+    short                 q_cur_cnt[ADV_MAX_TID+1]; /* current queue count */
+    short                 q_max_cnt[ADV_MAX_TID+1]; /* maximum queue count */
+    ulong                 q_tot_cnt[ADV_MAX_TID+1]; /* total enqueue count */
+    ulong                 q_tot_tim[ADV_MAX_TID+1]; /* total time queued */
+    ushort                q_max_tim[ADV_MAX_TID+1]; /* maximum time queued */
+    ushort                q_min_tim[ADV_MAX_TID+1]; /* minimum time queued */
+#endif /* ADVANSYS_STATS */
+} asc_queue_t;
 
 /*
- * advansys_command()
+ * Adv Library Request Structures
  *
- * Polled-I/O. Apparently host drivers shouldn't return until
- * command is finished.
+ * The following two se structures are used to process Wide Board requests.
+ * One structure is needed for each command received from the Mid-Level SCSI
+ * driver.
  *
- * Note: This is an old interface that is no longer used by the SCSI
- * mid-level driver. The new interface, advansys_queuecommand(),
- * currently handles all requests.
+ * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
+ * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
+ * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
+ * Mid-Level SCSI request structure.
+ *
+ * The adv_sgblk_t structure is used to handle requests that include
+ * scatter-gather elements.
  */
-int
-advansys_command(Scsi_Cmnd *scp)
-{
-    ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
-    ASC_STATS(scp->host, command);
-    scp->SCp.Status = 0; /* Set to a known state */
-    advansys_queuecommand(scp, advansys_command_done);
-    /*
-     * XXX - Can host drivers block here instead of spinning on
-     * command status?
-     */
-    while (scp->SCp.Status == 0) {
-        continue;
-    }
-    ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
-    return scp->result;
-}
+typedef struct adv_sgblk {
+    ADV_SG_BLOCK        sg_block[ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING];
+    uchar               align2[4];       /* Sgblock structure padding. */
+    struct adv_sgblk    *next_sgblkp;    /* Next scatter-gather structure. */
+} adv_sgblk_t;
+
+typedef struct adv_req {
+    ADV_SCSI_REQ_Q      scsi_req_q;   /* Adv Library request structure. */
+    uchar               align1[4];    /* Request structure padding. */
+    Scsi_Cmnd           *cmndp;       /* Mid-Level SCSI command pointer. */
+    adv_sgblk_t         *sgblkp;      /* Adv Library scatter-gather pointer. */
+    struct adv_req      *next_reqp;   /* Next Request Structure. */
+} adv_req_t;
 
 /*
- * advansys_queuecommand()
+ * Structure allocated for each board.
  *
- * This function always returns 0. Command return status is saved
- * in the 'scp' result field.
+ * This structure is allocated by scsi_register() at the end
+ * of the 'Scsi_Host' structure starting at the 'hostdata'
+ * field. It is guaranteed to be allocated from DMA-able memory.
  */
-int
-advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
-{
-    struct Scsi_Host    *shp;
-    asc_board_t         *boardp;
-    int                 flags;
-    Scsi_Cmnd           *done_scp;
-
-    shp = scp->host;
-    boardp = ASC_BOARDP(shp);
-    ASC_STATS(shp, queuecommand);
-
+typedef struct asc_board {
+    int                  id;                    /* Board Id */
+    uint                 flags;                 /* Board flags */
+    union {
+        ASC_DVC_VAR      asc_dvc_var;           /* Narrow board */
+        ADV_DVC_VAR      adv_dvc_var;           /* Wide board */
+    } dvc_var;
+    union {
+        ASC_DVC_CFG      asc_dvc_cfg;           /* Narrow board */
+        ADV_DVC_CFG      adv_dvc_cfg;           /* Wide board */
+    } dvc_cfg;
+    asc_queue_t          active;                /* Active command queue */
+    asc_queue_t          waiting;               /* Waiting command queue */
+    asc_queue_t          done;                  /* Done command queue */
+    ADV_SCSI_BIT_ID_TYPE init_tidmask;          /* Target init./valid mask */
+    Scsi_Device          *device[ADV_MAX_TID+1]; /* Mid-Level Scsi Device */
+    ushort               reqcnt[ADV_MAX_TID+1]; /* Starvation request count */
+#if ASC_QUEUE_FLOW_CONTROL
+    ushort               nerrcnt[ADV_MAX_TID+1]; /* No error request count */
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+    ADV_SCSI_BIT_ID_TYPE queue_full;            /* Queue full mask */
+    ushort               queue_full_cnt[ADV_MAX_TID+1]; /* Queue full count */
+    union {
+        ASCEEP_CONFIG    asc_eep;               /* Narrow EEPROM config. */
+        ADVEEP_CONFIG    adv_eep;               /* Wide EEPROM config. */
+    } eep_config;
+    ulong                last_reset;            /* Saved last reset time */
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+    /* /proc/scsi/advansys/[0...] */
+    char                 *prtbuf;               /* Statistics Print Buffer */
+#endif /* version >= v1.3.0 */
+#ifdef ADVANSYS_STATS
+    struct asc_stats     asc_stats;             /* Board statistics */
+#endif /* ADVANSYS_STATS */
     /*
-     * Disable interrupts to preserve request ordering and provide
-     * mutually exclusive access to global structures used to initiate
-     * a request.
+     * The following fields are used only for Narrow Boards.
      */
-    save_flags(flags);
-    cli();
-
+    /* The following three structures must be in DMA-able memory. */
+    ASC_SCSI_REQ_Q       scsireqq;
+    ASC_CAP_INFO         cap_info;
+    ASC_SCSI_INQUIRY     inquiry;
+    uchar                sdtr_data[ASC_MAX_TID+1]; /* SDTR information */
     /*
-     * Block new commands while handling a reset or abort request.
+     * The following fields are used only for Wide Boards.
      */
-    if (boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
-        if (boardp->flags & ASC_HOST_IN_RESET) {
-            ASC_DBG1(1,
-                "advansys_queuecommand: scp %x blocked for reset request\n",
-                (unsigned) scp);
-            scp->result = HOST_BYTE(DID_RESET);
-        } else {
-            ASC_DBG1(1,
-                "advansys_queuecommand: scp %x blocked for abort request\n",
-                (unsigned) scp);
-            scp->result = HOST_BYTE(DID_ABORT);
-        }
+    void                 *ioremap_addr;         /* I/O Memory remap address. */
+    ushort               ioport;                /* I/O Port address. */
+    adv_req_t            *orig_reqp;            /* adv_req_t memory block. */
+    adv_req_t            *adv_reqp;             /* Request structures. */
+    adv_sgblk_t          *orig_sgblkp;          /* adv_sgblk_t memory block. */
+    adv_sgblk_t          *adv_sgblkp;           /* Scatter-gather structures. */
+    ushort               bios_signature;        /* BIOS Signature. */
+    ushort               bios_version;          /* BIOS Version. */
+    ushort               bios_codeseg;          /* BIOS Code Segment. */
+    ushort               bios_codelen;          /* BIOS Code Segment Length. */
+} asc_board_t;
 
-        /*
-         * Add blocked requests to the board's 'done' queue. The queued
-         * requests will be completed at the end of the abort or reset
-         * handling.
-         */
-        asc_enqueue(&boardp->done, scp, ASC_BACK);
-        restore_flags(flags);
-        return 0;
-    }
+/*
+ * PCI configuration structures
+ */
+typedef struct _PCI_DATA_
+{
+    uchar    type;
+    uchar    bus;
+    uchar    slot;
+    uchar    func;
+    uchar    offset;
+} PCI_DATA;
 
-    /*
-     * Attempt to execute any waiting commands for the board.
-     */
-    if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
-        ASC_DBG(1,
-            "advansys_queuecommand: before asc_execute_queue() waiting\n");
-        asc_execute_queue(&boardp->waiting);
-    }
+typedef struct _PCI_DEVICE_
+{
+    ushort   vendorID;
+    ushort   deviceID;
+    ushort   slotNumber;
+    ushort   slotFound;
+    uchar    busNumber;
+    uchar    maxBusNumber;
+    uchar    devFunc;
+    ushort   startSlot;
+    ushort   endSlot;
+    uchar    bridge;
+    uchar    type;
+} PCI_DEVICE;
 
-    /*
-     * Save the function pointer to Linux mid-level 'done' function
-     * and attempt to execute the command.
-     *
-     * If ASC_ERROR is returned the request has been added to the
-     * board's 'active' queue and will be completed by the interrupt
-     * handler.
-     *
-     * If ASC_BUSY is returned add the request to the board's per
-     * target waiting list.
-     * 
-     * If an error occurred, the request will have been placed on the
-     * board's 'done' queue and must be completed before returning.
-     */
-    scp->scsi_done = done;
-    switch (asc_execute_scsi_cmnd(scp)) {
-    case ASC_NOERROR:
-        break;
-    case ASC_BUSY:
-        asc_enqueue(&boardp->waiting, scp, ASC_BACK);
-        break;
-    case ASC_ERROR:
-    default:
-        done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
-        /* Interrupts could be enabled here. */
-        asc_scsi_done_list(done_scp);
-        break;
-    }
+typedef struct _PCI_CONFIG_SPACE_
+{
+    ushort   vendorID;
+    ushort   deviceID;
+    ushort   command;
+    ushort   status;
+    uchar    revision;
+    uchar    classCode[3];
+    uchar    cacheSize;
+    uchar    latencyTimer;
+    uchar    headerType;
+    uchar    bist;
+    ulong    baseAddress[6];
+    ushort   reserved[4];
+    ulong    optionRomAddr;
+    ushort   reserved2[4];
+    uchar    irqLine;
+    uchar    irqPin;
+    uchar    minGnt;
+    uchar    maxLatency;
+} PCI_CONFIG_SPACE;
 
-    restore_flags(flags);
-    return 0;
-}
 
 /*
- * advansys_abort()
- *
- * Abort the command specified by 'scp'.
+ * --- Driver Data
  */
-int
-advansys_abort(Scsi_Cmnd *scp)
-{
-    struct Scsi_Host    *shp;
-    asc_board_t         *boardp;
-    ASC_DVC_VAR         *asc_dvc_varp;
-    int                 flags;
-    int                 do_scsi_done;
-    int                 scp_found;
-    Scsi_Cmnd           *done_scp = NULL;
-    int                 ret;
 
-    /* Save current flags and disable interrupts. */
-    save_flags(flags);
-    cli();
+/* Note: All driver global data should be initialized. */
 
-    ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+struct proc_dir_entry proc_scsi_advansys =
+{
+    PROC_SCSI_ADVANSYS,              /* unsigned short low_ino */
+    8,                               /* unsigned short namelen */
+    "advansys",                      /* const char *name */
+    S_IFDIR | S_IRUGO | S_IXUGO,     /* mode_t mode */
+    2                                /* nlink_t nlink */
+};
+#endif /* version >= v1.3.0 */
 
-#ifdef ADVANSYS_STATS
-    if (scp->host != NULL) {
-        ASC_STATS(scp->host, abort);
-    }    
-#endif /* ADVANSYS_STATS */
+/* Number of boards detected in system. */
+STATIC int asc_board_count = 0;
+STATIC struct Scsi_Host    *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
 
-#ifdef ADVANSYS_ASSERT
-    do_scsi_done = ASC_ERROR;
-    scp_found = ASC_ERROR;
-    ret = ASC_ERROR;
-#endif /* ADVANSYS_ASSERT */
+/* Overrun buffer shared between all boards. */
+STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-    if (scp->serial_number != scp->serial_number_at_timeout) {
-        ASC_PRINT1(
-"advansys_abort: timeout serial number changed for request %x\n",
-            (unsigned) scp);
-        do_scsi_done = ASC_FALSE;
-        scp_found = ASC_FALSE;
-        ret = SCSI_ABORT_NOT_RUNNING;
-    } else
-#endif /* version >= v1.3.89 */
-    if ((shp = scp->host) == NULL) {
-        scp->result = HOST_BYTE(DID_ERROR);
-        do_scsi_done = ASC_TRUE;
-        scp_found = ASC_FALSE;
-        ret = SCSI_ABORT_ERROR;
-    } else if ((boardp = ASC_BOARDP(shp))->flags & 
-                (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
-        ASC_PRINT2(
-"advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n",
-            boardp->id, boardp->flags);
-        do_scsi_done = ASC_TRUE;
-        if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
-            (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
-            scp_found = ASC_TRUE;
-        } else {
-            scp_found = ASC_FALSE;
-        }
-        scp->result = HOST_BYTE(DID_ERROR);
-        ret = SCSI_ABORT_ERROR;
-    } else {
-        /* Set abort flag to avoid nested reset or abort requests. */
-        boardp->flags |= ASC_HOST_IN_ABORT;
+/*
+ * Global structures required to issue a command.
+ */
+STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } };
+STATIC ASC_SG_HEAD asc_sg_head = { 0 };
 
-        do_scsi_done = ASC_TRUE;
-        if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
-            /*
-              * If asc_rmqueue() found the command on the waiting
-             * queue, it had not been sent to the device. After
-             * the queue is removed, no other handling is required.
-              */
-            ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n",
-                (unsigned) scp);
-            scp_found = ASC_TRUE;
-            scp->result = HOST_BYTE(DID_ABORT);
-            ret = SCSI_ABORT_SUCCESS;
-        } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) {
-            /*
-              * If asc_isqueued() found the command on the active
-             * queue, it has been sent to the device. The command
-             * should be returned through the interrupt handler after
-             * calling AscAbortSRB().
-              */
-            asc_dvc_varp = &boardp->asc_dvc_var;
-            scp->result = HOST_BYTE(DID_ABORT);
+/* List of supported bus types. */
+STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = {
+    ASC_IS_ISA,
+    ASC_IS_VL,
+    ASC_IS_EISA,
+    ASC_IS_PCI,
+};
 
-            sti(); /* Enable interrupts for AscAbortSRB(). */
-            ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n",
-                (unsigned) scp);
-            switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
-            case ASC_TRUE:
-                /* asc_isr_callback() will be called */
-                ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
-                ret = SCSI_ABORT_PENDING;
-                break;
-            case ASC_FALSE:
-                /* Request has apparently already completed. */
-                ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
-                ret = SCSI_ABORT_NOT_RUNNING;
-                break;
-            case ASC_ERROR:
-            default:
-                ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
-                ret = SCSI_ABORT_ERROR;
-                break;
-            }
-            cli();
+STATIC int pci_scan_method ASC_INITDATA = -1;
 
-            /*
-             * The request will either still be on the active queue
-             * or have been added to the board's done queue.
-             */
-            if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
-                scp->result = HOST_BYTE(DID_ABORT);
-                scp_found = ASC_TRUE;
-            } else {
-                scp_found = asc_rmqueue(&boardp->done, scp);
-                ASC_ASSERT(scp_found == ASC_TRUE);
-            }
+/*
+ * Used with the LILO 'advansys' option to eliminate or
+ * limit I/O port probing at boot time, cf. advansys_setup().
+ */
+STATIC int asc_iopflag = ASC_FALSE;
+STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
 
-        } else {
-            /*
-             * The command was not found on the active or waiting queues.
-             */
-            do_scsi_done = ASC_TRUE;
-            scp_found = ASC_FALSE;
-            ret = SCSI_ABORT_NOT_RUNNING;
-        }
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+/*
+ * In kernels earlier than v1.3.0, kmalloc() does not work
+ * during driver initialization. Therefore statically declare
+ * 16 elements of each structure. v1.3.0 kernels will probably
+ * not need any more than this number.
+ */
+uchar adv_req_buf[16 * sizeof(adv_req_t)] = { 0 };
+uchar adv_sgblk_buf[16 * sizeof(adv_sgblk_t)] = { 0 };
+#endif /* version >= v1,3,0 */
 
-        /* Clear abort flag. */
-        boardp->flags &= ~ASC_HOST_IN_ABORT;
+#ifdef ADVANSYS_DEBUG
+STATIC char *
+asc_bus_name[ASC_NUM_BUS] = {
+    "ASC_IS_ISA",
+    "ASC_IS_VL",
+    "ASC_IS_EISA",
+    "ASC_IS_PCI",
+};
 
-        /*
-         * Because the ASC_HOST_IN_ABORT flag causes both
-         * 'advansys_interrupt' and 'asc_isr_callback' to
-         * queue requests to the board's 'done' queue and
-         * prevents waiting commands from being executed,
-         * these queued requests must be handled here.
-         */
-        done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
+STATIC int          asc_dbglvl = 0;
+#endif /* ADVANSYS_DEBUG */
 
-        /*
-         * Start any waiting commands for the board.
-         */
-        if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
-            ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
-            asc_execute_queue(&boardp->waiting);
-        }
-    }
+/* Declaration for Asc Library internal data referenced by driver. */
+STATIC PortAddr     _asc_def_iop_base[];
 
-    /* Interrupts could be enabled here. */
 
-    /*
-     * Complete the request to be aborted, unless it has been
-     * restarted as detected above, even if it was not found on
-     * the device active or waiting queues.
-     */
-    ASC_ASSERT(do_scsi_done != ASC_ERROR);
-    ASC_ASSERT(scp_found != ASC_ERROR);
-    if (do_scsi_done == ASC_TRUE) {
-        if (scp->scsi_done == NULL) {
-            ASC_PRINT1(
-"advansys_abort: aborted request scsi_done() is NULL, %x\n",
-                (unsigned) scp);
-        } else {
-            if (scp_found == ASC_FALSE) {
-                ASC_PRINT1(
-"advansys_abort: abort request not active or waiting, completing anyway %x\n",
-                    (unsigned) scp);
-            }
-            ASC_STATS(scp->host, done);
-            scp->scsi_done(scp);
-        }
-    }
+/*
+ * --- Driver Function Prototypes
+ *
+ * advansys.h contains function prototypes for functions global to Linux.
+ */
 
-    /*
-     * It is possible for the request done function to re-enable
-     * interrupts without confusing the driver. But here interrupts
-     * aren't enabled until all requests have been completed.
-     */
-    if (done_scp != NULL) {
-        asc_scsi_done_list(done_scp);
-    }
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+STATIC int          asc_proc_copy(off_t, off_t, char *, int , char *, int);
+#endif /* version >= v1.3.0 */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
+STATIC void         advansys_interrupt(int, struct pt_regs *);
+#else /* version >= v1.3.70 */
+STATIC void         advansys_interrupt(int, void *, struct pt_regs *);
+#endif /* version >= v1.3.70 */
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+STATIC void         advansys_select_queue_depths(struct Scsi_Host *,
+                                                Scsi_Device *);
+#endif /* version >= v1.3.89 */
+STATIC void       advansys_command_done(Scsi_Cmnd *);
+STATIC void       asc_scsi_done_list(Scsi_Cmnd *);
+STATIC int        asc_execute_scsi_cmnd(Scsi_Cmnd *);
+STATIC int        asc_build_req(asc_board_t *, Scsi_Cmnd *);
+STATIC int        adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **);
+STATIC int        adv_get_sglist(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, Scsi_Cmnd *);
+STATIC void       asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
+STATIC void       adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
+STATIC int        asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *);
+STATIC int        asc_srch_pci_dev(PCI_DEVICE *);
+STATIC uchar      asc_scan_method(void);
+STATIC int        asc_pci_find_dev(PCI_DEVICE *);
+STATIC void       asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *);
+STATIC ushort     asc_get_cfg_word(PCI_DATA *);
+STATIC uchar      asc_get_cfg_byte(PCI_DATA *);
+STATIC void       asc_put_cfg_byte(PCI_DATA *, uchar);
+STATIC void       asc_enqueue(asc_queue_t *, REQP, int);
+STATIC REQP       asc_dequeue(asc_queue_t *, int);
+STATIC REQP       asc_dequeue_list(asc_queue_t *, REQP *, int);
+STATIC int        asc_rmqueue(asc_queue_t *, REQP);
+STATIC int        asc_isqueued(asc_queue_t *, REQP);
+STATIC void       asc_execute_queue(asc_queue_t *);
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+STATIC int        asc_prt_board_devices(struct Scsi_Host *, char *, int);
+STATIC int        asc_prt_adv_bios(struct Scsi_Host *, char *, int);
+STATIC int        asc_get_eeprom_string(ushort *serialnum, uchar *cp);
+STATIC int        asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
+STATIC int        asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
+STATIC int        asc_prt_driver_conf(struct Scsi_Host *, char *, int);
+STATIC int        asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
+STATIC int        asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
+STATIC int        asc_prt_line(char *, int, char *fmt, ...);
+#endif /* version >= v1.3.0 */
 
-    ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
+/* Declaration for Asc Library internal functions reference by driver. */
+STATIC int          AscFindSignature(PortAddr);
+STATIC ushort       AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
 
-    /* Re-enable interrupts, if they were enabled on entry. */
-    restore_flags(flags);
+#ifdef ADVANSYS_STATS
+STATIC int          asc_prt_board_stats(struct Scsi_Host *, char *, int);
+#endif /* ADVANSYS_STATS */
+
+#ifdef ADVANSYS_DEBUG
+STATIC void         asc_prt_scsi_host(struct Scsi_Host *);
+STATIC void         asc_prt_scsi_cmnd(Scsi_Cmnd *);
+STATIC void         asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
+STATIC void         asc_prt_asc_dvc_var(ASC_DVC_VAR *);
+STATIC void         asc_prt_asc_scsi_q(ASC_SCSI_Q *);
+STATIC void         asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
+STATIC void         asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
+STATIC void         asc_prt_adv_dvc_var(ADV_DVC_VAR *);
+STATIC void         asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
+STATIC void         asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
+STATIC void         asc_prt_hex(char *f, uchar *, int);
+#endif /* ADVANSYS_DEBUG */
+
+#ifdef ADVANSYS_ASSERT
+STATIC int             interrupts_enabled(void);
+#endif /* ADVANSYS_ASSERT */
 
-    ASC_ASSERT(ret != ASC_ERROR);
-    return ret;
-}
 
 /*
- * advansys_reset()
+ * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
+ */
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+/*
+ * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
  *
- * Reset the device associated with the command 'scp'.
+ * *buffer: I/O buffer
+ * **start: if inout == FALSE pointer into buffer where user read should start
+ * offset: current offset into a /proc/scsi/advansys/[0...] file
+ * length: length of buffer
+ * hostno: Scsi_Host host_no
+ * inout: TRUE - user is writing; FALSE - user is reading
+ *
+ * Return the number of bytes read from or written to a
+ * /proc/scsi/advansys/[0...] file.
+ *
+ * Note: This function uses the per board buffer 'prtbuf' which is
+ * allocated when the board is initialized in advansys_detect(). The
+ * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
+ * used to write to the buffer. The way asc_proc_copy() is written
+ * if 'prtbuf' is too small it will not be overwritten. Instead the
+ * user just won't get all the available statistics.
  */
 int
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
-advansys_reset(Scsi_Cmnd *scp)
-#else /* version >= v1.3.89 */
-advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
-#endif /* version >= v1.3.89 */
+advansys_proc_info(char *buffer, char **start, off_t offset, int length, 
+                   int hostno, int inout)
 {
-    struct Scsi_Host     *shp;
-    asc_board_t          *boardp;
-    ASC_DVC_VAR          *asc_dvc_varp;
-    int                  flags;
-    Scsi_Cmnd            *done_scp = NULL, *last_scp = NULL;
-    Scsi_Cmnd            *tscp, *new_last_scp;
-    int                  do_scsi_done;
-    int                  scp_found;
-    int                  status;
-    int                  target;
-    int                  ret;
+    struct Scsi_Host    *shp;
+    asc_board_t         *boardp;
+    int                 i;
+    char                *cp;
+    int                 cplen;
+    int                 cnt;
+    int                 totcnt;
+    int                 leftlen;
+    char                *curbuf;
+    off_t               advoffset;
+    Scsi_Device         *scd;
 
-    /* Save current flags and disable interrupts. */
-    save_flags(flags);
-    cli();
+    ASC_DBG(1, "advansys_proc_info: begin\n");
 
-    ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
+    /*
+     * User write not supported.
+     */
+    if (inout == TRUE) {
+        return(-ENOSYS);
+    }
 
-#ifdef ADVANSYS_STATS
-    if (scp->host != NULL) {
-        ASC_STATS(scp->host, reset);
-    }    
-#endif /* ADVANSYS_STATS */
+    /*
+     * User read of /proc/scsi/advansys/[0...] file.
+     */
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-    if ((reset_flags & SCSI_RESET_ASYNCHRONOUS) &&
-        (scp->serial_number != scp->serial_number_at_timeout)) {
-        ASC_PRINT1(
-"advansys_reset: timeout serial number changed for request %x\n",
-            (unsigned) scp);
-        do_scsi_done = ASC_FALSE;
-        scp_found = ASC_FALSE;
-        ret = SCSI_RESET_NOT_RUNNING;
-    } else
-#endif /* version >= v1.3.89 */
-    if ((shp = scp->host) == NULL) {
-        scp->result = HOST_BYTE(DID_ERROR);
-        do_scsi_done = ASC_TRUE;
-        scp_found = ASC_FALSE;
-        ret = SCSI_RESET_ERROR;
-    } else if ((boardp = ASC_BOARDP(shp))->flags & 
-                (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
-        ASC_PRINT2(
-"advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n",
-            boardp->id, boardp->flags);
-        do_scsi_done = ASC_TRUE;
-        if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
-            (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
-            scp_found = ASC_TRUE;
-        } else {
-            scp_found = ASC_FALSE;
-        }
-        scp->result = HOST_BYTE(DID_ERROR);
-        ret = SCSI_RESET_ERROR;
-    } else if (jiffies >= boardp->last_reset &&
-               jiffies < (boardp->last_reset + (10 * HZ))) {
-        /*
-         * Don't allow a reset to be attempted within 10 seconds
-         * of the last reset.
-         *
-         * If 'jiffies' wrapping occurs, the reset request will go
-         * through, because a wrapped 'jiffies' would not pass the
-         * test above.
-         */
-        ASC_DBG(1,
-            "advansys_reset: reset within 10 sec of last reset ignored\n");
-        do_scsi_done = ASC_TRUE;
-        if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
-            (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
-            scp_found = ASC_TRUE;
-        } else {
-            scp_found = ASC_FALSE;
+    /* Find the specified board. */
+    for (i = 0; i < asc_board_count; i++) {
+        if (asc_host[i]->host_no == hostno) {
+            break;
         }
-        scp->result = HOST_BYTE(DID_ERROR);
-        ret = SCSI_RESET_ERROR;
-    } else {
-        int device_reset = ASC_FALSE;
+    }
+    if (i == asc_board_count) {
+        return(-ENOENT);
+    }
 
-        do_scsi_done = ASC_TRUE;
+    shp = asc_host[i];
+    boardp = ASC_BOARDP(shp);
 
-        /* Set reset flag to avoid nested reset or abort requests. */
-        boardp->flags |= ASC_HOST_IN_RESET;
+    /* Copy read data starting at the beginning of the buffer. */
+    *start = buffer;
+    curbuf = buffer;
+    advoffset = 0;
+    totcnt = 0;
+    leftlen = length;
 
-        /*
-          * If the request is on the target waiting or active queue
-         * or the board done queue, then remove it and note that it
-         * was found.
-         */
-        if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
-            ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n");
-            scp_found = ASC_TRUE;
-        } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
-            ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n");
-            scp_found = ASC_TRUE;
-        } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) {
-            scp_found = ASC_TRUE;
-        } else {
-            scp_found = ASC_FALSE;
+    /*
+     * Get board configuration information.
+     *
+     * advansys_info() returns the board string from its own static buffer.
+     */
+    cp = (char *) advansys_info(shp);
+    strcat(cp, "\n");
+    cplen = strlen(cp);
+    /* Copy board information. */
+    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+    totcnt += cnt;
+    leftlen -= cnt;
+    if (leftlen == 0) {
+        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+        return totcnt;
+    }
+    advoffset += cplen;
+    curbuf += cnt;
+
+    /*
+     * Display Wide Board BIOS Information.
+     */
+    if (ASC_WIDE_BOARD(boardp)) {
+        cp = boardp->prtbuf;
+        cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE);
+        ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
+        cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+        totcnt += cnt;
+        leftlen -= cnt;
+        if (leftlen == 0) {
+            ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+            return totcnt;
         }
+        advoffset += cplen;
+        curbuf += cnt;
+    }
 
-        /*
-         * If the suggest reset bus flags are set, reset the bus.
-         * Otherwise only reset the device.
-         */
-        asc_dvc_varp = &boardp->asc_dvc_var;
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-        if (reset_flags &
-            (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) {
-#endif /* version >= v1.3.89 */
+    /*
+     * Display driver information for each device attached to the board.
+     */
+    cp = boardp->prtbuf;
+    cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE);
+    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
+    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+    totcnt += cnt;
+    leftlen -= cnt;
+    if (leftlen == 0) {
+        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+        return totcnt;
+    }
+    advoffset += cplen;
+    curbuf += cnt;
 
+    /*
+     * Display target driver information for each device attached
+     * to the board.
+     */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,75)
+    for (scd = scsi_devices; scd; scd = scd->next)
+#else /* version >= v2.1.75 */
+    for (scd = shp->host_queue; scd; scd = scd->next)
+#endif /* version >= v2.1.75 */
+    {
+        if (scd->host == shp) {
+            cp = boardp->prtbuf;
             /*
-             * Reset the target's SCSI bus.
+             * Note: If proc_print_scsidevice() writes more than
+             * ASC_PRTBUF_SIZE bytes, it will overrun 'prtbuf'.
              */
-            ASC_DBG(1, "advansys_reset: before AscResetSB()\n");
-            sti();    /* Enable interrupts for AscResetSB(). */
-            status = AscResetSB(asc_dvc_varp);
-            cli();
-            switch (status) {
-            case ASC_TRUE:
-                ASC_DBG(1, "advansys_reset: AscResetSB() success\n");
-                ret = SCSI_RESET_SUCCESS;
-                break;
-            case ASC_ERROR:
-            default:
-                ASC_DBG(1, "advansys_reset: AscResetSB() failed\n");
-                ret = SCSI_RESET_ERROR;
-                break;
+            proc_print_scsidevice(scd, cp, &cplen, 0);
+            ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
+            cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+            totcnt += cnt;
+            leftlen -= cnt;
+            if (leftlen == 0) {
+                ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+                return totcnt;
             }
+            advoffset += cplen;
+            curbuf += cnt;
+        }
+    }
+    
+    /*
+     * Display EEPROM configuration for the board.
+     */
+    cp = boardp->prtbuf;
+    if (ASC_NARROW_BOARD(boardp)) {
+        cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
+    } else {
+        cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
+    }
+    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
+    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+    totcnt += cnt;
+    leftlen -= cnt;
+    if (leftlen == 0) {
+        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+        return totcnt;
+    }
+    advoffset += cplen;
+    curbuf += cnt;
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-        } else {
-            /*
-             * Reset the specified device. If the device reset fails,
-             * then reset the SCSI bus.
-             */
+    /*
+     * Display driver configuration and information for the board.
+     */
+    cp = boardp->prtbuf;
+    cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE);
+    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
+    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+    totcnt += cnt;
+    leftlen -= cnt;
+    if (leftlen == 0) {
+        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+        return totcnt;
+    }
+    advoffset += cplen;
+    curbuf += cnt;
 
-            ASC_DBG1(1, "advansys_reset: before AscResetDevice(), target %d\n",
-                scp->target);
-            sti();    /* Enable interrupts for AscResetDevice(). */
-            status = AscResetDevice(asc_dvc_varp, scp->target);
-            cli();
+#ifdef ADVANSYS_STATS
+    /*
+     * Display driver statistics for the board.
+     */
+    cp = boardp->prtbuf;
+    cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE);
+    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
+    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+    totcnt += cnt;
+    leftlen -= cnt;
+    if (leftlen == 0) {
+        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+        return totcnt;
+    }
+    advoffset += cplen;
+    curbuf += cnt;
+#endif /* ADVANSYS_STATS */
 
-            /*
-             * If the device has been reset, try to initialize it.
-             */
-            if (status == ASC_TRUE) {
-                status = asc_init_dev(asc_dvc_varp, scp);
-            }
+    /*
+     * Display Asc Library dynamic configuration information
+     * for the board.
+     */
+    cp = boardp->prtbuf;
+    if (ASC_NARROW_BOARD(boardp)) {
+        cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE);
+    } else {
+        cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE);
+    }
+    ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
+    cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
+    totcnt += cnt;
+    leftlen -= cnt;
+    if (leftlen == 0) {
+        ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+        return totcnt;
+    }
+    advoffset += cplen;
+    curbuf += cnt;
 
-            switch (status) {
-            case ASC_TRUE:
-                ASC_DBG(1, "advansys_reset: AscResetDevice() success\n");
-                device_reset = ASC_TRUE;
-                ret = SCSI_RESET_SUCCESS;
-                break;
-            case ASC_ERROR:
-            default:
-                ASC_DBG(1,
-"advansys_reset: AscResetDevice() failed; Calling AscResetSB()\n");
-                sti();    /* Enable interrupts for AscResetSB(). */
-                status = AscResetSB(asc_dvc_varp);
-                cli();
-                switch (status) {
-                case ASC_TRUE:
-                    ASC_DBG(1, "advansys_reset: AscResetSB() TRUE\n");
-                    ret = SCSI_RESET_SUCCESS;
-                    break;
-                case ASC_ERROR:
-                default:
-                    ASC_DBG(1, "advansys_reset: AscResetSB() ERROR\n");
-                    ret = SCSI_RESET_ERROR;
-                    break;
-                }
-                break;
-            }
-        }
-#endif /* version >= v1.3.89 */
-
-        /*
-         * Because the ASC_HOST_IN_RESET flag causes both
-         * 'advansys_interrupt' and 'asc_isr_callback' to
-         * queue requests to the board's 'done' queue and
-         * prevents waiting commands from being executed,
-         * these queued requests must be handled here.
-         */
-        done_scp = asc_dequeue_list(&boardp->done, &last_scp,
-                                    ASC_TID_ALL);
-
-        /*
-         * If a device reset was performed dequeue all waiting
-         * and active requests for the device and set the request
-         * status to DID_RESET.
-         *
-         * If a SCSI bus reset was performed dequeue all waiting
-         * and active requests for all devices and set the request
-         * status to DID_RESET.
-         */
-        if (device_reset == ASC_TRUE) {
-            target = scp->target;
-        } else {
-            target = ASC_TID_ALL;
-        }
-
-        /*
-         * Add active requests to 'done_scp' and set the request status
-         * to DID_RESET.
-         */
-        if (done_scp == NULL) {
-            done_scp = asc_dequeue_list(&boardp->active, &last_scp, target);
-            for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
-                tscp->result = HOST_BYTE(DID_RESET);
-            }
-        } else {
-            ASC_ASSERT(last_scp != NULL);
-            REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active,
-                &new_last_scp, target);
-            if (new_last_scp != NULL) {
-                ASC_ASSERT(REQPNEXT(last_scp) != NULL);
-                for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
-                    tscp->result = HOST_BYTE(DID_RESET);
-                }
-                last_scp = new_last_scp;
-            }
-        }
-
-        /*
-         * Add waiting requests to 'done_scp' and set the request status
-         * to DID_RESET.
-         */
-        if (done_scp == NULL) {
-            done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, target);
-            for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
-                tscp->result = HOST_BYTE(DID_RESET);
-            }
-        } else {
-            ASC_ASSERT(last_scp != NULL);
-            REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting,
-                &new_last_scp, target);
-            if (new_last_scp != NULL) {
-                ASC_ASSERT(REQPNEXT(last_scp) != NULL);
-                for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
-                    tscp->result = HOST_BYTE(DID_RESET);
-                }
-                last_scp = new_last_scp;
-            }
-        }
-
-        /* Save the time of the most recently completed reset. */
-        boardp->last_reset = jiffies;
-
-        /* Clear reset flag. */
-        boardp->flags &= ~ASC_HOST_IN_RESET;
-
-        /*
-         * Start any waiting commands for the board.
-         */
-        if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
-            ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
-            asc_execute_queue(&boardp->waiting);
-        }
-        ret = SCSI_RESET_SUCCESS;
-    }
-
-    /* Interrupts could be enabled here. */
-
-    ASC_ASSERT(do_scsi_done != ASC_ERROR);
-    ASC_ASSERT(scp_found != ASC_ERROR);
-    if (do_scsi_done == ASC_TRUE) {
-        if (scp->scsi_done == NULL) {
-            ASC_PRINT1(
-"advansys_reset: reset request scsi_done() is NULL, %x\n",
-                (unsigned) scp);
-        } else {
-            if (scp_found == ASC_FALSE) {
-                ASC_PRINT1(
-"advansys_reset: reset request not active or waiting, completing anyway %x\n",
-                    (unsigned) scp);
-            }
-            ASC_STATS(scp->host, done);
-            scp->scsi_done(scp);
-        }
-    }
-
-    /*
-     * It is possible for the request done function to re-enable
-     * interrupts without confusing the driver. But here interrupts
-     * aren't enabled until requests have been completed.
-     */
-    if (done_scp != NULL) {
-        asc_scsi_done_list(done_scp);
-    }
-
-    ASC_DBG1(1, "advansys_reset: ret %d", ret);
-
-    /* Re-enable interrupts, if they were enabled on entry. */
-    restore_flags(flags);
+    ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
 
-    ASC_ASSERT(ret != ASC_ERROR);
-    return ret;
+    return totcnt;
 }
-
-/*
- * advansys_biosparam()
- *
- * Translate disk drive geometry if the "BIOS greater than 1 GB"
- * support is enabled for a drive.
- *
- * ip (information pointer) is an int array with the following definition:
- * ip[0]: heads
- * ip[1]: sectors
- * ip[2]: cylinders
- */
-int
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
-advansys_biosparam(Disk *dp, int dep, int ip[])
-#else /* version >= v1.3.0 */
-advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
 #endif /* version >= v1.3.0 */
-{
-    ASC_DBG(1, "advansys_biosparam: begin\n");
-    ASC_STATS(dp->device->host, biosparam);
-    if ((ASC_BOARDP(dp->device->host)->asc_dvc_var.dvc_cntl &
-         ASC_CNTL_BIOS_GT_1GB) && dp->capacity > 0x200000) {
-            ip[0] = 255;
-            ip[1] = 63;
-    } else {
-            ip[0] = 64;
-            ip[1] = 32;
-    }
-    ip[2] = dp->capacity / (ip[0] * ip[1]);
-    ASC_DBG(1, "advansys_biosparam: end\n");
-    return 0;
-}
 
 /*
- * advansys_setup()
- *
- * This function is called from init/main.c at boot time.
- * It it passed LILO parameters that can be set from the
- * LILO command line or in /etc/lilo.conf.
+ * advansys_detect()
  *
- * It is used by the AdvanSys driver to either disable I/O
- * port scanning or to limit scanning to 1 - 4 I/O ports.
- * Regardless of the option setting EISA and PCI boards
- * will still be searched for and detected. This option
- * only affects searching for ISA and VL boards.
+ * Detect function for AdvanSys adapters.
  *
- * If ADVANSYS_DEBUG is defined the driver debug level may
- * be set using the 5th (ASC_NUM_BOARD_SUPPORTED + 1) I/O Port.
+ * Argument is a pointer to the host driver's scsi_hosts entry.
  *
- * Examples:
- * 1. Eliminate I/O port scanning:
- *         boot: linux advansys=
- *       or
- *         boot: linux advansys=0x0
- * 2. Limit I/O port scanning to one I/O port:
- *        boot: linux advansys=0x110
- * 3. Limit I/O port scanning to four I/O ports:
- *        boot: linux advansys=0x110,0x210,0x230,0x330
- * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
- *    set the driver debug level to 2.
- *        boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
+ * Return number of adapters found.
  *
- * ints[0] - number of arguments
- * ints[1] - first argument
- * ints[2] - second argument
- * ...
+ * Note: Because this function is called during system initialization
+ * it must not call SCSI mid-level functions including scsi_malloc()
+ * and scsi_free().
  */
 ASC_INITFUNC(
-void
-advansys_setup(char *str, int *ints)
+int
+advansys_detect(Scsi_Host_Template *tpnt)
 )
 {
-    int    i;
+    static int          detect_called = ASC_FALSE;
+    int                 iop;
+    int                 bus;
+    struct Scsi_Host    *shp;
+    asc_board_t         *boardp;
+    ASC_DVC_VAR         *asc_dvc_varp = NULL;
+    ADV_DVC_VAR         *adv_dvc_varp = NULL;
+    int                 ioport = 0;
+    int                 share_irq = FALSE;
+    PCI_DEVICE          pciDevice;
+    PCI_CONFIG_SPACE    pciConfig;
+    int                 warn_code, err_code;
+    int                 ret;
 
-    if (asc_iopflag == ASC_TRUE) {
-        printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
-        return;
+    if (detect_called == ASC_FALSE) {
+        detect_called = ASC_TRUE;
+    } else {
+        printk("AdvanSys SCSI: advansys_detect() multiple calls ignored\n");
+        return 0;
     }
 
-    asc_iopflag = ASC_TRUE;
+    ASC_DBG(1, "advansys_detect: begin\n");
 
-    if (ints[0] > ASC_NUM_BOARD_SUPPORTED) {
-#ifdef ADVANSYS_DEBUG
-        if ((ints[0] == ASC_NUM_BOARD_SUPPORTED + 1) &&
-            (ints[ASC_NUM_BOARD_SUPPORTED + 1] >> 4 == 0xdeb)) {
-            asc_dbglvl = ints[ASC_NUM_BOARD_SUPPORTED + 1] & 0xf;
-        } else {
-#endif /* ADVANSYS_DEBUG */
-            printk("AdvanSys SCSI: only %d I/O ports accepted\n",
-                ASC_NUM_BOARD_SUPPORTED);
-#ifdef ADVANSYS_DEBUG
-        }
-#endif /* ADVANSYS_DEBUG */
-    }
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+    tpnt->proc_dir = &proc_scsi_advansys;
+#endif /* version >= v1.3.0 */
 
-#ifdef ADVANSYS_DEBUG
-    ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
-    for (i = 1; i < ints[0]; i++) {
-        ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
-    }
-    ASC_DBG(1, "\n");
-#endif /* ADVANSYS_DEBUG */
+    asc_board_count = 0;
 
-    for (i = 1; i <= ints[0] && i <= ASC_NUM_BOARD_SUPPORTED; i++) {
-        asc_ioport[i-1] = ints[i];
-        ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
-            i - 1, asc_ioport[i-1]);
+    /*
+     * If I/O port probing has been modified, then verify and
+     * clean-up the 'asc_ioport' list.
+     */
+    if (asc_iopflag == ASC_TRUE) {
+        for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
+            ASC_DBG2(1, "advansys_detect: asc_ioport[%d] %x\n",
+                ioport, asc_ioport[ioport]);
+            if (asc_ioport[ioport] != 0) {
+                for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
+                    if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
+                        break;
+                    }
+                }
+                if (iop == ASC_IOADR_TABLE_MAX_IX) {
+                    printk(
+"AdvanSys SCSI: specified I/O Port 0x%X is invalid\n",
+                        asc_ioport[ioport]);
+                    asc_ioport[ioport] = 0;
+                }
+            }
+        }
+        ioport = 0;
     }
-}
 
+    memset(&pciDevice, 0, sizeof(PCI_DEVICE));
+    memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
+    pciDevice.maxBusNumber = PCI_MAX_BUS;
+    pciDevice.endSlot = PCI_MAX_SLOT;
 
-/*
- * --- Loadable Driver Support
- */
-
-#ifdef MODULE
-Scsi_Host_Template driver_template = ADVANSYS;
-# include "scsi_module.c"
-#endif /* MODULE */
+    for (bus = 0; bus < ASC_NUM_BUS; bus++) {
 
+        ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n",
+            bus, asc_bus_name[bus]);
+        iop = 0;
 
-/*
- * --- Miscellaneous Driver Functions
- */
+        while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
 
-/*
- * First-level interrupt handler.
- *
- * For versions > v1.3.70, 'dev_id' is a pointer to the interrupting
- * adapter's asc_board_t. Because all boards are currently checked
- * for interrupts on each interrupt, 'dev_id' is not referenced. 'dev_id'
- * could be used to identify an interrupt passed to the AdvanSys driver,
- * which is for a device sharing an interrupt with an AdvanSys adapter.
- */
-STATIC void
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
-advansys_interrupt(int irq, struct pt_regs *regs)
-#else /* version >= v1.3.70 */
-advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-#endif /* version >= v1.3.70 */
-{
-    int             flags;
-    int             i;
-    asc_board_t     *boardp;
-    Scsi_Cmnd       *done_scp = NULL, *last_scp = NULL;
-    Scsi_Cmnd       *new_last_scp;
+            ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
+                asc_board_count);
 
-    /* Disable interrupts, if they aren't already disabled. */
-    save_flags(flags);
-    cli();
+            switch (asc_bus[bus]) {
+            case ASC_IS_ISA:
+            case ASC_IS_VL:
+                if (asc_iopflag == ASC_FALSE) {
+                    iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
+                } else {
+                    /*
+                     * ISA and VL I/O port scanning has either been
+                     * eliminated or limited to selected ports on
+                     * the LILO command line, /etc/lilo.conf, or
+                     * by setting variables when the module was loaded.
+                     */
+                    ASC_DBG(1, "advansys_detect: I/O port scanning modified\n");
+                ioport_try_again:
+                    iop = 0;
+                    for (; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
+                        if ((iop = asc_ioport[ioport]) != 0) {
+                            break;
+                        }
+                    }
+                    if (iop) {
+                        ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n",
+                            iop);
+                        if (check_region(iop, ASC_IOADR_GAP) != 0) {
+                            printk(
+"AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop);
+                            /* Don't try this I/O port twice. */
+                            asc_ioport[ioport] = 0;
+                            goto ioport_try_again;
+                        } else if (AscFindSignature(iop) == ASC_FALSE) {
+                            printk(
+"AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop);
+                            /* Don't try this I/O port twice. */
+                            asc_ioport[ioport] = 0;
+                            goto ioport_try_again;
+                        } else {
+                            /*
+                             * If this isn't an ISA board, then it must be
+                             * a VL board. If currently looking an ISA
+                             * board is being looked for then try for
+                             * another ISA board in 'asc_ioport'.
+                             */
+                            if (asc_bus[bus] == ASC_IS_ISA &&
+                                (AscGetChipVersion(iop, ASC_IS_ISA) &
+                                 ASC_CHIP_VER_ISA_BIT) == 0) {
+                                 /*
+                                 * Don't clear 'asc_ioport[ioport]'. Try
+                                 * this board again for VL. Increment
+                                 * 'ioport' past this board.
+                                 */
+                                 ioport++;
+                                 goto ioport_try_again;
+                            }
+                        }
+                        /*
+                         * This board appears good, don't try the I/O port
+                         * again by clearing its value. Increment 'ioport'
+                         * for the next iteration.
+                         */
+                        asc_ioport[ioport++] = 0;
+                    }
+                }
+                break;
 
-    ASC_DBG(1, "advansys_interrupt: begin\n");
-    /*
-     * Check for interrupts on all boards.
-     * AscISR() will call asc_isr_callback().
-     */
-    for (i = 0; i < asc_board_count; i++) {
-        ASC_STATS(asc_host[i], check_interrupt);
-        boardp = ASC_BOARDP(asc_host[i]);
-        while (AscIsIntPending(asc_host[i]->io_port)) {
-            ASC_STATS(asc_host[i], interrupt);
-            ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
-            AscISR(&boardp->asc_dvc_var);
-        }
+            case ASC_IS_EISA:
+                iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
+                break;
 
-        /*
-         * Start waiting requests and create a list of completed requests.
-         * 
-         * If a reset or abort request is being performed for the board,
-         * the reset or abort handler will complete pending requests after
-         * it has completed.
-         */
-        if ((boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) == 0) {
-            /* Start any waiting commands for the board. */
-            if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
-                ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
-                asc_execute_queue(&boardp->waiting);
+            case ASC_IS_PCI:
+                    if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
+                        iop = 0;
+                    } else {
+                        ASC_DBG2(2,
+                            "advansys_detect: slotFound %d, busNumber %d\n",
+                            pciDevice.slotFound, pciDevice.busNumber);
+                        asc_get_pci_cfg(&pciDevice, &pciConfig);
+                        iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
+                        ASC_DBG2(1,
+                            "advansys_detect: vendorID %X, deviceID %X\n",
+                            pciConfig.vendorID, pciConfig.deviceID);
+                        ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
+                            iop, pciConfig.irqLine);
+                    }
+                break;
+
+            default:
+                ASC_PRINT1("advansys_detect: unknown bus type: %d\n",
+                    asc_bus[bus]);
+                break;
             }
+            ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
 
-             /*
-             * Add to the list of requests that must be completed.
+            /*
+             * Adapter not found, try next bus type.
              */
-            if (done_scp == NULL) {
-                done_scp = asc_dequeue_list(&boardp->done, &last_scp,
-                    ASC_TID_ALL);
-            } else {
-                ASC_ASSERT(last_scp != NULL);
-                REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done,
-                    &new_last_scp, ASC_TID_ALL);
-                if (new_last_scp != NULL) {
-                    ASC_ASSERT(REQPNEXT(last_scp) != NULL);
-                    last_scp = new_last_scp;
-                }
+            if (iop == 0) {
+                break;
             }
-        }
-    }
 
-    /* Interrupts could be enabled here. */
+            /*
+             * Adapter found.
+             *
+             * Register the adapter, get its configuration, and
+             * initialize it.
+             */
+            ASC_DBG(2, "advansys_detect: scsi_register()\n");
+            shp = scsi_register(tpnt, sizeof(asc_board_t));
 
-    /*
-     * It is possible for the request done function to re-enable
-     * interrupts without confusing the driver. But here interrupts
-     * aren't enabled until all requests have been completed.
-     */
-    asc_scsi_done_list(done_scp);
+            /* Save a pointer to the Scsi_host of each board found. */
+            asc_host[asc_board_count++] = shp;
 
-    /* Re-enable interrupts, if they were enabled on entry. */
-    restore_flags(flags);
+            /* Initialize private per board data */
+            boardp = ASC_BOARDP(shp);
+            memset(boardp, 0, sizeof(asc_board_t));
+            boardp->id = asc_board_count - 1;
 
-    ASC_DBG(1, "advansys_interrupt: end\n");
-    return;
-}
+            /*
+             * Handle both narrow and wide PCI boards.
+             *
+             * If a Wide board was detected, set the board structure
+             * wide board flag. Set-up the board structure based on
+             * the board type.
+             */
+            if ((asc_bus[bus] == ASC_IS_PCI &&
+                 pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300) == 0) {
+                ASC_DBG(1, "advansys_detect: narrow board\n");
+                asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
+                asc_dvc_varp->bus_type = asc_bus[bus];
+                asc_dvc_varp->drv_ptr = (ulong) boardp;
+                asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
+                asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
+                asc_dvc_varp->iop_base = iop;
+                asc_dvc_varp->isr_callback = (Ptr2Func) asc_isr_callback;
+            } else {
+                ASC_DBG(1, "advansys_detect: wide board\n");
+                boardp->flags |= ASC_IS_WIDE_BOARD;
+                adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+                adv_dvc_varp->drv_ptr = (ulong) boardp;
+                adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
+                adv_dvc_varp->isr_callback = (Ptr2Func) adv_isr_callback;
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-/*
- * Set the number of commands to queue per device for the
- * specified host adapter.
- */
-STATIC void
-advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist)
-{
-    Scsi_Device        *device;
-    asc_board_t        *boardp;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+                adv_dvc_varp->iop_base = iop;
+#else /* version >= v1,3,0 */
+                /*
+                 * Map the board's registers into virtual memory for
+                 * PCI slave access. Only memory accesses are used to
+                 * access the board's registers.
+                 *
+                 * Note: The PCI register base address is not always
+                 * page aligned, but the address passed to ioremap()
+                 * must be page aligned. It is guaranteed that the
+                 * PCI register base address will not cross a page
+                 * boundary.
+                 */
+                if ((boardp->ioremap_addr =
+                    ioremap(pciConfig.baseAddress[1] & PAGE_MASK,
+                         PAGE_SIZE)) == 0) {
+                   ASC_PRINT3(
+"advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
+                   boardp->id, pciConfig.baseAddress[1], ADV_CONDOR_IOLEN);
+                   scsi_unregister(shp);
+                   asc_board_count--;
+                   continue;
+                }
+                adv_dvc_varp->iop_base = (AdvPortAddr)
+                    (boardp->ioremap_addr +
+                     (pciConfig.baseAddress[1] -
+                      (pciConfig.baseAddress[1] & PAGE_MASK)));
+#endif /* version >= v1,3,0 */
 
-    boardp = ASC_BOARDP(shp);
-    for (device = devicelist; device != NULL; device = device->next) {
-        if (device->host != shp) {
-            continue;
-        }
-        /*
-         * Save a pointer to the device and set its initial/maximum
-         * queue depth.
-         */
-        boardp->device[device->id] = device;
-        device->queue_depth = boardp->asc_dvc_var.max_dvc_qng[device->id];
-        ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n",
-            (unsigned) shp, device->id, device->queue_depth);
-    }
-}
-#endif /* version >= v1.3.89 */
+                /*
+                 * Even though it isn't used to access the board in
+                 * kernels greater than or equal to v1.3.0, save
+                 * the I/O Port address so that it can be reported and
+                 * displayed.
+                 */
+                boardp->ioport = iop;
+            }
 
-/*
- * Function used only with polled I/O requests that are initiated by
- * advansys_command().
- */
-STATIC void
-advansys_command_done(Scsi_Cmnd *scp)
-{
-    ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
-    scp->SCp.Status = 1;
-}
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+            /*
+             * Allocate buffer for printing information from
+             * /proc/scsi/advansys/[0...].
+             */
+            if ((boardp->prtbuf =
+                kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
+                ASC_PRINT3(
+"advansys_detect: board %d: kmalloc(%d, %d) returned NULL\n",
+                    boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
+                scsi_unregister(shp);
+                asc_board_count--;
+                continue;
+            }
+#endif /* version >= v1.3.0 */
 
-/*
- * Complete all requests on the singly linked list pointed
- * to by 'scp'.
- *
- * Interrupts can be enabled on entry.
- */
-STATIC void
-asc_scsi_done_list(Scsi_Cmnd *scp)
-{
-    Scsi_Cmnd    *tscp;
-
-    while (scp != NULL) {
-        tscp = REQPNEXT(scp);
-        REQPNEXT(scp) = NULL;
-        ASC_STATS(scp->host, done);
-        ASC_ASSERT(scp->scsi_done != NULL);
-        scp->scsi_done(scp);
-        scp = tscp;
-    }
-    return;
-}
+            if (ASC_NARROW_BOARD(boardp)) {
+                /*
+                 * Set the board bus type and PCI IRQ before
+                 * calling AscInitGetConfig().
+                 */
+                switch (asc_dvc_varp->bus_type) {
+                case ASC_IS_ISA:
+                    shp->unchecked_isa_dma = TRUE;
+                    share_irq = FALSE;
+                    break;
+                case ASC_IS_VL:
+                    shp->unchecked_isa_dma = FALSE;
+                    share_irq = FALSE;
+                    break;
+                case ASC_IS_EISA:
+                    shp->unchecked_isa_dma = FALSE;
+                    share_irq = TRUE;
+                    break;
+                case ASC_IS_PCI:
+                    shp->irq = asc_dvc_varp->irq_no = pciConfig.irqLine;
+                    shp->unchecked_isa_dma = FALSE;
+                    share_irq = TRUE;
+                    asc_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
+                    asc_dvc_varp->cfg->pci_slot_info =
+                        ASC_PCI_MKID(pciDevice.busNumber,
+                            pciDevice.slotFound,
+                            pciDevice.devFunc);
+                    break;
+                default:
+                    ASC_PRINT2(
+"advansys_detect: board %d: unknown adapter type: %d\n",
+                        boardp->id, asc_dvc_varp->bus_type);
+                    shp->unchecked_isa_dma = TRUE;
+                    share_irq = FALSE;
+                    break;
+                }
+            } else {
+                /*
+                 * For Wide boards set PCI information before calling
+                 * AdvInitGetConfig().
+                 */
+                shp->irq = adv_dvc_varp->irq_no = pciConfig.irqLine;
+                shp->unchecked_isa_dma = FALSE;
+                share_irq = TRUE;
+                adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
+                adv_dvc_varp->cfg->pci_slot_info =
+                    ASC_PCI_MKID(pciDevice.busNumber,
+                        pciDevice.slotFound,
+                        pciDevice.devFunc);
+            }
 
-/*
- * Execute a single 'Scsi_Cmnd'.
- *
- * The function 'done' is called when the request has been completed.
- *
- * Scsi_Cmnd:
- *
- *  host - board controlling device
- *  device - device to send command
- *  target - target of device
- *  lun - lun of device
- *  cmd_len - length of SCSI CDB
- *    cmnd - buffer for SCSI 8, 10, or 12 byte CDB
- *  use_sg - if non-zero indicates scatter-gather request with use_sg elements
- *
- *  if (use_sg == 0)
- *        request_buffer - buffer address for request
- *        request_bufflen - length of request buffer
- *  else
- *        request_buffer - pointer to scatterlist structure
- *
- *  sense_buffer - sense command buffer
- *
- *  result (4 bytes of an int):
- *   Byte Meaning
- *   0      SCSI Status Byte Code
- *   1      SCSI One Byte Message Code
- *   2       Host Error Code
- *   3      Mid-Level Error Code
- *
- *  host driver fields:
- *  SCp - Scsi_Pointer used for command processing status
- *  scsi_done - used to save caller's done function
- *     host_scribble - used for pointer to another Scsi_Cmnd
- *
- * If this function returns ASC_NOERROR or ASC_ERROR the request
- * has been enqueued on the board's 'done' queue and must be
- * completed by the caller.
- *
- * If ASC_BUSY is returned the request must be enqueued by the
- * caller and re-tried later.
- */
-STATIC int
-asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
-{
-    asc_board_t        *boardp;
-    ASC_DVC_VAR        *asc_dvc_varp;
-    Scsi_Device        *device;
-    int                ret;
+            /*
+             * Read the board configuration.
+             */
+            if (ASC_NARROW_BOARD(boardp)) {
+                 /*
+                  * NOTE: AscInitGetConfig() may change the board's
+                  * bus_type value. The asc_bus[bus] value should no
+                  * longer be used. If the bus_type field must be
+                  * referenced only use the bit-wise AND operator "&".
+                  */
+                 ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
+                switch(ret = AscInitGetConfig(asc_dvc_varp)) {
+                case 0:    /* No error */
+                    break;
+                case ASC_WARN_IO_PORT_ROTATE:
+                    ASC_PRINT1(
+"AscInitGetConfig: board %d: I/O port address modified\n",
+                        boardp->id);
+                    break;
+                case ASC_WARN_AUTO_CONFIG:
+                    ASC_PRINT1(
+"AscInitGetConfig: board %d: I/O port increment switch enabled\n",
+                        boardp->id);
+                    break;
+                case ASC_WARN_EEPROM_CHKSUM:
+                    ASC_PRINT1(
+"AscInitGetConfig: board %d: EEPROM checksum error\n",
+                        boardp->id);
+                    break;
+                case ASC_WARN_IRQ_MODIFIED:
+                    ASC_PRINT1(
+"AscInitGetConfig: board %d: IRQ modified\n",
+                        boardp->id);
+                    break;
+                case ASC_WARN_CMD_QNG_CONFLICT:
+                    ASC_PRINT1(
+"AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n",
+                        boardp->id);
+                    break;
+                default:
+                    ASC_PRINT2(
+"AscInitGetConfig: board %d: unknown warning: %x\n",
+                        boardp->id, ret);
+                    break;
+                }
+                if ((err_code = asc_dvc_varp->err_code) != 0) {
+                    ASC_PRINT3(
+"AscInitGetConfig: board %d error: init_state %x, err_code %x\n",
+                        boardp->id, asc_dvc_varp->init_state,
+                        asc_dvc_varp->err_code);
+                }
+            } else {
+                ASC_DBG(2, "advansys_detect: AdvInitGetConfig()\n");
+                if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) {
+                    ASC_PRINT2("AdvInitGetConfig: board %d: warning: %x\n",
+                        boardp->id, ret);
+                }
+                if ((err_code = adv_dvc_varp->err_code) != 0) {
+                    ASC_PRINT2(
+"AdvInitGetConfig: board %d error: err_code %x\n",
+                        boardp->id, adv_dvc_varp->err_code);
+                }
+            }
+        
+            if (err_code != 0) {
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+                kfree(boardp->prtbuf);
+#endif /* version >= v1.3.0 */
+                scsi_unregister(shp);
+                asc_board_count--;
+                continue;
+            }
 
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
-        (unsigned) scp, (unsigned) scp->scsi_done);
+            /*
+             * Save the EEPROM configuration so that it can be displayed
+             * from /proc/scsi/advansys/[0...].
+             */
+            if (ASC_NARROW_BOARD(boardp)) {
 
-    boardp = ASC_BOARDP(scp->host);
-    asc_dvc_varp = &boardp->asc_dvc_var;
-    device = boardp->device[scp->target];
+                ASCEEP_CONFIG *ep;
 
-    /*
-     * If this is the first command, then initialize the device. If
-     * no device is found set 'DID_BAD_TARGET' and return.
-     */
-    if ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(scp->target)) == 0) {
-        if (asc_init_dev(asc_dvc_varp, scp) == ASC_FALSE) {
-            scp->result = HOST_BYTE(DID_BAD_TARGET);
-            asc_enqueue(&boardp->done, scp, ASC_BACK);
-            return ASC_ERROR;
-        }
-        boardp->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target);
-    }
+                /*
+                 * Set the adapter's target id bit in the 'init_tidmask' field.
+                 */
+                boardp->init_tidmask |=
+                    ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
 
-    /*
-     * Mutually exclusive access is required to 'asc_scsi_q' and
-     * 'asc_sg_head' until after the request is started.
-     */
-    memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
+                /*
+                 * Save EEPROM settings for the board.
+                 */
+                ep = &boardp->eep_config.asc_eep;
+
+                ep->init_sdtr = asc_dvc_varp->init_sdtr;
+                ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
+                ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
+                ep->isa_dma_speed = asc_dvc_varp->cfg->isa_dma_speed;
+                ep->start_motor = asc_dvc_varp->start_motor;
+                ep->cntl = asc_dvc_varp->dvc_cntl;
+                ep->no_scam = asc_dvc_varp->no_scam;
+                ep->max_total_qng = asc_dvc_varp->max_total_qng;
+                ep->chip_scsi_id = asc_dvc_varp->cfg->chip_scsi_id;
+                /* 'max_tag_qng' is set to the same value for every device. */
+                ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
+                ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
+                ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
+                ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
+                ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
+                ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
+                ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
+                ep->adapter_info[6] = asc_dvc_varp->cfg->adapter_info[6];
+
+               /*
+                * Modify board configuration.
+                */
+                ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
+                switch (ret = AscInitSetConfig(asc_dvc_varp)) {
+                case 0:    /* No error. */
+                    break;
+                case ASC_WARN_IO_PORT_ROTATE:
+                    ASC_PRINT1(
+"AscInitSetConfig: board %d: I/O port address modified\n",
+                        boardp->id);
+                    break;
+                case ASC_WARN_AUTO_CONFIG:
+                    ASC_PRINT1(
+"AscInitSetConfig: board %d: I/O port increment switch enabled\n",
+                        boardp->id);
+                    break;
+                case ASC_WARN_EEPROM_CHKSUM:
+                    ASC_PRINT1(
+"AscInitSetConfig: board %d: EEPROM checksum error\n",
+                        boardp->id);
+                    break;
+                case ASC_WARN_IRQ_MODIFIED:
+                    ASC_PRINT1(
+"AscInitSetConfig: board %d: IRQ modified\n",
+                        boardp->id);
+                    break;
+                case ASC_WARN_CMD_QNG_CONFLICT:
+                    ASC_PRINT1(
+"AscInitSetConfig: board %d: tag queuing w/o disconnects\n",
+                        boardp->id);
+                    break;
+                default:
+                    ASC_PRINT2(
+"AscInitSetConfig: board %d: unknown warning: %x\n",
+                        boardp->id, ret);
+                    break;
+                }
+                if (asc_dvc_varp->err_code != 0) {
+                    ASC_PRINT3(
+"AscInitSetConfig: board %d error: init_state %x, err_code %x\n",
+                        boardp->id, asc_dvc_varp->init_state,
+                        asc_dvc_varp->err_code);
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+                    kfree(boardp->prtbuf);
+#endif /* version >= v1.3.0 */
+                    scsi_unregister(shp);
+                    asc_board_count--;
+                    continue;
+                }
 
-    /*
-     * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
-     */
-    asc_scsi_q.q2.srb_ptr = (ulong) scp;
+                /*
+                 * Finish initializing the 'Scsi_Host' structure.
+                 */
+                /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
+                if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
+                    shp->irq = asc_dvc_varp->irq_no;
+                }
+            } else {
 
-    /*
-     * Build the ASC_SCSI_Q request.
-     */
-    asc_scsi_q.cdbptr = &scp->cmnd[0];
-    asc_scsi_q.q2.cdb_len = scp->cmd_len;
-    asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
-    asc_scsi_q.q1.target_lun = scp->lun;
-    asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
-    asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
-#else /* version >= v2.0.0 */
-    asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
-#endif /* version >= v2.0.0 */
-    asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
+                ADVEEP_CONFIG *ep;
 
-    /*
-     * If there are any outstanding requests for the current target,
-     * then every 255th request send an ORDERED request. This heuristic
-     * tries to retain the benefit of request sorting while preventing
-     * request starvation. 255 is the max number of tags or pending commands
-     * a device may have outstanding.
-     *
-     * The request count is incremented below for every successfully
-     * started request.
-     * 
-     */
-    if ((asc_dvc_varp->cur_dvc_qng[scp->target] > 0) &&
-        (boardp->reqcnt[scp->target] % 255) == 0) {
-        asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
-    } else {
-        asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
-    }
+                /*
+                 * Save Wide EEP Configuration Information.
+                 */
+                ep = &boardp->eep_config.adv_eep;
+
+                ep->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
+                ep->max_host_qng = adv_dvc_varp->max_host_qng;
+                ep->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
+                ep->termination = adv_dvc_varp->cfg->termination;
+                ep->disc_enable = adv_dvc_varp->cfg->disc_enable;
+                ep->bios_ctrl = adv_dvc_varp->bios_ctrl;
+                ep->wdtr_able = adv_dvc_varp->wdtr_able;
+                ep->sdtr_able = adv_dvc_varp->sdtr_able;
+                ep->ultra_able = adv_dvc_varp->ultra_able;
+                ep->tagqng_able = adv_dvc_varp->tagqng_able;
+                ep->start_motor = adv_dvc_varp->start_motor;
+                ep->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait;
+                ep->bios_boot_delay = adv_dvc_varp->cfg->bios_boot_wait;
+                ep->serial_number_word1 = adv_dvc_varp->cfg->serial1;
+                ep->serial_number_word2 = adv_dvc_varp->cfg->serial2;
+                ep->serial_number_word3 = adv_dvc_varp->cfg->serial3;
 
-    /*
-     * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
-     * buffer command.
-     */
-    if (scp->use_sg == 0) {
-        /*
-         * CDB request of single contiguous buffer.
-         */
-        ASC_STATS(scp->host, cont_cnt);
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
-        asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
-#else /* version >= v2.0.0 */
-        asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
-#endif /* version >= v2.0.0 */
-        asc_scsi_q.q1.data_cnt = scp->request_bufflen;
-        ASC_STATS_ADD(scp->host, cont_xfer,
-                      ASC_CEILING(scp->request_bufflen, 512));
-        asc_scsi_q.q1.sg_queue_cnt = 0;
-        asc_scsi_q.sg_head = NULL;
-    } else {
-        /*
-         * CDB scatter-gather request list.
-         */
-        int                    sgcnt;
-        struct scatterlist    *slp;
+                /*
+                 * Set the adapter's target id bit in the 'init_tidmask' field.
+                 */
+                boardp->init_tidmask |=
+                    ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
 
-        if (scp->use_sg > scp->host->sg_tablesize) {
-            ASC_PRINT3(
-"asc_execute_scsi_cmnd: board %d: use_sg %d > sg_tablesize %d\n",
-                boardp->id, scp->use_sg, scp->host->sg_tablesize);
-            scp->result = HOST_BYTE(DID_ERROR);
-            asc_enqueue(&boardp->done, scp, ASC_BACK);
-            return ASC_ERROR;
-        }
+                /*
+                 * Finish initializing the 'Scsi_Host' structure.
+                 */
+                shp->irq = adv_dvc_varp->irq_no;
+            }
 
-        ASC_STATS(scp->host, sg_cnt);
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+            /*
+             * Channels are numbered beginning with 0. For AdvanSys One host
+             * structure supports one channel. Multi-channel boards have a
+             * separate host structure for each channel. 
+             */
+            shp->max_channel = 0;
+#endif /* version >= v1.3.89 */
+            if (ASC_NARROW_BOARD(boardp)) {
+                shp->max_id = ASC_MAX_TID + 1;
+                shp->max_lun = ASC_MAX_LUN + 1;
 
-        /*
-         * Allocate a ASC_SG_HEAD structure and set the ASC_SCSI_Q
-         * to point to it.
-         */
-        memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
+                shp->io_port = asc_dvc_varp->iop_base;
+                shp->n_io_port = ASC_IOADR_GAP;
+                shp->this_id = asc_dvc_varp->cfg->chip_scsi_id;
 
-        asc_scsi_q.q1.cntl |= QC_SG_HEAD;
-        asc_scsi_q.sg_head = &asc_sg_head;
-        asc_scsi_q.q1.data_cnt = 0;
-        asc_scsi_q.q1.data_addr = 0;
-        asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg;
-        ASC_STATS_ADD(scp->host, sg_elem, asc_sg_head.entry_cnt);
+                /* Set maximum number of queues the adapter can handle. */
+                shp->can_queue = asc_dvc_varp->max_total_qng;
+            } else {
+                shp->max_id = ADV_MAX_TID + 1;
+                shp->max_lun = ADV_MAX_LUN + 1;
 
-        /*
-         * Convert scatter-gather list into ASC_SG_HEAD list.
-         */
-        slp = (struct scatterlist *) scp->request_buffer;
-        for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
-            asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
-#else /* version >= v2.0.0 */
-            asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
-#endif /* version >= v2.0.0 */
-            asc_sg_head.sg_list[sgcnt].bytes = slp->length;
-            ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
-        }
-    }
+                /*
+                 * Save the I/O Port address and length even though the
+                 * in v1.3.0 and greater kernels the region is not used
+                 * by a Wide board. Instead the board is accessed with
+                 * Memory Mapped I/O.
+                 */
+                shp->io_port = iop;
+                shp->n_io_port = ADV_CONDOR_IOLEN;
 
-    ASC_DBG_PRT_SCSI_Q(2, &asc_scsi_q);
-    ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
+                shp->this_id = adv_dvc_varp->chip_scsi_id;
 
-    /*
-     * Execute the command. If there is no error, add the command
-     * to the active queue.
-     */
-    switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
-    case ASC_NOERROR:
-        ASC_STATS(scp->host, asc_noerror);
-        /*
-         * Increment monotonically increasing per device successful
-         * request counter. Wrapping doesn't matter.
-         */
-        boardp->reqcnt[scp->target]++;
+                /* Set maximum number of queues the adapter can handle. */
+                shp->can_queue = adv_dvc_varp->max_host_qng;
+            }
 
-#if ASC_QUEUE_FLOW_CONTROL
-        /*
-         * Conditionally increment the device queue depth.
-         *
-          * If no error occurred and there have been 100 consecutive
-         * successfull requests and the current queue depth is less
-         * than the maximum queue depth, then increment the current
-         * queue depth.
-         */
-        if (boardp->nerrcnt[scp->target]++ > 100) {
-            boardp->nerrcnt[scp->target] = 0;
-            if ((device->queue_curr_depth < device->queue_depth) &&
-                (!(boardp->queue_full & ASC_TIX_TO_TARGET_ID(scp->target)) ||
-                 (boardp->queue_full_cnt[scp->target] >
-                  device->queue_curr_depth))) {
-                device->queue_curr_depth++;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+            /*
+             * In old kernels without tag queuing support and with memory
+             * allocation problems set a conservative 'cmd_per_lun' value.
+             */
+#ifdef MODULE
+            shp->cmd_per_lun = 1;
+#else /* MODULE */
+            shp->cmd_per_lun = 4;
+#endif /* MODULE */
+            ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun);
+#else /* version >= v1.3.89 */
+            /*
+             * Following v1.3.89, 'cmd_per_lun' is no longer needed
+             * and should be set to zero.
+             *
+             * But because of a bug introduced in v1.3.89 if the driver is
+             * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
+             * SCSI function 'allocate_device' will panic. To allow the driver
+             * to work as a module in these kernels set 'cmd_per_lun' to 1.
+             */
+#ifdef MODULE
+            shp->cmd_per_lun = 1;
+#else /* MODULE */
+            shp->cmd_per_lun = 0;
+#endif /* MODULE */
+            /*
+             * Use the host 'select_queue_depths' function to determine
+             * the number of commands to queue per device.
+             */
+            shp->select_queue_depths = advansys_select_queue_depths;
+#endif /* version >= v1.3.89 */
+
+            /*
+             * Set the maximum number of scatter-gather elements the
+             * adapter can handle.
+             */
+            if (ASC_NARROW_BOARD(boardp)) {
+                /*
+                 * Allow two commands with 'sg_tablesize' scatter-gather
+                 * elements to be executed simultaneously. This value is
+                 * the theoretical hardware limit. It may be decreased
+                 * below.
+                 */
+                shp->sg_tablesize =
+                    (((asc_dvc_varp->max_total_qng - 2) / 2) *
+                    ASC_SG_LIST_PER_Q) + 1;
+            } else {
+                shp->sg_tablesize = ADV_MAX_SG_LIST;
             }
-        }
-#endif /* ASC_QUEUE_FLOW_CONTROL */
-        asc_enqueue(&boardp->active, scp, ASC_BACK);
-        ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
-        break;
-    case ASC_BUSY:
-        /* Caller must enqueue request and retry later. */
-        ASC_STATS(scp->host, asc_busy);
-#if ASC_QUEUE_FLOW_CONTROL
-        /*
-         * Clear consecutive no error counter and if possbile decrement
-         * queue depth.
-         */
-        boardp->nerrcnt[scp->target] = 0;
-        if (device->queue_curr_depth > 1) {
-            device->queue_curr_depth--;
-        }
-#endif /* ASC_QUEUE_FLOW_CONTROL */
-        break;
-    case ASC_ERROR:
-        ASC_PRINT2(
-"asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n",
-            boardp->id, asc_dvc_varp->err_code);
-        ASC_STATS(scp->host, asc_error);
-#if ASC_QUEUE_FLOW_CONTROL
-        /* Clear consecutive no error counter. */
-        boardp->nerrcnt[scp->target] = 0;
-#endif /* ASC_QUEUE_FLOW_CONTROL */
-        scp->result = HOST_BYTE(DID_ERROR);
-        asc_enqueue(&boardp->done, scp, ASC_BACK);
-        break;
-    default:
-        ASC_PRINT2(
-"asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n",
-            boardp->id, asc_dvc_varp->err_code);
-        ASC_STATS(scp->host, asc_unknown);
-#if ASC_QUEUE_FLOW_CONTROL
-        /* Clear consecutive no error counter. */
-        boardp->nerrcnt[scp->target] = 0;
-#endif /* ASC_QUEUE_FLOW_CONTROL */
-        scp->result = HOST_BYTE(DID_ERROR);
-        asc_enqueue(&boardp->done, scp, ASC_BACK);
-        break;
-    }
 
-    ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    return ret;
-}
+#ifdef MODULE
+            /*
+             * If the driver is compiled as a module, set a limit on the
+             * 'sg_tablesize' value to prevent memory allocation failures.
+             * Memory allocation errors are more likely to occur at module
+             * load time, then at driver initialization time.
+             */
+            if (shp->sg_tablesize > 64) {
+                shp->sg_tablesize = 64;
+            }
+#endif /* MODULE */
 
-/*
- * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
- */
-STATIC void
-asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
-{
-    asc_board_t         *boardp;
-    Scsi_Cmnd           *scp;
-    struct Scsi_Host    *shp;
-    int                 i;
+            /*
+             * The value of 'sg_tablesize' can not exceed the SCSI
+             * mid-level driver definition of SG_ALL. SG_ALL also
+             * must not be exceeded, because it is used to define the
+             * size of the scatter-gather table in 'struct asc_sg_head'.
+             */
+            if (shp->sg_tablesize > SG_ALL) {
+                shp->sg_tablesize = SG_ALL;
+            }
 
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp %x, qdonep %x\n",
-        (unsigned) asc_dvc_varp, (unsigned) qdonep);
-    ASC_DBG_PRT_QDONE_INFO(2, qdonep);
+            ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
+                shp->sg_tablesize);
 
-    /*
-     * Get the Scsi_Cmnd structure and Scsi_Host structure for the
-     * command that has been completed.
-     */
-    scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
-    ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
-    ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
+            /* BIOS start address. */
+            if (ASC_NARROW_BOARD(boardp)) {
+                shp->base = (char *) ((ulong) AscGetChipBiosAddress(
+                                                asc_dvc_varp->iop_base,
+                                                asc_dvc_varp->bus_type));
+            } else {
+                /*
+                 * Fill-in BIOS board variables. The Wide BIOS saves
+                 * information in LRAM that is used by the driver.
+                 */
+                AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE,
+                    boardp->bios_signature);
+                AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION,
+                    boardp->bios_version);
+                AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG,
+                    boardp->bios_codeseg);
+                AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN,
+                    boardp->bios_codelen);
+
+                ASC_DBG2(1,
+                    "advansys_detect: bios_signature %x, bios_version %x\n",
+                    boardp->bios_signature, boardp->bios_version);
+
+                ASC_DBG2(1,
+                    "advansys_detect: bios_codeseg %x, bios_codelen %x\n",
+                    boardp->bios_codeseg, boardp->bios_codelen);
 
-    if (scp == NULL) {
-        ASC_PRINT("asc_isr_callback: scp is NULL\n");
-        return;
-    }
+                /*
+                 * If the BIOS saved a valid signature, then fill in
+                 * the BIOS code segment base address.
+                 */
+                if (boardp->bios_signature == 0x55AA) {
+                    /*
+                     * Convert x86 realmode code segment to a linear
+                     * address by shifting left 4.
+                     */
+                    shp->base = (uchar *) (boardp->bios_codeseg << 4);
+                } else {
+                    shp->base = 0;
+                }
+            }
 
-    /*
-     * If the request's host pointer is not valid, display a
-     * message and return.
-     */
-    shp = scp->host;
-    for (i = 0; i < asc_board_count; i++) {
-        if (asc_host[i] == shp) {
-            break;
-        }
-    }
-    if (i == asc_board_count) {
-        ASC_PRINT2("asc_isr_callback: scp %x has bad host pointer, host %x\n",
-            (unsigned) scp, (unsigned) shp);
-        return;
-    }
+            /*
+             * Register Board Resources - I/O Port, DMA, IRQ
+             */
 
-    ASC_STATS(shp, callback);
-    ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
+            /* Register I/O port range. */
+            ASC_DBG(2, "advansys_detect: request_region()\n");
+            request_region(shp->io_port, shp->n_io_port, "advansys");
 
-    /*
-     * If the request isn't found on the active queue, it may
-     * have been removed to handle a reset or abort request.
-     * Display a message and return.
-     */
-    boardp = ASC_BOARDP(shp);
-    if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
-        ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n",
-            boardp->id, (unsigned) scp);
-        return;
-    }
+            /* Register DMA Channel for Narrow boards. */
+            shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
+            if (ASC_NARROW_BOARD(boardp)) {
+                /* Register DMA channel for ISA bus. */
+                if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
+                    shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
+                    if ((ret =
+                         request_dma(shp->dma_channel, "advansys")) != 0) {
+                        ASC_PRINT3(
+"advansys_detect: board %d: request_dma() %d failed %d\n",
+                            boardp->id, shp->dma_channel, ret);
+                        release_region(shp->io_port, shp->n_io_port);
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+                        kfree(boardp->prtbuf);
+#endif /* version >= v1.3.0 */
+                        scsi_unregister(shp);
+                        asc_board_count--;
+                        continue;
+                    }
+                    AscEnableIsaDma(shp->dma_channel);
+                }
+            }
 
-    /*
-     * 'qdonep' contains the command's ending status.
-     */
-    switch (qdonep->d3.done_stat) {
-    case QD_NO_ERROR:
-        ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
-        switch (qdonep->d3.host_stat) {
-        case QHSTA_NO_ERROR:
-            scp->result = 0;
-            break;
-        default:
-            /* QHSTA error occurred */
-            scp->result = HOST_BYTE(DID_ERROR);
-            break;
-        }
-        break;
+            /* Register IRQ Number. */
+            ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
+            if ((ret = request_irq(shp->irq, advansys_interrupt,
+                            SA_INTERRUPT, "advansys")) != 0)
+#else /* version >= v1.3.70 */
+            if ((ret = request_irq(shp->irq, advansys_interrupt,
+                            SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
+                            "advansys", boardp)) != 0)
+#endif /* version >= v1.3.70 */
+            {
+                ASC_PRINT2(
+"advansys_detect: board %d: request_irq() failed %d\n",
+                    boardp->id, ret);
+                release_region(shp->io_port, shp->n_io_port);
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+                iounmap(boardp->ioremap_addr);
+#endif /* version >= v1,3,0 */
+                if (shp->dma_channel != NO_ISA_DMA) {
+                    free_dma(shp->dma_channel);
+                }
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+                kfree(boardp->prtbuf);
+#endif /* version >= v1.3.0 */
+                scsi_unregister(shp);
+                asc_board_count--;
+                continue;
+            }
 
-    case QD_WITH_ERROR:
-        ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
-        switch (qdonep->d3.host_stat) {
-        case QHSTA_NO_ERROR:
-            if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
-                ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
-                ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
-                    sizeof(scp->sense_buffer));
+            /*
+             * Initialize board RISC chip and enable interrupts.
+             */
+            if (ASC_NARROW_BOARD(boardp)) {
+                ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
+                warn_code = AscInitAsc1000Driver(asc_dvc_varp);
+                err_code = asc_dvc_varp->err_code;
+
+                if (warn_code || err_code) {
+                    ASC_PRINT4(
+"AscInitAsc1000Driver: board %d: error: init_state %x, warn %x error %x\n",
+                        boardp->id, asc_dvc_varp->init_state,
+                        warn_code, err_code);
+                }
+            } else {
+                int             req_cnt;
+                adv_req_t       *reqp = NULL;
+                int             sg_cnt;
+                adv_sgblk_t     *sgp = NULL;
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+                req_cnt = sizeof(adv_req_buf)/sizeof(adv_req_t);
+                sg_cnt = sizeof(adv_sgblk_buf)/sizeof(adv_sgblk_t);
+                reqp = (adv_req_t *) &adv_req_buf[0];
+                sgp = (adv_sgblk_t *) &adv_sgblk_buf[0];
+#else /* version >= v1.3.0 */
                 /*
-                 * Note: The 'status_byte()' macro used by target drivers
-                 * defined in scsi.h shifts the status byte returned by
-                 * host drivers right by 1 bit. This is why target drivers
-                 * also use right shifted status byte definitions. For
-                 * instance target drivers use CHECK_CONDITION, defined to
-                 * 0x1, instead of the SCSI defined check condition value
-                 * of 0x2. Host drivers are supposed to return the status
-                 * byte as it is defined by SCSI.
+                 * Allocate up to 'max_host_qng' request structures for
+                 * the Wide board.
                  */
-                scp->result = DRIVER_BYTE(DRIVER_SENSE) |
-                    STATUS_BYTE(qdonep->d3.scsi_stat); 
-            } else {
-                scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); 
-            }
-            break;
+                for (req_cnt = adv_dvc_varp->max_host_qng;
+                    req_cnt > 0; req_cnt--) {
 
-        default:
-            /* QHSTA error occurred */
-            ASC_DBG1(2, "asc_isr_callback: host_stat %x\n",
-                qdonep->d3.host_stat);
-            scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
-                STATUS_BYTE(qdonep->d3.scsi_stat);
-            break;
-        }
-        break;
+                    reqp = (adv_req_t *)
+                        kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
 
-    case QD_ABORTED_BY_HOST:
-        ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
-        scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
-                STATUS_BYTE(qdonep->d3.scsi_stat);
-        break;
+                    ASC_DBG3(1,
+                        "advansys_detect: reqp %x, req_cnt %d, bytes %d\n",
+                        (unsigned) reqp, req_cnt, sizeof(adv_req_t) * req_cnt);
 
-    default:
-        ASC_PRINT1("asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat);
-        scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
-                STATUS_BYTE(qdonep->d3.scsi_stat);
-        break;
-    }
+                    if (reqp != NULL) {
+                        break;
+                    }
+                }
 
-    /* 
-     * Because interrupts may be enabled by the 'Scsi_Cmnd' done
-     * function, add the command to the end of the board's done queue.
-     * The done function for the command will be called from
-     * advansys_interrupt().
-     */
-    asc_enqueue(&boardp->done, scp, ASC_BACK);
+                /*
+                 * Allocate up to ADV_TOT_SG_LIST request structures for
+                 * the Wide board.
+                 */
+                for (sg_cnt = ADV_TOT_SG_LIST; sg_cnt > 0; sg_cnt--) {
 
-    return;
-}
+                    sgp = (adv_sgblk_t *)
+                        kmalloc(sizeof(adv_sgblk_t) * sg_cnt, GFP_ATOMIC);
 
-/*
- * asc_init_dev()
- *
- * Perform one-time initialization of a device.
- */
-STATIC int
-asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
-{
-    asc_board_t             *boardp;
-    ASC_SCSI_REQ_Q          *scsireqq;
-    ASC_CAP_INFO            *cap_info;
-    ASC_SCSI_INQUIRY        *inquiry;
-    int                     found;
-    ASC_SCSI_BIT_ID_TYPE    save_use_tagged_qng;
-    ASC_SCSI_BIT_ID_TYPE    save_can_tagged_qng;
-    int                     ret;
-#ifdef ADVANSYS_DEBUG
-    ASC_SCSI_BIT_ID_TYPE    tidmask; /* target id bit mask: 1 - 128 */
-#endif /* ADVANSYS_DEBUG */
+                    ASC_DBG3(1,
+                        "advansys_detect: sgp %x, sg_cnt %d, bytes %d\n",
+                        (unsigned) sgp, sg_cnt, sizeof(adv_sgblk_t) * sg_cnt);
 
-    ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target);
+                    if (sgp != NULL) {
+                        break;
+                    }
+                }
+#endif /* version >= v1.3.0 */
 
-    /* The host's target id is set in init_tidmask during initialization. */
-    ASC_ASSERT(asc_dvc_varp->cfg->chip_scsi_id != scp->target);
+                /*
+                 * If no request structures or scatter-gather structures could
+                 * be allocated, then return an error. Otherwise continue with
+                 * initialization.
+                 */
+                if (reqp == NULL) {
+                    ASC_PRINT1(
+"advansys_detect: board %d: error: failed to kmalloc() adv_req_t buffer.\n",
+                        boardp->id);
+                    err_code = ADV_ERROR;
+                } else if (sgp == NULL) {
+                    kfree(reqp);
+                    ASC_PRINT1(
+"advansys_detect: board %d: error: failed to kmalloc() adv_sgblk_t buffer.\n",
+                        boardp->id);
+                    err_code = ADV_ERROR;
+                } else {
+                    
+                    /*
+                     * Save original pointer for kfree() in case the
+                     * driver is built as a module and can be unloaded.
+                     */
+                    boardp->orig_reqp = reqp;
 
-    boardp = ASC_BOARDP(scp->host);
+                    /*
+                     * Point 'adv_reqp' to the request structures and
+                     * link them together.
+                     */
+                    req_cnt--;
+                    reqp[req_cnt].next_reqp = NULL;
+                    for (; req_cnt > 0; req_cnt--) {
+                        reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
+                    }
+                    boardp->adv_reqp = &reqp[0];
 
-    /* Set-up AscInitPollTarget() arguments. */
-    scsireqq = &boardp->scsireqq;
-    memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
-    cap_info = &boardp->cap_info;
-    memset(cap_info, 0, sizeof(ASC_CAP_INFO));
-    inquiry = &boardp->inquiry;
-    memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
+                    /*
+                     * Save original pointer for kfree() in case the
+                     * driver is built as a module and can be unloaded.
+                     */
+                    boardp->orig_sgblkp = sgp;
 
-    /*
-     * XXX - AscInitPollBegin() re-initializes these fields to
-     * zero. 'Or' in the new values and restore them before calling 
-     * AscInitPollEnd(). Normally all targets are initialized within
-     * a call to AscInitPollBegin() and AscInitPollEnd().
-     */
-    save_use_tagged_qng = asc_dvc_varp->use_tagged_qng;
-    save_can_tagged_qng = asc_dvc_varp->cfg->can_tagged_qng;
+                    /*
+                     * Point 'adv_sgblkp' to the request structures and
+                     * link them together.
+                     */
+                    sg_cnt--;
+                    sgp[sg_cnt].next_sgblkp = NULL;
+                    for (; sg_cnt > 0; sg_cnt--) {
+                        sgp[sg_cnt - 1].next_sgblkp = &sgp[sg_cnt];
+                    }
+                    boardp->adv_sgblkp = &sgp[0];
 
-    ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n");
-    if (AscInitPollBegin(asc_dvc_varp)) {
-        ASC_PRINT1("asc_init_dev: board %d: AscInitPollBegin() failed\n",
-            boardp->id);
-        return ASC_FALSE;
-    }
+                    ASC_DBG(2, "advansys_detect: AdvInitAsc3550Driver()\n");
+                    warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
+                    err_code = adv_dvc_varp->err_code;
 
-    scsireqq->sense_ptr = &scsireqq->sense[0];
-    scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN;
-    scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
-    scsireqq->r1.target_lun = 0;
-    scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
+                    if (warn_code || err_code) {
+                        ASC_PRINT3(
+"AdvInitAsc3550Driver: board %d: error: warn %x, error %x\n",
+                            boardp->id, warn_code, adv_dvc_varp->err_code);
+                    }
+                }
+            }
 
-    found = ASC_FALSE;
-    ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n");
-    switch (ret = AscInitPollTarget(asc_dvc_varp, scsireqq, inquiry,
-        cap_info)) {
-    case ASC_TRUE:
-        found = ASC_TRUE;
-#ifdef ADVANSYS_DEBUG
-        tidmask = ASC_TIX_TO_TARGET_ID(scp->target);
-        ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n",
-            cap_info->lba, cap_info->blk_size);
-        ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n",
-            inquiry->byte0.peri_dvc_type);
-        if (asc_dvc_varp->use_tagged_qng & tidmask) {
-            ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
-                asc_dvc_varp->max_dvc_qng[scp->target]);
-        } else {
-            ASC_DBG(1, "asc_init_dev: command queuing disabled\n");
-        }
-        if (asc_dvc_varp->init_sdtr & tidmask) {
-            ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n");
-        } else {
-            ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n");
-        }
-        /* Set bit means fix disabled. */
-        if (asc_dvc_varp->pci_fix_asyn_xfer & tidmask) {
-            ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n");
-        } else {
-            ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n");
+            if (err_code != 0) {
+                release_region(shp->io_port, shp->n_io_port);
+                if (ASC_WIDE_BOARD(boardp)) {
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+                    iounmap(boardp->ioremap_addr);
+#endif /* version >= v1,3,0 */
+                    if (boardp->orig_reqp) {
+                        kfree(boardp->orig_reqp);
+                        boardp->orig_reqp = boardp->adv_reqp = NULL;
+                    }
+                    if (boardp->orig_sgblkp) {
+                        kfree(boardp->orig_sgblkp);
+                        boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
+                    }
+                }
+                if (shp->dma_channel != NO_ISA_DMA) {
+                    free_dma(shp->dma_channel);
+                }
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+                kfree(boardp->prtbuf);
+#endif /* version >= v1.3.0 */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
+                free_irq(shp->irq);
+#else /* version >= v1.3.70 */
+                free_irq(shp->irq, boardp);
+#endif /* version >= v1.3.70 */
+                scsi_unregister(shp);
+                asc_board_count--;
+                continue;
+            }
+            ASC_DBG_PRT_SCSI_HOST(2, shp);
         }
-#endif /* ADVANSYS_DEBUG */
-        break;
-    case ASC_FALSE:
-        ASC_DBG(1, "asc_init_dev: no device found\n");
-        break;
-    case ASC_ERROR:
-        ASC_PRINT1("asc_init_dev: board %d: AscInitPollTarget() ASC_ERROR\n",
-                boardp->id);
-        break;
-    default:
-        ASC_PRINT2(
-"asc_init_dev: board %d: AscInitPollTarget() unknown ret %d\n",
-                boardp->id, ret);
-        break;
     }
-
-    /* XXX - 'Or' in original tag bits. */
-    asc_dvc_varp->use_tagged_qng |= save_use_tagged_qng;
-    asc_dvc_varp->cfg->can_tagged_qng |= save_can_tagged_qng;
-
-    ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n");
-    AscInitPollEnd(asc_dvc_varp);
-
-    ASC_DBG1(1, "asc_init_dev: found %d\n", found); 
-
-    return found;
+    ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count);
+    return asc_board_count;
 }
 
 /*
- * Search for an AdvanSys PCI device in the PCI configuration space.
+ * advansys_release()
+ *
+ * Release resources allocated for a single AdvanSys adapter.
  */
-ASC_INITFUNC(
-STATIC int
-asc_srch_pci_dev(PCI_DEVICE *pciDevice)
-)
+int
+advansys_release(struct Scsi_Host *shp)
 {
-    int ret;
-
-    ASC_DBG(2, "asc_srch_pci_dev: begin\n");
+    asc_board_t    *boardp;
 
-    if (pci_scan_method == -1) {
-        pci_scan_method = asc_scan_method();
+    ASC_DBG(1, "advansys_release: begin\n");
+    boardp = ASC_BOARDP(shp);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
+    free_irq(shp->irq);
+#else /* version >= v1.3.70 */
+    free_irq(shp->irq, boardp);
+#endif /* version >= v1.3.70 */
+    if (shp->dma_channel != NO_ISA_DMA) {
+        ASC_DBG(1, "advansys_release: free_dma()\n");
+        free_dma(shp->dma_channel);
     }
-    pciDevice->type = pci_scan_method;
-    ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
-
-    ret = asc_pci_find_dev(pciDevice);
-    ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
-    if (ret == PCI_DEVICE_FOUND) {
-        pciDevice->slotNumber = pciDevice->slotFound + 1;
-        pciDevice->startSlot = pciDevice->slotFound + 1;
-    } else {
-        if (pciDevice->bridge > pciDevice->busNumber) {
-            ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
-                pciDevice->bridge, pciDevice->busNumber);
-            pciDevice->busNumber++;
-            pciDevice->slotNumber = 0;
-            pciDevice->startSlot = 0;
-            pciDevice->endSlot = 0x0f;
-            ret = asc_srch_pci_dev(pciDevice);
-            ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret);
+    release_region(shp->io_port, shp->n_io_port);
+    if (ASC_WIDE_BOARD(boardp)) {
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+        iounmap(boardp->ioremap_addr);
+#endif /* version >= v1,3,0 */
+        if (boardp->orig_reqp) {
+            kfree(boardp->orig_reqp);
+            boardp->orig_reqp = boardp->adv_reqp = NULL;
+        }
+        if (boardp->orig_sgblkp) {
+            kfree(boardp->orig_sgblkp);
+            boardp->orig_sgblkp = boardp->adv_sgblkp = NULL;
         }
     }
-    ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
-    return ret;
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+    ASC_ASSERT(boardp->prtbuf != NULL);
+    kfree(boardp->prtbuf);
+#endif /* version >= v1.3.0 */
+    scsi_unregister(shp);
+    ASC_DBG(1, "advansys_release: end\n");
+    return 0;
 }
 
 /*
- * Determine the access method to be used for 'pciDevice'.
+ * advansys_info()
+ *
+ * Return suitable for printing on the console with the argument
+ * adapter's configuration information.
+ *
+ * Note: The information line should not exceed ASC_INFO_SIZE bytes,
+ * otherwise the static 'info' array will be overrun.
  */
-ASC_INITFUNC(
-STATIC uchar
-asc_scan_method(void)
-)
+const char *
+advansys_info(struct Scsi_Host *shp)
 {
-    ushort      data;
-    PCI_DATA    pciData;
-    uchar       type;
-    uchar       slot;
+    static char     info[ASC_INFO_SIZE];
+    asc_board_t     *boardp;
+    ASC_DVC_VAR     *asc_dvc_varp;
+    ADV_DVC_VAR     *adv_dvc_varp;
+    char            *busname;
 
-    ASC_DBG(2, "asc_scan_method: begin\n");
-    memset(&pciData, 0, sizeof(pciData));
-    for (type = 1; type < 3; type++) {
-        pciData.type = type;
-        for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
-            pciData.slot = slot;
-            data = asc_get_cfg_word(&pciData);
-            if ((data != 0xFFFF) && (data != 0x0000)) {
-                ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
-                return (type);
+    boardp = ASC_BOARDP(shp);
+    if (ASC_NARROW_BOARD(boardp)) {
+        asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
+        ASC_DBG(1, "advansys_info: begin\n");
+        if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
+            if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) {
+                busname = "ISA PnP";
+            } else {
+                busname = "ISA";
+            }
+            sprintf(info,
+"AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u, DMA %u",
+                ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
+                (unsigned) shp->base,
+                shp->io_port, shp->n_io_port - 1,
+                shp->irq, shp->dma_channel);
+        } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
+            if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
+                == ASC_IS_PCI_ULTRA) {
+                busname = "PCI Ultra";
+            } else {
+                busname = "PCI";
+            }
+            sprintf(info,
+                "AdvanSys SCSI %s: %s %u CDB: IO %X/%X, IRQ %u",
+                ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
+                shp->io_port, shp->n_io_port - 1, shp->irq);
+        } else {
+            if (asc_dvc_varp->bus_type & ASC_IS_VL) {
+                busname = "VL";
+            } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
+                busname = "EISA";
+            } else {
+                busname = "?";
+                ASC_PRINT2(
+    "advansys_info: board %d: unknown bus type %d\n",
+                    boardp->id, asc_dvc_varp->bus_type);
             }
+            sprintf(info,
+                "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u",
+                ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
+                (unsigned) shp->base, shp->io_port - 1,
+                shp->n_io_port, shp->irq);
+        }
+    } else {
+        /*
+         * Wide Adapter Information
+         *
+         * Memory-mapped I/O is used instead of I/O space to access
+         * the adapter, but display the I/O Port range. The Memory
+         * I/O address is displayed through the driver /proc file.
+         */
+        adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+        if (boardp->bios_signature == 0x55AA) {
+            sprintf(info,
+"AdvanSys SCSI %s: PCI Ultra-Wide: BIOS %X/%X, IO %X/%X, IRQ %u",
+                ASC_VERSION,
+                boardp->bios_codeseg << 4,
+                boardp->bios_codelen > 0 ?
+                (boardp->bios_codelen << 9) - 1 : 0,
+                (unsigned) boardp->ioport, ADV_CONDOR_IOLEN - 1,
+                shp->irq);
+        } else {
+            sprintf(info,
+"AdvanSys SCSI %s: PCI Ultra-Wide: IO %X/%X, IRQ %u",
+                ASC_VERSION,
+                (unsigned) boardp->ioport,
+                (ADV_CONDOR_IOLEN - 1),
+                shp->irq);
         }
     }
-    ASC_DBG1(4, "asc_scan_method: type %d\n", type);
-    return (type);
+    ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
+    ASC_DBG(1, "advansys_info: end\n");
+    return info;
 }
 
 /*
- * Check for an AdvanSys PCI device in 'pciDevice'.
+ * advansys_command() - polled I/O entrypoint.
  *
- * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
- */
-ASC_INITFUNC(
-STATIC int
-asc_pci_find_dev(PCI_DEVICE *pciDevice)
-)
-{
-    PCI_DATA    pciData;
-    ushort      vendorid, deviceid;
-    uchar       classcode, subclass;
-    uchar       lslot;
-
-    ASC_DBG(3, "asc_pci_find_dev: begin\n");
-    pciData.type = pciDevice->type;
-    pciData.bus = pciDevice->busNumber;
-    pciData.func = pciDevice->devFunc;
-    lslot = pciDevice->startSlot;
-    for (; lslot < pciDevice->endSlot; lslot++) {
-        pciData.slot = lslot;
-        pciData.offset = VENDORID_OFFSET;
-        vendorid = asc_get_cfg_word(&pciData);
-        ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
-        if (vendorid != 0xffff) {
-            pciData.offset = DEVICEID_OFFSET;
-            deviceid = asc_get_cfg_word(&pciData);
-            ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
-            if ((vendorid == ASC_PCI_VENDORID) &&
-                ((deviceid == ASC_PCI_DEVICE_ID_1100) ||
-                 (deviceid == ASC_PCI_DEVICE_ID_1200) ||
-                 (deviceid == ASC_PCI_DEVICE_ID_1300))) {
-                pciDevice->slotFound = lslot;
-                ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
-                return PCI_DEVICE_FOUND;
-            } else {
-                pciData.offset = SUBCLASS_OFFSET;
-                subclass = asc_get_cfg_byte(&pciData);
-                pciData.offset = CLASSCODE_OFFSET;
-                classcode = asc_get_cfg_byte(&pciData);
-                if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
-                    (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
-                    pciDevice->bridge++;
-                }
-                ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
-                    subclass, classcode);
-            }
-        }
-    }
-    return PCI_DEVICE_NOT_FOUND;
-}
-
-/*
- * Read PCI configuration data into 'pciConfig'.
+ * Apparently host drivers shouldn't return until the command
+ * is finished.
+ *
+ * Note: This is an old interface that is no longer used by the SCSI
+ * mid-level driver. The new interface, advansys_queuecommand(),
+ * currently handles all requests.
  */
-ASC_INITFUNC(
-STATIC void
-asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
-)
+int
+advansys_command(Scsi_Cmnd *scp)
 {
-    PCI_DATA    pciData;
-    uchar       counter;
-    uchar       *localConfig;
-
-    ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ",
-        pciDevice->slotFound);
-
-    pciData.type = pciDevice->type;
-    pciData.bus = pciDevice->busNumber;
-    pciData.slot = pciDevice->slotFound;
-    pciData.func = pciDevice->devFunc;
-    localConfig = (uchar *) pciConfig;
-
-    for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
-        pciData.offset = counter;
-        *localConfig = asc_get_cfg_byte(&pciData);
-        ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
-        localConfig++;
+    ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
+    ASC_STATS(scp->host, command);
+    scp->SCp.Status = 0; /* Set to a known state */
+    advansys_queuecommand(scp, advansys_command_done);
+    while (scp->SCp.Status == 0) {
+        continue;
     }
-    ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
+    ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
+    return scp->result;
 }
 
 /*
- * Read a word (16 bits) from the PCI configuration space.
+ * advansys_queuecommand() - interrupt-driven I/O entrypoint.
  *
- * The configuration mechanism is checked for the correct access method.
+ * This function always returns 0. Command return status is saved
+ * in the 'scp' result field.
  */
-ASC_INITFUNC(
-STATIC ushort
-asc_get_cfg_word(PCI_DATA *pciData)
-)
+int
+advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
 {
-    ushort   tmp;
-    ulong    address;
-    ulong    lbus = pciData->bus;
-    ulong    lslot = pciData->slot;
-    ulong    lfunc = pciData->func;
-    uchar    t2CFA, t2CF8;
-    ulong    t1CF8, t1CFC;
+    struct Scsi_Host    *shp;
+    asc_board_t         *boardp;
+    int                 flags;
+    Scsi_Cmnd           *done_scp;
 
-    ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
-        pciData->type, lbus, lslot, lfunc);
+    shp = scp->host;
+    boardp = ASC_BOARDP(shp);
+    ASC_STATS(shp, queuecommand);
 
     /*
-     * Check type of configuration mechanism.
+     * Disable interrupts to preserve request ordering and provide
+     * mutually exclusive access to global structures used to initiate
+     * a request.
      */
-    if (pciData->type == 2) {
-        /*
-         * Save registers to be restored later.
-         */
-        t2CFA = inp(0xCFA);    /* save PCI bus register */
-        t2CF8 = inp(0xCF8);    /* save config space enable register */
-
-        /*
-         * Write the bus and enable registers.
-         */
-        /* set for type 1 cycle, if needed */
-        outp(0xCFA, pciData->bus);
-        /* set the function number */
-        outp(0xCF8, 0x10 | (pciData->func << 1)) ;
-
-        /*
-         * Read the configuration space type 2 locations.
-         */
-        tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
-
-        outp(0xCFA, t2CFA);    /* save PCI bus register */
-        outp(0xCF8, t2CF8);    /* save config space enable register */
-    } else {
-        /*
-         * Type 1 or 3 configuration mechanism.
-         *
-         * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
-         */
-        t1CF8 = inpl(0xCF8);
-        t1CFC = inpl(0xCFC);
+    save_flags(flags);
+    cli();
 
-        /*
-         * enable <31>, bus = <23:16>, slot = <15:11>,
-         * func = <10:8>, reg = <7:2>
-         */
-        address = (ulong) ((lbus << 16) | (lslot << 11) |
-            (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
+    /*
+     * Block new commands while handling a reset or abort request.
+     */
+    if (boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
+        if (boardp->flags & ASC_HOST_IN_RESET) {
+            ASC_DBG1(1,
+                "advansys_queuecommand: scp %x blocked for reset request\n",
+                (unsigned) scp);
+            scp->result = HOST_BYTE(DID_RESET);
+        } else {
+            ASC_DBG1(1,
+                "advansys_queuecommand: scp %x blocked for abort request\n",
+                (unsigned) scp);
+            scp->result = HOST_BYTE(DID_ABORT);
+        }
 
         /*
-         * Write out the address to CONFIG_ADDRESS.
+         * Add blocked requests to the board's 'done' queue. The queued
+         * requests will be completed at the end of the abort or reset
+         * handling.
          */
-        outpl(0xCF8, address);
+        asc_enqueue(&boardp->done, scp, ASC_BACK);
+        restore_flags(flags);
+        return 0;
+    }
 
-        /*
-         * Read in word from CONFIG_DATA.
-         */
-        tmp = (ushort) ((inpl(0xCFC) >>
-                 ((pciData->offset & 2) * 8)) & 0xFFFF);
+    /*
+     * Attempt to execute any waiting commands for the board.
+     */
+    if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
+        ASC_DBG(1,
+            "advansys_queuecommand: before asc_execute_queue() waiting\n");
+        asc_execute_queue(&boardp->waiting);
+    }
 
-        /*
-         * Restore registers.
-         */
-        outpl(0xCF8, t1CF8);
-        outpl(0xCFC, t1CFC);
+    /*
+     * Save the function pointer to Linux mid-level 'done' function
+     * and attempt to execute the command.
+     *
+     * If ASC_ERROR is returned the request has been added to the
+     * board's 'active' queue and will be completed by the interrupt
+     * handler.
+     *
+     * If ASC_BUSY is returned add the request to the board's per
+     * target waiting list.
+     * 
+     * If an error occurred, the request will have been placed on the
+     * board's 'done' queue and must be completed before returning.
+     */
+    scp->scsi_done = done;
+    switch (asc_execute_scsi_cmnd(scp)) {
+    case ASC_NOERROR:
+        break;
+    case ASC_BUSY:
+        asc_enqueue(&boardp->waiting, scp, ASC_BACK);
+        break;
+    case ASC_ERROR:
+    default:
+        done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
+        /* Interrupts could be enabled here. */
+        asc_scsi_done_list(done_scp);
+        break;
     }
-    ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
-    return tmp;
+
+    restore_flags(flags);
+    return 0;
 }
 
 /*
- * Reads a byte from the PCI configuration space.
+ * advansys_abort()
  *
- * The configuration mechanism is checked for the correct access method.
+ * Abort the command specified by 'scp'.
  */
-ASC_INITFUNC(
-STATIC uchar
-asc_get_cfg_byte(PCI_DATA *pciData)
-)
+int
+advansys_abort(Scsi_Cmnd *scp)
 {
-    uchar tmp;
-    ulong address;
-    ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
-    uchar t2CFA, t2CF8;
-    ulong t1CF8, t1CFC;
-
-    ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
+    struct Scsi_Host    *shp;
+    asc_board_t         *boardp;
+    ASC_DVC_VAR         *asc_dvc_varp;
+    ADV_DVC_VAR         *adv_dvc_varp;
+    int                 flags;
+    int                 do_scsi_done;
+    int                 scp_found;
+    Scsi_Cmnd           *done_scp = NULL;
+    int                 ret;
 
-    /*
-     * Check type of configuration mechanism.
-     */
-    if (pciData->type == 2) {
-        /*
-         * Save registers to be restored later.
-         */
-        t2CFA = inp(0xCFA);    /* save PCI bus register */
-        t2CF8 = inp(0xCF8);    /* save config space enable register */
+    /* Save current flags and disable interrupts. */
+    save_flags(flags);
+    cli();
 
-        /*
-         * Write the bus and enable registers.
-         */
-        /* set for type 1 cycle, if needed */
-        outp(0xCFA, pciData->bus);
-        /* set the function number */
-        outp(0xCF8, 0x10 | (pciData->func << 1));
+    ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
 
-        /*
-         * Read configuration space type 2 locations.
-         */
-        tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
+#ifdef ADVANSYS_STATS
+    if (scp->host != NULL) {
+        ASC_STATS(scp->host, abort);
+    }    
+#endif /* ADVANSYS_STATS */
 
-        /*
-         * Restore registers.
-         */
-        outp(0xCF8, t2CF8);    /* restore the enable register */
-        outp(0xCFA, t2CFA);    /* restore PCI bus register */
+#ifdef ADVANSYS_ASSERT
+    do_scsi_done = ASC_ERROR;
+    scp_found = ASC_ERROR;
+    ret = ASC_ERROR;
+#endif /* ADVANSYS_ASSERT */
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+    if (scp->serial_number != scp->serial_number_at_timeout) {
+        ASC_PRINT1(
+"advansys_abort: timeout serial number changed for request %x\n",
+            (unsigned) scp);
+        do_scsi_done = ASC_FALSE;
+        scp_found = ASC_FALSE;
+        ret = SCSI_ABORT_NOT_RUNNING;
+    } else
+#endif /* version >= v1.3.89 */
+    if ((shp = scp->host) == NULL) {
+        scp->result = HOST_BYTE(DID_ERROR);
+        do_scsi_done = ASC_TRUE;
+        scp_found = ASC_FALSE;
+        ret = SCSI_ABORT_ERROR;
+    } else if ((boardp = ASC_BOARDP(shp))->flags & 
+                (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
+        ASC_PRINT2(
+"advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n",
+            boardp->id, boardp->flags);
+        do_scsi_done = ASC_TRUE;
+        if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+            (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+            scp_found = ASC_TRUE;
+        } else {
+            scp_found = ASC_FALSE;
+        }
+        scp->result = HOST_BYTE(DID_ERROR);
+        ret = SCSI_ABORT_ERROR;
     } else {
-        /*
-         * Type 1 or 3 configuration mechanism.
-         *
-         * Save CONFIG_ADDRESS and CONFIG_DATA register values.
-         */
-        t1CF8 = inpl(0xCF8);
-        t1CFC = inpl(0xCFC);
+        /* Set abort flag to avoid nested reset or abort requests. */
+        boardp->flags |= ASC_HOST_IN_ABORT;
 
-        /*
-         * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
-         * reg = <7:2>
-         */
-        address = (ulong) ((lbus << 16) | (lslot << 11) |
-            (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
+        do_scsi_done = ASC_TRUE;
+        if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
+            /*
+             * If asc_rmqueue() found the command on the waiting
+             * queue, it had not been sent to the device. After
+             * the queue is removed, no other handling is required.
+             */
+            ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n",
+                (unsigned) scp);
+            scp_found = ASC_TRUE;
+            scp->result = HOST_BYTE(DID_ABORT);
+            ret = SCSI_ABORT_SUCCESS;
+        } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) {
+            /*
+             * If asc_isqueued() found the command on the active
+             * queue, it has been sent to the device. The command
+             * will be returned through the interrupt handler after
+             * it has been aborted.
+             */
 
-        /*
-         * Write out address to CONFIG_ADDRESS.
-         */
-        outpl(0xCF8, address);
+            if (ASC_NARROW_BOARD(boardp)) {
+                /*
+                 * Narrow Board
+                 */
+                asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
+                scp->result = HOST_BYTE(DID_ABORT);
 
-        /*
-         * Read in word from CONFIG_DATA.
-         */
-        tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
+                sti(); /* Enable interrupts for AscAbortSRB(). */
+                ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n",
+                    (unsigned) scp);
+                switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
+                case ASC_TRUE:
+                    /* asc_isr_callback() will be called */
+                    ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
+                    ret = SCSI_ABORT_PENDING;
+                    break;
+                case ASC_FALSE:
+                    /* Request has apparently already completed. */
+                    ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n");
+                    ret = SCSI_ABORT_NOT_RUNNING;
+                    break;
+                case ASC_ERROR:
+                default:
+                    ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n");
+                    ret = SCSI_ABORT_ERROR;
+                    break;
+                }
+                cli();
+            } else {
+                /*
+                 * Wide Board
+                 */
+                adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+                scp->result = HOST_BYTE(DID_ABORT);
 
-        /*
-         * Restore registers.
-         */
-        outpl(0xCF8, t1CF8);
-        outpl(0xCFC, t1CFC);
-    }
-    ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
-    return tmp;
-}
+                ASC_DBG1(1, "advansys_abort: before AdvAbortSRB(), scp %x\n",
+                    (unsigned) scp);
+                switch (AdvAbortSRB(adv_dvc_varp, (ulong) scp)) {
+                case ASC_TRUE:
+                    /* asc_isr_callback() will be called */
+                    ASC_DBG(1, "advansys_abort: AdvAbortSRB() TRUE\n");
+                    ret = SCSI_ABORT_PENDING;
+                    break;
+                case ASC_FALSE:
+                    /* Request has apparently already completed. */
+                    ASC_DBG(1, "advansys_abort: AdvAbortSRB() FALSE\n");
+                    ret = SCSI_ABORT_NOT_RUNNING;
+                    break;
+                case ASC_ERROR:
+                default:
+                    ASC_DBG(1, "advansys_abort: AdvAbortSRB() ERROR\n");
+                    ret = SCSI_ABORT_ERROR;
+                    break;
+                }
+                /*
+                 * Ensure all requests completed by the microcode have
+                 * been processed by calling AdvISR().
+                 */
+                (void) AdvISR(adv_dvc_varp);
+            }
 
-/*
- * Write a byte to the PCI configuration space.
- */
-ASC_INITFUNC(
-STATIC void
-asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data)
-)
-{
-    ulong tmpl;
-    ulong address;
-    ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
-    uchar t2CFA, t2CF8;
-    ulong t1CF8, t1CFC;
+            /*
+             * The request will either still be on the active queue
+             * or have been added to the board's done queue.
+             */
+            if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
+                scp->result = HOST_BYTE(DID_ABORT);
+                scp_found = ASC_TRUE;
+            } else {
+                scp_found = asc_rmqueue(&boardp->done, scp);
+                ASC_ASSERT(scp_found == ASC_TRUE);
+            }
 
-    ASC_DBG2(4, "asc_put_cfg_byte: type: %d, byte_data %x\n",
-        pciData->type, byte_data);
+        } else {
+            /*
+             * The command was not found on the active or waiting queues.
+             */
+            do_scsi_done = ASC_TRUE;
+            scp_found = ASC_FALSE;
+            ret = SCSI_ABORT_NOT_RUNNING;
+        }
 
-    /*
-     * Check type of configuration mechanism.
-     */
-    if (pciData->type == 2) {
+        /* Clear abort flag. */
+        boardp->flags &= ~ASC_HOST_IN_ABORT;
 
         /*
-         * Save registers to be restored later.
+         * Because the ASC_HOST_IN_ABORT flag causes both
+         * 'advansys_interrupt' and 'asc_isr_callback' to
+         * queue requests to the board's 'done' queue and
+         * prevents waiting commands from being executed,
+         * these queued requests must be handled here.
          */
-        t2CFA = inp(0xCFA);    /* save PCI bus register */
-        t2CF8 = inp(0xCF8);    /* save config space enable register */
+        done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
 
         /*
-         * Write bus and enable registers.
+         * Start any waiting commands for the board.
          */
-        outp(0xCFA, pciData->bus);
+        if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
+            ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
+            asc_execute_queue(&boardp->waiting);
+        }
+    }
 
-        /*
-         * Set the function number.
-         */
-        outp(0xCF8, 0x10 | (pciData->func << 1));
+    /* Interrupts could be enabled here. */
 
-        /*
-         * Write the configuration space type 2 locations.
-         */
-        outp(0xC000 | ((pciData->slot << 8) + pciData->offset), byte_data);
+    /*
+     * Complete the request to be aborted, unless it has been
+     * restarted as detected above, even if it was not found on
+     * the device active or waiting queues.
+     */
+    ASC_ASSERT(do_scsi_done != ASC_ERROR);
+    ASC_ASSERT(scp_found != ASC_ERROR);
+    if (do_scsi_done == ASC_TRUE) {
+        if (scp->scsi_done == NULL) {
+            ASC_PRINT1(
+"advansys_abort: aborted request scsi_done() is NULL, %x\n",
+                (unsigned) scp);
+        } else {
+            if (scp_found == ASC_FALSE) {
+                ASC_PRINT1(
+"advansys_abort: abort request not active or waiting, completing anyway %x\n",
+                    (unsigned) scp);
+            }
+            ASC_STATS(scp->host, done);
+            scp->scsi_done(scp);
+        }
+    }
 
-        /*
-         * Restore registers.
-         */
-        outp(0xCF8, t2CF8);    /* restore the enable register */
-        outp(0xCFA, t2CFA);    /* restore PCI bus register    */
-    } else {
+    /*
+     * It is possible for the request done function to re-enable
+     * interrupts without confusing the driver. But here interrupts
+     * aren't enabled until all requests have been completed.
+     */
+    if (done_scp != NULL) {
+        asc_scsi_done_list(done_scp);
+    }
 
-        /*
-         * Type 1 or 3 configuration mechanism.
-         *
-         * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
-         */
-        t1CF8 = inpl(0xCF8);
-        t1CFC = inpl(0xCFC);
+    ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
 
-        /*
-         * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
-         * reg = <7:2>
-         */
-        address = (ulong) ((lbus << 16) | (lslot << 11) | (lfunc << 8) |
-                (pciData->offset & 0xFC) | 0x80000000L);
-        /*
-         * Write out address to CONFIG_ADDRESS.
-         */
-        outpl(0xCF8, address);
-
-        /*
-         * Write double word to CONFIG_DATA preserving the bytes
-         * in the double not written.
-         */
-        tmpl = inpl(0xCFC) & ~(0xFF << ((pciData->offset & 3) * 8));
-        outpl(0xCFC, tmpl | (byte_data << ((pciData->offset & 3) * 8)));
+    /* Re-enable interrupts, if they were enabled on entry. */
+    restore_flags(flags);
 
-        /*
-         * Restore registers.
-         */
-        outpl(0xCF8, t1CF8);
-        outpl(0xCFC, t1CFC);
-    }
-    ASC_DBG(4, "asc_put_cfg_byte: end\n");
+    ASC_ASSERT(ret != ASC_ERROR);
+    return ret;
 }
 
 /*
- * Add a 'REQP' to the end of specified queue. Set 'tidmask'
- * to indicate a command is queued for the device.
- *
- * 'flag' may be either ASC_FRONT or ASC_BACK.
+ * advansys_reset()
  *
- * 'REQPNEXT(reqp)' returns reqp's next pointer.
+ * Reset the device associated with the command 'scp'.
  */
-STATIC void
-asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
+int
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+advansys_reset(Scsi_Cmnd *scp)
+#else /* version >= v1.3.89 */
+advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
+#endif /* version >= v1.3.89 */
 {
-    int        tid;
+    struct Scsi_Host     *shp;
+    asc_board_t          *boardp;
+    ASC_DVC_VAR          *asc_dvc_varp;
+    ADV_DVC_VAR          *adv_dvc_varp;
+    int                  flags;
+    Scsi_Cmnd            *done_scp = NULL, *last_scp = NULL;
+    Scsi_Cmnd            *tscp, *new_last_scp;
+    int                  do_scsi_done;
+    int                  scp_found;
+    int                  status;
+    int                  target;
+    int                  ret;
+    int                  device_reset = ASC_FALSE;
 
-    ASC_DBG3(2, "asc_enqueue: ascq %x, reqp %x, flag %d\n",
-        (unsigned) ascq, (unsigned) reqp, flag);
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    ASC_ASSERT(reqp != NULL);
-    ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
-    tid = REQPTID(reqp);
-    ASC_ASSERT(tid >= 0 && tid <= ASC_MAX_TID);
-    if (flag == ASC_FRONT) {
-        REQPNEXT(reqp) = ascq->q_first[tid];
-        ascq->q_first[tid] = reqp;
-        /* If the queue was empty, set the last pointer. */
-        if (ascq->q_last[tid] == NULL) {
-            ascq->q_last[tid] = reqp;
-        }
-    } else { /* ASC_BACK */
-        if (ascq->q_last[tid] != NULL) {
-            REQPNEXT(ascq->q_last[tid]) = reqp;
-        }
-        ascq->q_last[tid] = reqp;
-        REQPNEXT(reqp) = NULL;
-        /* If the queue was empty, set the first pointer. */
-        if (ascq->q_first[tid] == NULL) {
-            ascq->q_first[tid] = reqp;
-        }
-    }
-    /* The queue has at least one entry, set its bit. */
-    ascq->q_tidmask |= ASC_TIX_TO_TARGET_ID(tid);
-#ifdef ADVANSYS_STATS
-    /* Maintain request queue statistics. */
-    ascq->q_tot_cnt[tid]++;
-    ascq->q_cur_cnt[tid]++;
-    if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
-        ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
-        ASC_DBG2(1, "asc_enqueue: new q_max_cnt[%d] %d\n",
-            tid, ascq->q_max_cnt[tid]);
-    }
-    REQPTIME(reqp) = REQTIMESTAMP();
-#endif /* ADVANSYS_STATS */
-    ASC_DBG1(1, "asc_enqueue: reqp %x\n", (unsigned) reqp);
-    return;
-}
+    /* Save current flags and disable interrupts. */
+    save_flags(flags);
+    cli();
 
-/*
- * Return first queued 'REQP' on the specified queue for
- * the specified target device. Clear the 'tidmask' bit for
- * the device if no more commands are left queued for it.
- *
- * 'REQPNEXT(reqp)' returns reqp's next pointer.
- */
-STATIC REQP
-asc_dequeue(asc_queue_t *ascq, int tid)
-{
-    REQP    reqp;
+    ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
 
-    ASC_DBG2(1, "asc_dequeue: ascq %x, tid %d\n", (unsigned) ascq, tid);
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    ASC_ASSERT(tid >= 0 && tid <= ASC_MAX_TID);
-    if ((reqp = ascq->q_first[tid]) != NULL) {
-        ASC_ASSERT(ascq->q_tidmask & ASC_TIX_TO_TARGET_ID(tid));
-        ascq->q_first[tid] = REQPNEXT(reqp);
-        /* If the queue is empty, clear its bit and the last pointer. */
-        if (ascq->q_first[tid] == NULL) {
-            ascq->q_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
-            ASC_ASSERT(ascq->q_last[tid] == reqp);
-            ascq->q_last[tid] = NULL;
-        }
 #ifdef ADVANSYS_STATS
-        /* Maintain request queue statistics. */
-        ascq->q_cur_cnt[tid]--;
-        ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
-        REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
+    if (scp->host != NULL) {
+        ASC_STATS(scp->host, reset);
+    }    
 #endif /* ADVANSYS_STATS */
-    }
-    ASC_DBG1(1, "asc_dequeue: reqp %x\n", (unsigned) reqp);
-    return reqp;
-}
-
-/*
- * Return a pointer to a singly linked list of all the requests queued
- * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
- *
- * If 'lastpp' is not NULL, '*lastpp' will be set to point to the 
- * the last request returned in the singly linked list.
- *
- * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
- * then all queued requests are concatenated into one list and
- * returned.
- *
- * Note: If 'lastpp' is used to append a new list to the end of
- * an old list, only change the old list last pointer if '*lastpp'
- * (or the function return value) is not NULL, i.e. use a temporary
- * variable for 'lastpp' and check its value after the function return
- * before assigning it to the list last pointer.
- *
- * Unfortunately collecting queuing time statistics adds overhead to
- * the function that isn't inherent to the function's algorithm.
- */
-STATIC REQP
-asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
-{
-    REQP    firstp, lastp;
-    int     i;
-
-    ASC_DBG2(1, "asc_dequeue_list: ascq %x, tid %d\n", (unsigned) ascq, tid);
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ASC_MAX_TID));
 
-    /*
-     * If 'tid' is not ASC_TID_ALL, return requests only for
-     * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
-     * requests for all tids.
-     */
-    if (tid != ASC_TID_ALL) {
-        /* Return all requests for the specified 'tid'. */
-        if ((ascq->q_tidmask & ASC_TIX_TO_TARGET_ID(tid)) == 0) {
-            /* List is empty; Set first and last return pointers to NULL. */
-            firstp = lastp = NULL;
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+    if ((reset_flags & SCSI_RESET_ASYNCHRONOUS) &&
+        (scp->serial_number != scp->serial_number_at_timeout)) {
+        ASC_PRINT1(
+"advansys_reset: timeout serial number changed for request %x\n",
+            (unsigned) scp);
+        do_scsi_done = ASC_FALSE;
+        scp_found = ASC_FALSE;
+        ret = SCSI_RESET_NOT_RUNNING;
+    } else
+#endif /* version >= v1.3.89 */
+    if ((shp = scp->host) == NULL) {
+        scp->result = HOST_BYTE(DID_ERROR);
+        do_scsi_done = ASC_TRUE;
+        scp_found = ASC_FALSE;
+        ret = SCSI_RESET_ERROR;
+    } else if ((boardp = ASC_BOARDP(shp))->flags & 
+                (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
+        ASC_PRINT2(
+"advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n",
+            boardp->id, boardp->flags);
+        do_scsi_done = ASC_TRUE;
+        if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+            (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+            scp_found = ASC_TRUE;
         } else {
-            firstp = ascq->q_first[tid];
-            lastp = ascq->q_last[tid];
-            ascq->q_first[tid] = ascq->q_last[tid] = NULL;
-            ascq->q_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
-#ifdef ADVANSYS_STATS
-            {
-                REQP reqp;
-                ascq->q_cur_cnt[tid] = 0;
-                for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
-                    REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid);
-                }
-            }
-#endif /* ADVANSYS_STATS */
-        }
-    } else {
-        /* Return all requests for all tids. */
-        firstp = lastp = NULL;
-        for (i = 0; i <= ASC_MAX_TID; i++) {
-            if (ascq->q_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
-                if (firstp == NULL) {
-                    firstp = ascq->q_first[i];
-                    lastp = ascq->q_last[i];
-                } else {
-                    ASC_ASSERT(lastp != NULL);
-                    REQPNEXT(lastp) = ascq->q_first[i];
-                    lastp = ascq->q_last[i];
-                }
-                ascq->q_first[i] = ascq->q_last[i] = NULL;
-                ascq->q_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
-#ifdef ADVANSYS_STATS
-                ascq->q_cur_cnt[i] = 0;
-#endif /* ADVANSYS_STATS */
-            }
+            scp_found = ASC_FALSE;
         }
-#ifdef ADVANSYS_STATS
-        {
-            REQP reqp;
-            for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
-                REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target);
-            }
+        scp->result = HOST_BYTE(DID_ERROR);
+        ret = SCSI_RESET_ERROR;
+    } else if (jiffies >= boardp->last_reset &&
+               jiffies < (boardp->last_reset + (10 * HZ))) {
+        /*
+         * Don't allow a reset to be attempted within 10 seconds
+         * of the last reset.
+         *
+         * If 'jiffies' wrapping occurs, the reset request will go
+         * through, because a wrapped 'jiffies' would not pass the
+         * test above.
+         */
+        ASC_DBG(1,
+            "advansys_reset: reset within 10 sec of last reset ignored\n");
+        do_scsi_done = ASC_TRUE;
+        if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+            (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+            scp_found = ASC_TRUE;
+        } else {
+            scp_found = ASC_FALSE;
         }
-#endif /* ADVANSYS_STATS */
-    }
-    if (lastpp) {
-        *lastpp = lastp;
-    }
-    ASC_DBG1(1, "asc_dequeue_list: firstp %x\n", (unsigned) firstp);
-    return firstp;
-}
+        scp->result = HOST_BYTE(DID_ERROR);
+        ret = SCSI_RESET_ERROR;
+    } else {
+        do_scsi_done = ASC_TRUE;
 
-/*
- * Remove the specified 'REQP' from the specified queue for
- * the specified target device. Clear the 'tidmask' bit for the
- * device if no more commands are left queued for it.
- *
- * 'REQPNEXT(reqp)' returns reqp's the next pointer.
- *
- * Return ASC_TRUE if the command was found and removed,
- * otherwise return ASC_FALSE.
- */
-STATIC int
-asc_rmqueue(asc_queue_t *ascq, REQP reqp)
-{
-    REQP        currp, prevp;
-    int         tid;
-    int         ret = ASC_FALSE;
-
-    ASC_DBG2(1, "asc_rmqueue: ascq %x, reqp %x\n",
-        (unsigned) ascq, (unsigned) reqp);
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    ASC_ASSERT(reqp != NULL);
-
-    tid = REQPTID(reqp);
-    ASC_ASSERT(tid >= 0 && tid <= ASC_MAX_TID);
+        /* Set reset flag to avoid nested reset or abort requests. */
+        boardp->flags |= ASC_HOST_IN_RESET;
 
-    /*
-     * Handle the common case of 'reqp' being the first
-     * entry on the queue.
-     */
-    if (reqp == ascq->q_first[tid]) {
-        ret = ASC_TRUE;
-        ascq->q_first[tid] = REQPNEXT(reqp);
-        /* If the queue is now empty, clear its bit and the last pointer. */
-        if (ascq->q_first[tid] == NULL) {
-            ascq->q_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
-            ASC_ASSERT(ascq->q_last[tid] == reqp);
-            ascq->q_last[tid] = NULL;
-        }
-    } else if (ascq->q_first[tid] != NULL) {
-        ASC_ASSERT(ascq->q_last[tid] != NULL);
         /*
-         * Because the case of 'reqp' being the first entry has been
-         * handled above and it is known the queue is not empty, if
-         * 'reqp' is found on the queue it is guaranteed the queue will
-         * not become empty and that 'q_first[tid]' will not be changed.
-         *
-         * Set 'prevp' to the first entry, 'currp' to the second entry,
-         * and search for 'reqp'.
+          * If the request is on the target waiting or active queue
+         * or the board done queue, then remove it and note that it
+         * was found.
          */
-        for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
-             currp; prevp = currp, currp = REQPNEXT(currp)) {
-            if (currp == reqp) {
-                ret = ASC_TRUE;
-                REQPNEXT(prevp) = REQPNEXT(currp);
-                REQPNEXT(reqp) = NULL;
-                if (ascq->q_last[tid] == reqp) {
-                    ascq->q_last[tid] = prevp;
-                }
-                break;
-            }
+        if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
+            ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n");
+            scp_found = ASC_TRUE;
+        } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
+            ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n");
+            scp_found = ASC_TRUE;
+        } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) {
+            scp_found = ASC_TRUE;
+        } else {
+            scp_found = ASC_FALSE;
         }
-    }
-#ifdef ADVANSYS_STATS
-    /* Maintain request queue statistics. */
-    if (ret == ASC_TRUE) {
-        ascq->q_cur_cnt[tid]--;
-        REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
-    }
-    ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
-#endif /* ADVANSYS_STATS */
-    ASC_DBG2(1, "asc_rmqueue: reqp %x, ret %d\n", (unsigned) reqp, ret);
-    return ret;
-}
 
-/*
- * If the specified 'REQP' is queued on the specified queue for
- * the specified target device, return ASC_TRUE.
- */
-STATIC int
-asc_isqueued(asc_queue_t *ascq, REQP reqp)
-{
-    REQP        treqp;
-    int            tid;
-    int            ret = ASC_FALSE;
 
-    ASC_DBG2(1, "asc_isqueued: ascq %x, reqp %x\n",
-        (unsigned) ascq, (unsigned) reqp);
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    ASC_ASSERT(reqp != NULL);
+        if (ASC_NARROW_BOARD(boardp)) {
+            /*
+             * Narrow Board
+             *
+             * If the suggest reset bus flags are set, then reset the bus.
+             * Otherwise only reset the device.
+             */
+            asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+            if (reset_flags &
+                (SCSI_RESET_SUGGEST_BUS_RESET |
+                 SCSI_RESET_SUGGEST_HOST_RESET)) {
+#endif /* version >= v1.3.89 */
 
-    tid = REQPTID(reqp);
-    ASC_ASSERT(tid >= 0 && tid <= ASC_MAX_TID);
+                /*
+                 * Reset the target's SCSI bus.
+                 */
+                ASC_DBG(1, "advansys_reset: before AscResetSB()\n");
+                sti();    /* Enable interrupts for AscResetSB(). */
+                status = AscResetSB(asc_dvc_varp);
+                cli();
+                switch (status) {
+                case ASC_TRUE:
+                    ASC_DBG(1, "advansys_reset: AscResetSB() success\n");
+                    ret = SCSI_RESET_SUCCESS;
+                    break;
+                case ASC_ERROR:
+                default:
+                    ASC_DBG(1, "advansys_reset: AscResetSB() failed\n");
+                    ret = SCSI_RESET_ERROR;
+                    break;
+                }
 
-    for (treqp = ascq->q_first[tid]; treqp; treqp = REQPNEXT(treqp)) {
-        ASC_ASSERT(ascq->q_tidmask & ASC_TIX_TO_TARGET_ID(tid));
-        if (treqp == reqp) {
-            ret = ASC_TRUE;
-            break;
-        }
-    }
-    ASC_DBG1(1, "asc_isqueued: ret %x\n", ret);
-    return ret;
-}
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+            } else {
+                /*
+                 * Reset the specified device. If the device reset fails,
+                 * then reset the SCSI bus.
+                 */
 
-/*
- * Execute as many queued requests as possible for the specified queue.
- *
- * Calls asc_execute_scsi_cmnd() to execute a REQP/Scsi_Cmnd.
- */
-STATIC void
-asc_execute_queue(asc_queue_t *ascq)
-{
-    ASC_SCSI_BIT_ID_TYPE    scan_tidmask;
-    REQP                    reqp;
-    int                        i;
+                ASC_DBG1(1,
+                    "advansys_reset: before AscResetDevice(), target %d\n",
+                    scp->target);
+                sti();    /* Enable interrupts for AscResetDevice(). */
+                status = AscResetDevice(asc_dvc_varp, scp->target);
+                cli();
 
-    ASC_DBG1(1, "asc_execute_queue: ascq %x\n", (unsigned) ascq);
-    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
-    /*
-     * Execute queued commands for devices attached to
-     * the current board in round-robin fashion.
-     */
-    scan_tidmask = ascq->q_tidmask;
-    do {
-        for (i = 0; i <= ASC_MAX_TID; i++) {
-            if (scan_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
-                if ((reqp = asc_dequeue(ascq, i)) == NULL) {
-                    scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
-                } else if (asc_execute_scsi_cmnd((Scsi_Cmnd *) reqp)
-                            == ASC_BUSY) {
-                    scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
-                    /* Put the request back at front of the list. */
-                    asc_enqueue(ascq, reqp, ASC_FRONT);
+                /*
+                 * If the device has been reset, try to initialize it.
+                 */
+                if (status == ASC_TRUE) {
+                    status = asc_init_dev(asc_dvc_varp, scp);
+                }
+
+                switch (status) {
+                case ASC_TRUE:
+                    ASC_DBG(1, "advansys_reset: AscResetDevice() success\n");
+                    device_reset = ASC_TRUE;
+                    ret = SCSI_RESET_SUCCESS;
+                    break;
+                case ASC_ERROR:
+                default:
+                    ASC_DBG(1,
+"advansys_reset: AscResetDevice() failed; Calling AscResetSB()\n");
+                    sti();    /* Enable interrupts for AscResetSB(). */
+                    status = AscResetSB(asc_dvc_varp);
+                    cli();
+                    switch (status) {
+                    case ASC_TRUE:
+                        ASC_DBG(1, "advansys_reset: AscResetSB() TRUE\n");
+                        ret = SCSI_RESET_SUCCESS;
+                        break;
+                    case ASC_ERROR:
+                    default:
+                        ASC_DBG(1, "advansys_reset: AscResetSB() ERROR\n");
+                        ret = SCSI_RESET_ERROR;
+                        break;
+                    }
+                    break;
                 }
             }
-        }
-    } while (scan_tidmask);
-    return;
-}
+#endif /* version >= v1.3.89 */
+        } else {
+            /*
+             * Wide Board
+             *
+             * If the suggest reset bus flags are set, then reset the bus.
+             * Otherwise only reset the device.
+             */
+            adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+            if (reset_flags &
+                (SCSI_RESET_SUGGEST_BUS_RESET |
+                 SCSI_RESET_SUGGEST_HOST_RESET)) {
+#endif /* version >= v1.3.89 */
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-/*
- * asc_prt_board_devices()
- *
- * Print driver information for devices attached to the board.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
- */
-STATIC int
-asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen)
-{
-    asc_board_t        *boardp;
-    int                leftlen;
-    int                totlen;
-    int                len;
-    int                i;
+                /*
+                 * Reset the target's SCSI bus.
+                 */
+                ASC_DBG(1, "advansys_reset: before AdvResetSB()\n");
+                switch (AdvResetSB(adv_dvc_varp)) {
+                case ASC_TRUE:
+                    ASC_DBG(1, "advansys_reset: AdvResetSB() success\n");
+                    ret = SCSI_RESET_SUCCESS;
+                    break;
+                case ASC_FALSE:
+                default:
+                    ASC_DBG(1, "advansys_reset: AdvResetSB() failed\n");
+                    ret = SCSI_RESET_ERROR;
+                    break;
+                }
+                /*
+                 * Ensure all requests completed by the microcode have
+                 * been processed by calling AdvISR().
+                 */
+                (void) AdvISR(adv_dvc_varp);
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+            } else {
+                /*
+                 * Reset the specified device. If the device reset fails,
+                 * then reset the SCSI bus.
+                 */
 
-    boardp = ASC_BOARDP(shp);
-    leftlen = cplen;
-    totlen = len = 0;
+                ASC_DBG1(1,
+                    "advansys_reset: before AdvResetDevice(), target %d\n",
+                    scp->target);
+                
+                switch (AdvResetDevice(adv_dvc_varp, scp->target)) {
+                case ASC_TRUE:
+                    ASC_DBG(1, "advansys_reset: AdvResetDevice() success\n");
+                    device_reset = ASC_TRUE;
+                    ret = SCSI_RESET_SUCCESS;
+                    break;
+                case ASC_FALSE:
+                default:
+                    ASC_DBG(1,
+"advansys_reset: AdvResetDevice() failed; Calling AdvResetSB()\n");
+                    
+                    switch (AdvResetSB(adv_dvc_varp)) {
+                    case ASC_TRUE:
+                        ASC_DBG(1, "advansys_reset: AdvResetSB() TRUE\n");
+                        ret = SCSI_RESET_SUCCESS;
+                        break;
+                    case ASC_FALSE:
+                    default:
+                        ASC_DBG(1, "advansys_reset: AdvResetSB() ERROR\n");
+                        ret = SCSI_RESET_ERROR;
+                        break;
+                    }
+                    break;
+                }
+                /*
+                 * Ensure all requests completed by the microcode have
+                 * been processed by calling AdvISR().
+                 */
+                (void) AdvISR(adv_dvc_varp);
+            }
+#endif /* version >= v1.3.89 */
+        }
 
-    len = asc_prt_line(cp, leftlen,
-"\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no);
-    ASC_PRT_NEXT();
+        /*
+         * Because the ASC_HOST_IN_RESET flag causes both
+         * 'advansys_interrupt' and 'asc_isr_callback' to
+         * queue requests to the board's 'done' queue and
+         * prevents waiting commands from being executed,
+         * these queued requests must be handled here.
+         */
+        done_scp = asc_dequeue_list(&boardp->done, &last_scp,
+                                    ASC_TID_ALL);
 
-    len = asc_prt_line(cp, leftlen, "Target Ids Detected:");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if (boardp->asc_dvc_cfg.chip_scsi_id == i) {
-            continue;
-        } else if (boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
-            len = asc_prt_line(cp, leftlen, " %d,", i);
-            ASC_PRT_NEXT();
+        /*
+         * If a device reset was performed dequeue all waiting
+         * and active requests for the device and set the request
+         * status to DID_RESET.
+         *
+         * If a SCSI bus reset was performed dequeue all waiting
+         * and active requests for all devices and set the request
+         * status to DID_RESET.
+         */
+        if (device_reset == ASC_TRUE) {
+            target = scp->target;
+        } else {
+            target = ASC_TID_ALL;
         }
-    }
-    len = asc_prt_line(cp, leftlen, " (%d=Host Adapter)\n",
-                       boardp->asc_dvc_cfg.chip_scsi_id);
-    ASC_PRT_NEXT();
 
-     return totlen;
-}
+        /*
+         * Add active requests to 'done_scp' and set the request status
+         * to DID_RESET.
+         */
+        if (done_scp == NULL) {
+            done_scp = asc_dequeue_list(&boardp->active, &last_scp, target);
+            for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
+                tscp->result = HOST_BYTE(DID_RESET);
+            }
+        } else {
+            ASC_ASSERT(last_scp != NULL);
+            REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active,
+                &new_last_scp, target);
+            if (new_last_scp != NULL) {
+                ASC_ASSERT(REQPNEXT(last_scp) != NULL);
+                for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
+                    tscp->result = HOST_BYTE(DID_RESET);
+                }
+                last_scp = new_last_scp;
+            }
+        }
 
-/*
- * asc_prt_board_eeprom()
- *
- * Print board EEPROM configuration.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
- *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
- */
-STATIC int
-asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
-{
-    asc_board_t        *boardp;
-    ASC_DVC_VAR        *asc_dvc_varp;
-    int                leftlen;
-    int                totlen;
-    int                len;
-    ASCEEP_CONFIG      *ep;
-    int                i;
-    int                isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
+        /*
+         * Add waiting requests to 'done_scp' and set the request status
+         * to DID_RESET.
+         */
+        if (done_scp == NULL) {
+            done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, target);
+            for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
+                tscp->result = HOST_BYTE(DID_RESET);
+            }
+        } else {
+            ASC_ASSERT(last_scp != NULL);
+            REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting,
+                &new_last_scp, target);
+            if (new_last_scp != NULL) {
+                ASC_ASSERT(REQPNEXT(last_scp) != NULL);
+                for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
+                    tscp->result = HOST_BYTE(DID_RESET);
+                }
+                last_scp = new_last_scp;
+            }
+        }
 
-    boardp = ASC_BOARDP(shp);
-    asc_dvc_varp = &boardp->asc_dvc_var;
-    ep = &boardp->eep_config;
+        /* Save the time of the most recently completed reset. */
+        boardp->last_reset = jiffies;
 
-    leftlen = cplen;
-    totlen = len = 0;
+        /* Clear reset flag. */
+        boardp->flags &= ~ASC_HOST_IN_RESET;
 
-    len = asc_prt_line(cp, leftlen,
-"\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
-    ASC_PRT_NEXT();
+        /*
+         * Start any waiting commands for the board.
+         */
+        if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
+            ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
+            asc_execute_queue(&boardp->waiting);
+        }
+        ret = SCSI_RESET_SUCCESS;
+    }
 
-    len = asc_prt_line(cp, leftlen,
-" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
-        ep->chip_scsi_id, ep->max_total_qng, ep->max_tag_qng);
-    ASC_PRT_NEXT();
+    /* Interrupts could be enabled here. */
 
-    len = asc_prt_line(cp, leftlen,
-" Disconnects:         ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        len = asc_prt_line(cp, leftlen, " %d:%c",
-            i, (ep->disc_enable & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
-        ASC_PRT_NEXT();
+    ASC_ASSERT(do_scsi_done != ASC_ERROR);
+    ASC_ASSERT(scp_found != ASC_ERROR);
+    if (do_scsi_done == ASC_TRUE) {
+        if (scp->scsi_done == NULL) {
+            ASC_PRINT1(
+"advansys_reset: reset request scsi_done() is NULL, %x\n",
+                (unsigned) scp);
+        } else {
+            if (scp_found == ASC_FALSE) {
+                ASC_PRINT1(
+"advansys_reset: reset request not active or waiting, completing anyway %x\n",
+                    (unsigned) scp);
+            }
+            ASC_STATS(scp->host, done);
+            scp->scsi_done(scp);
+        }
     }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
 
-    len = asc_prt_line(cp, leftlen,
-" Command Queuing:     ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        len = asc_prt_line(cp, leftlen, " %d:%c",
-            i, (ep->use_cmd_qng & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
-        ASC_PRT_NEXT();
+    /*
+     * It is possible for the request done function to re-enable
+     * interrupts without confusing the driver. But here interrupts
+     * aren't enabled until requests have been completed.
+     */
+    if (done_scp != NULL) {
+        asc_scsi_done_list(done_scp);
     }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
 
-    len = asc_prt_line(cp, leftlen,
-" Start Motor:         ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        len = asc_prt_line(cp, leftlen, " %d:%c",
-            i, (ep->start_motor & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
-        ASC_PRT_NEXT();
-    }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
+    ASC_DBG1(1, "advansys_reset: ret %d", ret);
 
-    len = asc_prt_line(cp, leftlen,
-" Synchronous Transfer:");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        len = asc_prt_line(cp, leftlen, " %d:%c",
-            i, (ep->init_sdtr & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
-        ASC_PRT_NEXT();
-    }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
+    /* Re-enable interrupts, if they were enabled on entry. */
+    restore_flags(flags);
 
-    if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
-        len = asc_prt_line(cp, leftlen,
-" Host ISA DMA speed:   %d MB/S\n",
-            isa_dma_speed[ep->isa_dma_speed]);
-        ASC_PRT_NEXT();
-    }
+    ASC_ASSERT(ret != ASC_ERROR);
+    return ret;
+}
 
-     return totlen;
+/*
+ * advansys_biosparam()
+ *
+ * Translate disk drive geometry if the "BIOS greater than 1 GB"
+ * support is enabled for a drive.
+ *
+ * ip (information pointer) is an int array with the following definition:
+ * ip[0]: heads
+ * ip[1]: sectors
+ * ip[2]: cylinders
+ */
+int
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+advansys_biosparam(Disk *dp, int dep, int ip[])
+#else /* version >= v1.3.0 */
+advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
+#endif /* version >= v1.3.0 */
+{
+    asc_board_t     *boardp;
+
+    ASC_DBG(1, "advansys_biosparam: begin\n");
+    ASC_STATS(dp->device->host, biosparam);
+    boardp = ASC_BOARDP(dp->device->host);
+    if (ASC_NARROW_BOARD(boardp)) {
+        if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
+             ASC_CNTL_BIOS_GT_1GB) && dp->capacity > 0x200000) {
+                ip[0] = 255;
+                ip[1] = 63;
+        } else {
+                ip[0] = 64;
+                ip[1] = 32;
+        }
+    } else {
+        if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
+             BIOS_CTRL_EXTENDED_XLAT) && dp->capacity > 0x200000) {
+                ip[0] = 255;
+                ip[1] = 63;
+        } else {
+                ip[0] = 64;
+                ip[1] = 32;
+        }
+    }
+    ip[2] = dp->capacity / (ip[0] * ip[1]);
+    ASC_DBG(1, "advansys_biosparam: end\n");
+    return 0;
 }
 
 /*
- * asc_prt_driver_conf()
+ * advansys_setup()
  *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
+ * This function is called from init/main.c at boot time.
+ * It it passed LILO parameters that can be set from the
+ * LILO command line or in /etc/lilo.conf.
  *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
+ * It is used by the AdvanSys driver to either disable I/O
+ * port scanning or to limit scanning to 1 - 4 I/O ports.
+ * Regardless of the option setting EISA and PCI boards
+ * will still be searched for and detected. This option
+ * only affects searching for ISA and VL boards.
+ *
+ * If ADVANSYS_DEBUG is defined the driver debug level may
+ * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port.
+ *
+ * Examples:
+ * 1. Eliminate I/O port scanning:
+ *         boot: linux advansys=
+ *       or
+ *         boot: linux advansys=0x0
+ * 2. Limit I/O port scanning to one I/O port:
+ *        boot: linux advansys=0x110
+ * 3. Limit I/O port scanning to four I/O ports:
+ *        boot: linux advansys=0x110,0x210,0x230,0x330
+ * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and
+ *    set the driver debug level to 2.
+ *        boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2
+ *
+ * ints[0] - number of arguments
+ * ints[1] - first argument
+ * ints[2] - second argument
+ * ...
  */
-STATIC int
-asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
+ASC_INITFUNC(
+void
+advansys_setup(char *str, int *ints)
+)
 {
-    asc_board_t            *boardp;
-    int                    leftlen;
-    int                    totlen;
-    int                    len;
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-    int                    i;
-#endif /* version >= v1.3.89 */
+    int    i;
 
-    boardp = ASC_BOARDP(shp);
+    if (asc_iopflag == ASC_TRUE) {
+        printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
+        return;
+    }
 
-    leftlen = cplen;
-    totlen = len = 0;
+    asc_iopflag = ASC_TRUE;
 
-    len = asc_prt_line(cp, leftlen,
-"\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
-        shp->host_no);
-    ASC_PRT_NEXT();
+    if (ints[0] > ASC_NUM_IOPORT_PROBE) {
+#ifdef ADVANSYS_DEBUG
+        if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) &&
+            (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) {
+            asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf;
+        } else {
+#endif /* ADVANSYS_DEBUG */
+            printk("AdvanSys SCSI: only %d I/O ports accepted\n",
+                ASC_NUM_IOPORT_PROBE);
+#ifdef ADVANSYS_DEBUG
+        }
+#endif /* ADVANSYS_DEBUG */
+    }
 
-    len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
-" host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
-        shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
-#else /* version >= v1.3.89 */
-" host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
-        shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun,
-        shp->max_channel);
-#endif /* version >= v1.3.89 */
-    ASC_PRT_NEXT();
-    
-    len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
-" can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
-        shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
-#else /* version >= v1.3.57 */
-" unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
-        shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize,
-        shp->cmd_per_lun);
-#endif /* version >= v1.3.57 */
-    ASC_PRT_NEXT();
+#ifdef ADVANSYS_DEBUG
+    ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]);
+    for (i = 1; i < ints[0]; i++) {
+        ASC_DBG2(1, " ints[%d] %x", i, ints[i]);
+    }
+    ASC_DBG(1, "\n");
+#endif /* ADVANSYS_DEBUG */
 
-    len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
-" unchecked_isa_dma %d, loaded_as_module %d\n",
-        shp->unchecked_isa_dma, shp->loaded_as_module);
-#else /* version >= v1.3.57 */
-" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
-        shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
-#endif /* version >= v1.3.57 */
-    ASC_PRT_NEXT();
+    for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) {
+        asc_ioport[i-1] = ints[i];
+        ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n",
+            i - 1, asc_ioport[i-1]);
+    }
+}
 
-    len = asc_prt_line(cp, leftlen,
-" flags %x, last_reset %x, jiffies %x\n",
-        ASC_BOARDP(shp)->flags, ASC_BOARDP(shp)->last_reset, jiffies);
-    ASC_PRT_NEXT();
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-    len = asc_prt_line(cp, leftlen,
-" queue_depth:     ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
-            continue;
-        }
-        len = asc_prt_line(cp, leftlen, " %d:%d",
-            i, boardp->device[i]->queue_depth);
-        ASC_PRT_NEXT();
-    }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
-#endif /* version >= v1.3.89 */
+/*
+ * --- Loadable Driver Support
+ */
 
-#if ASC_QUEUE_FLOW_CONTROL
-    len = asc_prt_line(cp, leftlen,
-" queue_curr_depth:");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
-            continue;
-        }
-        len = asc_prt_line(cp, leftlen, " %d:%d",
-            i, boardp->device[i]->queue_curr_depth);
-        ASC_PRT_NEXT();
-    }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
+#ifdef MODULE
+Scsi_Host_Template driver_template = ADVANSYS;
+# include "scsi_module.c"
+#endif /* MODULE */
 
-    len = asc_prt_line(cp, leftlen,
-" queue_count:     ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
-            continue;
-        }
-        len = asc_prt_line(cp, leftlen, " %d:%d",
-            i, boardp->device[i]->queue_count);
-        ASC_PRT_NEXT();
-    }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
-#endif /* ASC_QUEUE_FLOW_CONTROL */
 
-     return totlen;
-}
+/*
+ * --- Miscellaneous Driver Functions
+ */
 
 /*
- * asc_prt_board_info()
- *
- * Print dynamic board configuration information.
- *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
+ * First-level interrupt handler.
  *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
+ * For versions > v1.3.70, 'dev_id' is a pointer to the interrupting
+ * adapter's asc_board_t. Because all boards are currently checked
+ * for interrupts on each interrupt, 'dev_id' is not referenced. 'dev_id'
+ * could be used to identify an interrupt passed to the AdvanSys driver,
+ * which is for a device sharing an interrupt with an AdvanSys adapter.
  */
-STATIC int
-asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
+STATIC void
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
+advansys_interrupt(int irq, struct pt_regs *regs)
+#else /* version >= v1.3.70 */
+advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+#endif /* version >= v1.3.70 */
 {
-    asc_board_t            *boardp;
-    int                    leftlen;
-    int                    totlen;
-    int                    len;
-    ASC_DVC_VAR            *v;
-    ASC_DVC_CFG            *c;
-    int                    i;
-
-    boardp = ASC_BOARDP(shp);
-    v = &boardp->asc_dvc_var;
-    c = &boardp->asc_dvc_cfg;
+    int             flags;
+    int             i;
+    asc_board_t     *boardp;
+    Scsi_Cmnd       *done_scp = NULL, *last_scp = NULL;
+    Scsi_Cmnd       *new_last_scp;
 
-    leftlen = cplen;
-    totlen = len = 0;
+    /* Disable interrupts, if they aren't already disabled. */
+    save_flags(flags);
+    cli();
 
-    len = asc_prt_line(cp, leftlen,
-"\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
-    shp->host_no);
-    ASC_PRT_NEXT();
+    ASC_DBG(1, "advansys_interrupt: begin\n");
 
-    len = asc_prt_line(cp, leftlen,
-" chip_version %u, lib_version %u, lib_serial_no %u, mcode_date %u\n",
-        c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date);
-    ASC_PRT_NEXT();
+    /*
+     * Check for interrupts on all boards.
+     * AscISR() will call asc_isr_callback().
+     */
+    for (i = 0; i < asc_board_count; i++) {
+        boardp = ASC_BOARDP(asc_host[i]);
+        ASC_DBG2(2, "advansys_interrupt: i %d, boardp %lx\n",
+            i, (ulong) boardp)            
+        if (ASC_NARROW_BOARD(boardp)) {
+            /*
+             * Narrow Board
+             */
+            if (AscIsIntPending(asc_host[i]->io_port)) {
+                ASC_STATS(asc_host[i], interrupt);
+                ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
+                AscISR(&boardp->dvc_var.asc_dvc_var);
+            }
+        } else {
+            /*
+             * Wide Board
+             */
+            ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
+            if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
+                ASC_STATS(asc_host[i], interrupt);
+            }
+        }
 
-    len = asc_prt_line(cp, leftlen,
-" mcode_version %u, err_code %u\n",
-         c->mcode_version, v->err_code);
-    ASC_PRT_NEXT();
+        /*
+         * Start waiting requests and create a list of completed requests.
+         * 
+         * If a reset or abort request is being performed for the board,
+         * the reset or abort handler will complete pending requests after
+         * it has completed.
+         */
+        if ((boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) == 0) {
+            ASC_DBG2(1, "advansys_interrupt: done_scp %lx, last_scp %lx\n",
+                (ulong) done_scp, (ulong) last_scp);
 
-    /* Current number of commands waiting for the host. */
-    len = asc_prt_line(cp, leftlen,
-" Total Command Pending:    %d\n", v->cur_total_qng);
-    ASC_PRT_NEXT();
+            /* Start any waiting commands for the board. */
+            if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
+                ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
+                asc_execute_queue(&boardp->waiting);
+            }
 
-    len = asc_prt_line(cp, leftlen,
-" Command Queuing:         ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
-            continue;
+             /*
+              * Add to the list of requests that must be completed.
+              *
+              * 'done_scp' will always be NULL on the first iteration
+              * of this loop. 'last_scp' is set at the same time as
+              * 'done_scp'.
+              */
+            if (done_scp == NULL) {
+                done_scp = asc_dequeue_list(&boardp->done, &last_scp,
+                    ASC_TID_ALL);
+            } else {
+                ASC_ASSERT(last_scp != NULL);
+                REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done,
+                    &new_last_scp, ASC_TID_ALL);
+                if (new_last_scp != NULL) {
+                    ASC_ASSERT(REQPNEXT(last_scp) != NULL);
+                    last_scp = new_last_scp;
+                }
+            }
         }
-        len = asc_prt_line(cp, leftlen, " %d:%c",
-            i, (v->use_tagged_qng & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
-        ASC_PRT_NEXT();
     }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
 
-    /* Current number of commands waiting for a device. */
-    len = asc_prt_line(cp, leftlen,
-" Command Queue Pending:   ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
-            continue;
-        }
-        len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]);
-        ASC_PRT_NEXT();
-    }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
+    /* Interrupts could be enabled here. */
 
-    /* Current limit on number of commands that can be sent to a device. */
-    len = asc_prt_line(cp, leftlen,
-" Command Queue Limit:     ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
-            continue;
-        }
-        len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]);
-        ASC_PRT_NEXT();
-    }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
+    /*
+     * It is possible for the request done function to re-enable
+     * interrupts without confusing the driver. But here interrupts
+     * aren't enabled until all requests have been completed.
+     */
+    asc_scsi_done_list(done_scp);
 
-    /* Indicate whether the device has returned queue full status. */
-    len = asc_prt_line(cp, leftlen,
-" Command Queue Full:      ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
+    /* Re-enable interrupts, if they were enabled on entry. */
+    restore_flags(flags);
+
+    ASC_DBG(1, "advansys_interrupt: end\n");
+    return;
+}
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+/*
+ * Set the number of commands to queue per device for the
+ * specified host adapter.
+ */
+STATIC void
+advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist)
+{
+    Scsi_Device        *device;
+    asc_board_t        *boardp;
+
+    boardp = ASC_BOARDP(shp);
+    boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
+    for (device = devicelist; device != NULL; device = device->next) {
+        if (device->host != shp) {
             continue;
         }
-        if (boardp->queue_full & ASC_TIX_TO_TARGET_ID(i)) {
-            len = asc_prt_line(cp, leftlen, " %d:Y-%d",
-                i, boardp->queue_full_cnt[i]);
+        /*
+         * Save a pointer to the device and set its initial/maximum
+         * queue depth.
+         */
+        boardp->device[device->id] = device;
+        if (ASC_NARROW_BOARD(boardp)) {
+            device->queue_depth =
+                boardp->dvc_var.asc_dvc_var.max_dvc_qng[device->id];
         } else {
-            len = asc_prt_line(cp, leftlen, " %d:N", i);
+            device->queue_depth =
+                boardp->dvc_var.adv_dvc_var.max_dvc_qng;
         }
-        ASC_PRT_NEXT();
+        ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n",
+            (unsigned) shp, device->id, device->queue_depth);
     }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
-
-    len = asc_prt_line(cp, leftlen,
-" Synchronous Transfer:    ");
-    ASC_PRT_NEXT();
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
-            continue;
-        }
-        len = asc_prt_line(cp, leftlen, " %d:%c",
-            i, (v->sdtr_done & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
-        ASC_PRT_NEXT();
-    }
-    len = asc_prt_line(cp, leftlen, "\n");
-    ASC_PRT_NEXT();
-
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        uchar syn_period_ix;
-
-        if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-            ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
-            continue;
-        }
-        if ((v->sdtr_done & ASC_TIX_TO_TARGET_ID(i)) == 0) {
-            continue;
-        }
-        syn_period_ix = (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1);
-        len = asc_prt_line(cp, leftlen, "   %d:", i);
-        ASC_PRT_NEXT();
-
-        len = asc_prt_line(cp, leftlen,
-            " Transfer Period Factor: %d (%d.%d Mhz),",
-            v->sdtr_period_tbl[syn_period_ix],
-            250 / v->sdtr_period_tbl[syn_period_ix],
-            ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix]));
-        ASC_PRT_NEXT();
-
-        len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
-            boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
-        ASC_PRT_NEXT();
-    }
-
-     return totlen;
 }
+#endif /* version >= v1.3.89 */
 
 /*
- * asc_proc_copy() 
- *
- * Copy proc information to a read buffer taking into account the current
- * read offset in the file and the remaining space in the read buffer.
+ * Function used only with polled I/O requests that are initiated by
+ * advansys_command().
  */
-STATIC int
-asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
-              char *cp, int cplen)
+STATIC void
+advansys_command_done(Scsi_Cmnd *scp)
 {
-    int cnt = 0;
-    
-    ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
-            (unsigned) offset, (unsigned) advoffset, cplen);
-    if (offset <= advoffset) {
-        /* Read offset below current offset, copy everything. */
-        cnt = ASC_MIN(cplen, leftlen);
-        ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
-                (unsigned) curbuf, (unsigned) cp, cnt);
-        memcpy(curbuf, cp, cnt);
-    } else if (offset < advoffset + cplen) {
-        /* Read offset within current range, partial copy. */
-        cnt = (advoffset + cplen) - offset;
-        cp = (cp + cplen) - cnt;
-        cnt = ASC_MIN(cnt, leftlen);
-        ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
-                (unsigned) curbuf, (unsigned) cp, cnt);
-        memcpy(curbuf, cp, cnt);
-    }
-    return cnt;
+    ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp);
+    scp->SCp.Status = 1;
 }
 
 /*
- * asc_prt_line()
- *
- * If 'cp' is NULL print to the console, otherwise print to a buffer.
- *
- * Return 0 if printing to the console, otherwise return the number of
- * bytes written to the buffer.
+ * Complete all requests on the singly linked list pointed
+ * to by 'scp'.
  *
- * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
- * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
- */
-STATIC int
-asc_prt_line(char *buf, int buflen, char *fmt, ...)
-{
-    va_list        args;
-    int            ret;
-    char        s[ASC_PRTLINE_SIZE];
-
-    va_start(args, fmt);
-    ret = vsprintf(s, fmt, args);
-    ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
-    if (buf == NULL) {
-        (void) printk(s);
-        ret = 0;
-    } else {
-        ret = ASC_MIN(buflen, ret);
-        memcpy(buf, s, ret);
-    }
-    va_end(args);
-    return ret;
-}
-#endif /* version >= v1.3.0 */
-
-
-/*
- * --- Functions Required by the Asc Library
- */
-
-/*
- * Delay for 'n' milliseconds. Don't use the 'jiffies'
- * global variable which is incremented once every 5 ms
- * from a timer interrupt, because this function may be
- * called when interrupts are disabled.
+ * Interrupts can be enabled on entry.
  */
 STATIC void
-DvcSleepMilliSecond(ulong n)
+asc_scsi_done_list(Scsi_Cmnd *scp)
 {
-    ulong i;
+    Scsi_Cmnd    *tscp;
 
-    ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
-    for (i = 0; i < n; i++) {
-        udelay(1000);
+    ASC_DBG(2, "asc_scsi_done_list: begin\n");
+    while (scp != NULL) {
+        ASC_DBG1(3, "asc_scsi_done_list: scp %x\n", (unsigned) scp);
+        tscp = REQPNEXT(scp);
+        REQPNEXT(scp) = NULL;
+        ASC_STATS(scp->host, done);
+        ASC_ASSERT(scp->scsi_done != NULL);
+        scp->scsi_done(scp);
+        scp = tscp;
     }
-}
-
-STATIC int
-DvcEnterCritical(void)
-{
-    int    flags;
-
-    save_flags(flags);
-    cli();
-    return flags;
-}
-
-STATIC void
-DvcLeaveCritical(int flags)
-{
-    restore_flags(flags);
-}
-
-STATIC ulong
-DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
-             ASC_SG_HEAD *asc_sg_head_ptr)
-{
-    ulong buf_size;
-
-    buf_size = buf_len;
-    asc_sg_head_ptr->entry_cnt = 1;
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
-    asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
-#else /* version >= v2.0.0 */
-    asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
-#endif /* version >= v2.0.0 */
-    asc_sg_head_ptr->sg_list[0].bytes = buf_size;
-    return buf_size;
+    ASC_DBG(2, "asc_scsi_done_list: done\n");
+    return;
 }
 
 /*
- * void
- * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
+ * Execute a single 'Scsi_Cmnd'.
  *
- * Calling/Exit State:
- *    none
+ * The function 'done' is called when the request has been completed.
  *
- * Description:
- *     Output an ASC_SCSI_Q structure to the chip
- */
-STATIC void
-DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
-{
-    int    i;
-
-    ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
-    AscSetChipLramAddr(iop_base, s_addr);
-    for (i = 0; i < words; i++, outbuf++) {
-        if (i == 2 || i == 10) {
-            continue;
-        }
-        AscSetChipLramDataNoSwap(iop_base, *outbuf);
-    }
-}
-
-/*
- * void
- * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
+ * Scsi_Cmnd:
  *
- * Calling/Exit State:
- *    none
+ *  host - board controlling device
+ *  device - device to send command
+ *  target - target of device
+ *  lun - lun of device
+ *  cmd_len - length of SCSI CDB
+ *  cmnd - buffer for SCSI 8, 10, or 12 byte CDB
+ *  use_sg - if non-zero indicates scatter-gather request with use_sg elements
  *
- * Description:
- *     Input an ASC_QDONE_INFO structure from the chip
- */
-STATIC void
-DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
-{
-    int    i;
-
-    AscSetChipLramAddr(iop_base, s_addr);
-    for (i = 0; i < words; i++, inbuf++) {
-        if (i == 5) {
-            continue;
-        }
-        *inbuf = AscGetChipLramDataNoSwap(iop_base);
-    }
-    ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
-}
-
-/*
- * void    DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
+ *  if (use_sg == 0) {
+ *    request_buffer - buffer address for request
+ *    request_bufflen - length of request buffer
+ *  } else {
+ *    request_buffer - pointer to scatterlist structure
+ *  }
  *
- * Calling/Exit State:
- *    none
+ *  sense_buffer - sense command buffer
  *
- * Description:
- *     output a buffer to an i/o port address
- */
-STATIC void
-DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
-{
-    int    i;
-
-    for (i = 0; i < words; i++, outbuf++)
-        outpw(iop_base, *outbuf);
-}
-
-/*
- * void    DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
+ *  result (4 bytes of an int):
+ *    Byte Meaning
+ *    0 SCSI Status Byte Code
+ *    1 SCSI One Byte Message Code
+ *    2 Host Error Code
+ *    3 Mid-Level Error Code
  *
- * Calling/Exit State:
- *    none
+ *  host driver fields:
+ *    SCp - Scsi_Pointer used for command processing status
+ *    scsi_done - used to save caller's done function
+ *    host_scribble - used for pointer to another Scsi_Cmnd
  *
- * Description:
- *     input a buffer from an i/o port address
+ * If this function returns ASC_NOERROR or ASC_ERROR the request
+ * has been enqueued on the board's 'done' queue and must be
+ * completed by the caller.
+ *
+ * If ASC_BUSY is returned the request must be enqueued by the
+ * caller and re-tried later.
  */
-STATIC void
-DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
+STATIC int
+asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
 {
-    int    i;
-
-    for (i = 0; i < words; i++, inbuf++)
-        *inbuf = inpw(iop_base);
-}
+    asc_board_t        *boardp;
+    ASC_DVC_VAR        *asc_dvc_varp;
+    ADV_DVC_VAR        *adv_dvc_varp;
+    ADV_SCSI_REQ_Q     *adv_scsiqp;
+    Scsi_Device        *device;
+    int                ret;
 
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
+        (unsigned) scp, (unsigned) scp->scsi_done);
 
-/*
- * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
- *
- * Calling/Exit State:
- *    none
- *
- * Description:
- *     output a buffer of 32-bit integers to an i/o port address in
- *  16 bit integer units
- */
-STATIC void  
-DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
-{
-    int        i;
-    int        words;
-    ushort    *pw;
+    boardp = ASC_BOARDP(scp->host);
+    device = boardp->device[scp->target];
 
-    pw = (ushort *) pdw;
-    words = dwords << 1;
-    for(i = 0; i < words; i++, pw++) {
-        outpw(port, *pw);
-    }
-    return;
-}
+    if (ASC_NARROW_BOARD(boardp)) {
+        /*
+         * Build and execute Narrow Board request.
+         */
 
-/*
- * Read a PCI configuration byte.
- */
-ASC_INITFUNC(
-STATIC uchar
-DvcReadPCIConfigByte(
-        ASC_DVC_VAR asc_ptr_type *asc_dvc, 
-        ushort offset)
-)
-{
-    PCI_DATA    pciData;
+        asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
 
-    pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
-    pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
-    pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
-    pciData.offset = offset;
-    pciData.type = pci_scan_method;
-    return asc_get_cfg_byte(&pciData);
-}
+        /*
+         * Narrow Board - Asc Library requires special device initialization.
+         *
+         * If this is the first command, then initialize the device. If
+         * no device is found set 'DID_BAD_TARGET' and return.
+         */
+        if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0) {
+            if (asc_init_dev(asc_dvc_varp, scp) == ASC_FALSE) {
+                scp->result = HOST_BYTE(DID_BAD_TARGET);
+                asc_enqueue(&boardp->done, scp, ASC_BACK);
+                return ASC_ERROR;
+            }
+            boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
+        }
 
-/*
- * Write a PCI configuration byte.
- */
-ASC_INITFUNC(
-STATIC void
-DvcWritePCIConfigByte(
-        ASC_DVC_VAR asc_ptr_type *asc_dvc, 
-        ushort offset, 
-        uchar  byte_data)
-)
-{
-    PCI_DATA    pciData;
+        /*
+         * Build Asc Library request structure using the
+         * global structures 'asc_scsi_req' and 'asc_sg_head'.
+         *
+         * asc_build_req() can not return ASC_BUSY.
+         */
+        if (asc_build_req(boardp, scp) == ASC_ERROR) {
+            ASC_STATS(scp->host, build_error);
+            return ASC_ERROR;
+        }
 
-    pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
-    pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
-    pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
-    pciData.offset = offset;
-    pciData.type = pci_scan_method;
-    asc_put_cfg_byte(&pciData, byte_data);
-}
+        /*
+         * Execute the command. If there is no error, add the command
+         * to the active queue.
+         */
+        switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
+        case ASC_NOERROR:
+            ASC_STATS(scp->host, exe_noerror);
+            /*
+             * Increment monotonically increasing per device successful
+             * request counter. Wrapping doesn't matter.
+             */
+            boardp->reqcnt[scp->target]++;
 
-/*
- * Return the BIOS address of the adapter at the specified
- * I/O port and with the specified bus type.
- */
-ASC_INITFUNC(
-STATIC ushort
-AscGetChipBiosAddress(
-        PortAddr iop_base,
-        ushort bus_type
-)
-)
-{
-    ushort  cfg_lsw ;
-    ushort  bios_addr ;
+#if ASC_QUEUE_FLOW_CONTROL
+            /*
+             * Conditionally increment the device queue depth.
+             *
+             * If no error occurred and there have been 100 consecutive
+             * successful requests and the current queue depth is less
+             * than the maximum queue depth, then increment the current
+             * queue depth.
+             */
+            if (boardp->nerrcnt[scp->target]++ > 100) {
+                boardp->nerrcnt[scp->target] = 0;
+                if (device != NULL &&
+                    (device->queue_curr_depth < device->queue_depth) &&
+                    (!(boardp->queue_full &
+                       ADV_TID_TO_TIDMASK(scp->target)) ||
+                     (boardp->queue_full_cnt[scp->target] >
+                      device->queue_curr_depth))) {
+                    device->queue_curr_depth++;
+                }
+            }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+            asc_enqueue(&boardp->active, scp, ASC_BACK);
+            ASC_DBG(1,
+                "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
+            break;
+        case ASC_BUSY:
+            /* Caller must enqueue request and retry later. */
+            ASC_STATS(scp->host, exe_busy);
+#if ASC_QUEUE_FLOW_CONTROL
+            /*
+             * Clear consecutive no error counter and if possible decrement
+             * queue depth.
+             */
+            boardp->nerrcnt[scp->target] = 0;
+            if (device != NULL && device->queue_curr_depth > 1) {
+                device->queue_curr_depth--;
+            }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+            break;
+        case ASC_ERROR:
+            ASC_PRINT2(
+"asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n",
+                boardp->id, asc_dvc_varp->err_code);
+            ASC_STATS(scp->host, exe_error);
+#if ASC_QUEUE_FLOW_CONTROL
+            /* Clear consecutive no error counter. */
+            boardp->nerrcnt[scp->target] = 0;
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+            scp->result = HOST_BYTE(DID_ERROR);
+            asc_enqueue(&boardp->done, scp, ASC_BACK);
+            break;
+        default:
+            ASC_PRINT2(
+"asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n",
+                boardp->id, asc_dvc_varp->err_code);
+            ASC_STATS(scp->host, exe_unknown);
+#if ASC_QUEUE_FLOW_CONTROL
+            /* Clear consecutive no error counter. */
+            boardp->nerrcnt[scp->target] = 0;
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+            scp->result = HOST_BYTE(DID_ERROR);
+            asc_enqueue(&boardp->done, scp, ASC_BACK);
+            break;
+        }
+    } else {
+        /*
+         * Build and execute Wide Board request.
+         */
+        adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
 
-    /*
-     * The PCI BIOS is re-located by the motherboard BIOS. Because
-     * of this the driver can not determine where a PCI BIOS is
-     * loaded and executes.
-     */
-    if (bus_type & ASC_IS_PCI)
-    {
-        return(0);
+        /*
+         * Build and get a pointer to an Adv Library request structure.
+         *
+         * If the request is successfully built then send  it below,
+         * otherwise return with an error.
+         */
+        switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
+        case ASC_NOERROR:
+            ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n");
+            break;
+        case ASC_BUSY:
+            ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n");
+            return ASC_BUSY;
+        case ASC_ERROR:
+        default:
+            ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n");
+            ASC_STATS(scp->host, build_error);
+            return ASC_ERROR;
+        }
+    
+        /*
+         * Execute the command. If there is no error, add the command
+         * to the active queue.
+         */
+        switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
+        case ASC_NOERROR:
+            ASC_STATS(scp->host, exe_noerror);
+            /*
+             * Increment monotonically increasing per device successful
+             * request counter. Wrapping doesn't matter.
+             */
+            boardp->reqcnt[scp->target]++;
+            asc_enqueue(&boardp->active, scp, ASC_BACK);
+            ASC_DBG(1,
+                "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n");
+            break;
+        case ASC_BUSY:
+            /* Caller must enqueue request and retry later. */
+            ASC_STATS(scp->host, exe_busy);
+            break;
+        case ASC_ERROR:
+            ASC_PRINT2(
+"asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code %x\n",
+                boardp->id, adv_dvc_varp->err_code);
+            ASC_STATS(scp->host, exe_error);
+            scp->result = HOST_BYTE(DID_ERROR);
+            asc_enqueue(&boardp->done, scp, ASC_BACK);
+            break;
+        default:
+            ASC_PRINT2(
+"asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code %x\n",
+                boardp->id, adv_dvc_varp->err_code);
+            ASC_STATS(scp->host, exe_unknown);
+            scp->result = HOST_BYTE(DID_ERROR);
+            asc_enqueue(&boardp->done, scp, ASC_BACK);
+            break;
+        }
     }
 
-    if((bus_type & ASC_IS_EISA) != 0)
-    {
-        cfg_lsw = AscGetEisaChipCfg(iop_base) ;
-        cfg_lsw &= 0x000F ;
-        bios_addr = (ushort)(ASC_BIOS_MIN_ADDR  +
-                                (cfg_lsw * ASC_BIOS_BANK_SIZE)) ;
-        return(bios_addr) ;
-    }/* if */
-
-    cfg_lsw = AscGetChipCfgLsw(iop_base) ;
-
-    /*
-    *  ISA PnP uses the top bit as the 32K BIOS flag
-    */
-    if (bus_type == ASC_IS_ISAPNP)
-    {
-        cfg_lsw &= 0x7FFF;
-    }/* if */
-
-    bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
-            ASC_BIOS_MIN_ADDR) ;
-    return(bios_addr) ;
+    ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    return ret;
 }
 
-
-/*
- * --- Tracing and Debugging Functions
- */
-
-#ifdef ADVANSYS_STATS
 /*
- * asc_prt_board_stats()
+ * Build a request structure for the Asc Library (Narrow Board).
  *
- * Note: no single line should be greater than ASC_PRTLINE_SIZE,
- * cf. asc_prt_line().
+ * The global structures 'asc_scsi_q' and 'asc_sg_head' are
+ * used to build the request.
  *
- * Return the number of characters copied into 'cp'. No more than
- * 'cplen' characters will be copied to 'cp'.
+ * If an error occurs, then return ASC_ERROR.
  */
 STATIC int
-asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
+asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp)
 {
-    int                    leftlen;
-    int                    totlen;
-    int                    len;
-    struct asc_stats    *s;
-    int                    i;
-    asc_queue_t            *active;
-    asc_queue_t            *waiting;
-
-    leftlen = cplen;
-    totlen = len = 0;
-
-    s = &ASC_BOARDP(shp)->asc_stats;
-    len = asc_prt_line(cp, leftlen,
-"\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no);
-    ASC_PRT_NEXT();
-    
-    len = asc_prt_line(cp, leftlen,
-" command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu\n",
-        s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
-    ASC_PRT_NEXT();
-
-    len = asc_prt_line(cp, leftlen,
-" check_interrupt %lu, interrupt %lu, callback %lu, done %lu\n",
-        s->check_interrupt, s->interrupt, s->callback, s->done);
-    ASC_PRT_NEXT();
-
-    len = asc_prt_line(cp, leftlen,
-" asc_noerror %lu, asc_busy %lu, asc_error %lu, asc_unknown %lu\n",
-        s->asc_noerror, s->asc_busy, s->asc_error, s->asc_unknown);
-    ASC_PRT_NEXT();
-
     /*
-     * Display data transfer statistics.
+     * Mutually exclusive access is required to 'asc_scsi_q' and
+     * 'asc_sg_head' until after the request is started.
      */
-    if (s->cont_cnt > 0) {
-        len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
-        ASC_PRT_NEXT();
+    memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
 
-        len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
-                    s->cont_xfer/2,
-                    ASC_TENTHS(s->cont_xfer, 2));
-        ASC_PRT_NEXT();
+    /*
+     * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
+     */
+    asc_scsi_q.q2.srb_ptr = (ulong) scp;
 
-        /* Contiguous transfer average size */
-        len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
-                    (s->cont_xfer/2)/s->cont_cnt,
-                    ASC_TENTHS((s->cont_xfer/2), s->cont_cnt));
-        ASC_PRT_NEXT();
+    /*
+     * Build the ASC_SCSI_Q request.
+     */
+    ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
+    if (scp->cmd_len > ASC_MAX_CDB_LEN) {
+        scp->cmd_len = ASC_MAX_CDB_LEN;
     }
+    asc_scsi_q.cdbptr = &scp->cmnd[0];
+    asc_scsi_q.q2.cdb_len = scp->cmd_len;
+    asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
+    asc_scsi_q.q1.target_lun = scp->lun;
+    asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+    asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
+#else /* version >= v2.0.0 */
+    asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
+#endif /* version >= v2.0.0 */
+    asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
 
-    if (s->sg_cnt > 0) {
-
-        len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
-                    s->sg_cnt, s->sg_elem);
-        ASC_PRT_NEXT();
-
-        len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
-                    s->sg_xfer/2,
-                    ASC_TENTHS(s->sg_xfer, 2));
-        ASC_PRT_NEXT();
-
-        /* Scatter gather transfer statistics */
-        len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
-                    s->sg_elem/s->sg_cnt,
-                    ASC_TENTHS(s->sg_elem, s->sg_cnt));
-        ASC_PRT_NEXT();
-
-        len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
-                    (s->sg_xfer/2)/s->sg_elem,
-                    ASC_TENTHS((s->sg_xfer/2), s->sg_elem));
-        ASC_PRT_NEXT();
-
-        len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
-                    (s->sg_xfer/2)/s->sg_cnt,
-                    ASC_TENTHS((s->sg_xfer/2), s->sg_cnt));
-        ASC_PRT_NEXT();
+    /*
+     * If there are any outstanding requests for the current target,
+     * then every 255th request send an ORDERED request. This heuristic
+     * tries to retain the benefit of request sorting while preventing
+     * request starvation. 255 is the max number of tags or pending commands
+     * a device may have outstanding.
+     *
+     * The request count is incremented below for every successfully
+     * started request.
+     * 
+     */
+    if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->target] > 0) &&
+        (boardp->reqcnt[scp->target] % 255) == 0) {
+        asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
+    } else {
+        asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
     }
 
     /*
-     * Display request queuing statistics.
+     * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
+     * buffer command.
      */
-    len = asc_prt_line(cp, leftlen,
-" Active and Waiting Request Queues (time unit: %d HZ):\n", HZ);
-    ASC_PRT_NEXT();
+    if (scp->use_sg == 0) {
+        /*
+         * CDB request of single contiguous buffer.
+         */
+        ASC_STATS(scp->host, cont_cnt);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+        asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
+#else /* version >= v2.0.0 */
+        asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
+#endif /* version >= v2.0.0 */
+        asc_scsi_q.q1.data_cnt = scp->request_bufflen;
+        ASC_STATS_ADD(scp->host, cont_xfer,
+                      ASC_CEILING(scp->request_bufflen, 512));
+        asc_scsi_q.q1.sg_queue_cnt = 0;
+        asc_scsi_q.sg_head = NULL;
+    } else {
+        /*
+         * CDB scatter-gather request list.
+         */
+        int                     sgcnt;
+        struct scatterlist      *slp;
 
-    active = &ASC_BOARDP(shp)->active;
-    waiting = &ASC_BOARDP(shp)->waiting;
-    for (i = 0; i < ASC_MAX_TID + 1; i++) {
-        if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) {
-            len = asc_prt_line(cp, leftlen, " target %d\n", i);
-            ASC_PRT_NEXT();
+        if (scp->use_sg > scp->host->sg_tablesize) {
+            ASC_PRINT3(
+"asc_build_req: board %d: use_sg %d > sg_tablesize %d\n",
+                boardp->id, scp->use_sg, scp->host->sg_tablesize);
+            scp->result = HOST_BYTE(DID_ERROR);
+            asc_enqueue(&boardp->done, scp, ASC_BACK);
+            return ASC_ERROR;
+        }
 
-            len = asc_prt_line(cp, leftlen,
-"   active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
-                active->q_cur_cnt[i], active->q_max_cnt[i],
-                active->q_tot_cnt[i],
-                active->q_min_tim[i], active->q_max_tim[i],
-                (active->q_tot_cnt[i] == 0) ? 0 :
-                (active->q_tot_tim[i]/active->q_tot_cnt[i]),
-                (active->q_tot_cnt[i] == 0) ? 0 :
-                ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i]));
-            ASC_PRT_NEXT();
+        ASC_STATS(scp->host, sg_cnt);
 
-            len = asc_prt_line(cp, leftlen,
-"   waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
-                waiting->q_cur_cnt[i], waiting->q_max_cnt[i],
-                waiting->q_tot_cnt[i],
-                waiting->q_min_tim[i], waiting->q_max_tim[i],
-                (waiting->q_tot_cnt[i] == 0) ? 0 :
-                (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]),
-                (waiting->q_tot_cnt[i] == 0) ? 0 :
-                ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i]));
-            ASC_PRT_NEXT();
+        /*
+         * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
+         * structure to point to it.
+         */
+        memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
+
+        asc_scsi_q.q1.cntl |= QC_SG_HEAD;
+        asc_scsi_q.sg_head = &asc_sg_head;
+        asc_scsi_q.q1.data_cnt = 0;
+        asc_scsi_q.q1.data_addr = 0;
+        asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg;
+        ASC_STATS_ADD(scp->host, sg_elem, asc_sg_head.entry_cnt);
+
+        /*
+         * Convert scatter-gather list into ASC_SG_HEAD list.
+         */
+        slp = (struct scatterlist *) scp->request_buffer;
+        for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+            asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
+#else /* version >= v2.0.0 */
+            asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
+#endif /* version >= v2.0.0 */
+            asc_sg_head.sg_list[sgcnt].bytes = slp->length;
+            ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
         }
     }
 
-     return totlen;
+    ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
+    ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
+
+    return ASC_NOERROR;
 }
-#endif /* ADVANSYS_STATS */
 
-#ifdef ADVANSYS_DEBUG
 /*
- * asc_prt_scsi_host()
+ * Build a request structure for the Adv Library (Wide Board).
+ *
+ * If an adv_req_t can not be allocated to issue the request,
+ * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
  */
-STATIC void 
-asc_prt_scsi_host(struct Scsi_Host *s)
+STATIC int
+adv_build_req(asc_board_t *boardp, Scsi_Cmnd *scp,
+    ADV_SCSI_REQ_Q **adv_scsiqpp)
 {
-    printk("Scsi_Host at addr %x\n", (unsigned) s);
-    printk(
-" next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
-        (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
-        (unsigned) s->last_reset);
+    adv_req_t           *reqp;
+    ADV_SCSI_REQ_Q      *scsiqp;
+    int                 i;
 
-#ifdef ERIC_neverdef /* { */
-       /*
-        * This information is private to the mid-layer scsi and the
-        * the low-level drivers shouldn't even be aware that it is there.
-        */
-    printk(
-" host_wait %x, host_queue %x, hostt %x, block %x,\n",
-        (unsigned) s->host_wait, (unsigned) s->host_queue,
-        (unsigned) s->hostt, (unsigned) s->block);
-#endif /* ERIC_neverdef */ /* } */
+    /*
+     * Allocate an adv_req_t structure from the board to execute
+     * the command.
+     */
+    if (boardp->adv_reqp == NULL) {
+        ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
+        ASC_STATS(scp->host, adv_build_noreq);
+        return ASC_BUSY;
+    } else {
+        reqp = boardp->adv_reqp;
+        boardp->adv_reqp = reqp->next_reqp;
+        reqp->next_reqp = NULL;
+    }
 
-    printk(
-" wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n",
-        s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port,
-        s->irq, s->dma_channel);
+    /*
+     * Get 4-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
+     */
+    scsiqp = (ADV_SCSI_REQ_Q *) ADV_DWALIGN(&reqp->scsi_req_q);
+    memset(scsiqp, 0, sizeof(ADV_SCSI_REQ_Q));
 
-    printk(
-" this_id %d, can_queue %d,\n", s->this_id, s->can_queue);
+    /*
+     * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
+     */
+    scsiqp->srb_ptr = (ulong) reqp;
 
-    printk(
-" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
-        s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
-        s->loaded_as_module);
+    /*
+     * Set the adv_req_t 'cmndp' to point to the Scsi_Cmnd structure.
+     */
+    reqp->cmndp = scp;
 
-    asc_prt_dvc_var(&ASC_BOARDP(s)->asc_dvc_var);
-    asc_prt_dvc_cfg(&ASC_BOARDP(s)->asc_dvc_cfg);
-}
+    /*
+     * Build the ADV_SCSI_REQ_Q request.
+     */
 
-/*
- * asc_prt_scsi_cmnd()
- */
-STATIC void 
-asc_prt_scsi_cmnd(Scsi_Cmnd *s)
-{
-    printk("Scsi_Cmnd at addr %x\n", (unsigned) s);
+    /*
+     * Set CDB length and copy it to the request structure.
+     */
+    ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN);
+    if (scp->cmd_len > ASC_MAX_CDB_LEN) {
+        scp->cmd_len = ASC_MAX_CDB_LEN;
+    }
+    scsiqp->cdb_len = scp->cmd_len;
+    for (i = 0; i < scp->cmd_len; i++) {
+        scsiqp->cdb[i] = scp->cmnd[i];
+    }
 
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
-    printk(
-" host %x, device %x, target %u, lun %u\n",
-        (unsigned) s->host, (unsigned) s->device, s->target, s->lun);
-#else /* version >= v1.3.0 */
-    printk(
-" host %x, device %x, target %u, lun %u, channel %u,\n",
-        (unsigned) s->host, (unsigned) s->device, s->target, s->lun,
-        s->channel);
-#endif /* version >= v1.3.0 */
+    scsiqp->target_id = scp->target;
+    scsiqp->target_lun = scp->lun;
 
-    asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
+    scsiqp->vsense_addr = (ulong) &scp->sense_buffer[0];
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+    scsiqp->sense_addr = (ulong) &scp->sense_buffer[0];
+#else /* version >= v2.0.0 */
+    scsiqp->sense_addr = virt_to_bus(&scp->sense_buffer[0]);
+#endif /* version >= v2.0.0 */
+    scsiqp->sense_len = sizeof(scp->sense_buffer);
 
-    printk(
-" use_sg %u, sglist_len %u, abort_reason %x\n",
-        s->use_sg, s->sglist_len, s->abort_reason);
+    /*
+     * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
+     * buffer command.
+     */
+    scsiqp->data_cnt = scp->request_bufflen;
+    scsiqp->vdata_addr = (ulong) scp->request_buffer;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+    scsiqp->data_addr = (ulong) scp->request_buffer;
+#else /* version >= v2.0.0 */
+    scsiqp->data_addr = virt_to_bus(scp->request_buffer);
+#endif /* version >= v2.0.0 */
 
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
-    printk(
-" retries %d, allowed %d\n",
-         s->retries, s->allowed);
-#else /* version >= v1.3.89 */
-    printk(
-" serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n",
-        (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
-         s->retries, s->allowed);
-#endif /* version >= v1.3.89 */
+    if (scp->use_sg == 0) {
+        /*
+         * CDB request of single contiguous buffer.
+         */
+        reqp->sgblkp = NULL;
+        scsiqp->sg_list_ptr = NULL;
+        ASC_STATS(scp->host, cont_cnt);
+        ASC_STATS_ADD(scp->host, cont_xfer,
+                      ASC_CEILING(scp->request_bufflen, 512));
+    } else {
+        /*
+         * CDB scatter-gather request list.
+         */
+        if (scp->use_sg > ADV_MAX_SG_LIST) {
+            ASC_PRINT3(
+"adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n",
+                boardp->id, scp->use_sg, scp->host->sg_tablesize);
+            scp->result = HOST_BYTE(DID_ERROR);
+            asc_enqueue(&boardp->done, scp, ASC_BACK);
 
-    printk(
-" timeout_per_command %d, timeout_total %d, timeout %d\n",
-        s->timeout_per_command, s->timeout_total, s->timeout);
+            /*
+             * Free the 'adv_req_t' structure by adding it back to the
+             * board free list.
+             */
+            reqp->next_reqp = boardp->adv_reqp;
+            boardp->adv_reqp = reqp;
 
-    printk(
-" internal_timeout %u, flags %u, this_count %d\n",
-        s->internal_timeout, s->flags, s->this_count);
+            return ASC_ERROR;
+        }
 
-    printk(
-" scsi_done %x, done %x, host_scribble %x, result %x\n",
-        (unsigned) s->scsi_done, (unsigned) s->done,
-        (unsigned) s->host_scribble, s->result);
+        /*
+         * Allocate an 'adv_sgblk_t' structure from the board to
+         * execute the command.
+         */
+        if (boardp->adv_sgblkp == NULL) {
+            ASC_DBG(1, "adv_build_req: no free adv_sgblk_t\n");
+            ASC_STATS(scp->host, adv_build_nosg);
+            /*
+             * Free the 'adv_req_t' structure by adding it back to the
+             * board free list.
+             */
+            reqp->next_reqp = boardp->adv_reqp;
+            boardp->adv_reqp = reqp;
+            return ASC_BUSY;
+        } else {
+            reqp->sgblkp = boardp->adv_sgblkp;
+            boardp->adv_sgblkp = reqp->sgblkp->next_sgblkp;
+            reqp->sgblkp->next_sgblkp = NULL;
+        }
 
-    printk(
-" tag %u, pid %u\n",
-        (unsigned) s->tag, (unsigned) s->pid);
-}
+        /*
+         * Build scatter-gather list.
+         */
+        scsiqp->sg_list_ptr = (ADV_SG_BLOCK *)
+            ADV_DWALIGN(&reqp->sgblkp->sg_block[0]);
 
-/*
- * asc_prt_dvc_var()
- */
-STATIC void 
-asc_prt_dvc_var(ASC_DVC_VAR *h)
-{
-    printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
+        memset(scsiqp->sg_list_ptr, 0, sizeof(ADV_SG_BLOCK) *
+            (ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING));
+         
+        if (adv_get_sglist(&boardp->dvc_var.adv_dvc_var, scsiqp, scp) ==
+            ADV_ERROR) {
 
-    printk(
-" iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
-        h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
+            /*
+             * Free the adv_sgblk_t structure, if any, by adding it back
+             * to the board free list.
+             */
+            ASC_ASSERT(reqp->sgblkp != NULL);
+            reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
+            boardp->adv_sgblkp = reqp->sgblkp;
 
-    printk(
-" bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
-        h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
-        (unsigned) h->init_sdtr);
+            /*
+             * Free the adv_req_t structure by adding it back to the
+             * board free list.
+             */
+            reqp->next_reqp = boardp->adv_reqp;
+            boardp->adv_reqp = reqp;
 
-    printk(
-" sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
-        (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
-        (unsigned) h->unit_not_ready, (unsigned) h->chip_no);
-        
-    printk(
-" queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
-        (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
-        (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
+            return ADV_ERROR;
+        }
 
-    printk(
-" is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
-        (unsigned) h->is_in_int, (unsigned) h->max_total_qng,
-        (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
+        ASC_STATS(scp->host, sg_cnt);
+        ASC_STATS_ADD(scp->host, sg_elem, scp->use_sg);
+    }
 
-    printk(
-" last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
-        (unsigned) h->last_q_shortage, (unsigned) h->init_state,
-        (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
+    ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
+    ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
 
-    printk(
-" cfg %x, saved_ptr2func %x\n",
-        (unsigned) h->cfg, (unsigned) h->saved_ptr2func);
+    *adv_scsiqpp = scsiqp;
+
+    return ASC_NOERROR;
 }
 
 /*
- * asc_prt_dvc_cfg()
+ * Build scatter-gather list for Adv Library (Wide Board).
+ *
+ * Return:
+ *      ADV_SUCCESS(1) - SG List successfully created
+ *      ADV_ERROR(-1) - SG List creation failed
  */
-STATIC void 
-asc_prt_dvc_cfg(ASC_DVC_CFG *h)
-{
-    printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
-
-    printk(
-" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n",
-            h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res);
+STATIC int
+adv_get_sglist(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp,
+    Scsi_Cmnd *scp)
+{
+    ADV_SG_BLOCK        *sg_block;              /* virtual address of a SG */
+    ulong               sg_block_next_addr;     /* block and its next */
+    ulong               sg_block_physical_addr;
+    int                 sg_block_index, i;      /* how many SG entries */
+    struct scatterlist  *slp;
+    int                 sg_elem_cnt;
+
+    slp = (struct scatterlist *) scp->request_buffer;
+    sg_elem_cnt = scp->use_sg;
+
+    sg_block = scsiqp->sg_list_ptr;
+    sg_block_next_addr = (ulong) sg_block;    /* allow math operation */
+    sg_block_physical_addr =
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+        (ulong) scsiqp->sg_list_ptr;
+#else /* version >= v2.0.0 */
+        virt_to_bus(scsiqp->sg_list_ptr);
+#endif /* version >= v2.0.0 */
+    ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
+                   sg_block_physical_addr);
+    scsiqp->sg_real_addr = sg_block_physical_addr;
 
-    printk(
-" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
-             h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
-             h->chip_version);
+    sg_block_index = 0;
+    do
+    {
+        sg_block->first_entry_no = sg_block_index;
+        for (i = 0; i < NO_OF_SG_PER_BLOCK; i++)
+        {
+            sg_block->sg_list[i].sg_addr =
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+                (ulong) slp->address;
+#else /* version >= v2.0.0 */
+                virt_to_bus(slp->address);
+#endif /* version >= v2.0.0 */
+            sg_block->sg_list[i].sg_count = slp->length;
+            ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
 
-    printk(
-" pci_device_id %d, lib_serial_no %d, lib_version %d, mcode_date %d,\n",
-          h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
+            if (--sg_elem_cnt == 0)
+            {   /* last entry, get out */
+                scsiqp->sg_entry_cnt = sg_block_index + i + 1;
+                sg_block->last_entry_no = sg_block_index + i;
+                sg_block->sg_ptr = 0L;    /* next link = NULL */
+                return ADV_SUCCESS;
+            }
+            slp++;
+        } 
+        sg_block_next_addr += sizeof(ADV_SG_BLOCK);
+        sg_block_physical_addr += sizeof(ADV_SG_BLOCK);
+        ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) ==
+                       sg_block_physical_addr);
 
-    printk(
-" mcode_version %d, overrun_buf %x\n",
-            h->mcode_version, (unsigned) h->overrun_buf);
+        sg_block_index += NO_OF_SG_PER_BLOCK;
+        sg_block->sg_ptr = (ADV_SG_BLOCK *) sg_block_physical_addr;
+        sg_block->last_entry_no = sg_block_index - 1;
+        sg_block = (ADV_SG_BLOCK *) sg_block_next_addr; /* virtual addr */
+    }
+    while (1);
+    /* NOTREACHED */
 }
 
 /*
- * asc_prt_scsi_q()
+ * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
+ *
+ * Interrupt callback function for the Narrow SCSI Asc Library.
  */
-STATIC void 
-asc_prt_scsi_q(ASC_SCSI_Q *q)
+STATIC void
+asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
 {
-    ASC_SG_HEAD    *sgp;
-    int i;
-
-    printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
+    asc_board_t         *boardp;
+    Scsi_Cmnd           *scp;
+    struct Scsi_Host    *shp;
+    int            underrun = ASC_FALSE;
+    int                 i;
 
-    printk(
-" target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
-            q->q2.target_ix, q->q1.target_lun,
-            (unsigned) q->q2.srb_ptr, q->q2.tag_code);
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp %x, qdonep %x\n",
+        (unsigned) asc_dvc_varp, (unsigned) qdonep);
+    ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
 
-    printk(
-" data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
-            (unsigned) q->q1.data_addr, q->q1.data_cnt,
-            (unsigned) q->q1.sense_addr, q->q1.sense_len);
+    /*
+     * Get the Scsi_Cmnd structure and Scsi_Host structure for the
+     * command that has been completed.
+     */
+    scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr;
+    ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp);
 
-    printk(
-" cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
-            (unsigned) q->cdbptr, q->q2.cdb_len,
-            (unsigned) q->sg_head, q->q1.sg_queue_cnt);
+    if (scp == NULL) {
+        ASC_PRINT("asc_isr_callback: scp is NULL\n");
+        return;
+    }
+    ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
 
-    if (q->sg_head) {
-        sgp = q->sg_head;
-        printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
-        printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
-        for (i = 0; i < sgp->entry_cnt; i++) {
-            printk(" [%u]: addr %x, bytes %lu\n",
-                i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
+    /*
+     * If the request's host pointer is not valid, display a
+     * message and return.
+     */
+    shp = scp->host;
+    for (i = 0; i < asc_board_count; i++) {
+        if (asc_host[i] == shp) {
+            break;
         }
-
     }
-}
+    if (i == asc_board_count) {
+        ASC_PRINT2("asc_isr_callback: scp %x has bad host pointer, host %x\n",
+            (unsigned) scp, (unsigned) shp);
+        return;
+    }
 
-/*
- * asc_prt_qdone_info()
- */
-STATIC void 
-asc_prt_qdone_info(ASC_QDONE_INFO *q)
-{
-    printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
-    printk(
-" srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
-            (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
-            q->d2.tag_code, q->d3.done_stat);
-    printk(
-" host_stat %x, scsi_stat %x, scsi_msg %x\n",
-            q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
-}
+    ASC_STATS(shp, callback);
+    ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
 
-/*
- * asc_prt_hex()
- *
- * Print hexadecimal output in 4 byte groupings 32 bytes 
- * or 8 double-words per line.
- */
-STATIC void 
-asc_prt_hex(char *f, uchar *s, int l)
-{
-    int            i;
-    int            j;
-    int            k;
-    int            m;
+    /*
+     * If the request isn't found on the active queue, it may
+     * have been removed to handle a reset or abort request.
+     * Display a message and return.
+     */
+    boardp = ASC_BOARDP(shp);
+    if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
+        ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n",
+            boardp->id, (unsigned) scp);
+        return;
+    }
 
-    printk("%s: (%d bytes)\n", f, l);
+    /*
+     * Check for an underrun condition.
+     */
+    if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && 
+    qdonep->remain_bytes <= scp->request_bufflen != 0) {
+        ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n",
+        (unsigned) qdonep->remain_bytes);
+        underrun = ASC_TRUE;
+    }
 
-    for (i = 0; i < l; i += 32) {
-        
-        /* Display a maximum of 8 double-words per line. */
-        if ((k = (l - i) / 4) >= 8) {
-            k = 8;
-            m = 0;
-        } else {
-            m = (l - i) % 4 ;
+    /*
+     * 'qdonep' contains the command's ending status.
+     */
+    switch (qdonep->d3.done_stat) {
+    case QD_NO_ERROR:
+        ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
+        switch (qdonep->d3.host_stat) {
+        case QHSTA_NO_ERROR:
+            scp->result = 0;
+            break;
+        default:
+            /* QHSTA error occurred */
+            scp->result = HOST_BYTE(DID_ERROR);
+            break;
         }
+    /*
+     * If there was an underrun without any other error,
+     * set DID_ERROR to indicate the underrun error.
+     */
+    if (scp->result == 0 && underrun == ASC_TRUE) {
+            scp->result = HOST_BYTE(DID_UNDERRUN);
+    }
+        break;
 
-        for (j = 0; j < k; j++) {
-            printk(" %2.2X%2.2X%2.2X%2.2X",
-                (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
-                (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
-        }
+    case QD_WITH_ERROR:
+        ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
+        switch (qdonep->d3.host_stat) {
+        case QHSTA_NO_ERROR:
+            if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
+                ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n");
+                ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
+                    sizeof(scp->sense_buffer));
+                /*
+                 * Note: The 'status_byte()' macro used by target drivers
+                 * defined in scsi.h shifts the status byte returned by
+                 * host drivers right by 1 bit. This is why target drivers
+                 * also use right shifted status byte definitions. For
+                 * instance target drivers use CHECK_CONDITION, defined to
+                 * 0x1, instead of the SCSI defined check condition value
+                 * of 0x2. Host drivers are supposed to return the status
+                 * byte as it is defined by SCSI.
+                 */
+                scp->result = DRIVER_BYTE(DRIVER_SENSE) |
+                    STATUS_BYTE(qdonep->d3.scsi_stat); 
+            } else {
+                scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); 
+            }
+            break;
 
-        switch (m) {
-        case 0:
         default:
-            break;
-        case 1:
-            printk(" %2.2X",
-                (unsigned) s[i+(j*4)]);
-            break;
-        case 2:
-            printk(" %2.2X%2.2X",
-                (unsigned) s[i+(j*4)],
-                (unsigned) s[i+(j*4)+1]);
-            break;
-        case 3:
-            printk(" %2.2X%2.2X%2.2X",
-                (unsigned) s[i+(j*4)+1],
-                (unsigned) s[i+(j*4)+2],
-                (unsigned) s[i+(j*4)+3]);
+            /* QHSTA error occurred */
+            ASC_DBG1(2, "asc_isr_callback: host_stat %x\n",
+                qdonep->d3.host_stat);
+            scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
+                STATUS_BYTE(qdonep->d3.scsi_stat);
             break;
         }
+        break;
 
-        printk("\n");
-    }
-}
-#endif /* ADVANSYS_DEBUG */
-
-#ifdef ADVANSYS_ASSERT
-/*
- * interrupts_enabled()
- *
- * Return 1 if interrupts are enabled, otherwise return 0.
- */
-STATIC int
-interrupts_enabled(void)
-{
-    int flags;
+    case QD_ABORTED_BY_HOST:
+        ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
+        scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) |
+                STATUS_BYTE(qdonep->d3.scsi_stat);
+        break;
 
-    save_flags(flags);
-    if (flags & 0x0200) {
-        return ASC_TRUE;
-    } else {
-        return ASC_FALSE;
+    default:
+        ASC_PRINT1("asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat);
+        scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
+                STATUS_BYTE(qdonep->d3.scsi_stat);
+        break;
     }
-}
-#endif /* ADVANSYS_ASSERT */
 
+    /* 
+     * Because interrupts may be enabled by the 'Scsi_Cmnd' done
+     * function, add the command to the end of the board's done queue.
+     * The done function for the command will be called from
+     * advansys_interrupt().
+     */
+    asc_enqueue(&boardp->done, scp, ASC_BACK);
+
+    return;
+}
 
 /*
- * --- Asc Library Functions
+ * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
+ *
+ * Callback function for the Wide SCSI Adv Library.
  */
-
-ASC_INITFUNC(
-STATIC ushort
-AscGetEisaChipCfg(
-                     PortAddr iop_base
-)
-)
+STATIC void
+adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
 {
-    PortAddr            eisa_cfg_iop;
-    eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
-      (PortAddr) (ASC_EISA_CFG_IOP_MASK);
-    return (inpw(eisa_cfg_iop));
-}
+    asc_board_t         *boardp;
+    adv_req_t           *reqp;
+    Scsi_Cmnd           *scp;
+    struct Scsi_Host    *shp;
+    int            underrun = ASC_FALSE;
+    int                 i;
 
-ASC_INITFUNC(
-STATIC uchar
-AscSetChipScsiID(
-                    PortAddr iop_base,
-                    uchar new_host_id
-)
-)
-{
-    ushort              cfg_lsw;
-    if (AscGetChipScsiID(iop_base) == new_host_id) {
-        return (new_host_id);
-    }
-    cfg_lsw = AscGetChipCfgLsw(iop_base);
-    cfg_lsw &= 0xF8FF;
-    cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
-    AscSetChipCfgLsw(iop_base, cfg_lsw);
-    return (AscGetChipScsiID(iop_base));
-}
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp %x, scsiqp %x\n",
+        (unsigned) adv_dvc_varp, (unsigned) scsiqp);
+    ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
 
-ASC_INITFUNC(
-STATIC uchar
-AscGetChipScsiCtrl(
-                      PortAddr iop_base
-)
-)
-{
-    uchar               sc;
-    AscSetBank(iop_base, 1);
-    sc = inp(iop_base + IOP_REG_SC);
-    AscSetBank(iop_base, 0);
-    return (sc);
-}
+    /*
+     * Get the adv_req_t structure for the command that has been
+     * completed. The adv_req_t structure actually contains the
+     * completed ADV_SCSI_REQ_Q structure.
+     */
+    reqp = (adv_req_t *) scsiqp->srb_ptr;
+    ASC_DBG1(1, "adv_isr_callback: reqp %x\n", (unsigned) reqp);
+    if (reqp == NULL) {
+        ASC_PRINT("adv_isr_callback: reqp is NULL\n");
+        return;
+    }
 
-ASC_INITFUNC(
-STATIC uchar
-AscGetChipVersion(
-                     PortAddr iop_base,
-                     ushort bus_type
-)
-)
-{
-    if ((bus_type & ASC_IS_EISA) != 0) {
-        PortAddr            eisa_iop;
-        uchar               revision;
-        eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
-          (PortAddr) ASC_EISA_REV_IOP_MASK;
-        revision = inp(eisa_iop);
-        return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
+    /*
+     * Get the Scsi_Cmnd structure and Scsi_Host structure for the
+     * command that has been completed.
+     *
+     * Note: The adv_req_t request structure and adv_sgblk_t structure,
+     * if any, * dropped, because a board structure pointer can not be
+     * determined.
+     */
+    scp = reqp->cmndp;
+    ASC_DBG1(1, "adv_isr_callback: scp %x\n", (unsigned) scp);
+    if (scp == NULL) {
+        ASC_PRINT("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
+        return;
     }
-    return (AscGetChipVerNo(iop_base));
-}
+    ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
 
-ASC_INITFUNC(
-STATIC ushort
-AscGetChipBusType(
-                     PortAddr iop_base
-)
-)
-{
-    ushort              chip_ver;
-    chip_ver = AscGetChipVerNo(iop_base);
-    if (
-           (chip_ver >= ASC_CHIP_MIN_VER_VL)
-           && (chip_ver <= ASC_CHIP_MAX_VER_VL)
-) {
-        if (
-               ((iop_base & 0x0C30) == 0x0C30)
-               || ((iop_base & 0x0C50) == 0x0C50)
-) {
-            return (ASC_IS_EISA);
+    /*
+     * If the request's host pointer is not valid, display a message
+     * and return.
+     */
+    shp = scp->host;
+    for (i = 0; i < asc_board_count; i++) {
+        if (asc_host[i] == shp) {
+            break;
         }
-        return (ASC_IS_VL);
     }
-    if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
-        (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
-        if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
-            return (ASC_IS_ISAPNP);
-        }
-        return (ASC_IS_ISA);
-    } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
-               (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
-        return (ASC_IS_PCI);
+    /*
+     * Note: If the host structure is not found, the adv_req_t request
+     * structure and adv_sgblk_t structure, if any, is dropped.
+     */
+    if (i == asc_board_count) {
+        ASC_PRINT2("adv_isr_callback: scp %x has bad host pointer, host %x\n",
+            (unsigned) scp, (unsigned) shp);
+        return;
     }
-    return (0);
-}
 
-ASC_INITFUNC(
-STATIC ulong
-AscLoadMicroCode(
-                    PortAddr iop_base,
-                    ushort s_addr,
-                    ushort *mcode_buf,
-                    ushort mcode_size
-)
-)
-{
-    ulong               chksum;
-    ushort              mcode_word_size;
-    ushort              mcode_chksum;
-    mcode_word_size = (ushort) (mcode_size >> 1);
-    AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
-    AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
-    chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
-    mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
-                                              (ushort) ASC_CODE_SEC_BEG,
-          (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
-    AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
-    AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
-    return (chksum);
-}
+    ASC_STATS(shp, callback);
+    ASC_DBG1(1, "adv_isr_callback: shp %x\n", (unsigned) shp);
 
-ASC_INITFUNC(
-STATIC int
-AscFindSignature(
-                    PortAddr iop_base
-)
-)
-{
-    ushort              sig_word;
-    if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) {
-        sig_word = AscGetChipSignatureWord(iop_base);
-        if ((sig_word == (ushort) ASC_1000_ID0W) ||
-            (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
-            return (1);
-        }
+    /*
+     * If the request isn't found on the active queue, it may have been
+     * removed to handle a reset or abort request. Display a message and
+     * return.
+     *
+     * Note: Because the structure may still be in use don't attempt
+     * to free the adv_req_t and adv_sgblk_t, if any, structures.
+     */
+    boardp = ASC_BOARDP(shp);
+    if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
+        ASC_PRINT2("adv_isr_callback: board %d: scp %x not on active queue\n",
+            boardp->id, (unsigned) scp);
+        return;
     }
-    return (0);
-}
-
-STATIC uchar _isa_pnp_inited ASC_INITDATA = 0;
-STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA =
-{
-    0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
-    ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
-};
 
-ASC_INITFUNC(
-STATIC PortAddr
-AscSearchIOPortAddr(
-                       PortAddr iop_beg,
-                       ushort bus_type
-)
-)
-{
-    if (bus_type & ASC_IS_VL) {
-        while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
-            if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
-                return (iop_beg);
-            }
-        }
-        return (0);
+    /*
+     * Check for an underrun condition.
+     */
+    if (scp->request_bufflen != 0 && scsiqp->data_cnt != 0) {
+        ASC_DBG1(1, "adv_isr_callback: underrun condition %lu bytes\n",
+        scsiqp->data_cnt);
+        underrun = ASC_TRUE;
     }
-    if (bus_type & ASC_IS_ISA) {
-        if (_isa_pnp_inited == 0) {
-            AscSetISAPNPWaitForKey();
-            _isa_pnp_inited++;
-        }
-        while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
-            if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
-                return (iop_beg);
-            }
+
+    /*
+     * 'done_status' contains the command's ending status.
+     */
+    switch (scsiqp->done_status) {
+    case QD_NO_ERROR:
+        ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
+        switch (scsiqp->host_status) {
+        case QHSTA_NO_ERROR:
+            scp->result = 0;
+            break;
+        default:
+            /* QHSTA error occurred. */
+            ASC_DBG1(2, "adv_isr_callback: host_status %x\n",
+                scsiqp->host_status);
+            scp->result = HOST_BYTE(DID_ERROR);
+            break;
         }
-        return (0);
+    /*
+     * If there was an underrun without any other error,
+     * set DID_ERROR to indicate the underrun error.
+     */
+    if (scp->result == 0 && underrun == ASC_TRUE) {
+            scp->result = HOST_BYTE(DID_UNDERRUN);
     }
-    if (bus_type & ASC_IS_EISA) {
-        if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
-            return (iop_beg);
-        }
-        return (0);
+        break;
+
+    case QD_WITH_ERROR:
+        ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
+        switch (scsiqp->host_status) {
+        case QHSTA_NO_ERROR:
+            if (scsiqp->scsi_status == SS_CHK_CONDITION) {
+                ASC_DBG(2, "adv_isr_callback: SS_CHK_CONDITION\n");
+                ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
+                    sizeof(scp->sense_buffer));
+                /*
+                 * Note: The 'status_byte()' macro used by target drivers
+                 * defined in scsi.h shifts the status byte returned by
+                 * host drivers right by 1 bit. This is why target drivers
+                 * also use right shifted status byte definitions. For
+                 * instance target drivers use CHECK_CONDITION, defined to
+                 * 0x1, instead of the SCSI defined check condition value
+                 * of 0x2. Host drivers are supposed to return the status
+                 * byte as it is defined by SCSI.
+                 */
+                scp->result = DRIVER_BYTE(DRIVER_SENSE) |
+                    STATUS_BYTE(scsiqp->scsi_status);
+            } else {
+                scp->result = STATUS_BYTE(scsiqp->scsi_status);
+            }
+            break;
+
+        default:
+            /* Some other QHSTA error occurred. */
+            ASC_DBG1(2, "adv_isr_callback: host_status %x\n",
+                scsiqp->host_status);
+            scp->result = HOST_BYTE(DID_BAD_TARGET);
+            break;
+        }
+        break;
+
+    case QD_ABORTED_BY_HOST:
+        ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
+        scp->result = HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
+        break;
+
+    default:
+        ASC_PRINT1("adv_isr_callback: done_status %x\n", scsiqp->done_status);
+        scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
+        break;
     }
-    return (0);
+
+    /*
+     * If the 'init_tidmask' bit isn't already set for the target and the
+     * current request did not finish with a Selection Timeout, then set
+     * the bit for the target to indicate that a device is present.
+     */
+    if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
+        scsiqp->done_status == QD_NO_ERROR &&
+        scsiqp->host_status == QHSTA_NO_ERROR) {
+        boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
+    }
+
+    /* 
+     * Because interrupts may be enabled by the 'Scsi_Cmnd' done
+     * function, add the command to the end of the board's done queue.
+     * The done function for the command will be called from
+     * advansys_interrupt().
+     */
+    asc_enqueue(&boardp->done, scp, ASC_BACK);
+
+    /*
+     * Free the adv_sgblk_t structure, if any, by adding it back
+     * to the board free list.
+     */
+    if (reqp->sgblkp != NULL) {
+        reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp;
+        boardp->adv_sgblkp = reqp->sgblkp;
+    }
+
+    /*
+     * Free the adv_req_t structure used with the command by adding
+     * it back to the board free list.
+     */
+    reqp->next_reqp = boardp->adv_reqp;
+    boardp->adv_reqp = reqp;
+
+    ASC_DBG(1, "adv_isr_callback: done\n");
+
+    return;
 }
 
-ASC_INITFUNC(
-STATIC PortAddr
-AscSearchIOPortAddr11(
-                         PortAddr s_addr
-)
-)
+/*
+ * asc_init_dev() - Narrow Board initialization function. 
+ *
+ * Perform one-time initialization of a device for Asc Library
+ */
+STATIC int
+asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
 {
-    int                 i;
-    PortAddr            iop_base;
-    for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
-        if (_asc_def_iop_base[i] > s_addr) {
-            break;
-        }
+    asc_board_t             *boardp;
+    ASC_SCSI_REQ_Q          *scsireqq;
+    ASC_CAP_INFO            *cap_info;
+    ASC_SCSI_INQUIRY        *inquiry;
+    int                     found;
+    ASC_SCSI_BIT_ID_TYPE    save_use_tagged_qng;
+    ASC_SCSI_BIT_ID_TYPE    save_can_tagged_qng;
+    int                     ret;
+#ifdef ADVANSYS_DEBUG
+    ASC_SCSI_BIT_ID_TYPE    tidmask; /* target id bit mask: 1 - 128 */
+#endif /* ADVANSYS_DEBUG */
+
+    ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target);
+
+    /* The host's target id is set in init_tidmask during initialization. */
+    ASC_ASSERT(asc_dvc_varp->cfg->chip_scsi_id != scp->target);
+
+    boardp = ASC_BOARDP(scp->host);
+
+    /* Set-up AscInitPollTarget() arguments. */
+    scsireqq = &boardp->scsireqq;
+    memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
+    cap_info = &boardp->cap_info;
+    memset(cap_info, 0, sizeof(ASC_CAP_INFO));
+    inquiry = &boardp->inquiry;
+    memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
+
+    /*
+     * AscInitPollBegin() re-initializes these bitmask fields to zero.
+     * Save the current bitmask value and 'or' them back in after calling
+     * AscInitPollEnd() below..
+     */
+    save_use_tagged_qng = asc_dvc_varp->use_tagged_qng;
+    save_can_tagged_qng = asc_dvc_varp->cfg->can_tagged_qng;
+
+    ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n");
+    if (AscInitPollBegin(asc_dvc_varp)) {
+        ASC_PRINT1("asc_init_dev: board %d: AscInitPollBegin() failed\n",
+            boardp->id);
+        return ASC_FALSE;
     }
-    for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
-        iop_base = _asc_def_iop_base[i];
-        if (check_region(iop_base, ASC_IOADR_GAP) != 0) {
-            ASC_DBG1(1,
-               "AscSearchIOPortAddr11: check_region() failed I/O port %x\n",
-                     iop_base);
-            continue;
+
+    scsireqq->sense_ptr = &scsireqq->sense[0];
+    scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN;
+    scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
+    scsireqq->r1.target_lun = 0;
+    scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
+
+    found = ASC_FALSE;
+    ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n");
+    switch (ret = AscInitPollTarget(asc_dvc_varp, scsireqq, inquiry,
+        cap_info)) {
+    case ASC_TRUE:
+        found = ASC_TRUE;
+#ifdef ADVANSYS_DEBUG
+        tidmask = ADV_TID_TO_TIDMASK(scp->target);
+        ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n",
+            cap_info->lba, cap_info->blk_size);
+        ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n",
+            inquiry->byte0.peri_dvc_type);
+        if (asc_dvc_varp->use_tagged_qng & tidmask) {
+            ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
+                asc_dvc_varp->max_dvc_qng[scp->target]);
+        } else {
+            ASC_DBG(1, "asc_init_dev: command queuing disabled\n");
         }
-        ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port %x\n", iop_base);
-        if (AscFindSignature(iop_base)) {
-            return (iop_base);
+        if (asc_dvc_varp->init_sdtr & tidmask) {
+            ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n");
+        } else {
+            ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n");
+        }
+        /* Set bit means fix disabled. */
+        if (asc_dvc_varp->pci_fix_asyn_xfer & tidmask) {
+            ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n");
+        } else {
+            ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n");
         }
+#endif /* ADVANSYS_DEBUG */
+        break;
+    case ASC_FALSE:
+        ASC_DBG(1, "asc_init_dev: no device found\n");
+        break;
+    case ASC_ERROR:
+        ASC_PRINT1("asc_init_dev: board %d: AscInitPollTarget() ASC_ERROR\n",
+                boardp->id);
+        break;
+    default:
+        ASC_PRINT2(
+"asc_init_dev: board %d: AscInitPollTarget() unknown ret %d\n",
+                boardp->id, ret);
+        break;
     }
-    return (0);
+
+    /* Restore previously set bits in the bitmask fields. */
+    asc_dvc_varp->use_tagged_qng |= save_use_tagged_qng;
+    asc_dvc_varp->cfg->can_tagged_qng |= save_can_tagged_qng;
+
+    ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n");
+    AscInitPollEnd(asc_dvc_varp);
+
+    ASC_DBG1(1, "asc_init_dev: found %d\n", found); 
+
+    return found;
 }
 
+/*
+ * Search for an AdvanSys PCI device in the PCI configuration space.
+ */
 ASC_INITFUNC(
-STATIC void
-AscToggleIRQAct(
-                   PortAddr iop_base
-)
+STATIC int
+asc_srch_pci_dev(PCI_DEVICE *pciDevice)
 )
 {
-    AscSetChipStatus(iop_base, CIW_IRQ_ACT);
-    AscSetChipStatus(iop_base, 0);
-    return;
+    int ret;
+
+    ASC_DBG(2, "asc_srch_pci_dev: begin\n");
+
+    if (pci_scan_method == -1) {
+        pci_scan_method = asc_scan_method();
+    }
+    pciDevice->type = pci_scan_method;
+    ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type);
+
+    ret = asc_pci_find_dev(pciDevice);
+    ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret);
+    if (ret == PCI_DEVICE_FOUND) {
+        pciDevice->slotNumber = pciDevice->slotFound + 1;
+        pciDevice->startSlot = pciDevice->slotFound + 1;
+    } else {
+        if (pciDevice->bridge > pciDevice->busNumber) {
+            ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n",
+                pciDevice->bridge, pciDevice->busNumber);
+            pciDevice->busNumber++;
+            pciDevice->slotNumber = 0;
+            pciDevice->startSlot = 0;
+            pciDevice->endSlot = 0x0f;
+            ret = asc_srch_pci_dev(pciDevice);
+            ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret);
+        }
+    }
+    ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
+    return ret;
 }
 
+/*
+ * Determine the access method to be used for 'pciDevice'.
+ */
 ASC_INITFUNC(
-STATIC void
-AscSetISAPNPWaitForKey(
-    void)
+STATIC uchar
+asc_scan_method(void)
 )
 {
-    outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
-    outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
-    return;
+    ushort      data;
+    PCI_DATA    pciData;
+    uchar       type;
+    uchar       slot;
+
+    ASC_DBG(2, "asc_scan_method: begin\n");
+    memset(&pciData, 0, sizeof(pciData));
+    for (type = 1; type < 3; type++) {
+        pciData.type = type;
+        for (slot = 0; slot < PCI_MAX_SLOT; slot++) {
+            pciData.slot = slot;
+            data = asc_get_cfg_word(&pciData);
+            if ((data != 0xFFFF) && (data != 0x0000)) {
+                ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type);
+                return (type);
+            }
+        }
+    }
+    ASC_DBG1(4, "asc_scan_method: type %d\n", type);
+    return (type);
 }
 
+/*
+ * Check for an AdvanSys PCI device in 'pciDevice'.
+ *
+ * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
+ */
 ASC_INITFUNC(
-STATIC uchar
-AscGetChipIRQ(
-                 PortAddr iop_base,
-                 ushort bus_type
-)
+STATIC int
+asc_pci_find_dev(PCI_DEVICE *pciDevice)
 )
 {
-    ushort              cfg_lsw;
-    uchar               chip_irq;
-    if ((bus_type & ASC_IS_EISA) != 0) {
-        cfg_lsw = AscGetEisaChipCfg(iop_base);
-        chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
-        if ((chip_irq == 13) || (chip_irq > 15)) {
-            return (0);
-        }
-        return (chip_irq);
-    }
-    if ((bus_type & ASC_IS_VL) != 0) {
-        cfg_lsw = AscGetChipCfgLsw(iop_base);
-        chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
-        if ((chip_irq == 0) ||
-            (chip_irq == 4) ||
-            (chip_irq == 7)) {
-            return (0);
-        }
-#if CC_PLEXTOR_VL
-        if (chip_irq == 5) {
-            return (9);
-        }
-#endif
-        return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
-    }
-    cfg_lsw = AscGetChipCfgLsw(iop_base);
-    chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
-    if (chip_irq == 3)
-        chip_irq += (uchar) 2;
-    return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
-}
+    PCI_DATA    pciData;
+    ushort      vendorid, deviceid;
+    uchar       classcode, subclass;
+    uchar       lslot;
 
-ASC_INITFUNC(
-STATIC uchar
-AscSetChipIRQ(
-                 PortAddr iop_base,
-                 uchar irq_no,
-                 ushort bus_type
-)
-)
-{
-    ushort              cfg_lsw;
-    if ((bus_type & ASC_IS_VL) != 0) {
-        if (irq_no != 0) {
-#if CC_PLEXTOR_VL
-            if (irq_no == 9) {
-                irq_no = 14;
-            }
-#endif
-            if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
-                irq_no = 0;
+    ASC_DBG(3, "asc_pci_find_dev: begin\n");
+    pciData.type = pciDevice->type;
+    pciData.bus = pciDevice->busNumber;
+    pciData.func = pciDevice->devFunc;
+    lslot = pciDevice->startSlot;
+    for (; lslot < pciDevice->endSlot; lslot++) {
+        pciData.slot = lslot;
+        pciData.offset = VENDORID_OFFSET;
+        vendorid = asc_get_cfg_word(&pciData);
+        ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid);
+        if (vendorid != 0xffff) {
+            pciData.offset = DEVICEID_OFFSET;
+            deviceid = asc_get_cfg_word(&pciData);
+            ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid);
+            if ((vendorid == ASC_PCI_VENDORID) &&
+                ((deviceid == ASC_PCI_DEVICE_ID_1100) ||
+                 (deviceid == ASC_PCI_DEVICE_ID_1200) ||
+                 (deviceid == ASC_PCI_DEVICE_ID_1300) ||
+                 (deviceid == ASC_PCI_DEVICE_ID_2300))) {
+                pciDevice->slotFound = lslot;
+                ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n");
+                return PCI_DEVICE_FOUND;
             } else {
-                irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
+                pciData.offset = SUBCLASS_OFFSET;
+                subclass = asc_get_cfg_byte(&pciData);
+                pciData.offset = CLASSCODE_OFFSET;
+                classcode = asc_get_cfg_byte(&pciData);
+                if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) &&
+                    (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) {
+                    pciDevice->bridge++;
+                }
+                ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n",
+                    subclass, classcode);
             }
         }
-        cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
-        cfg_lsw |= (ushort) 0x0010;
-        AscSetChipCfgLsw(iop_base, cfg_lsw);
-        AscToggleIRQAct(iop_base);
-        cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
-        cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
-        AscSetChipCfgLsw(iop_base, cfg_lsw);
-        AscToggleIRQAct(iop_base);
-        return (AscGetChipIRQ(iop_base, bus_type));
-    }
-    if ((bus_type & (ASC_IS_ISA)) != 0) {
-        if (irq_no == 15)
-            irq_no -= (uchar) 2;
-        irq_no -= (uchar) ASC_MIN_IRQ_NO;
-        cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
-        cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
-        AscSetChipCfgLsw(iop_base, cfg_lsw);
-        return (AscGetChipIRQ(iop_base, bus_type));
     }
-    return (0);
+    return PCI_DEVICE_NOT_FOUND;
 }
 
+/*
+ * Read PCI configuration data into 'pciConfig'.
+ */
 ASC_INITFUNC(
 STATIC void
-AscEnableIsaDma(
-                   uchar dma_channel
-)
+asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
 )
 {
-    if (dma_channel < 4) {
-        outp(0x000B, (ushort) (0xC0 | dma_channel));
-        outp(0x000A, dma_channel);
-    } else if (dma_channel < 8) {
-        outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
-        outp(0x00D4, (ushort) (dma_channel - 4));
+    PCI_DATA    pciData;
+    uchar       counter;
+    uchar       *localConfig;
+
+    ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ",
+        pciDevice->slotFound);
+
+    pciData.type = pciDevice->type;
+    pciData.bus = pciDevice->busNumber;
+    pciData.slot = pciDevice->slotFound;
+    pciData.func = pciDevice->devFunc;
+    localConfig = (uchar *) pciConfig;
+
+    for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) {
+        pciData.offset = counter;
+        *localConfig = asc_get_cfg_byte(&pciData);
+        ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig);
+        localConfig++;
     }
-    return;
+    ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter);
 }
 
-STATIC int 
-AscIsrChipHalted(
-                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+/*
+ * Read a word (16 bits) from the PCI configuration space.
+ *
+ * The configuration mechanism is checked for the correct access method.
+ */
+ASC_INITFUNC(
+STATIC ushort
+asc_get_cfg_word(PCI_DATA *pciData)
 )
 {
-    EXT_MSG             ext_msg;
-    EXT_MSG             out_msg;
-    ushort              halt_q_addr;
-    int                 sdtr_accept;
-    ushort              int_halt_code;
-    ASC_SCSI_BIT_ID_TYPE scsi_busy;
-    ASC_SCSI_BIT_ID_TYPE target_id;
-    PortAddr            iop_base;
-    uchar               tag_code;
-    uchar               q_status;
-    uchar               halt_qp;
-    uchar               sdtr_data;
-    uchar               target_ix;
-    uchar               q_cntl, tid_no;
-    uchar               cur_dvc_qng;
-    uchar               asyn_sdtr;
-    uchar               scsi_status;
-    asc_board_t            *boardp;
+    ushort   tmp;
+    ulong    address;
+    ulong    lbus = pciData->bus;
+    ulong    lslot = pciData->slot;
+    ulong    lfunc = pciData->func;
+    uchar    t2CFA, t2CF8;
+    ulong    t1CF8, t1CFC;
 
-    ASC_ASSERT(asc_dvc->drv_ptr != 0);
-    boardp = (asc_board_t *) asc_dvc->drv_ptr;
+    ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
+        pciData->type, lbus, lslot, lfunc);
 
-    iop_base = asc_dvc->iop_base;
-    int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
+    /*
+     * Check type of configuration mechanism.
+     */
+    if (pciData->type == 2) {
+        /*
+         * Save registers to be restored later.
+         */
+        t2CFA = inp(0xCFA);    /* save PCI bus register */
+        t2CF8 = inp(0xCF8);    /* save config space enable register */
 
-    halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
-    halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
-    target_ix = AscReadLramByte(iop_base,
-                   (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
-    q_cntl = AscReadLramByte(iop_base,
-                        (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
-    tid_no = ASC_TIX_TO_TID(target_ix);
-    target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
-    if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+        /*
+         * Write the bus and enable registers.
+         */
+        /* set for type 1 cycle, if needed */
+        outp(0xCFA, pciData->bus);
+        /* set the function number */
+        outp(0xCF8, 0x10 | (pciData->func << 1)) ;
 
-        asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
+        /*
+         * Read the configuration space type 2 locations.
+         */
+        tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset));
+
+        outp(0xCFA, t2CFA);    /* save PCI bus register */
+        outp(0xCF8, t2CF8);    /* save config space enable register */
     } else {
-        asyn_sdtr = 0;
-    }
-    if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
-        if (asc_dvc->pci_fix_asyn_xfer & target_id) {
-            AscSetChipSDTR(iop_base, 0, tid_no);
-            boardp->sdtr_data[tid_no] = 0;
-        }
-        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-        return (0);
-    } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
-        if (asc_dvc->pci_fix_asyn_xfer & target_id) {
-            AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
-            boardp->sdtr_data[tid_no] = asyn_sdtr;
-        }
-        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-        return (0);
-    } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
+        /*
+         * Type 1 or 3 configuration mechanism.
+         *
+         * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
+         */
+        t1CF8 = inpl(0xCF8);
+        t1CFC = inpl(0xCFC);
 
-        AscMemWordCopyFromLram(iop_base,
-                               ASCV_MSGIN_BEG,
-                               (ushort *) & ext_msg,
-                               (ushort) (sizeof (EXT_MSG) >> 1));
+        /*
+         * enable <31>, bus = <23:16>, slot = <15:11>,
+         * func = <10:8>, reg = <7:2>
+         */
+        address = (ulong) ((lbus << 16) | (lslot << 11) |
+            (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
 
-        if (ext_msg.msg_type == MS_EXTEND &&
-            ext_msg.msg_req == MS_SDTR_CODE &&
-            ext_msg.msg_len == MS_SDTR_LEN) {
-            sdtr_accept = TRUE;
-            if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
+        /*
+         * Write out the address to CONFIG_ADDRESS.
+         */
+        outpl(0xCF8, address);
 
-                sdtr_accept = FALSE;
-                ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
-            }
-            if ((ext_msg.xfer_period <
-                 asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) ||
-                (ext_msg.xfer_period >
-                 asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) {
-                sdtr_accept = FALSE;
-                ext_msg.xfer_period =
-                    asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index];
-            }
-            if (sdtr_accept) {
-                sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
-                                           ext_msg.req_ack_offset);
-                if ((sdtr_data == 0xFF)) {
+        /*
+         * Read in word from CONFIG_DATA.
+         */
+        tmp = (ushort) ((inpl(0xCFC) >>
+                 ((pciData->offset & 2) * 8)) & 0xFFFF);
 
-                    q_cntl |= QC_MSG_OUT;
-                    asc_dvc->init_sdtr &= ~target_id;
-                    asc_dvc->sdtr_done &= ~target_id;
-                    AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
-                    boardp->sdtr_data[tid_no] = asyn_sdtr;
-                }
-            }
-            if (ext_msg.req_ack_offset == 0) {
+        /*
+         * Restore registers.
+         */
+        outpl(0xCF8, t1CF8);
+        outpl(0xCFC, t1CFC);
+    }
+    ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
+    return tmp;
+}
 
-                q_cntl &= ~QC_MSG_OUT;
-                asc_dvc->init_sdtr &= ~target_id;
-                asc_dvc->sdtr_done &= ~target_id;
-                AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
-            } else {
-                if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
+/*
+ * Reads a byte from the PCI configuration space.
+ *
+ * The configuration mechanism is checked for the correct access method.
+ */
+ASC_INITFUNC(
+STATIC uchar
+asc_get_cfg_byte(PCI_DATA *pciData)
+)
+{
+    uchar tmp;
+    ulong address;
+    ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
+    uchar t2CFA, t2CF8;
+    ulong t1CF8, t1CFC;
 
-                    q_cntl &= ~QC_MSG_OUT;
-                    asc_dvc->sdtr_done |= target_id;
-                    asc_dvc->init_sdtr |= target_id;
-                    asc_dvc->pci_fix_asyn_xfer &= ~target_id;
-                    sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
-                                               ext_msg.req_ack_offset);
-                    AscSetChipSDTR(iop_base, sdtr_data, tid_no);
-                    boardp->sdtr_data[tid_no] = sdtr_data;
-                } else {
+    ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
 
-                    q_cntl |= QC_MSG_OUT;
-                    AscMsgOutSDTR(asc_dvc,
-                                  ext_msg.xfer_period,
-                                  ext_msg.req_ack_offset);
-                    asc_dvc->pci_fix_asyn_xfer &= ~target_id;
-                    sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
-                                               ext_msg.req_ack_offset);
-                    AscSetChipSDTR(iop_base, sdtr_data, tid_no);
-                    boardp->sdtr_data[tid_no] = sdtr_data;
-                    asc_dvc->sdtr_done |= target_id;
-                    asc_dvc->init_sdtr |= target_id;
-                }
-            }
+    /*
+     * Check type of configuration mechanism.
+     */
+    if (pciData->type == 2) {
+        /*
+         * Save registers to be restored later.
+         */
+        t2CFA = inp(0xCFA);    /* save PCI bus register */
+        t2CF8 = inp(0xCF8);    /* save config space enable register */
 
-            AscWriteLramByte(iop_base,
-                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
-                             q_cntl);
-            AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-            return (0);
-        } else if (ext_msg.msg_type == MS_EXTEND &&
-                   ext_msg.msg_req == MS_WDTR_CODE &&
-                   ext_msg.msg_len == MS_WDTR_LEN) {
+        /*
+         * Write the bus and enable registers.
+         */
+        /* set for type 1 cycle, if needed */
+        outp(0xCFA, pciData->bus);
+        /* set the function number */
+        outp(0xCF8, 0x10 | (pciData->func << 1));
 
-            ext_msg.wdtr_width = 0;
-            AscMemWordCopyToLram(iop_base,
-                                 ASCV_MSGOUT_BEG,
-                                 (ushort *) & ext_msg,
-                                 (ushort) (sizeof (EXT_MSG) >> 1));
-            q_cntl |= QC_MSG_OUT;
-            AscWriteLramByte(iop_base,
-                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
-                             q_cntl);
-            AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-            return (0);
-        } else {
+        /*
+         * Read configuration space type 2 locations.
+         */
+        tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
 
-            ext_msg.msg_type = M1_MSG_REJECT;
-            AscMemWordCopyToLram(iop_base,
-                                 ASCV_MSGOUT_BEG,
-                                 (ushort *) & ext_msg,
-                                 (ushort) (sizeof (EXT_MSG) >> 1));
-            q_cntl |= QC_MSG_OUT;
-            AscWriteLramByte(iop_base,
-                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
-                             q_cntl);
-            AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-            return (0);
-        }
-    } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
+        /*
+         * Restore registers.
+         */
+        outp(0xCF8, t2CF8);    /* restore the enable register */
+        outp(0xCFA, t2CFA);    /* restore PCI bus register */
+    } else {
+        /*
+         * Type 1 or 3 configuration mechanism.
+         *
+         * Save CONFIG_ADDRESS and CONFIG_DATA register values.
+         */
+        t1CF8 = inpl(0xCF8);
+        t1CFC = inpl(0xCFC);
 
-        q_cntl |= QC_REQ_SENSE;
+        /*
+         * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
+         * reg = <7:2>
+         */
+        address = (ulong) ((lbus << 16) | (lslot << 11) |
+            (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
 
-#if CC_CHK_COND_REDO_SDTR
-        if ((asc_dvc->init_sdtr & target_id) != 0) {
+        /*
+         * Write out address to CONFIG_ADDRESS.
+         */
+        outpl(0xCF8, address);
 
-            asc_dvc->sdtr_done &= ~target_id;
+        /*
+         * Read in word from CONFIG_DATA.
+         */
+        tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
 
-            sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
-            q_cntl |= QC_MSG_OUT;
-            AscMsgOutSDTR(asc_dvc,
-                          asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
-                           (uchar) (asc_dvc->max_sdtr_index - 1)],
-                          (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
-        }
-#endif
+        /*
+         * Restore registers.
+         */
+        outpl(0xCF8, t1CF8);
+        outpl(0xCFC, t1CFC);
+    }
+    ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
+    return tmp;
+}
 
-        AscWriteLramByte(iop_base,
-                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
-                         q_cntl);
+/*
+ * Write a byte to the PCI configuration space.
+ */
+ASC_INITFUNC(
+STATIC void
+asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data)
+)
+{
+    ulong tmpl;
+    ulong address;
+    ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
+    uchar t2CFA, t2CF8;
+    ulong t1CF8, t1CFC;
 
-        tag_code = AscReadLramByte(iop_base,
-                    (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
-        tag_code &= 0xDC;
-        if (
-               (asc_dvc->pci_fix_asyn_xfer & target_id)
-               && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
-) {
+    ASC_DBG2(4, "asc_put_cfg_byte: type: %d, byte_data %x\n",
+        pciData->type, byte_data);
 
-            tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
-                         | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
+    /*
+     * Check type of configuration mechanism.
+     */
+    if (pciData->type == 2) {
 
-        }
-        AscWriteLramByte(iop_base,
-                     (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
-                         tag_code);
+        /*
+         * Save registers to be restored later.
+         */
+        t2CFA = inp(0xCFA);    /* save PCI bus register */
+        t2CF8 = inp(0xCF8);    /* save config space enable register */
 
-        q_status = AscReadLramByte(iop_base,
-                      (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
-        q_status |= (QS_READY | QS_BUSY);
-        AscWriteLramByte(iop_base,
-                       (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
-                         q_status);
+        /*
+         * Write bus and enable registers.
+         */
+        outp(0xCFA, pciData->bus);
 
-        scsi_busy = AscReadLramByte(iop_base,
-                                    (ushort) ASCV_SCSIBUSY_B);
-        scsi_busy &= ~target_id;
-        AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
+        /*
+         * Set the function number.
+         */
+        outp(0xCF8, 0x10 | (pciData->func << 1));
 
-        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-        return (0);
-    } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
+        /*
+         * Write the configuration space type 2 locations.
+         */
+        outp(0xC000 | ((pciData->slot << 8) + pciData->offset), byte_data);
 
-        AscMemWordCopyFromLram(iop_base,
-                               ASCV_MSGOUT_BEG,
-                               (ushort *) & out_msg,
-                               (ushort) (sizeof (EXT_MSG) >> 1));
+        /*
+         * Restore registers.
+         */
+        outp(0xCF8, t2CF8);    /* restore the enable register */
+        outp(0xCFA, t2CFA);    /* restore PCI bus register    */
+    } else {
 
-        if ((out_msg.msg_type == MS_EXTEND) &&
-            (out_msg.msg_len == MS_SDTR_LEN) &&
-            (out_msg.msg_req == MS_SDTR_CODE)) {
+        /*
+         * Type 1 or 3 configuration mechanism.
+         *
+         * Save the CONFIG_ADDRESS and CONFIG_DATA register values.
+         */
+        t1CF8 = inpl(0xCF8);
+        t1CFC = inpl(0xCFC);
 
-            asc_dvc->init_sdtr &= ~target_id;
-            asc_dvc->sdtr_done &= ~target_id;
-            AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
-            boardp->sdtr_data[tid_no] = asyn_sdtr;
+        /*
+         * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
+         * reg = <7:2>
+         */
+        address = (ulong) ((lbus << 16) | (lslot << 11) | (lfunc << 8) |
+                (pciData->offset & 0xFC) | 0x80000000L);
+        /*
+         * Write out address to CONFIG_ADDRESS.
+         */
+        outpl(0xCF8, address);
+
+        /*
+         * Write double word to CONFIG_DATA preserving the bytes
+         * in the double not written.
+         */
+        tmpl = inpl(0xCFC) & ~(0xFF << ((pciData->offset & 3) * 8));
+        outpl(0xCFC, tmpl | (byte_data << ((pciData->offset & 3) * 8)));
+
+        /*
+         * Restore registers.
+         */
+        outpl(0xCF8, t1CF8);
+        outpl(0xCFC, t1CFC);
+    }
+    ASC_DBG(4, "asc_put_cfg_byte: end\n");
+}
+
+/*
+ * Add a 'REQP' to the end of specified queue. Set 'tidmask'
+ * to indicate a command is queued for the device.
+ *
+ * 'flag' may be either ASC_FRONT or ASC_BACK.
+ *
+ * 'REQPNEXT(reqp)' returns reqp's next pointer.
+ */
+STATIC void
+asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
+{
+    int        tid;
+
+    ASC_DBG3(3, "asc_enqueue: ascq %x, reqp %x, flag %d\n",
+        (unsigned) ascq, (unsigned) reqp, flag);
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    ASC_ASSERT(reqp != NULL);
+    ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
+    tid = REQPTID(reqp);
+    ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
+    if (flag == ASC_FRONT) {
+        REQPNEXT(reqp) = ascq->q_first[tid];
+        ascq->q_first[tid] = reqp;
+        /* If the queue was empty, set the last pointer. */
+        if (ascq->q_last[tid] == NULL) {
+            ascq->q_last[tid] = reqp;
         }
-        q_cntl &= ~QC_MSG_OUT;
-        AscWriteLramByte(iop_base,
-                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
-                         q_cntl);
-        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-        return (0);
-    } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
+    } else { /* ASC_BACK */
+        if (ascq->q_last[tid] != NULL) {
+            REQPNEXT(ascq->q_last[tid]) = reqp;
+        }
+        ascq->q_last[tid] = reqp;
+        REQPNEXT(reqp) = NULL;
+        /* If the queue was empty, set the first pointer. */
+        if (ascq->q_first[tid] == NULL) {
+            ascq->q_first[tid] = reqp;
+        }
+    }
+    /* The queue has at least one entry, set its bit. */
+    ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid);
+#ifdef ADVANSYS_STATS
+    /* Maintain request queue statistics. */
+    ascq->q_tot_cnt[tid]++;
+    ascq->q_cur_cnt[tid]++;
+    if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
+        ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
+        ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n",
+            tid, ascq->q_max_cnt[tid]);
+    }
+    REQPTIME(reqp) = REQTIMESTAMP();
+#endif /* ADVANSYS_STATS */
+    ASC_DBG1(3, "asc_enqueue: reqp %x\n", (unsigned) reqp);
+    return;
+}
 
-        scsi_status = AscReadLramByte(iop_base,
-          (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
-        cur_dvc_qng = AscReadLramByte(iop_base,
-                     (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
-        if ((cur_dvc_qng > 0) &&
-            (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
+/*
+ * Return first queued 'REQP' on the specified queue for
+ * the specified target device. Clear the 'tidmask' bit for
+ * the device if no more commands are left queued for it.
+ *
+ * 'REQPNEXT(reqp)' returns reqp's next pointer.
+ */
+STATIC REQP
+asc_dequeue(asc_queue_t *ascq, int tid)
+{
+    REQP    reqp;
 
-            scsi_busy = AscReadLramByte(iop_base,
-                                        (ushort) ASCV_SCSIBUSY_B);
-            scsi_busy |= target_id;
-            AscWriteLramByte(iop_base,
-                             (ushort) ASCV_SCSIBUSY_B, scsi_busy);
-            asc_dvc->queue_full_or_busy |= target_id;
+    ASC_DBG2(3, "asc_dequeue: ascq %x, tid %d\n", (unsigned) ascq, tid);
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
+    if ((reqp = ascq->q_first[tid]) != NULL) {
+        ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
+        ascq->q_first[tid] = REQPNEXT(reqp);
+        /* If the queue is empty, clear its bit and the last pointer. */
+        if (ascq->q_first[tid] == NULL) {
+            ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
+            ASC_ASSERT(ascq->q_last[tid] == reqp);
+            ascq->q_last[tid] = NULL;
+        }
+#ifdef ADVANSYS_STATS
+        /* Maintain request queue statistics. */
+        ascq->q_cur_cnt[tid]--;
+        ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
+        REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
+#endif /* ADVANSYS_STATS */
+    }
+    ASC_DBG1(3, "asc_dequeue: reqp %x\n", (unsigned) reqp);
+    return reqp;
+}
 
-            if (scsi_status == SS_QUEUE_FULL) {
-                if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
-                    cur_dvc_qng -= 1;
-                    asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
+/*
+ * Return a pointer to a singly linked list of all the requests queued
+ * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'.
+ *
+ * If 'lastpp' is not NULL, '*lastpp' will be set to point to the 
+ * the last request returned in the singly linked list.
+ *
+ * 'tid' should either be a valid target id or if it is ASC_TID_ALL,
+ * then all queued requests are concatenated into one list and
+ * returned.
+ *
+ * Note: If 'lastpp' is used to append a new list to the end of
+ * an old list, only change the old list last pointer if '*lastpp'
+ * (or the function return value) is not NULL, i.e. use a temporary
+ * variable for 'lastpp' and check its value after the function return
+ * before assigning it to the list last pointer.
+ *
+ * Unfortunately collecting queuing time statistics adds overhead to
+ * the function that isn't inherent to the function's algorithm.
+ */
+STATIC REQP
+asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
+{
+    REQP    firstp, lastp;
+    int     i;
 
-                    AscWriteLramByte(iop_base,
-                          (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG +
-                           (ushort) tid_no),
-                          cur_dvc_qng);
+    ASC_DBG2(3, "asc_dequeue_list: ascq %x, tid %d\n", (unsigned) ascq, tid);
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
 
-                    /*
-                     * Set the device queue depth to the number of
-                     * active requests when the QUEUE FULL condition
-                     * was encountered.
-                     */
-                    boardp->queue_full |= target_id;
-                    boardp->queue_full_cnt[tid_no] = cur_dvc_qng;
-#if ASC_QUEUE_FLOW_CONTROL
-                    if (boardp->device[tid_no]->queue_curr_depth >
-                        cur_dvc_qng) {
-                        boardp->device[tid_no]->queue_curr_depth =
-                            cur_dvc_qng;
-                    }
-#endif /* ASC_QUEUE_FLOW_CONTROL */
+    /*
+     * If 'tid' is not ASC_TID_ALL, return requests only for
+     * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all
+     * requests for all tids.
+     */
+    if (tid != ASC_TID_ALL) {
+        /* Return all requests for the specified 'tid'. */
+        if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) {
+            /* List is empty; Set first and last return pointers to NULL. */
+            firstp = lastp = NULL;
+        } else {
+            firstp = ascq->q_first[tid];
+            lastp = ascq->q_last[tid];
+            ascq->q_first[tid] = ascq->q_last[tid] = NULL;
+            ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
+#ifdef ADVANSYS_STATS
+            {
+                REQP reqp;
+                ascq->q_cur_cnt[tid] = 0;
+                for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
+                    REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid);
                 }
             }
+#endif /* ADVANSYS_STATS */
         }
-        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-        return (0);
+    } else {
+        /* Return all requests for all tids. */
+        firstp = lastp = NULL;
+        for (i = 0; i <= ADV_MAX_TID; i++) {
+            if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) {
+                if (firstp == NULL) {
+                    firstp = ascq->q_first[i];
+                    lastp = ascq->q_last[i];
+                } else {
+                    ASC_ASSERT(lastp != NULL);
+                    REQPNEXT(lastp) = ascq->q_first[i];
+                    lastp = ascq->q_last[i];
+                }
+                ascq->q_first[i] = ascq->q_last[i] = NULL;
+                ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i);
+#ifdef ADVANSYS_STATS
+                ascq->q_cur_cnt[i] = 0;
+#endif /* ADVANSYS_STATS */
+            }
+        }
+#ifdef ADVANSYS_STATS
+        {
+            REQP reqp;
+            for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
+                REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target);
+            }
+        }
+#endif /* ADVANSYS_STATS */
     }
-    return (0);
+    if (lastpp) {
+        *lastpp = lastp;
+    }
+    ASC_DBG1(3, "asc_dequeue_list: firstp %x\n", (unsigned) firstp);
+    return firstp;
 }
 
-STATIC uchar
-_AscCopyLramScsiDoneQ(
-                         PortAddr iop_base,
-                         ushort q_addr,
-                         REG ASC_QDONE_INFO * scsiq,
-                         ulong max_dma_count
-)
+/*
+ * Remove the specified 'REQP' from the specified queue for
+ * the specified target device. Clear the 'tidmask' bit for the
+ * device if no more commands are left queued for it.
+ *
+ * 'REQPNEXT(reqp)' returns reqp's the next pointer.
+ *
+ * Return ASC_TRUE if the command was found and removed,
+ * otherwise return ASC_FALSE.
+ */
+STATIC int
+asc_rmqueue(asc_queue_t *ascq, REQP reqp)
 {
-    ushort              _val;
-    uchar               sg_queue_cnt;
-    DvcGetQinfo(iop_base,
-                (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
-                (ushort *) scsiq,
-              (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
-#if !CC_LITTLE_ENDIAN_HOST
-    AscAdjEndianQDoneInfo(scsiq);
-#endif
-    _val = AscReadLramWord(iop_base,
-                           (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
-    scsiq->q_status = (uchar) _val;
-    scsiq->q_no = (uchar) (_val >> 8);
-    _val = AscReadLramWord(iop_base,
-                           (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
-    scsiq->cntl = (uchar) _val;
-    sg_queue_cnt = (uchar) (_val >> 8);
-    _val = AscReadLramWord(iop_base,
-                        (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
-    scsiq->sense_len = (uchar) _val;
-    scsiq->extra_bytes = (uchar) (_val >> 8);
-    scsiq->remain_bytes = AscReadLramWord(iop_base,
-                 (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
-    scsiq->remain_bytes &= max_dma_count;
-    return (sg_queue_cnt);
-}
+    REQP        currp, prevp;
+    int         tid;
+    int         ret = ASC_FALSE;
 
-STATIC int
-AscIsrQDone(
-               REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-{
-    uchar               next_qp;
-    uchar               n_q_used;
-    uchar               sg_list_qp;
-    uchar               sg_queue_cnt;
-    uchar               q_cnt;
-    uchar               done_q_tail;
-    uchar               tid_no;
-    ASC_SCSI_BIT_ID_TYPE scsi_busy;
-    ASC_SCSI_BIT_ID_TYPE target_id;
-    PortAddr            iop_base;
-    ushort              q_addr;
-    ushort              sg_q_addr;
-    uchar               cur_target_qng;
-    ASC_QDONE_INFO      scsiq_buf;
-    REG ASC_QDONE_INFO *scsiq;
-    int                 false_overrun;
-    ASC_ISR_CALLBACK    asc_isr_callback;
-    iop_base = asc_dvc->iop_base;
-    asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
-    n_q_used = 1;
-    scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
-    done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
-    q_addr = ASC_QNO_TO_QADDR(done_q_tail);
-    next_qp = AscReadLramByte(iop_base,
-                              (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
-    if (next_qp != ASC_QLINK_END) {
-        AscPutVarDoneQTail(iop_base, next_qp);
-        q_addr = ASC_QNO_TO_QADDR(next_qp);
-        sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
-            asc_dvc->max_dma_count);
-        AscWriteLramByte(iop_base,
-                         (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
-             (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
-        tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
-        target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
-        if ((scsiq->cntl & QC_SG_HEAD) != 0) {
-            sg_q_addr = q_addr;
-            sg_list_qp = next_qp;
-            for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
-                sg_list_qp = AscReadLramByte(iop_base,
-                           (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
-                sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
-                if (sg_list_qp == ASC_QLINK_END) {
-                    AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
-                    scsiq->d3.done_stat = QD_WITH_ERROR;
-                    scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
-                    goto FATAL_ERR_QDONE;
-                }
-                AscWriteLramByte(iop_base,
-                         (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
-                                 QS_FREE);
-            }
-            n_q_used = sg_queue_cnt + 1;
-            AscPutVarDoneQTail(iop_base, sg_list_qp);
-        }
-        if (asc_dvc->queue_full_or_busy & target_id) {
-            cur_target_qng = AscReadLramByte(iop_base,
-            (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
-            if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
-                scsi_busy = AscReadLramByte(iop_base,
-                                            (ushort) ASCV_SCSIBUSY_B);
-                scsi_busy &= ~target_id;
-                AscWriteLramByte(iop_base,
-                                 (ushort) ASCV_SCSIBUSY_B, scsi_busy);
-                asc_dvc->queue_full_or_busy &= ~target_id;
-            }
-        }
-        if (asc_dvc->cur_total_qng >= n_q_used) {
-            asc_dvc->cur_total_qng -= n_q_used;
-            if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
-                asc_dvc->cur_dvc_qng[tid_no]--;
-            }
-        } else {
-            AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
-            scsiq->d3.done_stat = QD_WITH_ERROR;
-            goto FATAL_ERR_QDONE;
+    ASC_DBG2(3, "asc_rmqueue: ascq %x, reqp %x\n",
+        (unsigned) ascq, (unsigned) reqp);
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    ASC_ASSERT(reqp != NULL);
+
+    tid = REQPTID(reqp);
+    ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
+
+    /*
+     * Handle the common case of 'reqp' being the first
+     * entry on the queue.
+     */
+    if (reqp == ascq->q_first[tid]) {
+        ret = ASC_TRUE;
+        ascq->q_first[tid] = REQPNEXT(reqp);
+        /* If the queue is now empty, clear its bit and the last pointer. */
+        if (ascq->q_first[tid] == NULL) {
+            ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid);
+            ASC_ASSERT(ascq->q_last[tid] == reqp);
+            ascq->q_last[tid] = NULL;
         }
-        if ((scsiq->d2.srb_ptr == 0UL) ||
-            ((scsiq->q_status & QS_ABORTED) != 0)) {
-            return (0x11);
-        } else if (scsiq->q_status == QS_DONE) {
-            false_overrun = FALSE;
-            if (scsiq->extra_bytes != 0) {
-                scsiq->remain_bytes += (ulong) scsiq->extra_bytes;
-            }
-            if (scsiq->d3.done_stat == QD_WITH_ERROR) {
-                if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) {
-                    if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
-                        scsiq->d3.done_stat = QD_NO_ERROR;
-                        scsiq->d3.host_stat = QHSTA_NO_ERROR;
-                    } else if (false_overrun) {
-                        scsiq->d3.done_stat = QD_NO_ERROR;
-                        scsiq->d3.host_stat = QHSTA_NO_ERROR;
-                    }
-                } else if (scsiq->d3.host_stat ==
-                           QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
-                    AscStopChip(iop_base);
-                    AscSetChipControl(iop_base,
-                        (uchar) (CC_SCSI_RESET | CC_HALT));
-                    DvcDelayNanoSecond(asc_dvc, 30000);
-                    AscSetChipControl(iop_base, CC_HALT);
-                    AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
-                    AscSetChipStatus(iop_base, 0);
-                    AscSetChipControl(iop_base, 0);
-                }
-            }
-#if CC_CLEAR_LRAM_SRB_PTR
-            AscWriteLramDWord(iop_base,
-                            (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
-                              asc_dvc->int_count);
-#endif
-            if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
-                (*asc_isr_callback) (asc_dvc, scsiq);
-            } else {
-                if ((AscReadLramByte(iop_base,
-                          (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
-                     SCSICMD_StartStopUnit)) {
-                    asc_dvc->unit_not_ready &= ~target_id;
-                    if (scsiq->d3.done_stat != QD_NO_ERROR) {
-                        asc_dvc->start_motor &= ~target_id;
-                    }
+    } else if (ascq->q_first[tid] != NULL) {
+        ASC_ASSERT(ascq->q_last[tid] != NULL);
+        /*
+         * Because the case of 'reqp' being the first entry has been
+         * handled above and it is known the queue is not empty, if
+         * 'reqp' is found on the queue it is guaranteed the queue will
+         * not become empty and that 'q_first[tid]' will not be changed.
+         *
+         * Set 'prevp' to the first entry, 'currp' to the second entry,
+         * and search for 'reqp'.
+         */
+        for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp);
+             currp; prevp = currp, currp = REQPNEXT(currp)) {
+            if (currp == reqp) {
+                ret = ASC_TRUE;
+                REQPNEXT(prevp) = REQPNEXT(currp);
+                REQPNEXT(reqp) = NULL;
+                if (ascq->q_last[tid] == reqp) {
+                    ascq->q_last[tid] = prevp;
                 }
+                break;
             }
-            return (1);
-        } else {
-            AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
-          FATAL_ERR_QDONE:
-            if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
-                (*asc_isr_callback) (asc_dvc, scsiq);
-            }
-            return (0x80);
         }
     }
-    return (0);
+#ifdef ADVANSYS_STATS
+    /* Maintain request queue statistics. */
+    if (ret == ASC_TRUE) {
+        ascq->q_cur_cnt[tid]--;
+        REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
+    }
+    ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
+#endif /* ADVANSYS_STATS */
+    ASC_DBG2(3, "asc_rmqueue: reqp %x, ret %d\n", (unsigned) reqp, ret);
+    return ret;
 }
 
+/*
+ * If the specified 'REQP' is queued on the specified queue for
+ * the specified target device, return ASC_TRUE.
+ */
 STATIC int
-AscISR(
-          REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+asc_isqueued(asc_queue_t *ascq, REQP reqp)
 {
-    ASC_CS_TYPE         chipstat;
-    PortAddr            iop_base;
-    ushort              saved_ram_addr;
-    uchar               ctrl_reg;
-    uchar               saved_ctrl_reg;
-    int                 int_pending;
-    int                 status;
-    uchar               host_flag;
-    iop_base = asc_dvc->iop_base;
-    int_pending = FALSE;
-    if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0)
-        || (asc_dvc->isr_callback == 0)
-) {
-        return (ERR);
-    }
-    if (asc_dvc->in_critical_cnt != 0) {
-        AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
-        return (ERR);
-    }
-    if (asc_dvc->is_in_int) {
-        AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
-        return (ERR);
+    REQP        treqp;
+    int            tid;
+    int            ret = ASC_FALSE;
+
+    ASC_DBG2(3, "asc_isqueued: ascq %x, reqp %x\n",
+        (unsigned) ascq, (unsigned) reqp);
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    ASC_ASSERT(reqp != NULL);
+
+    tid = REQPTID(reqp);
+    ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
+
+    for (treqp = ascq->q_first[tid]; treqp; treqp = REQPNEXT(treqp)) {
+        ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
+        if (treqp == reqp) {
+            ret = ASC_TRUE;
+            break;
+        }
     }
-    asc_dvc->is_in_int = TRUE;
-    ctrl_reg = AscGetChipControl(iop_base);
-    saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
-                                   CC_SINGLE_STEP | CC_DIAG | CC_TEST));
-    chipstat = AscGetChipStatus(iop_base);
-    if (chipstat & CSW_SCSI_RESET_LATCH) {
-        if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
-            int_pending = TRUE;
-            asc_dvc->sdtr_done = 0;
-            saved_ctrl_reg &= (uchar) (~CC_HALT);
-            while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
-            AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
-            AscSetChipControl(iop_base, CC_HALT);
-            AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
-            AscSetChipStatus(iop_base, 0);
-            chipstat = AscGetChipStatus(iop_base);
-        }
-    }
-    saved_ram_addr = AscGetChipLramAddr(iop_base);
-    host_flag = AscReadLramByte(iop_base,
-        ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR);
-    AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
-                     (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
-#if CC_ASCISR_CHECK_INT_PENDING
-    if ((chipstat & CSW_INT_PENDING)
-        || (int_pending)
-) {
-        AscAckInterrupt(iop_base);
-#endif
-        int_pending = TRUE;
-        if ((chipstat & CSW_HALTED) &&
-            (ctrl_reg & CC_SINGLE_STEP)) {
-            if (AscIsrChipHalted(asc_dvc) == ERR) {
-                goto ISR_REPORT_QDONE_FATAL_ERROR;
-            } else {
-                saved_ctrl_reg &= (uchar) (~CC_HALT);
-            }
-        } else {
-          ISR_REPORT_QDONE_FATAL_ERROR:
-            if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
-                while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
+    ASC_DBG1(3, "asc_isqueued: ret %x\n", ret);
+    return ret;
+}
+
+/*
+ * Execute as many queued requests as possible for the specified queue.
+ *
+ * Calls asc_execute_scsi_cmnd() to execute a REQP/Scsi_Cmnd.
+ */
+STATIC void
+asc_execute_queue(asc_queue_t *ascq)
+{
+    ADV_SCSI_BIT_ID_TYPE    scan_tidmask;
+    REQP                    reqp;
+    int                     i;
+
+    ASC_DBG1(1, "asc_execute_queue: ascq %x\n", (unsigned) ascq);
+    ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+    /*
+     * Execute queued commands for devices attached to
+     * the current board in round-robin fashion.
+     */
+    scan_tidmask = ascq->q_tidmask;
+    do {
+        for (i = 0; i <= ADV_MAX_TID; i++) {
+            if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) {
+                if ((reqp = asc_dequeue(ascq, i)) == NULL) {
+                    scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
+                } else if (asc_execute_scsi_cmnd((Scsi_Cmnd *) reqp)
+                            == ASC_BUSY) {
+                    scan_tidmask &= ~ADV_TID_TO_TIDMASK(i);
+                    /* Put the request back at front of the list. */
+                    asc_enqueue(ascq, reqp, ASC_FRONT);
                 }
-            } else {
-                do {
-                    if ((status = AscIsrQDone(asc_dvc)) == 1) {
-                        break;
-                    }
-                } while (status == 0x11);
             }
-            if ((status & 0x80) != 0)
-                int_pending = ERR;
         }
-#if CC_ASCISR_CHECK_INT_PENDING
+    } while (scan_tidmask);
+    return;
+}
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+/*
+ * asc_prt_board_devices()
+ *
+ * Print driver information for devices attached to the board.
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
+STATIC int
+asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen)
+{
+    asc_board_t        *boardp;
+    int                leftlen;
+    int                totlen;
+    int                len;
+    int                chip_scsi_id;
+    int                i;
+
+    boardp = ASC_BOARDP(shp);
+    leftlen = cplen;
+    totlen = len = 0;
+
+    len = asc_prt_line(cp, leftlen,
+"\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no);
+    ASC_PRT_NEXT();
+
+    if (ASC_NARROW_BOARD(boardp)) {
+        chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
+    } else {
+        chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
+    }
+
+    len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
+            len = asc_prt_line(cp, leftlen, " %X,", i);
+            ASC_PRT_NEXT();
+        }
     }
-#endif
-    AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
-    AscSetChipLramAddr(iop_base, saved_ram_addr);
-    AscSetChipControl(iop_base, saved_ctrl_reg);
-    asc_dvc->is_in_int = FALSE;
-    return (int_pending);
+    len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
+    ASC_PRT_NEXT();
+
+    return totlen;
 }
 
+/*
+ * Display Wide Board BIOS Information.
+ */
 STATIC int
-AscScsiSetupCmdQ(
-                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                    REG ASC_SCSI_REQ_Q * scsiq,
-                    uchar * buf_addr,
-                    ulong buf_len
-)
+asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen)
 {
-    ulong               phy_addr;
-    scsiq->r1.cntl = 0;
-    scsiq->r1.sg_queue_cnt = 0;
-    scsiq->r1.q_no = 0;
-    scsiq->r1.extra_bytes = 0;
-    scsiq->r3.scsi_stat = 0;
-    scsiq->r3.scsi_msg = 0;
-    scsiq->r3.host_stat = 0;
-    scsiq->r3.done_stat = 0;
-    scsiq->r2.vm_id = 0;
-    scsiq->r1.data_cnt = buf_len;
-    scsiq->cdbptr = (uchar *) scsiq->cdb;
-    scsiq->sense_ptr = (uchar *) scsiq->sense ;
-    scsiq->r1.sense_len = ASC_MIN_SENSE_LEN ;
-    scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE;
-    scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ;
-    scsiq->r2.srb_ptr = (ulong) scsiq;
-    scsiq->r1.status = (uchar) QS_READY;
-    scsiq->r1.data_addr = 0L;
-    if (buf_len != 0L) {
-        if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
-                    (uchar *) buf_addr, scsiq->r1.data_cnt)) == 0L) {
-            return (ERR);
+    asc_board_t        *boardp;
+    int                leftlen;
+    int                totlen;
+    int                len;
+    int                upgrade = ASC_FALSE;
+    ushort             major, minor, letter;
+
+    boardp = ASC_BOARDP(shp);
+    leftlen = cplen;
+    totlen = len = 0;
+
+    len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
+    ASC_PRT_NEXT();
+
+    /*
+     * If the BIOS saved a valid signature, then fill in
+     * the BIOS code segment base address.
+     */
+    if (boardp->bios_signature != 0x55AA) {
+        len = asc_prt_line(cp, leftlen, "Pre-3.1\n");
+        ASC_PRT_NEXT();
+        upgrade = ASC_TRUE;
+    } else {
+        major = (boardp->bios_version >> 12) & 0xF;
+        minor = (boardp->bios_version >> 8) & 0xF;
+        letter = (boardp->bios_version & 0xFF);
+
+        len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
+            major, minor, letter >= 26 ? '?' : letter + 'A');
+        ASC_PRT_NEXT();
+
+        /* Current available ROM BIOS release is 3.1E. */
+        if (major < 3 || (major <= 3 && minor < 1) ||
+            (major <= 3 && minor <= 1 && letter < ('E'- 'A'))) {
+            upgrade = ASC_TRUE;
         }
-        scsiq->r1.data_addr = phy_addr;
     }
-    if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
-                       (uchar *) scsiq->sense_ptr,
-                       (ulong) scsiq->r1.sense_len)) == 0L) {
-        return (ERR);
+    if (upgrade == ASC_TRUE) {
+        len = asc_prt_line(cp, leftlen,
+"Newer version of ROM BIOS available: ftp://ftp.advansys.com/pub\n");
+            ASC_PRT_NEXT();
     }
-    scsiq->r1.sense_addr = phy_addr ;
-    return (0);
+
+    return totlen;
 }
 
-STATIC uchar _mcode_buf[] ASC_INITDATA =
-{
-    0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x79, 0x0D, 0x09, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x23, 0x00, 0x22, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
-    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x88, 0x00, 0x00, 0x00, 0x00,
-    0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
-    0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80,
-    0x08, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x32, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
-    0x4F, 0x00, 0xF5, 0x00, 0x32, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
-    0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00,
-    0x00, 0xA3, 0xD6, 0x00, 0x90, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xD8, 0x84, 0xD2, 0xC1,
-    0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE2, 0x01, 0x90, 0x97, 0xCE, 0x81, 0x00, 0x33,
-    0x02, 0x00, 0xAA, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0x02, 0x01, 0x4F, 0x00,
-    0x6E, 0x97, 0x07, 0xA6, 0x0C, 0x01, 0x00, 0x33, 0x03, 0x00, 0xAA, 0x88, 0x03, 0x03, 0x03, 0xDE,
-    0x00, 0x33, 0x05, 0x00, 0xAA, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60,
-    0x00, 0xA2, 0x80, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x2C, 0x01, 0x80, 0x81, 0x03, 0x03, 0x80, 0x63,
-    0xE2, 0x00, 0x07, 0xA6, 0x3C, 0x01, 0x00, 0x33, 0x04, 0x00, 0xAA, 0x88, 0x03, 0x07, 0x02, 0x01,
-    0x04, 0xCA, 0x0D, 0x23, 0x52, 0x98, 0x4D, 0x04, 0xF6, 0x84, 0x05, 0xD8, 0x0D, 0x23, 0x52, 0x98,
-    0xCD, 0x04, 0x15, 0x23, 0xE0, 0x88, 0xFB, 0x23, 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03,
-    0x06, 0xA3, 0x6A, 0x01, 0x00, 0x33, 0x0A, 0x00, 0xAA, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x76, 0x01,
-    0x00, 0x33, 0x0B, 0x00, 0xAA, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xAA, 0x88,
-    0x50, 0x04, 0x90, 0x81, 0x06, 0xAB, 0x8A, 0x01, 0x90, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x9A, 0x01,
-    0x50, 0x00, 0x00, 0xA3, 0x44, 0x01, 0x00, 0x05, 0x84, 0x81, 0x30, 0x97, 0x02, 0x01, 0x05, 0xC6,
-    0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xC6, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01,
-    0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xBC, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D,
-    0x00, 0x33, 0x1B, 0x00, 0xAA, 0x88, 0x06, 0x23, 0x52, 0x98, 0xCD, 0x04, 0xD8, 0x84, 0x06, 0x01,
-    0x00, 0xA2, 0xDC, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE2, 0x01, 0xD8, 0x84, 0x80, 0x23, 0xA0, 0x01,
-    0xD8, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x08, 0x02, 0x04, 0x01, 0x0C, 0xDE,
-    0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x6E, 0x97, 0x04, 0x82, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
-    0x4F, 0x00, 0x4C, 0x97, 0x48, 0x04, 0x84, 0x80, 0xDA, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0,
-    0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x67, 0xEB,
-    0x11, 0x23, 0xE0, 0x88, 0xEE, 0x97, 0xF4, 0x80, 0x80, 0x73, 0x80, 0x77, 0x06, 0xA6, 0x36, 0x02,
-    0x00, 0x33, 0x31, 0x00, 0xAA, 0x88, 0x04, 0x01, 0x03, 0xD8, 0x9C, 0x98, 0x44, 0x96, 0x48, 0x82,
-    0xD4, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x72, 0x02, 0x07, 0xA6,
-    0x60, 0x02, 0x06, 0xA6, 0x64, 0x02, 0x03, 0xA6, 0x68, 0x02, 0x00, 0x33, 0x10, 0x00, 0xAA, 0x88,
-    0x6E, 0x95, 0x4A, 0x82, 0x3A, 0x96, 0x4A, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01,
-    0x2E, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04,
-    0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B,
-    0x1C, 0x01, 0x02, 0xA6, 0xB0, 0x02, 0x07, 0xA6, 0x60, 0x02, 0x06, 0xA6, 0x64, 0x02, 0x03, 0xA6,
-    0x12, 0x04, 0x01, 0xA6, 0xBA, 0x02, 0x00, 0xA6, 0xBA, 0x02, 0x00, 0x33, 0x12, 0x00, 0xAA, 0x88,
-    0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x92, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC,
-    0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38,
-    0x00, 0x3F, 0x00, 0x00, 0xF0, 0x82, 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE8, 0x02, 0x04, 0x01,
-    0x98, 0xC8, 0x00, 0x33, 0x1F, 0x00, 0xAA, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D,
-    0x68, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x1A, 0x03, 0x00, 0xA6, 0x1A, 0x03, 0x07, 0xA6, 0x12, 0x03,
-    0x06, 0xA6, 0x16, 0x03, 0x03, 0xA6, 0x12, 0x04, 0x02, 0xA6, 0x72, 0x02, 0x00, 0x33, 0x33, 0x00,
-    0xAA, 0x88, 0x6E, 0x95, 0xF4, 0x82, 0x3A, 0x96, 0xF4, 0x82, 0x6C, 0x98, 0x80, 0x42, 0x68, 0x98,
-    0x60, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x5A, 0x03, 0x00, 0x43,
-    0x87, 0x01, 0x05, 0x05, 0x70, 0x98, 0x68, 0x98, 0x00, 0xA6, 0x1C, 0x03, 0x07, 0xA6, 0x52, 0x03,
-    0x03, 0xA6, 0x2E, 0x04, 0x06, 0xA6, 0x56, 0x03, 0x01, 0xA6, 0x1C, 0x03, 0x00, 0x33, 0x25, 0x00,
-    0xAA, 0x88, 0x6E, 0x95, 0x38, 0x83, 0x3A, 0x96, 0x38, 0x83, 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8,
-    0x00, 0x33, 0x42, 0x00, 0xAA, 0x88, 0x00, 0x01, 0x05, 0x05, 0xFF, 0xA2, 0x78, 0x03, 0xB1, 0x01,
-    0x08, 0x23, 0xB2, 0x01, 0x34, 0x83, 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x98, 0x03, 0xEC, 0x00,
-    0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x94, 0x03, 0x00, 0xA6,
-    0x94, 0x03, 0x08, 0x84, 0x80, 0x42, 0x68, 0x98, 0x01, 0xA6, 0xA2, 0x03, 0x00, 0xA6, 0xBA, 0x03,
-    0x08, 0x84, 0x90, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA2, 0x03, 0x07, 0xA6, 0xB0, 0x03, 0xD2, 0x83,
-    0x6E, 0x95, 0xA6, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xAA, 0x88, 0x90, 0x98, 0x80, 0x42, 0x00, 0xA6,
-    0xBA, 0x03, 0x07, 0xA6, 0xC8, 0x03, 0xD2, 0x83, 0x6E, 0x95, 0xBE, 0x83, 0x00, 0x33, 0x26, 0x00,
-    0xAA, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01,
-    0x08, 0x84, 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, 0x20, 0x00, 0xAA, 0x88, 0x03, 0xA6, 0x06, 0x04,
-    0x07, 0xA6, 0xFE, 0x03, 0x06, 0xA6, 0x02, 0x04, 0x00, 0x33, 0x17, 0x00, 0xAA, 0x88, 0x6E, 0x95,
-    0xEC, 0x83, 0x3A, 0x96, 0xEC, 0x83, 0x12, 0x84, 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, 0x20, 0x00,
-    0xAA, 0x88, 0xB6, 0x2D, 0x03, 0xA6, 0x2E, 0x04, 0x07, 0xA6, 0x26, 0x04, 0x06, 0xA6, 0x2A, 0x04,
-    0x00, 0x33, 0x30, 0x00, 0xAA, 0x88, 0x6E, 0x95, 0x12, 0x84, 0x3A, 0x96, 0x12, 0x84, 0x1D, 0x01,
-    0x06, 0xCC, 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D,
-    0x80, 0x63, 0x07, 0xA6, 0x4C, 0x04, 0x00, 0x33, 0x18, 0x00, 0xAA, 0x88, 0x03, 0x03, 0x80, 0x63,
-    0xA3, 0x01, 0x07, 0xA4, 0x56, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x78, 0x04, 0x0A, 0xA0, 0x68, 0x04,
-    0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00, 0xAA, 0x88, 0x0B, 0xA0, 0x74, 0x04, 0xE0, 0x00, 0x00, 0x33,
-    0x1E, 0x00, 0xAA, 0x88, 0x42, 0x23, 0xE0, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xD8, 0x04, 0x08, 0x23,
-    0x22, 0xA3, 0x94, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xA0, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xB6, 0x04,
-    0x42, 0x23, 0xE0, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xA0, 0x04, 0x45, 0x23, 0xE0, 0x88,
-    0xEE, 0x97, 0x00, 0xA2, 0xB2, 0x04, 0x9C, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62,
-    0xF0, 0x81, 0x47, 0x23, 0xE0, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0xEE, 0x97, 0x9C, 0x98, 0x00, 0x33,
-    0x00, 0x81, 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x08, 0x02, 0x43, 0x23, 0xE0, 0x88,
-    0x04, 0x23, 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xE6, 0x04,
-    0x00, 0x33, 0x27, 0x00, 0xAA, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23,
-    0xA0, 0x01, 0xEE, 0x97, 0x18, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3,
-    0x14, 0x05, 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x0E, 0x05, 0xFC, 0x84, 0x30, 0x97,
-    0xCD, 0x04, 0x16, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01,
-    0x26, 0x85, 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x32, 0x05, 0x1D, 0x01,
-    0x04, 0xD6, 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00,
-    0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04,
-    0x80, 0x01, 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x52, 0x05, 0x77, 0x04, 0x01, 0x23,
-    0xEA, 0x00, 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4,
-    0xD2, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x80, 0x05, 0xCE, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xAA, 0x88,
-    0x04, 0xA0, 0xA6, 0x05, 0x80, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x92, 0x05, 0x1D, 0x01,
-    0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x4C, 0x97, 0xF6, 0x84, 0x04, 0x23,
-    0x02, 0x41, 0x82, 0x01, 0xF6, 0x84, 0x08, 0xA0, 0xAC, 0x05, 0xCE, 0x85, 0x03, 0xA0, 0xB2, 0x05,
-    0xCE, 0x85, 0x01, 0xA0, 0xBC, 0x05, 0x88, 0x00, 0x80, 0x63, 0xAA, 0x86, 0x07, 0xA0, 0xC8, 0x05,
-    0x06, 0x23, 0x52, 0x98, 0x48, 0x23, 0xE0, 0x88, 0x07, 0x23, 0x80, 0x00, 0xF0, 0x86, 0x80, 0x63,
-    0x6E, 0x85, 0x00, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x10, 0x06, 0x1D, 0x01, 0x18, 0xD4,
-    0xC0, 0x23, 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0xF2, 0x05, 0x00, 0x33, 0x37, 0x00,
-    0xAA, 0x88, 0x1D, 0x01, 0x02, 0xD6, 0x46, 0x23, 0xE0, 0x88, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63,
-    0x06, 0xA6, 0x0A, 0x06, 0x00, 0x33, 0x38, 0x00, 0xAA, 0x88, 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63,
-    0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x28, 0x06, 0x1D, 0x01,
-    0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83,
-    0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, 0x80, 0x67, 0x08, 0x23, 0x83, 0x03,
-    0x80, 0x63, 0x00, 0x63, 0x06, 0xA6, 0x56, 0x06, 0x07, 0xA6, 0x6E, 0x05, 0x02, 0xA6, 0xE4, 0x06,
-    0x00, 0x33, 0x39, 0x00, 0xAA, 0x88, 0x00, 0x00, 0x01, 0xA0, 0xFE, 0x06, 0xD4, 0x95, 0x83, 0x03,
-    0x80, 0x63, 0x06, 0xA6, 0x6A, 0x06, 0x07, 0xA6, 0x6E, 0x05, 0x00, 0x00, 0x01, 0xA0, 0xFE, 0x06,
-    0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0x86, 0x06, 0x07, 0xA6, 0x6E, 0x05,
-    0x00, 0x33, 0x3A, 0x00, 0xAA, 0x88, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x78, 0x06,
-    0x06, 0xA6, 0x9E, 0x06, 0x07, 0xA6, 0x6E, 0x05, 0x00, 0x33, 0x3B, 0x00, 0xAA, 0x88, 0x80, 0x67,
-    0x40, 0x0E, 0x80, 0x63, 0x07, 0xA6, 0x6E, 0x05, 0x00, 0x63, 0x07, 0xA6, 0xB4, 0x06, 0x00, 0x33,
-    0x2A, 0x00, 0xAA, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xC6, 0x06,
-    0x00, 0x33, 0x29, 0x00, 0xAA, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xD2, 0x06, 0xC0, 0x0E, 0x80, 0x63,
-    0xBC, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, 0x08, 0xDA,
-    0x80, 0x63, 0x6E, 0x85, 0x80, 0x67, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
-    0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x62, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xAA, 0x88, 0x0C, 0xA2,
-    0x18, 0x07, 0xD4, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x16, 0x07, 0x07, 0xA6, 0x6E, 0x05,
-    0x00, 0x33, 0x3D, 0x00, 0xAA, 0x88, 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0,
-    0x2E, 0x07, 0x07, 0xA6, 0x6E, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xD8, 0x84, 0x00, 0x63,
-    0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00, 0x01, 0x05, 0x80, 0x01, 0x72, 0x04,
-    0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00,
-    0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00, 0x81, 0x01,
-    0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04,
-    0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00,
-    0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x00, 0x63,
-    0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01, 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01,
-    0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xAE, 0x07, 0x00, 0x33, 0x07, 0x00, 0xAA, 0x88, 0x80, 0x05,
-    0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01,
-    0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xCE, 0x07, 0x00, 0x05, 0xC4, 0x87, 0x00, 0x01,
-    0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08,
-    0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04,
-    0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0, 0xFE, 0x07, 0x00, 0x88, 0x00, 0x43,
-    0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00,
-    0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x2E, 0x08, 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9,
-    0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x0E, 0x08, 0xEE, 0x97, 0x18, 0x95, 0x0E, 0x88, 0x73, 0x04,
-    0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x44, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x30, 0x97, 0xEE, 0x97,
-    0x18, 0x95, 0x34, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x4E, 0x08, 0x00, 0x05, 0x38, 0x88, 0x73, 0x04,
-    0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x60, 0x08, 0x00, 0x33, 0x3E, 0x00, 0xAA, 0x88,
-    0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B, 0x86, 0x88, 0x38, 0x2B, 0x7C, 0x88,
-    0x32, 0x09, 0x31, 0x05, 0x7C, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32, 0x00, 0x36,
-    0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36, 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63,
-    0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
-    0x00, 0xA0, 0x9C, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23,
-    0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, 0x13, 0x23, 0xE0, 0x88, 0x66, 0x20, 0xC0, 0x20,
-    0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xCA, 0x88, 0x80, 0x73, 0x80, 0x77,
-    0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23, 0xE0, 0x88, 0x11, 0x23,
-    0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xD8, 0x84,
-};
+/*
+ * Add serial number to information bar if signature AAh
+ * is found in at bit 15-9 (7 bits) of word 1.
+ *
+ * Serial Number consists 12 alpha-numeric digits.
+ *
+ *       1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
+ *       2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
+ *     3-4 - Product ID (0-99)        Word0: 10-0 (11 bits)
+ *       5 - Product revision         Word0:  "         "
+ *
+ *         Signature                Word1: 15-9 (7 bits)
+ *       6 - Year (4-9)               Word1: 8-6 (3 bits)
+ *     7-8 - Week of the year         Word1: 5-0 (6 bits)
+ *
+ *    9-12 - Serial Number            Word2: 15-0 (16 bits)
+ *
+ * Note 1: Only production cards will have a serial number.
+ *
+ * Note 2: Signature is most significant 7 bits (0xFE).
+ *
+ * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
+ */
+STATIC int
+asc_get_eeprom_string(ushort *serialnum, uchar *cp)
+{
+    ushort      w, num;
 
-STATIC ushort _mcode_size ASC_INITDATA = sizeof(_mcode_buf);
-STATIC ulong _mcode_chksum ASC_INITDATA = 0x01297F32UL;
+    if ((serialnum[1] & 0xFE00) != ((ushort) 0xAA << 8)) {
+        return ASC_FALSE;
+    } else {
+        /*
+         * First word - 6 digits.
+         */
+        w = serialnum[0];
 
-#define ASC_SYN_OFFSET_ONE_DISABLE_LIST  16
-STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] =
-{
-    SCSICMD_Inquiry,
-    SCSICMD_RequestSense,
-    SCSICMD_ReadCapacity,
-    SCSICMD_ReadTOC,
-    SCSICMD_ModeSelect6,
-    SCSICMD_ModeSense6,
-    SCSICMD_ModeSelect10,
-    SCSICMD_ModeSense10,
-    0xFF,
-    0xFF,
-    0xFF,
-    0xFF,
-    0xFF,
-    0xFF,
-    0xFF,
-    0xFF
-};
+        /* Product type - 1st digit. */
+        *cp++ = 'A' + ((w & 0xE000) >> 13);
+
+        /* Manufacturing location - 2nd digit. */
+        *cp++ = 'A' + ((w & 0x1C00) >> 10);
+
+        /* Product ID - 3rd, 4th digits. */
+        num = w & 0x3FF;
+        *cp++ = '0' + (num / 100);
+        num %= 100;
+        *cp++ = '0' + (num / 10);
+
+        /* Product revision - 5th digit. */
+        *cp++ = 'A' + (num % 10);
 
+        /*
+         * Second word
+         */
+        w = serialnum[1];
+
+        /* Year - 6th digit. */
+        *cp++ = '0' + ((w & 0x1C0) >> 6);
+
+        /* Week of year - 7th, 8th digits. */
+        num = w & 0x003F;
+        *cp++ = '0' + num / 10;
+        num %= 10;
+        *cp++ = '0' + num;
+
+        /*
+         * Third word
+         */
+        w = serialnum[2];
+
+        /* Serial number - 9th digit. */
+        *cp++ = 'A' + (w / 1000);
+
+        /* 10th, 11th, 12th digits. */
+        num = w % 1000;
+        *cp++ = '0' + num / 100;
+        num %= 100;
+        *cp++ = '0' + num / 10;
+        num %= 10;
+        *cp++ = '0' + num;
+
+        *cp = '\0';     /* Null Terminate the string. */
+        return ASC_TRUE;
+    }
+}
+
+/*
+ * asc_prt_asc_board_eeprom()
+ *
+ * Print board EEPROM configuration.
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
 STATIC int
-AscExeScsiQueue(
-                   REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                   REG ASC_SCSI_Q * scsiq
-)
+asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
 {
-    PortAddr            iop_base;
-    int                 last_int_level;
-    int                 sta;
-    int                 n_q_required;
-    int                 disable_syn_offset_one_fix;
-    int                 i;
-    ulong               addr;
-    ASC_EXE_CALLBACK    asc_exe_callback;
-    ushort              sg_entry_cnt = 0;
-    ushort              sg_entry_cnt_minus_one = 0;
-    uchar               target_ix;
-    uchar               tid_no;
-    uchar               sdtr_data;
-    uchar               extra_bytes;
-    uchar               scsi_cmd;
-    uchar               disable_cmd;
-    ASC_SG_HEAD *sg_head;
-    ulong               data_cnt;
-    iop_base = asc_dvc->iop_base;
-    sg_head = scsiq->sg_head;
-    asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
-    if (asc_dvc->err_code != 0)
-        return (ERR);
-    if (scsiq == (ASC_SCSI_Q *) 0L) {
-        AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
-        return (ERR);
-    }
-    scsiq->q1.q_no = 0;
-    if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
-        scsiq->q1.extra_bytes = 0;
-    }
-    sta = 0;
-    target_ix = scsiq->q2.target_ix;
-    tid_no = ASC_TIX_TO_TID(target_ix);
-    n_q_required = 1;
-    if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
-        if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
-            asc_dvc->sdtr_done &= ~scsiq->q1.target_id ;
-            sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
-            AscMsgOutSDTR(asc_dvc,
-                          asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
-                          (uchar) (asc_dvc->max_sdtr_index - 1)],
-                          (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
-            scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
+    asc_board_t        *boardp;
+    ASC_DVC_VAR        *asc_dvc_varp;
+    int                leftlen;
+    int                totlen;
+    int                len;
+    ASCEEP_CONFIG      *ep;
+    int                i;
+    int                isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
+    uchar              serialstr[13];
+
+    boardp = ASC_BOARDP(shp);
+    asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
+    ep = &boardp->eep_config.asc_eep;
+
+    leftlen = cplen;
+    totlen = len = 0;
+
+    len = asc_prt_line(cp, leftlen,
+"\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
+    ASC_PRT_NEXT();
+
+    if (asc_get_eeprom_string((ushort *) &ep->adapter_info[0], serialstr) ==
+        ASC_TRUE) {
+        len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
+        ASC_PRT_NEXT();
+    } else {
+        if (ep->adapter_info[5] == 0xBB) {
+            len = asc_prt_line(cp, leftlen,
+                " Default Settings Used for EEPROM-less Adapter.\n");
+            ASC_PRT_NEXT();
+        } else {
+            len = asc_prt_line(cp, leftlen,
+                " Serial Number Signature Not Present.\n");
+            ASC_PRT_NEXT();
         }
     }
-    last_int_level = DvcEnterCritical();
-    if (asc_dvc->in_critical_cnt != 0) {
-        DvcLeaveCritical(last_int_level);
-        AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
-        return (ERR);
+
+    len = asc_prt_line(cp, leftlen,
+" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+        ep->chip_scsi_id, ep->max_total_qng, ep->max_tag_qng);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" cntl %x, no_scam %x\n",
+        ep->cntl, ep->no_scam);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Target ID:           ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %d", i);
+        ASC_PRT_NEXT();
     }
-    asc_dvc->in_critical_cnt++;
-    if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
-        if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
-            asc_dvc->in_critical_cnt--;
-            DvcLeaveCritical(last_int_level);
-            return (ERR);
-        }
-        if (sg_entry_cnt > ASC_MAX_SG_LIST) {
-            return (ERR);
-        }
-        if (sg_entry_cnt == 1) {
-            scsiq->q1.data_addr = sg_head->sg_list[0].addr;
-            scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
-            scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
-        }
-        sg_entry_cnt_minus_one = sg_entry_cnt - 1;
-#if CC_DEBUG_SG_LIST
-        if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
-            for (i = 0; i < sg_entry_cnt_minus_one; i++) {
-                addr = sg_head->sg_list[i].addr + sg_head->sg_list[i].bytes;
-                if (((ushort) addr & 0x0003) != 0) {
-                    asc_dvc->in_critical_cnt--;
-                    DvcLeaveCritical(last_int_level);
-                    AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_LIST_ODD_ADDRESS);
-                    return (ERR);
-                }
-            }
-        }
-#endif
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Disconnects:         ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    scsi_cmd = scsiq->cdbptr[0];
-    disable_syn_offset_one_fix = FALSE;
-    if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
-        !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
-        if (scsiq->q1.cntl & QC_SG_HEAD) {
-            data_cnt = 0;
-            for (i = 0; i < sg_entry_cnt; i++) {
-                data_cnt += sg_head->sg_list[i].bytes;
-            }
-        } else {
-            data_cnt = scsiq->q1.data_cnt;
-        }
-        if (data_cnt != 0UL) {
-            if (data_cnt < 512UL) {
-                disable_syn_offset_one_fix = TRUE;
-            } else {
-                for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) {
-                    disable_cmd = _syn_offset_one_disable_cmd[i];
-                    if (disable_cmd == 0xFF) {
-                        break;
-                    }
-                    if (scsi_cmd == disable_cmd) {
-                        disable_syn_offset_one_fix = TRUE;
-                        break;
-                    }
-                }
-            }
-        }
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Command Queuing:     ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    if (disable_syn_offset_one_fix) {
-        scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
-        scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
-                               ASC_TAG_FLAG_DISABLE_DISCONNECT);
-    } else {
-        scsiq->q2.tag_code &= 0x23;
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Start Motor:         ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
-        if (asc_dvc->bug_fix_cntl) {
-            if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
-                if ((scsi_cmd == SCSICMD_Read6) ||
-                    (scsi_cmd == SCSICMD_Read10)) {
-                    addr = sg_head->sg_list[sg_entry_cnt_minus_one].addr +
-                      sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
-                    extra_bytes = (uchar) ((ushort) addr & 0x0003);
-                    if ((extra_bytes != 0) &&
-                        ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
-                         == 0)) {
-                        scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
-                        scsiq->q1.extra_bytes = extra_bytes;
-                        sg_head->sg_list[sg_entry_cnt_minus_one].bytes -=
-                            (ulong) extra_bytes;
-                    }
-                }
-            }
-        }
-        sg_head->entry_to_copy = sg_head->entry_cnt;
-        n_q_required = AscSgListToQueue(sg_entry_cnt);
-        if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
-            (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
-            if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
-                                        n_q_required)) == 1) {
-                asc_dvc->in_critical_cnt--;
-                if (asc_exe_callback != 0) {
-                    (*asc_exe_callback) (asc_dvc, scsiq);
-                }
-                DvcLeaveCritical(last_int_level);
-                return (sta);
-            }
-        }
-    } else {
-        if (asc_dvc->bug_fix_cntl) {
-            if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
-                if ((scsi_cmd == SCSICMD_Read6) ||
-                    (scsi_cmd == SCSICMD_Read10)) {
-                    addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
-                    extra_bytes = (uchar) ((ushort) addr & 0x0003);
-                    if ((extra_bytes != 0) &&
-                        ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
-                          == 0)) {
-                        if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
-                            scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
-                            scsiq->q1.data_cnt -= (ulong) extra_bytes;
-                            scsiq->q1.extra_bytes = extra_bytes;
-                        }
-                    }
-                }
-            }
-        }
-        n_q_required = 1;
-        if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
-            ((scsiq->q1.cntl & QC_URGENT) != 0)) {
-            if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
-                                        n_q_required)) == 1) {
-                asc_dvc->in_critical_cnt--;
-                if (asc_exe_callback != 0) {
-                    (*asc_exe_callback) (asc_dvc, scsiq);
-                }
-                DvcLeaveCritical(last_int_level);
-                return (sta);
-            }
-        }
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Synchronous Transfer:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    asc_dvc->in_critical_cnt--;
-    DvcLeaveCritical(last_int_level);
-    return (sta);
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
+        len = asc_prt_line(cp, leftlen,
+" Host ISA DMA speed:   %d MB/S\n",
+            isa_dma_speed[ep->isa_dma_speed]);
+        ASC_PRT_NEXT();
+    }
+
+     return totlen;
 }
 
+/*
+ * asc_prt_adv_board_eeprom()
+ *
+ * Print board EEPROM configuration.
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
 STATIC int
-AscSendScsiQueue(
-                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                    REG ASC_SCSI_Q * scsiq,
-                    uchar n_q_required
-)
+asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
 {
-    PortAddr            iop_base;
-    uchar               free_q_head;
-    uchar               next_qp;
-    uchar               tid_no;
-    uchar               target_ix;
-    int                 sta;
-    iop_base = asc_dvc->iop_base;
-    target_ix = scsiq->q2.target_ix;
-    tid_no = ASC_TIX_TO_TID(target_ix);
-    sta = 0;
-    free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
-    if (n_q_required > 1) {
-        if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
-                                       free_q_head, (uchar) (n_q_required)))
-            != (uchar) ASC_QLINK_END) {
-            asc_dvc->last_q_shortage = 0;
-            scsiq->sg_head->queue_cnt = n_q_required - 1;
-            scsiq->q1.q_no = free_q_head;
-            if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
-                                              free_q_head)) == 1) {
-#if CC_WRITE_IO_COUNT
-                asc_dvc->req_count++;
-#endif
-                AscPutVarFreeQHead(iop_base, next_qp);
-                asc_dvc->cur_total_qng += (uchar) (n_q_required);
-                asc_dvc->cur_dvc_qng[tid_no]++;
-            }
-            return (sta);
-        }
-    } else if (n_q_required == 1) {
-        if ((next_qp = AscAllocFreeQueue(iop_base,
-                                         free_q_head)) != ASC_QLINK_END) {
-            scsiq->q1.q_no = free_q_head;
-            if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
-                                        free_q_head)) == 1) {
-#if CC_WRITE_IO_COUNT
-                asc_dvc->req_count++;
-#endif
-                AscPutVarFreeQHead(iop_base, next_qp);
-                asc_dvc->cur_total_qng++;
-                asc_dvc->cur_dvc_qng[tid_no]++;
-            }
-            return (sta);
-        }
+    asc_board_t        *boardp;
+    ADV_DVC_VAR        *adv_dvc_varp;
+    int                leftlen;
+    int                totlen;
+    int                len;
+    int                i;
+    char               *termstr;
+    uchar              serialstr[13];
+    ADVEEP_CONFIG      *ep;
+
+    boardp = ASC_BOARDP(shp);
+    adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
+    ep = &boardp->eep_config.adv_eep;
+
+    leftlen = cplen;
+    totlen = len = 0;
+
+    len = asc_prt_line(cp, leftlen,
+"\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no);
+    ASC_PRT_NEXT();
+
+    if (asc_get_eeprom_string(&ep->serial_number_word1, serialstr) ==
+        ASC_TRUE) {
+        len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr);
+        ASC_PRT_NEXT();
+    } else {
+        len = asc_prt_line(cp, leftlen,
+            " Serial Number Signature Not Present.\n");
+        ASC_PRT_NEXT();
     }
-    return (sta);
-}
 
-STATIC int
-AscSgListToQueue(
-                    int sg_list
-)
-{
-    int                 n_sg_list_qs;
-    n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
-    if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
-        n_sg_list_qs++;
-    return (n_sg_list_qs + 1);
-}
+    len = asc_prt_line(cp, leftlen,
+" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
+        ep->adapter_scsi_id, ep->max_host_qng, ep->max_dvc_qng);
+    ASC_PRT_NEXT();
 
+    switch (ep->termination) {
+        case 1:
+            termstr = "Low Off/High Off";
+            break;
+        case 2:
+            termstr = "Low Off/High On";
+            break;
+        case 3:
+            termstr = "Low On/High On";
+            break;
+        default:
+        case 0:
+            termstr = "Automatic";
+            break;
+    }
 
-STATIC uint
-AscGetNumOfFreeQueue(
-                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                        uchar target_ix,
-                        uchar n_qs
-)
-{
-    uint                cur_used_qs;
-    uint                cur_free_qs;
-    ASC_SCSI_BIT_ID_TYPE target_id;
-    uchar               tid_no;
-    target_id = ASC_TIX_TO_TARGET_ID(target_ix);
-    tid_no = ASC_TIX_TO_TID(target_ix);
-    if ((asc_dvc->unit_not_ready & target_id) ||
-        (asc_dvc->queue_full_or_busy & target_id)) {
-        return (0);
+    len = asc_prt_line(cp, leftlen,
+" termination: %u (%s), bios_ctrl: %x\n",
+        ep->termination, termstr, ep->bios_ctrl);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Target ID:           ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %X", i);
+        ASC_PRT_NEXT();
     }
-    if (n_qs == 1) {
-        cur_used_qs = (uint) asc_dvc->cur_total_qng +
-          (uint) asc_dvc->last_q_shortage +
-          (uint) ASC_MIN_FREE_Q;
-    } else {
-        cur_used_qs = (uint) asc_dvc->cur_total_qng +
-          (uint) ASC_MIN_FREE_Q;
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Disconnects:         ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
-        cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
-        if (asc_dvc->cur_dvc_qng[tid_no] >=
-            asc_dvc->max_dvc_qng[tid_no]) {
-            return (0);
-        }
-        return (cur_free_qs);
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Command Queuing:     ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    if (n_qs > 1) {
-        if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
-            asc_dvc->last_q_shortage = n_qs;
-        }
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Start Motor:         ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    return (0);
-}
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
 
-STATIC int
-AscPutReadyQueue(
-                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                    REG ASC_SCSI_Q * scsiq,
-                    uchar q_no
-)
-{
-    ushort              q_addr;
-    uchar               tid_no;
-    uchar               sdtr_data;
-    uchar               syn_period_ix;
-    uchar               syn_offset;
-    PortAddr            iop_base;
-    iop_base = asc_dvc->iop_base;
-    if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
-        ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
-        tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
-        sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
-        syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
-        syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
-        AscMsgOutSDTR(asc_dvc,
-                      asc_dvc->sdtr_period_tbl[syn_period_ix],
-                      syn_offset);
-        scsiq->q1.cntl |= QC_MSG_OUT;
+    len = asc_prt_line(cp, leftlen,
+" Synchronous Transfer:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    q_addr = ASC_QNO_TO_QADDR(q_no);
-    if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
-        scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Ultra Transfer:      ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->ultra_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    scsiq->q1.status = QS_FREE;
-    AscMemWordCopyToLram(iop_base,
-                         (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
-                         (ushort *) scsiq->cdbptr,
-                         (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
-#if !CC_LITTLE_ENDIAN_HOST
-    AscAdjEndianScsiQ(scsiq);
-#endif
-    DvcPutScsiQ(iop_base,
-                (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
-                (ushort *) & scsiq->q1.cntl,
-      (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
-#if CC_WRITE_IO_COUNT
-    AscWriteLramWord(iop_base,
-                     (ushort) (q_addr + (ushort) ASC_SCSIQ_W_REQ_COUNT),
-                     (ushort) asc_dvc->req_count);
-#endif
-#if CC_VERIFY_LRAM_COPY
-    if ((asc_dvc->dvc_cntl & ASC_CNTL_NO_VERIFY_COPY) == 0) {
-        if (AscMemWordCmpToLram(iop_base,
-                             (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
-                                (ushort *) scsiq->cdbptr,
-                                (ushort) (scsiq->q2.cdb_len >> 1)) != 0) {
-            AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
-            return (ERR);
-        }
-        if (AscMemWordCmpToLram(iop_base,
-                             (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
-                                (ushort *) & scsiq->q1.cntl,
-         (ushort) (((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1))
-            != 0) {
-            AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
-            return (ERR);
-        }
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Wide Transfer:       ");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        len = asc_prt_line(cp, leftlen, " %c",
+            (ep->wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-#endif
-#if CC_CLEAR_DMA_REMAIN
-    AscWriteLramDWord(iop_base,
-           (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_ADDR), 0UL);
-    AscWriteLramDWord(iop_base,
-            (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT), 0UL);
-#endif
-    AscWriteLramWord(iop_base,
-                     (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
-             (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
-    return (1);
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    return totlen;
 }
 
+/*
+ * asc_prt_driver_conf()
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
 STATIC int
-AscPutReadySgListQueue(
-                          REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                          REG ASC_SCSI_Q * scsiq,
-                          uchar q_no
-)
+asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
 {
-    int                 sta;
-    int                 i;
-    ASC_SG_HEAD *sg_head;
-    ASC_SG_LIST_Q       scsi_sg_q;
-    ulong               saved_data_addr;
-    ulong               saved_data_cnt;
-    PortAddr            iop_base;
-    ushort              sg_list_dwords;
-    ushort              sg_index;
-    ushort              sg_entry_cnt;
-    ushort              q_addr;
-    uchar               next_qp;
-    iop_base = asc_dvc->iop_base;
-    sg_head = scsiq->sg_head;
-    saved_data_addr = scsiq->q1.data_addr;
-    saved_data_cnt = scsiq->q1.data_cnt;
-    scsiq->q1.data_addr = sg_head->sg_list[0].addr;
-    scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
-    sg_entry_cnt = sg_head->entry_cnt - 1;
-    if (sg_entry_cnt != 0) {
-        scsiq->q1.cntl |= QC_SG_HEAD;
-        q_addr = ASC_QNO_TO_QADDR(q_no);
-        sg_index = 1;
-        scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
-        scsi_sg_q.sg_head_qp = q_no;
-        scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
-        for (i = 0; i < sg_head->queue_cnt; i++) {
-            scsi_sg_q.seq_no = i + 1;
-            if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
-                sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
-                sg_entry_cnt -= ASC_SG_LIST_PER_Q;
-                if (i == 0) {
-                    scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
-                    scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
-                } else {
-                    scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
-                    scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
-                }
-            } else {
-                scsi_sg_q.cntl |= QCSG_SG_XFER_END;
-                sg_list_dwords = sg_entry_cnt << 1;
-                if (i == 0) {
-                    scsi_sg_q.sg_list_cnt = sg_entry_cnt;
-                    scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
-                } else {
-                    scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
-                    scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
-                }
-                sg_entry_cnt = 0;
-            }
-            next_qp = AscReadLramByte(iop_base,
-                                      (ushort) (q_addr + ASC_SCSIQ_B_FWD));
-            scsi_sg_q.q_no = next_qp;
-            q_addr = ASC_QNO_TO_QADDR(next_qp);
-            AscMemWordCopyToLram(iop_base,
-                                 (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
-                                 (ushort *) & scsi_sg_q,
-                                 (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
-            AscMemDWordCopyToLram(iop_base,
-                                  (ushort) (q_addr + ASC_SGQ_LIST_BEG),
-                              (ulong *) & sg_head->sg_list[sg_index],
-                                  (ushort) sg_list_dwords);
-            sg_index += ASC_SG_LIST_PER_Q;
-        }
-    } else {
-        scsiq->q1.cntl &= ~QC_SG_HEAD;
-    }
-    sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
-    scsiq->q1.data_addr = saved_data_addr;
-    scsiq->q1.data_cnt = saved_data_cnt;
-    return (sta);
-}
+    asc_board_t            *boardp;
+    int                    leftlen;
+    int                    totlen;
+    int                    len;
+    int                    chip_scsi_id;
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+    int                    i;
+#endif /* version >= v1.3.89 */
 
-STATIC int
-AscAbortSRB(
-               REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-               ulong srb_ptr
-)
-{
-    int                 sta;
-    ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
-    PortAddr            iop_base;
-    iop_base = asc_dvc->iop_base;
-    sta = ERR;
-    saved_unit_not_ready = asc_dvc->unit_not_ready;
-    asc_dvc->unit_not_ready = 0xFF;
-    AscWaitISRDone(asc_dvc);
-    if (AscStopQueueExe(iop_base) == 1) {
-        if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
-            sta = 1;
-            AscCleanUpBusyQueue(iop_base);
-            AscStartQueueExe(iop_base);
-        } else {
-            sta = 0;
-            AscStartQueueExe(iop_base);
-        }
+    boardp = ASC_BOARDP(shp);
+
+    leftlen = cplen;
+    totlen = len = 0;
+
+    len = asc_prt_line(cp, leftlen,
+"\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
+        shp->host_no);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+" host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
+        shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
+#else /* version >= v1.3.89 */
+" host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
+        shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun,
+        shp->max_channel);
+#endif /* version >= v1.3.89 */
+    ASC_PRT_NEXT();
+    
+    len = asc_prt_line(cp, leftlen,
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
+" can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
+        shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
+#else /* version >= v1.3.57 */
+" unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
+        shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize,
+        shp->cmd_per_lun);
+#endif /* version >= v1.3.57 */
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
+" unchecked_isa_dma %d, loaded_as_module %d\n",
+        shp->unchecked_isa_dma, shp->loaded_as_module);
+#else /* version >= v1.3.57 */
+" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
+        shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
+#endif /* version >= v1.3.57 */
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen, " flags %x, last_reset %x, jiffies %x\n",
+        boardp->flags, boardp->last_reset, jiffies);
+    ASC_PRT_NEXT();
+
+    if (ASC_NARROW_BOARD(boardp)) {
+        chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
+    } else {
+        chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
     }
-    asc_dvc->unit_not_ready = saved_unit_not_ready;
-    return (sta);
-}
 
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-STATIC int
-AscResetDevice(
-                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                  uchar target_ix
-)
-{
-    PortAddr            iop_base;
-    int                 sta;
-    uchar               tid_no;
-    ASC_SCSI_BIT_ID_TYPE target_id;
-    int                 i;
-    ASC_SCSI_REQ_Q      scsiq_buf;
-    ASC_SCSI_REQ_Q *scsiq;
-    uchar       *buf;
-    ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
-    iop_base = asc_dvc->iop_base;
-    tid_no = ASC_TIX_TO_TID(target_ix);
-    target_id = ASC_TID_TO_TARGET_ID(tid_no);
-    saved_unit_not_ready = asc_dvc->unit_not_ready;
-    asc_dvc->unit_not_ready = target_id;
-    sta = ERR;
-    AscWaitTixISRDone(asc_dvc, target_ix);
-    if (AscStopQueueExe(iop_base) == 1) {
-        if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
-            AscCleanUpBusyQueue(iop_base);
-            AscStartQueueExe(iop_base);
-            AscWaitTixISRDone(asc_dvc, target_ix);
-            sta = TRUE;
-            scsiq = (ASC_SCSI_REQ_Q *) & scsiq_buf;
-            buf = (uchar *) & scsiq_buf;
-            for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
-                *buf++ = 0x00;
+    if (boardp->flags & ASC_SELECT_QUEUE_DEPTHS) {
+        len = asc_prt_line(cp, leftlen, " queue_depth:");
+        ASC_PRT_NEXT();
+        for (i = 0; i <= ADV_MAX_TID; i++) {
+            if ((chip_scsi_id == i) ||
+                ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                continue;
             }
-            scsiq->r1.status = (uchar) QS_READY;
-            scsiq->r2.cdb_len = 6;
-            scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
-            scsiq->r1.target_id = target_id;
-            scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
-            scsiq->cdbptr = (uchar *) scsiq->cdb;
-            scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
-            AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
-                             M1_BUS_DVC_RESET);
-            asc_dvc->unit_not_ready &= ~target_id;
-            asc_dvc->sdtr_done |= target_id;
-            if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q *) scsiq)
-                == 1) {
-                asc_dvc->unit_not_ready = target_id;
-                DvcSleepMilliSecond(1000);
-                _AscWaitQDone(iop_base, (ASC_SCSI_Q *) scsiq);
-                if (AscStopQueueExe(iop_base) == 1) {
-                    AscCleanUpDiscQueue(iop_base);
-                    AscStartQueueExe(iop_base);
-                    if (asc_dvc->pci_fix_asyn_xfer & target_id) {
-                        AscSetRunChipSynRegAtID(iop_base, tid_no,
-                                             ASYN_SDTR_DATA_FIX_PCI_REV_AB);
-                    }
-                    AscWaitTixISRDone(asc_dvc, target_ix);
-                }
-            } else {
-                sta = 0;
+            if (boardp->device[i] == NULL) {
+                continue;
             }
-            asc_dvc->sdtr_done &= ~target_id;
-        } else {
-            sta = ERR;
-            AscStartQueueExe(iop_base);
+            len = asc_prt_line(cp, leftlen, " %X:%d",
+                i, boardp->device[i]->queue_depth);
+            ASC_PRT_NEXT();
         }
+        len = asc_prt_line(cp, leftlen, "\n");
+        ASC_PRT_NEXT();
     }
-    asc_dvc->unit_not_ready = saved_unit_not_ready;
-    return (sta);
-}
 #endif /* version >= v1.3.89 */
 
-STATIC int
-AscResetSB(
-              REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-{
-    int                 sta;
-    int                 i;
-    PortAddr            iop_base;
-    iop_base = asc_dvc->iop_base;
-    asc_dvc->unit_not_ready = 0xFF;
-    sta = TRUE;
-    AscWaitISRDone(asc_dvc);
-    AscStopQueueExe(iop_base);
-    asc_dvc->sdtr_done = 0;
-    AscResetChipAndScsiBus(iop_base);
-    DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
-    AscReInitLram(asc_dvc);
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        asc_dvc->cur_dvc_qng[i] = 0;
-        if (asc_dvc->pci_fix_asyn_xfer & (ASC_SCSI_BIT_ID_TYPE) (0x01 << i)) {
-            AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+#if ASC_QUEUE_FLOW_CONTROL
+    if (ASC_NARROW_BOARD(boardp)) {
+        len = asc_prt_line(cp, leftlen, " queue_curr_depth:");
+        ASC_PRT_NEXT();
+        /* Use ASC_MAX_TID for Narrow Board. */
+        for (i = 0; i <= ASC_MAX_TID; i++) {
+            if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
+                ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                continue;
+            }
+            if (boardp->device[i] == NULL) {
+                continue;
+            }
+            len = asc_prt_line(cp, leftlen, " %d:%d",
+                i, boardp->device[i]->queue_curr_depth);
+            ASC_PRT_NEXT();
         }
-    }
-    asc_dvc->err_code = 0;
-    AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
-    if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
-        sta = ERR;
-    }
-    if (AscStartChip(iop_base) == 0) {
-        sta = ERR;
-    }
-    AscStartQueueExe(iop_base);
-    asc_dvc->unit_not_ready = 0;
-    asc_dvc->queue_full_or_busy = 0;
-    return (sta);
-}
+        len = asc_prt_line(cp, leftlen, "\n");
+        ASC_PRT_NEXT();
 
-STATIC int
-AscSetRunChipSynRegAtID(
-                           PortAddr iop_base,
-                           uchar tid_no,
-                           uchar sdtr_data
-)
-{
-    int                 sta = FALSE;
-    if (AscHostReqRiscHalt(iop_base)) {
-        sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
-        AscStartChip(iop_base);
-        return (sta);
+        len = asc_prt_line(cp, leftlen, " queue_count:");
+        ASC_PRT_NEXT();
+        /* Use ASC_MAX_TID for Narrow Board. */
+        for (i = 0; i <= ASC_MAX_TID; i++) {
+            if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
+                ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+                continue;
+            }
+            if (boardp->device[i] == NULL) {
+                continue;
+            }
+            len = asc_prt_line(cp, leftlen, " %d:%d",
+                i, boardp->device[i]->queue_count);
+            ASC_PRT_NEXT();
+        }
+        len = asc_prt_line(cp, leftlen, "\n");
+        ASC_PRT_NEXT();
     }
-    return (sta);
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+
+    return totlen;
 }
 
+/*
+ * asc_prt_asc_board_info()
+ *
+ * Print dynamic board configuration information.
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
 STATIC int
-AscSetChipSynRegAtID(
-                        PortAddr iop_base,
-                        uchar id,
-                        uchar sdtr_data
-)
+asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen)
 {
-    ASC_SCSI_BIT_ID_TYPE org_id;
-    int                 i;
-    int                 sta;
-    sta = TRUE;
-    AscSetBank(iop_base, 1);
-    org_id = AscReadChipDvcID(iop_base);
+    asc_board_t            *boardp;
+    int                    leftlen;
+    int                    totlen;
+    int                    len;
+    ASC_DVC_VAR            *v;
+    ASC_DVC_CFG            *c;
+    int                    i;
+
+    boardp = ASC_BOARDP(shp);
+    v = &boardp->dvc_var.asc_dvc_var;
+    c = &boardp->dvc_cfg.asc_dvc_cfg;
+
+    leftlen = cplen;
+    totlen = len = 0;
+
+    len = asc_prt_line(cp, leftlen,
+"\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+    shp->host_no);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" chip_version %u, lib_version %x, lib_serial_no %u, mcode_date %x\n",
+        c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" mcode_version %x, err_code %u\n",
+         c->mcode_version, v->err_code);
+    ASC_PRT_NEXT();
+
+    /* Current number of commands waiting for the host. */
+    len = asc_prt_line(cp, leftlen,
+" Total Command Pending: %d\n", v->cur_total_qng);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Command Queuing:");
+    ASC_PRT_NEXT();
     for (i = 0; i <= ASC_MAX_TID; i++) {
-        if (org_id == (0x01 << i))
-            break;
+        if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
+        len = asc_prt_line(cp, leftlen, " %d:%c",
+            i, (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    org_id = i;
-    AscWriteChipDvcID(iop_base, id);
-    if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
-        AscSetBank(iop_base, 0);
-        AscSetChipSyn(iop_base, sdtr_data);
-        if (AscGetChipSyn(iop_base) != sdtr_data) {
-            sta = FALSE;
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    /* Current number of commands waiting for a device. */
+    len = asc_prt_line(cp, leftlen,
+" Command Queue Pending:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
         }
-    } else {
-        sta = FALSE;
+        len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]);
+        ASC_PRT_NEXT();
     }
-    AscSetBank(iop_base, 1);
-    AscWriteChipDvcID(iop_base, org_id);
-    AscSetBank(iop_base, 0);
-    return (sta);
-}
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
 
-STATIC int
-AscReInitLram(
-                 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-{
-    AscInitLram(asc_dvc);
-    AscInitQLinkVar(asc_dvc);
-    return (0);
-}
+    /* Current limit on number of commands that can be sent to a device. */
+    len = asc_prt_line(cp, leftlen,
+" Command Queue Limit:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
+        len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]);
+        ASC_PRT_NEXT();
+    }
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
 
-STATIC ushort
-AscInitLram(
-               REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-{
-    uchar               i;
-    ushort              s_addr;
-    PortAddr            iop_base;
-    ushort              warn_code;
-    iop_base = asc_dvc->iop_base;
-    warn_code = 0;
-    AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
-               (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
-);
-    i = ASC_MIN_ACTIVE_QNO;
-    s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
-    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
-                     (uchar) (i + 1));
-    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
-                     (uchar) (asc_dvc->max_total_qng));
-    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
-                     (uchar) i);
-    i++;
-    s_addr += ASC_QBLK_SIZE;
-    for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
-        AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
-                         (uchar) (i + 1));
-        AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
-                         (uchar) (i - 1));
-        AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
-                         (uchar) i);
+    /* Indicate whether the device has returned queue full status. */
+    len = asc_prt_line(cp, leftlen,
+" Command Queue Full:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
+        if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
+            len = asc_prt_line(cp, leftlen, " %d:Y-%d",
+                i, boardp->queue_full_cnt[i]);
+        } else {
+            len = asc_prt_line(cp, leftlen, " %d:N", i);
+        }
+        ASC_PRT_NEXT();
     }
-    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
-                     (uchar) ASC_QLINK_END);
-    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
-                     (uchar) (asc_dvc->max_total_qng - 1));
-    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
-                     (uchar) asc_dvc->max_total_qng);
-    i++;
-    s_addr += ASC_QBLK_SIZE;
-    for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
-         i++, s_addr += ASC_QBLK_SIZE) {
-        AscWriteLramByte(iop_base,
-                         (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
-        AscWriteLramByte(iop_base,
-                         (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
-        AscWriteLramByte(iop_base,
-                         (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Synchronous Transfer:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
+        len = asc_prt_line(cp, leftlen, " %d:%c",
+            i, (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    return (warn_code);
-}
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
 
-STATIC ushort
-AscInitQLinkVar(
-                   REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-{
-    PortAddr            iop_base;
-    int                 i;
-    ushort              lram_addr;
-    iop_base = asc_dvc->iop_base;
-    AscPutRiscVarFreeQHead(iop_base, 1);
-    AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
-    AscPutVarFreeQHead(iop_base, 1);
-    AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
-    AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
-                     (uchar) ((int) asc_dvc->max_total_qng + 1));
-    AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
-                     (uchar) ((int) asc_dvc->max_total_qng + 2));
-    AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
-                     asc_dvc->max_total_qng);
-    AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
-    AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
-    AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
-    AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
-    AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
-    AscPutQDoneInProgress(iop_base, 0);
-    lram_addr = ASC_QADR_BEG;
-    for (i = 0; i < 32; i++, lram_addr += 2) {
-        AscWriteLramWord(iop_base, lram_addr, 0);
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        uchar syn_period_ix;
+
+        if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
+        if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
+            continue;
+        }
+        syn_period_ix = (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1);
+        len = asc_prt_line(cp, leftlen, "  %d:", i);
+        ASC_PRT_NEXT();
+
+        len = asc_prt_line(cp, leftlen,
+            " Transfer Period Factor: %d (%d.%d Mhz),",
+            v->sdtr_period_tbl[syn_period_ix],
+            250 / v->sdtr_period_tbl[syn_period_ix],
+            ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix]));
+        ASC_PRT_NEXT();
+
+        len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
+            boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET);
+        ASC_PRT_NEXT();
     }
-    return (0);
+
+    return totlen;
 }
 
+/*
+ * asc_prt_adv_board_info()
+ *
+ * Print dynamic board configuration information.
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
 STATIC int
-AscSetLibErrorCode(
-                      REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                      ushort err_code
-)
+asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen)
 {
-    if (asc_dvc->err_code == 0) {
-        asc_dvc->err_code = err_code;
-        AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
-                         err_code);
-    }
-    return (err_code);
-}
+    asc_board_t            *boardp;
+    int                    leftlen;
+    int                    totlen;
+    int                    len;
+    int                    i;
+    ADV_DVC_VAR            *v;
+    ADV_DVC_CFG            *c;
+    AdvPortAddr            iop_base;
+    ushort                 chip_scsi_id;
+    ushort                 lramword;
+    uchar                  lrambyte;
+    ushort                 sdtr_able;
+    ushort                 period;
 
+    boardp = ASC_BOARDP(shp);
+    v = &boardp->dvc_var.adv_dvc_var;
+    c = &boardp->dvc_cfg.adv_dvc_cfg;
+    iop_base = v->iop_base;
+    chip_scsi_id = v->chip_scsi_id;
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-STATIC int
-_AscWaitQDone(
-                 PortAddr iop_base,
-                 REG ASC_SCSI_Q * scsiq
-)
-{
-    ushort              q_addr;
-    uchar               q_status;
-    int                 count = 0;
-    while (scsiq->q1.q_no == 0) ;
-    q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
-    do {
-        q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
-        DvcSleepMilliSecond(100L);
-        if (count++ > 30) {
-            return (0);
+    leftlen = cplen;
+    totlen = len = 0;
+
+    len = asc_prt_line(cp, leftlen,
+"\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
+    shp->host_no);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" iop_base %lx, cable_detect: %X, err_code %u, idle_cmd_done %u\n",
+         v->iop_base,
+         AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1) & CABLE_DETECT,
+         v->err_code, v->idle_cmd_done);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" chip_version %u, lib_version %x, mcode_date %x, mcode_version %x\n",
+        c->chip_version, c->lib_version, c->mcode_date, c->mcode_version);
+    ASC_PRT_NEXT();
+
+    AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, lramword);
+    len = asc_prt_line(cp, leftlen,
+" Queuing Enabled:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        if ((chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
         }
-    } while ((q_status & QS_READY) != 0);
-    return (1);
-}
-#endif /* version >= v1.3.89 */
 
-STATIC uchar 
-AscMsgOutSDTR(
-                 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                 uchar sdtr_period,
-                 uchar sdtr_offset
-)
-{
-    EXT_MSG             sdtr_buf;
-    uchar               sdtr_period_index;
-    PortAddr            iop_base;
+        len = asc_prt_line(cp, leftlen, " %X:%c",
+            i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
+    }
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
 
-    iop_base = asc_dvc->iop_base;
-    sdtr_buf.msg_type = MS_EXTEND;
-    sdtr_buf.msg_len = MS_SDTR_LEN;
-    sdtr_buf.msg_req = MS_SDTR_CODE;
-    sdtr_buf.xfer_period = sdtr_period;
-    sdtr_offset &= ASC_SYN_MAX_OFFSET;
-    sdtr_buf.req_ack_offset = sdtr_offset;
-    if ((sdtr_period_index =
-         AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
-        asc_dvc->max_sdtr_index) {
-        AscMemWordCopyToLram(iop_base,
-                             ASCV_MSGOUT_BEG,
-                             (ushort *) & sdtr_buf,
-                             (ushort) (sizeof (EXT_MSG) >> 1));
-        return ((sdtr_period_index << 4) | sdtr_offset);
-    } else {
+    len = asc_prt_line(cp, leftlen,
+" Queue Limit:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        if ((chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
 
-        sdtr_buf.req_ack_offset = 0;
-        AscMemWordCopyToLram(iop_base,
-                             ASCV_MSGOUT_BEG,
-                             (ushort *) & sdtr_buf,
-                             (ushort) (sizeof (EXT_MSG) >> 1));
-        return (0);
+        AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, lrambyte);
+
+        len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
+        ASC_PRT_NEXT();
     }
-}
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
 
-STATIC uchar
-AscCalSDTRData(
-                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                  uchar sdtr_period,
-                  uchar syn_offset
-)
-{
-    uchar               byte;
-    uchar               sdtr_period_ix;
-    sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
-    if (
-           (sdtr_period_ix > asc_dvc->max_sdtr_index)
-) {
-        return (0xFF);
+    len = asc_prt_line(cp, leftlen,
+" Command Pending:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        if ((chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
+
+        AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, lrambyte);
+
+        len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
+        ASC_PRT_NEXT();
     }
-    byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
-    return (byte);
-}
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
 
-STATIC void
-AscSetChipSDTR(
-                  PortAddr iop_base,
-                  uchar sdtr_data,
-                  uchar tid_no
-)
-{
-    AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
-    AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
-    return;
-}
+    AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, lramword);
+    len = asc_prt_line(cp, leftlen,
+" Wide Enabled:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        if ((chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
 
-STATIC uchar
-AscGetSynPeriodIndex(
-                        ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                        ruchar syn_time
-)
-{
-    ruchar             *period_table;
-    int                 max_index;
-    int                 min_index;
-    int                 i;
-    period_table = asc_dvc->sdtr_period_tbl;
-    max_index = (int) asc_dvc->max_sdtr_index;
-    min_index = (int)asc_dvc->host_init_sdtr_index ;
-    if ((syn_time <= period_table[max_index])) {
-        for (i = min_index; i < (max_index - 1); i++) {
-            if (syn_time <= period_table[i]) {
-                return ((uchar) i);
-            }
+        len = asc_prt_line(cp, leftlen, " %X:%c",
+            i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
+    }
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" Transfer Bit Width:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        if ((chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
         }
-        return ((uchar) max_index);
-    } else {
-        return ((uchar) (max_index + 1));
+
+        AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
+            lramword);
+        len = asc_prt_line(cp, leftlen, " %X:%d",
+            i, (lramword & 0x8000) ? 16 : 8);
+        ASC_PRT_NEXT();
     }
-}
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
 
-STATIC uchar
-AscAllocFreeQueue(
-                     PortAddr iop_base,
-                     uchar free_q_head
-)
-{
-    ushort              q_addr;
-    uchar               next_qp;
-    uchar               q_status;
-    q_addr = ASC_QNO_TO_QADDR(free_q_head);
-    q_status = (uchar) AscReadLramByte(iop_base,
-                                    (ushort) (q_addr + ASC_SCSIQ_B_STATUS));
-    next_qp = AscReadLramByte(iop_base,
-                              (ushort) (q_addr + ASC_SCSIQ_B_FWD));
-    if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
-        return (next_qp);
+    AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
+    len = asc_prt_line(cp, leftlen,
+" Synchronous Enabled:");
+    ASC_PRT_NEXT();
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+        if ((chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
+        }
+
+        len = asc_prt_line(cp, leftlen, " %X:%c",
+            i, (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
+        ASC_PRT_NEXT();
     }
-    return (ASC_QLINK_END);
+    len = asc_prt_line(cp, leftlen, "\n");
+    ASC_PRT_NEXT();
+
+    for (i = 0; i <= ADV_MAX_TID; i++) {
+
+        AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
+            lramword);
+        lramword &= ~0x8000;
+
+        if ((chip_scsi_id == i) ||
+            ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0) ||
+            (lramword == 0)) {
+            continue;
+        }
+
+        len = asc_prt_line(cp, leftlen, "  %X:", i);
+        ASC_PRT_NEXT();
+        
+        period = (((lramword >> 8) * 25) + 50)/4;
+
+        len = asc_prt_line(cp, leftlen,
+            " Transfer Period Factor: %d (%d.%d Mhz),",
+            period, 250/period, ASC_TENTHS(250, period));
+        ASC_PRT_NEXT();
+
+        len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n",
+            lramword & 0x1F);
+        ASC_PRT_NEXT();
+    }
+
+    return totlen;
 }
 
-STATIC uchar
-AscAllocMultipleFreeQueue(
-                             PortAddr iop_base,
-                             uchar free_q_head,
-                             uchar n_free_q
-)
+/*
+ * asc_proc_copy() 
+ *
+ * Copy proc information to a read buffer taking into account the current
+ * read offset in the file and the remaining space in the read buffer.
+ */
+STATIC int
+asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
+              char *cp, int cplen)
 {
-    uchar               i;
-    for (i = 0; i < n_free_q; i++) {
-        if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
-            == ASC_QLINK_END) {
-            return (ASC_QLINK_END);
-        }
+    int cnt = 0;
+    
+    ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
+            (unsigned) offset, (unsigned) advoffset, cplen);
+    if (offset <= advoffset) {
+        /* Read offset below current offset, copy everything. */
+        cnt = ASC_MIN(cplen, leftlen);
+        ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
+                (unsigned) curbuf, (unsigned) cp, cnt);
+        memcpy(curbuf, cp, cnt);
+    } else if (offset < advoffset + cplen) {
+        /* Read offset within current range, partial copy. */
+        cnt = (advoffset + cplen) - offset;
+        cp = (cp + cplen) - cnt;
+        cnt = ASC_MIN(cnt, leftlen);
+        ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n",
+                (unsigned) curbuf, (unsigned) cp, cnt);
+        memcpy(curbuf, cp, cnt);
     }
-    return (free_q_head);
+    return cnt;
 }
 
+/*
+ * asc_prt_line()
+ *
+ * If 'cp' is NULL print to the console, otherwise print to a buffer.
+ *
+ * Return 0 if printing to the console, otherwise return the number of
+ * bytes written to the buffer.
+ *
+ * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
+ * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
+ */
 STATIC int
-AscRiscHaltedAbortSRB(
-                         REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                         ulong srb_ptr
-)
+asc_prt_line(char *buf, int buflen, char *fmt, ...)
 {
-    PortAddr            iop_base;
-    ushort              q_addr;
-    uchar               q_no;
-    ASC_QDONE_INFO      scsiq_buf;
-    ASC_QDONE_INFO *scsiq;
-    ASC_ISR_CALLBACK    asc_isr_callback;
-    int                 last_int_level;
-    iop_base = asc_dvc->iop_base;
-    asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
-    last_int_level = DvcEnterCritical();
-    scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
-    for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
-         q_no++) {
-        q_addr = ASC_QNO_TO_QADDR(q_no);
-        scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
-                           (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
-        if (scsiq->d2.srb_ptr == srb_ptr) {
-            _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
-            if (((scsiq->q_status & QS_READY) != 0)
-                 && ((scsiq->q_status & QS_ABORTED) == 0)
-                 && ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
-                scsiq->q_status |= QS_ABORTED;
-                scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
-                AscWriteLramDWord(iop_base,
-                            (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
-                                  0L);
-                AscWriteLramByte(iop_base,
-                            (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
-                                 scsiq->q_status);
-                (*asc_isr_callback) (asc_dvc, scsiq);
-                return (1);
-            }
-        }
-    }
-    DvcLeaveCritical(last_int_level);
-    return (0);
-}
+    va_list        args;
+    int            ret;
+    char        s[ASC_PRTLINE_SIZE];
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-STATIC int
-AscRiscHaltedAbortTIX(
-                         REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                         uchar target_ix
-)
-{
-    PortAddr            iop_base;
-    ushort              q_addr;
-    uchar               q_no;
-    ASC_QDONE_INFO      scsiq_buf;
-    ASC_QDONE_INFO *scsiq;
-    ASC_ISR_CALLBACK    asc_isr_callback;
-    int                 last_int_level;
-    iop_base = asc_dvc->iop_base;
-    asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
-    last_int_level = DvcEnterCritical();
-    scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
-    for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
-         q_no++) {
-        q_addr = ASC_QNO_TO_QADDR(q_no);
-        _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
-        if (((scsiq->q_status & QS_READY) != 0) &&
-            ((scsiq->q_status & QS_ABORTED) == 0) &&
-            ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
-            if (scsiq->d2.target_ix == target_ix) {
-                scsiq->q_status |= QS_ABORTED;
-                scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
-                AscWriteLramDWord(iop_base,
-                            (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
-                                  0L);
-                AscWriteLramByte(iop_base,
-                            (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
-                                 scsiq->q_status);
-                (*asc_isr_callback) (asc_dvc, scsiq);
-            }
-        }
+    va_start(args, fmt);
+    ret = vsprintf(s, fmt, args);
+    ASC_ASSERT(ret < ASC_PRTLINE_SIZE);
+    if (buf == NULL) {
+        (void) printk(s);
+        ret = 0;
+    } else {
+        ret = ASC_MIN(buflen, ret);
+        memcpy(buf, s, ret);
     }
-    DvcLeaveCritical(last_int_level);
-    return (1);
+    va_end(args);
+    return ret;
 }
-#endif /* version >= v1.3.89 */
+#endif /* version >= v1.3.0 */
 
-STATIC int
-AscHostReqRiscHalt(
-                      PortAddr iop_base
-)
-{
-    int                 count = 0;
-    int                 sta = 0;
-    uchar               saved_stop_code;
-    if (AscIsChipHalted(iop_base))
-        return (1);
-    saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
-    AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
-                     ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
-);
-    do {
-        if (AscIsChipHalted(iop_base)) {
-            sta = 1;
-            break;
-        }
-        DvcSleepMilliSecond(100);
-    } while (count++ < 20);
-    AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
-    return (sta);
-}
 
-STATIC int
-AscStopQueueExe(
-                   PortAddr iop_base
-)
+/*
+ * --- Functions Required by the Asc Library
+ */
+
+/*
+ * Delay for 'n' milliseconds. Don't use the 'jiffies'
+ * global variable which is incremented once every 5 ms
+ * from a timer interrupt, because this function may be
+ * called when interrupts are disabled.
+ */
+STATIC void
+DvcSleepMilliSecond(ulong n)
 {
-    int                 count;
-    count = 0;
-    if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
-        AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
-                         ASC_STOP_REQ_RISC_STOP);
-        do {
-            if (
-                   AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
-                   ASC_STOP_ACK_RISC_STOP) {
-                return (1);
-            }
-            DvcSleepMilliSecond(100);
-        } while (count++ < 20);
+    ulong i;
+
+    ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
+    for (i = 0; i < n; i++) {
+        udelay(1000);
     }
-    return (0);
 }
 
 STATIC int
-AscStartQueueExe(
-                    PortAddr iop_base
-)
+DvcEnterCritical(void)
 {
-    if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
-        AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
-    }
-    return (1);
+    int    flags;
+
+    save_flags(flags);
+    cli();
+    return flags;
 }
 
-STATIC int
-AscCleanUpBusyQueue(
-                       PortAddr iop_base
-)
+STATIC void
+DvcLeaveCritical(int flags)
 {
-    int                 count;
-    uchar               stop_code;
-    count = 0;
-    if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
-        AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
-                         ASC_STOP_CLEAN_UP_BUSY_Q);
-        do {
-            stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
-            if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
-                break;
-            DvcSleepMilliSecond(100);
-        } while (count++ < 20);
-    }
-    return (1);
+    restore_flags(flags);
 }
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-STATIC int
-AscCleanUpDiscQueue(
-                       PortAddr iop_base
-)
+STATIC ulong
+DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
+             ASC_SG_HEAD *asc_sg_head_ptr)
 {
-    int                 count;
-    uchar               stop_code;
-    count = 0;
-    if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
-        AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
-                         ASC_STOP_CLEAN_UP_DISC_Q);
-        do {
-            stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
-            if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
-                break;
-            DvcSleepMilliSecond(100);
-        } while (count++ < 20);
-    }
-    return (1);
+    ulong buf_size;
+
+    buf_size = buf_len;
+    asc_sg_head_ptr->entry_cnt = 1;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+    asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
+#else /* version >= v2.0.0 */
+    asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
+#endif /* version >= v2.0.0 */
+    asc_sg_head_ptr->sg_list[0].bytes = buf_size;
+    return buf_size;
 }
-#endif /* version >= v1.3.89 */
 
-STATIC int
-AscWaitTixISRDone(
-                     ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                     uchar target_ix
-)
+/*
+ * void
+ * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
+ *
+ * Calling/Exit State:
+ *    none
+ *
+ * Description:
+ *     Output an ASC_SCSI_Q structure to the chip
+ */
+STATIC void
+DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words)
 {
-    uchar               cur_req;
-    uchar               tid_no;
-    tid_no = ASC_TIX_TO_TID(target_ix);
-    while (TRUE) {
-        if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
-            break;
-        }
-        DvcSleepMilliSecond(1000L);
-        if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
-            break;
+    int    i;
+
+    ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words);
+    AscSetChipLramAddr(iop_base, s_addr);
+    for (i = 0; i < words; i++, outbuf++) {
+        if (i == 2 || i == 10) {
+            continue;
         }
+        AscSetChipLramDataNoSwap(iop_base, *outbuf);
     }
-    return (1);
 }
 
-STATIC int
-AscWaitISRDone(
-                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+/*
+ * void
+ * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
+ *
+ * Calling/Exit State:
+ *    none
+ *
+ * Description:
+ *     Input an ASC_QDONE_INFO structure from the chip
+ */
+STATIC void
+DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words)
 {
-    int                 tid;
-    for (tid = 0; tid <= ASC_MAX_TID; tid++) {
-        AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
+    int    i;
+
+    AscSetChipLramAddr(iop_base, s_addr);
+    for (i = 0; i < words; i++, inbuf++) {
+        if (i == 5) {
+            continue;
+        }
+        *inbuf = AscGetChipLramDataNoSwap(iop_base);
     }
-    return (1);
+    ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
 }
 
-STATIC ulong
-AscGetOnePhyAddr(
-                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                    uchar * buf_addr,
-                    ulong buf_size
-)
+/*
+ * void    DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
+ *
+ * Calling/Exit State:
+ *    none
+ *
+ * Description:
+ *     output a buffer to an i/o port address
+ */
+STATIC void
+DvcOutPortWords(ushort iop_base, ushort *outbuf, int words)
 {
-    ASC_MIN_SG_HEAD     sg_head;
-    sg_head.entry_cnt = ASC_MIN_SG_LIST;
-    if (DvcGetSGList(asc_dvc, (uchar *) buf_addr,
-                  buf_size, (ASC_SG_HEAD *) & sg_head) != buf_size) {
-        return (0L);
-    }
-    if (sg_head.entry_cnt > 1) {
-        return (0L);
-    }
-    return (sg_head.sg_list[0].addr);
+    int    i;
+
+    for (i = 0; i < words; i++, outbuf++)
+        outpw(iop_base, *outbuf);
 }
 
+/*
+ * void    DvcInPortWords(ushort iop_base, ushort &outbuf, int words)
+ *
+ * Calling/Exit State:
+ *    none
+ *
+ * Description:
+ *     input a buffer from an i/o port address
+ */
 STATIC void
-DvcDelayNanoSecond(
-                      ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                      ulong nano_sec
-)
+DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
 {
-    ulong               loop;
-    PortAddr            iop_base;
-    iop_base = asc_dvc->iop_base;
-    loop = nano_sec / 90;
-    loop++;
-    while (loop-- != 0) {
-        inp(iop_base);
+    int    i;
+
+    for (i = 0; i < words; i++, inbuf++)
+        *inbuf = inpw(iop_base);
+}
+
+/*
+ * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
+ *
+ * Calling/Exit State:
+ *    none
+ *
+ * Description:
+ *     output a buffer of 32-bit integers to an i/o port address in
+ *  16 bit integer units
+ */
+STATIC void  
+DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords)
+{
+    int        i;
+    int        words;
+    ushort    *pw;
+
+    pw = (ushort *) pdw;
+    words = dwords << 1;
+    for(i = 0; i < words; i++, pw++) {
+        outpw(port, *pw);
     }
     return;
 }
 
+/*
+ * Read a PCI configuration byte.
+ */
 ASC_INITFUNC(
-STATIC ulong
-AscGetEisaProductID(
-                       PortAddr iop_base
-)
+STATIC uchar
+DvcReadPCIConfigByte(
+        ASC_DVC_VAR asc_ptr_type *asc_dvc, 
+        ushort offset)
 )
 {
-    PortAddr            eisa_iop;
-    ushort              product_id_high, product_id_low;
-    ulong               product_id;
-    eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
-    product_id_low = inpw(eisa_iop);
-    product_id_high = inpw(eisa_iop + 2);
-    product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
-    return (product_id);
+    PCI_DATA    pciData;
+
+    pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
+    pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
+    pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
+    pciData.offset = offset;
+    pciData.type = pci_scan_method;
+    return asc_get_cfg_byte(&pciData);
 }
 
+/*
+ * Write a PCI configuration byte.
+ */
 ASC_INITFUNC(
-STATIC PortAddr
-AscSearchIOPortAddrEISA(
-                           PortAddr iop_base
-)
+STATIC void
+DvcWritePCIConfigByte(
+        ASC_DVC_VAR asc_ptr_type *asc_dvc, 
+        ushort offset, 
+        uchar  byte_data)
 )
 {
-    ulong               eisa_product_id;
-    if (iop_base == 0) {
-        iop_base = ASC_EISA_MIN_IOP_ADDR;
-    } else {
-        if (iop_base == ASC_EISA_MAX_IOP_ADDR)
-            return (0);
-        if ((iop_base & 0x0050) == 0x0050) {
-            iop_base += ASC_EISA_BIG_IOP_GAP;
-        } else {
-            iop_base += ASC_EISA_SMALL_IOP_GAP;
-        }
-    }
-    while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
-        eisa_product_id = AscGetEisaProductID(iop_base);
-        if ((eisa_product_id == ASC_EISA_ID_740) ||
-            (eisa_product_id == ASC_EISA_ID_750)) {
-            if (AscFindSignature(iop_base)) {
-                inpw(iop_base + 4);
-                return (iop_base);
-            }
-        }
-        if (iop_base == ASC_EISA_MAX_IOP_ADDR)
-            return (0);
-        if ((iop_base & 0x0050) == 0x0050) {
-            iop_base += ASC_EISA_BIG_IOP_GAP;
-        } else {
-            iop_base += ASC_EISA_SMALL_IOP_GAP;
-        }
-    }
-    return (0);
+    PCI_DATA    pciData;
+
+    pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
+    pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
+    pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
+    pciData.offset = offset;
+    pciData.type = pci_scan_method;
+    asc_put_cfg_byte(&pciData, byte_data);
 }
 
-STATIC int
-AscStartChip(
-                PortAddr iop_base
+/*
+ * Return the BIOS address of the adapter at the specified
+ * I/O port and with the specified bus type.
+ */
+ASC_INITFUNC(
+STATIC ushort
+AscGetChipBiosAddress(
+        PortAddr iop_base,
+        ushort bus_type
+)
 )
 {
-    AscSetChipControl(iop_base, 0);
-    if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
-        return (0);
+    ushort  cfg_lsw ;
+    ushort  bios_addr ;
+
+    /*
+     * The PCI BIOS is re-located by the motherboard BIOS. Because
+     * of this the driver can not determine where a PCI BIOS is
+     * loaded and executes.
+     */
+    if (bus_type & ASC_IS_PCI)
+    {
+        return(0);
     }
-    return (1);
+
+    if((bus_type & ASC_IS_EISA) != 0)
+    {
+        cfg_lsw = AscGetEisaChipCfg(iop_base) ;
+        cfg_lsw &= 0x000F ;
+        bios_addr = (ushort)(ASC_BIOS_MIN_ADDR  +
+                                (cfg_lsw * ASC_BIOS_BANK_SIZE)) ;
+        return(bios_addr) ;
+    }/* if */
+
+    cfg_lsw = AscGetChipCfgLsw(iop_base) ;
+
+    /*
+    *  ISA PnP uses the top bit as the 32K BIOS flag
+    */
+    if (bus_type == ASC_IS_ISAPNP)
+    {
+        cfg_lsw &= 0x7FFF;
+    }/* if */
+
+    bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) +
+            ASC_BIOS_MIN_ADDR) ;
+    return(bios_addr) ;
 }
 
-STATIC int
-AscStopChip(
-               PortAddr iop_base
-)
+
+/*
+ * --- Functions Required by the Adv Library
+ */
+
+/*
+ * DvcGetPhyAddr()
+ *
+ * Return the physical address of 'vaddr' and set '*lenp' to the
+ * number of physically contiguous bytes that follow 'vaddr'.
+ * 'flag' indicates the type of structure whose physical address
+ * is being translated.
+ *
+ * Note: Because Linux currently doesn't page the kernel and all
+ * kernel buffers are physically contiguous, leave '*lenp' unchanged.
+ */
+ulong
+DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
+        uchar *vaddr, long *lenp, int flag)
 {
-    uchar               cc_val;
-    cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
-    AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
-    AscSetChipIH(iop_base, INS_HALT);
-    AscSetChipIH(iop_base, INS_RFLAG_WTM);
-    if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
-        return (0);
-    }
-    return (1);
+    ulong                paddr;
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+    paddr = (ulong) vaddr;
+#else /* version >= v2.0.0 */
+    paddr = virt_to_bus(vaddr);
+#endif /* version >= v2.0.0 */
+
+    ASC_DBG4(4,
+        "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", 
+        (ulong) vaddr, (ulong) lenp, (ulong) *((ulong *) lenp), paddr);
+
+    return paddr;
 }
 
-STATIC int
-AscIsChipHalted(
-                   PortAddr iop_base
+/*
+ * Read a PCI configuration byte.
+ */
+ASC_INITFUNC(
+STATIC uchar
+DvcAdvReadPCIConfigByte(
+        ADV_DVC_VAR *asc_dvc, 
+        ushort offset)
 )
 {
-    if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
-        if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
-            return (1);
-        }
-    }
-    return (0);
-}
+    PCI_DATA    pciData;
 
-STATIC void
-AscSetChipIH(
-                PortAddr iop_base,
-                ushort ins_code
-)
-{
-    AscSetBank(iop_base, 1);
-    AscWriteChipIH(iop_base, ins_code);
-    AscSetBank(iop_base, 0);
-    return;
+    pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
+    pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
+    pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
+    pciData.offset = offset;
+    pciData.type = pci_scan_method;
+    return asc_get_cfg_byte(&pciData);
 }
 
+/*
+ * Write a PCI configuration byte.
+ */
+ASC_INITFUNC(
 STATIC void
-AscAckInterrupt(
-                   PortAddr iop_base
+DvcAdvWritePCIConfigByte(
+        ADV_DVC_VAR *asc_dvc, 
+        ushort offset, 
+        uchar  byte_data)
 )
 {
-    uchar               host_flag;
-    uchar               risc_flag;
-    ushort              loop;
-    loop = 0;
-    do {
-        risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
-        if (loop++ > 0x7FFF) {
-            break;
-        }
-    } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
-    host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
-    AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
-                     (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
-    AscSetChipStatus(iop_base, CIW_INT_ACK);
-    loop = 0;
-    while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
-        AscSetChipStatus(iop_base, CIW_INT_ACK);
-        if (loop++ > 3) {
-            break;
-        }
-    }
-    AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
-    return;
-}
+    PCI_DATA    pciData;
 
-STATIC void
-AscDisableInterrupt(
-                       PortAddr iop_base
-)
-{
-    ushort              cfg;
-    cfg = AscGetChipCfgLsw(iop_base);
-    AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
-    return;
+    pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
+    pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info);
+    pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info);
+    pciData.offset = offset;
+    pciData.type = pci_scan_method;
+    asc_put_cfg_byte(&pciData, byte_data);
 }
 
-STATIC void
-AscEnableInterrupt(
-                      PortAddr iop_base
-)
+/*
+ * --- Tracing and Debugging Functions
+ */
+
+#ifdef ADVANSYS_STATS
+/*
+ * asc_prt_board_stats()
+ *
+ * Note: no single line should be greater than ASC_PRTLINE_SIZE,
+ * cf. asc_prt_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
+STATIC int
+asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
 {
-    ushort              cfg;
-    cfg = AscGetChipCfgLsw(iop_base);
-    AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
-    return;
-}
+    int                    leftlen;
+    int                    totlen;
+    int                    len;
+    struct asc_stats       *s;
+    int                    i;
+    ushort                 chip_scsi_id;
+    asc_board_t            *boardp;
+    asc_queue_t            *active;
+    asc_queue_t            *waiting;
 
+    leftlen = cplen;
+    totlen = len = 0;
 
+    boardp = ASC_BOARDP(shp);
+    s = &boardp->asc_stats;
 
-STATIC void
-AscSetBank(
-              PortAddr iop_base,
-              uchar bank
-)
-{
-    uchar               val;
-    val = AscGetChipControl(iop_base) &
-      (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
-    if (bank == 1) {
-        val |= CC_BANK_ONE;
-    } else if (bank == 2) {
-        val |= CC_DIAG | CC_BANK_ONE;
+    len = asc_prt_line(cp, leftlen,
+"\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no);
+    ASC_PRT_NEXT();
+    
+    len = asc_prt_line(cp, leftlen,
+" command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu\n",
+        s->command, s->queuecommand, s->abort, s->reset, s->biosparam);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" interrupt %lu, callback %lu, done %lu\n",
+        s->interrupt, s->callback, s->done);
+    ASC_PRT_NEXT();
+
+    len = asc_prt_line(cp, leftlen,
+" exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
+        s->exe_noerror, s->exe_busy, s->exe_error, s->exe_unknown);
+    ASC_PRT_NEXT();
+
+    if (ASC_NARROW_BOARD(boardp)) {
+        len = asc_prt_line(cp, leftlen,
+" build_error %lu\n",
+         s->build_error);
     } else {
-        val &= ~CC_BANK_ONE;
+        len = asc_prt_line(cp, leftlen,
+" build_error %lu, build_noreq %lu, build_nosg %lu\n",
+         s->build_error, s->adv_build_noreq, s->adv_build_nosg);
     }
-    AscSetChipControl(iop_base, val);
-    return;
-}
+    ASC_PRT_NEXT();
 
+    /*
+     * Display data transfer statistics.
+     */
+    if (s->cont_cnt > 0) {
+        len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
+        ASC_PRT_NEXT();
 
+        len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
+                    s->cont_xfer/2,
+                    ASC_TENTHS(s->cont_xfer, 2));
+        ASC_PRT_NEXT();
 
-STATIC int
-AscResetChipAndScsiBus(
-                          PortAddr iop_base
-)
-{
-    while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
-    AscStopChip(iop_base);
-    AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
-    DvcSleepMilliSecond(200);
-    AscSetChipIH(iop_base, INS_RFLAG_WTM);
-    AscSetChipIH(iop_base, INS_HALT);
-    AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
-    AscSetChipControl(iop_base, CC_HALT);
-    DvcSleepMilliSecond(200);
-    AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
-    AscSetChipStatus(iop_base, 0);
-    return (AscIsChipHalted(iop_base));
-}
+        /* Contiguous transfer average size */
+        len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
+                    (s->cont_xfer/2)/s->cont_cnt,
+                    ASC_TENTHS((s->cont_xfer/2), s->cont_cnt));
+        ASC_PRT_NEXT();
+    }
 
-ASC_INITFUNC(
-STATIC ulong
-AscGetMaxDmaCount(
-                     ushort bus_type
-)
-)
-{
-    if (bus_type & ASC_IS_ISA)
-        return (ASC_MAX_ISA_DMA_COUNT);
-    else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
-        return (ASC_MAX_VL_DMA_COUNT);
-    return (ASC_MAX_PCI_DMA_COUNT);
-}
+    if (s->sg_cnt > 0) {
 
-ASC_INITFUNC(
-STATIC ushort
-AscGetIsaDmaChannel(
-                       PortAddr iop_base
-)
-)
-{
-    ushort              channel;
-    channel = AscGetChipCfgLsw(iop_base) & 0x0003;
-    if (channel == 0x03)
-        return (0);
-    else if (channel == 0x00)
-        return (7);
-    return (channel + 4);
-}
+        len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
+                    s->sg_cnt, s->sg_elem);
+        ASC_PRT_NEXT();
 
-ASC_INITFUNC(
-STATIC ushort
-AscSetIsaDmaChannel(
-                       PortAddr iop_base,
-                       ushort dma_channel
-)
-)
-{
-    ushort              cfg_lsw;
-    uchar               value;
-    if ((dma_channel >= 5) && (dma_channel <= 7)) {
-        if (dma_channel == 7)
-            value = 0x00;
-        else
-            value = dma_channel - 4;
-        cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
-        cfg_lsw |= value;
-        AscSetChipCfgLsw(iop_base, cfg_lsw);
-        return (AscGetIsaDmaChannel(iop_base));
+        len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
+                    s->sg_xfer/2,
+                    ASC_TENTHS(s->sg_xfer, 2));
+        ASC_PRT_NEXT();
+
+        /* Scatter gather transfer statistics */
+        len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
+                    s->sg_elem/s->sg_cnt,
+                    ASC_TENTHS(s->sg_elem, s->sg_cnt));
+        ASC_PRT_NEXT();
+
+        len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
+                    (s->sg_xfer/2)/s->sg_elem,
+                    ASC_TENTHS((s->sg_xfer/2), s->sg_elem));
+        ASC_PRT_NEXT();
+
+        len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
+                    (s->sg_xfer/2)/s->sg_cnt,
+                    ASC_TENTHS((s->sg_xfer/2), s->sg_cnt));
+        ASC_PRT_NEXT();
     }
-    return (0);
-}
 
-ASC_INITFUNC(
-STATIC uchar
-AscSetIsaDmaSpeed(
-                     PortAddr iop_base,
-                     uchar speed_value
-)
-)
-{
-    speed_value &= 0x07;
-    AscSetBank(iop_base, 1);
-    AscWriteChipDmaSpeed(iop_base, speed_value);
-    AscSetBank(iop_base, 0);
-    return (AscGetIsaDmaSpeed(iop_base));
-}
-
-ASC_INITFUNC(
-STATIC uchar
-AscGetIsaDmaSpeed(
-                     PortAddr iop_base
-)
-)
-{
-    uchar               speed_value;
-    AscSetBank(iop_base, 1);
-    speed_value = AscReadChipDmaSpeed(iop_base);
-    speed_value &= 0x07;
-    AscSetBank(iop_base, 0);
-    return (speed_value);
-}
-
-ASC_INITFUNC(
-STATIC ushort
-AscReadPCIConfigWord(
-    ASC_DVC_VAR asc_ptr_type *asc_dvc,
-    ushort pci_config_offset)
-)
-{
-    uchar       lsb, msb;
-
-    lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
-    msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
-    return ((ushort) ((msb << 8) | lsb));
-}
+    /*
+     * Display request queuing statistics.
+     */
+    len = asc_prt_line(cp, leftlen,
+" Active and Waiting Request Queues (Time Unit: %d HZ):\n", HZ);
+    ASC_PRT_NEXT();
 
-ASC_INITFUNC(
-STATIC ushort 
-AscInitGetConfig(
-        ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-)
-{
-    ushort              warn_code;
-    PortAddr            iop_base;
-    ushort              PCIDeviceID;
-    ushort              PCIVendorID;
-    uchar               PCIRevisionID;
-    uchar               prevCmdRegBits;
+    active = &ASC_BOARDP(shp)->active;
+    waiting = &ASC_BOARDP(shp)->waiting;
 
-    warn_code = 0;
-    iop_base = asc_dvc->iop_base;
-    asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
-    if (asc_dvc->err_code != 0) {
-        return (UW_ERR);
+    if (ASC_NARROW_BOARD(boardp)) {
+        chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
+    } else {
+        chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
     }
-    if (asc_dvc->bus_type == ASC_IS_PCI) {
-        PCIVendorID = AscReadPCIConfigWord(asc_dvc,
-                                    AscPCIConfigVendorIDRegister);
-
-        PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
-                                    AscPCIConfigDeviceIDRegister);
 
-        PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
-                                    AscPCIConfigRevisionIDRegister);
+    for (i = 0; i <= ADV_MAX_TID; i++) {
 
-        if (PCIVendorID != ASC_PCI_VENDORID) {
-            warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
+        if ((chip_scsi_id == i) ||
+            ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
+            continue;
         }
-        prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
-                                    AscPCIConfigCommandRegister);
 
-        if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
-            AscPCICmdRegBits_IOMemBusMaster) {
-            DvcWritePCIConfigByte(asc_dvc,
-                            AscPCIConfigCommandRegister,
-                            (prevCmdRegBits |
-                             AscPCICmdRegBits_IOMemBusMaster));
+        if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) {
+            len = asc_prt_line(cp, leftlen, " target %d\n", i);
+            ASC_PRT_NEXT();
 
-            if ((DvcReadPCIConfigByte(asc_dvc,
-                                AscPCIConfigCommandRegister)
-                 & AscPCICmdRegBits_IOMemBusMaster)
-                != AscPCICmdRegBits_IOMemBusMaster) {
-                warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
-            }
-        }
-        if ((PCIDeviceID == ASC_PCI_DEVICEID_1200A) ||
-            (PCIDeviceID == ASC_PCI_DEVICEID_1200B)) {
-            DvcWritePCIConfigByte(asc_dvc,
-                            AscPCIConfigLatencyTimer, 0x00);
-            if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer)
-                != 0x00) {
-                warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
-            }
-        } else if (PCIDeviceID == ASC_PCI_DEVICEID_ULTRA) {
-            if (DvcReadPCIConfigByte(asc_dvc,
-                                AscPCIConfigLatencyTimer) < 0x20) {
-                DvcWritePCIConfigByte(asc_dvc,
-                                    AscPCIConfigLatencyTimer, 0x20);
+            len = asc_prt_line(cp, leftlen,
+"   active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
+                active->q_cur_cnt[i], active->q_max_cnt[i],
+                active->q_tot_cnt[i],
+                active->q_min_tim[i], active->q_max_tim[i],
+                (active->q_tot_cnt[i] == 0) ? 0 :
+                (active->q_tot_tim[i]/active->q_tot_cnt[i]),
+                (active->q_tot_cnt[i] == 0) ? 0 :
+                ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i]));
+            ASC_PRT_NEXT();
 
-                if (DvcReadPCIConfigByte(asc_dvc,
-                                    AscPCIConfigLatencyTimer) < 0x20) {
-                    warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
-                }
-            }
+            len = asc_prt_line(cp, leftlen,
+"   waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
+                waiting->q_cur_cnt[i], waiting->q_max_cnt[i],
+                waiting->q_tot_cnt[i],
+                waiting->q_min_tim[i], waiting->q_max_tim[i],
+                (waiting->q_tot_cnt[i] == 0) ? 0 :
+                (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]),
+                (waiting->q_tot_cnt[i] == 0) ? 0 :
+                ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i]));
+            ASC_PRT_NEXT();
         }
     }
 
-    if (AscFindSignature(iop_base)) {
-        warn_code |= AscInitAscDvcVar(asc_dvc);
-        warn_code |= AscInitFromEEP(asc_dvc);
-        asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
-        if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) {
-            asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
-        }
-    } else {
-        asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
-    }
-    return(warn_code);
+     return totlen;
 }
+#endif /* ADVANSYS_STATS */
 
-ASC_INITFUNC(
-STATIC ushort
-AscInitSetConfig(
-                    ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-)
+#ifdef ADVANSYS_DEBUG
+/*
+ * asc_prt_scsi_host()
+ */
+STATIC void 
+asc_prt_scsi_host(struct Scsi_Host *s)
 {
-    ushort              warn_code;
-    warn_code = 0;
-    asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
-    if (asc_dvc->err_code != 0)
-        return (UW_ERR);
-    if (AscFindSignature(asc_dvc->iop_base)) {
-        warn_code |= AscInitFromAscDvcVar(asc_dvc);
-        asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
+    asc_board_t         *boardp;
+
+    boardp = ASC_BOARDP(s);
+
+    printk("Scsi_Host at addr %x\n", (unsigned) s);
+    printk(
+" next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n",
+        (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no,
+        (unsigned) s->last_reset);
+
+    printk(
+" host_wait %x, host_queue %x, hostt %x, block %x,\n",
+        (unsigned) s->host_wait, (unsigned) s->host_queue,
+        (unsigned) s->hostt, (unsigned) s->block);
+
+    printk(
+" wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n",
+        s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port,
+        s->irq, s->dma_channel);
+
+    printk(
+" this_id %d, can_queue %d,\n", s->this_id, s->can_queue);
+
+    printk(
+" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n",
+        s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma,
+        s->loaded_as_module);
+
+    if (ASC_NARROW_BOARD(boardp)) {
+        asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
+        asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
     } else {
-        asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+        asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
+        asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
     }
-    return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort
-AscInitFromAscDvcVar(
-                        ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-)
+/*
+ * asc_prt_scsi_cmnd()
+ */
+STATIC void 
+asc_prt_scsi_cmnd(Scsi_Cmnd *s)
 {
-    PortAddr            iop_base;
-    ushort              cfg_msw;
-    ushort              warn_code;
-    ushort              pci_device_id;
-    iop_base = asc_dvc->iop_base;
-    pci_device_id = asc_dvc->cfg->pci_device_id;
-    warn_code = 0;
-    cfg_msw = AscGetChipCfgMsw(iop_base);
-    if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
-        cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
-        warn_code |= ASC_WARN_CFG_MSW_RECOVER;
-        AscSetChipCfgMsw(iop_base, cfg_msw);
-    }
-    if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
-        asc_dvc->cfg->cmd_qng_enabled) {
-        asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
-        warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
-    }
-    if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
-        warn_code |= ASC_WARN_AUTO_CONFIG;
-    }
-    if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
-        if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
-            != asc_dvc->irq_no) {
-            asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
-        }
-    }
-    if (asc_dvc->bus_type & ASC_IS_PCI) {
-#if CC_DISABLE_PCI_PARITY_INT
-        cfg_msw &= 0xFFC0;
-        AscSetChipCfgMsw(iop_base, cfg_msw);
-#endif
-        if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
-        } else {
-            if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
-                (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
-                asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
-                asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
-            }
-        }
-    } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
-        if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
-            == ASC_CHIP_VER_ASYN_BUG) {
-            asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
-        }
-    }
-    if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
-        asc_dvc->cfg->chip_scsi_id) {
-        asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
-    }
+    printk("Scsi_Cmnd at addr %x\n", (unsigned) s);
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+    printk(
+" host %x, device %x, target %u, lun %u\n",
+        (unsigned) s->host, (unsigned) s->device, s->target, s->lun);
+#else /* version >= v1.3.0 */
+    printk(
+" host %x, device %x, target %u, lun %u, channel %u,\n",
+        (unsigned) s->host, (unsigned) s->device, s->target, s->lun,
+        s->channel);
+#endif /* version >= v1.3.0 */
+
+    asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
+
+    printk(
+" use_sg %u, sglist_len %u, abort_reason %x\n",
+        s->use_sg, s->sglist_len, s->abort_reason);
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+    printk(
+" retries %d, allowed %d\n",
+         s->retries, s->allowed);
+#else /* version >= v1.3.89 */
+    printk(
+" serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n",
+        (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
+         s->retries, s->allowed);
+#endif /* version >= v1.3.89 */
+
+    printk(
+" timeout_per_command %d, timeout_total %d, timeout %d\n",
+        s->timeout_per_command, s->timeout_total, s->timeout);
+
+    printk(
+" internal_timeout %u, flags %u, this_count %d\n",
+        s->internal_timeout, s->flags, s->this_count);
+
+    printk(
+" scsi_done %x, done %x, host_scribble %x, result %x\n",
+        (unsigned) s->scsi_done, (unsigned) s->done,
+        (unsigned) s->host_scribble, s->result);
+
+    printk(
+" tag %u, pid %u\n",
+        (unsigned) s->tag, (unsigned) s->pid);
+}
+
+/*
+ * asc_prt_asc_dvc_var()
+ */
+STATIC void 
+asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
+{
+    printk("ASC_DVC_VAR at addr %x\n", (unsigned) h);
+
+    printk(
+" iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n",
+        h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
+
+    printk(
+" bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n",
+        h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback,
+        (unsigned) h->init_sdtr);
+
+    printk(
+" sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n",
+        (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng,
+        (unsigned) h->unit_not_ready, (unsigned) h->chip_no);
+        
+    printk(
+" queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n",
+        (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor,
+        (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
+
+    printk(
+" is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n",
+        (unsigned) h->is_in_int, (unsigned) h->max_total_qng,
+        (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt);
+
+    printk(
+" last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n",
+        (unsigned) h->last_q_shortage, (unsigned) h->init_state,
+        (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer);
+
+    printk(
+" cfg %x, saved_ptr2func %x\n",
+        (unsigned) h->cfg, (unsigned) h->saved_ptr2func);
+}
+
+/*
+ * asc_prt_asc_dvc_cfg()
+ */
+STATIC void 
+asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
+{
+    printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
+
+    printk(
+" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n",
+            h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res);
+
+    printk(
+" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
+             h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
+             h->chip_version);
+
+    printk(
+" pci_device_id %d, lib_serial_no %x, lib_version %x, mcode_date %x,\n",
+          h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date);
+
+    printk(
+" mcode_version %d, overrun_buf %x\n",
+            h->mcode_version, (unsigned) h->overrun_buf);
+}
+
+/*
+ * asc_prt_asc_scsi_q()
+ */
+STATIC void 
+asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
+{
+    ASC_SG_HEAD    *sgp;
+    int i;
+
+    printk("ASC_SCSI_Q at addr %x\n", (unsigned) q);
+
+    printk(
+" target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n",
+            q->q2.target_ix, q->q1.target_lun,
+            (unsigned) q->q2.srb_ptr, q->q2.tag_code);
+
+    printk(
+" data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n",
+            (unsigned) q->q1.data_addr, q->q1.data_cnt,
+            (unsigned) q->q1.sense_addr, q->q1.sense_len);
+
+    printk(
+" cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n",
+            (unsigned) q->cdbptr, q->q2.cdb_len,
+            (unsigned) q->sg_head, q->q1.sg_queue_cnt);
+
+    if (q->sg_head) {
+        sgp = q->sg_head;
+        printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp);
+        printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt);
+        for (i = 0; i < sgp->entry_cnt; i++) {
+            printk(" [%u]: addr %x, bytes %lu\n",
+                i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes);
+        }
+
+    }
+}
+
+/*
+ * asc_prt_asc_qdone_info()
+ */
+STATIC void 
+asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
+{
+    printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q);
+    printk(
+" srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n",
+            (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
+            q->d2.tag_code, q->d3.done_stat);
+    printk(
+" host_stat %x, scsi_stat %x, scsi_msg %x\n",
+            q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
+}
+
+/*
+ * asc_prt_adv_dvc_var()
+ *
+ * Display an ADV_DVC_VAR structure.
+ */
+STATIC void 
+asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
+{
+    printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong) h);
+
+    printk(
+"  iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
+        (ulong) h->iop_base, h->err_code, (unsigned) h->ultra_able);
+
+    printk(
+"  isr_callback 0x%x, sdtr_able 0x%x, wdtr_able 0x%x\n",
+        (unsigned) h->isr_callback, (unsigned) h->wdtr_able,
+        (unsigned) h->sdtr_able);
+
+    printk(
+"  start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
+        (unsigned) h->start_motor,
+        (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no);
+
+    printk(
+"  max_host_qng 0x%x, cur_host_qng 0x%x, max_dvc_qng 0x%x\n",
+        (unsigned) h->max_host_qng, (unsigned) h->cur_host_qng,
+        (unsigned) h->max_dvc_qng);
+
+    printk(
+"  no_scam 0x%x, tagqng_able 0x%x, chip_scsi_id 0x%x, cfg 0x%lx\n",
+        (unsigned) h->no_scam, (unsigned) h->tagqng_able,
+        (unsigned) h->chip_scsi_id, (ulong) h->cfg);
+
+}
+
+/*
+ * asc_prt_adv_dvc_cfg()
+ *
+ * Display an ADV_DVC_CFG structure.
+ */
+STATIC void 
+asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
+{
+    printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong) h);
+
+    printk(
+"  disc_enable 0x%x, termination 0x%x\n",
+        h->disc_enable, h->termination);
+
+    printk(
+"  chip_version 0x%x, mcode_date 0x%x\n",
+        h->chip_version, h->mcode_date);
+
+    printk(
+"  mcode_version 0x%x, pci_device_id 0x%x, lib_version 0x%x\n",
+       h->mcode_version, h->pci_device_id, h->lib_version);
+
+    printk(
+"  control_flag 0x%x, pci_slot_info 0x%x\n",
+       h->control_flag, h->pci_slot_info);
+}
+
+/*
+ * asc_prt_adv_scsi_req_q()
+ *
+ * Display an ADV_SCSI_REQ_Q structure.
+ */
+STATIC void 
+asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
+{
+    int                 i;
+    struct asc_sg_block *sg_ptr;
+
+    printk("ADV_SCSI_REQ_Q at addr %x\n", (unsigned) q);
+
+    printk(
+"  target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
+            q->target_id, q->target_lun, q->srb_ptr, q->a_flag);
+
+    printk("  cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
+            q->cntl, q->data_addr, q->vdata_addr);
+
+    printk(
+"  data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
+            q->data_cnt, q->sense_addr, q->sense_len);
+
+    printk(
+"  cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
+            q->cdb_len, q->done_status, q->host_status, q->scsi_status);
+
+    printk(
+"  vsense_addr 0x%lx, scsiq_ptr 0x%lx, ux_wk_data_cnt %lu\n",
+            (ulong) q->vsense_addr, (ulong) q->scsiq_ptr,
+            (ulong) q->ux_wk_data_cnt);
+
+    printk(
+"  sg_list_ptr 0x%lx, sg_real_addr 0x%lx, sg_entry_cnt %u\n",
+            (ulong) q->sg_list_ptr, (ulong) q->sg_real_addr, q->sg_entry_cnt);
+
+    printk(
+"  ux_sg_ix %u, orig_sense_len %u\n",
+            q->ux_sg_ix, q->orig_sense_len);
+
+    /* Display the request's ADV_SG_BLOCK structures. */
+    for (sg_ptr = q->sg_list_ptr, i = 0; sg_ptr != NULL;
+        sg_ptr = sg_ptr->sg_ptr, i++) {
+        /*
+         * 'sg_ptr' is a physical address. Convert it to a virtual
+         * address by indexing 'i' into the virtual address array
+         * 'sg_list_ptr'.
+         *
+         * At the end of the each iteration of the loop 'sg_ptr' is
+         * converted back into a physical address by setting 'sg_ptr'
+         *  to the next pointer 'sg_ptr->sg_ptr'.
+         */
+        sg_ptr = &(((ADV_SG_BLOCK *) (q->sg_list_ptr))[i]);
+        asc_prt_adv_sgblock(i, sg_ptr);
+    }
+}
+
+/*
+ * asc_prt_adv_sgblock()
+ *
+ * Display an ADV_SG_BLOCK structure.
+ */
+STATIC void
+asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
+{
+    int i, s;
+
+    /* Calculate starting entry number for the current block. */
+    s = sgblockno * NO_OF_SG_PER_BLOCK;
+
+    printk(" ADV_SG_BLOCK at addr 0x%lx (sgblockno %lu)\n",
+        (ulong) b, (ulong) sgblockno);
+    printk(
+"  first_entry_no %lu, last_entry_no %lu, sg_ptr 0x%lx\n",
+        (ulong) b->first_entry_no, (ulong) b->last_entry_no, (ulong) b->sg_ptr);
+    ASC_ASSERT(b->first_entry_no - s >= 0);
+    ASC_ASSERT(b->last_entry_no - s >= 0);
+    ASC_ASSERT(b->last_entry_no - s <= NO_OF_SG_PER_BLOCK);
+    ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK);
+    ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK);
+    ASC_ASSERT(b->first_entry_no - s <= b->last_entry_no - s);
+    for (i = b->first_entry_no - s; i <= b->last_entry_no - s; i++) {
+        printk("  [%lu]: sg_addr 0x%lx, sg_count 0x%lx\n",
+            (ulong) i, (ulong) b->sg_list[i].sg_addr,
+            (ulong) b->sg_list[i].sg_count);
+    }
+}
+
+/*
+ * asc_prt_hex()
+ *
+ * Print hexadecimal output in 4 byte groupings 32 bytes 
+ * or 8 double-words per line.
+ */
+STATIC void 
+asc_prt_hex(char *f, uchar *s, int l)
+{
+    int            i;
+    int            j;
+    int            k;
+    int            m;
+
+    printk("%s: (%d bytes)\n", f, l);
+
+    for (i = 0; i < l; i += 32) {
+        
+        /* Display a maximum of 8 double-words per line. */
+        if ((k = (l - i) / 4) >= 8) {
+            k = 8;
+            m = 0;
+        } else {
+            m = (l - i) % 4 ;
+        }
+
+        for (j = 0; j < k; j++) {
+            printk(" %2.2X%2.2X%2.2X%2.2X",
+                (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1],
+                (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]);
+        }
+
+        switch (m) {
+        case 0:
+        default:
+            break;
+        case 1:
+            printk(" %2.2X",
+                (unsigned) s[i+(j*4)]);
+            break;
+        case 2:
+            printk(" %2.2X%2.2X",
+                (unsigned) s[i+(j*4)],
+                (unsigned) s[i+(j*4)+1]);
+            break;
+        case 3:
+            printk(" %2.2X%2.2X%2.2X",
+                (unsigned) s[i+(j*4)+1],
+                (unsigned) s[i+(j*4)+2],
+                (unsigned) s[i+(j*4)+3]);
+            break;
+        }
+
+        printk("\n");
+    }
+}
+#endif /* ADVANSYS_DEBUG */
+
+#ifdef ADVANSYS_ASSERT
+/*
+ * interrupts_enabled()
+ *
+ * Return 1 if interrupts are enabled, otherwise return 0.
+ */
+STATIC int
+interrupts_enabled(void)
+{
+    int flags;
+
+    save_flags(flags);
+    if (flags & 0x0200) {
+        return ASC_TRUE;
+    } else {
+        return ASC_FALSE;
+    }
+}
+#endif /* ADVANSYS_ASSERT */
+
+
+/*
+ * --- Asc Library Functions
+ */
+
+ASC_INITFUNC(
+STATIC ushort
+AscGetEisaChipCfg(
+                     PortAddr iop_base
+)
+)
+{
+    PortAddr            eisa_cfg_iop;
+
+    eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
+      (PortAddr) (ASC_EISA_CFG_IOP_MASK);
+    return (inpw(eisa_cfg_iop));
+}
+
+ASC_INITFUNC(
+STATIC uchar
+AscSetChipScsiID(
+                    PortAddr iop_base,
+                    uchar new_host_id
+)
+)
+{
+    ushort              cfg_lsw;
+
+    if (AscGetChipScsiID(iop_base) == new_host_id) {
+        return (new_host_id);
+    }
+    cfg_lsw = AscGetChipCfgLsw(iop_base);
+    cfg_lsw &= 0xF8FF;
+    cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8);
+    AscSetChipCfgLsw(iop_base, cfg_lsw);
+    return (AscGetChipScsiID(iop_base));
+}
+
+ASC_INITFUNC(
+STATIC uchar
+AscGetChipScsiCtrl(
+                      PortAddr iop_base
+)
+)
+{
+    uchar               sc;
+
+    AscSetBank(iop_base, 1);
+    sc = inp(iop_base + IOP_REG_SC);
+    AscSetBank(iop_base, 0);
+    return (sc);
+}
+
+ASC_INITFUNC(
+STATIC uchar
+AscGetChipVersion(
+                     PortAddr iop_base,
+                     ushort bus_type
+)
+)
+{
+    if ((bus_type & ASC_IS_EISA) != 0) {
+        PortAddr            eisa_iop;
+        uchar               revision;
+        eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
+          (PortAddr) ASC_EISA_REV_IOP_MASK;
+        revision = inp(eisa_iop);
+        return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision));
+    }
+    return (AscGetChipVerNo(iop_base));
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscGetChipBusType(
+                     PortAddr iop_base
+)
+)
+{
+    ushort              chip_ver;
+
+    chip_ver = AscGetChipVerNo(iop_base);
+    if (
+           (chip_ver >= ASC_CHIP_MIN_VER_VL)
+           && (chip_ver <= ASC_CHIP_MAX_VER_VL)
+) {
+        if (
+               ((iop_base & 0x0C30) == 0x0C30)
+               || ((iop_base & 0x0C50) == 0x0C50)
+) {
+            return (ASC_IS_EISA);
+        }
+        return (ASC_IS_VL);
+    }
+    if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) &&
+        (chip_ver <= ASC_CHIP_MAX_VER_ISA)) {
+        if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) {
+            return (ASC_IS_ISAPNP);
+        }
+        return (ASC_IS_ISA);
+    } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) &&
+               (chip_ver <= ASC_CHIP_MAX_VER_PCI)) {
+        return (ASC_IS_PCI);
+    }
+    return (0);
+}
+
+ASC_INITFUNC(
+STATIC ulong
+AscLoadMicroCode(
+                    PortAddr iop_base,
+                    ushort s_addr,
+                    ushort *mcode_buf,
+                    ushort mcode_size
+)
+)
+{
+    ulong               chksum;
+    ushort              mcode_word_size;
+    ushort              mcode_chksum;
+
+    mcode_word_size = (ushort) (mcode_size >> 1);
+    AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
+    AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
+    chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
+    mcode_chksum = (ushort) AscMemSumLramWord(iop_base,
+                                              (ushort) ASC_CODE_SEC_BEG,
+          (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2));
+    AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
+    AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
+    return (chksum);
+}
+
+ASC_INITFUNC(
+STATIC int
+AscFindSignature(
+                    PortAddr iop_base
+)
+)
+{
+    ushort              sig_word;
+
+    if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) {
+        sig_word = AscGetChipSignatureWord(iop_base);
+        if ((sig_word == (ushort) ASC_1000_ID0W) ||
+            (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
+            return (1);
+        }
+    }
+    return (0);
+}
+
+STATIC uchar _isa_pnp_inited ASC_INITDATA = 0;
+STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA =
+{
+    0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4,
+    ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
+};
+
+ASC_INITFUNC(
+STATIC PortAddr
+AscSearchIOPortAddr(
+                       PortAddr iop_beg,
+                       ushort bus_type
+)
+)
+{
+    if (bus_type & ASC_IS_VL) {
+        while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
+            if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) {
+                return (iop_beg);
+            }
+        }
+        return (0);
+    }
+    if (bus_type & ASC_IS_ISA) {
+        if (_isa_pnp_inited == 0) {
+            AscSetISAPNPWaitForKey();
+            _isa_pnp_inited++;
+        }
+        while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
+            if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) {
+                return (iop_beg);
+            }
+        }
+        return (0);
+    }
+    if (bus_type & ASC_IS_EISA) {
+        if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) {
+            return (iop_beg);
+        }
+        return (0);
+    }
+    return (0);
+}
+
+ASC_INITFUNC(
+STATIC PortAddr
+AscSearchIOPortAddr11(
+                         PortAddr s_addr
+)
+)
+{
+    int                 i;
+    PortAddr            iop_base;
+
+    for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
+        if (_asc_def_iop_base[i] > s_addr) {
+            break;
+        }
+    }
+    for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
+        iop_base = _asc_def_iop_base[i];
+        if (check_region(iop_base, ASC_IOADR_GAP) != 0) {
+            ASC_DBG1(1,
+               "AscSearchIOPortAddr11: check_region() failed I/O port %x\n",
+                     iop_base);
+            continue;
+        }
+        ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port %x\n", iop_base);
+        if (AscFindSignature(iop_base)) {
+            return (iop_base);
+        }
+    }
+    return (0);
+}
+
+ASC_INITFUNC(
+STATIC void
+AscToggleIRQAct(
+                   PortAddr iop_base
+)
+)
+{
+    AscSetChipStatus(iop_base, CIW_IRQ_ACT);
+    AscSetChipStatus(iop_base, 0);
+    return;
+}
+
+ASC_INITFUNC(
+STATIC void
+AscSetISAPNPWaitForKey(
+    void)
+)
+{
+    outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
+    outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
+    return;
+}
+
+ASC_INITFUNC(
+STATIC uchar
+AscGetChipIRQ(
+                 PortAddr iop_base,
+                 ushort bus_type
+)
+)
+{
+    ushort              cfg_lsw;
+    uchar               chip_irq;
+
+    if ((bus_type & ASC_IS_EISA) != 0) {
+        cfg_lsw = AscGetEisaChipCfg(iop_base);
+        chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10);
+        if ((chip_irq == 13) || (chip_irq > 15)) {
+            return (0);
+        }
+        return (chip_irq);
+    }
+    if ((bus_type & ASC_IS_VL) != 0) {
+        cfg_lsw = AscGetChipCfgLsw(iop_base);
+        chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07));
+        if ((chip_irq == 0) ||
+            (chip_irq == 4) ||
+            (chip_irq == 7)) {
+            return (0);
+        }
+        return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1)));
+    }
+    cfg_lsw = AscGetChipCfgLsw(iop_base);
+    chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
+    if (chip_irq == 3)
+        chip_irq += (uchar) 2;
+    return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
+}
+
+ASC_INITFUNC(
+STATIC uchar
+AscSetChipIRQ(
+                 PortAddr iop_base,
+                 uchar irq_no,
+                 ushort bus_type
+)
+)
+{
+    ushort              cfg_lsw;
+
+    if ((bus_type & ASC_IS_VL) != 0) {
+        if (irq_no != 0) {
+            if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) {
+                irq_no = 0;
+            } else {
+                irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1));
+            }
+        }
+        cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3);
+        cfg_lsw |= (ushort) 0x0010;
+        AscSetChipCfgLsw(iop_base, cfg_lsw);
+        AscToggleIRQAct(iop_base);
+        cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0);
+        cfg_lsw |= (ushort) ((irq_no & 0x07) << 2);
+        AscSetChipCfgLsw(iop_base, cfg_lsw);
+        AscToggleIRQAct(iop_base);
+        return (AscGetChipIRQ(iop_base, bus_type));
+    }
+    if ((bus_type & (ASC_IS_ISA)) != 0) {
+        if (irq_no == 15)
+            irq_no -= (uchar) 2;
+        irq_no -= (uchar) ASC_MIN_IRQ_NO;
+        cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3);
+        cfg_lsw |= (ushort) ((irq_no & 0x03) << 2);
+        AscSetChipCfgLsw(iop_base, cfg_lsw);
+        return (AscGetChipIRQ(iop_base, bus_type));
+    }
+    return (0);
+}
+
+ASC_INITFUNC(
+STATIC void
+AscEnableIsaDma(
+                   uchar dma_channel
+)
+)
+{
+    if (dma_channel < 4) {
+        outp(0x000B, (ushort) (0xC0 | dma_channel));
+        outp(0x000A, dma_channel);
+    } else if (dma_channel < 8) {
+        outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4)));
+        outp(0x00D4, (ushort) (dma_channel - 4));
+    }
+    return;
+}
+
+STATIC int 
+AscIsrChipHalted(
+                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    EXT_MSG             ext_msg;
+    EXT_MSG             out_msg;
+    ushort              halt_q_addr;
+    int                 sdtr_accept;
+    ushort              int_halt_code;
+    ASC_SCSI_BIT_ID_TYPE scsi_busy;
+    ASC_SCSI_BIT_ID_TYPE target_id;
+    PortAddr            iop_base;
+    uchar               tag_code;
+    uchar               q_status;
+    uchar               halt_qp;
+    uchar               sdtr_data;
+    uchar               target_ix;
+    uchar               q_cntl, tid_no;
+    uchar               cur_dvc_qng;
+    uchar               asyn_sdtr;
+    uchar               scsi_status;
+    asc_board_t            *boardp;
+
+    ASC_ASSERT(asc_dvc->drv_ptr != 0);
+    boardp = (asc_board_t *) asc_dvc->drv_ptr;
+
+    iop_base = asc_dvc->iop_base;
+    int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
+
+    halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
+    halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
+    target_ix = AscReadLramByte(iop_base,
+                   (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX));
+    q_cntl = AscReadLramByte(iop_base,
+                        (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL));
+    tid_no = ASC_TIX_TO_TID(target_ix);
+    target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no);
+    if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+
+        asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
+    } else {
+        asyn_sdtr = 0;
+    }
+    if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
+        if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+            AscSetChipSDTR(iop_base, 0, tid_no);
+            boardp->sdtr_data[tid_no] = 0;
+        }
+        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+        return (0);
+    } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
+        if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+            AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+            boardp->sdtr_data[tid_no] = asyn_sdtr;
+        }
+        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+        return (0);
+    } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
+
+        AscMemWordCopyFromLram(iop_base,
+                               ASCV_MSGIN_BEG,
+                               (ushort *) & ext_msg,
+                               (ushort) (sizeof (EXT_MSG) >> 1));
+
+        if (ext_msg.msg_type == MS_EXTEND &&
+            ext_msg.msg_req == MS_SDTR_CODE &&
+            ext_msg.msg_len == MS_SDTR_LEN) {
+            sdtr_accept = TRUE;
+            if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
+
+                sdtr_accept = FALSE;
+                ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
+            }
+            if ((ext_msg.xfer_period <
+                 asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) ||
+                (ext_msg.xfer_period >
+                 asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) {
+                sdtr_accept = FALSE;
+                ext_msg.xfer_period =
+                    asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index];
+            }
+            if (sdtr_accept) {
+                sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
+                                           ext_msg.req_ack_offset);
+                if ((sdtr_data == 0xFF)) {
+
+                    q_cntl |= QC_MSG_OUT;
+                    asc_dvc->init_sdtr &= ~target_id;
+                    asc_dvc->sdtr_done &= ~target_id;
+                    AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+                    boardp->sdtr_data[tid_no] = asyn_sdtr;
+                }
+            }
+            if (ext_msg.req_ack_offset == 0) {
+
+                q_cntl &= ~QC_MSG_OUT;
+                asc_dvc->init_sdtr &= ~target_id;
+                asc_dvc->sdtr_done &= ~target_id;
+                AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+            } else {
+                if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
+
+                    q_cntl &= ~QC_MSG_OUT;
+                    asc_dvc->sdtr_done |= target_id;
+                    asc_dvc->init_sdtr |= target_id;
+                    asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+                    sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
+                                               ext_msg.req_ack_offset);
+                    AscSetChipSDTR(iop_base, sdtr_data, tid_no);
+                    boardp->sdtr_data[tid_no] = sdtr_data;
+                } else {
+
+                    q_cntl |= QC_MSG_OUT;
+                    AscMsgOutSDTR(asc_dvc,
+                                  ext_msg.xfer_period,
+                                  ext_msg.req_ack_offset);
+                    asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+                    sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
+                                               ext_msg.req_ack_offset);
+                    AscSetChipSDTR(iop_base, sdtr_data, tid_no);
+                    boardp->sdtr_data[tid_no] = sdtr_data;
+                    asc_dvc->sdtr_done |= target_id;
+                    asc_dvc->init_sdtr |= target_id;
+                }
+            }
+
+            AscWriteLramByte(iop_base,
+                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
+                             q_cntl);
+            AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+            return (0);
+        } else if (ext_msg.msg_type == MS_EXTEND &&
+                   ext_msg.msg_req == MS_WDTR_CODE &&
+                   ext_msg.msg_len == MS_WDTR_LEN) {
+
+            ext_msg.wdtr_width = 0;
+            AscMemWordCopyToLram(iop_base,
+                                 ASCV_MSGOUT_BEG,
+                                 (ushort *) & ext_msg,
+                                 (ushort) (sizeof (EXT_MSG) >> 1));
+            q_cntl |= QC_MSG_OUT;
+            AscWriteLramByte(iop_base,
+                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
+                             q_cntl);
+            AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+            return (0);
+        } else {
+
+            ext_msg.msg_type = M1_MSG_REJECT;
+            AscMemWordCopyToLram(iop_base,
+                                 ASCV_MSGOUT_BEG,
+                                 (ushort *) & ext_msg,
+                                 (ushort) (sizeof (EXT_MSG) >> 1));
+            q_cntl |= QC_MSG_OUT;
+            AscWriteLramByte(iop_base,
+                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
+                             q_cntl);
+            AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+            return (0);
+        }
+    } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
+
+        q_cntl |= QC_REQ_SENSE;
+
+        if ((asc_dvc->init_sdtr & target_id) != 0) {
+
+            asc_dvc->sdtr_done &= ~target_id;
+
+            sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
+            q_cntl |= QC_MSG_OUT;
+            AscMsgOutSDTR(asc_dvc,
+                          asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
+                           (uchar) (asc_dvc->max_sdtr_index - 1)],
+                          (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
+        }
+
+        AscWriteLramByte(iop_base,
+                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
+                         q_cntl);
+
+        tag_code = AscReadLramByte(iop_base,
+                    (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
+        tag_code &= 0xDC;
+        if (
+               (asc_dvc->pci_fix_asyn_xfer & target_id)
+               && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
+) {
+
+            tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
+                         | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
+
+        }
+        AscWriteLramByte(iop_base,
+                     (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE),
+                         tag_code);
+
+        q_status = AscReadLramByte(iop_base,
+                      (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS));
+        q_status |= (QS_READY | QS_BUSY);
+        AscWriteLramByte(iop_base,
+                       (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+                         q_status);
+
+        scsi_busy = AscReadLramByte(iop_base,
+                                    (ushort) ASCV_SCSIBUSY_B);
+        scsi_busy &= ~target_id;
+        AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy);
+
+        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+        return (0);
+    } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
+
+        AscMemWordCopyFromLram(iop_base,
+                               ASCV_MSGOUT_BEG,
+                               (ushort *) & out_msg,
+                               (ushort) (sizeof (EXT_MSG) >> 1));
+
+        if ((out_msg.msg_type == MS_EXTEND) &&
+            (out_msg.msg_len == MS_SDTR_LEN) &&
+            (out_msg.msg_req == MS_SDTR_CODE)) {
+
+            asc_dvc->init_sdtr &= ~target_id;
+            asc_dvc->sdtr_done &= ~target_id;
+            AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
+            boardp->sdtr_data[tid_no] = asyn_sdtr;
+        }
+        q_cntl &= ~QC_MSG_OUT;
+        AscWriteLramByte(iop_base,
+                         (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL),
+                         q_cntl);
+        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+        return (0);
+    } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
+
+        scsi_status = AscReadLramByte(iop_base,
+          (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS));
+        cur_dvc_qng = AscReadLramByte(iop_base,
+                     (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix));
+        if ((cur_dvc_qng > 0) &&
+            (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
+
+            scsi_busy = AscReadLramByte(iop_base,
+                                        (ushort) ASCV_SCSIBUSY_B);
+            scsi_busy |= target_id;
+            AscWriteLramByte(iop_base,
+                             (ushort) ASCV_SCSIBUSY_B, scsi_busy);
+            asc_dvc->queue_full_or_busy |= target_id;
+
+            if (scsi_status == SS_QUEUE_FULL) {
+                if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
+                    cur_dvc_qng -= 1;
+                    asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng;
+
+                    AscWriteLramByte(iop_base,
+                          (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG +
+                           (ushort) tid_no),
+                          cur_dvc_qng);
+
+                    /*
+                     * Set the device queue depth to the number of
+                     * active requests when the QUEUE FULL condition
+                     * was encountered.
+                     */
+                    boardp->queue_full |= target_id;
+                    boardp->queue_full_cnt[tid_no] = cur_dvc_qng;
+#if ASC_QUEUE_FLOW_CONTROL
+                    if (boardp->device[tid_no] != NULL &&
+                        boardp->device[tid_no]->queue_curr_depth >
+                        cur_dvc_qng) {
+                        boardp->device[tid_no]->queue_curr_depth =
+                            cur_dvc_qng;
+                    }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+                }
+            }
+        }
+        AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+        return (0);
+    }
+    return (0);
+}
+
+STATIC uchar
+_AscCopyLramScsiDoneQ(
+                         PortAddr iop_base,
+                         ushort q_addr,
+                         REG ASC_QDONE_INFO * scsiq,
+                         ulong max_dma_count
+)
+{
+    ushort              _val;
+    uchar               sg_queue_cnt;
+
+    DvcGetQinfo(iop_base,
+                (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
+                (ushort *) scsiq,
+              (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2));
+    _val = AscReadLramWord(iop_base,
+                           (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS));
+    scsiq->q_status = (uchar) _val;
+    scsiq->q_no = (uchar) (_val >> 8);
+    _val = AscReadLramWord(iop_base,
+                           (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL));
+    scsiq->cntl = (uchar) _val;
+    sg_queue_cnt = (uchar) (_val >> 8);
+    _val = AscReadLramWord(iop_base,
+                        (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN));
+    scsiq->sense_len = (uchar) _val;
+    scsiq->extra_bytes = (uchar) (_val >> 8);
+    scsiq->remain_bytes = AscReadLramWord(iop_base,
+                 (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
+    scsiq->remain_bytes &= max_dma_count;
+    return (sg_queue_cnt);
+}
+
+STATIC int
+AscIsrQDone(
+               REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    uchar               next_qp;
+    uchar               n_q_used;
+    uchar               sg_list_qp;
+    uchar               sg_queue_cnt;
+    uchar               q_cnt;
+    uchar               done_q_tail;
+    uchar               tid_no;
+    ASC_SCSI_BIT_ID_TYPE scsi_busy;
+    ASC_SCSI_BIT_ID_TYPE target_id;
+    PortAddr            iop_base;
+    ushort              q_addr;
+    ushort              sg_q_addr;
+    uchar               cur_target_qng;
+    ASC_QDONE_INFO      scsiq_buf;
+    REG ASC_QDONE_INFO *scsiq;
+    int                 false_overrun;
+    ASC_ISR_CALLBACK    asc_isr_callback;
+
+    iop_base = asc_dvc->iop_base;
+    asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+    n_q_used = 1;
+    scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
+    done_q_tail = (uchar) AscGetVarDoneQTail(iop_base);
+    q_addr = ASC_QNO_TO_QADDR(done_q_tail);
+    next_qp = AscReadLramByte(iop_base,
+                              (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD));
+    if (next_qp != ASC_QLINK_END) {
+        AscPutVarDoneQTail(iop_base, next_qp);
+        q_addr = ASC_QNO_TO_QADDR(next_qp);
+        sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
+            asc_dvc->max_dma_count);
+        AscWriteLramByte(iop_base,
+                         (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+             (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED)));
+        tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
+        target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
+        if ((scsiq->cntl & QC_SG_HEAD) != 0) {
+            sg_q_addr = q_addr;
+            sg_list_qp = next_qp;
+            for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
+                sg_list_qp = AscReadLramByte(iop_base,
+                           (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD));
+                sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
+                if (sg_list_qp == ASC_QLINK_END) {
+                    AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS);
+                    scsiq->d3.done_stat = QD_WITH_ERROR;
+                    scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED;
+                    goto FATAL_ERR_QDONE;
+                }
+                AscWriteLramByte(iop_base,
+                         (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+                                 QS_FREE);
+            }
+            n_q_used = sg_queue_cnt + 1;
+            AscPutVarDoneQTail(iop_base, sg_list_qp);
+        }
+        if (asc_dvc->queue_full_or_busy & target_id) {
+            cur_target_qng = AscReadLramByte(iop_base,
+            (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix));
+            if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
+                scsi_busy = AscReadLramByte(iop_base,
+                                            (ushort) ASCV_SCSIBUSY_B);
+                scsi_busy &= ~target_id;
+                AscWriteLramByte(iop_base,
+                                 (ushort) ASCV_SCSIBUSY_B, scsi_busy);
+                asc_dvc->queue_full_or_busy &= ~target_id;
+            }
+        }
+        if (asc_dvc->cur_total_qng >= n_q_used) {
+            asc_dvc->cur_total_qng -= n_q_used;
+            if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
+                asc_dvc->cur_dvc_qng[tid_no]--;
+            }
+        } else {
+            AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
+            scsiq->d3.done_stat = QD_WITH_ERROR;
+            goto FATAL_ERR_QDONE;
+        }
+        if ((scsiq->d2.srb_ptr == 0UL) ||
+            ((scsiq->q_status & QS_ABORTED) != 0)) {
+            return (0x11);
+        } else if (scsiq->q_status == QS_DONE) {
+            false_overrun = FALSE;
+            if (scsiq->extra_bytes != 0) {
+                scsiq->remain_bytes += (ulong) scsiq->extra_bytes;
+            }
+            if (scsiq->d3.done_stat == QD_WITH_ERROR) {
+                if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) {
+                    if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
+                        scsiq->d3.done_stat = QD_NO_ERROR;
+                        scsiq->d3.host_stat = QHSTA_NO_ERROR;
+                    } else if (false_overrun) {
+                        scsiq->d3.done_stat = QD_NO_ERROR;
+                        scsiq->d3.host_stat = QHSTA_NO_ERROR;
+                    }
+                } else if (scsiq->d3.host_stat ==
+                           QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
+                    AscStopChip(iop_base);
+                    AscSetChipControl(iop_base,
+                        (uchar) (CC_SCSI_RESET | CC_HALT));
+                    DvcDelayNanoSecond(asc_dvc, 60000);
+                    AscSetChipControl(iop_base, CC_HALT);
+                    AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
+                    AscSetChipStatus(iop_base, 0);
+                    AscSetChipControl(iop_base, 0);
+                }
+            }
+            if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
+                (*asc_isr_callback) (asc_dvc, scsiq);
+            } else {
+                if ((AscReadLramByte(iop_base,
+                          (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) ==
+                     SCSICMD_StartStopUnit)) {
+                    asc_dvc->unit_not_ready &= ~target_id;
+                    if (scsiq->d3.done_stat != QD_NO_ERROR) {
+                        asc_dvc->start_motor &= ~target_id;
+                    }
+                }
+            }
+            return (1);
+        } else {
+            AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
+          FATAL_ERR_QDONE:
+            if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
+                (*asc_isr_callback) (asc_dvc, scsiq);
+            }
+            return (0x80);
+        }
+    }
+    return (0);
+}
+
+STATIC int
+AscISR(
+          REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    ASC_CS_TYPE         chipstat;
+    PortAddr            iop_base;
+    ushort              saved_ram_addr;
+    uchar               ctrl_reg;
+    uchar               saved_ctrl_reg;
+    int                 int_pending;
+    int                 status;
+    uchar               host_flag;
+
+    iop_base = asc_dvc->iop_base;
+    int_pending = FALSE;
+    if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0)
+        || (asc_dvc->isr_callback == 0)
+) {
+        return (ERR);
+    }
+    if (asc_dvc->in_critical_cnt != 0) {
+        AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
+        return (ERR);
+    }
+    if (asc_dvc->is_in_int) {
+        AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
+        return (ERR);
+    }
+    asc_dvc->is_in_int = TRUE;
+    ctrl_reg = AscGetChipControl(iop_base);
+    saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
+                                   CC_SINGLE_STEP | CC_DIAG | CC_TEST));
+    chipstat = AscGetChipStatus(iop_base);
+    if (chipstat & CSW_SCSI_RESET_LATCH) {
+        if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
+            int_pending = TRUE;
+            asc_dvc->sdtr_done = 0;
+            saved_ctrl_reg &= (uchar) (~CC_HALT);
+            while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
+            AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
+            AscSetChipControl(iop_base, CC_HALT);
+            AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
+            AscSetChipStatus(iop_base, 0);
+            chipstat = AscGetChipStatus(iop_base);
+        }
+    }
+    saved_ram_addr = AscGetChipLramAddr(iop_base);
+    host_flag = AscReadLramByte(iop_base,
+        ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR);
+    AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
+                     (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
+    if ((chipstat & CSW_INT_PENDING)
+        || (int_pending)
+) {
+        AscAckInterrupt(iop_base);
+        int_pending = TRUE;
+        if ((chipstat & CSW_HALTED) &&
+            (ctrl_reg & CC_SINGLE_STEP)) {
+            if (AscIsrChipHalted(asc_dvc) == ERR) {
+                goto ISR_REPORT_QDONE_FATAL_ERROR;
+            } else {
+                saved_ctrl_reg &= (uchar) (~CC_HALT);
+            }
+        } else {
+          ISR_REPORT_QDONE_FATAL_ERROR:
+            if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
+                while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) {
+                }
+            } else {
+                do {
+                    if ((status = AscIsrQDone(asc_dvc)) == 1) {
+                        break;
+                    }
+                } while (status == 0x11);
+            }
+            if ((status & 0x80) != 0)
+                int_pending = ERR;
+        }
+    }
+    AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
+    AscSetChipLramAddr(iop_base, saved_ram_addr);
+    AscSetChipControl(iop_base, saved_ctrl_reg);
+    asc_dvc->is_in_int = FALSE;
+    return (int_pending);
+}
+
+STATIC int
+AscScsiSetupCmdQ(
+                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                    REG ASC_SCSI_REQ_Q * scsiq,
+                    uchar * buf_addr,
+                    ulong buf_len
+)
+{
+    ulong               phy_addr;
+
+    scsiq->r1.cntl = 0;
+    scsiq->r1.sg_queue_cnt = 0;
+    scsiq->r1.q_no = 0;
+    scsiq->r1.extra_bytes = 0;
+    scsiq->r3.scsi_stat = 0;
+    scsiq->r3.scsi_msg = 0;
+    scsiq->r3.host_stat = 0;
+    scsiq->r3.done_stat = 0;
+    scsiq->r2.vm_id = 0;
+    scsiq->r1.data_cnt = buf_len;
+    scsiq->cdbptr = (uchar *) scsiq->cdb;
+    scsiq->sense_ptr = (uchar *) scsiq->sense ;
+    scsiq->r1.sense_len = ASC_MIN_SENSE_LEN ;
+    scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE;
+    scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ;
+    scsiq->r2.srb_ptr = (ulong) scsiq;
+    scsiq->r1.status = (uchar) QS_READY;
+    scsiq->r1.data_addr = 0L;
+    if (buf_len != 0L) {
+        if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+                    (uchar *) buf_addr, scsiq->r1.data_cnt)) == 0L) {
+            return (ERR);
+        }
+        scsiq->r1.data_addr = phy_addr;
+    }
+    if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+                       (uchar *) scsiq->sense_ptr,
+                       (ulong) scsiq->r1.sense_len)) == 0L) {
+        return (ERR);
+    }
+    scsiq->r1.sense_addr = phy_addr ;
+    return (0);
+}
+
+STATIC uchar _asc_mcode_buf[] ASC_INITDATA =
+{
+  0x01,  0x03,  0x01,  0x19,  0x0F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0xDB,  0x0C,  0x0A,  0x05,  0x01,  0x00,  0x00,  0x00,  0x00,  0xFF,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0xFF,  0x80,  0xFF,  0xFF,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x23,  0x00,  0x23,  0x00,  0x00,  0x00,  0x07,  0x00,  0xFF,  0x00,  0x00,  0x00,  0x00,
+  0xFF,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xD4,  0x88,  0x00,  0x00,  0x00,  0x00,
+  0x80,  0x73,  0x48,  0x04,  0x36,  0x00,  0x00,  0xA2,  0xC2,  0x00,  0x80,  0x73,  0x03,  0x23,  0x36,  0x40,
+  0xB6,  0x00,  0x36,  0x00,  0x05,  0xD6,  0x0C,  0xD2,  0x12,  0xDA,  0x00,  0xA2,  0xC2,  0x00,  0x92,  0x80,
+  0x10,  0x98,  0x50,  0x00,  0xF5,  0x00,  0x3A,  0x98,  0xDF,  0x23,  0x36,  0x60,  0xB6,  0x00,  0x92,  0x80,
+  0x4F,  0x00,  0xF5,  0x00,  0x3A,  0x98,  0xEF,  0x23,  0x36,  0x60,  0xB6,  0x00,  0x92,  0x80,  0x80,  0x62,
+  0x92,  0x80,  0x00,  0x46,  0x17,  0xEE,  0x13,  0xEA,  0x02,  0x01,  0x09,  0xD8,  0xCD,  0x04,  0x4D,  0x00,
+  0x00,  0xA3,  0xD6,  0x00,  0x98,  0x97,  0x7F,  0x23,  0x04,  0x61,  0x84,  0x01,  0xE0,  0x84,  0xD2,  0xC1,
+  0x80,  0x73,  0xCD,  0x04,  0x4D,  0x00,  0x00,  0xA3,  0xE2,  0x01,  0x98,  0x97,  0xCE,  0x81,  0x00,  0x33,
+  0x02,  0x00,  0xB2,  0x88,  0x80,  0x73,  0x80,  0x77,  0x00,  0x01,  0x01,  0xA1,  0x02,  0x01,  0x4F,  0x00,
+  0x76,  0x97,  0x07,  0xA6,  0x0C,  0x01,  0x00,  0x33,  0x03,  0x00,  0xB2,  0x88,  0x03,  0x03,  0x03,  0xDE,
+  0x00,  0x33,  0x05,  0x00,  0xB2,  0x88,  0xCE,  0x00,  0x69,  0x60,  0xCE,  0x00,  0x02,  0x03,  0x4A,  0x60,
+  0x00,  0xA2,  0x80,  0x01,  0x80,  0x63,  0x07,  0xA6,  0x2C,  0x01,  0x80,  0x81,  0x03,  0x03,  0x80,  0x63,
+  0xE2,  0x00,  0x07,  0xA6,  0x3C,  0x01,  0x00,  0x33,  0x04,  0x00,  0xB2,  0x88,  0x03,  0x07,  0x02,  0x01,
+  0x04,  0xCA,  0x0D,  0x23,  0x5A,  0x98,  0x4D,  0x04,  0xFE,  0x84,  0x05,  0xD8,  0x0D,  0x23,  0x5A,  0x98,
+  0xCD,  0x04,  0x15,  0x23,  0xE8,  0x88,  0xFB,  0x23,  0x02,  0x61,  0x82,  0x01,  0x80,  0x63,  0x02,  0x03,
+  0x06,  0xA3,  0x6A,  0x01,  0x00,  0x33,  0x0A,  0x00,  0xB2,  0x88,  0x4E,  0x00,  0x07,  0xA3,  0x76,  0x01,
+  0x00,  0x33,  0x0B,  0x00,  0xB2,  0x88,  0xCD,  0x04,  0x36,  0x2D,  0x00,  0x33,  0x1A,  0x00,  0xB2,  0x88,
+  0x50,  0x04,  0x90,  0x81,  0x06,  0xAB,  0x8A,  0x01,  0x90,  0x81,  0x4E,  0x00,  0x07,  0xA3,  0x9A,  0x01,
+  0x50,  0x00,  0x00,  0xA3,  0x44,  0x01,  0x00,  0x05,  0x84,  0x81,  0x38,  0x97,  0x02,  0x01,  0x05,  0xC6,
+  0x04,  0x23,  0xA0,  0x01,  0x15,  0x23,  0xA1,  0x01,  0xC6,  0x81,  0xFD,  0x23,  0x02,  0x61,  0x82,  0x01,
+  0x0A,  0xDA,  0x4A,  0x00,  0x06,  0x61,  0x00,  0xA0,  0xBC,  0x01,  0x80,  0x63,  0xCD,  0x04,  0x36,  0x2D,
+  0x00,  0x33,  0x1B,  0x00,  0xB2,  0x88,  0x06,  0x23,  0x5A,  0x98,  0xCD,  0x04,  0xE0,  0x84,  0x06,  0x01,
+  0x00,  0xA2,  0xDC,  0x01,  0x57,  0x60,  0x00,  0xA0,  0xE2,  0x01,  0xE0,  0x84,  0x80,  0x23,  0xA0,  0x01,
+  0xE0,  0x84,  0x80,  0x73,  0x4B,  0x00,  0x06,  0x61,  0x00,  0xA2,  0x08,  0x02,  0x04,  0x01,  0x0C,  0xDE,
+  0x02,  0x01,  0x03,  0xCC,  0x4F,  0x00,  0x76,  0x97,  0x04,  0x82,  0x08,  0x23,  0x02,  0x41,  0x82,  0x01,
+  0x4F,  0x00,  0x54,  0x97,  0x48,  0x04,  0x84,  0x80,  0xE2,  0x97,  0x00,  0x46,  0x56,  0x00,  0x03,  0xC0,
+  0x01,  0x23,  0xE8,  0x00,  0x81,  0x73,  0x06,  0x29,  0x03,  0x42,  0x06,  0xE2,  0x03,  0xEE,  0x67,  0xEB,
+  0x11,  0x23,  0xE8,  0x88,  0xF6,  0x97,  0xF4,  0x80,  0x80,  0x73,  0x80,  0x77,  0x06,  0xA6,  0x36,  0x02,
+  0x00,  0x33,  0x31,  0x00,  0xB2,  0x88,  0x04,  0x01,  0x03,  0xD8,  0xA4,  0x98,  0x4C,  0x96,  0x48,  0x82,
+  0xDC,  0x95,  0x80,  0x67,  0x83,  0x03,  0x80,  0x63,  0xB6,  0x2D,  0x02,  0xA6,  0x72,  0x02,  0x07,  0xA6,
+  0x60,  0x02,  0x06,  0xA6,  0x64,  0x02,  0x03,  0xA6,  0x68,  0x02,  0x00,  0x33,  0x10,  0x00,  0xB2,  0x88,
+  0x76,  0x95,  0x4A,  0x82,  0x42,  0x96,  0x4A,  0x82,  0x04,  0x23,  0xA0,  0x01,  0x14,  0x23,  0xA1,  0x01,
+  0x36,  0x84,  0x04,  0x01,  0x0C,  0xDC,  0xE0,  0x23,  0x25,  0x61,  0xEF,  0x00,  0x14,  0x01,  0x4F,  0x04,
+  0xA8,  0x01,  0x6F,  0x00,  0xA5,  0x01,  0x03,  0x23,  0xA4,  0x01,  0x06,  0x23,  0x9C,  0x01,  0x24,  0x2B,
+  0x1C,  0x01,  0x02,  0xA6,  0xB0,  0x02,  0x07,  0xA6,  0x60,  0x02,  0x06,  0xA6,  0x64,  0x02,  0x03,  0xA6,
+  0x1A,  0x04,  0x01,  0xA6,  0xBA,  0x02,  0x00,  0xA6,  0xBA,  0x02,  0x00,  0x33,  0x12,  0x00,  0xB2,  0x88,
+  0x00,  0x0E,  0x80,  0x63,  0x00,  0x43,  0x00,  0xA0,  0x92,  0x02,  0x4D,  0x04,  0x04,  0x01,  0x0B,  0xDC,
+  0xE7,  0x23,  0x04,  0x61,  0x84,  0x01,  0x10,  0x31,  0x12,  0x35,  0x14,  0x01,  0xEC,  0x00,  0x6C,  0x38,
+  0x00,  0x3F,  0x00,  0x00,  0xF0,  0x82,  0x18,  0x23,  0x04,  0x61,  0x18,  0xA0,  0xE8,  0x02,  0x04,  0x01,
+  0x9C,  0xC8,  0x00,  0x33,  0x1F,  0x00,  0xB2,  0x88,  0x08,  0x31,  0x0A,  0x35,  0x0C,  0x39,  0x0E,  0x3D,
+  0x70,  0x98,  0xB6,  0x2D,  0x01,  0xA6,  0x1A,  0x03,  0x00,  0xA6,  0x1A,  0x03,  0x07,  0xA6,  0x12,  0x03,
+  0x06,  0xA6,  0x16,  0x03,  0x03,  0xA6,  0x1A,  0x04,  0x02,  0xA6,  0x72,  0x02,  0x00,  0x33,  0x33,  0x00,
+  0xB2,  0x88,  0x76,  0x95,  0xF4,  0x82,  0x42,  0x96,  0xF4,  0x82,  0x74,  0x98,  0x80,  0x42,  0x70,  0x98,
+  0x60,  0xE4,  0x04,  0x01,  0x29,  0xC8,  0x31,  0x05,  0x07,  0x01,  0x00,  0xA2,  0x5A,  0x03,  0x00,  0x43,
+  0x87,  0x01,  0x05,  0x05,  0x78,  0x98,  0x70,  0x98,  0x00,  0xA6,  0x1C,  0x03,  0x07,  0xA6,  0x52,  0x03,
+  0x03,  0xA6,  0x36,  0x04,  0x06,  0xA6,  0x56,  0x03,  0x01,  0xA6,  0x1C,  0x03,  0x00,  0x33,  0x25,  0x00,
+  0xB2,  0x88,  0x76,  0x95,  0x38,  0x83,  0x42,  0x96,  0x38,  0x83,  0x04,  0x01,  0x0C,  0xCE,  0x03,  0xC8,
+  0x00,  0x33,  0x42,  0x00,  0xB2,  0x88,  0x00,  0x01,  0x05,  0x05,  0xFF,  0xA2,  0x78,  0x03,  0xB1,  0x01,
+  0x08,  0x23,  0xB2,  0x01,  0x34,  0x83,  0x05,  0x05,  0x15,  0x01,  0x00,  0xA2,  0x98,  0x03,  0xEC,  0x00,
+  0x6E,  0x00,  0x95,  0x01,  0x6C,  0x38,  0x00,  0x3F,  0x00,  0x00,  0x01,  0xA6,  0x94,  0x03,  0x00,  0xA6,
+  0x94,  0x03,  0x0C,  0x84,  0x80,  0x42,  0x70,  0x98,  0x01,  0xA6,  0xA2,  0x03,  0x00,  0xA6,  0xBA,  0x03,
+  0x0C,  0x84,  0x98,  0x98,  0x80,  0x42,  0x01,  0xA6,  0xA2,  0x03,  0x07,  0xA6,  0xB0,  0x03,  0xD2,  0x83,
+  0x76,  0x95,  0xA6,  0x83,  0x00,  0x33,  0x2F,  0x00,  0xB2,  0x88,  0x98,  0x98,  0x80,  0x42,  0x00,  0xA6,
+  0xBA,  0x03,  0x07,  0xA6,  0xC8,  0x03,  0xD2,  0x83,  0x76,  0x95,  0xBE,  0x83,  0x00,  0x33,  0x26,  0x00,
+  0xB2,  0x88,  0x38,  0x2B,  0x80,  0x32,  0x80,  0x36,  0x04,  0x23,  0xA0,  0x01,  0x12,  0x23,  0xA1,  0x01,
+  0x0C,  0x84,  0x06,  0xF0,  0x06,  0xA4,  0xF0,  0x03,  0x80,  0x6B,  0x05,  0x23,  0x83,  0x03,  0x80,  0x63,
+  0x03,  0xA6,  0x0A,  0x04,  0x07,  0xA6,  0x02,  0x04,  0x06,  0xA6,  0x06,  0x04,  0x00,  0x33,  0x17,  0x00,
+  0xB2,  0x88,  0x76,  0x95,  0xF0,  0x83,  0x42,  0x96,  0xF0,  0x83,  0x1A,  0x84,  0x06,  0xF0,  0x06,  0xA4,
+  0x1A,  0x04,  0x80,  0x6B,  0x05,  0x23,  0x83,  0x03,  0x80,  0x63,  0xB6,  0x2D,  0x03,  0xA6,  0x36,  0x04,
+  0x07,  0xA6,  0x2E,  0x04,  0x06,  0xA6,  0x32,  0x04,  0x00,  0x33,  0x30,  0x00,  0xB2,  0x88,  0x76,  0x95,
+  0x1A,  0x84,  0x42,  0x96,  0x1A,  0x84,  0x1D,  0x01,  0x06,  0xCC,  0x00,  0x33,  0x00,  0x84,  0xC0,  0x20,
+  0x00,  0x23,  0xEA,  0x00,  0x81,  0x62,  0xA2,  0x0D,  0x80,  0x63,  0x07,  0xA6,  0x54,  0x04,  0x00,  0x33,
+  0x18,  0x00,  0xB2,  0x88,  0x03,  0x03,  0x80,  0x63,  0xA3,  0x01,  0x07,  0xA4,  0x5E,  0x04,  0x23,  0x01,
+  0x00,  0xA2,  0x80,  0x04,  0x0A,  0xA0,  0x70,  0x04,  0xE0,  0x00,  0x00,  0x33,  0x1D,  0x00,  0xB2,  0x88,
+  0x0B,  0xA0,  0x7C,  0x04,  0xE0,  0x00,  0x00,  0x33,  0x1E,  0x00,  0xB2,  0x88,  0x42,  0x23,  0xE8,  0x88,
+  0x00,  0x23,  0x22,  0xA3,  0xE0,  0x04,  0x08,  0x23,  0x22,  0xA3,  0x9C,  0x04,  0x28,  0x23,  0x22,  0xA3,
+  0xA8,  0x04,  0x02,  0x23,  0x22,  0xA3,  0xBE,  0x04,  0x42,  0x23,  0xE8,  0x88,  0x4A,  0x00,  0x06,  0x61,
+  0x00,  0xA0,  0xA8,  0x04,  0x45,  0x23,  0xE8,  0x88,  0xF6,  0x97,  0x00,  0xA2,  0xBA,  0x04,  0xA4,  0x98,
+  0x00,  0x33,  0x00,  0x82,  0xC0,  0x20,  0x81,  0x62,  0xF0,  0x81,  0x47,  0x23,  0xE8,  0x88,  0x04,  0x01,
+  0x0B,  0xDE,  0xF6,  0x97,  0xA4,  0x98,  0x00,  0x33,  0x00,  0x81,  0xC0,  0x20,  0x81,  0x62,  0x14,  0x01,
+  0x00,  0xA0,  0x08,  0x02,  0x43,  0x23,  0xE8,  0x88,  0x04,  0x23,  0xA0,  0x01,  0x44,  0x23,  0xA1,  0x01,
+  0x80,  0x73,  0x4D,  0x00,  0x03,  0xA3,  0xEE,  0x04,  0x00,  0x33,  0x27,  0x00,  0xB2,  0x88,  0x04,  0x01,
+  0x04,  0xDC,  0x02,  0x23,  0xA2,  0x01,  0x04,  0x23,  0xA0,  0x01,  0xF6,  0x97,  0x20,  0x95,  0x4B,  0x00,
+  0xF6,  0x00,  0x4F,  0x04,  0x4F,  0x00,  0x00,  0xA3,  0x1C,  0x05,  0x00,  0x05,  0x76,  0x00,  0x06,  0x61,
+  0x00,  0xA2,  0x16,  0x05,  0x04,  0x85,  0x38,  0x97,  0xCD,  0x04,  0x1E,  0x85,  0x48,  0x04,  0x84,  0x80,
+  0x02,  0x01,  0x03,  0xDA,  0x80,  0x23,  0x82,  0x01,  0x2E,  0x85,  0x02,  0x23,  0xA0,  0x01,  0x4A,  0x00,
+  0x06,  0x61,  0x00,  0xA2,  0x3A,  0x05,  0x1D,  0x01,  0x04,  0xD6,  0xFF,  0x23,  0x86,  0x41,  0x4B,  0x60,
+  0xCB,  0x00,  0xFF,  0x23,  0x80,  0x01,  0x49,  0x00,  0x81,  0x01,  0x04,  0x01,  0x02,  0xC8,  0x30,  0x01,
+  0x80,  0x01,  0xF7,  0x04,  0x03,  0x01,  0x49,  0x04,  0x80,  0x01,  0xC9,  0x00,  0x00,  0x05,  0x00,  0x01,
+  0xFF,  0xA0,  0x5A,  0x05,  0x77,  0x04,  0x01,  0x23,  0xEA,  0x00,  0x5D,  0x00,  0xFE,  0xC7,  0x00,  0x62,
+  0x00,  0x23,  0xEA,  0x00,  0x00,  0x63,  0x07,  0xA4,  0xDA,  0x05,  0x03,  0x03,  0x02,  0xA0,  0x88,  0x05,
+  0xD6,  0x85,  0x00,  0x33,  0x2D,  0x00,  0xB2,  0x88,  0x04,  0xA0,  0xAE,  0x05,  0x80,  0x63,  0x4A,  0x00,
+  0x06,  0x61,  0x00,  0xA2,  0x9A,  0x05,  0x1D,  0x01,  0x06,  0xD6,  0x02,  0x23,  0x02,  0x41,  0x82,  0x01,
+  0x50,  0x00,  0x54,  0x97,  0xFE,  0x84,  0x04,  0x23,  0x02,  0x41,  0x82,  0x01,  0xFE,  0x84,  0x08,  0xA0,
+  0xB4,  0x05,  0xD6,  0x85,  0x03,  0xA0,  0xBA,  0x05,  0xD6,  0x85,  0x01,  0xA0,  0xC4,  0x05,  0x88,  0x00,
+  0x80,  0x63,  0xB2,  0x86,  0x07,  0xA0,  0xD0,  0x05,  0x06,  0x23,  0x5A,  0x98,  0x48,  0x23,  0xE8,  0x88,
+  0x07,  0x23,  0x80,  0x00,  0xF8,  0x86,  0x80,  0x63,  0x76,  0x85,  0x00,  0x63,  0x4A,  0x00,  0x06,  0x61,
+  0x00,  0xA2,  0x18,  0x06,  0x1D,  0x01,  0x18,  0xD4,  0xC0,  0x23,  0x07,  0x41,  0x83,  0x03,  0x80,  0x63,
+  0x06,  0xA6,  0xFA,  0x05,  0x00,  0x33,  0x37,  0x00,  0xB2,  0x88,  0x1D,  0x01,  0x02,  0xD6,  0x46,  0x23,
+  0xE8,  0x88,  0x63,  0x60,  0x83,  0x03,  0x80,  0x63,  0x06,  0xA6,  0x12,  0x06,  0x00,  0x33,  0x38,  0x00,
+  0xB2,  0x88,  0xEF,  0x04,  0x6F,  0x00,  0x00,  0x63,  0x4B,  0x00,  0x06,  0x41,  0xCB,  0x00,  0x52,  0x00,
+  0x06,  0x61,  0x00,  0xA2,  0x30,  0x06,  0x1D,  0x01,  0x03,  0xCA,  0xC0,  0x23,  0x07,  0x41,  0x00,  0x63,
+  0x1D,  0x01,  0x04,  0xCC,  0x00,  0x33,  0x00,  0x83,  0xC0,  0x20,  0x81,  0x62,  0x80,  0x23,  0x07,  0x41,
+  0x00,  0x63,  0x80,  0x67,  0x08,  0x23,  0x83,  0x03,  0x80,  0x63,  0x00,  0x63,  0x06,  0xA6,  0x5E,  0x06,
+  0x07,  0xA6,  0x76,  0x05,  0x02,  0xA6,  0xEC,  0x06,  0x00,  0x33,  0x39,  0x00,  0xB2,  0x88,  0x00,  0x00,
+  0x01,  0xA0,  0x06,  0x07,  0xDC,  0x95,  0x83,  0x03,  0x80,  0x63,  0x06,  0xA6,  0x72,  0x06,  0x07,  0xA6,
+  0x76,  0x05,  0x00,  0x00,  0x01,  0xA0,  0x06,  0x07,  0x00,  0x2B,  0x40,  0x0E,  0x80,  0x63,  0x01,  0x00,
+  0x06,  0xA6,  0x8E,  0x06,  0x07,  0xA6,  0x76,  0x05,  0x00,  0x33,  0x3A,  0x00,  0xB2,  0x88,  0x40,  0x0E,
+  0x80,  0x63,  0x00,  0x43,  0x00,  0xA0,  0x80,  0x06,  0x06,  0xA6,  0xA6,  0x06,  0x07,  0xA6,  0x76,  0x05,
+  0x00,  0x33,  0x3B,  0x00,  0xB2,  0x88,  0x80,  0x67,  0x40,  0x0E,  0x80,  0x63,  0x07,  0xA6,  0x76,  0x05,
+  0x00,  0x63,  0x07,  0xA6,  0xBC,  0x06,  0x00,  0x33,  0x2A,  0x00,  0xB2,  0x88,  0x03,  0x03,  0x80,  0x63,
+  0x89,  0x00,  0x0A,  0x2B,  0x07,  0xA6,  0xCE,  0x06,  0x00,  0x33,  0x29,  0x00,  0xB2,  0x88,  0x00,  0x43,
+  0x00,  0xA2,  0xDA,  0x06,  0xC0,  0x0E,  0x80,  0x63,  0xC4,  0x86,  0xC0,  0x0E,  0x00,  0x33,  0x00,  0x80,
+  0xC0,  0x20,  0x81,  0x62,  0x04,  0x01,  0x08,  0xDA,  0x80,  0x63,  0x76,  0x85,  0x80,  0x67,  0x00,  0x33,
+  0x00,  0x40,  0xC0,  0x20,  0x81,  0x62,  0x00,  0x63,  0x80,  0x7B,  0x80,  0x63,  0x06,  0xA6,  0x6A,  0x06,
+  0x00,  0x33,  0x2C,  0x00,  0xB2,  0x88,  0x0C,  0xA2,  0x20,  0x07,  0xDC,  0x95,  0x83,  0x03,  0x80,  0x63,
+  0x06,  0xA6,  0x1E,  0x07,  0x07,  0xA6,  0x76,  0x05,  0x00,  0x33,  0x3D,  0x00,  0xB2,  0x88,  0x00,  0x00,
+  0x80,  0x67,  0x83,  0x03,  0x80,  0x63,  0x0C,  0xA0,  0x36,  0x07,  0x07,  0xA6,  0x76,  0x05,  0xBF,  0x23,
+  0x04,  0x61,  0x84,  0x01,  0xE0,  0x84,  0x00,  0x63,  0xF0,  0x04,  0x01,  0x01,  0xF1,  0x00,  0x00,  0x01,
+  0xF2,  0x00,  0x01,  0x05,  0x80,  0x01,  0x72,  0x04,  0x71,  0x00,  0x81,  0x01,  0x70,  0x04,  0x80,  0x05,
+  0x81,  0x05,  0x00,  0x63,  0xF0,  0x04,  0xF2,  0x00,  0x72,  0x04,  0x01,  0x01,  0xF1,  0x00,  0x70,  0x00,
+  0x81,  0x01,  0x70,  0x04,  0x71,  0x00,  0x81,  0x01,  0x72,  0x00,  0x80,  0x01,  0x71,  0x04,  0x70,  0x00,
+  0x80,  0x01,  0x70,  0x04,  0x00,  0x63,  0xF0,  0x04,  0xF2,  0x00,  0x72,  0x04,  0x00,  0x01,  0xF1,  0x00,
+  0x70,  0x00,  0x80,  0x01,  0x70,  0x04,  0x71,  0x00,  0x80,  0x01,  0x72,  0x00,  0x81,  0x01,  0x71,  0x04,
+  0x70,  0x00,  0x81,  0x01,  0x70,  0x04,  0x00,  0x63,  0x00,  0x23,  0xB3,  0x01,  0x83,  0x05,  0xA3,  0x01,
+  0xA2,  0x01,  0xA1,  0x01,  0x01,  0x23,  0xA0,  0x01,  0x00,  0x01,  0xC8,  0x00,  0x03,  0xA1,  0xB6,  0x07,
+  0x00,  0x33,  0x07,  0x00,  0xB2,  0x88,  0x80,  0x05,  0x81,  0x05,  0x04,  0x01,  0x11,  0xC8,  0x48,  0x00,
+  0xB0,  0x01,  0xB1,  0x01,  0x08,  0x23,  0xB2,  0x01,  0x05,  0x01,  0x48,  0x04,  0x00,  0x43,  0x00,  0xA2,
+  0xD6,  0x07,  0x00,  0x05,  0xCC,  0x87,  0x00,  0x01,  0xC8,  0x00,  0xFF,  0x23,  0x80,  0x01,  0x05,  0x05,
+  0x00,  0x63,  0xF7,  0x04,  0x1A,  0x09,  0xF6,  0x08,  0x6E,  0x04,  0x00,  0x02,  0x80,  0x43,  0x76,  0x08,
+  0x80,  0x02,  0x77,  0x04,  0x00,  0x63,  0xF7,  0x04,  0x1A,  0x09,  0xF6,  0x08,  0x6E,  0x04,  0x00,  0x02,
+  0x00,  0xA0,  0x06,  0x08,  0x08,  0x88,  0x00,  0x43,  0x76,  0x08,  0x80,  0x02,  0x77,  0x04,  0x00,  0x63,
+  0xF3,  0x04,  0x00,  0x23,  0xF4,  0x00,  0x74,  0x00,  0x80,  0x43,  0xF4,  0x00,  0xCF,  0x40,  0x00,  0xA2,
+  0x36,  0x08,  0x74,  0x04,  0x02,  0x01,  0xF7,  0xC9,  0xF6,  0xD9,  0x00,  0x01,  0x01,  0xA1,  0x16,  0x08,
+  0xF6,  0x97,  0x20,  0x95,  0x16,  0x88,  0x73,  0x04,  0x00,  0x63,  0xF3,  0x04,  0x75,  0x04,  0x4C,  0x88,
+  0x02,  0x01,  0x04,  0xD8,  0x38,  0x97,  0xF6,  0x97,  0x20,  0x95,  0x3C,  0x88,  0x75,  0x00,  0x00,  0xA3,
+  0x56,  0x08,  0x00,  0x05,  0x40,  0x88,  0x73,  0x04,  0x00,  0x63,  0x80,  0x7B,  0x80,  0x63,  0x06,  0xA6,
+  0x68,  0x08,  0x00,  0x33,  0x3E,  0x00,  0xB2,  0x88,  0x80,  0x67,  0x83,  0x03,  0x80,  0x63,  0x00,  0x63,
+  0x38,  0x2B,  0x8E,  0x88,  0x38,  0x2B,  0x84,  0x88,  0x32,  0x09,  0x31,  0x05,  0x84,  0x98,  0x05,  0x05,
+  0xB2,  0x09,  0x00,  0x63,  0x00,  0x32,  0x00,  0x36,  0x00,  0x3A,  0x00,  0x3E,  0x00,  0x63,  0x80,  0x32,
+  0x80,  0x36,  0x80,  0x3A,  0x80,  0x3E,  0x00,  0x63,  0x38,  0x2B,  0x40,  0x32,  0x40,  0x36,  0x40,  0x3A,
+  0x40,  0x3E,  0x00,  0x63,  0x5A,  0x20,  0xC9,  0x40,  0x00,  0xA0,  0xA4,  0x08,  0x5D,  0x00,  0xFE,  0xC3,
+  0x00,  0x63,  0x80,  0x73,  0xE6,  0x20,  0x02,  0x23,  0xE8,  0x00,  0x82,  0x73,  0xFF,  0xFD,  0x80,  0x73,
+  0x13,  0x23,  0xE8,  0x88,  0x66,  0x20,  0xC0,  0x20,  0x04,  0x23,  0xA0,  0x01,  0xA1,  0x23,  0xA1,  0x01,
+  0x81,  0x62,  0xD2,  0x88,  0x80,  0x73,  0x80,  0x77,  0x68,  0x00,  0x00,  0xA2,  0x80,  0x00,  0x03,  0xC2,
+  0xF1,  0xC7,  0x41,  0x23,  0xE8,  0x88,  0x11,  0x23,  0xA1,  0x01,  0x04,  0x23,  0xA0,  0x01,  0xE0,  0x84,
+
+};
+
+STATIC ushort _asc_mcode_size ASC_INITDATA = sizeof(_asc_mcode_buf);
+STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012A727FUL ;
+
+#define ASC_SYN_OFFSET_ONE_DISABLE_LIST  16
+STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] =
+{
+    SCSICMD_Inquiry,
+    SCSICMD_RequestSense,
+    SCSICMD_ReadCapacity,
+    SCSICMD_ReadTOC,
+    SCSICMD_ModeSelect6,
+    SCSICMD_ModeSense6,
+    SCSICMD_ModeSelect10,
+    SCSICMD_ModeSense10,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF,
+    0xFF
+};
+
+STATIC int
+AscExeScsiQueue(
+                   REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                   REG ASC_SCSI_Q * scsiq
+)
+{
+    PortAddr            iop_base;
+    int                 last_int_level;
+    int                 sta;
+    int                 n_q_required;
+    int                 disable_syn_offset_one_fix;
+    int                 i;
+    ulong               addr;
+    ASC_EXE_CALLBACK    asc_exe_callback;
+    ushort              sg_entry_cnt = 0;
+    ushort              sg_entry_cnt_minus_one = 0;
+    uchar               target_ix;
+    uchar               tid_no;
+    uchar               sdtr_data;
+    uchar               extra_bytes;
+    uchar               scsi_cmd;
+    uchar               disable_cmd;
+    ASC_SG_HEAD *sg_head;
+    ulong               data_cnt;
+
+    iop_base = asc_dvc->iop_base;
+    sg_head = scsiq->sg_head;
+    asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
+    if (asc_dvc->err_code != 0)
+        return (ERR);
+    if (scsiq == (ASC_SCSI_Q *) 0L) {
+        AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
+        return (ERR);
+    }
+    scsiq->q1.q_no = 0;
+    if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
+        scsiq->q1.extra_bytes = 0;
+    }
+    sta = 0;
+    target_ix = scsiq->q2.target_ix;
+    tid_no = ASC_TIX_TO_TID(target_ix);
+    n_q_required = 1;
+    if (scsiq->cdbptr[0] == SCSICMD_RequestSense) {
+        if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
+            asc_dvc->sdtr_done &= ~scsiq->q1.target_id ;
+            sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
+            AscMsgOutSDTR(asc_dvc,
+                          asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) &
+                          (uchar) (asc_dvc->max_sdtr_index - 1)],
+                          (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
+            scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
+        }
+    }
+    last_int_level = DvcEnterCritical();
+    if (asc_dvc->in_critical_cnt != 0) {
+        DvcLeaveCritical(last_int_level);
+        AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
+        return (ERR);
+    }
+    asc_dvc->in_critical_cnt++;
+    if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
+        if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
+            asc_dvc->in_critical_cnt--;
+            DvcLeaveCritical(last_int_level);
+            return (ERR);
+        }
+        if (sg_entry_cnt > ASC_MAX_SG_LIST) {
+            return (ERR);
+        }
+        if (sg_entry_cnt == 1) {
+            scsiq->q1.data_addr = sg_head->sg_list[0].addr;
+            scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
+            scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
+        }
+        sg_entry_cnt_minus_one = sg_entry_cnt - 1;
+    }
+    scsi_cmd = scsiq->cdbptr[0];
+    disable_syn_offset_one_fix = FALSE;
+    if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
+        !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
+        if (scsiq->q1.cntl & QC_SG_HEAD) {
+            data_cnt = 0;
+            for (i = 0; i < sg_entry_cnt; i++) {
+                data_cnt += sg_head->sg_list[i].bytes;
+            }
+        } else {
+            data_cnt = scsiq->q1.data_cnt;
+        }
+        if (data_cnt != 0UL) {
+            if (data_cnt < 512UL) {
+                disable_syn_offset_one_fix = TRUE;
+            } else {
+                for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) {
+                    disable_cmd = _syn_offset_one_disable_cmd[i];
+                    if (disable_cmd == 0xFF) {
+                        break;
+                    }
+                    if (scsi_cmd == disable_cmd) {
+                        disable_syn_offset_one_fix = TRUE;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    if (disable_syn_offset_one_fix) {
+        scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
+        scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
+                               ASC_TAG_FLAG_DISABLE_DISCONNECT);
+    } else {
+        scsiq->q2.tag_code &= 0x23;
+    }
+    if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
+        if (asc_dvc->bug_fix_cntl) {
+            if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
+                if ((scsi_cmd == SCSICMD_Read6) ||
+                    (scsi_cmd == SCSICMD_Read10)) {
+                    addr = sg_head->sg_list[sg_entry_cnt_minus_one].addr +
+                      sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
+                    extra_bytes = (uchar) ((ushort) addr & 0x0003);
+                    if ((extra_bytes != 0) &&
+                        ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
+                         == 0)) {
+                        scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
+                        scsiq->q1.extra_bytes = extra_bytes;
+                        sg_head->sg_list[sg_entry_cnt_minus_one].bytes -=
+                            (ulong) extra_bytes;
+                    }
+                }
+            }
+        }
+        sg_head->entry_to_copy = sg_head->entry_cnt;
+        n_q_required = AscSgListToQueue(sg_entry_cnt);
+        if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
+            (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
+            if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
+                                        n_q_required)) == 1) {
+                asc_dvc->in_critical_cnt--;
+                if (asc_exe_callback != 0) {
+                    (*asc_exe_callback) (asc_dvc, scsiq);
+                }
+                DvcLeaveCritical(last_int_level);
+                return (sta);
+            }
+        }
+    } else {
+        if (asc_dvc->bug_fix_cntl) {
+            if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
+                if ((scsi_cmd == SCSICMD_Read6) ||
+                    (scsi_cmd == SCSICMD_Read10)) {
+                    addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
+                    extra_bytes = (uchar) ((ushort) addr & 0x0003);
+                    if ((extra_bytes != 0) &&
+                        ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES)
+                          == 0)) {
+                        if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
+                            scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES;
+                            scsiq->q1.data_cnt -= (ulong) extra_bytes;
+                            scsiq->q1.extra_bytes = extra_bytes;
+                        }
+                    }
+                }
+            }
+        }
+        n_q_required = 1;
+        if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
+            ((scsiq->q1.cntl & QC_URGENT) != 0)) {
+            if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
+                                        n_q_required)) == 1) {
+                asc_dvc->in_critical_cnt--;
+                if (asc_exe_callback != 0) {
+                    (*asc_exe_callback) (asc_dvc, scsiq);
+                }
+                DvcLeaveCritical(last_int_level);
+                return (sta);
+            }
+        }
+    }
+    asc_dvc->in_critical_cnt--;
+    DvcLeaveCritical(last_int_level);
+    return (sta);
+}
+
+STATIC int
+AscSendScsiQueue(
+                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                    REG ASC_SCSI_Q * scsiq,
+                    uchar n_q_required
+)
+{
+    PortAddr            iop_base;
+    uchar               free_q_head;
+    uchar               next_qp;
+    uchar               tid_no;
+    uchar               target_ix;
+    int                 sta;
+
+    iop_base = asc_dvc->iop_base;
+    target_ix = scsiq->q2.target_ix;
+    tid_no = ASC_TIX_TO_TID(target_ix);
+    sta = 0;
+    free_q_head = (uchar) AscGetVarFreeQHead(iop_base);
+    if (n_q_required > 1) {
+        if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
+                                       free_q_head, (uchar) (n_q_required)))
+            != (uchar) ASC_QLINK_END) {
+            asc_dvc->last_q_shortage = 0;
+            scsiq->sg_head->queue_cnt = n_q_required - 1;
+            scsiq->q1.q_no = free_q_head;
+            if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
+                                              free_q_head)) == 1) {
+                AscPutVarFreeQHead(iop_base, next_qp);
+                asc_dvc->cur_total_qng += (uchar) (n_q_required);
+                asc_dvc->cur_dvc_qng[tid_no]++;
+            }
+            return (sta);
+        }
+    } else if (n_q_required == 1) {
+        if ((next_qp = AscAllocFreeQueue(iop_base,
+                                         free_q_head)) != ASC_QLINK_END) {
+            scsiq->q1.q_no = free_q_head;
+            if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
+                                        free_q_head)) == 1) {
+                AscPutVarFreeQHead(iop_base, next_qp);
+                asc_dvc->cur_total_qng++;
+                asc_dvc->cur_dvc_qng[tid_no]++;
+            }
+            return (sta);
+        }
+    }
+    return (sta);
+}
+
+STATIC int
+AscSgListToQueue(
+                    int sg_list
+)
+{
+    int                 n_sg_list_qs;
+
+    n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
+    if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
+        n_sg_list_qs++;
+    return (n_sg_list_qs + 1);
+}
+
+
+STATIC uint
+AscGetNumOfFreeQueue(
+                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                        uchar target_ix,
+                        uchar n_qs
+)
+{
+    uint                cur_used_qs;
+    uint                cur_free_qs;
+    ASC_SCSI_BIT_ID_TYPE target_id;
+    uchar               tid_no;
+
+    target_id = ASC_TIX_TO_TARGET_ID(target_ix);
+    tid_no = ASC_TIX_TO_TID(target_ix);
+    if ((asc_dvc->unit_not_ready & target_id) ||
+        (asc_dvc->queue_full_or_busy & target_id)) {
+        return (0);
+    }
+    if (n_qs == 1) {
+        cur_used_qs = (uint) asc_dvc->cur_total_qng +
+          (uint) asc_dvc->last_q_shortage +
+          (uint) ASC_MIN_FREE_Q;
+    } else {
+        cur_used_qs = (uint) asc_dvc->cur_total_qng +
+          (uint) ASC_MIN_FREE_Q;
+    }
+    if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
+        cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
+        if (asc_dvc->cur_dvc_qng[tid_no] >=
+            asc_dvc->max_dvc_qng[tid_no]) {
+            return (0);
+        }
+        return (cur_free_qs);
+    }
+    if (n_qs > 1) {
+        if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
+            asc_dvc->last_q_shortage = n_qs;
+        }
+    }
+    return (0);
+}
+
+STATIC int
+AscPutReadyQueue(
+                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                    REG ASC_SCSI_Q * scsiq,
+                    uchar q_no
+)
+{
+    ushort              q_addr;
+    uchar               tid_no;
+    uchar               sdtr_data;
+    uchar               syn_period_ix;
+    uchar               syn_offset;
+    PortAddr            iop_base;
+
+    iop_base = asc_dvc->iop_base;
+    if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
+        ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
+        tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
+        sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
+        syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
+        syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
+        AscMsgOutSDTR(asc_dvc,
+                      asc_dvc->sdtr_period_tbl[syn_period_ix],
+                      syn_offset);
+        scsiq->q1.cntl |= QC_MSG_OUT;
+    }
+    q_addr = ASC_QNO_TO_QADDR(q_no);
+    if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
+        scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE;
+    }
+    scsiq->q1.status = QS_FREE;
+    AscMemWordCopyToLram(iop_base,
+                         (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG),
+                         (ushort *) scsiq->cdbptr,
+                         (ushort) ((ushort) scsiq->q2.cdb_len >> 1));
+    DvcPutScsiQ(iop_base,
+                (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG),
+                (ushort *) & scsiq->q1.cntl,
+      (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1)));
+    AscWriteLramWord(iop_base,
+                     (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+             (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY));
+    return (1);
+}
+
+STATIC int
+AscPutReadySgListQueue(
+                          REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                          REG ASC_SCSI_Q * scsiq,
+                          uchar q_no
+)
+{
+    int                 sta;
+    int                 i;
+    ASC_SG_HEAD *sg_head;
+    ASC_SG_LIST_Q       scsi_sg_q;
+    ulong               saved_data_addr;
+    ulong               saved_data_cnt;
+    PortAddr            iop_base;
+    ushort              sg_list_dwords;
+    ushort              sg_index;
+    ushort              sg_entry_cnt;
+    ushort              q_addr;
+    uchar               next_qp;
+
+    iop_base = asc_dvc->iop_base;
+    sg_head = scsiq->sg_head;
+    saved_data_addr = scsiq->q1.data_addr;
+    saved_data_cnt = scsiq->q1.data_cnt;
+    scsiq->q1.data_addr = sg_head->sg_list[0].addr;
+    scsiq->q1.data_cnt = sg_head->sg_list[0].bytes;
+    sg_entry_cnt = sg_head->entry_cnt - 1;
+    if (sg_entry_cnt != 0) {
+        scsiq->q1.cntl |= QC_SG_HEAD;
+        q_addr = ASC_QNO_TO_QADDR(q_no);
+        sg_index = 1;
+        scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
+        scsi_sg_q.sg_head_qp = q_no;
+        scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
+        for (i = 0; i < sg_head->queue_cnt; i++) {
+            scsi_sg_q.seq_no = i + 1;
+            if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
+                sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2);
+                sg_entry_cnt -= ASC_SG_LIST_PER_Q;
+                if (i == 0) {
+                    scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q;
+                    scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q;
+                } else {
+                    scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
+                    scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1;
+                }
+            } else {
+                scsi_sg_q.cntl |= QCSG_SG_XFER_END;
+                sg_list_dwords = sg_entry_cnt << 1;
+                if (i == 0) {
+                    scsi_sg_q.sg_list_cnt = sg_entry_cnt;
+                    scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt;
+                } else {
+                    scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
+                    scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
+                }
+                sg_entry_cnt = 0;
+            }
+            next_qp = AscReadLramByte(iop_base,
+                                      (ushort) (q_addr + ASC_SCSIQ_B_FWD));
+            scsi_sg_q.q_no = next_qp;
+            q_addr = ASC_QNO_TO_QADDR(next_qp);
+            AscMemWordCopyToLram(iop_base,
+                                 (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG),
+                                 (ushort *) & scsi_sg_q,
+                                 (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
+            AscMemDWordCopyToLram(iop_base,
+                                  (ushort) (q_addr + ASC_SGQ_LIST_BEG),
+                              (ulong *) & sg_head->sg_list[sg_index],
+                                  (ushort) sg_list_dwords);
+            sg_index += ASC_SG_LIST_PER_Q;
+        }
+    } else {
+        scsiq->q1.cntl &= ~QC_SG_HEAD;
+    }
+    sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
+    scsiq->q1.data_addr = saved_data_addr;
+    scsiq->q1.data_cnt = saved_data_cnt;
+    return (sta);
+}
+
+STATIC int
+AscAbortSRB(
+               REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+               ulong srb_ptr
+)
+{
+    int                 sta;
+    ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
+    PortAddr            iop_base;
+
+    iop_base = asc_dvc->iop_base;
+    sta = ERR;
+    saved_unit_not_ready = asc_dvc->unit_not_ready;
+    asc_dvc->unit_not_ready = 0xFF;
+    AscWaitISRDone(asc_dvc);
+    if (AscStopQueueExe(iop_base) == 1) {
+        if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) {
+            sta = 1;
+            AscCleanUpBusyQueue(iop_base);
+            AscStartQueueExe(iop_base);
+        } else {
+            sta = 0;
+            AscStartQueueExe(iop_base);
+        }
+    }
+    asc_dvc->unit_not_ready = saved_unit_not_ready;
+    return (sta);
+}
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+STATIC int
+AscResetDevice(
+                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                  uchar target_ix
+)
+{
+    PortAddr            iop_base;
+    int                 sta;
+    uchar               tid_no;
+
+    ASC_SCSI_BIT_ID_TYPE target_id;
+    int                 i;
+    ASC_SCSI_REQ_Q      scsiq_buf;
+    ASC_SCSI_REQ_Q *scsiq;
+    uchar       *buf;
+    ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready;
+    iop_base = asc_dvc->iop_base;
+    tid_no = ASC_TIX_TO_TID(target_ix);
+    target_id = ASC_TID_TO_TARGET_ID(tid_no);
+    saved_unit_not_ready = asc_dvc->unit_not_ready;
+    asc_dvc->unit_not_ready = target_id;
+    sta = ERR;
+    AscWaitTixISRDone(asc_dvc, target_ix);
+    if (AscStopQueueExe(iop_base) == 1) {
+        if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) {
+            AscCleanUpBusyQueue(iop_base);
+            AscStartQueueExe(iop_base);
+            AscWaitTixISRDone(asc_dvc, target_ix);
+            sta = TRUE;
+            scsiq = (ASC_SCSI_REQ_Q *) & scsiq_buf;
+            buf = (uchar *) & scsiq_buf;
+            for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) {
+                *buf++ = 0x00;
+            }
+            scsiq->r1.status = (uchar) QS_READY;
+            scsiq->r2.cdb_len = 6;
+            scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE;
+            scsiq->r1.target_id = target_id;
+            scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0);
+            scsiq->cdbptr = (uchar *) scsiq->cdb;
+            scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT;
+            AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG,
+                             M1_BUS_DVC_RESET);
+            asc_dvc->unit_not_ready &= ~target_id;
+            asc_dvc->sdtr_done |= target_id;
+            if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q *) scsiq)
+                == 1) {
+                asc_dvc->unit_not_ready = target_id;
+                DvcSleepMilliSecond(1000);
+                _AscWaitQDone(iop_base, (ASC_SCSI_Q *) scsiq);
+                if (AscStopQueueExe(iop_base) == 1) {
+                    AscCleanUpDiscQueue(iop_base);
+                    AscStartQueueExe(iop_base);
+                    if (asc_dvc->pci_fix_asyn_xfer & target_id) {
+                        AscSetRunChipSynRegAtID(iop_base, tid_no,
+                                             ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+                    }
+                    AscWaitTixISRDone(asc_dvc, target_ix);
+                }
+            } else {
+                sta = 0;
+            }
+            asc_dvc->sdtr_done &= ~target_id;
+        } else {
+            sta = ERR;
+            AscStartQueueExe(iop_base);
+        }
+    }
+    asc_dvc->unit_not_ready = saved_unit_not_ready;
+    return (sta);
+}
+#endif /* version >= v1.3.89 */
+
+STATIC int
+AscResetSB(
+              REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    int                 sta;
+    int                 i;
+    PortAddr            iop_base;
+
+    iop_base = asc_dvc->iop_base;
+    asc_dvc->unit_not_ready = 0xFF;
+    sta = TRUE;
+    AscWaitISRDone(asc_dvc);
+    AscStopQueueExe(iop_base);
+    asc_dvc->sdtr_done = 0;
+    AscResetChipAndScsiBus(asc_dvc);
+    DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
+    AscReInitLram(asc_dvc);
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        asc_dvc->cur_dvc_qng[i] = 0;
+        if (asc_dvc->pci_fix_asyn_xfer & (ASC_SCSI_BIT_ID_TYPE) (0x01 << i)) {
+            AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+        }
+    }
+    asc_dvc->err_code = 0;
+    AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
+    if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
+        sta = ERR;
+    }
+    if (AscStartChip(iop_base) == 0) {
+        sta = ERR;
+    }
+    AscStartQueueExe(iop_base);
+    asc_dvc->unit_not_ready = 0;
+    asc_dvc->queue_full_or_busy = 0;
+    return (sta);
+}
+
+STATIC int
+AscSetRunChipSynRegAtID(
+                           PortAddr iop_base,
+                           uchar tid_no,
+                           uchar sdtr_data
+)
+{
+    int                 sta = FALSE;
+
+    if (AscHostReqRiscHalt(iop_base)) {
+        sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
+        AscStartChip(iop_base);
+        return (sta);
+    }
+    return (sta);
+}
+
+STATIC int
+AscSetChipSynRegAtID(
+                        PortAddr iop_base,
+                        uchar id,
+                        uchar sdtr_data
+)
+{
+    ASC_SCSI_BIT_ID_TYPE org_id;
+    int                 i;
+    int                 sta = TRUE;
+
+    AscSetBank(iop_base, 1);
+    org_id = AscReadChipDvcID(iop_base);
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        if (org_id == (0x01 << i))
+            break;
+    }
+    org_id = i;
+    AscWriteChipDvcID(iop_base, id);
+    if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
+        AscSetBank(iop_base, 0);
+        AscSetChipSyn(iop_base, sdtr_data);
+        if (AscGetChipSyn(iop_base) != sdtr_data) {
+            sta = FALSE;
+        }
+    } else {
+        sta = FALSE;
+    }
+    AscSetBank(iop_base, 1);
+    AscWriteChipDvcID(iop_base, org_id);
+    AscSetBank(iop_base, 0);
+    return (sta);
+}
+
+STATIC int
+AscReInitLram(
+                 REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    AscInitLram(asc_dvc);
+    AscInitQLinkVar(asc_dvc);
+    return (0);
+}
+
+STATIC ushort
+AscInitLram(
+               REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    uchar               i;
+    ushort              s_addr;
+    PortAddr            iop_base;
+    ushort              warn_code;
+
+    iop_base = asc_dvc->iop_base;
+    warn_code = 0;
+    AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
+               (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1)
+);
+    i = ASC_MIN_ACTIVE_QNO;
+    s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
+    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
+                     (uchar) (i + 1));
+    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
+                     (uchar) (asc_dvc->max_total_qng));
+    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
+                     (uchar) i);
+    i++;
+    s_addr += ASC_QBLK_SIZE;
+    for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
+        AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
+                         (uchar) (i + 1));
+        AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
+                         (uchar) (i - 1));
+        AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
+                         (uchar) i);
+    }
+    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD),
+                     (uchar) ASC_QLINK_END);
+    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD),
+                     (uchar) (asc_dvc->max_total_qng - 1));
+    AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO),
+                     (uchar) asc_dvc->max_total_qng);
+    i++;
+    s_addr += ASC_QBLK_SIZE;
+    for (; i <= (uchar) (asc_dvc->max_total_qng + 3);
+         i++, s_addr += ASC_QBLK_SIZE) {
+        AscWriteLramByte(iop_base,
+                         (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i);
+        AscWriteLramByte(iop_base,
+                         (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i);
+        AscWriteLramByte(iop_base,
+                         (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i);
+    }
+    return (warn_code);
+}
+
+STATIC ushort
+AscInitQLinkVar(
+                   REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    PortAddr            iop_base;
+    int                 i;
+    ushort              lram_addr;
+
+    iop_base = asc_dvc->iop_base;
+    AscPutRiscVarFreeQHead(iop_base, 1);
+    AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
+    AscPutVarFreeQHead(iop_base, 1);
+    AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
+    AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
+                     (uchar) ((int) asc_dvc->max_total_qng + 1));
+    AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
+                     (uchar) ((int) asc_dvc->max_total_qng + 2));
+    AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B,
+                     asc_dvc->max_total_qng);
+    AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
+    AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+    AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
+    AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
+    AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
+    AscPutQDoneInProgress(iop_base, 0);
+    lram_addr = ASC_QADR_BEG;
+    for (i = 0; i < 32; i++, lram_addr += 2) {
+        AscWriteLramWord(iop_base, lram_addr, 0);
+    }
+    return (0);
+}
+
+STATIC int
+AscSetLibErrorCode(
+                      REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                      ushort err_code
+)
+{
+    if (asc_dvc->err_code == 0) {
+        asc_dvc->err_code = err_code;
+        AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
+                         err_code);
+    }
+    return (err_code);
+}
+
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+STATIC int
+_AscWaitQDone(
+                 PortAddr iop_base,
+                 REG ASC_SCSI_Q * scsiq
+)
+{
+    ushort              q_addr;
+    uchar               q_status;
+    int                 count = 0;
+
+    while (scsiq->q1.q_no == 0) ;
+    q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no);
+    do {
+        q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS);
+        DvcSleepMilliSecond(100L);
+        if (count++ > 30) {
+            return (0);
+        }
+    } while ((q_status & QS_READY) != 0);
+    return (1);
+}
+#endif /* version >= v1.3.89 */
+
+STATIC uchar 
+AscMsgOutSDTR(
+                 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                 uchar sdtr_period,
+                 uchar sdtr_offset
+)
+{
+    EXT_MSG             sdtr_buf;
+    uchar               sdtr_period_index;
+    PortAddr            iop_base;
+
+    iop_base = asc_dvc->iop_base;
+    sdtr_buf.msg_type = MS_EXTEND;
+    sdtr_buf.msg_len = MS_SDTR_LEN;
+    sdtr_buf.msg_req = MS_SDTR_CODE;
+    sdtr_buf.xfer_period = sdtr_period;
+    sdtr_offset &= ASC_SYN_MAX_OFFSET;
+    sdtr_buf.req_ack_offset = sdtr_offset;
+    if ((sdtr_period_index =
+         AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
+        asc_dvc->max_sdtr_index) {
+        AscMemWordCopyToLram(iop_base,
+                             ASCV_MSGOUT_BEG,
+                             (ushort *) & sdtr_buf,
+                             (ushort) (sizeof (EXT_MSG) >> 1));
+        return ((sdtr_period_index << 4) | sdtr_offset);
+    } else {
+
+        sdtr_buf.req_ack_offset = 0;
+        AscMemWordCopyToLram(iop_base,
+                             ASCV_MSGOUT_BEG,
+                             (ushort *) & sdtr_buf,
+                             (ushort) (sizeof (EXT_MSG) >> 1));
+        return (0);
+    }
+}
+
+STATIC uchar
+AscCalSDTRData(
+                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                  uchar sdtr_period,
+                  uchar syn_offset
+)
+{
+    uchar               byte;
+    uchar               sdtr_period_ix;
+
+    sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
+    if (
+           (sdtr_period_ix > asc_dvc->max_sdtr_index)
+) {
+        return (0xFF);
+    }
+    byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
+    return (byte);
+}
+
+STATIC void
+AscSetChipSDTR(
+                  PortAddr iop_base,
+                  uchar sdtr_data,
+                  uchar tid_no
+)
+{
+    AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
+    AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
+    return;
+}
+
+STATIC uchar
+AscGetSynPeriodIndex(
+                        ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                        ruchar syn_time
+)
+{
+    ruchar             *period_table;
+    int                 max_index;
+    int                 min_index;
+    int                 i;
+
+    period_table = asc_dvc->sdtr_period_tbl;
+    max_index = (int) asc_dvc->max_sdtr_index;
+    min_index = (int)asc_dvc->host_init_sdtr_index ;
+    if ((syn_time <= period_table[max_index])) {
+        for (i = min_index; i < (max_index - 1); i++) {
+            if (syn_time <= period_table[i]) {
+                return ((uchar) i);
+            }
+        }
+        return ((uchar) max_index);
+    } else {
+        return ((uchar) (max_index + 1));
+    }
+}
+
+STATIC uchar
+AscAllocFreeQueue(
+                     PortAddr iop_base,
+                     uchar free_q_head
+)
+{
+    ushort              q_addr;
+    uchar               next_qp;
+    uchar               q_status;
+
+    q_addr = ASC_QNO_TO_QADDR(free_q_head);
+    q_status = (uchar) AscReadLramByte(iop_base,
+                                    (ushort) (q_addr + ASC_SCSIQ_B_STATUS));
+    next_qp = AscReadLramByte(iop_base,
+                              (ushort) (q_addr + ASC_SCSIQ_B_FWD));
+    if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
+        return (next_qp);
+    }
+    return (ASC_QLINK_END);
+}
+
+STATIC uchar
+AscAllocMultipleFreeQueue(
+                             PortAddr iop_base,
+                             uchar free_q_head,
+                             uchar n_free_q
+)
+{
+    uchar               i;
+
+    for (i = 0; i < n_free_q; i++) {
+        if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
+            == ASC_QLINK_END) {
+            return (ASC_QLINK_END);
+        }
+    }
+    return (free_q_head);
+}
+
+STATIC int
+AscRiscHaltedAbortSRB(
+                         REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                         ulong srb_ptr
+)
+{
+    PortAddr            iop_base;
+    ushort              q_addr;
+    uchar               q_no;
+    ASC_QDONE_INFO      scsiq_buf;
+    ASC_QDONE_INFO *scsiq;
+    ASC_ISR_CALLBACK    asc_isr_callback;
+    int                 last_int_level;
+
+    iop_base = asc_dvc->iop_base;
+    asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+    last_int_level = DvcEnterCritical();
+    scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
+    for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
+         q_no++) {
+        q_addr = ASC_QNO_TO_QADDR(q_no);
+        scsiq->d2.srb_ptr = AscReadLramDWord(iop_base,
+                           (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR));
+        if (scsiq->d2.srb_ptr == srb_ptr) {
+            _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
+            if (((scsiq->q_status & QS_READY) != 0)
+                 && ((scsiq->q_status & QS_ABORTED) == 0)
+                 && ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
+                scsiq->q_status |= QS_ABORTED;
+                scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
+                AscWriteLramDWord(iop_base,
+                            (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
+                                  0L);
+                AscWriteLramByte(iop_base,
+                            (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+                                 scsiq->q_status);
+                (*asc_isr_callback) (asc_dvc, scsiq);
+                return (1);
+            }
+        }
+    }
+    DvcLeaveCritical(last_int_level);
+    return (0);
+}
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+STATIC int
+AscRiscHaltedAbortTIX(
+                         REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                         uchar target_ix
+)
+{
+    PortAddr            iop_base;
+    ushort              q_addr;
+    uchar               q_no;
+    ASC_QDONE_INFO      scsiq_buf;
+    ASC_QDONE_INFO *scsiq;
+    ASC_ISR_CALLBACK    asc_isr_callback;
+    int                 last_int_level;
+
+    iop_base = asc_dvc->iop_base;
+    asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+    last_int_level = DvcEnterCritical();
+    scsiq = (ASC_QDONE_INFO *) & scsiq_buf;
+    for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng;
+         q_no++) {
+        q_addr = ASC_QNO_TO_QADDR(q_no);
+        _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count);
+        if (((scsiq->q_status & QS_READY) != 0) &&
+            ((scsiq->q_status & QS_ABORTED) == 0) &&
+            ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) {
+            if (scsiq->d2.target_ix == target_ix) {
+                scsiq->q_status |= QS_ABORTED;
+                scsiq->d3.done_stat = QD_ABORTED_BY_HOST;
+                AscWriteLramDWord(iop_base,
+                            (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR),
+                                  0L);
+                AscWriteLramByte(iop_base,
+                            (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS),
+                                 scsiq->q_status);
+                (*asc_isr_callback) (asc_dvc, scsiq);
+            }
+        }
+    }
+    DvcLeaveCritical(last_int_level);
+    return (1);
+}
+#endif /* version >= v1.3.89 */
+
+STATIC int
+AscHostReqRiscHalt(
+                      PortAddr iop_base
+)
+{
+    int                 count = 0;
+    int                 sta = 0;
+    uchar               saved_stop_code;
+
+    if (AscIsChipHalted(iop_base))
+        return (1);
+    saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
+    AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
+                     ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP
+);
+    do {
+        if (AscIsChipHalted(iop_base)) {
+            sta = 1;
+            break;
+        }
+        DvcSleepMilliSecond(100);
+    } while (count++ < 20);
+    AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
+    return (sta);
+}
+
+STATIC int
+AscStopQueueExe(
+                   PortAddr iop_base
+)
+{
+    int                 count = 0;
+
+    if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
+        AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
+                         ASC_STOP_REQ_RISC_STOP);
+        do {
+            if (
+                   AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
+                   ASC_STOP_ACK_RISC_STOP) {
+                return (1);
+            }
+            DvcSleepMilliSecond(100);
+        } while (count++ < 20);
+    }
+    return (0);
+}
+
+STATIC int
+AscStartQueueExe(
+                    PortAddr iop_base
+)
+{
+    if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
+        AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
+    }
+    return (1);
+}
+
+STATIC int
+AscCleanUpBusyQueue(
+                       PortAddr iop_base
+)
+{
+    int                 count;
+    uchar               stop_code;
+
+    count = 0;
+    if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
+        AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
+                         ASC_STOP_CLEAN_UP_BUSY_Q);
+        do {
+            stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
+            if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0)
+                break;
+            DvcSleepMilliSecond(100);
+        } while (count++ < 20);
+    }
+    return (1);
+}
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+STATIC int
+AscCleanUpDiscQueue(
+                       PortAddr iop_base
+)
+{
+    int                 count;
+    uchar               stop_code;
+
+    count = 0;
+    if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
+        AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
+                         ASC_STOP_CLEAN_UP_DISC_Q);
+        do {
+            stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
+            if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0)
+                break;
+            DvcSleepMilliSecond(100);
+        } while (count++ < 20);
+    }
+    return (1);
+}
+#endif /* version >= v1.3.89 */
+
+STATIC int
+AscWaitTixISRDone(
+                     ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                     uchar target_ix
+)
+{
+    uchar               cur_req;
+    uchar               tid_no;
+    int                 i = 0;
+
+    tid_no = ASC_TIX_TO_TID(target_ix);
+    while (i++ < 10) {
+        if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
+            break;
+        }
+        DvcSleepMilliSecond(100L);
+        if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
+            break;
+        }
+    }
+    return (1);
+}
+
+STATIC int
+AscWaitISRDone(
+                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    int                 tid;
+
+    for (tid = 0; tid <= ASC_MAX_TID; tid++) {
+        AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid));
+    }
+    return (1);
+}
+
+STATIC ulong
+AscGetOnePhyAddr(
+                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                    uchar * buf_addr,
+                    ulong buf_size
+)
+{
+    ASC_MIN_SG_HEAD     sg_head;
+
+    sg_head.entry_cnt = ASC_MIN_SG_LIST;
+    if (DvcGetSGList(asc_dvc, (uchar *) buf_addr,
+                  buf_size, (ASC_SG_HEAD *) & sg_head) != buf_size) {
+        return (0L);
+    }
+    if (sg_head.entry_cnt > 1) {
+        return (0L);
+    }
+    return (sg_head.sg_list[0].addr);
+}
+
+STATIC void
+DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec)
+{
+    udelay(micro_sec);
+}
+
+STATIC void
+DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type * asc_dvc, ulong nano_sec)
+{
+    udelay((nano_sec + 999)/1000);
+}
+
+ASC_INITFUNC(
+STATIC ulong
+AscGetEisaProductID(
+                       PortAddr iop_base
+)
+)
+{
+    PortAddr            eisa_iop;
+    ushort              product_id_high, product_id_low;
+    ulong               product_id;
+
+    eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK;
+    product_id_low = inpw(eisa_iop);
+    product_id_high = inpw(eisa_iop + 2);
+    product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low;
+    return (product_id);
+}
+
+ASC_INITFUNC(
+STATIC PortAddr
+AscSearchIOPortAddrEISA(
+                           PortAddr iop_base
+)
+)
+{
+    ulong               eisa_product_id;
+
+    if (iop_base == 0) {
+        iop_base = ASC_EISA_MIN_IOP_ADDR;
+    } else {
+        if (iop_base == ASC_EISA_MAX_IOP_ADDR)
+            return (0);
+        if ((iop_base & 0x0050) == 0x0050) {
+            iop_base += ASC_EISA_BIG_IOP_GAP;
+        } else {
+            iop_base += ASC_EISA_SMALL_IOP_GAP;
+        }
+    }
+    while (iop_base <= ASC_EISA_MAX_IOP_ADDR) {
+        eisa_product_id = AscGetEisaProductID(iop_base);
+        if ((eisa_product_id == ASC_EISA_ID_740) ||
+            (eisa_product_id == ASC_EISA_ID_750)) {
+            if (AscFindSignature(iop_base)) {
+                inpw(iop_base + 4);
+                return (iop_base);
+            }
+        }
+        if (iop_base == ASC_EISA_MAX_IOP_ADDR)
+            return (0);
+        if ((iop_base & 0x0050) == 0x0050) {
+            iop_base += ASC_EISA_BIG_IOP_GAP;
+        } else {
+            iop_base += ASC_EISA_SMALL_IOP_GAP;
+        }
+    }
+    return (0);
+}
+
+STATIC int
+AscStartChip(
+                PortAddr iop_base
+)
+{
+    AscSetChipControl(iop_base, 0);
+    if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
+        return (0);
+    }
+    return (1);
+}
+
+STATIC int
+AscStopChip(
+               PortAddr iop_base
+)
+{
+    uchar               cc_val;
+
+    cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
+    AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT));
+    AscSetChipIH(iop_base, INS_HALT);
+    AscSetChipIH(iop_base, INS_RFLAG_WTM);
+    if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
+        return (0);
+    }
+    return (1);
+}
+
+STATIC int
+AscIsChipHalted(
+                   PortAddr iop_base
+)
+{
+    if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
+        if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
+            return (1);
+        }
+    }
+    return (0);
+}
+
+STATIC void
+AscSetChipIH(
+                PortAddr iop_base,
+                ushort ins_code
+)
+{
+    AscSetBank(iop_base, 1);
+    AscWriteChipIH(iop_base, ins_code);
+    AscSetBank(iop_base, 0);
+    return;
+}
+
+STATIC void
+AscAckInterrupt(
+                   PortAddr iop_base
+)
+{
+    uchar               host_flag;
+    uchar               risc_flag;
+    ushort              loop;
+
+    loop = 0;
+    do {
+        risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
+        if (loop++ > 0x7FFF) {
+            break;
+        }
+    } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
+    host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
+    AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
+                     (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT));
+    AscSetChipStatus(iop_base, CIW_INT_ACK);
+    loop = 0;
+    while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
+        AscSetChipStatus(iop_base, CIW_INT_ACK);
+        if (loop++ > 3) {
+            break;
+        }
+    }
+    AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
+    return;
+}
+
+STATIC void
+AscDisableInterrupt(
+                       PortAddr iop_base
+)
+{
+    ushort              cfg;
+
+    cfg = AscGetChipCfgLsw(iop_base);
+    AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
+    return;
+}
+
+STATIC void
+AscEnableInterrupt(
+                      PortAddr iop_base
+)
+{
+    ushort              cfg;
+
+    cfg = AscGetChipCfgLsw(iop_base);
+    AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
+    return;
+}
+
+
+
+STATIC void
+AscSetBank(
+              PortAddr iop_base,
+              uchar bank
+)
+{
+    uchar               val;
+
+    val = AscGetChipControl(iop_base) &
+      (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET));
+    if (bank == 1) {
+        val |= CC_BANK_ONE;
+    } else if (bank == 2) {
+        val |= CC_DIAG | CC_BANK_ONE;
+    } else {
+        val &= ~CC_BANK_ONE;
+    }
+    AscSetChipControl(iop_base, val);
+    return;
+}
+
+STATIC int
+AscResetChipAndScsiBus(
+                          ASC_DVC_VAR *asc_dvc
+)
+{
+    PortAddr    iop_base;
+
+    iop_base = asc_dvc->iop_base;
+    while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ;
+    AscStopChip(iop_base);
+    AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
+    DvcDelayNanoSecond(asc_dvc, 60000);
+    AscSetChipIH(iop_base, INS_RFLAG_WTM);
+    AscSetChipIH(iop_base, INS_HALT);
+    AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
+    AscSetChipControl(iop_base, CC_HALT);
+    DvcSleepMilliSecond(200);
+    AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
+    AscSetChipStatus(iop_base, 0);
+    return (AscIsChipHalted(iop_base));
+}
+
+ASC_INITFUNC(
+STATIC ulong
+AscGetMaxDmaCount(
+                     ushort bus_type
+)
+)
+{
+    if (bus_type & ASC_IS_ISA)
+        return (ASC_MAX_ISA_DMA_COUNT);
+    else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
+        return (ASC_MAX_VL_DMA_COUNT);
+    return (ASC_MAX_PCI_DMA_COUNT);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscGetIsaDmaChannel(
+                       PortAddr iop_base
+)
+)
+{
+    ushort              channel;
+
+    channel = AscGetChipCfgLsw(iop_base) & 0x0003;
+    if (channel == 0x03)
+        return (0);
+    else if (channel == 0x00)
+        return (7);
+    return (channel + 4);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscSetIsaDmaChannel(
+                       PortAddr iop_base,
+                       ushort dma_channel
+)
+)
+{
+    ushort              cfg_lsw;
+    uchar               value;
+
+    if ((dma_channel >= 5) && (dma_channel <= 7)) {
+        if (dma_channel == 7)
+            value = 0x00;
+        else
+            value = dma_channel - 4;
+        cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
+        cfg_lsw |= value;
+        AscSetChipCfgLsw(iop_base, cfg_lsw);
+        return (AscGetIsaDmaChannel(iop_base));
+    }
+    return (0);
+}
+
+ASC_INITFUNC(
+STATIC uchar
+AscSetIsaDmaSpeed(
+                     PortAddr iop_base,
+                     uchar speed_value
+)
+)
+{
+    speed_value &= 0x07;
+    AscSetBank(iop_base, 1);
+    AscWriteChipDmaSpeed(iop_base, speed_value);
+    AscSetBank(iop_base, 0);
+    return (AscGetIsaDmaSpeed(iop_base));
+}
+
+ASC_INITFUNC(
+STATIC uchar
+AscGetIsaDmaSpeed(
+                     PortAddr iop_base
+)
+)
+{
+    uchar               speed_value;
+
+    AscSetBank(iop_base, 1);
+    speed_value = AscReadChipDmaSpeed(iop_base);
+    speed_value &= 0x07;
+    AscSetBank(iop_base, 0);
+    return (speed_value);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscReadPCIConfigWord(
+    ASC_DVC_VAR asc_ptr_type *asc_dvc,
+    ushort pci_config_offset)
+)
+{
+    uchar       lsb, msb;
+
+    lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset);
+    msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1);
+    return ((ushort) ((msb << 8) | lsb));
+}
+
+ASC_INITFUNC(
+STATIC ushort 
+AscInitGetConfig(
+        ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+)
+{
+    ushort              warn_code;
+    PortAddr            iop_base;
+    ushort              PCIDeviceID;
+    ushort              PCIVendorID;
+    uchar               PCIRevisionID;
+    uchar               prevCmdRegBits;
+
+    warn_code = 0;
+    iop_base = asc_dvc->iop_base;
+    asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
+    if (asc_dvc->err_code != 0) {
+        return (UW_ERR);
+    }
+    if (asc_dvc->bus_type == ASC_IS_PCI) {
+        PCIVendorID = AscReadPCIConfigWord(asc_dvc,
+                                    AscPCIConfigVendorIDRegister);
+
+        PCIDeviceID = AscReadPCIConfigWord(asc_dvc,
+                                    AscPCIConfigDeviceIDRegister);
+
+        PCIRevisionID = DvcReadPCIConfigByte(asc_dvc,
+                                    AscPCIConfigRevisionIDRegister);
+
+        if (PCIVendorID != ASC_PCI_VENDORID) {
+            warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
+        }
+        prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc,
+                                    AscPCIConfigCommandRegister);
+
+        if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) !=
+            AscPCICmdRegBits_IOMemBusMaster) {
+            DvcWritePCIConfigByte(asc_dvc,
+                            AscPCIConfigCommandRegister,
+                            (prevCmdRegBits |
+                             AscPCICmdRegBits_IOMemBusMaster));
+
+            if ((DvcReadPCIConfigByte(asc_dvc,
+                                AscPCIConfigCommandRegister)
+                 & AscPCICmdRegBits_IOMemBusMaster)
+                != AscPCICmdRegBits_IOMemBusMaster) {
+                warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
+            }
+        }
+        if ((PCIDeviceID == ASC_PCI_DEVICEID_1200A) ||
+            (PCIDeviceID == ASC_PCI_DEVICEID_1200B)) {
+            DvcWritePCIConfigByte(asc_dvc,
+                            AscPCIConfigLatencyTimer, 0x00);
+            if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer)
+                != 0x00) {
+                warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
+            }
+        } else if (PCIDeviceID == ASC_PCI_DEVICEID_ULTRA) {
+            if (DvcReadPCIConfigByte(asc_dvc,
+                                AscPCIConfigLatencyTimer) < 0x20) {
+                DvcWritePCIConfigByte(asc_dvc,
+                                    AscPCIConfigLatencyTimer, 0x20);
+
+                if (DvcReadPCIConfigByte(asc_dvc,
+                                    AscPCIConfigLatencyTimer) < 0x20) {
+                    warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
+                }
+            }
+        }
+    }
+
+    if (AscFindSignature(iop_base)) {
+        warn_code |= AscInitAscDvcVar(asc_dvc);
+        warn_code |= AscInitFromEEP(asc_dvc);
+        asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
+        if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) {
+            asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
+        }
+    } else {
+        asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+    }
+    return(warn_code);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscInitSetConfig(
+                    ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+)
+{
+    ushort              warn_code = 0;
+
+    asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
+    if (asc_dvc->err_code != 0)
+        return (UW_ERR);
+    if (AscFindSignature(asc_dvc->iop_base)) {
+        warn_code |= AscInitFromAscDvcVar(asc_dvc);
+        asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
+    } else {
+        asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+    }
+    return (warn_code);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscInitFromAscDvcVar(
+                        ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+)
+{
+    PortAddr            iop_base;
+    ushort              cfg_msw;
+    ushort              warn_code;
+    ushort              pci_device_id;
+
+    iop_base = asc_dvc->iop_base;
+    pci_device_id = asc_dvc->cfg->pci_device_id;
+    warn_code = 0;
+    cfg_msw = AscGetChipCfgMsw(iop_base);
+    if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
+        cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
+        warn_code |= ASC_WARN_CFG_MSW_RECOVER;
+        AscSetChipCfgMsw(iop_base, cfg_msw);
+    }
+    if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
+        asc_dvc->cfg->cmd_qng_enabled) {
+        asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
+        warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
+    }
+    if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
+        warn_code |= ASC_WARN_AUTO_CONFIG;
+    }
+    if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
+        if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
+            != asc_dvc->irq_no) {
+            asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
+        }
+    }
+    if (asc_dvc->bus_type & ASC_IS_PCI) {
+        cfg_msw &= 0xFFC0;
+        AscSetChipCfgMsw(iop_base, cfg_msw);
+        if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
+        } else {
+            if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
+                (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
+                asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
+                asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
+            }
+        }
+    } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
+        if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
+            == ASC_CHIP_VER_ASYN_BUG) {
+            asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
+        }
+    }
+    if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
+        asc_dvc->cfg->chip_scsi_id) {
+        asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
+    }
     if (asc_dvc->bus_type & ASC_IS_ISA) {
         AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
         AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
     }
-    return (warn_code);
+    return (warn_code);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscInitAsc1000Driver(
+                        ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+)
+{
+    ushort              warn_code;
+    PortAddr            iop_base;
+    extern ushort       _asc_mcode_size;
+    extern ulong        _asc_mcode_chksum;
+    extern uchar        _asc_mcode_buf[];
+
+    iop_base = asc_dvc->iop_base;
+    warn_code = 0;
+    if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
+        !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
+        AscResetChipAndScsiBus(asc_dvc);
+        DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
+    }
+    asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
+    if (asc_dvc->err_code != 0)
+        return (UW_ERR);
+    if (!AscFindSignature(asc_dvc->iop_base)) {
+        asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+        return (warn_code);
+    }
+    AscDisableInterrupt(iop_base);
+    warn_code |= AscInitLram(asc_dvc);
+    if (asc_dvc->err_code != 0)
+        return (UW_ERR);
+    if (AscLoadMicroCode(iop_base, 0, (ushort *) _asc_mcode_buf,
+                         _asc_mcode_size) != _asc_mcode_chksum) {
+        asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
+        return (warn_code);
+    }
+    warn_code |= AscInitMicroCodeVar(asc_dvc);
+    asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
+    AscEnableInterrupt(iop_base);
+    return (warn_code);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscInitAscDvcVar(
+                    ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+)
+{
+    int                 i;
+    PortAddr            iop_base;
+    ushort              warn_code;
+    uchar               chip_version;
+
+    iop_base = asc_dvc->iop_base;
+    warn_code = 0;
+    asc_dvc->err_code = 0;
+    if ((asc_dvc->bus_type &
+         (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
+        asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
+    }
+    AscSetChipControl(iop_base, CC_HALT);
+    AscSetChipStatus(iop_base, 0);
+    asc_dvc->bug_fix_cntl = 0;
+    asc_dvc->pci_fix_asyn_xfer = 0;
+    asc_dvc->pci_fix_asyn_xfer_always = 0;
+    asc_dvc->init_state = 0;
+    asc_dvc->sdtr_done = 0;
+    asc_dvc->cur_total_qng = 0;
+    asc_dvc->is_in_int = 0;
+    asc_dvc->in_critical_cnt = 0;
+    asc_dvc->last_q_shortage = 0;
+    asc_dvc->use_tagged_qng = 0;
+    asc_dvc->no_scam = 0;
+    asc_dvc->unit_not_ready = 0;
+    asc_dvc->queue_full_or_busy = 0;
+    asc_dvc->redo_scam = 0 ;
+    asc_dvc->res2 = 0 ;
+    asc_dvc->host_init_sdtr_index = 0 ;
+    asc_dvc->res7 = 0 ;
+    asc_dvc->res8 = 0 ;
+    asc_dvc->cfg->can_tagged_qng = 0 ;
+    asc_dvc->cfg->cmd_qng_enabled = 0;
+    asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
+    asc_dvc->init_sdtr = ASC_SCSI_WIDTH_BIT_SET;
+    asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
+    asc_dvc->scsi_reset_wait = 3;
+    asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
+    asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
+    asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
+    asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
+    asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
+    asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
+      ASC_LIB_VERSION_MINOR;
+    chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
+    asc_dvc->cfg->chip_version = chip_version;
+    asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
+    asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
+    asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
+    asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
+    asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
+    asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
+    asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
+    asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
+    asc_dvc->max_sdtr_index = 7;
+    if ((asc_dvc->bus_type & ASC_IS_PCI) &&
+        (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
+        asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
+        asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
+        asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
+        asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
+        asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
+        asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
+        asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
+        asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
+        asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
+        asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
+        asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
+        asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
+        asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
+        asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
+        asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
+        asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
+        asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
+        asc_dvc->max_sdtr_index = 15;
+        if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150)
+        {
+            AscSetExtraControl(iop_base,
+                (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
+        } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
+            AscSetExtraControl(iop_base,
+                (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER));
+        }
+    }
+    if (asc_dvc->bus_type == ASC_IS_PCI) {
+           AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
+    }
+
+    asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
+    if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
+        AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
+        asc_dvc->bus_type = ASC_IS_ISAPNP;
+    }
+    if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
+        asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
+    }
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        asc_dvc->cur_dvc_qng[i] = 0;
+        asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
+        asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L;
+        asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L;
+        asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
+    }
+    return (warn_code);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscInitFromEEP(
+                  ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+)
+{
+    ASCEEP_CONFIG       eep_config_buf;
+    ASCEEP_CONFIG       *eep_config;
+    PortAddr            iop_base;
+    ushort              chksum;
+    ushort              warn_code;
+    ushort              cfg_msw, cfg_lsw;
+    int                 i;
+    int                 write_eep = 0;
+
+    iop_base = asc_dvc->iop_base;
+    warn_code = 0;
+    AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
+    AscStopQueueExe(iop_base);
+    if ((AscStopChip(iop_base) == FALSE) ||
+        (AscGetChipScsiCtrl(iop_base) != 0)) {
+        asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
+        AscResetChipAndScsiBus(asc_dvc);
+        DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
+    }
+    if (AscIsChipHalted(iop_base) == FALSE) {
+        asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
+        return (warn_code);
+    }
+    AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
+    if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
+        asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
+        return (warn_code);
+    }
+    eep_config = (ASCEEP_CONFIG *) & eep_config_buf;
+    cfg_msw = AscGetChipCfgMsw(iop_base);
+    cfg_lsw = AscGetChipCfgLsw(iop_base);
+    if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
+        cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
+        warn_code |= ASC_WARN_CFG_MSW_RECOVER;
+        AscSetChipCfgMsw(iop_base, cfg_msw);
+    }
+    chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
+    if (chksum == 0) {
+        chksum = 0xaa55;
+    }
+    if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
+        warn_code |= ASC_WARN_AUTO_CONFIG;
+        if (asc_dvc->cfg->chip_version == 3) {
+            if (eep_config->cfg_lsw != cfg_lsw) {
+                warn_code |= ASC_WARN_EEPROM_RECOVER;
+                eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
+            }
+            if (eep_config->cfg_msw != cfg_msw) {
+                warn_code |= ASC_WARN_EEPROM_RECOVER;
+                eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
+            }
+        }
+    }
+    eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
+    eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
+    if (chksum != eep_config->chksum) {
+            if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
+                    ASC_CHIP_VER_PCI_ULTRA_3050 )
+            {
+                eep_config->init_sdtr = 0xFF;
+                eep_config->disc_enable = 0xFF;
+                eep_config->start_motor = 0xFF;
+                eep_config->use_cmd_qng = 0;
+                eep_config->max_total_qng = 0xF0;
+                eep_config->max_tag_qng = 0x20;
+                eep_config->cntl = 0xBFFF;
+                eep_config->chip_scsi_id = 7;
+                eep_config->no_scam = 0;
+                eep_config->adapter_info[0] = 0;
+                eep_config->adapter_info[1] = 0;
+                eep_config->adapter_info[2] = 0;
+                eep_config->adapter_info[3] = 0;
+                eep_config->adapter_info[4] = 0;
+                /* Indicate EEPROM-less board. */
+                eep_config->adapter_info[5] = 0xBB;
+            } else {
+                write_eep = 1 ;
+                warn_code |= ASC_WARN_EEPROM_CHKSUM ;
+            }
+    }
+    asc_dvc->init_sdtr = eep_config->init_sdtr;
+    asc_dvc->cfg->disc_enable = eep_config->disc_enable;
+    asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
+    asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
+    asc_dvc->start_motor = eep_config->start_motor;
+    asc_dvc->dvc_cntl = eep_config->cntl;
+    asc_dvc->no_scam = eep_config->no_scam;
+    asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
+    asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
+    asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
+    asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
+    asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
+    asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
+    if (!AscTestExternalLram(asc_dvc)) {
+        if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) {
+            eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
+            eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
+        } else {
+            eep_config->cfg_msw |= 0x0800;
+            cfg_msw |= 0x0800;
+            AscSetChipCfgMsw(iop_base, cfg_msw);
+            eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
+            eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
+        }
+    } else {
+    }
+    if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
+        eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
+    }
+    if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
+        eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
+    }
+    if (eep_config->max_tag_qng > eep_config->max_total_qng) {
+        eep_config->max_tag_qng = eep_config->max_total_qng;
+    }
+    if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
+        eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
+    }
+    asc_dvc->max_total_qng = eep_config->max_total_qng;
+    if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
+        eep_config->use_cmd_qng) {
+        eep_config->disc_enable = eep_config->use_cmd_qng;
+        warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
+    }
+    if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
+        asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
+    }
+    eep_config->chip_scsi_id &= ASC_MAX_TID;
+    asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
+    if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
+        !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
+        asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
+    }
+
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
+        asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
+        asc_dvc->cfg->sdtr_period_offset[i] =
+            (uchar) (ASC_DEF_SDTR_OFFSET |
+                     (asc_dvc->host_init_sdtr_index << 4));
+    }
+    eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
+    if (write_eep) {
+        (void) AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
+    }
+    return (warn_code);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscInitMicroCodeVar(
+                       ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+)
+{
+    int                 i;
+    ushort              warn_code;
+    PortAddr            iop_base;
+    ulong               phy_addr;
+
+    iop_base = asc_dvc->iop_base;
+    warn_code = 0;
+    for (i = 0; i <= ASC_MAX_TID; i++) {
+        AscPutMCodeInitSDTRAtID(iop_base, i,
+                                asc_dvc->cfg->sdtr_period_offset[i]
+);
+    }
+    AscInitQLinkVar(asc_dvc);
+    AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
+                     asc_dvc->cfg->disc_enable);
+    AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
+                     ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
+    if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+                                 (uchar *) asc_dvc->cfg->overrun_buf,
+                                     ASC_OVERRUN_BSIZE)) == 0L) {
+        asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
+    } else {
+        phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
+        AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
+        AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
+                          ASC_OVERRUN_BSIZE - 8);
+    }
+    asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
+                                               (ushort) ASCV_MC_DATE_W);
+    asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
+                                                  (ushort) ASCV_MC_VER_W);
+    AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
+    if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
+        asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
+        return (warn_code);
+    }
+    if (AscStartChip(iop_base) != 1) {
+        asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
+        return (warn_code);
+    }
+    return (warn_code);
+}
+
+STATIC void
+AscInitPollIsrCallBack(
+                          ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                          ASC_QDONE_INFO * scsi_done_q
+)
+{
+    ASC_SCSI_REQ_Q *scsiq_req;
+    ASC_ISR_CALLBACK    asc_isr_callback;
+    uchar               cp_sen_len;
+    uchar               i;
+
+    ASC_DBG(1, "AscInitPollIsrCallBack: begin\n");
+    if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) {
+        scsiq_req = (ASC_SCSI_REQ_Q *) scsi_done_q->d2.srb_ptr;
+        scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat;
+        scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat;
+        scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat;
+        scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg;
+        ASC_DBG4(1, "AscInitPollIsrCallBack: done_stat %x, host_stat %x, scsi_stat %x, scsi_msg %x\n",
+            scsi_done_q->d3.done_stat, scsi_done_q->d3.host_stat,
+            scsi_done_q->d3.scsi_stat, scsi_done_q->d3.scsi_msg);
+        if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) &&
+            (scsi_done_q->d3.host_stat == 0)) {
+            cp_sen_len = (uchar) ASC_MIN_SENSE_LEN;
+            if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) {
+                cp_sen_len = (uchar) scsiq_req->r1.sense_len;
+            }
+            for (i = 0; i < cp_sen_len; i++) {
+                scsiq_req->sense[i] = scsiq_req->sense_ptr[i];
+            }
+        }
+    } else {
+        if (asc_dvc->isr_callback != 0) {
+            asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+            (*asc_isr_callback) (asc_dvc, scsi_done_q);
+        }
+    }
+    ASC_DBG(1, "AscInitPollIsrCallBack: end\n");
+    return;
+}
+
+ASC_INITFUNC(
+STATIC int
+AscTestExternalLram(
+                       ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+)
+{
+    PortAddr            iop_base;
+    ushort              q_addr;
+    ushort              saved_word;
+    int                 sta;
+
+    iop_base = asc_dvc->iop_base;
+    sta = 0;
+    q_addr = ASC_QNO_TO_QADDR(241);
+    saved_word = AscReadLramWord(iop_base, q_addr);
+    AscSetChipLramAddr(iop_base, q_addr);
+    AscSetChipLramData(iop_base, 0x55AA);
+    DvcSleepMilliSecond(10);
+    AscSetChipLramAddr(iop_base, q_addr);
+    if (AscGetChipLramData(iop_base) == 0x55AA) {
+        sta = 1;
+        AscWriteLramWord(iop_base, q_addr, saved_word);
+    }
+    return (sta);
+}
+
+ASC_INITFUNC(
+STATIC int
+AscWriteEEPCmdReg(
+                     PortAddr iop_base,
+                     uchar cmd_reg
+)
+)
+{
+    uchar               read_back;
+    int                 retry;
+
+    retry = 0;
+    while (TRUE) {
+        AscSetChipEEPCmd(iop_base, cmd_reg);
+        DvcSleepMilliSecond(1);
+        read_back = AscGetChipEEPCmd(iop_base);
+        if (read_back == cmd_reg) {
+            return (1);
+        }
+        if (retry++ > ASC_EEP_MAX_RETRY) {
+            return (0);
+        }
+    }
+}
+
+ASC_INITFUNC(
+STATIC int
+AscWriteEEPDataReg(
+                      PortAddr iop_base,
+                      ushort data_reg
+)
+)
+{
+    ushort              read_back;
+    int                 retry;
+
+    retry = 0;
+    while (TRUE) {
+        AscSetChipEEPData(iop_base, data_reg);
+        DvcSleepMilliSecond(1);
+        read_back = AscGetChipEEPData(iop_base);
+        if (read_back == data_reg) {
+            return (1);
+        }
+        if (retry++ > ASC_EEP_MAX_RETRY) {
+            return (0);
+        }
+    }
+}
+
+ASC_INITFUNC(
+STATIC void
+AscWaitEEPRead(
+                  void
+)
+)
+{
+    DvcSleepMilliSecond(1);
+    return;
+}
+
+ASC_INITFUNC(
+STATIC void
+AscWaitEEPWrite(
+                   void
+)
+)
+{
+    DvcSleepMilliSecond(20);
+    return;
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscReadEEPWord(
+                  PortAddr iop_base,
+                  uchar addr
+)
+)
+{
+    ushort              read_wval;
+    uchar               cmd_reg;
+
+    AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
+    AscWaitEEPRead();
+    cmd_reg = addr | ASC_EEP_CMD_READ;
+    AscWriteEEPCmdReg(iop_base, cmd_reg);
+    AscWaitEEPRead();
+    read_wval = AscGetChipEEPData(iop_base);
+    AscWaitEEPRead();
+    return (read_wval);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscWriteEEPWord(
+                   PortAddr iop_base,
+                   uchar addr,
+                   ushort word_val
+)
+)
+{
+    ushort              read_wval;
+
+    read_wval = AscReadEEPWord(iop_base, addr);
+    if (read_wval != word_val) {
+        AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
+        AscWaitEEPRead();
+        AscWriteEEPDataReg(iop_base, word_val);
+        AscWaitEEPRead();
+        AscWriteEEPCmdReg(iop_base,
+                          (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
+        AscWaitEEPWrite();
+        AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
+        AscWaitEEPRead();
+        return (AscReadEEPWord(iop_base, addr));
+    }
+    return (read_wval);
+}
+
+ASC_INITFUNC(
+STATIC ushort
+AscGetEEPConfig(
+                   PortAddr iop_base,
+                   ASCEEP_CONFIG * cfg_buf, ushort bus_type
+)
+)
+{
+    ushort              wval;
+    ushort              sum;
+    ushort      *wbuf;
+    int                 cfg_beg;
+    int                 cfg_end;
+    int                 s_addr;
+    int                 isa_pnp_wsize;
+
+    wbuf = (ushort *) cfg_buf;
+    sum = 0;
+    isa_pnp_wsize = 0;
+    for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
+        wval = AscReadEEPWord(iop_base, (uchar) s_addr);
+        sum += wval;
+        *wbuf = wval;
+    }
+    if (bus_type & ASC_IS_VL) {
+        cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
+        cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
+    } else {
+        cfg_beg = ASC_EEP_DVC_CFG_BEG;
+        cfg_end = ASC_EEP_MAX_DVC_ADDR;
+    }
+    for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
+         s_addr++, wbuf++) {
+        wval = AscReadEEPWord(iop_base, (uchar) s_addr);
+        sum += wval;
+        *wbuf = wval;
+    }
+    *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
+    return (sum);
 }
 
 ASC_INITFUNC(
-STATIC ushort
-AscInitAsc1000Driver(
-                        ASC_DVC_VAR asc_ptr_type * asc_dvc
+STATIC int
+AscSetEEPConfigOnce(
+                       PortAddr iop_base,
+                       ASCEEP_CONFIG * cfg_buf, ushort bus_type
 )
 )
 {
-    ushort              warn_code;
-    PortAddr            iop_base;
-    extern ushort       _mcode_size;
-    extern ulong        _mcode_chksum;
-    extern uchar        _mcode_buf[];
-    iop_base = asc_dvc->iop_base;
-    warn_code = 0;
-    if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
-        !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
-        AscResetChipAndScsiBus(iop_base);
-        DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
+    int                 n_error;
+    ushort      *wbuf;
+    ushort              sum;
+    int                 s_addr;
+    int                 cfg_beg;
+    int                 cfg_end;
+
+    wbuf = (ushort *) cfg_buf;
+    n_error = 0;
+    sum = 0;
+    for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
+        sum += *wbuf;
+        if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
+            n_error++;
+        }
     }
-    asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
-    if (asc_dvc->err_code != 0)
-        return (UW_ERR);
-    if (!AscFindSignature(asc_dvc->iop_base)) {
-        asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
-        return (warn_code);
+    if (bus_type & ASC_IS_VL) {
+        cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
+        cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
+    } else {
+        cfg_beg = ASC_EEP_DVC_CFG_BEG;
+        cfg_end = ASC_EEP_MAX_DVC_ADDR;
     }
-    AscDisableInterrupt(iop_base);
-    warn_code |= AscInitLram(asc_dvc);
-    if (asc_dvc->err_code != 0)
-        return (UW_ERR);
-    if (AscLoadMicroCode(iop_base, 0, (ushort *) _mcode_buf,
-                         _mcode_size) != _mcode_chksum) {
-        asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
-        return (warn_code);
+    for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
+         s_addr++, wbuf++) {
+        sum += *wbuf;
+        if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
+            n_error++;
+        }
     }
-    warn_code |= AscInitMicroCodeVar(asc_dvc);
-    asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
-    AscEnableInterrupt(iop_base);
-    return (warn_code);
+    *wbuf = sum;
+    if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
+        n_error++;
+    }
+    wbuf = (ushort *) cfg_buf;
+    for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
+        if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
+            n_error++;
+        }
+    }
+    for (s_addr = cfg_beg; s_addr <= cfg_end;
+         s_addr++, wbuf++) {
+        if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
+            n_error++;
+        }
+    }
+    return (n_error);
 }
 
 ASC_INITFUNC(
-STATIC ushort
-AscInitAscDvcVar(
-                    ASC_DVC_VAR asc_ptr_type * asc_dvc
+STATIC int
+AscSetEEPConfig(
+                   PortAddr iop_base,
+                   ASCEEP_CONFIG * cfg_buf, ushort bus_type
 )
 )
 {
-    int                 i;
+    int            retry;
+    int            n_error;
+
+    retry = 0;
+    while (TRUE) {
+        if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
+                                           bus_type)) == 0) {
+            break;
+        }
+        if (++retry > ASC_EEP_MAX_RETRY) {
+            break;
+        }
+    }
+    return (n_error);
+}
+
+STATIC int
+AscInitPollBegin(
+                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
     PortAddr            iop_base;
-    ushort              warn_code;
-    uchar               chip_version;
+
     iop_base = asc_dvc->iop_base;
-    warn_code = 0;
-    asc_dvc->err_code = 0;
-    if ((asc_dvc->bus_type &
-         (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
-        asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
-    }
-    AscSetChipControl(iop_base, CC_HALT);
-    AscSetChipStatus(iop_base, 0);
-    asc_dvc->bug_fix_cntl = 0;
-    asc_dvc->pci_fix_asyn_xfer = 0;
-    asc_dvc->pci_fix_asyn_xfer_always = 0;
-    asc_dvc->init_state = 0;
-    asc_dvc->sdtr_done = 0;
-    asc_dvc->cur_total_qng = 0;
-    asc_dvc->is_in_int = 0;
-    asc_dvc->in_critical_cnt = 0;
-    asc_dvc->last_q_shortage = 0;
+    AscDisableInterrupt(iop_base);
+    asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY;
+    AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00);
     asc_dvc->use_tagged_qng = 0;
-    asc_dvc->no_scam = 0;
-    asc_dvc->unit_not_ready = 0;
-    asc_dvc->queue_full_or_busy = 0;
-    asc_dvc->redo_scam = 0 ;
-    asc_dvc->res2 = 0 ;
-    asc_dvc->host_init_sdtr_index = 0 ;
-    asc_dvc->res7 = 0 ;
-    asc_dvc->res8 = 0 ;
-    asc_dvc->cfg->can_tagged_qng = 0 ;
-    asc_dvc->cfg->cmd_qng_enabled = 0;
-    asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
-    asc_dvc->init_sdtr = ASC_SCSI_WIDTH_BIT_SET;
-    asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
-    asc_dvc->scsi_reset_wait = 3;
-    asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
-    asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
-    asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
-    asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
-    asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
-    asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
-      ASC_LIB_VERSION_MINOR;
-    chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
-    asc_dvc->cfg->chip_version = chip_version;
-    asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
-    asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
-    asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
-    asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
-    asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
-    asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
-    asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
-    asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
-    asc_dvc->max_sdtr_index = 7;
-    if ((asc_dvc->bus_type & ASC_IS_PCI) &&
-        (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
-        asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
-        asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
-        asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
-        asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
-        asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
-        asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
-        asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
-        asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
-        asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
-        asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
-        asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
-        asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
-        asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
-        asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
-        asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
-        asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
-        asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
-        asc_dvc->max_sdtr_index = 15;
-        if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150)
-        {
-            AscSetExtraControl(iop_base,
-                (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
-        } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
-            AscSetExtraControl(iop_base,
-                (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER));
-        }
-    }
-    if (asc_dvc->bus_type == ASC_IS_PCI) {
-           AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
-    }
+    asc_dvc->cfg->can_tagged_qng = 0;
+    asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback;
+    asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack);
+    return (0);
+}
 
-    asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
-    if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
-        AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
-        asc_dvc->bus_type = ASC_IS_ISAPNP;
-    }
-    if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
-        asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
-    }
+STATIC int
+AscInitPollEnd(
+                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+    PortAddr            iop_base;
+    rint                i;
+
+    iop_base = asc_dvc->iop_base;
+    asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func;
+    AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
+                     asc_dvc->cfg->disc_enable);
+    AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B,
+                     asc_dvc->use_tagged_qng);
+    AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B,
+                     asc_dvc->cfg->can_tagged_qng);
     for (i = 0; i <= ASC_MAX_TID; i++) {
-        asc_dvc->cur_dvc_qng[i] = 0;
-        asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
-        asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L;
-        asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L;
-        asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
+        AscWriteLramByte(iop_base,
+                      (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i),
+                         asc_dvc->max_dvc_qng[i]);
     }
-    return (warn_code);
+    AscAckInterrupt(iop_base);
+    AscEnableInterrupt(iop_base);
+    asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY;
+    return (0);
 }
 
-#if CC_INCLUDE_EEP_CONFIG
-ASC_INITFUNC(
-STATIC ushort
-AscInitFromEEP(
-                  ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+STATIC int
+AscInitPollTarget(
+                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                     REG ASC_SCSI_REQ_Q * scsiq,
+                     REG ASC_SCSI_INQUIRY * inq,
+                     REG ASC_CAP_INFO * cap_info
 )
 {
-    ASCEEP_CONFIG       eep_config_buf;
-    ASCEEP_CONFIG *eep_config;
-    PortAddr            iop_base;
-    ushort              chksum;
-    ushort              warn_code;
-    ushort              cfg_msw, cfg_lsw;
-    int                 i;
-    iop_base = asc_dvc->iop_base;
-    warn_code = 0;
-    AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
-    AscStopQueueExe(iop_base);
-    if ((AscStopChip(iop_base) == FALSE) ||
-        (AscGetChipScsiCtrl(iop_base) != 0)) {
-        asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
-        AscResetChipAndScsiBus(iop_base);
-        DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000));
-    }
-    if (AscIsChipHalted(iop_base) == FALSE) {
-        asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
-        return (warn_code);
-    }
-    AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
-    if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
-        asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
-        return (warn_code);
-    }
-    eep_config = (ASCEEP_CONFIG *) & eep_config_buf;
-    cfg_msw = AscGetChipCfgMsw(iop_base);
-    cfg_lsw = AscGetChipCfgLsw(iop_base);
-    if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
-        cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
-        warn_code |= ASC_WARN_CFG_MSW_RECOVER;
-        AscSetChipCfgMsw(iop_base, cfg_msw);
+    uchar               tid_no, lun;
+    uchar               dvc_type;
+    ASC_SCSI_BIT_ID_TYPE tid_bits;
+    int                 dvc_found;
+    int                 support_read_cap;
+    int                 tmp_disable_init_sdtr;
+    int                 sta;
+
+    dvc_found = 0;
+    tmp_disable_init_sdtr = FALSE;
+    tid_bits = scsiq->r1.target_id;
+    lun = scsiq->r1.target_lun;
+    tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix);
+    if (((asc_dvc->init_sdtr & tid_bits) != 0) &&
+        ((asc_dvc->sdtr_done & tid_bits) == 0)) {
+        asc_dvc->init_sdtr &= ~tid_bits;
+        tmp_disable_init_sdtr = TRUE;
     }
-    chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
-    eep_config->cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK));
-    if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
-        warn_code |= ASC_WARN_AUTO_CONFIG;
-        if (asc_dvc->cfg->chip_version == 3) {
-            if (eep_config->cfg_lsw != cfg_lsw) {
-                warn_code |= ASC_WARN_EEPROM_RECOVER;
-                eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base);
+    ASC_DBG(1, "AscInitPollTarget: before PollScsiInquiry\n");
+    if (PollScsiInquiry(asc_dvc, scsiq, (uchar *) inq,
+        sizeof (ASC_SCSI_INQUIRY)) == 1) {
+        dvc_found = 1;
+        dvc_type = inq->byte0.peri_dvc_type;
+        if (dvc_type != SCSI_TYPE_UNKNOWN) {
+            support_read_cap = TRUE;
+            if ((dvc_type != SCSI_TYPE_DASD)
+                && (dvc_type != SCSI_TYPE_WORM)
+                && (dvc_type != SCSI_TYPE_CDROM)
+                && (dvc_type != SCSI_TYPE_OPTMEM)) {
+                asc_dvc->start_motor &= ~tid_bits;
+                support_read_cap = FALSE;
             }
-            if (eep_config->cfg_msw != cfg_msw) {
-                warn_code |= ASC_WARN_EEPROM_RECOVER;
-                eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
+            if (lun == 0) {
+                if ((inq->byte3.rsp_data_fmt >= 2) ||
+                    (inq->byte2.ansi_apr_ver >= 2)) {
+                    if (inq->byte7.CmdQue) {
+                        asc_dvc->cfg->can_tagged_qng |= tid_bits;
+                        if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) {
+                                asc_dvc->use_tagged_qng |= tid_bits;
+                                asc_dvc->max_dvc_qng[tid_no] = asc_dvc->cfg->max_tag_qng[tid_no];
+                        }
+                    }
+                    if (!inq->byte7.Sync) {
+                        asc_dvc->init_sdtr &= ~tid_bits;
+                        asc_dvc->sdtr_done &= ~tid_bits;
+                    } else if (tmp_disable_init_sdtr) {
+                        asc_dvc->init_sdtr |= tid_bits;
+                    }
+                } else {
+                    asc_dvc->init_sdtr &= ~tid_bits;
+                    asc_dvc->sdtr_done &= ~tid_bits;
+                    asc_dvc->use_tagged_qng &= ~tid_bits;
+                }
+            }
+            if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
+                if (!(asc_dvc->init_sdtr & tid_bits)) {
+                    if ((dvc_type == SCSI_TYPE_CDROM) &&
+                        (AscCompareString((uchar *) inq->vendor_id,
+                            (uchar *) "HP ", 3) == 0)) {
+                        asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
+                    }
+                    asc_dvc->pci_fix_asyn_xfer |= tid_bits;
+                    if ((dvc_type == SCSI_TYPE_PROC) || (dvc_type == SCSI_TYPE_SCANNER)) {
+                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
+                    }
+                    if ((dvc_type == SCSI_TYPE_SASD) &&
+                        (AscCompareString((uchar *) inq->vendor_id,
+                            (uchar *) "TANDBERG", 8) == 0) &&
+                        (AscCompareString((uchar *) inq->product_id,
+                         (uchar *) " TDC 36", 7) == 0)) {
+                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
+                    }
+                    if ((dvc_type == SCSI_TYPE_SASD) &&
+                        (AscCompareString((uchar *) inq->vendor_id,
+                         (uchar *) "WANGTEK ", 8) == 0)) {
+                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
+                    }
+
+                    if ((dvc_type == SCSI_TYPE_CDROM) &&
+                       (AscCompareString((uchar *)inq->vendor_id,
+                        (uchar *)"NEC     ", 8) == 0) &&
+                        (AscCompareString((uchar *)inq->product_id,
+                         (uchar *)"CD-ROM DRIVE    ", 16) == 0)) {
+                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits ;
+                    }
+                    if ((dvc_type == SCSI_TYPE_CDROM) &&
+                        (AscCompareString((uchar *) inq->vendor_id,
+                         (uchar *) "YAMAHA", 6) == 0)  &&
+                        (AscCompareString((uchar *) inq->product_id,
+                         (uchar *) "CDR400", 6) == 0))
+                    {
+                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits ;
+                    }
+                    if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
+                        AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
+                                                ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+                    }
+                }
+            }
+            sta = 1;
+            ASC_DBG(1, "AscInitPollTarget: before InitTestUnitReady\n");
+            sta = InitTestUnitReady(asc_dvc, scsiq);
+            if (sta == 1) {
+                if ((cap_info != 0L) && support_read_cap) {
+                    ASC_DBG(1,
+                        "AscInitPollTarget: before PollScsiReadCapacity\n");
+                    if (PollScsiReadCapacity(asc_dvc, scsiq,
+                                             cap_info) != 1) {
+                        cap_info->lba = 0L;
+                        cap_info->blk_size = 0x0000;
+                    } else {
+                    }
+                }
             }
-        }
-    }
-    eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
-    if (chksum != eep_config->chksum) {
-        warn_code |= ASC_WARN_EEPROM_CHKSUM;
-    }
-    asc_dvc->init_sdtr = eep_config->init_sdtr;
-    asc_dvc->cfg->disc_enable = eep_config->disc_enable;
-    asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
-    asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
-    asc_dvc->start_motor = eep_config->start_motor;
-    asc_dvc->dvc_cntl = eep_config->cntl;
-    asc_dvc->no_scam = eep_config->no_scam;
-    if (!AscTestExternalLram(asc_dvc)) {
-        if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) {
-            eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
-            eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
         } else {
-            eep_config->cfg_msw |= 0x0800;
-            cfg_msw |= 0x0800;
-            AscSetChipCfgMsw(iop_base, cfg_msw);
-            eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
-            eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
+            asc_dvc->start_motor &= ~tid_bits;
         }
-    } else {
-    }
-    if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
-        eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
-    }
-    if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
-        eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
-    }
-    if (eep_config->max_tag_qng > eep_config->max_total_qng) {
-        eep_config->max_tag_qng = eep_config->max_total_qng;
-    }
-    if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
-        eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
-    }
-    asc_dvc->max_total_qng = eep_config->max_total_qng;
-    if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
-        eep_config->use_cmd_qng) {
-        eep_config->disc_enable = eep_config->use_cmd_qng;
-        warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
+    } else if (tmp_disable_init_sdtr) {
+        asc_dvc->init_sdtr |= tid_bits;
     }
-    if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
-        asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
+    ASC_DBG1(1, "AscInitPollTarget: dvc_found %d\n", dvc_found);
+    return (dvc_found);
+}
+
+STATIC int
+PollQueueDone(
+                 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                 REG ASC_SCSI_REQ_Q * scsiq,
+                 int timeout_sec
+)
+{
+    int                 status;
+    int                 retry = 0;
+
+    ASC_DBG1(1, "PollQueueDone: timeout_sec %d\n", timeout_sec);
+    do {
+        ASC_DBG(1, "PollQueueDone: before AscExeScsiQueue\n");
+        if ((status = AscExeScsiQueue(asc_dvc,
+                (ASC_SCSI_Q *) scsiq)) == 1) {
+            ASC_DBG(1, "PollQueueDone: before AscPollQDone\n");
+            if ((status = AscPollQDone(asc_dvc, scsiq,
+                                       timeout_sec)) != 1) {
+                ASC_DBG1(1, "PollQueueDone: status %x\n", status);
+                if (status == 0x80) {
+                    if (retry++ > ASC_MAX_INIT_BUSY_RETRY) {
+                        break;
+                    }
+                    scsiq->r3.done_stat = 0;
+                    scsiq->r3.host_stat = 0;
+                    scsiq->r3.scsi_stat = 0;
+                    scsiq->r3.scsi_msg = 0;
+                    DvcSleepMilliSecond(1000);
+                    continue;
+                }
+                scsiq->r3.done_stat = 0;
+                scsiq->r3.host_stat = 0;
+                scsiq->r3.scsi_stat = 0;
+                scsiq->r3.scsi_msg = 0;
+                ASC_DBG(1, "PollQueueDone: before AscAbortSRB()\n");
+                AscAbortSRB(asc_dvc, (ulong) scsiq);
+            }
+            ASC_DBG1(1, "PollQueueDone: status %x\n", status);
+            ASC_DBG1(1, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
+            return (scsiq->r3.done_stat);
+        }
+        ASC_DBG1(1, "PollQueueDone: status %x\n", status);
+        DvcSleepMilliSecond(5);
+    } while (((status == 0) || (status == 0x80)) &&
+              retry++ < ASC_MAX_INIT_BUSY_RETRY);
+    ASC_DBG1(1, "PollQueueDone: status %x\n", status);
+    ASC_DBG(1, "PollQueueDone: done_stat QD_WITH_ERROR\n");
+    return (scsiq->r3.done_stat = QD_WITH_ERROR);
+}
+
+STATIC int
+PollScsiInquiry(
+                   REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                   REG ASC_SCSI_REQ_Q * scsiq,
+                   uchar * buf,
+                   int buf_len
+)
+{
+    if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) {
+        return (scsiq->r3.done_stat = QD_WITH_ERROR);
     }
-    eep_config->chip_scsi_id &= ASC_MAX_TID;
-    asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id;
-    if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
-        !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
-        asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
+    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 4));
+}
+
+STATIC int
+PollScsiStartUnit(
+                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                     REG ASC_SCSI_REQ_Q * scsiq
+)
+{
+    if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) {
+        return (scsiq->r3.done_stat = QD_WITH_ERROR);
     }
+    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 40));
+}
 
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-#if CC_TMP_USE_EEP_SDTR
-        asc_dvc->cfg->sdtr_period_offset[i] = eep_config->dos_int13_table[i];
-#endif
-        asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
-        asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
-        asc_dvc->cfg->sdtr_period_offset[i] =
-            (uchar) (ASC_DEF_SDTR_OFFSET |
-                     (asc_dvc->host_init_sdtr_index << 4));
+STATIC int
+PollScsiReadCapacity(
+                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                        REG ASC_SCSI_REQ_Q * scsiq,
+                        REG ASC_CAP_INFO * cap_info
+)
+{
+    ASC_CAP_INFO        scsi_cap_info;
+    int                 status;
+
+    if (AscScsiReadCapacity(asc_dvc, scsiq,
+                            (uchar *) & scsi_cap_info) == ERR) {
+        return (scsiq->r3.done_stat = QD_WITH_ERROR);
     }
-    eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
-#if CC_CHK_FIX_EEP_CONTENT
-    if (AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type) != 0) {
-        asc_dvc->err_code |= ASC_IERR_WRITE_EEPROM;
+    status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 8);
+    if (status == 1) {
+        cap_info->lba = (ulong) * swapfarbuf4((uchar *) & scsi_cap_info.lba);
+        cap_info->blk_size = (ulong) * swapfarbuf4((uchar *) & scsi_cap_info.blk_size);
+        return (scsiq->r3.done_stat);
     }
-#endif
-    return (warn_code);
+    return (scsiq->r3.done_stat = QD_WITH_ERROR);
 }
-#endif
 
-ASC_INITFUNC(
-STATIC ushort
-AscInitMicroCodeVar(
-                       ASC_DVC_VAR asc_ptr_type * asc_dvc
+STATIC ulong *
+swapfarbuf4(
+    uchar *buf
 )
+{
+    uchar      tmp;
+
+    tmp = buf[3];
+    buf[3] = buf[0];
+    buf[0] = tmp;
+
+    tmp = buf[1];
+    buf[1] = buf[2];
+    buf[2] = tmp;
+
+    return ((ulong *) buf);
+}
+
+STATIC int
+PollScsiTestUnitReady(
+                         REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                         REG ASC_SCSI_REQ_Q * scsiq
 )
 {
-    int                 i;
-    ushort              warn_code;
-    PortAddr            iop_base;
-    ulong               phy_addr;
-    iop_base = asc_dvc->iop_base;
-    warn_code = 0;
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        AscPutMCodeInitSDTRAtID(iop_base, i,
-                                asc_dvc->cfg->sdtr_period_offset[i]
-);
-    }
-    AscInitQLinkVar(asc_dvc);
-    AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
-                     asc_dvc->cfg->disc_enable);
-    AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
-                     ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
-    if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
-                                 (uchar *) asc_dvc->cfg->overrun_buf,
-                                     ASC_OVERRUN_BSIZE)) == 0L) {
-        asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR;
-    } else {
-        phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8;
-        AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr);
-        AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D,
-                          ASC_OVERRUN_BSIZE - 8);
-    }
-    asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base,
-                                               (ushort) ASCV_MC_DATE_W);
-    asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base,
-                                                  (ushort) ASCV_MC_VER_W);
-    AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
-    if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
-        asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
-        return (warn_code);
-    }
-    if (AscStartChip(iop_base) != 1) {
-        asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
-        return (warn_code);
+    if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) {
+        return (scsiq->r3.done_stat = QD_WITH_ERROR);
     }
-    return (warn_code);
+    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 12));
 }
 
-STATIC void
-AscInitPollIsrCallBack(
-                          ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                          ASC_QDONE_INFO * scsi_done_q
+STATIC int
+InitTestUnitReady(
+                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                     REG ASC_SCSI_REQ_Q * scsiq
 )
 {
-    ASC_SCSI_REQ_Q *scsiq_req;
-    ASC_ISR_CALLBACK    asc_isr_callback;
-    uchar               cp_sen_len;
-    uchar               i;
-    ASC_DBG(1, "AscInitPollIsrCallBack: begin\n");
-    if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) {
-        scsiq_req = (ASC_SCSI_REQ_Q *) scsi_done_q->d2.srb_ptr;
-        scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat;
-        scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat;
-        scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat;
-        scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg;
-        ASC_DBG4(1, "AscInitPollIsrCallBack: done_stat %x, host_stat %x, scsi_stat %x, scsi_msg %x\n",
-            scsi_done_q->d3.done_stat, scsi_done_q->d3.host_stat,
-            scsi_done_q->d3.scsi_stat, scsi_done_q->d3.scsi_msg);
-        if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) &&
-            (scsi_done_q->d3.host_stat == 0)) {
-            cp_sen_len = (uchar) ASC_MIN_SENSE_LEN;
-            if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) {
-                cp_sen_len = (uchar) scsiq_req->r1.sense_len;
-            }
-            for (i = 0; i < cp_sen_len; i++) {
-                scsiq_req->sense[i] = scsiq_req->sense_ptr[i];
+    ASC_SCSI_BIT_ID_TYPE tid_bits;
+    int                 retry;
+    ASC_REQ_SENSE *sen;
+
+    retry = 0;
+    tid_bits = scsiq->r1.target_id;
+    while (retry++ < 4) {
+        PollScsiTestUnitReady(asc_dvc, scsiq);
+        if (scsiq->r3.done_stat == 0x01) {
+            return (1);
+        } else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
+            sen = (ASC_REQ_SENSE *) scsiq->sense_ptr;
+            if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) &&
+                ((sen->err_code & 0x70) != 0)) {
+                if (sen->sense_key == SCSI_SENKEY_NOT_READY) {
+                    if (sen->asc == SCSI_ASC_NOMEDIA)
+                    {
+                        break;
+                    }
+                    if (asc_dvc->start_motor & tid_bits) {
+                        if (PollScsiStartUnit(asc_dvc, scsiq) == 1) {
+                            DvcSleepMilliSecond(250);
+                            continue;
+                        } else {
+                            asc_dvc->start_motor &= ~tid_bits;
+                            break;
+                        }
+                    } else {
+                        DvcSleepMilliSecond(250);
+                    }
+                } else if (sen->sense_key == SCSI_SENKEY_ATTENTION) {
+                    DvcSleepMilliSecond(250);
+                } else {
+                    break;
+                }
+            } else {
+                break;
             }
-        }
-    } else {
-        if (asc_dvc->isr_callback != 0) {
-            asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
-            (*asc_isr_callback) (asc_dvc, scsi_done_q);
+        } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) {
+            break;
+        } else {
+            break;
         }
     }
-    ASC_DBG(1, "AscInitPollIsrCallBack: end\n");
-    return;
+    return (0);
 }
 
-ASC_INITFUNC(
 STATIC int
-AscTestExternalLram(
-                       ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+AscPollQDone(
+                REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                REG ASC_SCSI_REQ_Q * scsiq,
+                int timeout_sec
 )
 {
-    PortAddr            iop_base;
-    ushort              q_addr;
-    ushort              saved_word;
+    int                 loop, loop_end;
     int                 sta;
+    PortAddr            iop_base;
+
     iop_base = asc_dvc->iop_base;
-    sta = 0;
-    q_addr = ASC_QNO_TO_QADDR(241);
-    saved_word = AscReadLramWord(iop_base, q_addr);
-    AscSetChipLramAddr(iop_base, q_addr);
-    AscSetChipLramData(iop_base, 0x55AA);
-    DvcSleepMilliSecond(10);
-    AscSetChipLramAddr(iop_base, q_addr);
-    if (AscGetChipLramData(iop_base) == 0x55AA) {
-        sta = 1;
-        AscWriteLramWord(iop_base, q_addr, saved_word);
+    loop = 0;
+    loop_end = timeout_sec * 100;
+    sta = 1;
+    while (TRUE) {
+        if (asc_dvc->err_code != 0) {
+            scsiq->r3.done_stat = QD_WITH_ERROR;
+            ASC_DBG1(1, "AscPollQDone: err_code %x\n", asc_dvc->err_code);
+            sta = ERR;
+            break;
+        }
+        if (scsiq->r3.done_stat != QD_IN_PROGRESS) {
+            if ((scsiq->r3.done_stat == QD_WITH_ERROR) &&
+                (scsiq->r3.scsi_stat == SS_TARGET_BUSY)) {
+                sta = 0x80;
+            }
+            break;
+        }
+        DvcSleepMilliSecond(10);
+        if (loop++ > loop_end) {
+            ASC_DBG(1, "AscPollQDone: loop finished\n");
+            sta = 0;
+            break;
+        }
+        if (AscIsChipHalted(iop_base)) {
+            ASC_DBG(1, "AscPollQDone: AscIsChipHalted()\n");
+            AscISR(asc_dvc);
+            loop = 0;
+        } else {
+            if (AscIsIntPending(iop_base)) {
+                ASC_DBG(1, "AscPollQDone: AscIsIntPending()\n");
+                AscISR(asc_dvc);
+            }
+        }
     }
     return (sta);
 }
 
-#if CC_INCLUDE_EEP_CONFIG
-ASC_INITFUNC(
 STATIC int
-AscWriteEEPCmdReg(
-                     PortAddr iop_base,
-                     uchar cmd_reg
-)
+AscCompareString(
+                    ruchar * str1,
+                    ruchar * str2,
+                    int len
 )
 {
-    uchar               read_back;
-    int                 retry;
-    retry = 0;
-    while (TRUE) {
-        AscSetChipEEPCmd(iop_base, cmd_reg);
-        DvcSleepMilliSecond(1);
-        read_back = AscGetChipEEPCmd(iop_base);
-        if (read_back == cmd_reg) {
-            return (1);
-        }
-        if (retry++ > ASC_EEP_MAX_RETRY) {
-            return (0);
-        }
+    int                 i;
+    int                 diff;
+
+    for (i = 0; i < len; i++) {
+        diff = (int) (str1[i] - str2[i]);
+        if (diff != 0)
+            return (diff);
     }
+    return (0);
 }
 
-ASC_INITFUNC(
-STATIC int
-AscWriteEEPDataReg(
-                      PortAddr iop_base,
-                      ushort data_reg
-)
+STATIC uchar
+AscReadLramByte(
+                   PortAddr iop_base,
+                   ushort addr
 )
 {
-    ushort              read_back;
-    int                 retry;
-    retry = 0;
-    while (TRUE) {
-        AscSetChipEEPData(iop_base, data_reg);
-        DvcSleepMilliSecond(1);
-        read_back = AscGetChipEEPData(iop_base);
-        if (read_back == data_reg) {
-            return (1);
-        }
-        if (retry++ > ASC_EEP_MAX_RETRY) {
-            return (0);
-        }
+    uchar               byte_data;
+    ushort              word_data;
+
+    if (isodd_word(addr)) {
+        AscSetChipLramAddr(iop_base, addr - 1);
+        word_data = AscGetChipLramData(iop_base);
+        byte_data = (uchar) ((word_data >> 8) & 0xFF);
+    } else {
+        AscSetChipLramAddr(iop_base, addr);
+        word_data = AscGetChipLramData(iop_base);
+        byte_data = (uchar) (word_data & 0xFF);
     }
+    return (byte_data);
 }
 
-ASC_INITFUNC(
-STATIC void
-AscWaitEEPRead(
-                  void
-)
+STATIC ushort
+AscReadLramWord(
+                   PortAddr iop_base,
+                   ushort addr
 )
 {
-    DvcSleepMilliSecond(1);
-    return;
-}
+    ushort              word_data;
 
-ASC_INITFUNC(
-STATIC void
-AscWaitEEPWrite(
-                   void
-)
-)
-{
-    DvcSleepMilliSecond(20);
-    return;
+    AscSetChipLramAddr(iop_base, addr);
+    word_data = AscGetChipLramData(iop_base);
+    return (word_data);
 }
 
-ASC_INITFUNC(
-STATIC ushort
-AscReadEEPWord(
-                  PortAddr iop_base,
-                  uchar addr
-)
+STATIC ulong
+AscReadLramDWord(
+                    PortAddr iop_base,
+                    ushort addr
 )
 {
-    ushort              read_wval;
-    uchar               cmd_reg;
-    AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
-    AscWaitEEPRead();
-    cmd_reg = addr | ASC_EEP_CMD_READ;
-    AscWriteEEPCmdReg(iop_base, cmd_reg);
-    AscWaitEEPRead();
-    read_wval = AscGetChipEEPData(iop_base);
-    AscWaitEEPRead();
-    return (read_wval);
+    ushort              val_low, val_high;
+    ulong               dword_data;
+
+    AscSetChipLramAddr(iop_base, addr);
+    val_low = AscGetChipLramData(iop_base);
+    val_high = AscGetChipLramData(iop_base);
+    dword_data = ((ulong) val_high << 16) | (ulong) val_low;
+    return (dword_data);
 }
 
-ASC_INITFUNC(
-STATIC ushort
-AscWriteEEPWord(
-                   PortAddr iop_base,
-                   uchar addr,
-                   ushort word_val
-)
+STATIC void
+AscWriteLramWord(
+                    PortAddr iop_base,
+                    ushort addr,
+                    ushort word_val
 )
 {
-    ushort              read_wval;
-    read_wval = AscReadEEPWord(iop_base, addr);
-    if (read_wval != word_val) {
-        AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
-        AscWaitEEPRead();
-        AscWriteEEPDataReg(iop_base, word_val);
-        AscWaitEEPRead();
-        AscWriteEEPCmdReg(iop_base,
-                          (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr));
-        AscWaitEEPWrite();
-        AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
-        AscWaitEEPRead();
-        return (AscReadEEPWord(iop_base, addr));
-    }
-    return (read_wval);
+    AscSetChipLramAddr(iop_base, addr);
+    AscSetChipLramData(iop_base, word_val);
+    return;
 }
 
-ASC_INITFUNC(
-STATIC ushort
-AscGetEEPConfig(
-                   PortAddr iop_base,
-                   ASCEEP_CONFIG * cfg_buf, ushort bus_type
-)
+STATIC void
+AscWriteLramDWord(
+                     PortAddr iop_base,
+                     ushort addr,
+                     ulong dword_val
 )
 {
-    ushort              wval;
-    ushort              sum;
-    ushort      *wbuf;
-    int                 cfg_beg;
-    int                 cfg_end;
-    int                 s_addr;
-    int                 isa_pnp_wsize;
-    wbuf = (ushort *) cfg_buf;
-    sum = 0;
-    isa_pnp_wsize = 0;
-    for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) {
-        wval = AscReadEEPWord(iop_base, (uchar) s_addr);
-        sum += wval;
-        *wbuf = wval;
-    }
-    if (bus_type & ASC_IS_VL) {
-        cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
-        cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
-    } else {
-        cfg_beg = ASC_EEP_DVC_CFG_BEG;
-        cfg_end = ASC_EEP_MAX_DVC_ADDR;
-    }
-    for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
-         s_addr++, wbuf++) {
-        wval = AscReadEEPWord(iop_base, (uchar) s_addr);
-        sum += wval;
-        *wbuf = wval;
-    }
-    *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr);
-    return (sum);
+    ushort              word_val;
+
+    AscSetChipLramAddr(iop_base, addr);
+    word_val = (ushort) dword_val;
+    AscSetChipLramData(iop_base, word_val);
+    word_val = (ushort) (dword_val >> 16);
+    AscSetChipLramData(iop_base, word_val);
+    return;
 }
 
-#if CC_CHK_FIX_EEP_CONTENT
-ASC_INITFUNC(
-STATIC int
-AscSetEEPConfigOnce(
-                       PortAddr iop_base,
-                       ASCEEP_CONFIG * cfg_buf, ushort bus_type
-)
+STATIC void
+AscWriteLramByte(
+                    PortAddr iop_base,
+                    ushort addr,
+                    uchar byte_val
 )
 {
-    int                 n_error;
-    ushort      *wbuf;
-    ushort              sum;
-    int                 s_addr;
-    int                 cfg_beg;
-    int                 cfg_end;
-    wbuf = (ushort *) cfg_buf;
-    n_error = 0;
-    sum = 0;
-    for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
-        sum += *wbuf;
-        if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
-            n_error++;
-        }
-    }
-    if (bus_type & ASC_IS_VL) {
-        cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
-        cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
-    } else {
-        cfg_beg = ASC_EEP_DVC_CFG_BEG;
-        cfg_end = ASC_EEP_MAX_DVC_ADDR;
-    }
-    for (s_addr = cfg_beg; s_addr <= (cfg_end - 1);
-         s_addr++, wbuf++) {
-        sum += *wbuf;
-        if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) {
-            n_error++;
-        }
-    }
-    *wbuf = sum;
-    if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) {
-        n_error++;
-    }
-    wbuf = (ushort *) cfg_buf;
-    for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
-        if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
-            n_error++;
-        }
-    }
-    for (s_addr = cfg_beg; s_addr <= cfg_end;
-         s_addr++, wbuf++) {
-        if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) {
-            n_error++;
-        }
+    ushort              word_data;
+
+    if (isodd_word(addr)) {
+        addr--;
+        word_data = AscReadLramWord(iop_base, addr);
+        word_data &= 0x00FF;
+        word_data |= (((ushort) byte_val << 8) & 0xFF00);
+    } else {
+        word_data = AscReadLramWord(iop_base, addr);
+        word_data &= 0xFF00;
+        word_data |= ((ushort) byte_val & 0x00FF);
     }
-    return (n_error);
+    AscWriteLramWord(iop_base, addr, word_data);
+    return;
 }
 
-ASC_INITFUNC(
-STATIC int
-AscSetEEPConfig(
-                   PortAddr iop_base,
-                   ASCEEP_CONFIG * cfg_buf, ushort bus_type
-)
+STATIC void
+AscMemWordCopyToLram(
+                        PortAddr iop_base,
+                        ushort s_addr,
+                        ushort * s_buffer,
+                        int words
 )
 {
-    int            retry;
-    int            n_error;
+    AscSetChipLramAddr(iop_base, s_addr);
+    DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
+    return;
+}
 
-    retry = 0;
-    while (TRUE) {
-        if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
-                                           bus_type)) == 0) {
-            break;
-        }
-        if (++retry > ASC_EEP_MAX_RETRY) {
-            break;
-        }
-    }
-    return (n_error);
+STATIC void
+AscMemDWordCopyToLram(
+                         PortAddr iop_base,
+                         ushort s_addr,
+                         ulong * s_buffer,
+                         int dwords
+)
+{
+    AscSetChipLramAddr(iop_base, s_addr);
+    DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
+    return;
 }
-#endif
-#endif
 
-STATIC int
-AscInitPollBegin(
-                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+STATIC void
+AscMemWordCopyFromLram(
+                          PortAddr iop_base,
+                          ushort s_addr,
+                          ushort * d_buffer,
+                          int words
 )
 {
-    PortAddr            iop_base;
-    iop_base = asc_dvc->iop_base;
-    AscDisableInterrupt(iop_base);
-    asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY;
-    AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00);
-    asc_dvc->use_tagged_qng = 0;
-    asc_dvc->cfg->can_tagged_qng = 0;
-    asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback;
-    asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack);
-    return (0);
+    AscSetChipLramAddr(iop_base, s_addr);
+    DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
+    return;
 }
 
-STATIC int
-AscInitPollEnd(
-                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc
+STATIC ulong
+AscMemSumLramWord(
+                     PortAddr iop_base,
+                     ushort s_addr,
+                     rint words
 )
 {
-    PortAddr            iop_base;
-    rint                i;
-    iop_base = asc_dvc->iop_base;
-    asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func;
-    AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
-                     asc_dvc->cfg->disc_enable);
-    AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B,
-                     asc_dvc->use_tagged_qng);
-    AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B,
-                     asc_dvc->cfg->can_tagged_qng);
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        AscWriteLramByte(iop_base,
-                      (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i),
-                         asc_dvc->max_dvc_qng[i]);
+    ulong               sum;
+    int                 i;
+
+    sum = 0L;
+    for (i = 0; i < words; i++, s_addr += 2) {
+        sum += AscReadLramWord(iop_base, s_addr);
     }
-    AscAckInterrupt(iop_base);
-    AscEnableInterrupt(iop_base);
-    asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY;
-    return (0);
+    return (sum);
 }
 
-STATIC int                 _asc_wait_slow_device_ = FALSE;
-
-STATIC int
-AscInitPollTarget(
-                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                     REG ASC_SCSI_REQ_Q * scsiq,
-                     REG ASC_SCSI_INQUIRY * inq,
-                     REG ASC_CAP_INFO * cap_info
+STATIC void
+AscMemWordSetLram(
+                     PortAddr iop_base,
+                     ushort s_addr,
+                     ushort set_wval,
+                     rint words
 )
 {
-    uchar               tid_no, lun;
-    uchar               dvc_type;
-    ASC_SCSI_BIT_ID_TYPE tid_bits;
-    int                 dvc_found;
-    int                 support_read_cap;
-    int                 tmp_disable_init_sdtr;
-    int                 sta;
+    rint             i;
 
-    dvc_found = 0;
-    tmp_disable_init_sdtr = FALSE;
-    tid_bits = scsiq->r1.target_id;
-    lun = scsiq->r1.target_lun;
-    tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix);
-    if (((asc_dvc->init_sdtr & tid_bits) != 0) &&
-        ((asc_dvc->sdtr_done & tid_bits) == 0)) {
-        asc_dvc->init_sdtr &= ~tid_bits;
-        tmp_disable_init_sdtr = TRUE;
+    AscSetChipLramAddr(iop_base, s_addr);
+    for (i = 0; i < words; i++) {
+        AscSetChipLramData(iop_base, set_wval);
     }
-    ASC_DBG(1, "AscInitPollTarget: before PollScsiInquiry\n");
-    if (PollScsiInquiry(asc_dvc, scsiq, (uchar *) inq,
-        sizeof (ASC_SCSI_INQUIRY)) == 1) {
-        dvc_found = 1;
-        support_read_cap = TRUE;
-        dvc_type = inq->byte0.peri_dvc_type;
-        if (dvc_type != SCSI_TYPE_UNKNOWN) {
-            if ((dvc_type != SCSI_TYPE_DASD)
-                && (dvc_type != SCSI_TYPE_WORM)
-                && (dvc_type != SCSI_TYPE_CDROM)
-                && (dvc_type != SCSI_TYPE_OPTMEM)) {
-                asc_dvc->start_motor &= ~tid_bits;
-                support_read_cap = FALSE;
-            }
-            if ((dvc_type != SCSI_TYPE_DASD) || inq->byte1.rmb) {
-                if (!_asc_wait_slow_device_) {
-                    DvcSleepMilliSecond(3000 - ((int) tid_no * 250));
-                    _asc_wait_slow_device_ = TRUE;
-                }
-            }
-            if (lun == 0) {
-                if ((inq->byte3.rsp_data_fmt >= 2) ||
-                    (inq->byte2.ansi_apr_ver >= 2)) {
-                    if (inq->byte7.CmdQue) {
-                        asc_dvc->cfg->can_tagged_qng |= tid_bits;
-                        if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) {
-                                asc_dvc->use_tagged_qng |= tid_bits;
-                                asc_dvc->max_dvc_qng[tid_no] = asc_dvc->cfg->max_tag_qng[tid_no];
-                        }
-                    }
-                    if (!inq->byte7.Sync) {
-                        asc_dvc->init_sdtr &= ~tid_bits;
-                        asc_dvc->sdtr_done &= ~tid_bits;
-                    } else if (tmp_disable_init_sdtr) {
-                        asc_dvc->init_sdtr |= tid_bits;
-                    }
-                } else {
-                    asc_dvc->init_sdtr &= ~tid_bits;
-                    asc_dvc->sdtr_done &= ~tid_bits;
-                    asc_dvc->use_tagged_qng &= ~tid_bits;
-                }
-            }
-            if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
-                if (!(asc_dvc->init_sdtr & tid_bits)) {
-                    if ((dvc_type == SCSI_TYPE_CDROM) &&
-                        (AscCompareString((uchar *) inq->vendor_id,
-                            (uchar *) "HP ", 3) == 0)) {
-                        asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
-                    }
-                    asc_dvc->pci_fix_asyn_xfer |= tid_bits;
-                    if ((dvc_type == SCSI_TYPE_PROC) || (dvc_type == SCSI_TYPE_SCANNER)) {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
-                    }
-                    if ((dvc_type == SCSI_TYPE_SASD) &&
-                        (AscCompareString((uchar *) inq->vendor_id,
-                            (uchar *) "TANDBERG", 8) == 0) &&
-                        (AscCompareString((uchar *) inq->product_id,
-                         (uchar *) " TDC 36", 7) == 0)) {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
-                    }
-                    if ((dvc_type == SCSI_TYPE_SASD) &&
-                        (AscCompareString((uchar *) inq->vendor_id,
-                         (uchar *) "WANGTEK ", 8) == 0)) {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
-                    }
+    return;
+}
 
-                    if ((dvc_type == SCSI_TYPE_CDROM) &&
-                       (AscCompareString((uchar *)inq->vendor_id,
-                        (uchar *)"NEC     ", 8) == 0) &&
-                        (AscCompareString((uchar *)inq->product_id,
-                         (uchar *)"CD-ROM DRIVE    ", 16) == 0)) {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits ;
-                    }
-                    if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
-                        AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
-                                                ASYN_SDTR_DATA_FIX_PCI_REV_AB);
-                    }
-                }
-            }
-            sta = 1;
-            ASC_DBG(1, "AscInitPollTarget: before InitTestUnitReady\n");
-            sta = InitTestUnitReady(asc_dvc, scsiq);
-            if (sta == 1) {
-                if ((cap_info != 0L) && support_read_cap) {
-                    ASC_DBG(1,
-                        "AscInitPollTarget: before PollScsiReadCapacity\n");
-                    if (PollScsiReadCapacity(asc_dvc, scsiq,
-                                             cap_info) != 1) {
-                        cap_info->lba = 0L;
-                        cap_info->blk_size = 0x0000;
-                    } else {
-                    }
-                }
-            }
-        } else {
-            asc_dvc->start_motor &= ~tid_bits;
-        }
-    } else if (tmp_disable_init_sdtr) {
-        asc_dvc->init_sdtr |= tid_bits;
+
+STATIC int
+AscScsiInquiry(
+                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                  REG ASC_SCSI_REQ_Q * scsiq,
+                  uchar * buf,
+                  int buf_len
+)
+{
+    if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf,
+                         (ulong) buf_len) == ERR) {
+        return (scsiq->r3.done_stat = QD_WITH_ERROR);
     }
-    ASC_DBG1(1, "AscInitPollTarget: dvc_found %d\n", dvc_found);
-    return (dvc_found);
+    scsiq->cdb[0] = (uchar) SCSICMD_Inquiry;
+    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
+    scsiq->cdb[2] = 0;
+    scsiq->cdb[3] = 0;
+    scsiq->cdb[4] = buf_len;
+    scsiq->cdb[5] = 0;
+    scsiq->r2.cdb_len = 6;
+    return (0);
 }
 
 STATIC int
-PollQueueDone(
-                 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                 REG ASC_SCSI_REQ_Q * scsiq,
-                 int timeout_sec
+AscScsiReadCapacity(
+                       REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                       REG ASC_SCSI_REQ_Q * scsiq,
+                       uchar * info
 )
 {
-    int                 status;
-    int                 retry = 0;
+    if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) {
+        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    }
+    scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity;
+    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
+    scsiq->cdb[2] = 0;
+    scsiq->cdb[3] = 0;
+    scsiq->cdb[4] = 0;
+    scsiq->cdb[5] = 0;
+    scsiq->cdb[6] = 0;
+    scsiq->cdb[7] = 0;
+    scsiq->cdb[8] = 0;
+    scsiq->cdb[9] = 0;
+    scsiq->r2.cdb_len = 10;
+    return (0);
+}
 
-    ASC_DBG1(1, "PollQueueDone: timeout_sec %d\n", timeout_sec);
-    do {
-        ASC_DBG(1, "PollQueueDone: before AscExeScsiQueue\n");
-        if ((status = AscExeScsiQueue(asc_dvc,
-                (ASC_SCSI_Q *) scsiq)) == 1) {
-            ASC_DBG(1, "PollQueueDone: before AscPollQDone\n");
-            if ((status = AscPollQDone(asc_dvc, scsiq,
-                                       timeout_sec)) != 1) {
-                ASC_DBG1(1, "PollQueueDone: status %x\n", status);
-                if (status == 0x80) {
-                    if (retry++ > ASC_MAX_INIT_BUSY_RETRY) {
-                        break;
-                    }
-                    scsiq->r3.done_stat = 0;
-                    scsiq->r3.host_stat = 0;
-                    scsiq->r3.scsi_stat = 0;
-                    scsiq->r3.scsi_msg = 0;
-                    DvcSleepMilliSecond(2000);
-                    continue;
-                }
-                scsiq->r3.done_stat = 0;
-                scsiq->r3.host_stat = 0;
-                scsiq->r3.scsi_stat = 0;
-                scsiq->r3.scsi_msg = 0;
-                ASC_DBG(1, "PollQueueDone: before AscAbortSRB()\n");
-                AscAbortSRB(asc_dvc, (ulong) scsiq);
-            }
-            ASC_DBG1(1, "PollQueueDone: status %x\n", status);
-            ASC_DBG1(1, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
-            return (scsiq->r3.done_stat);
-        }
-        ASC_DBG1(1, "PollQueueDone: status %x\n", status);
-        DvcSleepMilliSecond(5);
-    } while (((status == 0) || (status == 0x80)) &&
-              retry++ < ASC_MAX_INIT_BUSY_RETRY);
-    ASC_DBG1(1, "PollQueueDone: status %x\n", status);
-    ASC_DBG(1, "PollQueueDone: done_stat QD_WITH_ERROR\n");
-    return (scsiq->r3.done_stat = QD_WITH_ERROR);
+STATIC int
+AscScsiTestUnitReady(
+                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                        REG ASC_SCSI_REQ_Q * scsiq
+)
+{
+    if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR,
+                         (ulong) 0L) == ERR) {
+        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    }
+    scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
+    scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady;
+    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
+    scsiq->cdb[2] = 0;
+    scsiq->cdb[3] = 0;
+    scsiq->cdb[4] = 0;
+    scsiq->cdb[5] = 0;
+    scsiq->r2.cdb_len = 6;
+    return (0);
 }
 
 STATIC int
-PollScsiInquiry(
-                   REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                   REG ASC_SCSI_REQ_Q * scsiq,
-                   uchar * buf,
-                   int buf_len
+AscScsiStartStopUnit(
+                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                        REG ASC_SCSI_REQ_Q * scsiq,
+                        uchar op_mode
 )
 {
-    if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) {
+    if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) {
         return (scsiq->r3.done_stat = QD_WITH_ERROR);
     }
-    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 4));
-}
+    scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
+    scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit;
+    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
+    scsiq->cdb[2] = 0;
+    scsiq->cdb[3] = 0;
+    scsiq->cdb[4] = op_mode;
+    scsiq->cdb[5] = 0;
+    scsiq->r2.cdb_len = 6;
+    return (0);
+}
+
+
+/*
+ * --- Adv Library Functions
+ */
+
+/* a_qswap.h */
+STATIC unsigned char _adv_mcode_buf[] ASC_INITDATA = {
+  0x9C,  0xF0,  0x80,  0x01,  0x00,  0xF0,  0x40,  0x0A,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x72,  0x01,  0xD2,  0x11,  0x00,  0x00,  0x70,  0x01,
+  0x30,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x88,  0x0F,  0x22,  0x03,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x48,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x78,  0x56,  0x34,  0x12,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x04,  0xF7,  0x70,  0x01,  0x0C,  0x1C,  0x06,  0xF7,  0x02,  0x00,  0x00,  0xF2,  0xD2,  0x0A,
+  0x04,  0xF7,  0x70,  0x01,  0x06,  0xF7,  0x02,  0x00,  0x3E,  0x57,  0x3C,  0x56,  0x0C,  0x1C,  0x00,  0xFC,
+  0xA6,  0x00,  0x01,  0x58,  0xAA,  0x13,  0x20,  0xF0,  0x9A,  0x03,  0x06,  0xEC,  0xB9,  0x00,  0x0E,  0x47,
+  0x03,  0xE6,  0x10,  0x00,  0xCE,  0x45,  0x02,  0x13,  0x3E,  0x57,  0x06,  0xEA,  0xB9,  0x00,  0x47,  0x4B,
+  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x01,  0x48,  0x4E,  0x12,  0x03,  0xF6,  0xC0,  0x00,
+  0x00,  0xF2,  0x64,  0x0A,  0x41,  0x58,  0x03,  0xF6,  0xD0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x49,  0x44,
+  0x59,  0xF0,  0x0A,  0x02,  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x44,  0x58,  0x00,  0xF2,
+  0xDE,  0x0D,  0x02,  0xCC,  0x4A,  0xE4,  0x01,  0x00,  0x55,  0xF0,  0x08,  0x03,  0x45,  0xF4,  0x02,  0x00,
+  0x83,  0x5A,  0x04,  0xCC,  0x01,  0x4A,  0x12,  0x12,  0x00,  0xF2,  0xDE,  0x0D,  0x00,  0xCD,  0x48,  0xE4,
+  0x01,  0x00,  0xE9,  0x13,  0x00,  0xF2,  0xC2,  0x0F,  0xFA,  0x10,  0x0E,  0x47,  0x03,  0xE6,  0x10,  0x00,
+  0xCE,  0x45,  0x02,  0x13,  0x3E,  0x57,  0xCE,  0x47,  0x97,  0x13,  0x04,  0xEC,  0xB4,  0x00,  0x00,  0xF2,
+  0xDE,  0x0D,  0x00,  0xCD,  0x48,  0xE4,  0x00,  0x00,  0x12,  0x12,  0x3E,  0x57,  0x06,  0xCC,  0x45,  0xF4,
+  0x02,  0x00,  0x83,  0x5A,  0x00,  0xCC,  0x00,  0xEA,  0xB4,  0x00,  0x92,  0x10,  0x00,  0xF0,  0x8C,  0x01,
+  0x43,  0xF0,  0x5C,  0x02,  0x44,  0xF0,  0x60,  0x02,  0x45,  0xF0,  0x64,  0x02,  0x46,  0xF0,  0x68,  0x02,
+  0x47,  0xF0,  0x6E,  0x02,  0x48,  0xF0,  0x9E,  0x02,  0xB9,  0x54,  0x62,  0x10,  0x00,  0x1C,  0x5A,  0x10,
+  0x02,  0x1C,  0x56,  0x10,  0x1E,  0x1C,  0x52,  0x10,  0x00,  0xF2,  0x1A,  0x11,  0x50,  0x10,  0x06,  0xFC,
+  0xA8,  0x00,  0x03,  0xF6,  0xBE,  0x00,  0x00,  0xF2,  0x4A,  0x0A,  0x8C,  0x10,  0x01,  0xF6,  0x01,  0x00,
+  0x01,  0xFA,  0xA8,  0x00,  0x00,  0xF2,  0x28,  0x0B,  0x06,  0x10,  0xB9,  0x54,  0x01,  0xFA,  0xA8,  0x00,
+  0x03,  0xF6,  0xBE,  0x00,  0x00,  0xF2,  0x54,  0x0A,  0x01,  0xFC,  0xA8,  0x00,  0x20,  0x10,  0x58,  0x1C,
+  0x00,  0xF2,  0x18,  0x0B,  0x5A,  0x1C,  0x01,  0xF6,  0x01,  0x00,  0x38,  0x54,  0x00,  0xFA,  0xA6,  0x00,
+  0x01,  0xFA,  0xA8,  0x00,  0x20,  0x1C,  0x00,  0xF0,  0x72,  0x01,  0x01,  0xF6,  0x01,  0x00,  0x38,  0x54,
+  0x00,  0xFA,  0xA6,  0x00,  0x01,  0xFA,  0xA8,  0x00,  0x20,  0x1C,  0x00,  0xF0,  0x80,  0x01,  0x03,  0xF6,
+  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x01,  0x48,  0x0A,  0x13,  0x00,  0xF2,  0x34,  0x10,  0x00,  0xF2,
+  0x50,  0x0F,  0x24,  0x10,  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x02,  0xF6,  0xD0,  0x00,
+  0x02,  0x57,  0x03,  0x59,  0x01,  0xCC,  0x49,  0x44,  0x5B,  0xF0,  0x04,  0x03,  0x00,  0xF2,  0x98,  0x0F,
+  0x00,  0xF0,  0x80,  0x01,  0x00,  0xF2,  0x10,  0x10,  0x0C,  0x1C,  0x02,  0x4B,  0xBF,  0x57,  0x9E,  0x43,
+  0x77,  0x57,  0x07,  0x4B,  0x20,  0xF0,  0x9A,  0x03,  0x40,  0x1C,  0x1E,  0xF0,  0x30,  0x03,  0x26,  0xF0,
+  0x2C,  0x03,  0xA0,  0xF0,  0x1A,  0x03,  0x11,  0xF0,  0x9A,  0x03,  0x12,  0x10,  0x9F,  0xF0,  0x3E,  0x03,
+  0x46,  0x1C,  0x82,  0xE7,  0x05,  0x00,  0x9E,  0xE7,  0x11,  0x00,  0x00,  0xF0,  0x02,  0x0A,  0x0C,  0x1C,
+  0x48,  0x1C,  0x46,  0x1C,  0x38,  0x54,  0x00,  0xEC,  0xBA,  0x00,  0x08,  0x44,  0x00,  0xEA,  0xBA,  0x00,
+  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x08,  0x44,  0x00,  0x4C,  0x82,  0xE7,  0x02,  0x00,
+  0x00,  0xF2,  0x0E,  0x11,  0x00,  0xF2,  0x0E,  0x11,  0x06,  0xF0,  0x74,  0x03,  0x1E,  0xF0,  0xF8,  0x09,
+  0x00,  0xF0,  0xFE,  0x09,  0x00,  0xFC,  0xBE,  0x00,  0x98,  0x57,  0x55,  0xF0,  0xA0,  0x04,  0x01,  0xE6,
+  0x0C,  0x00,  0x00,  0xF2,  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,
+  0xC4,  0x11,  0x01,  0xF0,  0x7C,  0x02,  0x00,  0xF0,  0x8A,  0x02,  0x46,  0x1C,  0x0C,  0x1C,  0x67,  0x1B,
+  0xBF,  0x57,  0x77,  0x57,  0x02,  0x4B,  0x48,  0x1C,  0x32,  0x1C,  0x00,  0xF2,  0x8E,  0x0D,  0x30,  0x1C,
+  0x96,  0xF0,  0xB0,  0x03,  0xB1,  0xF0,  0xB4,  0x03,  0x1E,  0xF0,  0xF8,  0x09,  0x85,  0xF0,  0xFE,  0x09,
+  0x00,  0xFC,  0xBE,  0x00,  0x98,  0x57,  0x14,  0x12,  0x01,  0xE6,  0x0C,  0x00,  0x00,  0xF2,  0x4A,  0x0D,
+  0x00,  0xF2,  0x0E,  0x11,  0x01,  0xF0,  0x7C,  0x02,  0x00,  0xF0,  0x8A,  0x02,  0x03,  0xF6,  0xE0,  0x00,
+  0x00,  0xF2,  0x64,  0x0A,  0x01,  0x48,  0x55,  0xF0,  0x8C,  0x04,  0x03,  0x82,  0x03,  0xFC,  0xA0,  0x00,
+  0x9B,  0x57,  0x40,  0x12,  0x69,  0x18,  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,  0x36,  0x04,  0x69,  0x08,
+  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,  0xFE,  0x09,  0x68,  0x08,  0x4C,  0x44,  0x28,  0x12,  0x44,  0x48,
+  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x45,  0x58,  0x00,  0xF2,  0xF2,  0x0D,  0x00,  0xCC,
+  0x01,  0x48,  0x55,  0xF0,  0x8C,  0x04,  0x4C,  0x44,  0xEF,  0x13,  0x00,  0xF2,  0xC2,  0x0F,  0x00,  0xF2,
+  0x10,  0x10,  0x08,  0x10,  0x68,  0x18,  0x45,  0x5A,  0x00,  0xF2,  0xF2,  0x0D,  0x04,  0x80,  0x18,  0xE4,
+  0x10,  0x00,  0x28,  0x12,  0x01,  0xE6,  0x06,  0x00,  0x04,  0x80,  0x18,  0xE4,  0x01,  0x00,  0x04,  0x12,
+  0x01,  0xE6,  0x0D,  0x00,  0x00,  0xF2,  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,  0x04,  0xE6,  0x02,  0x00,
+  0x9E,  0xE7,  0x15,  0x00,  0x01,  0xF0,  0x18,  0x0A,  0x00,  0xF0,  0xFE,  0x09,  0x69,  0x08,  0x05,  0x80,
+  0x48,  0xE4,  0x00,  0x00,  0x0C,  0x12,  0x00,  0xE6,  0x11,  0x00,  0x00,  0xEA,  0xB8,  0x00,  0x00,  0xF2,
+  0xB2,  0x10,  0x82,  0xE7,  0x02,  0x00,  0x1C,  0x90,  0x40,  0x5C,  0x00,  0x16,  0x01,  0xE6,  0x06,  0x00,
+  0x00,  0xF2,  0x4A,  0x0D,  0x01,  0xF0,  0x80,  0x01,  0x1E,  0xF0,  0x80,  0x01,  0x00,  0xF0,  0x94,  0x04,
+  0x42,  0x5B,  0x06,  0xF7,  0x03,  0x00,  0x46,  0x59,  0xBF,  0x57,  0x77,  0x57,  0x01,  0xE6,  0x80,  0x00,
+  0x07,  0x80,  0x31,  0x44,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x5E,  0x13,  0x20,  0x80,  0x48,  0xE4,
+  0x03,  0x00,  0x56,  0x12,  0x04,  0x80,  0x18,  0xE4,  0x02,  0x00,  0x4C,  0x13,  0x00,  0xFC,  0xA2,  0x00,
+  0x98,  0x57,  0x55,  0xF0,  0x18,  0x05,  0x31,  0xE4,  0x40,  0x00,  0x00,  0xFC,  0xA0,  0x00,  0x98,  0x57,
+  0x36,  0x12,  0x4C,  0x1C,  0x00,  0xF2,  0x0E,  0x11,  0x89,  0x48,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,
+  0x2A,  0x05,  0x82,  0xE7,  0x06,  0x00,  0x1B,  0x80,  0x48,  0xE4,  0x22,  0x00,  0x5B,  0xF0,  0x08,  0x05,
+  0x48,  0xE4,  0x20,  0x00,  0x59,  0xF0,  0x0C,  0x05,  0x00,  0xE6,  0x20,  0x00,  0x09,  0x48,  0x00,  0xF2,
+  0x0E,  0x11,  0x86,  0xF0,  0x2A,  0x05,  0x83,  0x80,  0x04,  0x10,  0x00,  0xF2,  0x9E,  0x0D,  0x00,  0xE6,
+  0x01,  0x00,  0x00,  0xEA,  0x26,  0x01,  0x01,  0xEA,  0x27,  0x01,  0x04,  0x80,  0x18,  0xE4,  0x10,  0x00,
+  0x36,  0x12,  0xB9,  0x54,  0x00,  0xF2,  0xF2,  0x0E,  0x01,  0xE6,  0x06,  0x00,  0x04,  0x80,  0x18,  0xE4,
+  0x01,  0x00,  0x04,  0x12,  0x01,  0xE6,  0x0D,  0x00,  0x00,  0xF2,  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,
+  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,  0xC4,  0x11,  0x04,  0xE6,  0x02,  0x00,  0x9E,  0xE7,  0x15,  0x00,
+  0x01,  0xF0,  0x18,  0x0A,  0x00,  0xF0,  0xFE,  0x09,  0x00,  0xFC,  0x20,  0x01,  0x98,  0x57,  0x34,  0x12,
+  0x00,  0xFC,  0x24,  0x01,  0x98,  0x57,  0x2C,  0x13,  0xB9,  0x54,  0x00,  0xF2,  0xF2,  0x0E,  0x86,  0xF0,
+  0xA4,  0x05,  0x03,  0xF6,  0x01,  0x00,  0x00,  0xF2,  0x88,  0x0E,  0x85,  0xF0,  0x9A,  0x05,  0x82,  0xE7,
+  0x03,  0x00,  0x00,  0xF2,  0x5C,  0x0B,  0x82,  0xE7,  0x02,  0x00,  0x00,  0xFC,  0x24,  0x01,  0xB0,  0x57,
+  0x00,  0xFA,  0x24,  0x01,  0x00,  0xFC,  0x9E,  0x00,  0x98,  0x57,  0x5A,  0x12,  0x00,  0xFC,  0xB6,  0x00,
+  0x98,  0x57,  0x52,  0x13,  0x03,  0xE6,  0x0C,  0x00,  0x00,  0xFC,  0x9C,  0x00,  0x98,  0x57,  0x04,  0x13,
+  0x03,  0xE6,  0x19,  0x00,  0x05,  0xE6,  0x08,  0x00,  0x00,  0xF6,  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,
+  0x03,  0x58,  0x00,  0xDC,  0x18,  0xF4,  0x00,  0x80,  0x04,  0x13,  0x05,  0xE6,  0x0F,  0x00,  0xB9,  0x54,
+  0x00,  0xF2,  0xF2,  0x0E,  0x86,  0xF0,  0x06,  0x06,  0x00,  0xF2,  0xB6,  0x0E,  0x85,  0xF0,  0xFC,  0x05,
+  0x82,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x5C,  0x0B,  0x82,  0xE7,  0x02,  0x00,  0x00,  0xFC,  0xB6,  0x00,
+  0xB0,  0x57,  0x00,  0xFA,  0xB6,  0x00,  0x01,  0xF6,  0x01,  0x00,  0x00,  0xF2,  0xF2,  0x0E,  0x9C,  0x32,
+  0x4E,  0x1C,  0x32,  0x1C,  0x00,  0xF2,  0x8E,  0x0D,  0x30,  0x1C,  0x82,  0xE7,  0x04,  0x00,  0xB1,  0xF0,
+  0x1E,  0x06,  0x0A,  0xF0,  0x3A,  0x06,  0x05,  0xF0,  0xD2,  0x06,  0x06,  0xF0,  0xD8,  0x06,  0x09,  0xF0,
+  0x20,  0x09,  0x1E,  0xF0,  0xF8,  0x09,  0x00,  0xF0,  0xFE,  0x09,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,
+  0x30,  0x12,  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x21,  0x80,  0x18,  0xE4,  0xE0,  0x00,
+  0x09,  0x48,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,
+  0x00,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x99,  0xA4,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,  0x00,  0x00,
+  0x9A,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x02,  0x00,  0x34,  0x12,  0x09,  0xE7,  0x1B,  0x00,  0x00,  0xF2,
+  0x0E,  0x11,  0x21,  0x80,  0x18,  0xE4,  0xE0,  0x00,  0x09,  0x48,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,
+  0x00,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,
+  0x01,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF0,  0x08,  0x09,  0xBB,  0x55,
+  0x9A,  0x81,  0x03,  0xF7,  0x20,  0x00,  0x09,  0x6F,  0x93,  0x45,  0x55,  0xF0,  0xDE,  0x06,  0xB1,  0xF0,
+  0xBE,  0x06,  0x0A,  0xF0,  0xB6,  0x06,  0x09,  0xF0,  0x20,  0x09,  0x1E,  0xF0,  0xF8,  0x09,  0x00,  0xF0,
+  0xFE,  0x09,  0x00,  0xF2,  0x5C,  0x0B,  0x47,  0x10,  0x09,  0xE7,  0x08,  0x00,  0x41,  0x10,  0x05,  0x80,
+  0x48,  0xE4,  0x00,  0x00,  0x1E,  0x12,  0x00,  0xE6,  0x11,  0x00,  0x00,  0xEA,  0xB8,  0x00,  0x00,  0xF2,
+  0xB2,  0x10,  0x2C,  0x90,  0xAE,  0x90,  0x08,  0x50,  0x8A,  0x50,  0x38,  0x54,  0x1F,  0x40,  0x00,  0xF2,
+  0xB0,  0x0D,  0x08,  0x10,  0x08,  0x90,  0x8A,  0x90,  0x30,  0x50,  0xB2,  0x50,  0x9C,  0x32,  0x0C,  0x92,
+  0x8E,  0x92,  0x38,  0x54,  0x04,  0x80,  0x30,  0xE4,  0x08,  0x00,  0x04,  0x40,  0x0C,  0x1C,  0x00,  0xF6,
+  0x03,  0x00,  0xB1,  0xF0,  0x22,  0x07,  0x9E,  0xF0,  0x36,  0x07,  0x01,  0x48,  0x55,  0xF0,  0xF8,  0x09,
+  0x0C,  0x1C,  0x10,  0x44,  0xED,  0x10,  0x0B,  0xF0,  0x5A,  0x07,  0x0C,  0xF0,  0x5E,  0x07,  0x05,  0xF0,
+  0x4E,  0x07,  0x06,  0xF0,  0x54,  0x07,  0x09,  0xF0,  0x20,  0x09,  0x00,  0xF0,  0xFE,  0x09,  0x00,  0xF2,
+  0x5C,  0x0B,  0xCF,  0x10,  0x09,  0xE7,  0x08,  0x00,  0xC9,  0x10,  0x2E,  0x1C,  0x02,  0x10,  0x2C,  0x1C,
+  0xAA,  0xF0,  0x60,  0x07,  0xAC,  0xF0,  0x6E,  0x07,  0x40,  0x10,  0x34,  0x1C,  0xF3,  0x10,  0xAD,  0xF0,
+  0x78,  0x07,  0xC8,  0x10,  0x36,  0x1C,  0xE9,  0x10,  0x2B,  0xF0,  0x7E,  0x08,  0x6B,  0x18,  0x18,  0xF4,
+  0x00,  0xFE,  0x20,  0x12,  0x01,  0x58,  0xD2,  0xF0,  0x7E,  0x08,  0x76,  0x18,  0x18,  0xF4,  0x03,  0x00,
+  0xEC,  0x12,  0x00,  0xFC,  0x22,  0x01,  0x18,  0xF4,  0x01,  0x00,  0xE2,  0x12,  0x0B,  0xF0,  0x60,  0x07,
+  0x0C,  0xF0,  0x60,  0x07,  0x36,  0x1C,  0x34,  0x1C,  0xB7,  0x10,  0x38,  0x54,  0xB9,  0x54,  0x84,  0x80,
+  0x19,  0xE4,  0x20,  0x00,  0xB2,  0x13,  0x85,  0x80,  0x81,  0x48,  0x66,  0x12,  0x04,  0x80,  0x18,  0xE4,
+  0x08,  0x00,  0x58,  0x13,  0x1F,  0x80,  0x08,  0x44,  0xC8,  0x44,  0x9F,  0x12,  0x1F,  0x40,  0x34,  0x91,
+  0xB6,  0x91,  0x44,  0x55,  0xE5,  0x55,  0x02,  0xEC,  0xB8,  0x00,  0x02,  0x49,  0xBB,  0x55,  0x82,  0x81,
+  0xC0,  0x55,  0x48,  0xF4,  0x0F,  0x00,  0x5A,  0xF0,  0x16,  0x08,  0x4A,  0xE4,  0x17,  0x00,  0xD5,  0xF0,
+  0xF6,  0x07,  0x02,  0xF6,  0x0F,  0x00,  0x02,  0xF4,  0x02,  0x00,  0x02,  0xEA,  0xB8,  0x00,  0x04,  0x91,
+  0x86,  0x91,  0x02,  0x4B,  0x2C,  0x90,  0x08,  0x50,  0x2E,  0x90,  0x0A,  0x50,  0x2C,  0x51,  0xAE,  0x51,
+  0x00,  0xF2,  0xB2,  0x10,  0x38,  0x54,  0x00,  0xF2,  0xB0,  0x0D,  0x56,  0x10,  0x34,  0x91,  0xB6,  0x91,
+  0x0C,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x08,  0x00,  0x41,  0x12,  0x0C,  0x91,  0x8E,  0x91,  0x04,  0x80,
+  0x18,  0xE4,  0xF7,  0x00,  0x04,  0x40,  0x30,  0x90,  0xB2,  0x90,  0x36,  0x10,  0x02,  0x80,  0x48,  0xE4,
+  0x10,  0x00,  0x31,  0x12,  0x82,  0xE7,  0x10,  0x00,  0x84,  0x80,  0x19,  0xE4,  0x20,  0x00,  0x10,  0x13,
+  0x0C,  0x90,  0x8E,  0x90,  0x5D,  0xF0,  0x74,  0x07,  0x0C,  0x58,  0x8D,  0x58,  0x00,  0xF0,  0x60,  0x07,
+  0x38,  0x54,  0xB9,  0x54,  0x19,  0x80,  0xF1,  0x10,  0x3A,  0x55,  0x19,  0x81,  0xBB,  0x55,  0x10,  0x90,
+  0x92,  0x90,  0x10,  0x58,  0x91,  0x58,  0x14,  0x59,  0x95,  0x59,  0x00,  0xF0,  0x60,  0x07,  0x04,  0x80,
+  0x18,  0xE4,  0x20,  0x00,  0x06,  0x12,  0x6C,  0x19,  0x19,  0x41,  0x7C,  0x10,  0x6C,  0x19,  0x0C,  0x51,
+  0xED,  0x19,  0x8E,  0x51,  0x6B,  0x18,  0x18,  0xF4,  0x00,  0xFF,  0x02,  0x13,  0x6A,  0x10,  0x01,  0x58,
+  0xD2,  0xF0,  0xBC,  0x08,  0x76,  0x18,  0x18,  0xF4,  0x03,  0x00,  0x0A,  0x12,  0x00,  0xFC,  0x22,  0x01,
+  0x18,  0xF4,  0x01,  0x00,  0x06,  0x13,  0x9E,  0xE7,  0x16,  0x00,  0x4C,  0x10,  0xD1,  0xF0,  0xC6,  0x08,
+  0x9E,  0xE7,  0x17,  0x00,  0x42,  0x10,  0xD0,  0xF0,  0xD0,  0x08,  0x9E,  0xE7,  0x19,  0x00,  0x38,  0x10,
+  0xCF,  0xF0,  0xDA,  0x08,  0x9E,  0xE7,  0x20,  0x00,  0x2E,  0x10,  0xCE,  0xF0,  0xE4,  0x08,  0x9E,  0xE7,
+  0x21,  0x00,  0x24,  0x10,  0xCD,  0xF0,  0xEE,  0x08,  0x9E,  0xE7,  0x22,  0x00,  0x1A,  0x10,  0xCC,  0xF0,
+  0x00,  0x09,  0x84,  0x80,  0x19,  0xE4,  0x04,  0x00,  0x06,  0x12,  0x9E,  0xE7,  0x12,  0x00,  0x08,  0x10,
+  0xCB,  0xF0,  0x08,  0x09,  0x9E,  0xE7,  0x24,  0x00,  0xB1,  0xF0,  0x08,  0x09,  0x05,  0xF0,  0x1A,  0x09,
+  0x09,  0xF0,  0x20,  0x09,  0x1E,  0xF0,  0xF8,  0x09,  0xE4,  0x10,  0x00,  0xF2,  0x5C,  0x0B,  0xE9,  0x10,
+  0x9C,  0x32,  0x82,  0xE7,  0x20,  0x00,  0x32,  0x1C,  0xE9,  0x09,  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,
+  0xFE,  0x09,  0x69,  0x08,  0x01,  0xF0,  0x40,  0x09,  0x1E,  0xF0,  0xF8,  0x09,  0x00,  0xF0,  0x34,  0x09,
+  0x30,  0x44,  0x06,  0x12,  0x9E,  0xE7,  0x42,  0x00,  0xB8,  0x10,  0x04,  0xF6,  0x01,  0x00,  0xB3,  0x45,
+  0x74,  0x12,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x22,  0x13,  0x4B,  0xE4,  0x02,  0x00,  0x36,  0x12,
+  0x4B,  0xE4,  0x28,  0x00,  0xAC,  0x13,  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,  0xC4,  0x11,  0x03,  0xF6,
+  0xD0,  0x00,  0xFA,  0x14,  0x82,  0xE7,  0x01,  0x00,  0x00,  0xF0,  0x80,  0x01,  0x9E,  0xE7,  0x44,  0x00,
+  0x4B,  0xE4,  0x02,  0x00,  0x06,  0x12,  0x03,  0xE6,  0x02,  0x00,  0x76,  0x10,  0x00,  0xF2,  0x9E,  0x0D,
+  0x03,  0xE6,  0x02,  0x00,  0x6C,  0x10,  0x00,  0xF2,  0x9E,  0x0D,  0x19,  0x82,  0x34,  0x46,  0x0A,  0x13,
+  0x03,  0xE6,  0x02,  0x00,  0x9E,  0xE7,  0x43,  0x00,  0x68,  0x10,  0x04,  0x80,  0x30,  0xE4,  0x20,  0x00,
+  0x04,  0x40,  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,  0xC4,  0x11,  0x82,  0xE7,  0x01,  0x00,  0x06,  0xF7,
+  0x02,  0x00,  0x00,  0xF0,  0x08,  0x03,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x06,  0x12,  0x03,  0xE6,
+  0x02,  0x00,  0x3E,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x02,  0x00,  0x3A,  0x12,  0x04,  0x80,  0x18,  0xE4,
+  0xFD,  0x00,  0x04,  0x40,  0x1C,  0x1C,  0x9D,  0xF0,  0xE6,  0x09,  0x1C,  0x1C,  0x9D,  0xF0,  0xEC,  0x09,
+  0xC1,  0x10,  0x9E,  0xE7,  0x13,  0x00,  0x0A,  0x10,  0x9E,  0xE7,  0x41,  0x00,  0x04,  0x10,  0x9E,  0xE7,
+  0x24,  0x00,  0x00,  0xFC,  0xBE,  0x00,  0x98,  0x57,  0xD5,  0xF0,  0x8A,  0x02,  0x04,  0xE6,  0x04,  0x00,
+  0x06,  0x10,  0x04,  0xE6,  0x04,  0x00,  0x9D,  0x41,  0x1C,  0x42,  0x9F,  0xE7,  0x00,  0x00,  0x06,  0xF7,
+  0x02,  0x00,  0x03,  0xF6,  0xE0,  0x00,  0x3C,  0x14,  0x44,  0x58,  0x45,  0x58,  0x00,  0xF2,  0xF2,  0x0D,
+  0x00,  0xF2,  0x7A,  0x10,  0x00,  0xF2,  0xC2,  0x0F,  0x3C,  0x14,  0x1E,  0x1C,  0x00,  0xF0,  0x80,  0x01,
+  0x12,  0x1C,  0x22,  0x1C,  0xD2,  0x14,  0x00,  0xF0,  0x72,  0x01,  0x83,  0x59,  0x03,  0xDC,  0x73,  0x57,
+  0x80,  0x5D,  0x00,  0x16,  0x83,  0x59,  0x03,  0xDC,  0x38,  0x54,  0x70,  0x57,  0x33,  0x54,  0x3B,  0x54,
+  0x80,  0x5D,  0x00,  0x16,  0x03,  0x57,  0x83,  0x59,  0x38,  0x54,  0x00,  0xCC,  0x00,  0x16,  0x03,  0x57,
+  0x83,  0x59,  0x00,  0x4C,  0x00,  0x16,  0x02,  0x80,  0x48,  0xE4,  0x01,  0x00,  0x0E,  0x12,  0x48,  0xE4,
+  0x05,  0x00,  0x08,  0x12,  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,  0xC4,  0x11,  0xC1,  0x5A,  0x3A,  0x55,
+  0x02,  0xEC,  0xB5,  0x00,  0x45,  0x59,  0x00,  0xF2,  0xF2,  0x0D,  0x83,  0x58,  0x30,  0xE7,  0x00,  0x00,
+  0x10,  0x4D,  0x30,  0xE7,  0x40,  0x00,  0x10,  0x4F,  0x38,  0x90,  0xBA,  0x90,  0x10,  0x5C,  0x80,  0x5C,
+  0x83,  0x5A,  0x10,  0x4E,  0x04,  0xEA,  0xB5,  0x00,  0x43,  0x5B,  0x03,  0xF4,  0xE0,  0x00,  0x83,  0x59,
+  0x04,  0xCC,  0x01,  0x4A,  0x0A,  0x12,  0x45,  0x5A,  0x00,  0xF2,  0xF2,  0x0D,  0x00,  0xF2,  0x34,  0x10,
+  0x00,  0x16,  0x08,  0x1C,  0x00,  0xFC,  0xAC,  0x00,  0x06,  0x58,  0x67,  0x18,  0x18,  0xF4,  0x8F,  0xE1,
+  0x01,  0xFC,  0xAE,  0x00,  0x19,  0xF4,  0x70,  0x1E,  0xB0,  0x54,  0x07,  0x58,  0x00,  0xFC,  0xB0,  0x00,
+  0x08,  0x58,  0x00,  0xFC,  0xB2,  0x00,  0x09,  0x58,  0x0A,  0x1C,  0x00,  0xE6,  0x0F,  0x00,  0x00,  0xEA,
+  0xB9,  0x00,  0x38,  0x54,  0x00,  0xFA,  0x24,  0x01,  0x00,  0xFA,  0xB6,  0x00,  0x18,  0x1C,  0x14,  0x1C,
+  0x10,  0x1C,  0x32,  0x1C,  0x12,  0x1C,  0x00,  0x16,  0x3E,  0x57,  0x0C,  0x14,  0x0E,  0x47,  0x07,  0xE6,
+  0x10,  0x00,  0xCE,  0x47,  0xF5,  0x13,  0x00,  0x16,  0x00,  0xF2,  0x9E,  0x0D,  0x02,  0x4B,  0x03,  0xF6,
+  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x01,  0x48,  0x20,  0x12,  0x44,  0x58,  0x45,  0x58,  0x9E,  0xE7,
+  0x15,  0x00,  0x9C,  0xE7,  0x04,  0x00,  0x00,  0xF2,  0xF2,  0x0D,  0x00,  0xF2,  0x7A,  0x10,  0x00,  0xF2,
+  0xC2,  0x0F,  0x00,  0xF2,  0x76,  0x0A,  0x1E,  0x1C,  0xD5,  0x10,  0x00,  0x16,  0x69,  0x08,  0x48,  0xE4,
+  0x04,  0x00,  0x64,  0x12,  0x48,  0xE4,  0x02,  0x00,  0x20,  0x12,  0x48,  0xE4,  0x03,  0x00,  0x1A,  0x12,
+  0x48,  0xE4,  0x08,  0x00,  0x14,  0x12,  0x48,  0xE4,  0x01,  0x00,  0xF0,  0x12,  0x48,  0xE4,  0x07,  0x00,
+  0x12,  0x12,  0x01,  0xE6,  0x07,  0x00,  0x00,  0xF2,  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,  0x05,  0xF0,
+  0x5C,  0x0B,  0x00,  0x16,  0x00,  0xE6,  0x01,  0x00,  0x00,  0xEA,  0x99,  0x00,  0x02,  0x80,  0x48,  0xE4,
+  0x03,  0x00,  0xB9,  0x12,  0x48,  0xE4,  0x06,  0x00,  0xB3,  0x12,  0x01,  0xE6,  0x06,  0x00,  0x00,  0xF2,
+  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,  0x04,  0xE6,  0x02,  0x00,  0x9E,  0xE7,  0x15,  0x00,  0x01,  0xF0,
+  0x18,  0x0A,  0x00,  0xF0,  0xFE,  0x09,  0x00,  0x16,  0x02,  0x80,  0x48,  0xE4,  0x10,  0x00,  0x1C,  0x12,
+  0x82,  0xE7,  0x08,  0x00,  0x3C,  0x56,  0x03,  0x82,  0x00,  0xF2,  0xDE,  0x0D,  0x30,  0xE7,  0x08,  0x00,
+  0x04,  0xF7,  0x70,  0x01,  0x06,  0xF7,  0x02,  0x00,  0x00,  0xF0,  0x80,  0x01,  0x6C,  0x19,  0xED,  0x19,
+  0x5D,  0xF0,  0xD0,  0x0B,  0x44,  0x55,  0xE5,  0x55,  0x59,  0xF0,  0x4E,  0x0C,  0x04,  0x55,  0xA5,  0x55,
+  0x1F,  0x80,  0x01,  0xEC,  0xB8,  0x00,  0x82,  0x48,  0x82,  0x80,  0x49,  0x44,  0x2E,  0x13,  0x01,  0xEC,
+  0xB8,  0x00,  0x41,  0xE4,  0x02,  0x00,  0x01,  0xEA,  0xB8,  0x00,  0x49,  0xE4,  0x11,  0x00,  0x59,  0xF0,
+  0x2A,  0x0C,  0x01,  0xE6,  0x17,  0x00,  0x01,  0xEA,  0xB8,  0x00,  0x02,  0x4B,  0x88,  0x90,  0xAC,  0x50,
+  0x8A,  0x90,  0xAE,  0x50,  0x01,  0xEC,  0xB8,  0x00,  0x82,  0x48,  0x82,  0x80,  0x10,  0x44,  0x02,  0x4B,
+  0x1F,  0x40,  0xC0,  0x44,  0x00,  0xF2,  0xB0,  0x0D,  0x04,  0x55,  0xA5,  0x55,  0x9F,  0x10,  0x0C,  0x51,
+  0x8E,  0x51,  0x30,  0x90,  0xB2,  0x90,  0x00,  0x56,  0xA1,  0x56,  0x30,  0x50,  0xB2,  0x50,  0x34,  0x90,
+  0xB6,  0x90,  0x40,  0x56,  0xE1,  0x56,  0x34,  0x50,  0xB6,  0x50,  0x65,  0x10,  0xB1,  0xF0,  0x6C,  0x0C,
+  0x85,  0xF0,  0xC6,  0x0B,  0xE9,  0x09,  0x4B,  0xE4,  0x03,  0x00,  0x78,  0x12,  0x4B,  0xE4,  0x02,  0x00,
+  0x01,  0x13,  0xB1,  0xF0,  0x82,  0x0C,  0x85,  0xF0,  0xC6,  0x0B,  0x69,  0x08,  0x48,  0xE4,  0x03,  0x00,
+  0xD5,  0xF0,  0x82,  0x0B,  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,  0xC6,  0x0B,  0xE8,  0x09,  0x3C,  0x56,
+  0x00,  0xFC,  0x20,  0x01,  0x98,  0x57,  0x02,  0x13,  0xBB,  0x45,  0x4B,  0xE4,  0x00,  0x00,  0x08,  0x12,
+  0x03,  0xE6,  0x01,  0x00,  0x04,  0xF6,  0x00,  0x80,  0xA8,  0x14,  0xD2,  0x14,  0x30,  0x1C,  0x02,  0x80,
+  0x48,  0xE4,  0x03,  0x00,  0x10,  0x13,  0x00,  0xFC,  0xB6,  0x00,  0x98,  0x57,  0x02,  0x13,  0x4C,  0x1C,
+  0x3E,  0x1C,  0x00,  0xF0,  0x8A,  0x0B,  0x00,  0xFC,  0x24,  0x01,  0xB0,  0x57,  0x00,  0xFA,  0x24,  0x01,
+  0x4C,  0x1C,  0x3E,  0x1C,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0x8A,  0x0B,  0x00,  0xF2,  0x88,  0x0E,
+  0x00,  0xF0,  0x8A,  0x0B,  0xB1,  0xF0,  0xF4,  0x0C,  0x85,  0xF0,  0x82,  0x0B,  0x69,  0x08,  0x48,  0xE4,
+  0x01,  0x00,  0xD5,  0xF0,  0x82,  0x0B,  0xFC,  0x14,  0x42,  0x58,  0x6C,  0x14,  0x80,  0x14,  0x30,  0x1C,
+  0x4A,  0xF4,  0x02,  0x00,  0x55,  0xF0,  0x82,  0x0B,  0x4A,  0xF4,  0x01,  0x00,  0x0E,  0x12,  0x02,  0x80,
+  0x48,  0xE4,  0x03,  0x00,  0x06,  0x13,  0x3E,  0x1C,  0x00,  0xF0,  0x8A,  0x0B,  0x00,  0xFC,  0xB6,  0x00,
+  0xB0,  0x57,  0x00,  0xFA,  0xB6,  0x00,  0x4C,  0x1C,  0x3E,  0x1C,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,
+  0x8A,  0x0B,  0x00,  0xF2,  0xB6,  0x0E,  0x00,  0xF0,  0x8A,  0x0B,  0x4C,  0x1C,  0xB1,  0xF0,  0x4C,  0x0D,
+  0x85,  0xF0,  0x58,  0x0D,  0x69,  0x08,  0xF3,  0x10,  0x86,  0xF0,  0x60,  0x0D,  0x4E,  0x1C,  0x89,  0x48,
+  0x00,  0x16,  0x00,  0xF6,  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,  0x03,  0x58,  0x00,  0xDC,  0x18,  0xF4,
+  0xFF,  0x7F,  0x30,  0x56,  0x00,  0x5C,  0x00,  0x16,  0x00,  0xF6,  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,
+  0x03,  0x58,  0x00,  0xDC,  0x18,  0xF4,  0x00,  0x80,  0x30,  0x56,  0x00,  0x5C,  0x00,  0x16,  0x00,  0xF6,
+  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,  0x03,  0x58,  0x00,  0xDC,  0x0B,  0x58,  0x00,  0x16,  0x03,  0xF6,
+  0x24,  0x01,  0x00,  0xF2,  0x54,  0x0A,  0x03,  0xF6,  0xB6,  0x00,  0x00,  0xF2,  0x54,  0x0A,  0x00,  0x16,
+  0x02,  0xEC,  0xB8,  0x00,  0x02,  0x49,  0x18,  0xF4,  0xFF,  0x00,  0x00,  0x54,  0x00,  0x54,  0x00,  0x54,
+  0x00,  0xF4,  0x08,  0x00,  0xE1,  0x18,  0x80,  0x54,  0x03,  0x58,  0x00,  0xDD,  0x01,  0xDD,  0x02,  0xDD,
+  0x03,  0xDC,  0x02,  0x4B,  0x30,  0x50,  0xB2,  0x50,  0x34,  0x51,  0xB6,  0x51,  0x00,  0x16,  0x45,  0x5A,
+  0x1D,  0xF4,  0xFF,  0x00,  0x85,  0x56,  0x85,  0x56,  0x85,  0x56,  0x05,  0xF4,  0x02,  0x12,  0x83,  0x5A,
+  0x00,  0x16,  0x1D,  0xF4,  0xFF,  0x00,  0x85,  0x56,  0x85,  0x56,  0x85,  0x56,  0x05,  0xF4,  0x00,  0x12,
+  0x83,  0x5A,  0x00,  0x16,  0x38,  0x54,  0xBB,  0x55,  0x3C,  0x56,  0xBD,  0x56,  0x00,  0xF2,  0x0E,  0x11,
+  0x85,  0xF0,  0x7E,  0x0E,  0xE9,  0x09,  0xC1,  0x59,  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,  0x7E,  0x0E,
+  0xE8,  0x0A,  0x83,  0x55,  0x83,  0x55,  0x4B,  0xF4,  0x90,  0x01,  0x5C,  0xF0,  0x32,  0x0E,  0xBD,  0x56,
+  0x40,  0x10,  0x4B,  0xF4,  0x30,  0x00,  0x59,  0xF0,  0x44,  0x0E,  0x01,  0xF6,  0x0C,  0x00,  0x00,  0xF6,
+  0x01,  0x00,  0x2E,  0x10,  0x02,  0xFC,  0x9C,  0x00,  0x9A,  0x57,  0x14,  0x13,  0x4B,  0xF4,  0x64,  0x00,
+  0x59,  0xF0,  0x60,  0x0E,  0x03,  0xF6,  0x64,  0x00,  0x01,  0xF6,  0x19,  0x00,  0x00,  0xF6,  0x01,  0x00,
+  0x43,  0xF4,  0x33,  0x00,  0x56,  0xF0,  0x72,  0x0E,  0x04,  0xF4,  0x00,  0x01,  0x43,  0xF4,  0x19,  0x00,
+  0xF3,  0x10,  0xB4,  0x56,  0xC3,  0x58,  0x02,  0xFC,  0x9E,  0x00,  0x9A,  0x57,  0x08,  0x13,  0x3C,  0x56,
+  0x00,  0xF6,  0x02,  0x00,  0x00,  0x16,  0x00,  0x16,  0x09,  0xE7,  0x01,  0x00,  0x00,  0xF2,  0x0E,  0x11,
+  0x86,  0xF0,  0xB4,  0x0E,  0x09,  0xE7,  0x02,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0xB4,  0x0E,
+  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0xB4,  0x0E,  0x4E,  0x1C,  0x89,  0x49,
+  0x00,  0xF2,  0x0E,  0x11,  0x00,  0x16,  0x09,  0xE7,  0x01,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,
+  0xEE,  0x0E,  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0xEE,  0x0E,  0x09,  0xE7,
+  0x01,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0xEE,  0x0E,  0x89,  0x49,  0x00,  0xF2,  0x0E,  0x11,
+  0x86,  0xF0,  0xEE,  0x0E,  0x4E,  0x1C,  0x89,  0x4A,  0x00,  0xF2,  0x0E,  0x11,  0x00,  0x16,  0x3C,  0x56,
+  0x00,  0x16,  0x00,  0xEC,  0x26,  0x01,  0x48,  0xE4,  0x01,  0x00,  0x1E,  0x13,  0x38,  0x44,  0x00,  0xEA,
+  0x26,  0x01,  0x49,  0xF4,  0x00,  0x00,  0x04,  0x12,  0x4E,  0x1C,  0x02,  0x10,  0x4C,  0x1C,  0x01,  0xEC,
+  0x27,  0x01,  0x89,  0x48,  0x00,  0xF2,  0x0E,  0x11,  0x02,  0x14,  0x00,  0x16,  0x85,  0xF0,  0x4E,  0x0F,
+  0x38,  0x54,  0x00,  0xEA,  0x99,  0x00,  0x00,  0xF2,  0x5C,  0x0B,  0x02,  0x80,  0x48,  0xE4,  0x06,  0x00,
+  0x1C,  0x13,  0x00,  0xEC,  0x99,  0x00,  0x48,  0xE4,  0x01,  0x00,  0x0A,  0x12,  0x04,  0x80,  0x30,  0xE4,
+  0x01,  0x00,  0x04,  0x40,  0x08,  0x10,  0x04,  0x80,  0x18,  0xE4,  0xFE,  0x00,  0x04,  0x40,  0x00,  0x16,
+  0x02,  0xF6,  0xE0,  0x00,  0x02,  0x57,  0x03,  0x59,  0x01,  0xCC,  0x81,  0x48,  0x22,  0x12,  0x00,  0x4E,
+  0x83,  0x5A,  0x90,  0x4C,  0x20,  0xE7,  0x00,  0x00,  0xC3,  0x58,  0x1B,  0xF4,  0xFF,  0x00,  0x83,  0x55,
+  0x83,  0x55,  0x83,  0x55,  0x03,  0xF4,  0x00,  0x12,  0x8B,  0x55,  0x83,  0x59,  0x00,  0x4E,  0x00,  0x16,
+  0x00,  0x4E,  0x02,  0xF6,  0xF0,  0x00,  0x02,  0x57,  0x03,  0x59,  0x00,  0x4E,  0x83,  0x5A,  0x30,  0xE7,
+  0x00,  0x00,  0x20,  0xE7,  0x00,  0x00,  0x00,  0x16,  0x02,  0xF6,  0xF0,  0x00,  0x02,  0x57,  0x03,  0x59,
+  0x01,  0xCC,  0x00,  0x4E,  0x83,  0x5A,  0x30,  0xE7,  0x00,  0x00,  0x80,  0x4C,  0xC3,  0x58,  0x1B,  0xF4,
+  0xFF,  0x00,  0x83,  0x55,  0x83,  0x55,  0x83,  0x55,  0x03,  0xF4,  0x00,  0x12,  0x83,  0x59,  0x00,  0x4E,
+  0x00,  0x16,  0x03,  0xF6,  0xE0,  0x00,  0x03,  0x57,  0x83,  0x59,  0x3A,  0x55,  0x02,  0xCC,  0x45,  0x5A,
+  0x00,  0xF2,  0xF2,  0x0D,  0xC0,  0x5A,  0x40,  0x5C,  0x38,  0x54,  0x00,  0xCD,  0x01,  0xCC,  0x4A,  0x46,
+  0x0A,  0x13,  0x83,  0x59,  0x00,  0x4C,  0x01,  0x48,  0x16,  0x13,  0x0C,  0x10,  0xC5,  0x58,  0x00,  0xF2,
+  0xF2,  0x0D,  0x00,  0x4C,  0x01,  0x48,  0x08,  0x13,  0x05,  0xF6,  0xF0,  0x00,  0x05,  0x57,  0x08,  0x10,
+  0x45,  0x58,  0x00,  0xF2,  0xF2,  0x0D,  0x8D,  0x56,  0x83,  0x5A,  0x80,  0x4C,  0x05,  0x17,  0x00,  0x16,
+  0x02,  0x4B,  0x06,  0xF7,  0x04,  0x00,  0x62,  0x0B,  0x03,  0x82,  0x00,  0xF2,  0xDE,  0x0D,  0x02,  0x80,
+  0x00,  0x4C,  0x45,  0xF4,  0x02,  0x00,  0x52,  0x14,  0x06,  0xF7,  0x02,  0x00,  0x06,  0x14,  0x00,  0xF2,
+  0x50,  0x0F,  0x00,  0x16,  0x02,  0x4B,  0x01,  0xF6,  0xFF,  0x00,  0x38,  0x1C,  0x05,  0xF4,  0x04,  0x00,
+  0x83,  0x5A,  0x18,  0xDF,  0x19,  0xDF,  0x1D,  0xF7,  0x3C,  0x00,  0xB8,  0xF0,  0x4A,  0x10,  0x9C,  0x14,
+  0x01,  0x48,  0x1C,  0x13,  0x0E,  0xF7,  0x3C,  0x00,  0x03,  0xF7,  0x04,  0x00,  0xAF,  0x19,  0x03,  0x42,
+  0x45,  0xF4,  0x02,  0x00,  0x83,  0x5A,  0x02,  0xCC,  0x02,  0x41,  0x45,  0xF4,  0x02,  0x00,  0x00,  0x16,
+  0x91,  0x44,  0xD5,  0xF0,  0x3A,  0x10,  0x00,  0xF0,  0x9E,  0x02,  0x01,  0xF6,  0xFF,  0x00,  0x38,  0x1C,
+  0x05,  0xF4,  0x04,  0x00,  0x83,  0x5A,  0x18,  0xDF,  0x19,  0xDF,  0x0E,  0xF7,  0x3C,  0x00,  0x03,  0xF7,
+  0x04,  0x00,  0x0F,  0x79,  0x1C,  0xF7,  0x3C,  0x00,  0xB8,  0xF0,  0x98,  0x10,  0x4E,  0x14,  0x01,  0x48,
+  0x06,  0x13,  0x45,  0xF4,  0x04,  0x00,  0x00,  0x16,  0x91,  0x44,  0xD5,  0xF0,  0x7E,  0x10,  0x00,  0xF0,
+  0x9E,  0x02,  0x02,  0xF6,  0xFF,  0x00,  0x38,  0x1C,  0x2C,  0xBC,  0xAE,  0xBC,  0xE2,  0x08,  0x00,  0xEC,
+  0xB8,  0x00,  0x02,  0x48,  0x1D,  0xF7,  0x80,  0x00,  0xB8,  0xF0,  0xC8,  0x10,  0x1E,  0x14,  0x01,  0x48,
+  0x0E,  0x13,  0x0E,  0xF7,  0x80,  0x00,  0x38,  0x54,  0x03,  0x58,  0xAF,  0x19,  0x82,  0x48,  0x00,  0x16,
+  0x82,  0x48,  0x12,  0x45,  0xD5,  0xF0,  0xB6,  0x10,  0x00,  0xF0,  0x9E,  0x02,  0x39,  0xF0,  0xF4,  0x10,
+  0x38,  0x44,  0x00,  0x16,  0x7E,  0x18,  0x18,  0xF4,  0x03,  0x00,  0x04,  0x13,  0x61,  0x18,  0x00,  0x16,
+  0x38,  0x1C,  0x00,  0xFC,  0x22,  0x01,  0x18,  0xF4,  0x01,  0x00,  0xF1,  0x12,  0xE3,  0x10,  0x30,  0x44,
+  0x30,  0x44,  0x30,  0x44,  0xB1,  0xF0,  0x14,  0x11,  0x00,  0x16,  0x3E,  0x57,  0x03,  0xF6,  0xE0,  0x00,
+  0x03,  0x57,  0x83,  0x59,  0x04,  0xCC,  0x01,  0x4A,  0x6A,  0x12,  0x45,  0x5A,  0x00,  0xF2,  0xF2,  0x0D,
+  0x02,  0x4B,  0x70,  0x14,  0x34,  0x13,  0x02,  0x80,  0x48,  0xE4,  0x08,  0x00,  0x18,  0x12,  0x9C,  0xE7,
+  0x02,  0x00,  0x9E,  0xE7,  0x15,  0x00,  0x00,  0xF2,  0xC2,  0x0F,  0x00,  0xF2,  0x76,  0x0A,  0x1E,  0x1C,
+  0x01,  0xF6,  0x01,  0x00,  0x00,  0x16,  0x30,  0xE4,  0x10,  0x00,  0x04,  0x40,  0x00,  0xF2,  0xDE,  0x0D,
+  0x20,  0xE7,  0x01,  0x00,  0x01,  0xF6,  0x01,  0x00,  0x00,  0x16,  0x04,  0xDC,  0x01,  0x4A,  0x24,  0x12,
+  0x45,  0x5A,  0x00,  0xF2,  0xF2,  0x0D,  0x43,  0x5B,  0x06,  0xEC,  0x98,  0x00,  0x00,  0xF2,  0x34,  0x10,
+  0xC6,  0x59,  0x20,  0x14,  0x0A,  0x13,  0x00,  0xF2,  0xC2,  0x0F,  0x00,  0xF2,  0x10,  0x10,  0xA7,  0x10,
+  0x83,  0x5A,  0xD7,  0x10,  0x0E,  0x47,  0x07,  0xE6,  0x10,  0x00,  0xCE,  0x47,  0x5A,  0xF0,  0x1C,  0x11,
+  0xB9,  0x54,  0x00,  0x16,  0x14,  0x90,  0x96,  0x90,  0x02,  0xFC,  0xA8,  0x00,  0x03,  0xFC,  0xAA,  0x00,
+  0x48,  0x55,  0x02,  0x13,  0xC9,  0x55,  0x00,  0x16,  0x00,  0xEC,  0xBA,  0x00,  0x10,  0x44,  0x00,  0xEA,
+  0xBA,  0x00,  0x00,  0x16,  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x10,  0x44,  0x00,  0x4C,
+  0x00,  0x16 };
+
+unsigned short _adv_mcode_size ASC_INITDATA =
+    sizeof(_adv_mcode_buf); /* 0x11D2 */
+unsigned long  _adv_mcode_chksum ASC_INITDATA = 0x0347D07AUL;
+
+/* a_init.c */
+/*
+ * EEPROM Configuration.
+ *
+ * All drivers should use this structure to set the default EEPROM
+ * configuration. The BIOS now uses this structure when it is built.
+ * Additional structure information can be found in a_condor.h where
+ * the structure is defined.
+ */
+STATIC ADVEEP_CONFIG
+Default_EEPROM_Config ASC_INITDATA = {
+    ADV_EEPROM_BIOS_ENABLE,     /* cfg_msw */
+    0x0000,                     /* cfg_lsw */
+    0xFFFF,                     /* disc_enable */
+    0xFFFF,                     /* wdtr_able */
+    0xFFFF,                     /* sdtr_able */
+    0xFFFF,                     /* start_motor */
+    0xFFFF,                     /* tagqng_able */
+    0xFFFF,                     /* bios_scan */
+    0,                          /* scam_tolerant */
+    7,                          /* adapter_scsi_id */
+    0,                          /* bios_boot_delay */
+    3,                          /* scsi_reset_delay */
+    0,                          /* bios_id_lun */
+    0,                          /* termination */
+    0,                          /* reserved1 */
+    0xFFEF,                     /* bios_ctrl */
+    0xFFFF,                     /* ultra_able */
+    0,                          /* reserved2 */
+    ASC_DEF_MAX_HOST_QNG,       /* max_host_qng */
+    ASC_DEF_MAX_DVC_QNG,        /* max_dvc_qng */
+    0,                          /* dvc_cntl */
+    0,                          /* bug_fix */
+    0,                          /* serial_number_word1 */
+    0,                          /* serial_number_word2 */
+    0,                          /* serial_number_word3 */
+    0,                          /* check_sum */
+    { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */
+    0,                          /* dvc_err_code */
+    0,                          /* adv_err_code */
+    0,                          /* adv_err_addr */
+    0,                          /* saved_dvc_err_code */
+    0,                          /* saved_adv_err_code */
+    0,                          /* saved_adv_err_addr */
+    0                           /* num_of_err */
+};
+
+/*
+ * Initialize the ADV_DVC_VAR structure.
+ *
+ * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ *
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
+ */
+ASC_INITFUNC(
+int
+AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
+)
+{
+    ushort      warn_code;
+    AdvPortAddr iop_base;
+    uchar       pci_cmd_reg;
+    int         status;
+
+    warn_code = 0;
+    asc_dvc->err_code = 0;
+    iop_base = asc_dvc->iop_base;
+
+    /*
+     * PCI Command Register
+     */
+
+    if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc,
+                            AscPCIConfigCommandRegister))
+         & AscPCICmdRegBits_BusMastering)
+        != AscPCICmdRegBits_BusMastering)
+    {
+        pci_cmd_reg |= AscPCICmdRegBits_BusMastering;
+
+        DvcAdvWritePCIConfigByte(asc_dvc,
+                AscPCIConfigCommandRegister, pci_cmd_reg);
+
+        if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister))
+             & AscPCICmdRegBits_BusMastering)
+            != AscPCICmdRegBits_BusMastering)
+        {
+            warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
+        }
+    }
+
+    /*
+     * PCI Latency Timer
+     *
+     * If the "latency timer" register is 0x20 or above, then we don't need
+     * to change it.  Otherwise, set it to 0x20 (i.e. set it to 0x20 if it
+     * comes up less than 0x20).
+     */
+    if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) {
+        DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, 0x20);
+        if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20)
+        {
+            warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE;
+        }
+    }
+
+    /*
+     * Save the state of the PCI Configuration Command Register
+     * "Parity Error Response Control" Bit. If the bit is clear (0),
+     * in AdvInitAsc3550Driver() tell the microcode to ignore DMA
+     * parity errors.
+     */
+    asc_dvc->cfg->control_flag = 0;
+    if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)
+         & AscPCICmdRegBits_ParErrRespCtrl)) == 0)
+    {
+        asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
+    }
+
+    asc_dvc->cur_host_qng = 0;
+
+    asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
+      ADV_LIB_VERSION_MINOR;
+    asc_dvc->cfg->chip_version =
+      AdvGetChipVersion(iop_base, asc_dvc->bus_type);
+
+    /*
+     * Reset the chip to start and allow register writes.
+     */
+    if (AdvFindSignature(iop_base) == 0)
+    {
+        asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+        return ADV_ERROR;
+    }
+    else {
+
+        AdvResetChip(asc_dvc);
+
+        if ((status = AdvInitFromEEP(asc_dvc)) == ADV_ERROR)
+        {
+            return ADV_ERROR;
+        }
+        warn_code |= status;
+
+        /*
+         * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
+         * Resets should be performed.
+         */
+        if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS)
+        {
+            AdvResetSCSIBus(asc_dvc);
+        }
+    }
+
+    return warn_code;
+}
+
+/*
+ * Initialize the ASC3550.
+ *
+ * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ *
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
+ */
+ASC_INITFUNC(
+int
+AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
+)
+{
+    AdvPortAddr iop_base;
+    ushort      warn_code;
+    ulong       sum;
+    int         begin_addr;
+    int         end_addr;
+    int         code_sum;
+    int         word;
+    int         rql_addr;                   /* RISC Queue List address */
+    int         i;
+    ushort      scsi_cfg1;
+    uchar       biosmem[ASC_MC_BIOSLEN];    /* BIOS RISC Memory 0x40-0x8F. */
+
+    /* If there is already an error, don't continue. */
+    if (asc_dvc->err_code != 0)
+    {
+        return ADV_ERROR;
+    }
+
+    warn_code = 0;
+    iop_base = asc_dvc->iop_base;
+
+    /*
+     * Save the RISC memory BIOS region before writing the microcode.
+     * The BIOS may already be loaded and using its RISC LRAM region
+     * so its region must be saved and restored.
+     *
+     * Note: This code makes the assumption, which is currently true,
+     * that a chip reset does not clear RISC LRAM.
+     */
+    for (i = 0; i < ASC_MC_BIOSLEN; i++)
+    {
+        AdvReadByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]);
+    }
+
+    /*
+     * Load the Microcode
+     *
+     * Write the microcode image to RISC memory starting at address 0.
+     */
+    AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
+    for (word = 0; word < _adv_mcode_size; word += 2)
+    {
+        AdvWriteWordAutoIncLram(iop_base,
+            *((ushort *) (&_adv_mcode_buf[word])));
+    }
+
+    /*
+     * Clear the rest of Condor's Internal RAM (8KB).
+     */
+    for (; word < ADV_CONDOR_MEMSIZE; word += 2)
+    {
+        AdvWriteWordAutoIncLram(iop_base, 0);
+    }
+
+    /*
+     * Verify the microcode checksum.
+     */
+    sum = 0;
+    AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
+    for (word = 0; word < _adv_mcode_size; word += 2)
+    {
+        sum += AdvReadWordAutoIncLram(iop_base);
+    }
+
+    if (sum != _adv_mcode_chksum)
+    {
+        asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
+        return ADV_ERROR;
+    }
+
+    /*
+     * Restore the RISC memory BIOS region.
+     */
+    for (i = 0; i < ASC_MC_BIOSLEN; i++)
+    {
+        AdvWriteByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]);
+    }
+
+    /*
+     * Calculate and write the microcode code checksum to the microcode
+     * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).  
+     */
+    AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
+    AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
+    code_sum = 0;
+    for (word = begin_addr; word < end_addr; word += 2)
+    {
+        code_sum += *((ushort *) (&_adv_mcode_buf[word]));
+    }
+    AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
+
+    /*
+     * Read microcode version and date.
+     */
+    AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date);
+    AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version);
+
+    /*
+     * Initialize microcode operating variables
+     */
+    AdvWriteWordLram(iop_base, ASC_MC_ADAPTER_SCSI_ID,
+                       asc_dvc->chip_scsi_id);
+
+    /*
+     * If the PCI Configuration Command Register "Parity Error Response
+     * Control" Bit was clear (0), then set the microcode variable
+     * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
+     * to ignore DMA parity errors.
+     */
+    if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR)
+    {
+        /* 
+         * Note: Don't remove the use of a temporary variable in
+         * the following code, otherwise the Microsoft C compiler
+         * will turn the following lines into a no-op.
+         */
+        AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+        word |= CONTROL_FLAG_IGNORE_PERR;
+        AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
+    }
+
+    /*
+     * Set default microcode operating variables for WDTR, SDTR, and
+     * command tag queuing based on the EEPROM configuration values.
+     *
+     * These ADV_DVC_VAR fields and the microcode variables will be
+     * changed in AdvInquiryHandling() if it is found a device is
+     * incapable of a particular feature.
+     */
+
+    /*
+     * Set the microcode ULTRA target mask from EEPROM value. The
+     * SDTR target mask overrides the ULTRA target mask in the
+     * microcode so it is safe to set this value without determining
+     * whether the device supports SDTR.
+     * 
+     * Note: There is no way to know whether a device supports ULTRA
+     * speed without attempting a SDTR ULTRA speed negotiation with
+     * the device. The device will reject the speed if it does not
+     * support it by responding with an SDTR message containing a
+     * slower speed.
+     */
+    AdvWriteWordLram(iop_base, ASC_MC_ULTRA_ABLE, asc_dvc->ultra_able);
+    AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable);
+
+
+    /*
+     * Set SCSI_CFG0 Microcode Default Value.
+     *
+     * The microcode will set the SCSI_CFG0 register using this value
+     * after it is started below.
+     */
+    AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
+        PARITY_EN | SEL_TMO_LONG | OUR_ID_EN | asc_dvc->chip_scsi_id);
+  
+    /*
+     * Determine SCSI_CFG1 Microcode Default Value.
+     *
+     * The microcode will set the SCSI_CFG1 register using this value
+     * after it is started below.
+     */
+
+    /* Read current SCSI_CFG1 Register value. */
+    scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
+
+    /*
+     * If all three connectors are in use, return an error.
+     */
+    if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
+        (scsi_cfg1 & CABLE_ILLEGAL_B) == 0)
+    {
+        asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
+        return ADV_ERROR;
+    }
 
-STATIC int
-PollScsiStartUnit(
-                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                     REG ASC_SCSI_REQ_Q * scsiq
-)
-{
-    if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    /*
+     * If the internal narrow cable is reversed all of the SCSI_CTRL
+     * register signals will be set. Check for and return an error if
+     * this condition is found.
+     */
+    if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07)
+    {
+        asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
+        return ADV_ERROR;
     }
-    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 40));
-}
 
-STATIC int
-PollScsiReadCapacity(
-                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                        REG ASC_SCSI_REQ_Q * scsiq,
-                        REG ASC_CAP_INFO * cap_info
-)
-{
-    ASC_CAP_INFO        scsi_cap_info;
-    int                 status;
-    if (AscScsiReadCapacity(asc_dvc, scsiq,
-                            (uchar *) & scsi_cap_info) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    /*
+     * If this is a differential board and a single-ended device
+     * is attached to one of the connectors, return an error.
+     */
+    if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0)
+    {
+        asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
+        return ADV_ERROR;
     }
-    status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 8);
-    if (status == 1) {
-#if CC_LITTLE_ENDIAN_HOST
-        cap_info->lba = (ulong) * swapfarbuf4((uchar *) & scsi_cap_info.lba);
-        cap_info->blk_size = (ulong) * swapfarbuf4((uchar *) & scsi_cap_info.blk_size);
-#else
-        cap_info->lba = scsi_cap_info.lba;
-        cap_info->blk_size = scsi_cap_info.blk_size;
-#endif
-        return (scsiq->r3.done_stat);
+
+    /*
+     * If automatic termination control is enabled, then set the
+     * termination value based on a table listed in a_condor.h.
+     *
+     * If manual termination was specified with an EEPROM setting
+     * then 'termination' was set-up in AdvInitFromEEP() and
+     * is ready to be 'ored' into SCSI_CFG1.
+     */
+    if (asc_dvc->cfg->termination == 0)
+    {
+        /*
+         * The software always controls termination by setting TERM_CTL_SEL.
+         * If TERM_CTL_SEL were set to 0, the hardware would set termination.
+         */
+        asc_dvc->cfg->termination |= TERM_CTL_SEL;
+
+        switch(scsi_cfg1 & CABLE_DETECT)
+        {
+            /* TERM_CTL_H: on, TERM_CTL_L: on */
+            case 0x3: case 0x7: case 0xB: case 0xD: case 0xE: case 0xF:
+                asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
+                break;
+
+            /* TERM_CTL_H: on, TERM_CTL_L: off */
+            case 0x1: case 0x5: case 0x9: case 0xA: case 0xC:
+                asc_dvc->cfg->termination |= TERM_CTL_H;
+                break;
+
+            /* TERM_CTL_H: off, TERM_CTL_L: off */
+            case 0x2: case 0x6:
+                break;
+        }
     }
-    return (scsiq->r3.done_stat = QD_WITH_ERROR);
-}
 
-STATIC ulong *
-swapfarbuf4(
-    uchar *buf
-)
-{
-    uchar      tmp;
+    /*
+     * Clear any set TERM_CTL_H and TERM_CTL_L bits.
+     */
+    scsi_cfg1 &= ~TERM_CTL;
 
-    tmp = buf[3];
-    buf[3] = buf[0];
-    buf[0] = tmp;
+    /*
+     * Invert the TERM_CTL_H and TERM_CTL_L bits and then
+     * set 'scsi_cfg1'. The TERM_POL bit does not need to be
+     * referenced, because the hardware internally inverts
+     * the Termination High and Low bits if TERM_POL is set.
+     */
+    scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
 
-    tmp = buf[1];
-    buf[1] = buf[2];
-    buf[2] = tmp;
+    /*
+     * Set SCSI_CFG1 Microcode Default Value
+     *
+     * Set filter value and possibly modified termination control
+     * bits in the Microcode SCSI_CFG1 Register Value.
+     *
+     * The microcode will set the SCSI_CFG1 register using this value
+     * after it is started below.
+     */
+    AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
+                       FLTR_11_TO_20NS | scsi_cfg1);
 
-    return ((ulong *) buf);
-}
+    /*
+     * Set SEL_MASK Microcode Default Value
+     *
+     * The microcode will set the SEL_MASK register using this value
+     * after it is started below.
+     */
+    AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
+                        ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
 
-STATIC int
-PollScsiTestUnitReady(
-                         REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                         REG ASC_SCSI_REQ_Q * scsiq
-)
-{
-    if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    /*
+     * Link all the RISC Queue Lists together in a doubly-linked
+     * NULL terminated list.
+     *
+     * Skip the NULL (0) queue which is not used.
+     */
+    for (i = 1, rql_addr = ASC_MC_RISC_Q_LIST_BASE + ASC_MC_RISC_Q_LIST_SIZE;
+         i < ASC_MC_RISC_Q_TOTAL_CNT;
+         i++, rql_addr += ASC_MC_RISC_Q_LIST_SIZE)
+    {
+        /*
+         * Set the current RISC Queue List's RQL_FWD and RQL_BWD pointers
+         * in a one word write and set the state (RQL_STATE) to free.
+         */
+        AdvWriteWordLram(iop_base, rql_addr, ((i + 1) + ((i - 1) << 8)));
+        AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE);
     }
-    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 12));
-}
 
-STATIC int
-InitTestUnitReady(
-                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                     REG ASC_SCSI_REQ_Q * scsiq
-)
-{
-    ASC_SCSI_BIT_ID_TYPE tid_bits;
-    int                 retry;
-    ASC_REQ_SENSE *sen;
-    retry = 0;
-    tid_bits = scsiq->r1.target_id;
-    while (retry++ < 4) {
-        PollScsiTestUnitReady(asc_dvc, scsiq);
-        if (scsiq->r3.done_stat == 0x01) {
-            return (1);
-        } else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
-            DvcSleepMilliSecond(200);
-            sen = (ASC_REQ_SENSE *) scsiq->sense_ptr;
-            if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) &&
-                ((sen->err_code & 0x70) != 0)) {
-                if (sen->sense_key == SCSI_SENKEY_NOT_READY) {
-                    if (asc_dvc->start_motor & tid_bits) {
-                        if (PollScsiStartUnit(asc_dvc, scsiq) == 1) {
-                            retry = 0;
-                            continue;
-                        } else {
-                            asc_dvc->start_motor &= ~tid_bits;
-                            break;
-                        }
-                    } else {
-                        DvcSleepMilliSecond(5000);
-                    }
-                } else if (sen->sense_key == SCSI_SENKEY_ATTENTION) {
-                    DvcSleepMilliSecond((ulong)(500L*retry)) ;
-                } else {
-                    DvcSleepMilliSecond(500) ;
-                    break;
-                }
-            } else {
-                break;
-            }
-        } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) {
-            break;
-        } else {
-            break;
-        }
-    }
-    return (0);
+    /*
+     * Set the Host and RISC Queue List pointers.
+     *
+     * Both sets of pointers are initialized with the same values:
+     * ASC_MC_RISC_Q_FIRST(0x01) and ASC_MC_RISC_Q_LAST (0xFF).
+     */
+    AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, ASC_MC_RISC_Q_FIRST);
+    AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, ASC_MC_RISC_Q_LAST);
+
+    AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_READY, ASC_MC_RISC_Q_FIRST);
+    AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_DONE, ASC_MC_RISC_Q_LAST);
+
+    /*
+     * Finally, set up the last RISC Queue List (255) with
+     * a NULL forward pointer.
+     */
+    AdvWriteWordLram(iop_base, rql_addr, (ASC_MC_NULL_Q + ((i - 1) << 8)));
+    AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE);
+
+    AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
+         (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR));
+
+    /* 
+     * Note: Don't remove the use of a temporary variable in
+     * the following code, otherwise the Microsoft C compiler
+     * will turn the following lines into a no-op.
+     */
+    AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
+    AdvWriteWordRegister(iop_base, IOPW_PC, word);
+
+    /* finally, finally, gentlemen, start your engine */
+    AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
+    return warn_code;
 }
 
+/*
+ * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
+ * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
+ * all of this is done.
+ *
+ * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
+ *
+ * For a non-fatal error return a warning code. If there are no warnings
+ * then 0 is returned.
+ *
+ * Note: Chip is stopped on entry.
+ */
+ASC_INITFUNC(
 STATIC int
-AscPollQDone(
-                REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                REG ASC_SCSI_REQ_Q * scsiq,
-                int timeout_sec
+AdvInitFromEEP(ADV_DVC_VAR *asc_dvc)
 )
 {
-    int                 loop, loop_end;
-    int                 sta;
-    PortAddr            iop_base;
+    AdvPortAddr         iop_base;
+    ushort              warn_code;
+    ADVEEP_CONFIG       eep_config;
+    int                 i;
+
     iop_base = asc_dvc->iop_base;
-    loop = 0;
-    loop_end = timeout_sec * 100;
-    sta = 1;
-    while (TRUE) {
-        if (asc_dvc->err_code != 0) {
-            scsiq->r3.done_stat = QD_WITH_ERROR;
-            ASC_DBG1(1, "AscPollQDone: err_code %x\n", asc_dvc->err_code);
-            sta = ERR;
-            break;
+
+    warn_code = 0;
+
+    /*
+     * Read the board's EEPROM configuration.
+     *
+     * Set default values if a bad checksum is found.
+     */
+    if (AdvGetEEPConfig(iop_base, &eep_config) != eep_config.check_sum)
+    {
+        warn_code |= ASC_WARN_EEPROM_CHKSUM;
+
+        /*
+         * Set EEPROM default values.
+         */
+        for (i = 0; i < sizeof(ADVEEP_CONFIG); i++)
+        {
+            *((uchar *) &eep_config + i) =
+                *((uchar *) &Default_EEPROM_Config + i);
         }
-        if (scsiq->r3.done_stat != QD_IN_PROGRESS) {
-            if ((scsiq->r3.done_stat == QD_WITH_ERROR) &&
-                (scsiq->r3.scsi_stat == SS_TARGET_BUSY)) {
-                sta = 0x80;
-            }
-            break;
+
+        /*
+         * Assume the 6 byte board serial number that was read
+         * from EEPROM is correct even if the EEPROM checksum
+         * failed.
+         */
+        eep_config.serial_number_word3 =
+            AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 1);
+        eep_config.serial_number_word2 =
+            AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 2);
+        eep_config.serial_number_word1 =
+            AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 3);
+        AdvSetEEPConfig(iop_base, &eep_config);
+    }
+
+    /*
+     * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
+     * EEPROM configuration that was read.
+     *
+     * This is the mapping of EEPROM fields to Adv Library fields.
+     */
+    asc_dvc->wdtr_able = eep_config.wdtr_able;
+    asc_dvc->sdtr_able = eep_config.sdtr_able;
+    asc_dvc->ultra_able = eep_config.ultra_able;
+    asc_dvc->tagqng_able = eep_config.tagqng_able;
+    asc_dvc->cfg->disc_enable = eep_config.disc_enable;
+    asc_dvc->max_host_qng = eep_config.max_host_qng;
+    asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
+    asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
+    asc_dvc->start_motor = eep_config.start_motor;
+    asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
+    asc_dvc->cfg->bios_boot_wait = eep_config.bios_boot_delay;
+    asc_dvc->bios_ctrl = eep_config.bios_ctrl;
+    asc_dvc->no_scam = eep_config.scam_tolerant;
+    asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
+    asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
+    asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
+
+    /*
+     * Set the host maximum queuing (max. 253, min. 16) and the per device
+     * maximum queuing (max. 63, min. 4).
+     */
+    if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG)
+    {
+        eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
+    } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG)
+    {
+        /* If the value is zero, assume it is uninitialized. */
+        if (eep_config.max_host_qng == 0)
+        {
+            eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
+        } else
+        {
+            eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
         }
-        DvcSleepMilliSecond(10);
-        if (loop++ > loop_end) {
-            ASC_DBG(1, "AscPollQDone: loop finished\n");
-            sta = 0;
-            break;
+    }
+
+    if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG)
+    {
+        eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+    } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG)
+    {
+        /* If the value is zero, assume it is uninitialized. */
+        if (eep_config.max_dvc_qng == 0)
+        {
+            eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
+        } else
+        {
+            eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
         }
-        if (AscIsChipHalted(iop_base)) {
-            ASC_DBG(1, "AscPollQDone: AscIsChipHalted()\n");
-#if !CC_ASCISR_CHECK_INT_PENDING
-            AscAckInterrupt(iop_base);
-#endif
-            AscISR(asc_dvc);
-            loop = 0;
-        } else {
-            if (AscIsIntPending(iop_base)) {
-                ASC_DBG(1, "AscPollQDone: AscIsIntPending()\n");
-#if !CC_ASCISR_CHECK_INT_PENDING
-                AscAckInterrupt(iop_base);
-#endif
-                AscISR(asc_dvc);
-            }
+    }
+
+    /*
+     * If 'max_dvc_qng' is greater than 'max_host_qng', then
+     * set 'max_dvc_qng' to 'max_host_qng'.
+     */
+    if (eep_config.max_dvc_qng > eep_config.max_host_qng)
+    {
+        eep_config.max_dvc_qng = eep_config.max_host_qng;
+    }
+
+    /*
+     * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_CFG 'max_dvc_qng'
+     * values based on possibly adjusted EEPROM values.
+     */
+    asc_dvc->max_host_qng = eep_config.max_host_qng;
+    asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
+
+
+    /*
+     * If the EEPROM 'termination' field is set to automatic (0), then set
+     * the ADV_DVC_CFG 'termination' field to automatic also.
+     *
+     * If the termination is specified with a non-zero 'termination'
+     * value check that a legal value is set and set the ADV_DVC_CFG
+     * 'termination' field appropriately.
+     */
+    if (eep_config.termination == 0)
+    {
+        asc_dvc->cfg->termination = 0;    /* auto termination */
+    } else
+    {
+        /* Enable manual control with low off / high off. */
+        if (eep_config.termination == 1)
+        {
+            asc_dvc->cfg->termination = TERM_CTL_SEL;
+
+        /* Enable manual control with low off / high on. */
+        } else if (eep_config.termination == 2)
+        {
+            asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
+
+        /* Enable manual control with low on / high on. */
+        } else if (eep_config.termination == 3)
+        {
+            asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
+        } else
+        {
+            /*
+             * The EEPROM 'termination' field contains a bad value. Use
+             * automatic termination instead.
+             */
+            asc_dvc->cfg->termination = 0;
+            warn_code |= ASC_WARN_EEPROM_TERMINATION;
         }
     }
-    return (sta);
-}
 
-STATIC int
-AscCompareString(
-                    ruchar * str1,
-                    ruchar * str2,
-                    int len
-)
-{
-    int                 i;
-    int                 diff;
-    for (i = 0; i < len; i++) {
-        diff = (int) (str1[i] - str2[i]);
-        if (diff != 0)
-            return (diff);
-    }
-    return (0);
+    return warn_code;
 }
 
-STATIC uchar
-AscReadLramByte(
-                   PortAddr iop_base,
-                   ushort addr
+/*
+ * Read EEPROM configuration into the specified buffer.
+ *
+ * Return a checksum based on the EEPROM configuration read.
+ */
+ASC_INITFUNC(
+STATIC ushort
+AdvGetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
 )
 {
-    uchar               byte_data;
-    ushort              word_data;
-    if (isodd_word(addr)) {
-        AscSetChipLramAddr(iop_base, addr - 1);
-        word_data = AscGetChipLramData(iop_base);
-        byte_data = (uchar) ((word_data >> 8) & 0xFF);
-    } else {
-        AscSetChipLramAddr(iop_base, addr);
-        word_data = AscGetChipLramData(iop_base);
-        byte_data = (uchar) (word_data & 0xFF);
+    ushort              wval, chksum;
+    ushort              *wbuf;
+    int                 eep_addr;
+
+    wbuf = (ushort *) cfg_buf;
+    chksum = 0;
+
+    for (eep_addr = ASC_EEP_DVC_CFG_BEGIN;
+         eep_addr < ASC_EEP_DVC_CFG_END;
+         eep_addr++, wbuf++)
+    {
+        wval = AdvReadEEPWord(iop_base, eep_addr);
+        chksum += wval;
+        *wbuf = wval;
     }
-    return (byte_data);
+    *wbuf = AdvReadEEPWord(iop_base, eep_addr);
+    wbuf++;
+    for (eep_addr = ASC_EEP_DVC_CTL_BEGIN;
+         eep_addr < ASC_EEP_MAX_WORD_ADDR;
+         eep_addr++, wbuf++)
+    {
+        *wbuf = AdvReadEEPWord(iop_base, eep_addr);
+    }
+    return chksum;
 }
 
+/*
+ * Read the EEPROM from specified location
+ */
+ASC_INITFUNC(
 STATIC ushort
-AscReadLramWord(
-                   PortAddr iop_base,
-                   ushort addr
+AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
 )
 {
-    ushort              word_data;
-    AscSetChipLramAddr(iop_base, addr);
-    word_data = AscGetChipLramData(iop_base);
-    return (word_data);
+    AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
+        ASC_EEP_CMD_READ | eep_word_addr);
+    AdvWaitEEPCmd(iop_base);
+    return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
 }
 
-STATIC ulong
-AscReadLramDWord(
-                    PortAddr iop_base,
-                    ushort addr
+/*
+ * Wait for EEPROM command to complete
+ */
+ASC_INITFUNC(
+STATIC void
+AdvWaitEEPCmd(AdvPortAddr iop_base)
 )
 {
-    ushort              val_low, val_high;
-    ulong               dword_data;
-    AscSetChipLramAddr(iop_base, addr);
-    val_low = AscGetChipLramData(iop_base);
-    val_high = AscGetChipLramData(iop_base);
-    dword_data = ((ulong) val_high << 16) | (ulong) val_low;
-    return (dword_data);
+    int eep_delay_ms;
+
+    for (eep_delay_ms = 0; eep_delay_ms < ASC_EEP_DELAY_MS; eep_delay_ms++)
+    {
+        if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE)
+        {
+            break;
+        }
+        DvcSleepMilliSecond(1);
+    }
+    if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == 0)
+    {
+        ADV_ASSERT(0);
+    }
+    return;
 }
 
+/*
+ * Write the EEPROM from 'cfg_buf'.
+ */
+ASC_INITFUNC(
 STATIC void
-AscWriteLramWord(
-                    PortAddr iop_base,
-                    ushort addr,
-                    ushort word_val
+AdvSetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
 )
 {
-    AscSetChipLramAddr(iop_base, addr);
-    AscSetChipLramData(iop_base, word_val);
+    ushort       *wbuf;
+    ushort       addr, chksum;
+
+    wbuf = (ushort *) cfg_buf;
+    chksum = 0;
+
+    AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
+    AdvWaitEEPCmd(iop_base);
+
+    /*
+     * Write EEPROM from word 0 to word 15
+     */
+    for (addr = ASC_EEP_DVC_CFG_BEGIN;
+         addr < ASC_EEP_DVC_CFG_END; addr++, wbuf++)
+    {
+        chksum += *wbuf;
+        AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
+        AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
+        AdvWaitEEPCmd(iop_base);
+        DvcSleepMilliSecond(ASC_EEP_DELAY_MS);
+    }
+
+    /*
+     * Write EEPROM checksum at word 18
+     */
+    AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
+    AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
+    AdvWaitEEPCmd(iop_base);
+    wbuf++;        /* skip over check_sum */
+
+    /*
+     * Write EEPROM OEM name at words 19 to 26 
+     */
+    for (addr = ASC_EEP_DVC_CTL_BEGIN;
+         addr < ASC_EEP_MAX_WORD_ADDR; addr++, wbuf++)
+    {
+        AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf);
+        AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
+        AdvWaitEEPCmd(iop_base);
+    }
+    AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
+    AdvWaitEEPCmd(iop_base);
     return;
 }
 
+/*
+ * This function resets the chip and SCSI bus
+ *
+ * It is up to the caller to add a delay to let the bus settle after
+ * calling this function.
+ *
+ * The SCSI_CFG0, SCSI_CFG1, and MEM_CFG registers are set-up in
+ * AdvInitAsc3550Driver(). Here when doing a write to one of these
+ * registers read first and then write.
+ *
+ * Note: A SCSI Bus Reset can not be done until after the EEPROM
+ * configuration is read to determine whether SCSI Bus Resets
+ * should be performed.
+ */
+ASC_INITFUNC(
 STATIC void
-AscWriteLramDWord(
-                     PortAddr iop_base,
-                     ushort addr,
-                     ulong dword_val
+AdvResetChip(ADV_DVC_VAR *asc_dvc)
 )
 {
-    ushort              word_val;
-    AscSetChipLramAddr(iop_base, addr);
-    word_val = (ushort) dword_val;
-    AscSetChipLramData(iop_base, word_val);
-    word_val = (ushort) (dword_val >> 16);
-    AscSetChipLramData(iop_base, word_val);
-    return;
+    AdvPortAddr    iop_base;
+    ushort         word;
+    uchar          byte;
+
+    iop_base = asc_dvc->iop_base;
+
+    /*
+     * Reset Chip.
+     */
+    AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
+    DvcSleepMilliSecond(100);
+    AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_WR_IO_REG);
+
+    /*
+     * Initialize Chip registers.
+     * 
+     * Note: Don't remove the use of a temporary variable in the following
+     * code, otherwise the Microsoft C compiler will turn the following lines
+     * into a no-op.
+     */
+    byte = AdvReadByteRegister(iop_base, IOPB_MEM_CFG);
+    byte |= RAM_SZ_8KB;
+    AdvWriteByteRegister(iop_base, IOPB_MEM_CFG, byte);
+
+    word = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
+    word &= ~BIG_ENDIAN;
+    AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, word);
+
+    /*
+     * Setting the START_CTL_EMFU 3:2 bits sets a FIFO threshold
+     * of 128 bytes. This register is only accessible to the host.
+     */
+    AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
+        START_CTL_EMFU | READ_CMD_MRM);
 }
 
-STATIC void
-AscWriteLramByte(
-                    PortAddr iop_base,
-                    ushort addr,
-                    uchar byte_val
-)
+/* a_advlib.c */
+/*
+ * Description:
+ *      Send a SCSI request to the ASC3550 chip
+ *
+ * If there is no SG list for the request, set 'sg_entry_cnt' to 0.
+ *
+ * If 'sg_real_addr' is non-zero on entry, AscGetSGList() will not be
+ * called. It is assumed the caller has already initialized 'sg_real_addr'.
+ *
+ * Return:
+ *      ADV_SUCCESS(1) - the request is in the mailbox
+ *      ADV_BUSY(0) - total request count > 253, try later
+ *      ADV_ERROR(-1) - invalid scsi request Q
+ */
+STATIC int
+AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc,
+                ADV_SCSI_REQ_Q *scsiq)
 {
-    ushort              word_data;
-    if (isodd_word(addr)) {
-        addr--;
-        word_data = AscReadLramWord(iop_base, addr);
-        word_data &= 0x00FF;
-        word_data |= (((ushort) byte_val << 8) & 0xFF00);
-    } else {
-        word_data = AscReadLramWord(iop_base, addr);
-        word_data &= 0xFF00;
-        word_data |= ((ushort) byte_val & 0x00FF);
+    if (scsiq == (ADV_SCSI_REQ_Q *) 0L)
+    {
+        /* 'scsiq' should never be NULL. */
+        ADV_ASSERT(0);
+        return ADV_ERROR;
     }
-    AscWriteLramWord(iop_base, addr, word_data);
-    return;
+
+    return AdvSendScsiCmd(asc_dvc, scsiq);
+}
+
+/*
+ * Reset SCSI Bus and purge all outstanding requests.
+ *
+ * Return Value:
+ *      ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
+ *
+ * Note: Should always return ADV_TRUE.
+ */
+STATIC int
+AdvResetSB(ADV_DVC_VAR *asc_dvc)
+{
+    int         status;
+
+    status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET, 0L, 0);
+
+    AdvResetSCSIBus(asc_dvc);
+
+    return status;
 }
 
+/*
+ * Reset SCSI Bus and delay.
+ */
 STATIC void
-AscMemWordCopyToLram(
-                        PortAddr iop_base,
-                        ushort s_addr,
-                        ushort * s_buffer,
-                        int words
-)
+AdvResetSCSIBus(ADV_DVC_VAR *asc_dvc)
 {
-    AscSetChipLramAddr(iop_base, s_addr);
-    DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
-    return;
+    AdvPortAddr    iop_base;
+    ushort         scsi_ctrl;
+
+    iop_base = asc_dvc->iop_base;
+
+    /*
+     * The microcode currently sets the SCSI Bus Reset signal while
+     * handling the AscSendIdleCmd() IDLE_CMD_SCSI_RESET command above.
+     * But the SCSI Bus Reset Hold Time in the microcode is not deterministic
+     * (it may in fact be for less than the SCSI Spec. minimum of 25 us).
+     * Therefore on return the Adv Library sets the SCSI Bus Reset signal
+     * for ASC_SCSI_RESET_HOLD_TIME_US, which is defined to be greater
+     * than 25 us.
+     */
+    scsi_ctrl = AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL);
+    AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL,
+        scsi_ctrl | ADV_SCSI_CTRL_RSTOUT);
+    DvcDelayMicroSecond(asc_dvc, (ushort) ASC_SCSI_RESET_HOLD_TIME_US);
+    AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL,
+        scsi_ctrl & ~ADV_SCSI_CTRL_RSTOUT);
+
+    DvcSleepMilliSecond((ulong) asc_dvc->scsi_reset_wait * 1000);
 }
 
-STATIC void
-AscMemDWordCopyToLram(
-                         PortAddr iop_base,
-                         ushort s_addr,
-                         ulong * s_buffer,
-                         int dwords
-)
-{
-    AscSetChipLramAddr(iop_base, s_addr);
-    DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
-    return;
+
+/*
+ * Adv Library Interrupt Service Routine
+ *
+ *  This function is called by a driver's interrupt service routine.
+ *  The function disables and re-enables interrupts.
+ *
+ *  When a microcode idle command is completed, the ADV_DVC_VAR
+ *  'idle_cmd_done' field is set to ADV_TRUE.
+ *
+ *  Note: AdvISR() can be called when interrupts are disabled or even
+ *  when there is no hardware interrupt condition present. It will
+ *  always check for completed idle commands and microcode requests.
+ *  This is an important feature that shouldn't be changed because it
+ *  allows commands to be completed from polling mode loops.
+ *
+ * Return:
+ *   ADV_TRUE(1) - interrupt was pending
+ *   ADV_FALSE(0) - no interrupt was pending
+ */
+STATIC int
+AdvISR(ADV_DVC_VAR *asc_dvc)
+{
+    AdvPortAddr                 iop_base;
+    uchar                       int_stat;
+    ushort                      next_done_loc, target_bit;
+    int                         completed_q;
+    int                         flags;
+    ADV_SCSI_REQ_Q              *scsiq;
+    ASC_REQ_SENSE               *sense_data;
+    int                         ret;
+
+    flags = DvcEnterCritical();
+    iop_base = asc_dvc->iop_base;
+
+    if (AdvIsIntPending(iop_base))
+    {
+        ret = ADV_TRUE;
+    } else
+    {
+        ret = ADV_FALSE;
+    }
+
+    /* Reading the register clears the interrupt. */
+    int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
+
+    if (int_stat & ADV_INTR_STATUS_INTRB)
+    {
+        asc_dvc->idle_cmd_done = ADV_TRUE;
+    }
+
+    /*
+     * Notify the driver of a hardware detected SCSI Bus Reset.
+     */
+    if (int_stat & ADV_INTR_STATUS_INTRC)
+    {
+        if (asc_dvc->sbreset_callback != 0)
+        {
+            (*(ADV_SBRESET_CALLBACK) asc_dvc->sbreset_callback)(asc_dvc);
+        }
+    }
+
+    /*
+     * ASC_MC_HOST_NEXT_DONE (0x129) is actually the last completed RISC
+     * Queue List request. Its forward pointer (RQL_FWD) points to the
+     * current completed RISC Queue List request.
+     */
+    AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, next_done_loc);
+    next_done_loc = ASC_MC_RISC_Q_LIST_BASE +
+        (next_done_loc * ASC_MC_RISC_Q_LIST_SIZE) + RQL_FWD;
+
+    AdvReadByteLram(iop_base, next_done_loc, completed_q);
+
+    /* Loop until all completed Q's are processed. */
+    while (completed_q != ASC_MC_NULL_Q)
+    {
+        AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, completed_q);
+
+        next_done_loc = ASC_MC_RISC_Q_LIST_BASE +
+          (completed_q * ASC_MC_RISC_Q_LIST_SIZE);
+
+        /*
+         * Read the ADV_SCSI_REQ_Q virtual address pointer from
+         * the RISC list entry. The microcode has changed the
+         * ADV_SCSI_REQ_Q physical address to its virtual address.
+         *
+         * Refer to comments at the end of AdvSendScsiCmd() for
+         * more information on the RISC list structure.
+         */
+        {
+            ushort lsw, msw;
+            AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR, lsw);
+            AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR + 2, msw);
+
+            scsiq = (ADV_SCSI_REQ_Q *) (((ulong) msw << 16) | lsw);
+        }
+        ADV_ASSERT(scsiq != NULL);
+
+        target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
+
+        /*
+         * Clear request microcode control flag.
+         */
+        scsiq->cntl = 0;
+
+        /*
+         * Check Condition handling
+         */
+        if ((scsiq->done_status == QD_WITH_ERROR) &&
+            (scsiq->scsi_status == SS_CHK_CONDITION) &&
+            (sense_data = (ASC_REQ_SENSE *) scsiq->vsense_addr) != 0 &&
+            (scsiq->orig_sense_len - scsiq->sense_len) >= ASC_MIN_SENSE_LEN)
+        {
+            /*
+             * Command returned with a check condition and valid
+             * sense data.
+             */
+        }
+        /*
+         * If the command that completed was a SCSI INQUIRY and
+         * LUN 0 was sent the command, then process the INQUIRY
+         * command information for the device.
+         */
+        else if (scsiq->done_status == QD_NO_ERROR &&
+                   scsiq->cdb[0] == SCSICMD_Inquiry &&
+                   scsiq->target_lun == 0)
+        {
+            AdvInquiryHandling(asc_dvc, scsiq);
+        }
+
+        
+        /* Change the RISC Queue List state to free. */
+        AdvWriteByteLram(iop_base, next_done_loc + RQL_STATE, ASC_MC_QS_FREE);
+
+        /* Get the RISC Queue List forward pointer. */
+        AdvReadByteLram(iop_base, next_done_loc + RQL_FWD, completed_q);
+
+        /*
+         * Notify the driver of the completed request by passing
+         * the ADV_SCSI_REQ_Q pointer to its callback function.
+         */
+        ADV_ASSERT(asc_dvc->cur_host_qng > 0);
+        asc_dvc->cur_host_qng--;
+        scsiq->a_flag |= ADV_SCSIQ_DONE;
+        (*(ADV_ISR_CALLBACK) asc_dvc->isr_callback)(asc_dvc, scsiq);
+        /*
+         * Note: After the driver callback function is called, 'scsiq'
+         * can no longer be referenced.
+         *
+         * Fall through and continue processing other completed
+         * requests...
+         */
+
+        /*
+         * Disable interrupts again in case the driver inadvertently
+         * enabled interrupts in its callback function.
+         *
+         * The DvcEnterCritical() return value is ignored, because
+         * the 'flags' saved when AdvISR() was first entered will be
+         * used to restore the interrupt flag on exit.
+         */
+        (void) DvcEnterCritical();
+    }
+    DvcLeaveCritical(flags);
+    return ret;
 }
 
-STATIC void
-AscMemWordCopyFromLram(
-                          PortAddr iop_base,
-                          ushort s_addr,
-                          ushort * d_buffer,
-                          int words
-)
+/*
+ * Send an idle command to the chip and wait for completion.
+ *
+ * Interrupts do not have to be enabled on entry.
+ *
+ * Return Values:
+ *   ADV_TRUE - command completed successfully
+ *   ADV_FALSE - command failed
+ */
+STATIC int
+AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
+               ushort idle_cmd,
+               ulong idle_cmd_parameter,
+               int flags)
 {
-    AscSetChipLramAddr(iop_base, s_addr);
-    DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
-    return;
-}
+    int         last_int_level;
+    ulong       i;
+    AdvPortAddr iop_base;
+    int         ret;
 
-STATIC ulong
-AscMemSumLramWord(
-                     PortAddr iop_base,
-                     ushort s_addr,
-                     rint words
-)
-{
-    ulong               sum;
-    int                 i;
-    sum = 0L;
-    for (i = 0; i < words; i++, s_addr += 2) {
-        sum += AscReadLramWord(iop_base, s_addr);
+    asc_dvc->idle_cmd_done = 0;
+
+    last_int_level = DvcEnterCritical();
+    iop_base = asc_dvc->iop_base;
+
+    /*
+     * Write the idle command value after the idle command parameter
+     * has been written to avoid a race condition. If the order is not
+     * followed, the microcode may process the idle command before the
+     * parameters have been written to LRAM.
+     */
+    AdvWriteDWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, idle_cmd_parameter);
+    AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
+    DvcLeaveCritical(last_int_level);
+
+    /*
+     * If the 'flags' argument contains the ADV_NOWAIT flag, then
+     * return with success.
+     */
+    if (flags & ADV_NOWAIT)
+    {
+        return ADV_TRUE;
     }
-    return (sum);
-}
 
-STATIC void
-AscMemWordSetLram(
-                     PortAddr iop_base,
-                     ushort s_addr,
-                     ushort set_wval,
-                     rint words
-)
-{
-    rint             i;
-    AscSetChipLramAddr(iop_base, s_addr);
-    for (i = 0; i < words; i++) {
-        AscSetChipLramData(iop_base, set_wval);
+    for (i = 0; i < SCSI_WAIT_10_SEC * SCSI_MS_PER_SEC; i++)
+    {
+        /*
+         * 'idle_cmd_done' is set by AdvISR().
+         */
+        if (asc_dvc->idle_cmd_done)
+        {
+            break;
+        }
+        DvcSleepMilliSecond(1);
+
+        /*
+         * If interrupts were disabled on entry to AdvSendIdleCmd(),
+         * then they will still be disabled here. Call AdvISR() to
+         * check for the idle command completion.
+         */
+        (void) AdvISR(asc_dvc);
     }
-    return;
-}
 
+    last_int_level = DvcEnterCritical();
 
-STATIC int
-AscScsiInquiry(
-                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                  REG ASC_SCSI_REQ_Q * scsiq,
-                  uchar * buf,
-                  int buf_len
-)
-{
-    if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf,
-                         (ulong) buf_len) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    if (asc_dvc->idle_cmd_done == ADV_FALSE)
+    {
+        ADV_ASSERT(0); /* The idle command should never timeout. */
+        return ADV_FALSE;
+    } else
+    {
+        AdvReadWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, ret);
+        return ret;
     }
-    scsiq->cdb[0] = (uchar) SCSICMD_Inquiry;
-    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
-    scsiq->cdb[2] = 0;
-    scsiq->cdb[3] = 0;
-    scsiq->cdb[4] = buf_len;
-    scsiq->cdb[5] = 0;
-    scsiq->r2.cdb_len = 6;
-    return (0);
 }
 
+/*
+ * Send the SCSI request block to the adapter
+ *
+ * Each of the 255 Adv Library/Microcode RISC Lists or mailboxes has the
+ * following structure:
+ *
+ * 0: RQL_FWD - RISC list forward pointer (1 byte)
+ * 1: RQL_BWD - RISC list backward pointer (1 byte)
+ * 2: RQL_STATE - RISC list state byte - free, ready, done, aborted (1 byte)
+ * 3: RQL_TID - request target id (1 byte)
+ * 4: RQL_PHYADDR - ADV_SCSI_REQ_Q physical pointer (4 bytes)
+ *
+ * Return:
+ *      ADV_SUCCESS(1) - the request is in the mailbox
+ *      ADV_BUSY(0) - total request count > 253, try later
+ */
 STATIC int
-AscScsiReadCapacity(
-                       REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                       REG ASC_SCSI_REQ_Q * scsiq,
-                       uchar * info
-)
+AdvSendScsiCmd(
+    ADV_DVC_VAR *asc_dvc,
+    ADV_SCSI_REQ_Q  *scsiq)
 {
-    if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    ushort                 next_ready_loc;
+    uchar                  next_ready_loc_fwd;
+    int                    last_int_level;
+    AdvPortAddr            iop_base;
+    long                   req_size;
+    ulong                  q_phy_addr;
+
+    /*
+     * The ADV_SCSI_REQ_Q 'target_id' field should never be equal
+     * to the host adapter ID or exceed ADV_MAX_TID.
+     */
+    if (scsiq->target_id == asc_dvc->chip_scsi_id ||
+        scsiq->target_id > ADV_MAX_TID)
+    {
+        scsiq->host_status = QHSTA_M_INVALID_DEVICE;
+        scsiq->done_status = QD_WITH_ERROR;
+        return ADV_ERROR;
     }
-    scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity;
-    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
-    scsiq->cdb[2] = 0;
-    scsiq->cdb[3] = 0;
-    scsiq->cdb[4] = 0;
-    scsiq->cdb[5] = 0;
-    scsiq->cdb[6] = 0;
-    scsiq->cdb[7] = 0;
-    scsiq->cdb[8] = 0;
-    scsiq->cdb[9] = 0;
-    scsiq->r2.cdb_len = 10;
-    return (0);
-}
 
-STATIC int
-AscScsiTestUnitReady(
-                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                        REG ASC_SCSI_REQ_Q * scsiq
-)
-{
-    if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR,
-                         (ulong) 0L) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    iop_base = asc_dvc->iop_base;
+
+    last_int_level = DvcEnterCritical();
+
+    if (asc_dvc->cur_host_qng >= asc_dvc->max_host_qng)
+    {
+        DvcLeaveCritical(last_int_level);
+        return ADV_BUSY;
+    } else
+    {
+        ADV_ASSERT(asc_dvc->cur_host_qng < ASC_MC_RISC_Q_TOTAL_CNT);
+        asc_dvc->cur_host_qng++;
     }
-    scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
-    scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady;
-    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
-    scsiq->cdb[2] = 0;
-    scsiq->cdb[3] = 0;
-    scsiq->cdb[4] = 0;
-    scsiq->cdb[5] = 0;
-    scsiq->r2.cdb_len = 6;
-    return (0);
+
+    /*
+     * Clear the ADV_SCSI_REQ_Q done flag.
+     */
+    scsiq->a_flag &= ~ADV_SCSIQ_DONE;
+
+    /*
+     * Save the original sense buffer length.
+     *
+     * After the request completes 'sense_len' will be set to the residual
+     * byte count of the Auto-Request Sense if a command returns CHECK
+     * CONDITION and the Sense Data is valid indicated by 'host_status' not
+     * being set to QHSTA_M_AUTO_REQ_SENSE_FAIL. To determine the valid
+     * Sense Data Length subtract 'sense_len' from 'orig_sense_len'.
+     */
+    scsiq->orig_sense_len = scsiq->sense_len;
+
+    AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc);
+    next_ready_loc = ASC_MC_RISC_Q_LIST_BASE +
+        (next_ready_loc * ASC_MC_RISC_Q_LIST_SIZE);
+
+    /*
+     * Write the physical address of the Q to the mailbox.
+     * We need to skip the first four bytes, because the microcode
+     * uses them internally for linking Q's together.
+     */
+    req_size = sizeof(ADV_SCSI_REQ_Q);
+    q_phy_addr = DvcGetPhyAddr(asc_dvc, scsiq,
+                    (uchar *) scsiq, &req_size,
+                    ADV_IS_SCSIQ_FLAG);
+    ADV_ASSERT(ADV_DWALIGN(q_phy_addr) == q_phy_addr);
+    ADV_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q));
+
+    scsiq->scsiq_ptr = (ADV_SCSI_REQ_Q *) scsiq;
+
+    /*
+     * The RISC list structure, which 'next_ready_loc' is a pointer
+     * to in microcode LRAM, has the format detailed in the comment
+     * header for this function.
+     *
+     * Write the ADV_SCSI_REQ_Q physical pointer to 'next_ready_loc' request.
+     */
+    AdvWriteDWordLram(iop_base, next_ready_loc + RQL_PHYADDR, q_phy_addr);
+
+    /* Write target_id to 'next_ready_loc' request. */
+    AdvWriteByteLram(iop_base, next_ready_loc + RQL_TID, scsiq->target_id);
+
+    /*
+     * Set the ASC_MC_HOST_NEXT_READY (0x128) microcode variable to
+     * the 'next_ready_loc' request forward pointer.
+     *
+     * Do this *before* changing the 'next_ready_loc' queue to QS_READY.
+     * After the state is changed to QS_READY 'RQL_FWD' will be changed
+     * by the microcode.
+     *
+     * NOTE: The temporary variable 'next_ready_loc_fwd' is required to
+     * prevent some compilers from optimizing out 'AdvReadByteLram()' if
+     * it were used as the 3rd argument to 'AdvWriteByteLram()'.
+     */
+    AdvReadByteLram(iop_base, next_ready_loc + RQL_FWD, next_ready_loc_fwd);
+    AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc_fwd);
+
+    /*
+     * Change the state of 'next_ready_loc' request from QS_FREE to
+     * QS_READY which will cause the microcode to pick it up and
+     * execute it.
+     *
+     * Can't reference 'next_ready_loc' after changing the request
+     * state to QS_READY. The microcode now owns the request.
+     */
+    AdvWriteByteLram(iop_base, next_ready_loc + RQL_STATE, ASC_MC_QS_READY);
+
+    DvcLeaveCritical(last_int_level);
+    return ADV_SUCCESS;
 }
 
-STATIC int
-AscScsiStartStopUnit(
-                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                        REG ASC_SCSI_REQ_Q * scsiq,
-                        uchar op_mode
-)
+/*
+ * Inquiry Information Byte 7 Handling
+ *
+ * Handle SCSI Inquiry Command information for a device by setting
+ * microcode operating variables that affect WDTR, SDTR, and Tag 
+ * Queuing.
+ */
+STATIC void
+AdvInquiryHandling(
+    ADV_DVC_VAR          *asc_dvc,
+    ADV_SCSI_REQ_Q       *scsiq)
 {
-    if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
+    AdvPortAddr          iop_base;
+    uchar                tid;
+    ASC_SCSI_INQUIRY     *inq;
+    ushort               tidmask;
+    ushort               cfg_word;
+
+    /*
+     * AdvInquiryHandling() requires up to INQUIRY information Byte 7
+     * to be available.
+     *
+     * If less than 8 bytes of INQUIRY information were requested or less
+     * than 8 bytes were transferred, then return. cdb[4] is the request
+     * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the
+     * microcode to the transfer residual count.
+     */
+    if (scsiq->cdb[4] < 8 || (scsiq->cdb[4] - scsiq->data_cnt) < 8)
+    {
+        return;
+    }
+
+    iop_base = asc_dvc->iop_base;
+    tid = scsiq->target_id;
+    inq = (ASC_SCSI_INQUIRY *) scsiq->vdata_addr;
+
+    /*
+     * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices.
+     */
+    if (inq->byte3.rsp_data_fmt < 2 && inq->byte2.ansi_apr_ver < 2)
+    {
+        return;
+    } else
+    {
+        /*
+         * INQUIRY Byte 7 Handling
+         *
+         * Use a device's INQUIRY byte 7 to determine whether it
+         * supports WDTR, SDTR, and Tag Queuing. If the feature
+         * is enabled in the EEPROM and the device supports the
+         * feature, then enable it in the microcode.
+         */
+
+        tidmask = ADV_TID_TO_TIDMASK(tid);
+
+        /*
+         * Wide Transfers
+         *
+         * If the EEPROM enabled WDTR for the device and the device
+         * supports wide bus (16 bit) transfers, then turn on the
+         * device's 'wdtr_able' bit and write the new value to the
+         * microcode.
+         */
+        if ((asc_dvc->wdtr_able & tidmask) && inq->byte7.WBus16)
+        {
+            AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
+            if ((cfg_word & tidmask) == 0)
+            {
+                cfg_word |= tidmask;
+                AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
+
+                /*
+                 * Clear the microcode "WDTR negotiation" done indicator
+                 * for the target to cause it to negotiate with the new
+                 * setting set above.
+                 */
+                AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
+                cfg_word &= ~tidmask;
+                AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
+            }
+        }
+
+        /*
+         * Synchronous Transfers
+         *
+         * If the EEPROM enabled SDTR for the device and the device
+         * supports synchronous transfers, then turn on the device's
+         * 'sdtr_able' bit. Write the new value to the microcode.
+         */
+        if ((asc_dvc->sdtr_able & tidmask) && inq->byte7.Sync)
+        {
+            AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
+            if ((cfg_word & tidmask) == 0)
+            {
+                cfg_word |= tidmask;
+                AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
+
+                /*
+                 * Clear the microcode "SDTR negotiation" done indicator
+                 * for the target to cause it to negotiate with the new
+                 * setting set above.
+                 */
+                AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
+                cfg_word &= ~tidmask;
+                AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
+            }
+        }
+
+        /*
+         * If the EEPROM enabled Tag Queuing for device and the
+         * device supports Tag Queuing, then turn on the device's
+         * 'tagqng_enable' bit in the microcode and set the microcode
+         * maximum command count to the ADV_DVC_VAR 'max_dvc_qng'
+         * value.
+         *
+         * Tag Queuing is disabled for the BIOS which runs in polled
+         * mode and would see no benefit from Tag Queuing. Also by
+         * disabling Tag Queuing in the BIOS devices with Tag Queuing
+         * bugs will at least work with the BIOS.
+         */
+        if ((asc_dvc->tagqng_able & tidmask) && inq->byte7.CmdQue)
+        {
+            AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
+            cfg_word |= tidmask;
+            AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
+            AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
+                asc_dvc->max_dvc_qng);
+        }
     }
-    scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
-    scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit;
-    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
-    scsiq->cdb[2] = 0;
-    scsiq->cdb[3] = 0;
-    scsiq->cdb[4] = op_mode;
-    scsiq->cdb[5] = 0;
-    scsiq->r2.cdb_len = 6;
-    return (0);
 }
index 54858404aadea0e7527f09a1fecc8da65f3acb17..010cd6153cd308df58b3998fd22c328d8717d07c 100644 (file)
@@ -1,9 +1,9 @@
-/* $Id: advansys.h,v 1.6 1997/05/30 19:25:12 davem Exp $ */
+/* $Id: advansys.h,v 1.17 1998/01/08 21:23:49 bobf Exp bobf $ */
 
 /*
  * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters
  * 
- * Copyright (c) 1995-1997 Advanced System Products, Inc.
+ * Copyright (c) 1995-1998 Advanced System Products, Inc.
  * All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -18,7 +18,7 @@
  *  ftp://ftp.advansys.com/pub/linux
  *
  * Please send questions, comments, bug reports to:
- * bobf@advansys.com (Bob Frey)
+ *  bobf@advansys.com (Bob Frey)
  */
 
 #ifndef _ADVANSYS_H
@@ -40,10 +40,18 @@ const char *advansys_info(struct Scsi_Host *);
 int advansys_command(Scsi_Cmnd *);
 int advansys_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
 int advansys_abort(Scsi_Cmnd *);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+int advansys_reset(Scsi_Cmnd *);
+#else /* version >= v1.3.89 */
 int advansys_reset(Scsi_Cmnd *, unsigned int);
+#endif /* version >= v1.3.89 */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+int advansys_biosparam(Disk *, int, int[]);
+#else /* version >= v1.3.0 */
 int advansys_biosparam(Disk *, kdev_t, int[]);
 extern struct proc_dir_entry proc_scsi_advansys;
 int advansys_proc_info(char *, char **, off_t, int, int, int);
+#endif /* version >= v1.3.0 */
 
 /* init/main.c setup function */
 void advansys_setup(char *, int *);
@@ -51,31 +59,116 @@ void advansys_setup(char *, int *);
 /*
  * AdvanSys Host Driver Scsi_Host_Template (struct SHT) from hosts.h.
  */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
 #define ADVANSYS { \
-                       proc_dir:     &proc_scsi_advansys,       \
-                       proc_info:    advansys_proc_info,        \
-                       name:         "advansys",                \
-                       detect:       advansys_detect,           \
-                       release:      advansys_release,          \
-                       info:         advansys_info,             \
-                       command:      advansys_command,          \
-                       queuecommand: advansys_queuecommand,     \
-                       abort:        advansys_abort,            \
-                       reset:        advansys_reset,            \
-                       bios_param:    advansys_biosparam,       \
-       /*                                                       \
-        * Because the driver may control an ISA adapter 'unchecked_isa_dma' \
-        * must be set. The flag will be cleared in advansys_detect for non-ISA \
-        * adapters. Refer to the comment in scsi_module.c for more information. \
-        */                                                      \
-                       unchecked_isa_dma: 1,                    \
-       /*                                                       \
-        * All adapters controlled by this driver are capable of large \
-        * scatter-gather lists. According to the mid-level SCSI documentation \
-        * this obviates any performance gain provided by setting \
-        * 'use_clustering'. But empirically while CPU utilization is increased \
-        * by enabling clustering, I/O throughput increases as well. \
-        */                                                      \
-                       use_clustering: ENABLE_CLUSTERING,       \
+    NULL,                     /* struct SHT *next */ \
+    NULL,                     /* int *usage_count */ \
+    "advansys",               /* char *name */ \
+    advansys_detect,          /* int (*detect)(struct SHT *) */ \
+    advansys_release,         /* int (*release)(struct Scsi_Host *) */ \
+    advansys_info,            /* const char *(*info)(struct Scsi_Host *) */ \
+    advansys_command,         /* int (*command)(Scsi_Cmnd *) */ \
+    advansys_queuecommand, \
+            /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \
+    advansys_abort,           /* int (*abort)(Scsi_Cmnd *) */ \
+    advansys_reset,           /* int (*reset)(Scsi_Cmnd *) */ \
+    NULL,                     /* int (*slave_attach)(int, int) */ \
+    advansys_biosparam,       /* int (* bios_param)(Disk *, int, int []) */ \
+    /* \
+     * The following fields are set per adapter in advansys_detect(). \
+     */ \
+    0,                        /* int can_queue */ \
+    0,                        /* int this_id */ \
+    0,                        /* short unsigned int sg_tablesize */ \
+    0,                        /* short cmd_per_lun */ \
+    0,                        /* unsigned char present */    \
+    /* \
+     * Because the driver may control an ISA adapter 'unchecked_isa_dma' \
+     * must be set. The flag will be cleared in advansys_detect for non-ISA \
+     * adapters. Refer to the comment in scsi_module.c for more information. \
+     */ \
+    1,                        /* unsigned unchecked_isa_dma:1 */ \
+    /* \
+     * All adapters controlled by this driver are capable of large \
+     * scatter-gather lists. According to the mid-level SCSI documentation \
+     * this obviates any performance gain provided by setting \
+     * 'use_clustering'. But empirically while CPU utilization is increased \
+     * by enabling clustering, I/O throughput increases as well. \
+     */ \
+    ENABLE_CLUSTERING,        /* unsigned use_clustering:1 */ \
 }
+#elif LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,75)
+#define ADVANSYS { \
+    NULL,                    /* struct SHT *next */ \
+    NULL, \
+        /* version < v2.1.23 long *usage_count */ \
+        /* version >= v2.1.23 struct module * */ \
+    &proc_scsi_advansys,     /* struct proc_dir_entry *proc_dir */ \
+    advansys_proc_info,    \
+        /* int (*proc_info)(char *, char **, off_t, int, int, int) */ \
+    "advansys",              /* const char *name */ \
+    advansys_detect,         /* int (*detect)(struct SHT *) */ \
+    advansys_release,        /* int (*release)(struct Scsi_Host *) */ \
+    advansys_info,           /* const char *(*info)(struct Scsi_Host *) */ \
+    advansys_command,        /* int (*command)(Scsi_Cmnd *) */ \
+    advansys_queuecommand, \
+        /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \
+    advansys_abort,          /* int (*abort)(Scsi_Cmnd *) */ \
+    advansys_reset, \
+        /* version < v1.3.89 int (*reset)(Scsi_Cmnd *) */ \
+        /* version >= v1.3.89 int (*reset)(Scsi_Cmnd *, unsigned int) */ \
+    NULL,                    /* int (*slave_attach)(int, int) */ \
+    advansys_biosparam,      /* int (* bios_param)(Disk *, kdev_t, int []) */ \
+    /* \
+     * The following fields are set per adapter in advansys_detect(). \
+     */ \
+    0,                        /* int can_queue */ \
+    0,                        /* int this_id */ \
+    0,                        /* short unsigned int sg_tablesize */ \
+    0,                        /* short cmd_per_lun */ \
+    0,                        /* unsigned char present */    \
+    /* \
+     * Because the driver may control an ISA adapter 'unchecked_isa_dma' \
+     * must be set. The flag will be cleared in advansys_detect for non-ISA \
+     * adapters. Refer to the comment in scsi_module.c for more information. \
+     */ \
+    1,                        /* unsigned unchecked_isa_dma:1 */ \
+    /* \
+     * All adapters controlled by this driver are capable of large \
+     * scatter-gather lists. According to the mid-level SCSI documentation \
+     * this obviates any performance gain provided by setting \
+     * 'use_clustering'. But empirically while CPU utilization is increased \
+     * by enabling clustering, I/O throughput increases as well. \
+     */ \
+    ENABLE_CLUSTERING,        /* unsigned use_clustering:1 */ \
+}
+#else /* version >= v2.1.75 */
+#define ADVANSYS { \
+    proc_dir:     &proc_scsi_advansys, \
+    proc_info:    advansys_proc_info, \
+    name:         "advansys", \
+    detect:       advansys_detect, \
+    release:      advansys_release, \
+    info:         advansys_info, \
+    command:      advansys_command, \
+    queuecommand: advansys_queuecommand, \
+    abort:        advansys_abort, \
+    reset:        advansys_reset, \
+    bios_param:    advansys_biosparam, \
+    /* \
+     * Because the driver may control an ISA adapter 'unchecked_isa_dma' \
+     * must be set. The flag will be cleared in advansys_detect for non-ISA \
+     * adapters. Refer to the comment in scsi_module.c for more information. \
+     */ \
+    unchecked_isa_dma: 1, \
+    /* \
+     * All adapters controlled by this driver are capable of large \
+     * scatter-gather lists. According to the mid-level SCSI documentation \
+     * this obviates any performance gain provided by setting \
+     * 'use_clustering'. But empirically while CPU utilization is increased \
+     * by enabling clustering, I/O throughput increases as well. \
+     */ \
+    use_clustering: ENABLE_CLUSTERING, \
+}
+#endif /* version >= v2.1.75 */
 #endif /* _ADVANSYS_H */
index 415cc8794141d1d1099e4f4f4fdcc7cd99b0d63b..ab8458d1df8757c87e7ba407d07babc2eb5bde04 100644 (file)
@@ -209,7 +209,7 @@ extern struct proc_dir_entry Proc_Scsi_Pci2000;
                  queuecommand:   Pci2000_QueueCommand,                 \
                  abort:          Pci2000_Abort,                        \
                  reset:          Pci2000_Reset,                        \
-                 biosparam:      Pci2000_BiosParam,                    \
+                 bios_param:     Pci2000_BiosParam,                    \
                  can_queue:      16,                                   \
                  this_id:        -1,                                   \
                  sg_tablesize:   16,                                   \
index 1658135be1a736dc8f63a788201bf3a5b8a1d216..1a9bd6cad4400bd1f45e3f49b8683287a8fbc4a6 100644 (file)
@@ -328,7 +328,7 @@ extern struct proc_dir_entry Proc_Scsi_Pci2220i;
                  queuecommand:   Pci2220i_QueueCommand,                \
                  abort:          Pci2220i_Abort,                       \
                  reset:          Pci2220i_Reset,                       \
-                 biosparam:      Pci2220i_BiosParam,                   \
+                 bios_param:     Pci2220i_BiosParam,                   \
                  can_queue:      1,                                    \
                  this_id:        -1,                                   \
                  sg_tablesize:   SG_NONE,                              \
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
new file mode 100644 (file)
index 0000000..3b4598a
--- /dev/null
@@ -0,0 +1,313 @@
+/* pluto.c: SparcSTORAGE Array SCSI host adapter driver.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "../fc4/fcp_scsi.h"
+#include "pluto.h"
+
+#include <linux/module.h>
+
+/* #define PLUTO_DEBUG */
+
+#define pluto_printk printk ("PLUTO %s: ", fc->name); printk
+
+#ifdef PLUTO_DEBUG
+#define PLD(x)  pluto_printk x;
+#define PLND(x) printk ("PLUTO: "); printk x;
+#else
+#define PLD(x)
+#define PLND(x)
+#endif
+
+struct proc_dir_entry proc_scsi_pluto = {
+       PROC_SCSI_PLUTO, 5, "pluto",
+       S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+static struct ctrl_inquiry {
+       struct Scsi_Host host;
+       struct pluto pluto;
+       Scsi_Cmnd cmd;
+       char inquiry[256];
+       fc_channel *fc;
+} *fcs __initdata;
+static int fcscount __initdata;
+static atomic_t fcss __initdata;
+static struct timer_list fc_timer __initdata = { 0 };
+struct semaphore fc_sem __initdata = MUTEX_LOCKED;
+
+static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr);
+
+__initfunc(static void pluto_detect_timeout(unsigned long data))
+{
+       PLND(("Timeout\n"))
+       up(&fc_sem);
+}
+
+__initfunc(static void pluto_detect_done(Scsi_Cmnd *SCpnt))
+{
+       /* Do nothing */
+}
+
+__initfunc(static void pluto_detect_scsi_done(Scsi_Cmnd *SCpnt))
+{
+       SCpnt->request.rq_status = RQ_SCSI_DONE;
+       PLND(("Detect done %08lx\n", (long)SCpnt))
+       if (atomic_dec_and_test (&fcss))
+               up(&fc_sem);
+}
+
+static void pluto_select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist)
+{
+       Scsi_Device *device;
+       
+       for (device = devlist; device; device = device->next) {
+               if (device->host != host) continue;
+               if (device->tagged_supported)
+                       device->queue_depth = /* 254 */ 8;
+               else
+                       device->queue_depth = 2;
+       }
+}
+
+/* Detect all SSAs attached to the machine.
+   To be fast, do it on all online FC channels at the same time. */
+__initfunc(int pluto_detect(Scsi_Host_Template *tpnt))
+{
+       int i, retry, nplutos;
+       fc_channel *fc;
+       Scsi_Device dev;
+
+       tpnt->proc_dir = &proc_scsi_pluto;
+       fcscount = 0;
+       for_each_online_fc_channel(fc)
+               fcscount++;
+       PLND(("%d channels online\n", fcscount))
+       if (!fcscount)
+               return 0;
+       fcs = (struct ctrl_inquiry *) scsi_init_malloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
+       if (!fcs) {
+               printk ("PLUTO: Not enough memory to probe\n");
+               return 0;
+       }
+       
+       memset (fcs, 0, sizeof (struct ctrl_inquiry) * fcscount);
+       memset (&dev, 0, sizeof(dev));
+       atomic_set (&fcss, fcscount);
+       fc_timer.function = pluto_detect_timeout;
+       
+       i = 0;
+       for_each_online_fc_channel(fc) {
+               Scsi_Cmnd *SCpnt;
+               struct Scsi_Host *host;
+               struct pluto *pluto;
+               
+               if (i == fcscount) break;
+               
+               PLD(("trying to find SSA\n"))
+
+               /* If this is already registered to some other SCSI host, then it cannot be pluto */
+               if (fc->scsi_name[0]) continue;
+               memcpy (fc->scsi_name, "SSA", 4);
+               
+               fcs[i].fc = fc;
+               
+               fc->can_queue = PLUTO_CAN_QUEUE;
+               fc->rsp_size = 64;
+               fc->encode_addr = pluto_encode_addr;
+               
+               fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
+       
+               SCpnt = &(fcs[i].cmd);
+               host = &(fcs[i].host);
+               pluto = (struct pluto *)host->hostdata;
+               
+               pluto->fc = fc;
+       
+               SCpnt->host = host;
+               SCpnt->cmnd[0] = INQUIRY;
+               SCpnt->cmnd[4] = 255;
+               
+               /* FC layer requires this, so that SCpnt->device->tagged_supported is initially 0 */
+               SCpnt->device = &dev;
+               
+               SCpnt->cmd_len = COMMAND_SIZE(INQUIRY);
+       
+               SCpnt->request.rq_status = RQ_SCSI_BUSY;
+               
+               SCpnt->done = pluto_detect_done;
+               SCpnt->bufflen = 256;
+               SCpnt->buffer = fcs[i].inquiry;
+               SCpnt->request_bufflen = 256;
+               SCpnt->request_buffer = fcs[i].inquiry;
+               PLD(("set up %d %08lx\n", i, (long)SCpnt))
+               i++;
+       }
+       
+       for (retry = 0; retry < 5; retry++) {
+               for (i = 0; i < fcscount; i++) {
+                       if (!fcs[i].fc) break;
+                       if (fcs[i].cmd.request.rq_status != RQ_SCSI_DONE) {
+                               disable_irq(fcs[i].fc->irq);
+                               PLND(("queuecommand %d %d\n", retry, i))
+                               fcp_scsi_queuecommand (&(fcs[i].cmd), 
+                                       pluto_detect_scsi_done);
+                               enable_irq(fcs[i].fc->irq);
+                       }
+               }
+           
+               fc_timer.expires = jiffies + 10 * HZ;
+               add_timer(&fc_timer);
+               
+               down(&fc_sem);
+               PLND(("Woken up\n"))
+               if (!atomic_read(&fcss))
+                       break; /* All fc channels have answered us */
+       }
+       del_timer(&fc_timer);
+
+       PLND(("Finished search\n"))
+       for (i = 0, nplutos = 0; i < fcscount; i++) {
+               Scsi_Cmnd *SCpnt;
+               
+               if (!(fc = fcs[i].fc)) break;
+       
+               SCpnt = &(fcs[i].cmd);
+               
+               /* Let FC mid-level free allocated resources */
+               SCpnt->done (SCpnt);
+               
+               if (!SCpnt->result) {
+                       struct pluto_inquiry *inq;
+                       struct pluto *pluto;
+                       struct Scsi_Host *host;
+                       
+                       inq = (struct pluto_inquiry *)fcs[i].inquiry;
+
+                       if ((inq->dtype & 0x1f) == TYPE_PROCESSOR &&
+                           !strncmp (inq->vendor_id, "SUN", 3) &&
+                           !strncmp (inq->product_id, "SSA", 3)) {
+                               char *p;
+                               long *ages;
+                               
+                               ages = kmalloc (((inq->channels + 1) * inq->targets) * sizeof(long), GFP_KERNEL);
+                               if (!ages) continue;
+                               
+                               host = scsi_register (tpnt, sizeof (struct pluto));
+                               if (!host) panic ("Cannot register PLUTO host\n");
+                               
+                               nplutos++;
+                               
+                               pluto = (struct pluto *)host->hostdata;
+                               
+                               host->max_id = inq->targets;
+                               host->max_channel = inq->channels;
+                               host->irq = fc->irq;
+                               
+                               host->select_queue_depths = pluto_select_queue_depths;
+                               
+                               fc->channels = inq->channels + 1;
+                               fc->targets = inq->targets;
+                               fc->ages = ages;
+                               memset (ages, 0, ((inq->channels + 1) * inq->targets) * sizeof(long));
+                               
+                               pluto->fc = fc;
+                               memcpy (pluto->rev_str, inq->revision, 4);
+                               pluto->rev_str[4] = 0;
+                               p = strchr (pluto->rev_str, ' ');
+                               if (p) *p = 0;
+                               memcpy (pluto->fw_rev_str, inq->fw_revision, 4);
+                               pluto->fw_rev_str[4] = 0;
+                               p = strchr (pluto->fw_rev_str, ' ');
+                               if (p) *p = 0;
+                               memcpy (pluto->serial_str, inq->serial, 12);
+                               pluto->serial_str[12] = 0;
+                               p = strchr (pluto->serial_str, ' ');
+                               if (p) *p = 0;
+                               
+                               PLD(("Found SSA rev %s fw rev %s serial %s %dx%d\n", pluto->rev_str, pluto->fw_rev_str, pluto->serial_str, host->max_channel, host->max_id))
+                       } else
+                               fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
+               } else
+                       fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
+       }
+       scsi_init_free((char *)fcs, sizeof (struct ctrl_inquiry) * fcscount);
+       if (nplutos)
+               printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos);
+       return nplutos;
+}
+
+int pluto_release(struct Scsi_Host *host)
+{
+       struct pluto *pluto = (struct pluto *)host->hostdata;
+       fc_channel *fc = pluto->fc;
+       
+       fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
+       kfree (fc->ages);
+       return 0;
+}
+
+const char *pluto_info(struct Scsi_Host *host)
+{
+       static char buf[80];
+       struct pluto *pluto = (struct pluto *) host->hostdata;
+
+       sprintf(buf, "SUN SparcSTORAGE Array %s fw %s serial %s %dx%d on %s",
+               pluto->rev_str, pluto->fw_rev_str, pluto->serial_str,
+               host->max_channel, host->max_id, pluto->fc->name);
+       return buf;
+}
+
+/* SSA uses this FC4S addressing:
+   switch (addr[0])
+   {
+   case 0: CONTROLLER - All of addr[1]..addr[3] has to be 0
+   case 1: SINGLE DISK - addr[1] channel, addr[2] id, addr[3] 0
+   case 2: DISK GROUP - ???
+   }
+   
+   So that SCSI mid-layer can access to these, we reserve
+   channel 0 id 0 lun 0 for CONTROLLER
+   and channels 1 .. max_channel are normal single disks.
+ */
+static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr)
+{
+       PLND(("encode addr %d %d %d\n", SCpnt->channel, SCpnt->target, SCpnt->cmnd[1] & 0xe0))
+       /* We don't support LUNs */
+       if (SCpnt->cmnd[1] & 0xe0) return -EINVAL;
+       if (!SCpnt->channel) {
+               if (SCpnt->target) return -EINVAL;
+               memset (addr, 0, 4 * sizeof(u16));
+       } else {
+               addr[0] = 1;
+               addr[1] = SCpnt->channel - 1;
+               addr[2] = SCpnt->target;
+               addr[3] = 0;
+       }
+       PLND(("trying %04x%04x%04x%04x\n", addr[0], addr[1], addr[2], addr[3]))
+       return 0;
+}
+
+#ifdef MODULE
+
+Scsi_Host_Template driver_template = PLUTO;
+
+#include "scsi_module.c"
+
+EXPORT_NO_SYMBOLS;
+#endif /* MODULE */
diff --git a/drivers/scsi/pluto.h b/drivers/scsi/pluto.h
new file mode 100644 (file)
index 0000000..6dbda6a
--- /dev/null
@@ -0,0 +1,59 @@
+/* pluto.h: SparcSTORAGE Array SCSI host adapter driver definitions.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef _PLUTO_H
+#define _PLUTO_H
+
+#include "../fc4/fcp_scsi.h"
+
+struct pluto {
+       /* This must be first */
+       fc_channel      *fc;
+       char            rev_str[5];
+       char            fw_rev_str[5];
+       char            serial_str[13];
+};
+
+struct pluto_inquiry {
+       u8      dtype;
+       u8      removable:1, qualifier:7;
+       u8      iso:2, ecma:3, ansi:3;
+       u8      aenc:1, trmiop:1, :2, rdf:4;
+       u8      len;
+       u8      xxx1;
+       u8      xxx2;
+       u8      reladdr:1, wbus32:1, wbus16:1, sync:1, linked:1, :1, cmdque:1, softreset:1;
+       u8      vendor_id[8];
+       u8      product_id[16];
+       u8      revision[4];
+       u8      fw_revision[4];
+       u8      serial[12];
+       u8      xxx3[2];
+       u8      channels;
+       u8      targets;
+};
+
+/* This is the max number of outstanding SCSI commands per pluto */
+#define PLUTO_CAN_QUEUE                254
+
+int pluto_detect(Scsi_Host_Template *);
+int pluto_release(struct Scsi_Host *);
+const char * pluto_info(struct Scsi_Host *);
+
+#define PLUTO {                                                        \
+       detect:                 pluto_detect,                   \
+       release:                pluto_release,                  \
+       info:                   pluto_info,                     \
+       queuecommand:           fcp_scsi_queuecommand,          \
+       abort:                  fcp_scsi_abort,                 \
+       reset:                  fcp_scsi_reset,                 \
+       can_queue:              PLUTO_CAN_QUEUE,                \
+       this_id:                -1,                             \
+       sg_tablesize:           1,                              \
+       cmd_per_lun:            1,                              \
+       use_clustering:         ENABLE_CLUSTERING               \
+}      
+
+#endif /* !(_PLUTO_H) */
index 0580c758cdebec229eed4ac85cb57913990696b8..1aed96ec7d47f40eff7d9bf38fe8175e10199a26 100644 (file)
@@ -327,7 +327,7 @@ extern struct proc_dir_entry Proc_Scsi_Psi240i;
                  queuecommand:   Psi240i_QueueCommand,         \
                  abort:          Psi240i_Abort,                        \
                  reset:          Psi240i_Reset,                        \
-                 biosparam:      Psi240i_BiosParam,                    \
+                 bios_param:     Psi240i_BiosParam,                    \
                  can_queue:      1,                                    \
                  this_id:        -1,                                   \
                  sg_tablesize:   SG_NONE,                              \
index 91f0eb3fe8f7162e93cd8f726b1b0b3f474fa40a..262c6da585674c9219ad6744e39232100c5f71fe 100644 (file)
@@ -200,16 +200,6 @@ extern int dispatch_scsi_info(int ino, char *buffer, char **start,
 static void scsi_dump_status(int level);
 
 
-/*
- *  This is the number  of clock ticks we should wait before we time out
- *  and abort the command.  This is for  where the scsi.c module generates
- *  the command, not where it originates from a higher level, in which
- *  case the timeout is specified there.
- *
- */
-
-
-
 struct dev_info{
     const char * vendor;
     const char * model;
@@ -3208,7 +3198,7 @@ scsi_dump_status(int level)
         printk(" %d %d %d : %d %p\n",
                shpnt->host_failed,
                shpnt->host_busy,
-               shpnt->host_active,
+               atomic_read(&shpnt->host_active),
                shpnt->host_blocked,
                shpnt->pending_commands);
 
index ff074388cc66da28a06003216afd6299dcf4f56e..48036ed33aee4787303582c6a38ead4e7a44d8ea 100644 (file)
@@ -141,11 +141,11 @@ static struct override {
 #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
 
 static struct base {
-    unsigned char *address;
+    unsigned int address;
     int noauto;
 } bases[] __initdata = {
-    {(unsigned char *) 0xcc000, 0}, {(unsigned char *) 0xc8000, 0},
-    {(unsigned char *) 0xdc000, 0}, {(unsigned char *) 0xd8000, 0}};
+    { 0xcc000, 0}, { 0xc8000, 0}, { 0xdc000, 0}, { 0xd8000, 0}
+};
 
 #define NO_BASES (sizeof (bases) / sizeof (struct base))
 
@@ -178,7 +178,7 @@ __initfunc(void t128_setup(char *str, int *ints)) {
            overrides[commandline_current].address = (unsigned char *) ints[1];
            overrides[commandline_current].irq = ints[2];
            for (i = 0; i < NO_BASES; ++i)
-               if (bases[i].address == (unsigned char *) ints[1]) {
+               if (bases[i].address == ints[1]) {
                    bases[i].noauto = 1;
                    break;
                }
@@ -216,7 +216,7 @@ __initfunc(int t128_detect(Scsi_Host_Template * tpnt)) {
        else 
            for (; !base && (current_base < NO_BASES); ++current_base) {
 #if (TDEBUG & TDEBUG_INIT)
-    printk("scsi-t128 : probing address %08x\n", (unsigned int) bases[current_base].address);
+    printk("scsi-t128 : probing address %08x\n", bases[current_base].address);
 #endif
                for (sig = 0; sig < NO_SIGNATURES; ++sig) 
                    if (!bases[current_base].noauto && 
@@ -224,7 +224,7 @@ __initfunc(int t128_detect(Scsi_Host_Template * tpnt)) {
                                        signatures[sig].offset,
                                        signatures[sig].string,
                                        strlen(signatures[sig].string))) {
-                     base = bases[current_base].address;
+                       base = (unsigned char *) bases[current_base].address;
 #if (TDEBUG & TDEBUG_INIT)
                        printk("scsi-t128 : detected board.\n");
 #endif
index 2eb2c0da7fcfe9ed9dc066dd2dabcabc4d40b2b8..9b6fa5c1258eeb89093c767f2fbb0b0196cbbad2 100644 (file)
@@ -350,7 +350,7 @@ int audio_read(int dev, struct fileinfo *file, char *buf, int count)
 int audio_ioctl(int dev, struct fileinfo *file_must_not_be_used,
                unsigned int cmd, caddr_t arg)
 {
-       int val, info, count;
+       int val = 0, info, count;
        unsigned long flags;
        struct dma_buffparms *dmap;
 
index 79583cbca8dde5848ac92debd7aa3ac3dea022e2..63dacee8e5d9d8b973fc168dd6870d0c018fa1e4 100644 (file)
@@ -36,9 +36,9 @@ int snd_find_driver(int type)
 
 static void start_services(void)
 {
+#ifdef FIXME
        int soundcards_installed;
 
-#ifdef FIXME
        if (!(soundcards_installed = sndtable_get_cardcount()))
                return;         /* No cards detected */
 #endif
index 823452ef47785ec73d9b0335ca8ee7b5438ae032..141cd7db8e1fdd17f11457395b28a065a970b129 100644 (file)
@@ -28,8 +28,7 @@ extern int      gus_pcm_volume;
 extern int      have_gus_max;
 int             gus_pnp_flag = 0;
 
-void
-attach_gus_card(struct address_info *hw_config)
+void attach_gus_card(struct address_info *hw_config)
 {
        snd_set_irq_handler(hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp);
 
@@ -48,8 +47,7 @@ attach_gus_card(struct address_info *hw_config)
 #endif
 }
 
-int
-probe_gus(struct address_info *hw_config)
+int probe_gus(struct address_info *hw_config)
 {
        int             irq;
        int             io_addr;
@@ -63,13 +61,13 @@ probe_gus(struct address_info *hw_config)
                if (irq != 3 && irq != 5 && irq != 7 && irq != 9 &&
                    irq != 11 && irq != 12 && irq != 15)
                  {
-                         printk("GUS: Unsupported IRQ %d\n", irq);
+                         printk(KERN_ERR "GUS: Unsupported IRQ %d\n", irq);
                          return 0;
                  }
        if (check_region(hw_config->io_base, 16))
-               printk("GUS: I/O range conflict (1)\n");
+               printk(KERN_ERR "GUS: I/O range conflict (1)\n");
        else if (check_region(hw_config->io_base + 0x100, 16))
-               printk("GUS: I/O range conflict (2)\n");
+               printk(KERN_ERR "GUS: I/O range conflict (2)\n");
        else if (gus_wave_detect(hw_config->io_base))
                return 1;
 
@@ -95,8 +93,7 @@ probe_gus(struct address_info *hw_config)
        return 0;
 }
 
-void
-unload_gus(struct address_info *hw_config)
+void unload_gus(struct address_info *hw_config)
 {
        DDB(printk("unload_gus(%x)\n", hw_config->io_base));
 
@@ -112,8 +109,7 @@ unload_gus(struct address_info *hw_config)
                sound_free_dma(hw_config->dma2);
 }
 
-void
-gusintr(int irq, void *dev_id, struct pt_regs *dummy)
+void gusintr(int irq, void *dev_id, struct pt_regs *dummy)
 {
        unsigned char   src;
        extern int      gus_timer_enabled;
@@ -126,56 +122,50 @@ gusintr(int irq, void *dev_id, struct pt_regs *dummy)
 #endif
 
        while (1)
-         {
-                 if (!(src = inb(u_IrqStatus)))
-                         return;
-
-                 if (src & DMA_TC_IRQ)
-                   {
-                           guswave_dma_irq();
-                   }
-                 if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ))
-                   {
+       {
+               if (!(src = inb(u_IrqStatus)))
+                       return;
+
+               if (src & DMA_TC_IRQ)
+               {
+                       guswave_dma_irq();
+               }
+               if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ))
+               {
 #if defined(CONFIG_MIDI)
-                           gus_midi_interrupt(0);
+                       gus_midi_interrupt(0);
 #endif
-                   }
-                 if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ))
-                   {
+               }
+               if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ))
+               {
 #if defined(CONFIG_SEQUENCER) || defined(CONFIG_SEQUENCER_MODULE)
-                           if (gus_timer_enabled)
-                             {
-                                     sound_timer_interrupt();
-                             }
-                           gus_write8(0x45, 0);        /* Ack IRQ */
-                           gus_timer_command(4, 0x80);         /* Reset IRQ flags */
-
+                       if (gus_timer_enabled)
+                               sound_timer_interrupt();
+                       gus_write8(0x45, 0);    /* Ack IRQ */
+                       gus_timer_command(4, 0x80);             /* Reset IRQ flags */
 #else
-                           gus_write8(0x45, 0);        /* Stop timers */
+                       gus_write8(0x45, 0);    /* Stop timers */
 #endif
-                   }
-                 if (src & (WAVETABLE_IRQ | ENVELOPE_IRQ))
-                   {
-                           gus_voice_irq();
-                   }
-         }
+               }
+               if (src & (WAVETABLE_IRQ | ENVELOPE_IRQ))
+                       gus_voice_irq();
+       }
 }
 
 #endif
 
 /*
- * Some extra code for the 16 bit sampling option
+ *     Some extra code for the 16 bit sampling option
  */
+
 #ifdef CONFIG_GUS16
 
-int
-probe_gus_db16(struct address_info *hw_config)
+int probe_gus_db16(struct address_info *hw_config)
 {
        return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
 }
 
-void
-attach_gus_db16(struct address_info *hw_config)
+void attach_gus_db16(struct address_info *hw_config)
 {
 #if defined(CONFIG_GUSHW) || defined(MODULE)
        gus_pcm_volume = 100;
@@ -189,8 +179,7 @@ attach_gus_db16(struct address_info *hw_config)
                                          hw_config->osp);
 }
 
-void
-unload_gus_db16(struct address_info *hw_config)
+void unload_gus_db16(struct address_info *hw_config)
 {
 
        ad1848_unload(hw_config->io_base,
@@ -226,16 +215,15 @@ MODULE_PARM(type, "i");
 MODULE_PARM(gus16, "i");
 MODULE_PARM(db16, "i");
 
-int
-init_module(void)
+int init_module(void)
 {
-       printk("Gravis Ultrasound audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
+       printk(KERN_INFO "Gravis Ultrasound audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
        if (io == -1 || dma == -1 || irq == -1)
-         {
-                 printk("I/O, IRQ, and DMA are mandatory\n");
-                 return -EINVAL;
-         }
+       {
+               printk(KERN_ERR "I/O, IRQ, and DMA are mandatory\n");
+               return -EINVAL;
+       }
        config.io_base = io;
        config.irq = irq;
        config.dma = dma;
@@ -244,10 +232,10 @@ init_module(void)
 
 #if defined(CONFIG_GUS16)
        if (probe_gus_db16(&config) && gus16)
-         {
-                 attach_gus_db16(&config);
-                 db16 = 1;
-         }
+       {
+               attach_gus_db16(&config);
+               db16 = 1;
+       }       
 #endif
        if (probe_gus(&config) == 0)
                return -ENODEV;
@@ -256,8 +244,7 @@ init_module(void)
        return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
 #if defined(CONFIG_GUS16)
        if (db16)
index 67e4d928dec8ad41b09366f565c4ae51e7648735..b3a33061ee2ed27b641296287fb1c10b2efaed9b 100644 (file)
@@ -33,24 +33,18 @@ static volatile unsigned char qhead, qtail;
 extern int      gus_base, gus_irq, gus_dma;
 extern int     *gus_osp;
 
-static int
-GUS_MIDI_STATUS(void)
+static int GUS_MIDI_STATUS(void)
 {
        return inb(u_MidiStatus);
 }
 
-static int
-gus_midi_open(int dev, int mode,
-             void            (*input) (int dev, unsigned char data),
-             void            (*output) (int dev)
-)
+static int gus_midi_open(int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev))
 {
-
        if (midi_busy)
-         {
-                 printk("GUS: Midi busy\n");
-                 return -EBUSY;
-         }
+       {
+/*             printk("GUS: Midi busy\n");*/
+               return -EBUSY;
+       }
        outb((MIDI_RESET), u_MidiControl);
        gus_delay();
 
@@ -59,10 +53,10 @@ gus_midi_open(int dev, int mode,
 
        if (mode == OPEN_READ || mode == OPEN_READWRITE)
                if (!gus_pnp_flag)
-                 {
-                         gus_midi_control |= MIDI_ENABLE_RCV;
-                         input_opened = 1;
-                 }
+               {
+                       gus_midi_control |= MIDI_ENABLE_RCV;
+                       input_opened = 1;
+               }
        outb((gus_midi_control), u_MidiControl);        /* Enable */
 
        midi_busy = 1;
@@ -72,8 +66,7 @@ gus_midi_open(int dev, int mode,
        return 0;
 }
 
-static int
-dump_to_midi(unsigned char midi_byte)
+static int dump_to_midi(unsigned char midi_byte)
 {
        unsigned long   flags;
        int             ok = 0;
@@ -84,24 +77,24 @@ dump_to_midi(unsigned char midi_byte)
        cli();
 
        if (GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY)
-         {
-                 ok = 1;
-                 outb((midi_byte), u_MidiData);
-       } else
-         {
-                 /*
-                  * Enable Midi xmit interrupts (again)
-                  */
-                 gus_midi_control |= MIDI_ENABLE_XMIT;
-                 outb((gus_midi_control), u_MidiControl);
-         }
+       {
+               ok = 1;
+               outb((midi_byte), u_MidiData);
+       }
+       else
+       {
+               /*
+                * Enable Midi xmit interrupts (again)
+                */
+               gus_midi_control |= MIDI_ENABLE_XMIT;
+               outb((gus_midi_control), u_MidiControl);
+       }
 
        restore_flags(flags);
        return ok;
 }
 
-static void
-gus_midi_close(int dev)
+static void gus_midi_close(int dev)
 {
        /*
         * Reset FIFO pointers, disable intrs
@@ -111,10 +104,8 @@ gus_midi_close(int dev)
        midi_busy = 0;
 }
 
-static int
-gus_midi_out(int dev, unsigned char midi_byte)
+static int gus_midi_out(int dev, unsigned char midi_byte)
 {
-
        unsigned long   flags;
 
        /*
@@ -125,15 +116,14 @@ gus_midi_out(int dev, unsigned char midi_byte)
        cli();
 
        while (qlen && dump_to_midi(tmp_queue[qhead]))
-         {
-                 qlen--;
-                 qhead++;
-         }
-
+       {
+               qlen--;
+               qhead++;
+       }
        restore_flags(flags);
 
        /*
-        * Output the byte if the local queue is empty.
+        *      Output the byte if the local queue is empty.
         */
 
        if (!qlen)
@@ -143,14 +133,13 @@ gus_midi_out(int dev, unsigned char midi_byte)
                                         */
 
        /*
-        * Put to the local queue
+        *      Put to the local queue
         */
 
        if (qlen >= 256)
                return 0;       /*
                                 * Local queue full
                                 */
-
        save_flags(flags);
        cli();
 
@@ -159,29 +148,24 @@ gus_midi_out(int dev, unsigned char midi_byte)
        qtail++;
 
        restore_flags(flags);
-
        return 1;
 }
 
-static int
-gus_midi_start_read(int dev)
+static int gus_midi_start_read(int dev)
 {
        return 0;
 }
 
-static int
-gus_midi_end_read(int dev)
+static int gus_midi_end_read(int dev)
 {
        return 0;
 }
 
-static void
-gus_midi_kick(int dev)
+static void gus_midi_kick(int dev)
 {
 }
 
-static int
-gus_midi_buffer_status(int dev)
+static int gus_midi_buffer_status(int dev)
 {
        unsigned long   flags;
 
@@ -192,12 +176,11 @@ gus_midi_buffer_status(int dev)
        cli();
 
        if (qlen && dump_to_midi(tmp_queue[qhead]))
-         {
-                 qlen--;
-                 qhead++;
-         }
+       {
+               qlen--;
+               qhead++;
+       }
        restore_flags(flags);
-
        return (qlen > 0) | !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY);
 }
 
@@ -207,7 +190,9 @@ gus_midi_buffer_status(int dev)
 
 static struct midi_operations gus_midi_operations =
 {
-       {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS},
+       {
+               "Gravis UltraSound Midi", 0, 0, SNDCARD_GUS
+       },
        &std_midi_synth,
        {0},
        gus_midi_open,
@@ -224,16 +209,15 @@ static struct midi_operations gus_midi_operations =
        NULL
 };
 
-void
-gus_midi_init(struct address_info *hw_config)
+void gus_midi_init(struct address_info *hw_config)
 {
-       int             dev = sound_alloc_mididev();
+       int dev = sound_alloc_mididev();
 
        if (dev == -1)
-         {
-                 printk(KERN_INFO "gus_midi: Too many midi devices detected\n");
-                 return;
-         }
+       {
+               printk(KERN_INFO "gus_midi: Too many midi devices detected\n");
+               return;
+       }
        outb((MIDI_RESET), u_MidiControl);
 
        std_midi_synth.midi_dev = my_dev = dev;
@@ -243,44 +227,41 @@ gus_midi_init(struct address_info *hw_config)
        return;
 }
 
-void
-gus_midi_interrupt(int dummy)
+void gus_midi_interrupt(int dummy)
 {
        volatile unsigned char stat, data;
-       unsigned long   flags;
-       int             timeout = 10;
+       unsigned long flags;
+       int timeout = 10;
 
        save_flags(flags);
        cli();
 
        while (timeout-- > 0 && (stat = GUS_MIDI_STATUS()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY))
-         {
-                 if (stat & MIDI_RCV_FULL)
-                   {
-                           data = inb(u_MidiData);
-                           if (input_opened)
-                                   midi_input_intr(my_dev, data);
-                   }
-                 if (stat & MIDI_XMIT_EMPTY)
-                   {
-                           while (qlen && dump_to_midi(tmp_queue[qhead]))
-                             {
-                                     qlen--;
-                                     qhead++;
-                             }
-
-                           if (!qlen)
-                             {
-                                     /*
-                                      * Disable Midi output interrupts, since no data in the buffer
-                                      */
-                                     gus_midi_control &= ~MIDI_ENABLE_XMIT;
-                                     outb((gus_midi_control), u_MidiControl);
-                                     outb((gus_midi_control), u_MidiControl);
-                             }
-                   }
-         }
-
+       {
+               if (stat & MIDI_RCV_FULL)
+               {
+                       data = inb(u_MidiData);
+                       if (input_opened)
+                               midi_input_intr(my_dev, data);
+               }
+               if (stat & MIDI_XMIT_EMPTY)
+               {
+                       while (qlen && dump_to_midi(tmp_queue[qhead]))
+                       {
+                               qlen--;
+                               qhead++;
+                       }
+                       if (!qlen)
+                       {
+                             /*
+                              * Disable Midi output interrupts, since no data in the buffer
+                              */
+                             gus_midi_control &= ~MIDI_ENABLE_XMIT;
+                             outb((gus_midi_control), u_MidiControl);
+                             outb((gus_midi_control), u_MidiControl);
+                       }
+               }
+       }
        restore_flags(flags);
 }
 
index a42c5c6e17b896bfda76ddf5a756b930982b5230..b68fca34a1d04c5276f34853e61d49619c6df8ab 100644 (file)
@@ -34,10 +34,10 @@ extern int      gus_wave_volume;
  * we can give a big boost to very weak voices like nylon guitar and the
  * basses.  The normal value is 64.  Strings are assigned lower values.
  */
-unsigned short
-gus_adagio_vol(int vel, int mainv, int xpn, int voicev)
+
+unsigned short gus_adagio_vol(int vel, int mainv, int xpn, int voicev)
 {
-       int             i, m, n, x;
+       int i, m, n, x;
 
 
        /*
@@ -50,6 +50,7 @@ gus_adagio_vol(int vel, int mainv, int xpn, int voicev)
        /*
         * Boost expression by voice volume above neutral.
         */
+        
        if (voicev > 65)
                xpn += voicev - 64;
        xpn += (voicev - 64) / 2;
@@ -85,18 +86,22 @@ gus_adagio_vol(int vel, int mainv, int xpn, int voicev)
         * Convert to GUS's logarithmic form with 4 bit exponent i and 8 bit
         * mantissa m.
         */
+        
        n = x;
        i = 7;
        if (n < 128)
-         {
+       {
                  while (i > 0 && n < (1 << i))
                          i--;
-       } else
+       }
+       else
+       {
                while (n > 255)
-                 {
+               {
                          n >>= 1;
                          i++;
-                 }
+               }
+       }
        /*
         * Mantissa is part of linear volume not expressed in exponent.  (This is
         * not quite like real logs -- I wonder if it's right.)
@@ -107,12 +112,12 @@ gus_adagio_vol(int vel, int mainv, int xpn, int voicev)
         * Adjust mantissa to 8 bits.
         */
        if (m > 0)
-         {
-                 if (i > 8)
-                         m >>= i - 8;
-                 else if (i < 8)
-                         m <<= 8 - i;
-         }
+       {
+               if (i > 8)
+                       m >>= i - 8;
+               else if (i < 8)
+                       m <<= 8 - i;
+       }
        return ((i << 8) + m);
 }
 
@@ -122,10 +127,9 @@ gus_adagio_vol(int vel, int mainv, int xpn, int voicev)
  * and the volume set by the mixer-device (default 60%).
  */
 
-unsigned short
-gus_linear_vol(int vol, int mainvol)
+unsigned short gus_linear_vol(int vol, int mainvol)
 {
-       int             mixer_mainvol;
+       int mixer_mainvol;
 
        if (vol <= 0)
                vol = 0;
@@ -146,7 +150,6 @@ gus_linear_vol(int vol, int mainvol)
 #else
        mainvol = 127;
 #endif
-
        return gus_linearvol[(((vol * mainvol) / 127) * mixer_mainvol) / 100];
 }
 
index 8db5f08dbe1a09cacafc41088a48202e6e1e1900..6f3f4a6890607bf4225e1c2289a0b642381a11e4 100644 (file)
 #define NOT_SAMPLE     0xffff
 
 struct voice_info
-  {
-         unsigned long   orig_freq;
-         unsigned long   current_freq;
-         unsigned long   mode;
-         int             fixed_pitch;
-         int             bender;
-         int             bender_range;
-         int             panning;
-         int             midi_volume;
-         unsigned int    initial_volume;
-         unsigned int    current_volume;
-         int             loop_irq_mode, loop_irq_parm;
+{
+       unsigned long   orig_freq;
+       unsigned long   current_freq;
+       unsigned long   mode;
+       int             fixed_pitch;
+       int             bender;
+       int             bender_range;
+       int             panning;
+       int             midi_volume;
+       unsigned int    initial_volume;
+       unsigned int    current_volume;
+       int             loop_irq_mode, loop_irq_parm;
 #define LMODE_FINISH           1
 #define LMODE_PCM              2
 #define LMODE_PCM_STOP         3
-         int             volume_irq_mode, volume_irq_parm;
+       int             volume_irq_mode, volume_irq_parm;
 #define VMODE_HALT             1
 #define VMODE_ENVELOPE         2
 #define VMODE_START_NOTE       3
 
-         int             env_phase;
-         unsigned char   env_rate[6];
-         unsigned char   env_offset[6];
+       int             env_phase;
+       unsigned char   env_rate[6];
+       unsigned char   env_offset[6];
 
-         /*
-          * Volume computation parameters for gus_adagio_vol()
-          */
-         int             main_vol, expression_vol, patch_vol;
+       /*
+        * Volume computation parameters for gus_adagio_vol()
+        */
+       int             main_vol, expression_vol, patch_vol;
 
-         /* Variables for "Ultraclick" removal */
-         int             dev_pending, note_pending, volume_pending,
-                         sample_pending;
-         char            kill_pending;
-         long            offset_pending;
+       /* Variables for "Ultraclick" removal */
+       int             dev_pending, note_pending, volume_pending,
+                       sample_pending;
+       char            kill_pending;
+       long            offset_pending;
 
-  };
+};
 
 static struct voice_alloc_info *voice_alloc;
 
@@ -101,6 +101,7 @@ int             gus_timer_enabled = 0;
  * Current version of this driver doesn't allow synth and PCM functions
  * at the same time. The active_device specifies the active driver
  */
+
 static int      active_device = 0;
 
 #define GUS_DEV_WAVE           1       /* Wave table synth */
@@ -114,12 +115,14 @@ static int      gus_audio_bsize;
 static char     bounce_buf[8 * 1024];  /* Must match value set to max_fragment */
 
 static struct wait_queue *dram_sleeper = NULL;
-static volatile struct snd_wait dram_sleep_flag =
-{0};
+static volatile struct snd_wait dram_sleep_flag = {
+       0
+};
 
 /*
  * Variables and buffers for PCM output
  */
+
 #define MAX_PCM_BUFFERS                (128*MAX_REALTIME_FACTOR)       /* Don't change */
 
 static int      pcm_bsize, pcm_nblk, pcm_banksize;
@@ -172,8 +175,10 @@ static int      mixer_type = 0;
 static int      patch_table[MAX_PATCH];
 static int      patch_map[32];
 
-static struct synth_info gus_info =
-{"Gravis UltraSound", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH};
+static struct synth_info gus_info = {
+       "Gravis UltraSound", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 
+       0, 16, 0, MAX_PATCH
+};
 
 static void     gus_poke(long addr, unsigned char data);
 static void     compute_and_set_volume(int voice, int volume, int ramp_time);
@@ -187,10 +192,9 @@ static void     gus_tmr_install(int io_base);
 #define        INSTANT_RAMP            -1      /* Instant change. No ramping */
 #define FAST_RAMP              0       /* Fastest possible ramp */
 
-static void
-reset_sample_memory(void)
+static void reset_sample_memory(void)
 {
-       int             i;
+       int i;
 
        for (i = 0; i <= MAX_SAMPLE; i++)
                sample_ptrs[i] = -1;
@@ -209,17 +213,15 @@ reset_sample_memory(void)
                patch_table[i] = NOT_SAMPLE;
 }
 
-void
-gus_delay(void)
+void gus_delay(void)
 {
-       int             i;
+       int i;
 
        for (i = 0; i < 7; i++)
                inb(u_DRAMIO);
 }
 
-static void
-gus_poke(long addr, unsigned char data)
+static void gus_poke(long addr, unsigned char data)
 {                              /* Writes a byte to the DRAM */
        unsigned long   flags;
 
@@ -235,8 +237,7 @@ gus_poke(long addr, unsigned char data)
        restore_flags(flags);
 }
 
-static unsigned char
-gus_peek(long addr)
+static unsigned char gus_peek(long addr)
 {                              /* Reads a byte from the DRAM */
        unsigned long   flags;
        unsigned char   tmp;
@@ -255,8 +256,7 @@ gus_peek(long addr)
        return tmp;
 }
 
-void
-gus_write8(int reg, unsigned int data)
+void gus_write8(int reg, unsigned int data)
 {                              /* Writes to an indirect register (8 bit) */
        unsigned long   flags;
 
@@ -269,9 +269,9 @@ gus_write8(int reg, unsigned int data)
        restore_flags(flags);
 }
 
-static unsigned char
-gus_read8(int reg)
-{                              /* Reads from an indirect register (8 bit). Offset 0x80. */
+static unsigned char gus_read8(int reg)
+{                              
+       /* Reads from an indirect register (8 bit). Offset 0x80. */
        unsigned long   flags;
        unsigned char   val;
 
@@ -284,9 +284,9 @@ gus_read8(int reg)
        return val;
 }
 
-static unsigned char
-gus_look8(int reg)
-{                              /* Reads from an indirect register (8 bit). No additional offset. */
+static unsigned char gus_look8(int reg)
+{
+       /* Reads from an indirect register (8 bit). No additional offset. */
        unsigned long   flags;
        unsigned char   val;
 
@@ -299,9 +299,9 @@ gus_look8(int reg)
        return val;
 }
 
-static void
-gus_write16(int reg, unsigned int data)
-{                              /* Writes to an indirect register (16 bit) */
+static void gus_write16(int reg, unsigned int data)
+{
+       /* Writes to an indirect register (16 bit) */
        unsigned long   flags;
 
        save_flags(flags);
@@ -315,9 +315,9 @@ gus_write16(int reg, unsigned int data)
        restore_flags(flags);
 }
 
-static unsigned short
-gus_read16(int reg)
-{                              /* Reads from an indirect register (16 bit). Offset 0x80. */
+static unsigned short gus_read16(int reg)
+{
+       /* Reads from an indirect register (16 bit). Offset 0x80. */
        unsigned long   flags;
        unsigned char   hi, lo;
 
@@ -334,9 +334,9 @@ gus_read16(int reg)
        return ((hi << 8) & 0xff00) | lo;
 }
 
-static unsigned short
-gus_look16(int reg)
-{                              /* Reads from an indirect register (16 bit). No additional offset. */
+static unsigned short gus_look16(int reg)
+{              
+       /* Reads from an indirect register (16 bit). No additional offset. */
        unsigned long   flags;
        unsigned char   hi, lo;
 
@@ -353,32 +353,33 @@ gus_look16(int reg)
        return ((hi << 8) & 0xff00) | lo;
 }
 
-static void
-gus_write_addr(int reg, unsigned long address, int frac, int is16bit)
-{                              /* Writes an 24 bit memory address */
+static void gus_write_addr(int reg, unsigned long address, int frac, int is16bit)
+{
+       /* Writes an 24 bit memory address */
        unsigned long   hold_address;
        unsigned long   flags;
 
        save_flags(flags);
        cli();
        if (is16bit)
-         {
-                 if (iw_mode)
-                   {
-                           /* Interwave spesific address translations */
-                           address >>= 1;
-                 } else
-                   {
-                           /*
-                            * Special processing required for 16 bit patches
-                            */
-
-                           hold_address = address;
-                           address = address >> 1;
-                           address &= 0x0001ffffL;
-                           address |= (hold_address & 0x000c0000L);
-                   }
-         }
+       {
+               if (iw_mode)
+               {
+                       /* Interwave spesific address translations */
+                       address >>= 1;
+               }
+               else
+               {
+                       /*
+                        * Special processing required for 16 bit patches
+                        */
+
+                       hold_address = address;
+                       address = address >> 1;
+                       address &= 0x0001ffffL;
+                       address |= (hold_address & 0x000c0000L);
+               }
+       }
        gus_write16(reg, (unsigned short) ((address >> 7) & 0xffff));
        gus_write16(reg + 1, (unsigned short) ((address << 9) & 0xffff)
                    + (frac << 5));
@@ -390,17 +391,14 @@ gus_write_addr(int reg, unsigned long address, int frac, int is16bit)
        restore_flags(flags);
 }
 
-static void
-gus_select_voice(int voice)
+static void gus_select_voice(int voice)
 {
        if (voice < 0 || voice > 31)
                return;
-
        outb((voice), u_Voice);
 }
 
-static void
-gus_select_max_voices(int nvoices)
+static void gus_select_max_voices(int nvoices)
 {
        if (iw_mode)
                nvoices = 32;
@@ -410,26 +408,22 @@ gus_select_max_voices(int nvoices)
                nvoices = 32;
 
        voice_alloc->max_voice = nr_voices = nvoices;
-
        gus_write8(0x0e, (nvoices - 1) | 0xc0);
 }
 
-static void
-gus_voice_on(unsigned int mode)
+static void gus_voice_on(unsigned int mode)
 {
        gus_write8(0x00, (unsigned char) (mode & 0xfc));
        gus_delay();
        gus_write8(0x00, (unsigned char) (mode & 0xfc));
 }
 
-static void
-gus_voice_off(void)
+static void gus_voice_off(void)
 {
        gus_write8(0x00, gus_read8(0x00) | 0x03);
 }
 
-static void
-gus_voice_mode(unsigned int m)
+static void gus_voice_mode(unsigned int m)
 {
        unsigned char   mode = (unsigned char) (m & 0xff);
 
@@ -439,8 +433,7 @@ gus_voice_mode(unsigned int m)
        gus_write8(0x00, (gus_read8(0x00) & 0x03) | (mode & 0xfc));
 }
 
-static void
-gus_voice_freq(unsigned long freq)
+static void gus_voice_freq(unsigned long freq)
 {
        unsigned long   divisor = freq_div_table[nr_voices - 14];
        unsigned short  fc;
@@ -455,34 +448,29 @@ gus_voice_freq(unsigned long freq)
        gus_write16(0x01, fc);
 }
 
-static void
-gus_voice_volume(unsigned int vol)
+static void gus_voice_volume(unsigned int vol)
 {
        gus_write8(0x0d, 0x03); /* Stop ramp before setting volume */
        gus_write16(0x09, (unsigned short) (vol << 4));
 }
 
-static void
-gus_voice_balance(unsigned int balance)
+static void gus_voice_balance(unsigned int balance)
 {
        gus_write8(0x0c, (unsigned char) (balance & 0xff));
 }
 
-static void
-gus_ramp_range(unsigned int low, unsigned int high)
+static void gus_ramp_range(unsigned int low, unsigned int high)
 {
        gus_write8(0x07, (unsigned char) ((low >> 4) & 0xff));
        gus_write8(0x08, (unsigned char) ((high >> 4) & 0xff));
 }
 
-static void
-gus_ramp_rate(unsigned int scale, unsigned int rate)
+static void gus_ramp_rate(unsigned int scale, unsigned int rate)
 {
        gus_write8(0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f)));
 }
 
-static void
-gus_rampon(unsigned int m)
+static void gus_rampon(unsigned int m)
 {
        unsigned char   mode = (unsigned char) (m & 0xff);
 
@@ -491,10 +479,9 @@ gus_rampon(unsigned int m)
        gus_write8(0x0d, mode & 0xfc);
 }
 
-static void
-gus_ramp_mode(unsigned int m)
+static void gus_ramp_mode(unsigned int m)
 {
-       unsigned char   mode = (unsigned char) (m & 0xff);
+       unsigned char mode = (unsigned char) (m & 0xff);
 
        gus_write8(0x0d, (gus_read8(0x0d) & 0x03) |
                   (mode & 0xfc));      /* Leave the last 2 bits alone */
@@ -502,16 +489,14 @@ gus_ramp_mode(unsigned int m)
        gus_write8(0x0d, (gus_read8(0x0d) & 0x03) | (mode & 0xfc));
 }
 
-static void
-gus_rampoff(void)
+static void gus_rampoff(void)
 {
        gus_write8(0x0d, 0x03);
 }
 
-static void
-gus_set_voice_pos(int voice, long position)
+static void gus_set_voice_pos(int voice, long position)
 {
-       int             sample_no;
+       int sample_no;
 
        if ((sample_no = sample_map[voice]) != -1)
                if (position < samples[sample_no].len)
@@ -522,8 +507,7 @@ gus_set_voice_pos(int voice, long position)
                                 samples[sample_no].mode & WAVE_16_BITS);
 }
 
-static void
-gus_voice_init(int voice)
+static void gus_voice_init(int voice)
 {
        unsigned long   flags;
 
@@ -541,8 +525,7 @@ gus_voice_init(int voice)
 
 }
 
-static void
-gus_voice_init2(int voice)
+static void gus_voice_init2(int voice)
 {
        voices[voice].panning = 0;
        voices[voice].mode = 0;
@@ -564,30 +547,30 @@ gus_voice_init2(int voice)
        voices[voice].fixed_pitch = 0;
 }
 
-static void
-step_envelope(int voice)
+static void step_envelope(int voice)
 {
        unsigned        vol, prev_vol, phase;
        unsigned char   rate;
        long int        flags;
 
        if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2)
-         {
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_rampoff();
-                 restore_flags(flags);
-                 return;
-                 /*
-                  * Sustain phase begins. Continue envelope after receiving note off.
-                  */
-         }
+       {
+               save_flags(flags);
+               cli();
+               gus_select_voice(voice);
+               gus_rampoff();
+               restore_flags(flags);
+               return;
+               /*
+                * Sustain phase begins. Continue envelope after receiving note off.
+                */
+       }
        if (voices[voice].env_phase >= 5)
-         {                     /* Envelope finished. Shoot the voice down */
-                 gus_voice_init(voice);
-                 return;
-         }
+       {
+               /* Envelope finished. Shoot the voice down */
+               gus_voice_init(voice);
+               return;
+       }
        prev_vol = voices[voice].current_volume;
        phase = ++voices[voice].env_phase;
        compute_volume(voice, voices[voice].midi_volume);
@@ -606,30 +589,30 @@ step_envelope(int voice)
        voices[voice].volume_irq_mode = VMODE_ENVELOPE;
 
        if (((vol - prev_vol) / 64) == 0)       /* No significant volume change */
-         {
-                 restore_flags(flags);
-                 step_envelope(voice);         /* Continue the envelope on the next step */
-                 return;
-         }
+       {
+               restore_flags(flags);
+               step_envelope(voice);           /* Continue the envelope on the next step */
+               return;
+       }
        if (vol > prev_vol)
-         {
-                 if (vol >= (4096 - 64))
-                         vol = 4096 - 65;
-                 gus_ramp_range(0, vol);
-                 gus_rampon(0x20);     /* Increasing volume, with IRQ */
-       } else
-         {
-                 if (vol <= 64)
-                         vol = 65;
-                 gus_ramp_range(vol, 4030);
-                 gus_rampon(0x60);     /* Decreasing volume, with IRQ */
-         }
+       {
+               if (vol >= (4096 - 64))
+                       vol = 4096 - 65;
+               gus_ramp_range(0, vol);
+               gus_rampon(0x20);       /* Increasing volume, with IRQ */
+       }
+       else
+       {
+               if (vol <= 64)
+                       vol = 65;
+               gus_ramp_range(vol, 4030);
+               gus_rampon(0x60);       /* Decreasing volume, with IRQ */
+       }
        voices[voice].current_volume = vol;
        restore_flags(flags);
 }
 
-static void
-init_envelope(int voice)
+static void init_envelope(int voice)
 {
        voices[voice].env_phase = -1;
        voices[voice].current_volume = 64;
@@ -637,17 +620,15 @@ init_envelope(int voice)
        step_envelope(voice);
 }
 
-static void
-start_release(int voice, long int flags)
+static void start_release(int voice, long int flags)
 {
        if (gus_read8(0x00) & 0x03)
                return;         /* Voice already stopped */
 
        voices[voice].env_phase = 2;    /* Will be incremented by step_envelope */
 
-       voices[voice].current_volume =
-           voices[voice].initial_volume =
-           gus_read16(0x09) >> 4;      /* Get current volume */
+       voices[voice].current_volume = voices[voice].initial_volume =
+                                               gus_read16(0x09) >> 4;  /* Get current volume */
 
        voices[voice].mode &= ~WAVE_SUSTAIN_ON;
        gus_rampoff();
@@ -655,42 +636,41 @@ start_release(int voice, long int flags)
        step_envelope(voice);
 }
 
-static void
-gus_voice_fade(int voice)
+static void gus_voice_fade(int voice)
 {
-       int             instr_no = sample_map[voice], is16bits;
-       long int        flags;
+       int instr_no = sample_map[voice], is16bits;
+       long int flags;
 
        save_flags(flags);
        cli();
        gus_select_voice(voice);
 
        if (instr_no < 0 || instr_no > MAX_SAMPLE)
-         {
-                 gus_write8(0x00, 0x03);       /* Hard stop */
-                 voice_alloc->map[voice] = 0;
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               gus_write8(0x00, 0x03); /* Hard stop */
+               voice_alloc->map[voice] = 0;
+               restore_flags(flags);
+               return;
+       }
        is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0;     /* 8 or 16 bits */
 
        if (voices[voice].mode & WAVE_ENVELOPES)
-         {
-                 start_release(voice, flags);
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               start_release(voice, flags);
+               restore_flags(flags);
+               return;
+       }
        /*
         * Ramp the volume down but not too quickly.
         */
        if ((int) (gus_read16(0x09) >> 4) < 100)        /* Get current volume */
-         {
-                 gus_voice_off();
-                 gus_rampoff();
-                 gus_voice_init(voice);
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               gus_voice_off();
+               gus_rampoff();
+               gus_voice_init(voice);
+               restore_flags(flags);
+               return;
+       }
        gus_ramp_range(65, 4030);
        gus_ramp_rate(2, 4);
        gus_rampon(0x40 | 0x20);        /* Down, once, with IRQ */
@@ -698,10 +678,9 @@ gus_voice_fade(int voice)
        restore_flags(flags);
 }
 
-static void
-gus_reset(void)
+static void gus_reset(void)
 {
-       int             i;
+       int i;
 
        gus_select_max_voices(24);
        volume_base = 3071;
@@ -709,23 +688,24 @@ gus_reset(void)
        volume_method = VOL_METHOD_ADAGIO;
 
        for (i = 0; i < 32; i++)
-         {
-                 gus_voice_init(i);    /* Turn voice off */
-                 gus_voice_init2(i);
-         }
+       {
+               gus_voice_init(i);      /* Turn voice off */
+               gus_voice_init2(i);
+       }
 }
 
-static void
-gus_initialize(void)
+static void gus_initialize(void)
 {
-       unsigned long   flags;
-       unsigned char   dma_image, irq_image, tmp;
+       unsigned long flags;
+       unsigned char dma_image, irq_image, tmp;
 
-       static unsigned char gus_irq_map[16] =
-       {0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
+       static unsigned char gus_irq_map[16] =  {
+               0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7
+       };
 
-       static unsigned char gus_dma_map[8] =
-       {0, 1, 0, 2, 0, 3, 4, 5};
+       static unsigned char gus_dma_map[8] = {
+               0, 1, 0, 2, 0, 3, 4, 5
+       };
 
        save_flags(flags);
        cli();
@@ -787,37 +767,39 @@ gus_initialize(void)
        irq_image = 0;
        tmp = gus_irq_map[gus_irq];
        if (!gus_pnp_flag && !tmp)
-               printk("Warning! GUS IRQ not selected\n");
+               printk(KERN_WARNING "Warning! GUS IRQ not selected\n");
        irq_image |= tmp;
        irq_image |= 0x40;      /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
 
        dual_dma_mode = 1;
        if (gus_dma2 == gus_dma || gus_dma2 == -1)
-         {
-                 dual_dma_mode = 0;
-                 dma_image = 0x40;     /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
+       {
+               dual_dma_mode = 0;
+               dma_image = 0x40;       /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
 
-                 tmp = gus_dma_map[gus_dma];
-                 if (!tmp)
-                         printk("Warning! GUS DMA not selected\n");
+               tmp = gus_dma_map[gus_dma];
+               if (!tmp)
+                       printk(KERN_WARNING "Warning! GUS DMA not selected\n");
 
-                 dma_image |= tmp;
-       } else
+               dma_image |= tmp;
+       }
+       else
+       {
                /* Setup dual DMA channel mode for GUS MAX */
-         {
-                 dma_image = gus_dma_map[gus_dma];
-                 if (!dma_image)
-                         printk("Warning! GUS DMA not selected\n");
-
-                 tmp = gus_dma_map[gus_dma2] << 3;
-                 if (!tmp)
-                   {
-                           printk("Warning! Invalid GUS MAX DMA\n");
-                           tmp = 0x40;         /* Combine DMA channels */
+
+               dma_image = gus_dma_map[gus_dma];
+               if (!dma_image)
+                       printk(KERN_WARNING "Warning! GUS DMA not selected\n");
+
+               tmp = gus_dma_map[gus_dma2] << 3;
+               if (!tmp)
+               {
+                       printk(KERN_WARNING "Warning! Invalid GUS MAX DMA\n");
+                       tmp = 0x40;             /* Combine DMA channels */
                            dual_dma_mode = 0;
-                   }
-                 dma_image |= tmp;
-         }
+               }
+               dma_image |= tmp;
+       }
 
        /*
         * For some reason the IRQ and DMA addresses must be written twice
@@ -848,8 +830,8 @@ gus_initialize(void)
        mix_image &= ~0x02;     /* Enable line out */
        mix_image |= 0x08;      /* Enable IRQ */
        outb((mix_image), u_Mixer);     /*
-                                          * Turn mixer channels on
-                                          * Note! Mic in is left off.
+                                        * Turn mixer channels on
+                                        * Note! Mic in is left off.
                                         */
 
        gus_select_voice(0);    /* This disables writes to IRQ/DMA reg */
@@ -869,17 +851,16 @@ gus_initialize(void)
 }
 
 
-static void
-pnp_mem_init(void)
+static void pnp_mem_init(void)
 {
 #include "iwmem.h"
 #define CHUNK_SIZE (256*1024)
 #define BANK_SIZE (4*1024*1024)
 #define CHUNKS_PER_BANK (BANK_SIZE/CHUNK_SIZE)
 
-       int             bank, chunk, addr, total = 0;
-       int             bank_sizes[4];
-       int             i, j, bits = -1, nbanks = 0;
+       int bank, chunk, addr, total = 0;
+       int bank_sizes[4];
+       int i, j, bits = -1, nbanks = 0;
 
 /*
  * This routine determines what kind of RAM is installed in each of the four
@@ -902,133 +883,137 @@ pnp_mem_init(void)
  * Perform the DRAM size detection for each bank individually.
  */
        for (bank = 0; bank < 4; bank++)
-         {
-                 int             size = 0;
+       {
+               int size = 0;
 
-                 addr = bank * BANK_SIZE;
+               addr = bank * BANK_SIZE;
 
-                 /* Clean check points of each chunk */
-                 for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++)
-                   {
-                           gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x00);
-                           gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0x00);
-                   }
+               /* Clean check points of each chunk */
+               for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++)
+               {
+                       gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x00);
+                       gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0x00);
+               }
 
-                 /* Write a value to each chunk point and verify the result */
-                 for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++)
-                   {
-                           gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x55);
-                           gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0xAA);
+               /* Write a value to each chunk point and verify the result */
+               for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++)
+               {
+                       gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x55);
+                       gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0xAA);
 
-                           if (gus_peek(addr + chunk * CHUNK_SIZE + 0L) == 0x55 &&
+                       if (gus_peek(addr + chunk * CHUNK_SIZE + 0L) == 0x55 &&
                                gus_peek(addr + chunk * CHUNK_SIZE + 1L) == 0xAA)
-                             { /* OK. There is RAM. Now check for possible shadows */
-                                     int             ok = 1, chunk2;
-
-                                     for (chunk2 = 0; ok && chunk2 < chunk; chunk2++)
-                                             if (gus_peek(addr + chunk2 * CHUNK_SIZE + 0L) ||
-                                                 gus_peek(addr + chunk2 * CHUNK_SIZE + 1L))
-                                                     ok = 0;   /* Addressing wraps */
-
-                                     if (ok)
-                                             size = (chunk + 1) * CHUNK_SIZE;
-                             }
-                           gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x00);
-                           gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0x00);
-                   }
-
-                 bank_sizes[bank] = size;
-                 if (size)
-                         nbanks = bank + 1;
-                 DDB(printk("Interwave: Bank %d, size=%dk\n", bank, size / 1024));
-         }
+                       {
+                               /* OK. There is RAM. Now check for possible shadows */
+                               int ok = 1, chunk2;
+
+                               for (chunk2 = 0; ok && chunk2 < chunk; chunk2++)
+                                       if (gus_peek(addr + chunk2 * CHUNK_SIZE + 0L) ||
+                                                       gus_peek(addr + chunk2 * CHUNK_SIZE + 1L))
+                                               ok = 0; /* Addressing wraps */
+
+                               if (ok)
+                                       size = (chunk + 1) * CHUNK_SIZE;
+                       }
+                       gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x00);
+                       gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0x00);
+               }
+               bank_sizes[bank] = size;
+               if (size)
+                       nbanks = bank + 1;
+               DDB(printk("Interwave: Bank %d, size=%dk\n", bank, size / 1024));
+       }
 
        if (nbanks == 0)        /* No RAM - Give up */
-         {
-                 printk("Sound: An Interwave audio chip detected but no DRAM\n");
-                 printk("Sound: Unable to work with this card.\n");
-                 gus_write8(0x19, gus_read8(0x19) & ~0x01);
-                 gus_mem_size = 0;
-                 return;
-         }
-/*
- * Now we know how much DRAM there is in each bank. The next step is
- * to find a DRAM size encoding (0 to 12) which is best for the combination
- * we have.
- *
- * First try if any of the possible alternatives matches exactly the amount
- * of memory we have.
- */
+       {
+               printk(KERN_ERR "Sound: An Interwave audio chip detected but no DRAM\n");
+               printk(KERN_ERR "Sound: Unable to work with this card.\n");
+               gus_write8(0x19, gus_read8(0x19) & ~0x01);
+               gus_mem_size = 0;
+               return;
+       }
+
+       /*
+        * Now we know how much DRAM there is in each bank. The next step is
+        * to find a DRAM size encoding (0 to 12) which is best for the combination
+        * we have.
+        *
+        * First try if any of the possible alternatives matches exactly the amount
+        * of memory we have.
+        */
 
        for (i = 0; bits == -1 && i < 13; i++)
-         {
-                 bits = i;
+       {
+               bits = i;
 
-                 for (j = 0; bits != -1 && j < 4; j++)
-                         if (mem_decode[i][j] != bank_sizes[j])
-                                 bits = -1;    /* No hit */
-         }
+               for (j = 0; bits != -1 && j < 4; j++)
+                       if (mem_decode[i][j] != bank_sizes[j])
+                               bits = -1;      /* No hit */
+       }
+
+       /*
+        * If necessary, try to find a combination where other than the last
+        * bank matches our configuration and the last bank is left oversized.
+        * In this way we don't leave holes in the middle of memory.
+        */
 
-/*
- * If necessary, try to find a combination where other than the last
- * bank matches our configuration and the last bank is left oversized.
- * In this way we don't leave holes in the middle of memory.
- */
        if (bits == -1)         /* No luck yet */
+       {
                for (i = 0; bits == -1 && i < 13; i++)
-                 {
-                         bits = i;
-
-                         for (j = 0; bits != -1 && j < nbanks - 1; j++)
-                                 if (mem_decode[i][j] != bank_sizes[j])
-                                         bits = -1;    /* No hit */
-                         if (mem_decode[i][nbanks - 1] < bank_sizes[nbanks - 1])
-                                 bits = -1;    /* The last bank is too small */
-                 }
-/*
- * The last resort is to search for a combination where the last bank is
- * smaller than the actual SIMM. This leaves some memory in the last bank
- * unused but doesn't leave holes in the DRAM address space.
- */
+               {
+                       bits = i;
+
+                       for (j = 0; bits != -1 && j < nbanks - 1; j++)
+                               if (mem_decode[i][j] != bank_sizes[j])
+                                       bits = -1;      /* No hit */
+                       if (mem_decode[i][nbanks - 1] < bank_sizes[nbanks - 1])
+                               bits = -1;      /* The last bank is too small */
+               }
+       }
+       /*
+        * The last resort is to search for a combination where the last bank is
+        * smaller than the actual SIMM. This leaves some memory in the last bank
+        * unused but doesn't leave holes in the DRAM address space.
+        */
        if (bits == -1)         /* No luck yet */
-         {
-                 for (i = 0; bits == -1 && i < 13; i++)
-                   {
-                           bits = i;
-
-                           for (j = 0; bits != -1 && j < nbanks - 1; j++)
-                                   if (mem_decode[i][j] != bank_sizes[j])
-                                           bits = -1;  /* No hit */
-                   }
-
-                 if (bits != -1)
-                   {
-                           printk("Interwave: Can't use all installed RAM.\n");
-                           printk("Interwave: Try reordering SIMMS.\n");
-                   }
-         }
+       {
+               for (i = 0; bits == -1 && i < 13; i++)
+               {
+                       bits = i;
+
+                       for (j = 0; bits != -1 && j < nbanks - 1; j++)
+                               if (mem_decode[i][j] != bank_sizes[j])
+                                       bits = -1;      /* No hit */
+               }
+               if (bits != -1)
+               {
+                       printk(KERN_INFO "Interwave: Can't use all installed RAM.\n");
+                       printk(KERN_INFO "Interwave: Try reordering SIMMS.\n");
+               }
+       }
        if (bits == -1)
-         {
-                 printk("Interwave: Can't find working DRAM encoding.\n");
-                 printk("Interwave: Defaulting to 256k. Try reordering SIMMS.\n");
-                 bits = 0;
-         }
+       {
+               printk(KERN_INFO "Interwave: Can't find working DRAM encoding.\n");
+               printk(KERN_INFO "Interwave: Defaulting to 256k. Try reordering SIMMS.\n");
+               bits = 0;
+       }
        DDB(printk("Interwave: Selecting DRAM addressing mode %d\n", bits));
 
        for (bank = 0; bank < 4; bank++)
-         {
-                 DDB(printk("  Bank %d, mem=%dk (limit %dk)\n", bank, bank_sizes[bank] / 1024, mem_decode[bits][bank] / 1024));
+       {
+               DDB(printk("  Bank %d, mem=%dk (limit %dk)\n", bank, bank_sizes[bank] / 1024, mem_decode[bits][bank] / 1024));
 
-                 if (bank_sizes[bank] > mem_decode[bits][bank])
-                         total += mem_decode[bits][bank];
-                 else
-                         total += bank_sizes[bank];
-         }
+               if (bank_sizes[bank] > mem_decode[bits][bank])
+                       total += mem_decode[bits][bank];
+               else
+                       total += bank_sizes[bank];
+       }
 
        DDB(printk("Total %dk of DRAM (enhanced mode)\n", total / 1024));
-/*
- *    Set the memory addressing mode.
- */
+
+       /*
+        *    Set the memory addressing mode.
+        */
        gus_write16(0x52, (gus_look16(0x52) & 0xfff0) | bits);
 
 /*      Leave the chip into enhanced mode. Disable LFO  */
@@ -1037,8 +1022,7 @@ pnp_mem_init(void)
        gus_write8(0x19, (gus_read8(0x19) | 0x01) & ~0x02);
 }
 
-int
-gus_wave_detect(int baseaddr)
+int gus_wave_detect(int baseaddr)
 {
        unsigned long   i, max_mem = 1024L;
        unsigned long   loc;
@@ -1059,15 +1043,18 @@ gus_wave_detect(int baseaddr)
        gus_write8(0x5b, ~val); /* Invert all bits */
 
        if ((gus_look8(0x5b) & 0xf0) == (val & 0xf0))   /* No change */
+       {
                if ((gus_look8(0x5b) & 0x0f) == ((~val) & 0x0f))        /* Change */
-                 {
-                         DDB(printk("Interwave chip version %d detected\n", (val & 0xf0) >> 4));
-                         gus_pnp_flag = 1;
-               } else
-                 {
-                         DDB(printk("Not an Interwave chip (%x)\n", gus_look8(0x5b)));
-                         gus_pnp_flag = 0;
-                 }
+               {
+                       DDB(printk("Interwave chip version %d detected\n", (val & 0xf0) >> 4));
+                       gus_pnp_flag = 1;
+               }
+               else
+               {
+                       DDB(printk("Not an Interwave chip (%x)\n", gus_look8(0x5b)));
+                       gus_pnp_flag = 0;
+               }
+       }
        gus_write8(0x5b, val);  /* Restore all bits */
 #endif
 
@@ -1084,28 +1071,26 @@ gus_wave_detect(int baseaddr)
        /* Now zero it out so that I can check for mirroring .. */
        gus_poke(0L, 0x00);
        for (i = 1L; i < max_mem; i++)
-         {
-                 int             n, failed;
-
-                 /* check for mirroring ... */
-                 if (gus_peek(0L) != 0)
-                         break;
-                 loc = i << 10;
-
-                 for (n = loc - 1, failed = 0; n <= loc; n++)
-                   {
-                           gus_poke(loc, 0xaa);
-                           if (gus_peek(loc) != 0xaa)
-                                   failed = 1;
-
-                           gus_poke(loc, 0x55);
-                           if (gus_peek(loc) != 0x55)
-                                   failed = 1;
-                   }
-
-                 if (failed)
-                         break;
-         }
+       {
+               int n, failed;
+
+               /* check for mirroring ... */
+               if (gus_peek(0L) != 0)
+                       break;
+               loc = i << 10;
+
+               for (n = loc - 1, failed = 0; n <= loc; n++)
+               {
+                       gus_poke(loc, 0xaa);
+                       if (gus_peek(loc) != 0xaa)
+                               failed = 1;
+                       gus_poke(loc, 0x55);
+                       if (gus_peek(loc) != 0x55)
+                               failed = 1;
+               }
+               if (failed)
+                       break;
+       }
        gus_mem_size = i << 10;
        return 1;
 }
@@ -1113,30 +1098,30 @@ gus_wave_detect(int baseaddr)
 static int guswave_ioctl(int dev, unsigned int cmd, caddr_t arg)
 {
 
-       switch (cmd) {
-       case SNDCTL_SYNTH_INFO:
-               gus_info.nr_voices = nr_voices;
-               return __copy_to_user(arg, &gus_info, sizeof(gus_info));
+       switch (cmd) 
+       {
+               case SNDCTL_SYNTH_INFO:
+                       gus_info.nr_voices = nr_voices;
+                       return copy_to_user(arg, &gus_info, sizeof(gus_info));
 
-       case SNDCTL_SEQ_RESETSAMPLES:
-               reset_sample_memory();
-               return 0;
+               case SNDCTL_SEQ_RESETSAMPLES:
+                       reset_sample_memory();
+                       return 0;
 
-       case SNDCTL_SEQ_PERCMODE:
-               return 0;
+               case SNDCTL_SEQ_PERCMODE:
+                       return 0;
 
-       case SNDCTL_SYNTH_MEMAVL:
-               return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32;
+               case SNDCTL_SYNTH_MEMAVL:
+                       return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32;
 
-       default:
-               return -EINVAL;
+               default:
+                       return -EINVAL;
        }
 }
 
-static int
-guswave_set_instr(int dev, int voice, int instr_no)
+static int guswave_set_instr(int dev, int voice, int instr_no)
 {
-       int             sample_no;
+       int sample_no;
 
        if (instr_no < 0 || instr_no > MAX_PATCH)
                instr_no = 0;   /* Default to acoustic piano */
@@ -1145,103 +1130,97 @@ guswave_set_instr(int dev, int voice, int instr_no)
                return -EINVAL;
 
        if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
-         {
-                 voices[voice].sample_pending = instr_no;
-                 return 0;
-         }
+       {
+               voices[voice].sample_pending = instr_no;
+               return 0;
+       }
        sample_no = patch_table[instr_no];
        patch_map[voice] = -1;
 
        if (sample_no == NOT_SAMPLE)
-         {
-                 printk("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
-                 return -EINVAL;       /* Patch not defined */
-         }
+       {
+/*             printk("GUS: Undefined patch %d for voice %d\n", instr_no, voice);*/
+               return -EINVAL; /* Patch not defined */
+       }
        if (sample_ptrs[sample_no] == -1)       /* Sample not loaded */
-         {
-                 printk("GUS: Sample #%d not loaded for patch %d (voice %d)\n", sample_no, instr_no, voice);
-                 return -EINVAL;
-         }
+       {
+/*             printk("GUS: Sample #%d not loaded for patch %d (voice %d)\n", sample_no, instr_no, voice);*/
+               return -EINVAL;
+       }
        sample_map[voice] = sample_no;
        patch_map[voice] = instr_no;
        return 0;
 }
 
-static int
-guswave_kill_note(int dev, int voice, int note, int velocity)
+static int guswave_kill_note(int dev, int voice, int note, int velocity)
 {
-       unsigned long   flags;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
        /* voice_alloc->map[voice] = 0xffff; */
        if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
-         {
-                 voices[voice].kill_pending = 1;
-                 restore_flags(flags);
-       } else
-         {
-                 restore_flags(flags);
-                 gus_voice_fade(voice);
-         }
+       {
+               voices[voice].kill_pending = 1;
+               restore_flags(flags);
+       }
+       else
+       {
+               restore_flags(flags);
+               gus_voice_fade(voice);
+       }
 
        restore_flags(flags);
        return 0;
 }
 
-static void
-guswave_aftertouch(int dev, int voice, int pressure)
+static void guswave_aftertouch(int dev, int voice, int pressure)
 {
 }
 
-static void
-guswave_panning(int dev, int voice, int value)
+static void guswave_panning(int dev, int voice, int value)
 {
        if (voice >= 0 || voice < 32)
                voices[voice].panning = value;
 }
 
-static void
-guswave_volume_method(int dev, int mode)
+static void guswave_volume_method(int dev, int mode)
 {
        if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO)
                volume_method = mode;
 }
 
-static void
-compute_volume(int voice, int volume)
+static void compute_volume(int voice, int volume)
 {
        if (volume < 128)
                voices[voice].midi_volume = volume;
 
        switch (volume_method)
-         {
-         case VOL_METHOD_ADAGIO:
-                 voices[voice].initial_volume =
-                     gus_adagio_vol(voices[voice].midi_volume, voices[voice].main_vol,
-                                    voices[voice].expression_vol,
-                                    voices[voice].patch_vol);
-                 break;
-
-         case VOL_METHOD_LINEAR:       /* Totally ignores patch-volume and expression */
-                 voices[voice].initial_volume =
-                     gus_linear_vol(volume, voices[voice].main_vol);
-                 break;
-
-         default:
-                 voices[voice].initial_volume = volume_base +
-                     (voices[voice].midi_volume * volume_scale);
-         }
+       {
+               case VOL_METHOD_ADAGIO:
+                       voices[voice].initial_volume =
+                               gus_adagio_vol(voices[voice].midi_volume, voices[voice].main_vol,
+                                       voices[voice].expression_vol,
+                                       voices[voice].patch_vol);
+                       break;
+
+               case VOL_METHOD_LINEAR: /* Totally ignores patch-volume and expression */
+                       voices[voice].initial_volume = gus_linear_vol(volume, voices[voice].main_vol);
+                       break;
+
+               default:
+                       voices[voice].initial_volume = volume_base +
+                               (voices[voice].midi_volume * volume_scale);
+       }
 
        if (voices[voice].initial_volume > 4030)
                voices[voice].initial_volume = 4030;
 }
 
-static void
-compute_and_set_volume(int voice, int volume, int ramp_time)
+static void compute_and_set_volume(int voice, int volume, int ramp_time)
 {
-       int             curr, target, rate;
-       unsigned long   flags;
+       int curr, target, rate;
+       unsigned long flags;
 
        compute_volume(voice, volume);
        voices[voice].current_volume = voices[voice].initial_volume;
@@ -1249,7 +1228,7 @@ compute_and_set_volume(int voice, int volume, int ramp_time)
        save_flags(flags);
        cli();
        /*
-          * CAUTION! Interrupts disabled. Enable them before returning
+        * CAUTION! Interrupts disabled. Enable them before returning
         */
 
        gus_select_voice(voice);
@@ -1258,12 +1237,12 @@ compute_and_set_volume(int voice, int volume, int ramp_time)
        target = voices[voice].initial_volume;
 
        if (ramp_time == INSTANT_RAMP)
-         {
-                 gus_rampoff();
-                 gus_voice_volume(target);
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               gus_rampoff();
+               gus_voice_volume(target);
+               restore_flags(flags);
+               return;
+       }
        if (ramp_time == FAST_RAMP)
                rate = 63;
        else
@@ -1271,34 +1250,34 @@ compute_and_set_volume(int voice, int volume, int ramp_time)
        gus_ramp_rate(0, rate);
 
        if ((target - curr) / 64 == 0)  /* Close enough to target. */
-         {
-                 gus_rampoff();
-                 gus_voice_volume(target);
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               gus_rampoff();
+               gus_voice_volume(target);
+               restore_flags(flags);
+               return;
+       }
        if (target > curr)
-         {
-                 if (target > (4095 - 65))
-                         target = 4095 - 65;
-                 gus_ramp_range(curr, target);
-                 gus_rampon(0x00);     /* Ramp up, once, no IRQ */
-       } else
-         {
-                 if (target < 65)
-                         target = 65;
-
-                 gus_ramp_range(target, curr);
-                 gus_rampon(0x40);     /* Ramp down, once, no irq */
-         }
+       {
+               if (target > (4095 - 65))
+                       target = 4095 - 65;
+               gus_ramp_range(curr, target);
+               gus_rampon(0x00);       /* Ramp up, once, no IRQ */
+       }
+       else
+       {
+               if (target < 65)
+                       target = 65;
+
+               gus_ramp_range(target, curr);
+               gus_rampon(0x40);       /* Ramp down, once, no irq */
+       }
        restore_flags(flags);
 }
 
-static void
-dynamic_volume_change(int voice)
+static void dynamic_volume_change(int voice)
 {
-       unsigned char   status;
-       unsigned long   flags;
+       unsigned char status;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
@@ -1310,10 +1289,11 @@ dynamic_volume_change(int voice)
                return;         /* Voice was not running */
 
        if (!(voices[voice].mode & WAVE_ENVELOPES))
-         {
-                 compute_and_set_volume(voice, voices[voice].midi_volume, 1);
-                 return;
-         }
+       {
+               compute_and_set_volume(voice, voices[voice].midi_volume, 1);
+               return;
+       }
+       
        /*
         * Voice is running and has envelopes.
         */
@@ -1325,10 +1305,10 @@ dynamic_volume_change(int voice)
        restore_flags(flags);
 
        if (status & 0x03)      /* Sustain phase? */
-         {
-                 compute_and_set_volume(voice, voices[voice].midi_volume, 1);
-                 return;
-         }
+       {
+               compute_and_set_volume(voice, voices[voice].midi_volume, 1);
+               return;
+       }
        if (voices[voice].env_phase < 0)
                return;
 
@@ -1336,8 +1316,7 @@ dynamic_volume_change(int voice)
 
 }
 
-static void
-guswave_controller(int dev, int voice, int ctrl_num, int value)
+static void guswave_controller(int dev, int voice, int ctrl_num, int value)
 {
        unsigned long   flags;
        unsigned long   freq;
@@ -1346,88 +1325,84 @@ guswave_controller(int dev, int voice, int ctrl_num, int value)
                return;
 
        switch (ctrl_num)
-         {
-         case CTRL_PITCH_BENDER:
-                 voices[voice].bender = value;
-
-                 if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
-                   {
-                           freq = compute_finetune(voices[voice].orig_freq, value,
-                                         voices[voice].bender_range, 0);
-                           voices[voice].current_freq = freq;
-
-                           save_flags(flags);
-                           cli();
-                           gus_select_voice(voice);
-                           gus_voice_freq(freq);
-                           restore_flags(flags);
-                   }
-                 break;
-
-         case CTRL_PITCH_BENDER_RANGE:
-                 voices[voice].bender_range = value;
-                 break;
-         case CTL_EXPRESSION:
-                 value /= 128;
-         case CTRL_EXPRESSION:
-                 if (volume_method == VOL_METHOD_ADAGIO)
-                   {
-                           voices[voice].expression_vol = value;
-                           if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
-                                   dynamic_volume_change(voice);
-                   }
-                 break;
-
-         case CTL_PAN:
-                 voices[voice].panning = (value * 2) - 128;
-                 break;
-
-         case CTL_MAIN_VOLUME:
-                 value = (value * 100) / 16383;
-
-         case CTRL_MAIN_VOLUME:
-                 voices[voice].main_vol = value;
-                 if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
-                         dynamic_volume_change(voice);
-                 break;
-
-         default:
-                 break;
-         }
+       {
+               case CTRL_PITCH_BENDER:
+                       voices[voice].bender = value;
+
+                       if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+                       {
+                               freq = compute_finetune(voices[voice].orig_freq, value, voices[voice].bender_range, 0);
+                               voices[voice].current_freq = freq;
+
+                               save_flags(flags);
+                               cli();
+                               gus_select_voice(voice);
+                               gus_voice_freq(freq);
+                               restore_flags(flags);
+                       }
+                       break;
+
+               case CTRL_PITCH_BENDER_RANGE:
+                       voices[voice].bender_range = value;
+                       break;
+               case CTL_EXPRESSION:
+                       value /= 128;
+               case CTRL_EXPRESSION:
+                       if (volume_method == VOL_METHOD_ADAGIO)
+                       {
+                               voices[voice].expression_vol = value;
+                               if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+                                       dynamic_volume_change(voice);
+                       }
+                       break;
+
+               case CTL_PAN:
+                       voices[voice].panning = (value * 2) - 128;
+                       break;
+
+               case CTL_MAIN_VOLUME:
+                       value = (value * 100) / 16383;
+
+               case CTRL_MAIN_VOLUME:
+                       voices[voice].main_vol = value;
+                       if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+                               dynamic_volume_change(voice);
+                       break;
+
+               default:
+                       break;
+       }
 }
 
-static int
-guswave_start_note2(int dev, int voice, int note_num, int volume)
+static int guswave_start_note2(int dev, int voice, int note_num, int volume)
 {
-       int             sample, best_sample, best_delta, delta_freq;
-       int             is16bits, samplep, patch, pan;
+       int sample, best_sample, best_delta, delta_freq;
+       int is16bits, samplep, patch, pan;
        unsigned long   note_freq, base_note, freq, flags;
        unsigned char   mode = 0;
 
        if (voice < 0 || voice > 31)
-         {
-                 printk("GUS: Invalid voice\n");
-                 return -EINVAL;
-         }
+       {
+/*             printk("GUS: Invalid voice\n");*/
+               return -EINVAL;
+       }
        if (note_num == 255)
-         {
-                 if (voices[voice].mode & WAVE_ENVELOPES)
-                   {
-                           voices[voice].midi_volume = volume;
-                           dynamic_volume_change(voice);
-                           return 0;
-                   }
-                 compute_and_set_volume(voice, volume, 1);
-                 return 0;
-         }
+       {
+               if (voices[voice].mode & WAVE_ENVELOPES)
+               {
+                       voices[voice].midi_volume = volume;
+                       dynamic_volume_change(voice);
+                       return 0;
+               }
+               compute_and_set_volume(voice, volume, 1);
+               return 0;
+       }
        if ((patch = patch_map[voice]) == -1)
-         {
-                 return -EINVAL;
-         }
+               return -EINVAL;
        if ((samplep = patch_table[patch]) == NOT_SAMPLE)
-         {
-                 return -EINVAL;
-         }
+       {
+               return -EINVAL;
+       }
        note_freq = note_to_freq(note_num);
 
        /*
@@ -1439,30 +1414,32 @@ guswave_start_note2(int dev, int voice, int note_num, int volume)
        best_sample = samplep;
        best_delta = 1000000;
        while (samplep != 0 && samplep != NOT_SAMPLE && sample == -1)
-         {
-                 delta_freq = note_freq - samples[samplep].base_note;
-                 if (delta_freq < 0)
-                         delta_freq = -delta_freq;
-                 if (delta_freq < best_delta)
-                   {
-                           best_sample = samplep;
-                           best_delta = delta_freq;
-                   }
-                 if (samples[samplep].low_note <= note_freq &&
-                     note_freq <= samples[samplep].high_note)
-                         sample = samplep;
-                 else
-                         samplep = samples[samplep].key;       /* Link to next sample */
+       {
+               delta_freq = note_freq - samples[samplep].base_note;
+               if (delta_freq < 0)
+                       delta_freq = -delta_freq;
+               if (delta_freq < best_delta)
+               {
+                       best_sample = samplep;
+                       best_delta = delta_freq;
+               }
+               if (samples[samplep].low_note <= note_freq &&
+                       note_freq <= samples[samplep].high_note)
+               {
+                       sample = samplep;
+               }
+               else
+                       samplep = samples[samplep].key; /* Link to next sample */
          }
        if (sample == -1)
                sample = best_sample;
 
        if (sample == -1)
-         {
-                 printk("GUS: Patch %d not defined for note %d\n", patch, note_num);
-                 return 0;     /* Should play default patch ??? */
-         }
-       is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;
+       {
+/*             printk("GUS: Patch %d not defined for note %d\n", patch, note_num);*/
+               return 0;       /* Should play default patch ??? */
+       }
+       is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;
        voices[voice].mode = samples[sample].mode;
        voices[voice].patch_vol = samples[sample].volume;
 
@@ -1470,27 +1447,28 @@ guswave_start_note2(int dev, int voice, int note_num, int volume)
                gus_write8(0x15, 0x00);         /* RAM, Reset voice deactivate bit of SMSI */
 
        if (voices[voice].mode & WAVE_ENVELOPES)
-         {
-                 int             i;
-
-                 for (i = 0; i < 6; i++)
-                   {
-                           voices[voice].env_rate[i] = samples[sample].env_rate[i];
-                           voices[voice].env_offset[i] = samples[sample].env_offset[i];
-                   }
-         }
+       {
+               int i;
+
+               for (i = 0; i < 6; i++)
+               {
+                       voices[voice].env_rate[i] = samples[sample].env_rate[i];
+                       voices[voice].env_offset[i] = samples[sample].env_offset[i];
+               }
+       }
        sample_map[voice] = sample;
 
        if (voices[voice].fixed_pitch)  /* Fixed pitch */
-         {
+       {
                  freq = samples[sample].base_freq;
-       } else
-         {
-                 base_note = samples[sample].base_note / 100;
-                 note_freq /= 100;
+       }
+       else
+       {
+               base_note = samples[sample].base_note / 100;
+               note_freq /= 100;
 
-                 freq = samples[sample].base_freq * note_freq / base_note;
-         }
+               freq = samples[sample].base_freq * note_freq / base_note;
+       }
 
        voices[voice].orig_freq = freq;
 
@@ -1511,15 +1489,15 @@ guswave_start_note2(int dev, int voice, int note_num, int volume)
                pan = 15;
 
        if (samples[sample].mode & WAVE_16_BITS)
-         {
-                 mode |= 0x04; /* 16 bits */
-                 if ((sample_ptrs[sample] / GUS_BANK_SIZE) !=
-                     ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE))
-                         printk("GUS: Sample address error\n");
-         }
-  /*************************************************************************
-   *    CAUTION!        Interrupts disabled. Don't return before enabling
-   *************************************************************************/
+       {
+               mode |= 0x04;   /* 16 bits */
+               if ((sample_ptrs[sample] / GUS_BANK_SIZE) !=
+                       ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE))
+                               printk(KERN_ERR "GUS: Sample address error\n");
+       }
+       /*************************************************************************
+        *    CAUTION!        Interrupts disabled. Don't return before enabling
+        *************************************************************************/
 
        save_flags(flags);
        cli();
@@ -1530,13 +1508,14 @@ guswave_start_note2(int dev, int voice, int note_num, int volume)
        restore_flags(flags);
 
        if (voices[voice].mode & WAVE_ENVELOPES)
-         {
-                 compute_volume(voice, volume);
-                 init_envelope(voice);
-       } else
-         {
-                 compute_and_set_volume(voice, volume, 0);
-         }
+       {
+               compute_volume(voice, volume);
+               init_envelope(voice);
+       }
+       else
+       {
+               compute_and_set_volume(voice, volume, 0);
+       }
 
        save_flags(flags);
        cli();
@@ -1544,43 +1523,38 @@ guswave_start_note2(int dev, int voice, int note_num, int volume)
 
        if (samples[sample].mode & WAVE_LOOP_BACK)
                gus_write_addr(0x0a, sample_ptrs[sample] + samples[sample].len -
-                              voices[voice].offset_pending, 0, is16bits);      /* start=end */
+                       voices[voice].offset_pending, 0, is16bits);     /* start=end */
        else
-               gus_write_addr(0x0a, sample_ptrs[sample] + voices[voice].offset_pending,
-                              0, is16bits);    /* Sample start=begin */
+               gus_write_addr(0x0a, sample_ptrs[sample] + voices[voice].offset_pending, 0, is16bits);  /* Sample start=begin */
 
        if (samples[sample].mode & WAVE_LOOPING)
-         {
-                 mode |= 0x08;
+       {
+               mode |= 0x08;
 
-                 if (samples[sample].mode & WAVE_BIDIR_LOOP)
-                         mode |= 0x10;
+               if (samples[sample].mode & WAVE_BIDIR_LOOP)
+                       mode |= 0x10;
 
-                 if (samples[sample].mode & WAVE_LOOP_BACK)
-                   {
-                           gus_write_addr(0x0a,
-                                          sample_ptrs[sample] + samples[sample].loop_end -
+               if (samples[sample].mode & WAVE_LOOP_BACK)
+               {
+                       gus_write_addr(0x0a, sample_ptrs[sample] + samples[sample].loop_end -
                                           voices[voice].offset_pending,
                                           (samples[sample].fractions >> 4) & 0x0f, is16bits);
-                           mode |= 0x40;
-                   }
-                 gus_write_addr(0x02, sample_ptrs[sample] + samples[sample].loop_start,
-                                samples[sample].fractions & 0x0f,
-                                is16bits);     /* Loop start location */
-                 gus_write_addr(0x04, sample_ptrs[sample] + samples[sample].loop_end,
-                                (samples[sample].fractions >> 4) & 0x0f,
-                                is16bits);     /* Loop end location */
-       } else
-         {
-                 mode |= 0x20; /* Loop IRQ at the end */
-                 voices[voice].loop_irq_mode = LMODE_FINISH;   /* Ramp down at the end */
-                 voices[voice].loop_irq_parm = 1;
-                 gus_write_addr(0x02, sample_ptrs[sample],
-                                0, is16bits);  /* Loop start location */
-                 gus_write_addr(0x04, sample_ptrs[sample] + samples[sample].len - 1,
-                                (samples[sample].fractions >> 4) & 0x0f,
-                                is16bits);     /* Loop end location */
-         }
+                       mode |= 0x40;
+               }
+               gus_write_addr(0x02, sample_ptrs[sample] + samples[sample].loop_start,
+                       samples[sample].fractions & 0x0f, is16bits);    /* Loop start location */
+               gus_write_addr(0x04, sample_ptrs[sample] + samples[sample].loop_end,
+                       (samples[sample].fractions >> 4) & 0x0f, is16bits);     /* Loop end location */
+       }
+       else
+       {
+               mode |= 0x20;   /* Loop IRQ at the end */
+               voices[voice].loop_irq_mode = LMODE_FINISH;     /* Ramp down at the end */
+               voices[voice].loop_irq_parm = 1;
+               gus_write_addr(0x02, sample_ptrs[sample], 0, is16bits); /* Loop start location */
+               gus_write_addr(0x04, sample_ptrs[sample] + samples[sample].len - 1,
+                       (samples[sample].fractions >> 4) & 0x0f, is16bits);     /* Loop end location */
+       }
        gus_voice_freq(freq);
        gus_voice_balance(pan);
        gus_voice_on(mode);
@@ -1595,82 +1569,81 @@ guswave_start_note2(int dev, int voice, int note_num, int volume)
  * ramping.
  */
 
-static int
-guswave_start_note(int dev, int voice, int note_num, int volume)
+static int guswave_start_note(int dev, int voice, int note_num, int volume)
 {
-       long int        flags;
-       int             mode;
-       int             ret_val = 0;
+       long int flags;
+       int mode;
+       int ret_val = 0;
 
        save_flags(flags);
        cli();
        if (note_num == 255)
-         {
-                 if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
-                   {
-                           voices[voice].volume_pending = volume;
-                 } else
-                   {
-                           ret_val = guswave_start_note2(dev, voice, note_num, volume);
-                   }
-       } else
-         {
-                 gus_select_voice(voice);
-                 mode = gus_read8(0x00);
-                 if (mode & 0x20)
-                         gus_write8(0x00, mode & 0xdf);        /* No interrupt! */
-
-                 voices[voice].offset_pending = 0;
-                 voices[voice].kill_pending = 0;
-                 voices[voice].volume_irq_mode = 0;
-                 voices[voice].loop_irq_mode = 0;
-
-                 if (voices[voice].sample_pending >= 0)
-                   {
-                           restore_flags(flags);       /* Run temporarily with interrupts enabled */
-                           guswave_set_instr(voices[voice].dev_pending, voice,
-                                          voices[voice].sample_pending);
-                           voices[voice].sample_pending = -1;
-                           save_flags(flags);
-                           cli();
-                           gus_select_voice(voice);    /* Reselect the voice (just to be sure) */
-                   }
-                 if ((mode & 0x01) || (int) ((gus_read16(0x09) >> 4) < (unsigned) 2065))
-                   {
-                           ret_val = guswave_start_note2(dev, voice, note_num, volume);
-                 } else
-                   {
-                           voices[voice].dev_pending = dev;
-                           voices[voice].note_pending = note_num;
-                           voices[voice].volume_pending = volume;
-                           voices[voice].volume_irq_mode = VMODE_START_NOTE;
-
-                           gus_rampoff();
-                           gus_ramp_range(2000, 4065);
-                           gus_ramp_rate(0, 63);       /* Fastest possible rate */
-                           gus_rampon(0x20 | 0x40);    /* Ramp down, once, irq */
-                   }
-         }
+       {
+               if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+               {
+                       voices[voice].volume_pending = volume;
+               }
+               else
+               {
+                       ret_val = guswave_start_note2(dev, voice, note_num, volume);
+               }
+       }
+       else
+       {
+               gus_select_voice(voice);
+               mode = gus_read8(0x00);
+               if (mode & 0x20)
+                       gus_write8(0x00, mode & 0xdf);  /* No interrupt! */
+
+               voices[voice].offset_pending = 0;
+               voices[voice].kill_pending = 0;
+               voices[voice].volume_irq_mode = 0;
+               voices[voice].loop_irq_mode = 0;
+
+               if (voices[voice].sample_pending >= 0)
+               {
+                       restore_flags(flags);   /* Run temporarily with interrupts enabled */
+                       guswave_set_instr(voices[voice].dev_pending, voice, voices[voice].sample_pending);
+                       voices[voice].sample_pending = -1;
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);        /* Reselect the voice (just to be sure) */
+               }
+               if ((mode & 0x01) || (int) ((gus_read16(0x09) >> 4) < (unsigned) 2065))
+               {
+                       ret_val = guswave_start_note2(dev, voice, note_num, volume);
+               }
+               else
+               {
+                       voices[voice].dev_pending = dev;
+                       voices[voice].note_pending = note_num;
+                       voices[voice].volume_pending = volume;
+                       voices[voice].volume_irq_mode = VMODE_START_NOTE;
+
+                       gus_rampoff();
+                       gus_ramp_range(2000, 4065);
+                       gus_ramp_rate(0, 63);   /* Fastest possible rate */
+                       gus_rampon(0x20 | 0x40);        /* Ramp down, once, irq */
+               }
+       }
        restore_flags(flags);
        return ret_val;
 }
 
-static void
-guswave_reset(int dev)
+static void guswave_reset(int dev)
 {
-       int             i;
+       int i;
 
        for (i = 0; i < 32; i++)
-         {
-                 gus_voice_init(i);
-                 gus_voice_init2(i);
-         }
+       {
+               gus_voice_init(i);
+               gus_voice_init2(i);
+       }
 }
 
-static int
-guswave_open(int dev, int mode)
+static int guswave_open(int dev, int mode)
 {
-       int             err;
+       int err;
 
        if (gus_busy)
                return -EBUSY;
@@ -1678,10 +1651,11 @@ guswave_open(int dev, int mode)
        voice_alloc->timestamp = 0;
 
        if ((err = DMAbuf_open_dma(gus_devnum)) < 0)
-         {
-                 /* printk( "GUS: Loading samples without DMA\n"); */
-                 gus_no_dma = 1;       /* Upload samples using PIO */
-       } else
+       {
+               /* printk( "GUS: Loading samples without DMA\n"); */
+               gus_no_dma = 1; /* Upload samples using PIO */
+       }
+       else
                gus_no_dma = 0;
 
        dram_sleep_flag.opts = WK_NONE;
@@ -1696,8 +1670,7 @@ guswave_open(int dev, int mode)
        return 0;
 }
 
-static void
-guswave_close(int dev)
+static void guswave_close(int dev)
 {
        gus_busy = 0;
        active_device = 0;
@@ -1707,35 +1680,34 @@ guswave_close(int dev)
                DMAbuf_close_dma(gus_devnum);
 }
 
-static int
-guswave_load_patch(int dev, int format, const char *addr,
+static int guswave_load_patch(int dev, int format, const char *addr,
                   int offs, int count, int pmgr_flag)
 {
        struct patch_info patch;
-       int             instr;
-       long            sizeof_patch;
+       int instr;
+       long sizeof_patch;
 
-       unsigned long   blk_sz, blk_end, left, src_offs, target;
+       unsigned long blk_sz, blk_end, left, src_offs, target;
 
        sizeof_patch = (long) &patch.data[0] - (long) &patch;   /* Header size */
 
        if (format != GUS_PATCH)
-         {
-                 printk("GUS Error: Invalid patch format (key) 0x%x\n", format);
-                 return -EINVAL;
-         }
+       {
+/*             printk("GUS Error: Invalid patch format (key) 0x%x\n", format);*/
+               return -EINVAL;
+       }
        if (count < sizeof_patch)
-         {
-                 printk("GUS Error: Patch header too short\n");
+       {
+/*               printk("GUS Error: Patch header too short\n");*/
                  return -EINVAL;
-         }
+       }
        count -= sizeof_patch;
 
        if (free_sample >= MAX_SAMPLE)
-         {
-                 printk("GUS: Sample table full\n");
+       {
+/*               printk("GUS: Sample table full\n");*/
                  return -ENOSPC;
-         }
+       }
        /*
         * Copy the header from user space but ignore the first bytes which have
         * been transferred already.
@@ -1746,63 +1718,63 @@ guswave_load_patch(int dev, int format, const char *addr,
        if (patch.mode & WAVE_ROM)
                return -EINVAL;
        if (gus_mem_size == 0)
-
                return -ENOSPC;
 
        instr = patch.instr_no;
 
        if (instr < 0 || instr > MAX_PATCH)
-         {
-                 printk("GUS: Invalid patch number %d\n", instr);
-                 return -EINVAL;
-         }
+       {
+/*             printk(KERN_ERR "GUS: Invalid patch number %d\n", instr);*/
+               return -EINVAL;
+       }
        if (count < patch.len)
-         {
-                 printk("GUS Warning: Patch record too short (%d<%d)\n", count, (int) patch.len);
-                 patch.len = count;
-         }
+       {
+/*             printk(KERN_ERR "GUS Warning: Patch record too short (%d<%d)\n", count, (int) patch.len);*/
+               patch.len = count;
+       }
        if (patch.len <= 0 || patch.len > gus_mem_size)
-         {
-                 printk("GUS: Invalid sample length %d\n", (int) patch.len);
-                 return -EINVAL;
-         }
+       {
+/*             printk(KERN_ERR "GUS: Invalid sample length %d\n", (int) patch.len);*/
+               return -EINVAL;
+       }
        if (patch.mode & WAVE_LOOPING)
-         {
-                 if (patch.loop_start < 0 || patch.loop_start >= patch.len)
-                   {
-                           printk("GUS: Invalid loop start\n");
-                           return -EINVAL;
-                   }
-                 if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
-                   {
-                           printk("GUS: Invalid loop end\n");
-                           return -EINVAL;
-                   }
-         }
+       {
+               if (patch.loop_start < 0 || patch.loop_start >= patch.len)
+               {
+/*                     printk(KERN_ERR "GUS: Invalid loop start\n");*/
+                       return -EINVAL;
+               }
+               if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
+               {
+/*                     printk(KERN_ERR "GUS: Invalid loop end\n");*/
+                       return -EINVAL;
+               }
+       }
        free_mem_ptr = (free_mem_ptr + 31) & ~31;       /* 32 byte alignment */
 
        if (patch.mode & WAVE_16_BITS)
-         {
-                 /*
-                  * 16 bit samples must fit one 256k bank.
-                  */
-                 if (patch.len >= GUS_BANK_SIZE)
-                   {
-                           printk("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
-                           return -ENOSPC;
-                   }
-                 if ((free_mem_ptr / GUS_BANK_SIZE) !=
-                     ((free_mem_ptr + patch.len) / GUS_BANK_SIZE))
-                   {
-                           unsigned long   tmp_mem =   /* Align to 256K */
-                           ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
-
-                           if ((tmp_mem + patch.len) > gus_mem_size)
-                                   return -ENOSPC;
-
-                           free_mem_ptr = tmp_mem;     /* This leaves unusable memory */
-                   }
-         }
+       {
+               /*
+                * 16 bit samples must fit one 256k bank.
+                */
+               if (patch.len >= GUS_BANK_SIZE)
+               {
+/*                      printk("GUS: Sample (16 bit) too long %d\n", (int) patch.len);*/
+                       return -ENOSPC;
+               }
+               if ((free_mem_ptr / GUS_BANK_SIZE) !=
+                       ((free_mem_ptr + patch.len) / GUS_BANK_SIZE))
+               {
+                       unsigned long   tmp_mem =       
+                               /* Align to 256K */
+                                       ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
+
+                       if ((tmp_mem + patch.len) > gus_mem_size)
+                               return -ENOSPC;
+
+                       free_mem_ptr = tmp_mem;         /* This leaves unusable memory */
+               }
+       }
        if ((free_mem_ptr + patch.len) > gus_mem_size)
                return -ENOSPC;
 
@@ -1816,9 +1788,9 @@ guswave_load_patch(int dev, int format, const char *addr,
                patch.mode &= ~WAVE_TREMOLO;
 
        if (!(patch.mode & WAVE_FRACTIONS))
-         {
+       {
                  patch.fractions = 0;
-         }
+       }
        memcpy((char *) &samples[free_sample], &patch, sizeof_patch);
 
        /*
@@ -1837,162 +1809,154 @@ guswave_load_patch(int dev, int format, const char *addr,
        target = free_mem_ptr;
 
        while (left)            /* Not completely transferred yet */
-         {
-                 blk_sz = audio_devs[gus_devnum]->dmap_out->bytes_in_use;
-                 if (blk_sz > left)
-                         blk_sz = left;
-
-                 /*
-                  * DMA cannot cross bank (256k) boundaries. Check for that.
-                  */
-                 blk_end = target + blk_sz;
-
-                 if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE))
-                   {           /* Split the block */
-
-                           blk_end &= ~(GUS_BANK_SIZE - 1);
-                           blk_sz = blk_end - target;
-                   }
-                 if (gus_no_dma)
-                   {
-                           /*
-                            * For some reason the DMA is not possible. We have to use PIO.
-                            */
-                           long            i;
-                           unsigned char   data;
-
-                           for (i = 0; i < blk_sz; i++)
-                             {
-                                     get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[sizeof_patch + i]));
-                                     if (patch.mode & WAVE_UNSIGNED)
-                                             if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
-                                                     data ^= 0x80;     /* Convert to signed */
-                                     gus_poke(target + i, data);
-                             }
-                 } else
-                   {
-                           unsigned long   address, hold_address;
-                           unsigned char   dma_command;
-                           unsigned long   flags;
-
-                           if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL)
-                             {
-                                     printk("GUS: DMA buffer == NULL\n");
-                                     return -ENOSPC;
-                             }
-                           /*
-                            * OK, move now. First in and then out.
-                            */
-
-                           copy_from_user(audio_devs[gus_devnum]->dmap_out->raw_buf, &(addr)[sizeof_patch + src_offs], blk_sz);
-
-                           save_flags(flags);
-                           cli();
-/******** INTERRUPTS DISABLED NOW ********/
-                           gus_write8(0x41, 0);        /* Disable GF1 DMA */
-                           DMAbuf_start_dma(gus_devnum,
-                                            audio_devs[gus_devnum]->dmap_out->raw_buf_phys,
-                                            blk_sz, DMA_MODE_WRITE);
-
-                           /*
-                            * Set the DRAM address for the wave data
-                            */
-
-                           if (iw_mode)
-                             {
-                                     /* Different address translation in enhanced mode */
-
-                                     unsigned char   hi;
-
-                                     if (gus_dma > 4)
-                                             address = target >> 1;    /* Convert to 16 bit word address */
-                                     else
-                                             address = target;
-
-                                     hi = (unsigned char) ((address >> 16) & 0xf0);
-                                     hi += (unsigned char) (address & 0x0f);
-
-                                     gus_write16(0x42, (address >> 4) & 0xffff);       /* DMA address (low) */
-                                     gus_write8(0x50, hi);
-                           } else
-                             {
-                                     address = target;
-
-                                     if (audio_devs[gus_devnum]->dmap_out->dma > 3)
-                                       {
-                                               hold_address = address;
-                                               address = address >> 1;
-                                               address &= 0x0001ffffL;
-                                               address |= (hold_address & 0x000c0000L);
-                                       }
-                                     gus_write16(0x42, (address >> 4) & 0xffff);       /* DRAM DMA address */
-                             }
-
-                           /*
-                            * Start the DMA transfer
-                            */
-
-                           dma_command = 0x21;         /* IRQ enable, DMA start */
-                           if (patch.mode & WAVE_UNSIGNED)
-                                   dma_command |= 0x80;        /* Invert MSB */
-                           if (patch.mode & WAVE_16_BITS)
-                                   dma_command |= 0x40;        /* 16 bit _DATA_ */
-                           if (audio_devs[gus_devnum]->dmap_out->dma > 3)
-                                   dma_command |= 0x04;        /* 16 bit DMA _channel_ */
-
-                           gus_write8(0x41, dma_command);      /* Lets go luteet (=bugs) */
-
-                           /*
-                            * Sleep here until the DRAM DMA done interrupt is served
-                            */
-                           active_device = GUS_DEV_WAVE;
-
-
-                           {
-                                   unsigned long   tlimit;
-
-                                   if (HZ)
-                                           current->timeout = tlimit = jiffies + (HZ);
-                                   else
-                                           tlimit = (unsigned long) -1;
-                                   dram_sleep_flag.opts = WK_SLEEP;
-                                   interruptible_sleep_on(&dram_sleeper);
-                                   if (!(dram_sleep_flag.opts & WK_WAKEUP))
-                                     {
-                                             if (jiffies >= tlimit)
-                                                     dram_sleep_flag.opts |= WK_TIMEOUT;
-                                     }
-                                   dram_sleep_flag.opts &= ~WK_SLEEP;
-                           };
-                           if ((dram_sleep_flag.opts & WK_TIMEOUT))
-                                   printk("GUS: DMA Transfer timed out\n");
-                           restore_flags(flags);
-                   }
-
-                 /*
-                  * Now the next part
-                  */
-
-                 left -= blk_sz;
-                 src_offs += blk_sz;
-                 target += blk_sz;
-
-                 gus_write8(0x41, 0);  /* Stop DMA */
-         }
+       {
+               blk_sz = audio_devs[gus_devnum]->dmap_out->bytes_in_use;
+               if (blk_sz > left)
+                       blk_sz = left;
 
-       free_mem_ptr += patch.len;
+               /*
+                * DMA cannot cross bank (256k) boundaries. Check for that.
+                */
+                
+               blk_end = target + blk_sz;
+
+               if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE))
+               {
+                       /* Split the block */
+                       blk_end &= ~(GUS_BANK_SIZE - 1);
+                       blk_sz = blk_end - target;
+               }
+               if (gus_no_dma)
+               {
+                       /*
+                        * For some reason the DMA is not possible. We have to use PIO.
+                        */
+                       long i;
+                       unsigned char data;
+
+                       for (i = 0; i < blk_sz; i++)
+                       {
+                               get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[sizeof_patch + i]));
+                               if (patch.mode & WAVE_UNSIGNED)
+                                       if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
+                                               data ^= 0x80;   /* Convert to signed */
+                               gus_poke(target + i, data);
+                       }
+               }
+               else
+               {
+                       unsigned long address, hold_address;
+                       unsigned char dma_command;
+                       unsigned long flags;
+                       unsigned long tlimit;
 
+                       if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL)
+                       {
+                               printk(KERN_ERR "GUS: DMA buffer == NULL\n");
+                               return -ENOSPC;
+                       }
+                       /*
+                        * OK, move now. First in and then out.
+                        */
+
+                       copy_from_user(audio_devs[gus_devnum]->dmap_out->raw_buf, &(addr)[sizeof_patch + src_offs], blk_sz);
+
+                       save_flags(flags);
+                       cli();
+                       /******** INTERRUPTS DISABLED NOW ********/
+                       gus_write8(0x41, 0);    /* Disable GF1 DMA */
+                       DMAbuf_start_dma(gus_devnum, audio_devs[gus_devnum]->dmap_out->raw_buf_phys,
+                               blk_sz, DMA_MODE_WRITE);
+
+                       /*
+                        * Set the DRAM address for the wave data
+                        */
+
+                       if (iw_mode)
+                       {
+                               /* Different address translation in enhanced mode */
+
+                               unsigned char   hi;
+
+                               if (gus_dma > 4)
+                                       address = target >> 1;  /* Convert to 16 bit word address */
+                               else
+                                       address = target;
+
+                               hi = (unsigned char) ((address >> 16) & 0xf0);
+                               hi += (unsigned char) (address & 0x0f);
+
+                               gus_write16(0x42, (address >> 4) & 0xffff);     /* DMA address (low) */
+                               gus_write8(0x50, hi);
+                       }
+                       else
+                       {
+                               address = target;
+                               if (audio_devs[gus_devnum]->dmap_out->dma > 3)
+                               {
+                                       hold_address = address;
+                                       address = address >> 1;
+                                       address &= 0x0001ffffL;
+                                       address |= (hold_address & 0x000c0000L);
+                               }
+                               gus_write16(0x42, (address >> 4) & 0xffff);     /* DRAM DMA address */
+                       }
+
+                       /*
+                        * Start the DMA transfer
+                        */
+
+                       dma_command = 0x21;             /* IRQ enable, DMA start */
+                       if (patch.mode & WAVE_UNSIGNED)
+                               dma_command |= 0x80;    /* Invert MSB */
+                       if (patch.mode & WAVE_16_BITS)
+                               dma_command |= 0x40;    /* 16 bit _DATA_ */
+                       if (audio_devs[gus_devnum]->dmap_out->dma > 3)
+                               dma_command |= 0x04;    /* 16 bit DMA _channel_ */
+                       
+                       gus_write8(0x41, dma_command);  /* Lets go luteet (=bugs) */
+
+                       /*
+                        * Sleep here until the DRAM DMA done interrupt is served
+                        */
+                       active_device = GUS_DEV_WAVE;
+
+                       current->timeout = tlimit = jiffies + HZ;
+                       dram_sleep_flag.opts = WK_SLEEP;
+                       interruptible_sleep_on(&dram_sleeper);
+                       if (!(dram_sleep_flag.opts & WK_WAKEUP))
+                       {
+                               if (jiffies >= tlimit)
+                                       dram_sleep_flag.opts |= WK_TIMEOUT;
+                       }
+                       dram_sleep_flag.opts &= ~WK_SLEEP;
+                       if ((dram_sleep_flag.opts & WK_TIMEOUT))
+                               printk(KERN_WARNING "GUS: DMA Transfer timed out\n");
+                       restore_flags(flags);
+               }
+
+               /*
+                * Now the next part
+                */
+
+               left -= blk_sz;
+               src_offs += blk_sz;
+               target += blk_sz;
+
+               gus_write8(0x41, 0);    /* Stop DMA */
+       }
+
+       free_mem_ptr += patch.len;
        free_sample++;
        return 0;
 }
 
-static void
-guswave_hw_control(int dev, unsigned char *event_rec)
+static void guswave_hw_control(int dev, unsigned char *event_rec)
 {
-       int             voice, cmd;
-       unsigned short  p1, p2;
-       unsigned int    plong;
-       unsigned        flags;
+       int voice, cmd;
+       unsigned short p1, p2;
+       unsigned int plong;
+       unsigned flags;
 
        cmd = event_rec[2];
        voice = event_rec[3];
@@ -2001,156 +1965,152 @@ guswave_hw_control(int dev, unsigned char *event_rec)
        plong = *(unsigned int *) &event_rec[4];
 
        if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&
-           (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
+               (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
                do_volume_irq(voice);
 
        switch (cmd)
-         {
-
-         case _GUS_NUMVOICES:
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_select_max_voices(p1);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_VOICESAMPLE:
-                 guswave_set_instr(dev, voice, p1);
-                 break;
-
-         case _GUS_VOICEON:
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 p1 &= ~0x20;  /* Don't allow interrupts */
-                 gus_voice_on(p1);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_VOICEOFF:
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_voice_off();
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_VOICEFADE:
-                 gus_voice_fade(voice);
-                 break;
-
-         case _GUS_VOICEMODE:
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 p1 &= ~0x20;  /* Don't allow interrupts */
-                 gus_voice_mode(p1);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_VOICEBALA:
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_voice_balance(p1);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_VOICEFREQ:
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_voice_freq(plong);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_VOICEVOL:
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_voice_volume(p1);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_VOICEVOL2:  /* Just update the software voice level */
-                 voices[voice].initial_volume =
-                     voices[voice].current_volume = p1;
-                 break;
-
-         case _GUS_RAMPRANGE:
-                 if (voices[voice].mode & WAVE_ENVELOPES)
-                         break;        /* NO-NO */
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_ramp_range(p1, p2);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_RAMPRATE:
-                 if (voices[voice].mode & WAVE_ENVELOPES)
-                         break;        /* NJET-NJET */
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_ramp_rate(p1, p2);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_RAMPMODE:
-                 if (voices[voice].mode & WAVE_ENVELOPES)
-                         break;        /* NO-NO */
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 p1 &= ~0x20;  /* Don't allow interrupts */
-                 gus_ramp_mode(p1);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_RAMPON:
-                 if (voices[voice].mode & WAVE_ENVELOPES)
-                         break;        /* EI-EI */
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 p1 &= ~0x20;  /* Don't allow interrupts */
-                 gus_rampon(p1);
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_RAMPOFF:
-                 if (voices[voice].mode & WAVE_ENVELOPES)
-                         break;        /* NEJ-NEJ */
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_rampoff();
-                 restore_flags(flags);
-                 break;
-
-         case _GUS_VOLUME_SCALE:
-                 volume_base = p1;
-                 volume_scale = p2;
-                 break;
-
-         case _GUS_VOICE_POS:
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(voice);
-                 gus_set_voice_pos(voice, plong);
-                 restore_flags(flags);
-                 break;
-
-         default:;
-         }
+       {
+               case _GUS_NUMVOICES:
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_select_max_voices(p1);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_VOICESAMPLE:
+                       guswave_set_instr(dev, voice, p1);
+                       break;
+
+               case _GUS_VOICEON:
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       p1 &= ~0x20;    /* Don't allow interrupts */
+                       gus_voice_on(p1);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_VOICEOFF:
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_voice_off();
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_VOICEFADE:
+                       gus_voice_fade(voice);
+                       break;
+
+               case _GUS_VOICEMODE:
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       p1 &= ~0x20;    /* Don't allow interrupts */
+                       gus_voice_mode(p1);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_VOICEBALA:
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_voice_balance(p1);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_VOICEFREQ:
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_voice_freq(plong);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_VOICEVOL:
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_voice_volume(p1);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_VOICEVOL2:    /* Just update the software voice level */
+                       voices[voice].initial_volume = voices[voice].current_volume = p1;
+                       break;
+
+               case _GUS_RAMPRANGE:
+                       if (voices[voice].mode & WAVE_ENVELOPES)
+                               break;  /* NO-NO */
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_ramp_range(p1, p2);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_RAMPRATE:
+                       if (voices[voice].mode & WAVE_ENVELOPES)
+                               break;  /* NJET-NJET */
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_ramp_rate(p1, p2);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_RAMPMODE:
+                       if (voices[voice].mode & WAVE_ENVELOPES)
+                               break;  /* NO-NO */
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       p1 &= ~0x20;    /* Don't allow interrupts */
+                       gus_ramp_mode(p1);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_RAMPON:
+                       if (voices[voice].mode & WAVE_ENVELOPES)
+                               break;  /* EI-EI */
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       p1 &= ~0x20;    /* Don't allow interrupts */
+                       gus_rampon(p1);
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_RAMPOFF:
+                       if (voices[voice].mode & WAVE_ENVELOPES)
+                               break;  /* NEJ-NEJ */
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_rampoff();
+                       restore_flags(flags);
+                       break;
+
+               case _GUS_VOLUME_SCALE:
+                       volume_base = p1;
+                       volume_scale = p2;
+                       break;
+
+               case _GUS_VOICE_POS:
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_set_voice_pos(voice, plong);
+                       restore_flags(flags);
+                       break;
+
+               default:
+       }
 }
 
-static int
-gus_audio_set_speed(int speed)
+static int gus_audio_set_speed(int speed)
 {
-
        if (speed <= 0)
                speed = gus_audio_speed;
 
@@ -2163,18 +2123,17 @@ gus_audio_set_speed(int speed)
        gus_audio_speed = speed;
 
        if (only_read_access)
-         {
-                 /* Compute nearest valid recording speed  and return it */
+       {
+               /* Compute nearest valid recording speed  and return it */
 
-                 /* speed = (9878400 / (gus_audio_speed + 2)) / 16; */
-                 speed = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16;
-                 speed = (9878400 / (speed * 16)) - 2;
-         }
+               /* speed = (9878400 / (gus_audio_speed + 2)) / 16; */
+               speed = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16;
+               speed = (9878400 / (speed * 16)) - 2;
+       }
        return speed;
 }
 
-static int
-gus_audio_set_channels(int channels)
+static int gus_audio_set_channels(int channels)
 {
        if (!channels)
                return gus_audio_channels;
@@ -2186,8 +2145,7 @@ gus_audio_set_channels(int channels)
        return channels;
 }
 
-static int
-gus_audio_set_bits(int bits)
+static int gus_audio_set_bits(int bits)
 {
        if (!bits)
                return gus_audio_bits;
@@ -2206,70 +2164,75 @@ static int gus_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
 {
        int val;
 
-       switch (cmd) {
-       case SOUND_PCM_WRITE_RATE:
-               if (__get_user(val, (int *)arg))
-                       return -EFAULT;
-               val = gus_audio_set_speed(val);
-               return __put_user(val, (int *)arg);
+       switch (cmd) 
+       {
+               case SOUND_PCM_WRITE_RATE:
+                       if (get_user(val, (int *)arg))
+                               return -EFAULT;
+                       val = gus_audio_set_speed(val);
+                       break;
 
-       case SOUND_PCM_READ_RATE:
-               return __put_user(gus_audio_speed, (int *)arg);
+               case SOUND_PCM_READ_RATE:
+                       val = gus_audio_speed;
+                       break;
 
-       case SNDCTL_DSP_STEREO:
-               if (__get_user(val, (int *)arg))
-                       return -EFAULT;
-               val = gus_audio_set_channels(val + 1) - 1;
-               return __put_user(val, (int *)arg);
+               case SNDCTL_DSP_STEREO:
+                       if (get_user(val, (int *)arg))
+                               return -EFAULT;
+                       val = gus_audio_set_channels(val + 1) - 1;
+                       break;
 
-       case SOUND_PCM_WRITE_CHANNELS:
-               if (__get_user(val, (int *)arg))
-                       return -EFAULT;
-               val = gus_audio_set_channels(val);
-               return __put_user(val, (int *)arg);
+               case SOUND_PCM_WRITE_CHANNELS:
+                       if (get_user(val, (int *)arg))
+                               return -EFAULT;
+                       val = gus_audio_set_channels(val);
+                       break;
 
-       case SOUND_PCM_READ_CHANNELS:
-               return __put_user(gus_audio_channels, (int *)arg);
+               case SOUND_PCM_READ_CHANNELS:
+                       val = gus_audio_channels;
+                       break;
                
-       case SNDCTL_DSP_SETFMT:
-               if (__get_user(val, (int *)arg))
-                       return -EFAULT;
-               val = gus_audio_set_bits(val);
-               return __put_user(val, (int *)arg);
+               case SNDCTL_DSP_SETFMT:
+                       if (get_user(val, (int *)arg))
+                               return -EFAULT;
+                       val = gus_audio_set_bits(val);
+                       break;
                
-       case SOUND_PCM_READ_BITS:
-               return __put_user(gus_audio_bits, (int *)arg);
+               case SOUND_PCM_READ_BITS:
+                       val = gus_audio_bits;
+                       break;
                
-       case SOUND_PCM_WRITE_FILTER:            /* NOT POSSIBLE */
-       case SOUND_PCM_READ_FILTER:
-               return __put_user(-EINVAL, (int *)arg);
+               case SOUND_PCM_WRITE_FILTER:            /* NOT POSSIBLE */
+               case SOUND_PCM_READ_FILTER:
+                       val = -EINVAL;
+                       break;
+               default:
+                       return -EINVAL;
        }
-       return -EINVAL;
+       return put_user(val, (int *)arg);
 }
 
-static void
-gus_audio_reset(int dev)
+static void gus_audio_reset(int dev)
 {
        if (recording_active)
-         {
-                 gus_write8(0x49, 0x00);       /* Halt recording */
-                 set_input_volumes();
-         }
+       {
+               gus_write8(0x49, 0x00); /* Halt recording */
+               set_input_volumes();
+       }
 }
 
-static int      saved_iw_mode; /* A hack hack hack */
+static int saved_iw_mode;      /* A hack hack hack */
 
-static int
-gus_audio_open(int dev, int mode)
+static int gus_audio_open(int dev, int mode)
 {
        if (gus_busy)
                return -EBUSY;
 
        if (gus_pnp_flag && mode & OPEN_READ)
-         {
-                 printk("GUS: Audio device #%d is playback only.\n", dev);
-                 return -EIO;
-         }
+       {
+/*             printk(KERN_ERR "GUS: Audio device #%d is playback only.\n", dev);*/
+               return -EIO;
+       }
        gus_initialize();
 
        gus_busy = 1;
@@ -2280,19 +2243,19 @@ gus_audio_open(int dev, int mode)
        gus_select_max_voices(14);
        saved_iw_mode = iw_mode;
        if (iw_mode)
-         {
-                 /* There are some problems with audio in enhanced mode so disable it */
-                 gus_write8(0x19, gus_read8(0x19) & ~0x01);    /* Disable enhanced mode */
-                 iw_mode = 0;
-         }
+       {
+               /* There are some problems with audio in enhanced mode so disable it */
+               gus_write8(0x19, gus_read8(0x19) & ~0x01);      /* Disable enhanced mode */
+               iw_mode = 0;
+       }
        pcm_active = 0;
        dma_active = 0;
        pcm_opened = 1;
        if (mode & OPEN_READ)
-         {
-                 recording_active = 1;
-                 set_input_volumes();
-         }
+       {
+               recording_active = 1;
+               set_input_volumes();
+       }
        only_read_access = !(mode & OPEN_WRITE);
        only_8_bits = mode & OPEN_READ;
        if (only_8_bits)
@@ -2303,8 +2266,7 @@ gus_audio_open(int dev, int mode)
        return 0;
 }
 
-static void
-gus_audio_close(int dev)
+static void gus_audio_close(int dev)
 {
        iw_mode = saved_iw_mode;
        gus_reset();
@@ -2313,40 +2275,38 @@ gus_audio_close(int dev)
        active_device = 0;
 
        if (recording_active)
-         {
-                 gus_write8(0x49, 0x00);       /* Halt recording */
-                 set_input_volumes();
-         }
+       {
+               gus_write8(0x49, 0x00); /* Halt recording */
+               set_input_volumes();
+       }
        recording_active = 0;
 }
 
-static void
-gus_audio_update_volume(void)
+static void gus_audio_update_volume(void)
 {
-       unsigned long   flags;
-       int             voice;
+       unsigned long flags;
+       int voice;
 
        if (pcm_active && pcm_opened)
                for (voice = 0; voice < gus_audio_channels; voice++)
-                 {
-                         save_flags(flags);
-                         cli();
-                         gus_select_voice(voice);
-                         gus_rampoff();
-                         gus_voice_volume(1530 + (25 * gus_pcm_volume));
-                         gus_ramp_range(65, 1530 + (25 * gus_pcm_volume));
-                         restore_flags(flags);
-                 }
+               {
+                       save_flags(flags);
+                       cli();
+                       gus_select_voice(voice);
+                       gus_rampoff();
+                       gus_voice_volume(1530 + (25 * gus_pcm_volume));
+                       gus_ramp_range(65, 1530 + (25 * gus_pcm_volume));
+                       restore_flags(flags);
+               }
 }
 
-static void
-play_next_pcm_block(void)
+static void play_next_pcm_block(void)
 {
-       unsigned long   flags;
-       int             speed = gus_audio_speed;
-       int             this_one, is16bits, chn;
-       unsigned long   dram_loc;
-       unsigned char   mode[2], ramp_mode[2];
+       unsigned long flags;
+       int speed = gus_audio_speed;
+       int this_one, is16bits, chn;
+       unsigned long dram_loc;
+       unsigned char mode[2], ramp_mode[2];
 
        if (!pcm_qlen)
                return;
@@ -2354,95 +2314,91 @@ play_next_pcm_block(void)
        this_one = pcm_head;
 
        for (chn = 0; chn < gus_audio_channels; chn++)
-         {
-                 mode[chn] = 0x00;
-                 ramp_mode[chn] = 0x03;        /* Ramping and rollover off */
-
-                 if (chn == 0)
-                   {
-                           mode[chn] |= 0x20;  /* Loop IRQ */
-                           voices[chn].loop_irq_mode = LMODE_PCM;
-                   }
-                 if (gus_audio_bits != 8)
-                   {
-                           is16bits = 1;
-                           mode[chn] |= 0x04;  /* 16 bit data */
-                 } else
-                         is16bits = 0;
-
-                 dram_loc = this_one * pcm_bsize;
-                 dram_loc += chn * pcm_banksize;
-
-                 if (this_one == (pcm_nblk - 1))       /* Last fragment of the DRAM buffer */
-                   {
-                           mode[chn] |= 0x08;  /* Enable loop */
-                           ramp_mode[chn] = 0x03;      /* Disable rollover bit */
-                 } else
-                   {
-                           if (chn == 0)
-                                   ramp_mode[chn] = 0x04;      /* Enable rollover bit */
-                   }
-
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(chn);
-                 gus_voice_freq(speed);
-
-                 if (gus_audio_channels == 1)
-                         gus_voice_balance(7);         /* mono */
-                 else if (chn == 0)
-                         gus_voice_balance(0);         /* left */
-                 else
-                         gus_voice_balance(15);        /* right */
-
-                 if (!pcm_active)      /* Playback not already active */
-                   {
-                           /*
-                            * The playback was not started yet (or there has been a pause).
-                            * Start the voice (again) and ask for a rollover irq at the end of
-                            * this_one block. If this_one one is last of the buffers, use just
-                            * the normal loop with irq.
-                            */
-
-                           gus_voice_off();
-                           gus_rampoff();
-                           gus_voice_volume(1530 + (25 * gus_pcm_volume));
-                           gus_ramp_range(65, 1530 + (25 * gus_pcm_volume));
-
-                           gus_write_addr(0x0a, chn * pcm_banksize, 0, is16bits);      /* Starting position */
-                           gus_write_addr(0x02, chn * pcm_banksize, 0, is16bits);      /* Loop start */
-
-                           if (chn != 0)
-                                   gus_write_addr(0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1,
-                                                  0, is16bits);        /* Loop end location */
-                   }
-                 if (chn == 0)
-                         gus_write_addr(0x04, dram_loc + pcm_bsize - 1,
-                                        0, is16bits);  /* Loop end location */
-                 else
-                         mode[chn] |= 0x08;    /* Enable looping */
+       {
+               mode[chn] = 0x00;
+               ramp_mode[chn] = 0x03;  /* Ramping and rollover off */
 
+               if (chn == 0)
+               {
+                       mode[chn] |= 0x20;      /* Loop IRQ */
+                       voices[chn].loop_irq_mode = LMODE_PCM;
+               }
+               if (gus_audio_bits != 8)
+               {
+                       is16bits = 1;
+                       mode[chn] |= 0x04;      /* 16 bit data */
+               }
+               else
+                       is16bits = 0;
 
-                 restore_flags(flags);
-         }
+               dram_loc = this_one * pcm_bsize;
+               dram_loc += chn * pcm_banksize;
 
-       for (chn = 0; chn < gus_audio_channels; chn++)
-         {
-                 save_flags(flags);
-                 cli();
-                 gus_select_voice(chn);
-                 gus_write8(0x0d, ramp_mode[chn]);
-                 if (iw_mode)
-                         gus_write8(0x15, 0x00);       /* Reset voice deactivate bit of SMSI */
-                 gus_voice_on(mode[chn]);
-                 restore_flags(flags);
-         }
+               if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */
+               {
+                       mode[chn] |= 0x08;      /* Enable loop */
+                       ramp_mode[chn] = 0x03;  /* Disable rollover bit */
+               }
+               else
+               {
+                       if (chn == 0)
+                               ramp_mode[chn] = 0x04;  /* Enable rollover bit */
+               }
+               save_flags(flags);
+               cli();
+               gus_select_voice(chn);
+               gus_voice_freq(speed);
+
+               if (gus_audio_channels == 1)
+                       gus_voice_balance(7);           /* mono */
+               else if (chn == 0)
+                       gus_voice_balance(0);           /* left */
+               else
+                       gus_voice_balance(15);          /* right */
 
+               if (!pcm_active)        /* Playback not already active */
+               {
+                       /*
+                        * The playback was not started yet (or there has been a pause).
+                        * Start the voice (again) and ask for a rollover irq at the end of
+                        * this_one block. If this_one one is last of the buffers, use just
+                        * the normal loop with irq.
+                        */
+
+                       gus_voice_off();
+                       gus_rampoff();
+                       gus_voice_volume(1530 + (25 * gus_pcm_volume));
+                       gus_ramp_range(65, 1530 + (25 * gus_pcm_volume));
+
+                       gus_write_addr(0x0a, chn * pcm_banksize, 0, is16bits);  /* Starting position */
+                       gus_write_addr(0x02, chn * pcm_banksize, 0, is16bits);  /* Loop start */
+
+                       if (chn != 0)
+                               gus_write_addr(0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1,
+                                                  0, is16bits);        /* Loop end location */
+               }
+               if (chn == 0)
+                       gus_write_addr(0x04, dram_loc + pcm_bsize - 1,
+                                        0, is16bits);  /* Loop end location */
+               else
+                       mode[chn] |= 0x08;      /* Enable looping */
+               restore_flags(flags);
+       }
+       for (chn = 0; chn < gus_audio_channels; chn++)
+       {
+               save_flags(flags);
+               cli();
+               gus_select_voice(chn);
+               gus_write8(0x0d, ramp_mode[chn]);
+               if (iw_mode)
+                       gus_write8(0x15, 0x00); /* Reset voice deactivate bit of SMSI */
+               gus_voice_on(mode[chn]);
+               restore_flags(flags);
+       }
        pcm_active = 1;
 }
 
-static void
-gus_transfer_output_block(int dev, unsigned long buf,
+static void gus_transfer_output_block(int dev, unsigned long buf,
                          int total_count, int intrflag, int chn)
 {
        /*
@@ -2454,10 +2410,10 @@ gus_transfer_output_block(int dev, unsigned long buf,
         * right data to the area pointed by gus_page_size.
         */
 
-       int             this_one, count;
-       unsigned long   flags;
-       unsigned char   dma_command;
-       unsigned long   address, hold_address;
+       int this_one, count;
+       unsigned long flags;
+       unsigned char dma_command;
+       unsigned long address, hold_address;
 
        save_flags(flags);
        cli();
@@ -2465,15 +2421,16 @@ gus_transfer_output_block(int dev, unsigned long buf,
        count = total_count / gus_audio_channels;
 
        if (chn == 0)
-         {
-                 if (pcm_qlen >= pcm_nblk)
-                         printk("GUS Warning: PCM buffers out of sync\n");
-
-                 this_one = pcm_current_block = pcm_tail;
-                 pcm_qlen++;
-                 pcm_tail = (pcm_tail + 1) % pcm_nblk;
-                 pcm_datasize[this_one] = count;
-       } else
+       {
+               if (pcm_qlen >= pcm_nblk)
+                       printk(KERN_WARNING "GUS Warning: PCM buffers out of sync\n");
+
+               this_one = pcm_current_block = pcm_tail;
+               pcm_qlen++;
+               pcm_tail = (pcm_tail + 1) % pcm_nblk;
+               pcm_datasize[this_one] = count;
+       }
+       else
                this_one = pcm_current_block;
 
        gus_write8(0x41, 0);    /* Disable GF1 DMA */
@@ -2483,12 +2440,12 @@ gus_transfer_output_block(int dev, unsigned long buf,
        address += chn * pcm_banksize;
 
        if (audio_devs[dev]->dmap_out->dma > 3)
-         {
-                 hold_address = address;
-                 address = address >> 1;
-                 address &= 0x0001ffffL;
-                 address |= (hold_address & 0x000c0000L);
-         }
+       {
+               hold_address = address;
+               address = address >> 1;
+               address &= 0x0001ffffL;
+               address |= (hold_address & 0x000c0000L);
+       }
        gus_write16(0x42, (address >> 4) & 0xffff);     /* DRAM DMA address */
 
        dma_command = 0x21;     /* IRQ enable, DMA start */
@@ -2504,62 +2461,60 @@ gus_transfer_output_block(int dev, unsigned long buf,
        gus_write8(0x41, dma_command);  /* Kick start */
 
        if (chn == (gus_audio_channels - 1))    /* Last channel */
-         {
-                 /*
-                  * Last (right or mono) channel data
-                  */
-                 dma_active = 1;       /* DMA started. There is a unacknowledged buffer */
-                 active_device = GUS_DEV_PCM_DONE;
-                 if (!pcm_active && (pcm_qlen > 1 || count < pcm_bsize))
-                   {
-                           play_next_pcm_block();
-                   }
-       } else
-         {
-                 /*
-                    * Left channel data. The right channel
-                    * is transferred after DMA interrupt
-                  */
-                 active_device = GUS_DEV_PCM_CONTINUE;
-         }
+       {
+               /*
+                * Last (right or mono) channel data
+                */
+               dma_active = 1; /* DMA started. There is a unacknowledged buffer */
+               active_device = GUS_DEV_PCM_DONE;
+               if (!pcm_active && (pcm_qlen > 1 || count < pcm_bsize))
+               {
+                       play_next_pcm_block();
+               }
+       }
+       else
+       {
+               /*
+                * Left channel data. The right channel
+                * is transferred after DMA interrupt
+                */
+               active_device = GUS_DEV_PCM_CONTINUE;
+       }
 
        restore_flags(flags);
 }
 
-static void
-gus_uninterleave8(char *buf, int l)
+static void gus_uninterleave8(char *buf, int l)
 {
 /* This routine uninterleaves 8 bit stereo output (LRLRLR->LLLRRR) */
-       int             i, p = 0, halfsize = l / 2;
-       char           *buf2 = buf + halfsize, *src = bounce_buf;
+       int i, p = 0, halfsize = l / 2;
+       char *buf2 = buf + halfsize, *src = bounce_buf;
 
        memcpy(bounce_buf, buf, l);
 
        for (i = 0; i < halfsize; i++)
-         {
-                 buf[i] = src[p++];    /* Left channel */
-                 buf2[i] = src[p++];   /* Right channel */
-         }
+       {
+               buf[i] = src[p++];      /* Left channel */
+               buf2[i] = src[p++];     /* Right channel */
+       }
 }
 
-static void
-gus_uninterleave16(short *buf, int l)
+static void gus_uninterleave16(short *buf, int l)
 {
 /* This routine uninterleaves 16 bit stereo output (LRLRLR->LLLRRR) */
-       int             i, p = 0, halfsize = l / 2;
-       short          *buf2 = buf + halfsize, *src = (short *) bounce_buf;
+       int i, p = 0, halfsize = l / 2;
+       short *buf2 = buf + halfsize, *src = (short *) bounce_buf;
 
        memcpy(bounce_buf, (char *) buf, l * 2);
 
        for (i = 0; i < halfsize; i++)
-         {
-                 buf[i] = src[p++];    /* Left channel */
-                 buf2[i] = src[p++];   /* Right channel */
-         }
+       {
+               buf[i] = src[p++];      /* Left channel */
+               buf2[i] = src[p++];     /* Right channel */
+       }
 }
 
-static void
-gus_audio_output_block(int dev, unsigned long buf, int total_count,
+static void gus_audio_output_block(int dev, unsigned long buf, int total_count,
                       int intrflag)
 {
        struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
@@ -2571,29 +2526,27 @@ gus_audio_output_block(int dev, unsigned long buf, int total_count,
        pcm_current_intrflag = intrflag;
        pcm_current_dev = dev;
        if (gus_audio_channels == 2)
-         {
-                 char           *b = dmap->raw_buf + (buf - dmap->raw_buf_phys);
+       {
+               char *b = dmap->raw_buf + (buf - dmap->raw_buf_phys);
 
-                 if (gus_audio_bits == 8)
-                         gus_uninterleave8(b, total_count);
-                 else
-                         gus_uninterleave16((short *) b, total_count / 2);
-         }
+               if (gus_audio_bits == 8)
+                       gus_uninterleave8(b, total_count);
+               else
+                       gus_uninterleave16((short *) b, total_count / 2);
+       }
        gus_transfer_output_block(dev, buf, total_count, intrflag, 0);
 }
 
-static void
-gus_audio_start_input(int dev, unsigned long buf, int count,
+static void gus_audio_start_input(int dev, unsigned long buf, int count,
                      int intrflag)
 {
-       unsigned long   flags;
-       unsigned char   mode;
+       unsigned long flags;
+       unsigned char mode;
 
        save_flags(flags);
        cli();
 
        DMAbuf_start_dma(dev, buf, count, DMA_MODE_READ);
-
        mode = 0xa0;            /* DMA IRQ enabled, invert MSB */
 
        if (audio_devs[dev]->dmap_in->dma > 3)
@@ -2603,14 +2556,12 @@ gus_audio_start_input(int dev, unsigned long buf, int count,
        mode |= 0x01;           /* DMA enable */
 
        gus_write8(0x49, mode);
-
        restore_flags(flags);
 }
 
-static int
-gus_audio_prepare_for_input(int dev, int bsize, int bcount)
+static int gus_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
-       unsigned int    rate;
+       unsigned int rate;
 
        gus_audio_bsize = bsize;
        audio_devs[dev]->dmap_in->flags |= DMA_NODMA;
@@ -2619,19 +2570,18 @@ gus_audio_prepare_for_input(int dev, int bsize, int bcount)
        gus_write8(0x48, rate & 0xff);  /* Set sampling rate */
 
        if (gus_audio_bits != 8)
-         {
-                 printk("GUS Error: 16 bit recording not supported\n");
-                 return -EINVAL;
-         }
+       {
+/*             printk("GUS Error: 16 bit recording not supported\n");*/
+               return -EINVAL;
+       }
        return 0;
 }
 
-static int
-gus_audio_prepare_for_output(int dev, int bsize, int bcount)
+static int gus_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
-       int             i;
+       int i;
 
-       long            mem_ptr, mem_size;
+       long mem_ptr, mem_size;
 
        audio_devs[dev]->dmap_out->flags |= DMA_NODMA | DMA_NOTIMEOUT;
        mem_ptr = 0;
@@ -2655,12 +2605,10 @@ gus_audio_prepare_for_output(int dev, int bsize, int bcount)
        if (gus_audio_bits != 8 && pcm_banksize == (256 * 1024))
                pcm_nblk--;
        gus_write8(0x41, 0);    /* Disable GF1 DMA */
-
        return 0;
 }
 
-static int
-gus_local_qlen(int dev)
+static int gus_local_qlen(int dev)
 {
        return pcm_qlen;
 }
@@ -2680,20 +2628,14 @@ static struct audio_driver gus_audio_driver =
        NULL
 };
 
-static void
-guswave_setup_voice(int dev, int voice, int chn)
+static void guswave_setup_voice(int dev, int voice, int chn)
 {
-       struct channel_info *info =
-       &synth_devs[dev]->chn_info[chn];
+       struct channel_info *info = &synth_devs[dev]->chn_info[chn];
 
        guswave_set_instr(dev, voice, info->pgm_num);
-
-       voices[voice].expression_vol =
-           info->controllers[CTL_EXPRESSION];  /* Just MSB */
-       voices[voice].main_vol =
-           (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
-       voices[voice].panning =
-           (info->controllers[CTL_PAN] * 2) - 128;
+       voices[voice].expression_vol = info->controllers[CTL_EXPRESSION];       /* Just MSB */
+       voices[voice].main_vol = (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
+       voices[voice].panning = (info->controllers[CTL_PAN] * 2) - 128;
        voices[voice].bender = 0;
        voices[voice].bender_range = info->bender_range;
 
@@ -2701,15 +2643,13 @@ guswave_setup_voice(int dev, int voice, int chn)
                voices[voice].fixed_pitch = 1;
 }
 
-static void
-guswave_bender(int dev, int voice, int value)
+static void guswave_bender(int dev, int voice, int value)
 {
-       int             freq;
+       int freq;
        unsigned long   flags;
 
        voices[voice].bender = value - 8192;
-       freq = compute_finetune(voices[voice].orig_freq, value - 8192,
-                               voices[voice].bender_range, 0);
+       freq = compute_finetune(voices[voice].orig_freq, value - 8192, voices[voice].bender_range, 0);
        voices[voice].current_freq = freq;
 
        save_flags(flags);
@@ -2719,45 +2659,43 @@ guswave_bender(int dev, int voice, int value)
        restore_flags(flags);
 }
 
-static int
-guswave_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
+static int guswave_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
 {
-       int             i, p, best = -1, best_time = 0x7fffffff;
+       int i, p, best = -1, best_time = 0x7fffffff;
 
        p = alloc->ptr;
        /*
-          * First look for a completely stopped voice
+        * First look for a completely stopped voice
         */
 
        for (i = 0; i < alloc->max_voice; i++)
-         {
-                 if (alloc->map[p] == 0)
-                   {
-                           alloc->ptr = p;
-                           return p;
-                   }
-                 if (alloc->alloc_times[p] < best_time)
-                   {
-                           best = p;
-                           best_time = alloc->alloc_times[p];
-                   }
-                 p = (p + 1) % alloc->max_voice;
-         }
+       {
+               if (alloc->map[p] == 0)
+               {
+                       alloc->ptr = p;
+                       return p;
+               }
+               if (alloc->alloc_times[p] < best_time)
+               {
+                       best = p;
+                       best_time = alloc->alloc_times[p];
+               }
+               p = (p + 1) % alloc->max_voice;
+       }
 
        /*
-          * Then look for a releasing voice
+        * Then look for a releasing voice
         */
 
        for (i = 0; i < alloc->max_voice; i++)
-         {
-                 if (alloc->map[p] == 0xffff)
-                   {
-                           alloc->ptr = p;
-                           return p;
-                   }
-                 p = (p + 1) % alloc->max_voice;
-         }
-
+       {
+               if (alloc->map[p] == 0xffff)
+               {
+                       alloc->ptr = p;
+                       return p;
+               }
+               p = (p + 1) % alloc->max_voice;
+       }
        if (best >= 0)
                p = best;
 
@@ -2790,11 +2728,10 @@ static struct synth_operations guswave_operations =
        guswave_setup_voice
 };
 
-static void
-set_input_volumes(void)
+static void set_input_volumes(void)
 {
-       unsigned long   flags;
-       unsigned char   mask = 0xff & ~0x06;    /* Just line out enabled */
+       unsigned long flags;
+       unsigned char mask = 0xff & ~0x06;      /* Just line out enabled */
 
        if (have_gus_max)       /* Don't disturb GUS MAX */
                return;
@@ -2813,15 +2750,15 @@ set_input_volumes(void)
                mask |= 0x04;
 
        if (recording_active)
-         {
-                 /*
-                  *    Disable channel, if not selected for recording
-                  */
-                 if (!(gus_recmask & SOUND_MASK_LINE))
-                         mask |= 0x01;
-                 if (!(gus_recmask & SOUND_MASK_MIC))
-                         mask &= ~0x04;
-         }
+       {
+               /*
+                *    Disable channel, if not selected for recording
+                */
+               if (!(gus_recmask & SOUND_MASK_LINE))
+                       mask |= 0x01;
+               if (!(gus_recmask & SOUND_MASK_MIC))
+                       mask &= ~0x04;
+       }
        mix_image &= ~0x07;
        mix_image |= mask & 0x07;
        outb((mix_image), u_Mixer);
@@ -2842,115 +2779,119 @@ int gus_default_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
        if (!access_ok(VERIFY_WRITE, (int *)arg, sizeof(int)))
                return -EFAULT;
 
-       if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
+       if (_SIOC_DIR(cmd) & _SIOC_WRITE) 
+       {
                if (__get_user(val, (int *) arg))
                        return -EFAULT;
 
-               switch (cmd & 0xff) {
-               case SOUND_MIXER_RECSRC:
-                       gus_recmask = val & MIX_DEVS;
-                       if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE)))
-                               gus_recmask = SOUND_MASK_MIC;
-                       /* Note! Input volumes are updated during next open for recording */
-                       val = gus_recmask;
-                       break;
-
-               case SOUND_MIXER_MIC:
-                       vol = val & 0xff;
-                       if (vol < 0)
-                               vol = 0;
-                       if (vol > 100)
-                               vol = 100;
-                       gus_mic_vol = vol;
-                       set_input_volumes();
-                       val = vol | (vol << 8);
-                       break;
+               switch (cmd & 0xff) 
+               {
+                       case SOUND_MIXER_RECSRC:
+                               gus_recmask = val & MIX_DEVS;
+                               if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE)))
+                                       gus_recmask = SOUND_MASK_MIC;
+                               /* Note! Input volumes are updated during next open for recording */
+                               val = gus_recmask;
+                               break;
+
+                       case SOUND_MIXER_MIC:
+                               vol = val & 0xff;
+                               if (vol < 0)
+                                       vol = 0;
+                               if (vol > 100)
+                                       vol = 100;
+                               gus_mic_vol = vol;
+                               set_input_volumes();
+                               val = vol | (vol << 8);
+                               break;
                                
-               case SOUND_MIXER_LINE:
-                       vol = val & 0xff;
-                       if (vol < 0)
-                               vol = 0;
-                       if (vol > 100)
-                               vol = 100;
-                       gus_line_vol = vol;
-                       set_input_volumes();
-                       val = vol | (vol << 8);
-                       break;
-
-               case SOUND_MIXER_PCM:
-                       gus_pcm_volume = val & 0xff;
-                       if (gus_pcm_volume < 0)
-                               gus_pcm_volume = 0;
-                       if (gus_pcm_volume > 100)
-                               gus_pcm_volume = 100;
-                       gus_audio_update_volume();
-                       val = gus_pcm_volume | (gus_pcm_volume << 8);
-                       break;
-
-               case SOUND_MIXER_SYNTH:
-                       gus_wave_volume = val & 0xff;
-                       if (gus_wave_volume < 0)
-                               gus_wave_volume = 0;
-                       if (gus_wave_volume > 100)
-                               gus_wave_volume = 100;
-                       if (active_device == GUS_DEV_WAVE) {
-                               int voice;
-                               for (voice = 0; voice < nr_voices; voice++)
+                       case SOUND_MIXER_LINE:
+                               vol = val & 0xff;
+                               if (vol < 0)
+                                       vol = 0;
+                               if (vol > 100)
+                                       vol = 100;
+                               gus_line_vol = vol;
+                               set_input_volumes();
+                               val = vol | (vol << 8);
+                               break;
+
+                       case SOUND_MIXER_PCM:
+                               gus_pcm_volume = val & 0xff;
+                               if (gus_pcm_volume < 0)
+                                       gus_pcm_volume = 0;
+                               if (gus_pcm_volume > 100)
+                                       gus_pcm_volume = 100;
+                               gus_audio_update_volume();
+                               val = gus_pcm_volume | (gus_pcm_volume << 8);
+                               break;
+
+                       case SOUND_MIXER_SYNTH:
+                               gus_wave_volume = val & 0xff;
+                               if (gus_wave_volume < 0)
+                                       gus_wave_volume = 0;
+                               if (gus_wave_volume > 100)
+                                       gus_wave_volume = 100;
+                               if (active_device == GUS_DEV_WAVE) 
+                               {
+                                       int voice;
+                                       for (voice = 0; voice < nr_voices; voice++)
                                        dynamic_volume_change(voice);   /* Apply the new vol */
-                       }
-                       val = gus_wave_volume | (gus_wave_volume << 8);
-                       break;
+                               }
+                               val = gus_wave_volume | (gus_wave_volume << 8);
+                               break;
 
-               default:
-                       return -EINVAL;
+                       default:
+                               return -EINVAL;
                }
-
-       } else {
-               switch (cmd & 0xff) {
-               /*
-                * Return parameters
-                */
-               case SOUND_MIXER_RECSRC:
-                       val = gus_recmask;
-                       break;
+       }
+       else
+       {
+               switch (cmd & 0xff) 
+               {
+                       /*
+                        * Return parameters
+                        */
+                       case SOUND_MIXER_RECSRC:
+                               val = gus_recmask;
+                               break;
                                        
-               case SOUND_MIXER_DEVMASK:
-                       val = MIX_DEVS;
-                       break;
+                       case SOUND_MIXER_DEVMASK:
+                               val = MIX_DEVS;
+                               break;
 
-               case SOUND_MIXER_STEREODEVS:
-                       val = 0;
-                       break;
+                       case SOUND_MIXER_STEREODEVS:
+                               val = 0;
+                               break;
 
-               case SOUND_MIXER_RECMASK:
-                       val = SOUND_MASK_MIC | SOUND_MASK_LINE;
-                       break;
+                       case SOUND_MIXER_RECMASK:
+                               val = SOUND_MASK_MIC | SOUND_MASK_LINE;
+                               break;
 
-               case SOUND_MIXER_CAPS:
-                       val = 0;
-                       break;
+                       case SOUND_MIXER_CAPS:
+                               val = 0;
+                               break;
 
-               case SOUND_MIXER_MIC:
-                       val = gus_mic_vol | (gus_mic_vol << 8);
-                       break;
+                       case SOUND_MIXER_MIC:
+                               val = gus_mic_vol | (gus_mic_vol << 8);
+                               break;
 
-               case SOUND_MIXER_LINE:
-                       val = gus_line_vol | (gus_line_vol << 8);
-                       break;
+                       case SOUND_MIXER_LINE:
+                               val = gus_line_vol | (gus_line_vol << 8);
+                               break;
 
-               case SOUND_MIXER_PCM:
-                       val = gus_pcm_volume | (gus_pcm_volume << 8);
-                       break;
+                       case SOUND_MIXER_PCM:
+                               val = gus_pcm_volume | (gus_pcm_volume << 8);
+                               break;
 
-               case SOUND_MIXER_SYNTH:
-                       val = gus_wave_volume | (gus_wave_volume << 8);
-                       break;
+                       case SOUND_MIXER_SYNTH:
+                               val = gus_wave_volume | (gus_wave_volume << 8);
+                               break;
 
-               default:
-                       return -EINVAL;
+                       default:
+                               return -EINVAL;
                }
        }
-
        return __put_user(val, (int *)arg);
 }
 
@@ -2961,43 +2902,42 @@ static struct mixer_operations gus_mixer_operations =
        gus_default_mixer_ioctl
 };
 
-static int
-gus_default_mixer_init(void)
+static int gus_default_mixer_init(void)
 {
-       int             n;
+       int n;
 
        if ((n = sound_alloc_mixerdev()) != -1)
-         {                     /*
-                                * Don't install if there is another
-                                * mixer
-                                */
-                 mixer_devs[n] = &gus_mixer_operations;
-         }
+       {       
+               /*
+                * Don't install if there is another
+                * mixer
+                */
+               mixer_devs[n] = &gus_mixer_operations;
+       }
        if (have_gus_max)
-         {
-/*
- *  Enable all mixer channels on the GF1 side. Otherwise recording will
- *  not be possible using GUS MAX.
- */
-                 mix_image &= ~0x07;
-                 mix_image |= 0x04;    /* All channels enabled */
-                 outb((mix_image), u_Mixer);
-         }
+       {
+               /*
               *  Enable all mixer channels on the GF1 side. Otherwise recording will
               *  not be possible using GUS MAX.
               */
+               mix_image &= ~0x07;
+               mix_image |= 0x04;      /* All channels enabled */
+               outb((mix_image), u_Mixer);
+       }
        return n;
 }
 
 void gus_wave_init(struct address_info *hw_config)
 {
-       unsigned long   flags;
-       unsigned char   val;
-       char           *model_num = "2.4";
-       char            tmp[64], tmp2[64];
-       int             gus_type = 0x24;        /* 2.4 */
+       unsigned long flags;
+       unsigned char val;
+       char *model_num = "2.4";
+       char tmp[64], tmp2[64];
+       int gus_type = 0x24;    /* 2.4 */
 
-       int             irq = hw_config->irq, dma = hw_config->dma,
-                       dma2 = hw_config->dma2;
-       int             dev;
-       int             sdev;
+       int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
+       int dev;
+       int sdev;
 
        hw_config->slots[0] = -1;       /* No wave */
        hw_config->slots[1] = -1;       /* No ad1848 */
@@ -3008,14 +2948,14 @@ void gus_wave_init(struct address_info *hw_config)
        {
                if (irq < 0 || irq > 15)
                {
-                       printk("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
+                       printk(KERN_ERR "ERROR! Invalid IRQ#%d. GUS Disabled", irq);
                        return;
                }
        }
        
        if (dma < 0 || dma > 7 || dma == 4)
        {
-               printk("ERROR! Invalid DMA#%d. GUS Disabled", dma);
+               printk(KERN_ERR "ERROR! Invalid DMA#%d. GUS Disabled", dma);
                return;
        }
        gus_irq = irq;
@@ -3046,7 +2986,7 @@ void gus_wave_init(struct address_info *hw_config)
                /*
                 * It has the digital ASIC so the card is at least v3.4.
                 * Next try to detect the true model.
-                  */
+                */
 
                if (gus_pnp_flag)       /* Hack hack hack */
                        val = 10;
@@ -3124,9 +3064,9 @@ void gus_wave_init(struct address_info *hw_config)
                                }
                        }
                        else
-                               printk(KERN_WARNING "[Where's the CS4231?]");
+                               printk(KERN_WARNING "GUS: No CS4231 ??");
 #else
-                       printk("\n\n\nGUS MAX support was not compiled in!!!\n\n\n\n");
+                       printk(KERN_ERR "GUS MAX found, but not compiled in\n");
 #endif
                }
        }
@@ -3291,78 +3231,77 @@ static void do_loop_irq(int voice)
        parm = voices[voice].loop_irq_parm;
 
        switch (mode)
-         {
+       {
+               case LMODE_FINISH:      /*
+                                        * Final loop finished, shoot volume down
+                                        */
 
-         case LMODE_FINISH:    /*
-                                * Final loop finished, shoot volume down
-                                */
+                       if ((int) (gus_read16(0x09) >> 4) < 100)        /*
+                                                                        * Get current volume
+                                                                        */
+                       {
+                               gus_voice_off();
+                               gus_rampoff();
+                               gus_voice_init(voice);
+                               break;
+                       }
+                       gus_ramp_range(65, 4065);
+                       gus_ramp_rate(0, 63);           /*
+                                                        * Fastest possible rate
+                                                        */
+                       gus_rampon(0x20 | 0x40);        /*
+                                                        * Ramp down, once, irq
+                                                        */
+                       voices[voice].volume_irq_mode = VMODE_HALT;
+                       break;
 
-                 if ((int) (gus_read16(0x09) >> 4) < 100)      /*
-                                                                * Get current volume
-                                                                */
-                   {
-                           gus_voice_off();
-                           gus_rampoff();
-                           gus_voice_init(voice);
-                           break;
-                   }
-                 gus_ramp_range(65, 4065);
-                 gus_ramp_rate(0, 63);         /*
-                                                * Fastest possible rate
-                                                */
-                 gus_rampon(0x20 | 0x40);      /*
-                                                * Ramp down, once, irq
-                                                */
-                 voices[voice].volume_irq_mode = VMODE_HALT;
-                 break;
-
-         case LMODE_PCM_STOP:
-                 pcm_active = 0;       /* Signal to the play_next_pcm_block routine */
-         case LMODE_PCM:
-                 {
-
-                         pcm_qlen--;
-                         pcm_head = (pcm_head + 1) % pcm_nblk;
-                         if (pcm_qlen && pcm_active)
-                           {
-                                   play_next_pcm_block();
-                         } else
-                           {   /* Underrun. Just stop the voice */
-                                   gus_select_voice(0);        /* Left channel */
-                                   gus_voice_off();
-                                   gus_rampoff();
-                                   gus_select_voice(1);        /* Right channel */
-                                   gus_voice_off();
-                                   gus_rampoff();
-                                   pcm_active = 0;
-                           }
-
-                         /*
-                          * If the queue was full before this interrupt, the DMA transfer was
-                          * suspended. Let it continue now.
-                          */
-                         if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
-                                 DMAbuf_outputintr(gus_devnum, 0);
-                 }
-                 break;
-
-         default:;
-         }
+               case LMODE_PCM_STOP:
+                       pcm_active = 0; /* Signal to the play_next_pcm_block routine */
+               case LMODE_PCM:
+               {
+                       pcm_qlen--;
+                       pcm_head = (pcm_head + 1) % pcm_nblk;
+                       if (pcm_qlen && pcm_active)
+                       {
+                               play_next_pcm_block();
+                       }
+                       else
+                       {
+                               /* Underrun. Just stop the voice */
+                               gus_select_voice(0);    /* Left channel */
+                               gus_voice_off();
+                               gus_rampoff();
+                               gus_select_voice(1);    /* Right channel */
+                               gus_voice_off();
+                               gus_rampoff();
+                               pcm_active = 0;
+                       }
+
+                       /*
+                        * If the queue was full before this interrupt, the DMA transfer was
+                        * suspended. Let it continue now.
+                        */
+                       
+                       if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
+                               DMAbuf_outputintr(gus_devnum, 0);
+               }
+               break;
+
+               default:
+       }
        restore_flags(flags);
 }
 
-static void
-do_volume_irq(int voice)
+static void do_volume_irq(int voice)
 {
-       unsigned char   tmp;
-       int             mode, parm;
-       unsigned long   flags;
+       unsigned char tmp;
+       int mode, parm;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
 
        gus_select_voice(voice);
-
        tmp = gus_read8(0x0d);
        tmp &= ~0x20;           /*
                                 * Disable volume ramp IRQ
@@ -3374,138 +3313,136 @@ do_volume_irq(int voice)
        parm = voices[voice].volume_irq_parm;
 
        switch (mode)
-         {
-         case VMODE_HALT:      /* Decay phase finished */
-                 if (iw_mode)
-                         gus_write8(0x15, 0x02);       /* Set voice deactivate bit of SMSI */
-                 restore_flags(flags);
-                 gus_voice_init(voice);
-                 break;
-
-         case VMODE_ENVELOPE:
-                 gus_rampoff();
-                 restore_flags(flags);
-                 step_envelope(voice);
-                 break;
-
-         case VMODE_START_NOTE:
-                 restore_flags(flags);
-                 guswave_start_note2(voices[voice].dev_pending, voice,
+       {
+               case VMODE_HALT:        /* Decay phase finished */
+                       if (iw_mode)
+                               gus_write8(0x15, 0x02); /* Set voice deactivate bit of SMSI */
+                       restore_flags(flags);
+                       gus_voice_init(voice);
+                       break;
+
+               case VMODE_ENVELOPE:
+                       gus_rampoff();
+                       restore_flags(flags);
+                       step_envelope(voice);
+                       break;
+
+               case VMODE_START_NOTE:
+                       restore_flags(flags);
+                       guswave_start_note2(voices[voice].dev_pending, voice,
                                      voices[voice].note_pending, voices[voice].volume_pending);
-                 if (voices[voice].kill_pending)
-                         guswave_kill_note(voices[voice].dev_pending, voice,
+                       if (voices[voice].kill_pending)
+                               guswave_kill_note(voices[voice].dev_pending, voice,
                                          voices[voice].note_pending, 0);
 
-                 if (voices[voice].sample_pending >= 0)
-                   {
-                           guswave_set_instr(voices[voice].dev_pending, voice,
-                                          voices[voice].sample_pending);
-                           voices[voice].sample_pending = -1;
-                   }
-                 break;
+                       if (voices[voice].sample_pending >= 0)
+                       {
+                               guswave_set_instr(voices[voice].dev_pending, voice,
+                                       voices[voice].sample_pending);
+                               voices[voice].sample_pending = -1;
+                       }
+                       break;
 
-         default:
-                 restore_flags(flags);
-         }
+               default:
+                       restore_flags(flags);
+       }
        restore_flags(flags);
 }
 
-void
-gus_voice_irq(void)
+void gus_voice_irq(void)
 {
-       unsigned long   wave_ignore = 0, volume_ignore = 0;
-       unsigned long   voice_bit;
+       unsigned long wave_ignore = 0, volume_ignore = 0;
+       unsigned long voice_bit;
 
-       unsigned char   src, voice;
+       unsigned char src, voice;
 
        while (1)
-         {
-                 src = gus_read8(0x0f);        /*
-                                                * Get source info
-                                                */
-                 voice = src & 0x1f;
-                 src &= 0xc0;
-
-                 if (src == (0x80 | 0x40))
-                         return;       /*
-                                        * No interrupt
+       {
+               src = gus_read8(0x0f);  /*
+                                        * Get source info
                                         */
+               voice = src & 0x1f;
+               src &= 0xc0;
+
+               if (src == (0x80 | 0x40))
+                       return; /*
+                                * No interrupt
+                                */
 
-                 voice_bit = 1 << voice;
+               voice_bit = 1 << voice;
 
-                 if (!(src & 0x80))    /*
+               if (!(src & 0x80))      /*
                                         * Wave IRQ pending
                                         */
-                         if (!(wave_ignore & voice_bit) && (int) voice < nr_voices)    /*
-                                                                                          * Not done
-                                                                                          * yet
+                       if (!(wave_ignore & voice_bit) && (int) voice < nr_voices)      /*
+                                                                                        * Not done
+                                                                                        * yet
                                                                                         */
-                           {
-                                   wave_ignore |= voice_bit;
-                                   do_loop_irq(voice);
-                           }
-                 if (!(src & 0x40))    /*
+                       {
+                               wave_ignore |= voice_bit;
+                               do_loop_irq(voice);
+                       }
+               if (!(src & 0x40))      /*
                                         * Volume IRQ pending
                                         */
-                         if (!(volume_ignore & voice_bit) && (int) voice < nr_voices)  /*
+                       if (!(volume_ignore & voice_bit) && (int) voice < nr_voices)    /*
                                                                                           * Not done
                                                                                           * yet
                                                                                         */
-                           {
-                                   volume_ignore |= voice_bit;
-                                   do_volume_irq(voice);
-                           }
-         }
+                       {
+                               volume_ignore |= voice_bit;
+                               do_volume_irq(voice);
+                       }
+       }
 }
 
-void
-guswave_dma_irq(void)
+void guswave_dma_irq(void)
 {
        unsigned char   status;
 
        status = gus_look8(0x41);       /* Get DMA IRQ Status */
        if (status & 0x40)      /* DMA interrupt pending */
                switch (active_device)
-                 {
-                 case GUS_DEV_WAVE:
-                         if ((dram_sleep_flag.opts & WK_SLEEP))
-                           {
-                                   dram_sleep_flag.opts = WK_WAKEUP;
-                                   wake_up(&dram_sleeper);
-                           };
-                         break;
-
-                 case GUS_DEV_PCM_CONTINUE:    /* Left channel data transferred */
-                         gus_write8(0x41, 0);  /* Disable GF1 DMA */
-                         gus_transfer_output_block(pcm_current_dev, pcm_current_buf,
-                                                   pcm_current_count,
+               {
+                       case GUS_DEV_WAVE:
+                               if ((dram_sleep_flag.opts & WK_SLEEP))
+                               {
+                                       dram_sleep_flag.opts = WK_WAKEUP;
+                                       wake_up(&dram_sleeper);
+                               }
+                               break;
+
+                       case GUS_DEV_PCM_CONTINUE:      /* Left channel data transferred */
+                               gus_write8(0x41, 0);    /* Disable GF1 DMA */
+                               gus_transfer_output_block(pcm_current_dev, pcm_current_buf,
+                                               pcm_current_count,
                                                pcm_current_intrflag, 1);
-                         break;
-
-                 case GUS_DEV_PCM_DONE:        /* Right or mono channel data transferred */
-                         gus_write8(0x41, 0);  /* Disable GF1 DMA */
-                         if (pcm_qlen < pcm_nblk)
-                           {
-                                   dma_active = 0;
-                                   if (gus_busy)
-                                     {
-                                             if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
-                                                     DMAbuf_outputintr(gus_devnum, 0);
-                                     }
-                           }
-                         break;
-
-                 default:;
-                 }
+                               break;
+
+                       case GUS_DEV_PCM_DONE:  /* Right or mono channel data transferred */
+                               gus_write8(0x41, 0);    /* Disable GF1 DMA */
+                               if (pcm_qlen < pcm_nblk)
+                               {
+                                       dma_active = 0;
+                                       if (gus_busy)
+                                       {
+                                               if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
+                                                       DMAbuf_outputintr(gus_devnum, 0);
+                                       }
+                               }
+                               break;
+
+                       default:
+       }
        status = gus_look8(0x49);       /*
                                         * Get Sampling IRQ Status
                                         */
        if (status & 0x40)      /*
                                 * Sampling Irq pending
                                 */
-         {
-                 DMAbuf_inputintr(gus_devnum);
-         }
+       {
+               DMAbuf_inputintr(gus_devnum);
+       }
 }
 
 #if defined(CONFIG_SEQUENCER) || defined(MODULE)
@@ -3517,10 +3454,9 @@ guswave_dma_irq(void)
 static volatile int select_addr, data_addr;
 static volatile int curr_timer = 0;
 
-void
-gus_timer_command(unsigned int addr, unsigned int val)
+void gus_timer_command(unsigned int addr, unsigned int val)
 {
-       int             i;
+       int i;
 
        outb(((unsigned char) (addr & 0xff)), select_addr);
 
@@ -3533,59 +3469,54 @@ gus_timer_command(unsigned int addr, unsigned int val)
                inb(select_addr);
 }
 
-static void
-arm_timer(int timer, unsigned int interval)
+static void arm_timer(int timer, unsigned int interval)
 {
-
        curr_timer = timer;
 
        if (timer == 1)
-         {
-                 gus_write8(0x46, 256 - interval);     /* Set counter for timer 1 */
-                 gus_write8(0x45, 0x04);       /* Enable timer 1 IRQ */
-                 gus_timer_command(0x04, 0x01);        /* Start timer 1 */
-       } else
-         {
-                 gus_write8(0x47, 256 - interval);     /* Set counter for timer 2 */
-                 gus_write8(0x45, 0x08);       /* Enable timer 2 IRQ */
-                 gus_timer_command(0x04, 0x02);        /* Start timer 2 */
-         }
+       {
+               gus_write8(0x46, 256 - interval);       /* Set counter for timer 1 */
+               gus_write8(0x45, 0x04);                 /* Enable timer 1 IRQ */
+               gus_timer_command(0x04, 0x01);          /* Start timer 1 */
+       }
+       else
+       {
+               gus_write8(0x47, 256 - interval);       /* Set counter for timer 2 */
+               gus_write8(0x45, 0x08);                 /* Enable timer 2 IRQ */
+               gus_timer_command(0x04, 0x02);          /* Start timer 2 */
+       }
 
        gus_timer_enabled = 1;
 }
 
-static unsigned int
-gus_tmr_start(int dev, unsigned int usecs_per_tick)
+static unsigned int gus_tmr_start(int dev, unsigned int usecs_per_tick)
 {
-       int             timer_no, resolution;
-       int             divisor;
+       int timer_no, resolution;
+       int divisor;
 
        if (usecs_per_tick > (256 * 80))
-         {
-                 timer_no = 2;
-                 resolution = 320;     /* usec */
-       } else
-         {
-                 timer_no = 1;
-                 resolution = 80;      /* usec */
-         }
-
+       {
+               timer_no = 2;
+               resolution = 320;       /* usec */
+       }
+       else
+       {
+               timer_no = 1;
+               resolution = 80;        /* usec */
+       }
        divisor = (usecs_per_tick + (resolution / 2)) / resolution;
-
        arm_timer(timer_no, divisor);
 
        return divisor * resolution;
 }
 
-static void
-gus_tmr_disable(int dev)
+static void gus_tmr_disable(int dev)
 {
        gus_write8(0x45, 0);    /* Disable both timers */
        gus_timer_enabled = 0;
 }
 
-static void
-gus_tmr_restart(int dev)
+static void gus_tmr_restart(int dev)
 {
        if (curr_timer == 1)
                gus_write8(0x45, 0x04);         /* Start timer 1 again */
@@ -3603,8 +3534,7 @@ static struct sound_lowlev_timer gus_tmr =
        gus_tmr_restart
 };
 
-static void
-gus_tmr_install(int io_base)
+static void gus_tmr_install(int io_base)
 {
        struct sound_lowlev_timer *tmr;
 
index 3cd56ae5bbc751dc738c537a366a8ba99fabcf4b..11c63ff1bb7a12f080c2557b343b94a63f0e89c7 100644 (file)
@@ -1101,8 +1101,7 @@ sound_alloc_dmap(int dev, struct dma_buffparms *dmap, int chan)
 
                dmap->buffsize = PAGE_SIZE * (1 << sz);
 
-               start_addr = (char *) __get_free_pages(GFP_ATOMIC | GFP_DMA, sz);
-               if (start_addr == NULL)
+               if ((start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA, sz)) == NULL)
                        dmap->buffsize /= 2;
        }
 
index a19ad233771b125bb9aa6b77d0813796994fcbc3..80562646faae77890455a612127a8a4d7fd8564f 100644 (file)
@@ -68,6 +68,7 @@ static inline void dentry_iput(struct dentry * dentry)
        if (inode) {
                dentry->d_inode = NULL;
                list_del(&dentry->d_alias);
+               INIT_LIST_HEAD(&dentry->d_alias);
                if (dentry->d_op && dentry->d_op->d_iput)
                        dentry->d_op->d_iput(dentry, inode);
                else
index 2c4c7a89f137d92de3e79c873ed2cec18599436b..86b3a2f5a6df173e83b2c0580c37124b416b971b 100644 (file)
@@ -30,9 +30,9 @@ struct buffer_head *fat_bread (
         * counterproductive or just plain wrong.
         */
 
-       if(MSDOS_SB(sb)->cvf_format)
-         if(MSDOS_SB(sb)->cvf_format->cvf_bread)
-           return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block);
+       if(MSDOS_SB(sb)->cvf_format &&
+          MSDOS_SB(sb)->cvf_format->cvf_bread)
+               return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block);
 
        if (sb->s_blocksize == 512) {
                ret = bread (sb->s_dev,block,512);
@@ -46,37 +46,37 @@ struct buffer_head *fat_bread (
 
                if (real != NULL){
                        ret = (struct buffer_head *)
-                         kmalloc (sizeof(struct buffer_head), GFP_KERNEL);
+                               kmalloc (sizeof(struct buffer_head), GFP_KERNEL);
                        if (ret != NULL) {
                                /* #Specification: msdos / strategy / special device / dummy blocks
-                                       Many special device (Scsi optical disk for one) use
-                                       larger hardware sector size. This allows for higher
-                                       capacity.
-
-                                       Most of the time, the MsDOS file system that sit
-                                       on this device is totally unaligned. It use logically
-                                       512 bytes sector size, with logical sector starting
-                                       in the middle of a hardware block. The bad news is
-                                       that a hardware sector may hold data own by two
-                                       different files. This means that the hardware sector
-                                       must be read, patch and written almost all the time.
-
-                                       Needless to say that it kills write performance
-                                       on all OS.
-
-                                       Internally the linux msdos fs is using 512 bytes
-                                       logical sector. When accessing such a device, we
-                                       allocate dummy buffer cache blocks, that we stuff
-                                       with the information of a real one (1k large).
-
-                                       This strategy is used to hide this difference to
-                                       the core of the msdos fs. The slowdown is not
-                                       hidden though!
-                               */
+                                * Many special device (Scsi optical disk for one) use
+                                * larger hardware sector size. This allows for higher
+                                * capacity.
+
+                                * Most of the time, the MsDOS file system that sit
+                                * on this device is totally unaligned. It use logically
+                                * 512 bytes sector size, with logical sector starting
+                                * in the middle of a hardware block. The bad news is
+                                * that a hardware sector may hold data own by two
+                                * different files. This means that the hardware sector
+                                * must be read, patch and written almost all the time.
+
+                                * Needless to say that it kills write performance
+                                * on all OS.
+
+                                * Internally the linux msdos fs is using 512 bytes
+                                * logical sector. When accessing such a device, we
+                                * allocate dummy buffer cache blocks, that we stuff
+                                * with the information of a real one (1k large).
+
+                                * This strategy is used to hide this difference to
+                                * the core of the msdos fs. The slowdown is not
+                                * hidden though!
+                                */
                                /*
-                                       The memset is there only to catch errors. The msdos
-                                       fs is only using b_data
-                               */
+                                * The memset is there only to catch errors. The msdos
+                                * fs is only using b_data
+                                */
                                memset (ret,0,sizeof(*ret));
                                ret->b_data = real->b_data;
                                if (sb->s_blocksize == 2048) {
@@ -92,26 +92,26 @@ struct buffer_head *fat_bread (
        }
        return ret;
 }
-struct buffer_head *fat_getblk (
-       struct super_block *sb,
-       int block)
+
+struct buffer_head *fat_getblk(struct super_block *sb, int block)
 {
        struct buffer_head *ret = NULL;
        PRINTK(("fat_getblk: block=0x%x\n", block));
 
-       if(MSDOS_SB(sb)->cvf_format)
-         if(MSDOS_SB(sb)->cvf_format->cvf_getblk)
-           return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block);
+       if (MSDOS_SB(sb)->cvf_format &&
+           MSDOS_SB(sb)->cvf_format->cvf_getblk)
+               return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block);
 
        if (sb->s_blocksize == 512){
                ret = getblk (sb->s_dev,block,512);
-       }else{
-               /* #Specification: msdos / special device / writing
-                       A write is always preceded by a read of the complete block
-                       (large hardware sector size). This defeat write performance.
-                       There is a possibility to optimize this when writing large
-                       chunk by making sure we are filling large block. Volunteer ?
-               */
+       } else {
+               /*
+                * #Specification: msdos / special device / writing
+                * A write is always preceded by a read of the complete block
+                * (large hardware sector size). This defeat write performance.
+                * There is a possibility to optimize this when writing large
+                * chunk by making sure we are filling large block. Volunteer ?
+                */
                ret = fat_bread (sb,block);
        }
        return ret;
@@ -121,10 +121,10 @@ void fat_brelse (
        struct super_block *sb,
        struct buffer_head *bh)
 {
-       if (bh != NULL){
-               if(MSDOS_SB(sb)->cvf_format)
-                 if(MSDOS_SB(sb)->cvf_format->cvf_brelse)
-                   return MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh);
+       if (bh != NULL) {
+               if (MSDOS_SB(sb)->cvf_format &&
+                   MSDOS_SB(sb)->cvf_format->cvf_brelse)
+                       return MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh);
 
                if (sb->s_blocksize == 512){
                        brelse (bh);
@@ -141,18 +141,18 @@ void fat_brelse (
 void fat_mark_buffer_dirty (
        struct super_block *sb,
        struct buffer_head *bh,
-       int dirty_val)
+       int dirty)
 {
-       if(MSDOS_SB(sb)->cvf_format)
-          if(MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty)
-          { MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty_val);
-            return;
-          }
+       if (MSDOS_SB(sb)->cvf_format &&
+           MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty) {
+               MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty);
+               return;
+       }
  
        if (sb->s_blocksize != 512){
                bh = bh->b_next;
        }
-       mark_buffer_dirty (bh,dirty_val);
+       mark_buffer_dirty (bh,dirty);
 }
 
 void fat_set_uptodate (
@@ -160,11 +160,11 @@ void fat_set_uptodate (
        struct buffer_head *bh,
        int val)
 {
-       if(MSDOS_SB(sb)->cvf_format)
-          if(MSDOS_SB(sb)->cvf_format->cvf_set_uptodate)
-          { MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val);
-            return;
-          }
+       if (MSDOS_SB(sb)->cvf_format && 
+           MSDOS_SB(sb)->cvf_format->cvf_set_uptodate) {
+               MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val);
+               return;
+       }
  
        if (sb->s_blocksize != 512){
                bh = bh->b_next;
@@ -175,9 +175,9 @@ int fat_is_uptodate (
        struct super_block *sb,
        struct buffer_head *bh)
 {
-       if(MSDOS_SB(sb)->cvf_format)
-          if(MSDOS_SB(sb)->cvf_format->cvf_is_uptodate)
-            return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh);
+       if(MSDOS_SB(sb)->cvf_format &&
+          MSDOS_SB(sb)->cvf_format->cvf_is_uptodate)
+               return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh);
  
        if (sb->s_blocksize != 512){
                bh = bh->b_next;
@@ -191,11 +191,11 @@ void fat_ll_rw_block (
        int nbreq,
        struct buffer_head *bh[32])
 {
-        if(MSDOS_SB(sb)->cvf_format)
-          if(MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block)
-          { MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh);
-            return;
-          }
+        if (MSDOS_SB(sb)->cvf_format &&
+           MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block) {
+               MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh);
+               return;
+       }
  
        if (sb->s_blocksize == 512){
                ll_rw_block(opr,nbreq,bh);
index edc976bd4fb9f3bd9bee186342ea3b2339f72bd2..9083d6b31ec5c729dbdf5f61d11411101e746147 100644 (file)
@@ -30,9 +30,9 @@ int fat_access(struct super_block *sb,int nr,int new_value)
        unsigned char *p_first,*p_last;
        int copy,first,last,next,b;
 
-       if(MSDOS_SB(sb)->cvf_format)
-         if(MSDOS_SB(sb)->cvf_format->fat_access)
-           return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value);
+       if (MSDOS_SB(sb)->cvf_format &&
+           MSDOS_SB(sb)->cvf_format->fat_access)
+               return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value);
 
        if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters)
                return 0;
@@ -267,9 +267,8 @@ int fat_smap(struct inode *inode,int sector)
        int cluster,offset;
 
        sb = MSDOS_SB(inode->i_sb);
-       if(sb->cvf_format)
-         if(sb->cvf_format->cvf_smap)
-           return sb->cvf_format->cvf_smap(inode,sector);
+       if (sb->cvf_format && sb->cvf_format->cvf_smap)
+               return sb->cvf_format->cvf_smap(inode,sector);
        if ((sb->fat_bits != 32) &&
            (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
             !MSDOS_I(inode)->i_start))) {
index 23b15726c455b8d3f8861028e123e826efa0ea0b..7ba11ec2d858a13f5a635875f86112c89bc26187 100644 (file)
@@ -437,10 +437,10 @@ int fat_dir_ioctl(struct inode * inode, struct file * filp,
        }
        default:
                /* forward ioctl to CVF extension */
-              if(MSDOS_SB(inode->i_sb)->cvf_format
-                 &&MSDOS_SB(inode->i_sb)->cvf_format->cvf_dir_ioctl)
-                     return MSDOS_SB(inode->i_sb)->cvf_format->
-                               cvf_dir_ioctl(inode,filp,cmd,arg);
+              if (MSDOS_SB(inode->i_sb)->cvf_format &&
+                  MSDOS_SB(inode->i_sb)->cvf_format->cvf_dir_ioctl)
+                      return MSDOS_SB(inode->i_sb)->cvf_format
+                              ->cvf_dir_ioctl(inode,filp,cmd,arg);
                return -EINVAL;
        }
 
index d0418d6c6a2df24564fb8323c77d9f30a2084c0a..4a271e876ea2cd2112cc8e83ba11f18fd15ef436 100644 (file)
@@ -312,9 +312,10 @@ ssize_t fat_file_read(
        loff_t *ppos)
 {
        struct inode *inode = filp->f_dentry->d_inode;
-       if(MSDOS_SB(inode->i_sb)->cvf_format)
-          if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_file_read)
-            return MSDOS_SB(inode->i_sb)->cvf_format->cvf_file_read(filp,buf,count,ppos);
+       if (MSDOS_SB(inode->i_sb)->cvf_format &&
+           MSDOS_SB(inode->i_sb)->cvf_format->cvf_file_read)
+               return MSDOS_SB(inode->i_sb)->cvf_format
+                       ->cvf_file_read(filp,buf,count,ppos);
 
        if (!MSDOS_I(inode)->i_binary)
                return fat_file_read_text(filp, buf, count, ppos);
@@ -338,13 +339,16 @@ ssize_t fat_file_write(
        struct buffer_head *bh;
        int binary_mode = MSDOS_I(inode)->i_binary;
 
+       PRINTK(("fat_file_write: dentry=%p, inode=%p, ino=%ld\n",
+               filp->f_dentry, inode, inode->i_ino));
        if (!inode) {
                printk("fat_file_write: inode = NULL\n");
                return -EINVAL;
        }
-        if(MSDOS_SB(sb)->cvf_format)
-          if(MSDOS_SB(sb)->cvf_format->cvf_file_write)
-            return MSDOS_SB(sb)->cvf_format->cvf_file_write(filp,buf,count,ppos);
+        if (MSDOS_SB(sb)->cvf_format &&
+           MSDOS_SB(sb)->cvf_format->cvf_file_write)
+               return MSDOS_SB(sb)->cvf_format
+                       ->cvf_file_write(filp,buf,count,ppos);
 
        /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
        if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
index d1c43bf17acd2e2fac352dc0174ad3e236181e9b..184a4d19b71f4f96798a1b4afc6b4c06cbec004e 100644 (file)
 #include <asm/unaligned.h>
 
 /* #define FAT_PARANOIA 1 */
+#define DEBUG_LEVEL 0
 #ifdef FAT_DEBUG
 #  define PRINTK(x) printk x
 #else
 #  define PRINTK(x)
 #endif
-
-/*
- * Free any dependent inodes at the (effective) last use.
- */
-static int fat_free_links(struct inode *inode)
-{
-       struct inode *depend, *linked, *old_inode;
-       int success = 0;
-
-       /*
-        * Clear the fields first to avoid races
-        */
-       depend = MSDOS_I(inode)->i_depend;
-       MSDOS_I(inode)->i_depend = NULL;
-       linked = MSDOS_I(inode)->i_linked;
-       MSDOS_I(inode)->i_linked = NULL;
-
-       if (depend) {
-#ifdef FAT_PARANOIA
-printk("fat_put_inode: depend inode is %ld, i_count=%d\n",
-depend->i_ino, depend->i_count); 
-#endif
-               old_inode = MSDOS_I(depend)->i_old;
-               if (old_inode != inode) {
-                       printk("fat_free_link: Invalid depend for inode %ld: "
-                               "expected 0x%p, got 0x%p\n",
-                               depend->i_ino, inode, old_inode);
-                       goto out;
-               }
-               MSDOS_I(depend)->i_old = NULL;
-               iput(depend);
-       }
-
-       if (linked) {
-#ifdef FAT_PARANOIA
-printk("fat_put_inode: linked inode is %ld, i_count=%d\n",
-linked->i_ino, linked->i_count); 
+#if (DEBUG_LEVEL >= 1)
+#  define PRINTK1(x) printk x
+#else
+#  define PRINTK1(x)
 #endif
-               old_inode = MSDOS_I(linked)->i_oldlink;
-               if (old_inode != inode) {
-                       printk("fat_free_link: Invalid link for inode %ld: "
-                               "expected 0x%p, got 0x%p\n",
-                               linked->i_ino, inode, old_inode);
-                       goto out;
-               }
-               MSDOS_I(linked)->i_oldlink = NULL;
-               iput(linked);
-       }
-       success = 1;
-out:
-       return success;
-}
 
-/*
- * This is a little tricky, as we may have links and may be linked
- * by other inodes. Also, we're subject to race conditions ...
- */
 void fat_put_inode(struct inode *inode)
 {
-       int last_use = 1;
-
        /*
         * Check whether we're a dependent of other inodes ...
         */ 
-       if (MSDOS_I(inode)->i_oldlink)
-               last_use++;
-       if (MSDOS_I(inode)->i_old)
-               last_use++;
-
-       if (inode->i_count <= last_use) {
+       if (inode->i_count <= 1) {
 #ifdef FAT_PARANOIA
-printk("fat_put_inode: last use for %ld, i_count=%d\n",
-inode->i_ino, inode->i_count); 
+printk("fat_put_inode: last use for (%p,%ld), i_count=%d\n",
+inode, inode->i_ino, inode->i_count); 
 #endif
                if (inode->i_nlink) {
                        if (MSDOS_I(inode)->i_busy)
                                fat_cache_inval_inode(inode);
-                       fat_free_links(inode);
                }
        }
 }
@@ -121,18 +63,9 @@ void fat_delete_inode(struct inode *inode)
        /*
         * Make sure there are no active dependencies ...
         */
-       if (MSDOS_I(inode)->i_old)
-               printk("fat_delete_inode: inode %ld, old=%p??\n",
-                       inode->i_ino, MSDOS_I(inode)->i_old);
-       if (MSDOS_I(inode)->i_oldlink)
-               printk("fat_delete_inode: inode %ld, oldlink=%p??\n",
-                       inode->i_ino, MSDOS_I(inode)->i_oldlink);
-
        fat_cache_inval_inode(inode);
        inode->i_size = 0;
        fat_truncate(inode);
-       if (!fat_free_links(inode))
-               fat_fs_panic(inode->i_sb,"..."); /* is this necessary? */
        clear_inode(inode);
 }
 
@@ -140,9 +73,9 @@ void fat_delete_inode(struct inode *inode)
 void fat_put_super(struct super_block *sb)
 {
        lock_super(sb);
-       if(MSDOS_SB(sb)->cvf_format)
-       { MSDOS_SB(sb)->cvf_format->unmount_cvf(sb);
-         dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version);
+       if (MSDOS_SB(sb)->cvf_format) {
+               dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version);
+               MSDOS_SB(sb)->cvf_format->unmount_cvf(sb);
        }
        if (MSDOS_SB(sb)->fat_bits == 32) {
                fat_clusters_flush(sb);
@@ -175,7 +108,7 @@ void fat_put_super(struct super_block *sb)
 
 static int parse_options(char *options,int *fat, int *blksize, int *debug,
                         struct fat_mount_options *opts,
-                        char* cvf_format, char*cvf_options)
+                        char *cvf_format, char *cvf_options)
 {
        char *this_char,*value,save,*savep;
        char *p;
@@ -355,10 +288,10 @@ fat_read_super(struct super_block *sb, void *data, int silent)
        char cvf_format[21];
        char cvf_options[101];
 
-       cvf_format[0]='\0';
-       cvf_options[0]='\0';
-       MSDOS_SB(sb)->cvf_format=NULL;
-       MSDOS_SB(sb)->private_data=NULL;
+       cvf_format[0] = '\0';
+       cvf_options[0] = '\0';
+       MSDOS_SB(sb)->cvf_format = NULL;
+       MSDOS_SB(sb)->private_data = NULL;
 
        MOD_INC_USE_COUNT;
        if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
@@ -484,9 +417,12 @@ fat_read_super(struct super_block *sb, void *data, int silent)
                                /* because clusters (DOS) are often aligned */
                                /* on odd sectors. */
        sb->s_blocksize_bits = blksize == 512 ? 9 : (blksize == 1024 ? 10 : 11);
-       if(!strcmp(cvf_format,"none"))i=-1;
-       else i=detect_cvf(sb,cvf_format);
-       if(i>=0)error=cvf_formats[i]->mount_cvf(sb,cvf_options);
+       if (!strcmp(cvf_format,"none"))
+               i = -1;
+       else
+               i = detect_cvf(sb,cvf_format);
+       if (i >= 0)
+               error = cvf_formats[i]->mount_cvf(sb,cvf_options);
        if (error || debug) {
                /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
                printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
@@ -546,9 +482,9 @@ fat_read_super(struct super_block *sb, void *data, int silent)
        sb->s_root = d_alloc_root(root_inode, NULL);
        if (!sb->s_root)
                goto out_no_root;
-       if(i>=0)
-       { MSDOS_SB(sb)->cvf_format=cvf_formats[i];
-         ++cvf_format_use_count[i];
+       if(i>=0) {
+               MSDOS_SB(sb)->cvf_format = cvf_formats[i];
+               ++cvf_format_use_count[i];
        }
        return sb;
 
@@ -585,9 +521,9 @@ int fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
        int free,nr;
        struct statfs tmp;
        
-        if(MSDOS_SB(sb)->cvf_format)
-          if(MSDOS_SB(sb)->cvf_format->cvf_statfs)
-            return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz);
+        if (MSDOS_SB(sb)->cvf_format &&
+           MSDOS_SB(sb)->cvf_format->cvf_statfs)
+               return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz);
           
        lock_fat(sb);
        if (MSDOS_SB(sb)->free_clusters != -1)
@@ -617,9 +553,9 @@ int fat_bmap(struct inode *inode,int block)
        int cluster,offset;
 
        sb = MSDOS_SB(inode->i_sb);
-       if(sb->cvf_format)
-         if(sb->cvf_format->cvf_bmap)
-           return sb->cvf_format->cvf_bmap(inode,block);
+       if (sb->cvf_format &&
+           sb->cvf_format->cvf_bmap)
+               return sb->cvf_format->cvf_bmap(inode,block);
        if ((inode->i_ino == MSDOS_ROOT_INO) && (sb->fat_bits != 32)) {
                return sb->dir_start + block;
        }
@@ -646,11 +582,9 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
        struct msdos_dir_entry *raw_entry;
        int nr;
 
-       PRINTK(("fat_read_inode: inode=%p, sb->dir_start=0x%x\n",
-               inode, MSDOS_SB(sb)->dir_start));
+       PRINTK1(("fat_read_inode: inode=%p, ino=%ld, sb->dir_start=0x%x\n",
+                inode, inode->i_ino, MSDOS_SB(sb)->dir_start));
        MSDOS_I(inode)->i_busy = 0;
-       MSDOS_I(inode)->i_depend = MSDOS_I(inode)->i_old = NULL;
-       MSDOS_I(inode)->i_linked = MSDOS_I(inode)->i_oldlink = NULL;
        MSDOS_I(inode)->i_binary = 1;
        inode->i_uid = MSDOS_SB(sb)->options.fs_uid;
        inode->i_gid = MSDOS_SB(sb)->options.fs_gid;
@@ -684,6 +618,7 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
 
                MSDOS_I(inode)->i_attrs = 0;
                inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
+               MSDOS_I(inode)->i_ctime_ms = 0;
                inode->i_nlink = fat_subdirs(inode)+2;
                    /* subdirs (neither . nor ..) plus . and "self" */
                return;
@@ -732,10 +667,10 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
                       !is_exec(raw_entry->ext)))
                        ? S_IRUGO|S_IWUGO : S_IRWXUGO)
                    & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG;
-               if(MSDOS_SB(sb)->cvf_format)
-                 inode->i_op = (MSDOS_SB(sb)->cvf_format->flags&CVF_USE_READPAGE)
-                       ? &fat_file_inode_operations_readpage
-                       : &fat_file_inode_operations_1024;
+               if (MSDOS_SB(sb)->cvf_format)
+                       inode->i_op = (MSDOS_SB(sb)->cvf_format->flags & CVF_USE_READPAGE)
+                               ? &fat_file_inode_operations_readpage
+                               : &fat_file_inode_operations_1024;
                else
                  inode->i_op = (sb->s_blocksize == 1024 || sb->s_blocksize == 2048)
                        ? &fat_file_inode_operations_1024
@@ -765,6 +700,7 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
                MSDOS_SB(sb)->options.isvfat
                ? date_dos2unix(CF_LE_W(raw_entry->ctime),CF_LE_W(raw_entry->cdate))
                : inode->i_mtime;
+       MSDOS_I(inode)->i_ctime_ms = raw_entry->ctime_ms;
        fat_brelse(sb, bh);
 }
 
@@ -774,29 +710,6 @@ void fat_write_inode(struct inode *inode)
        struct super_block *sb = inode->i_sb;
        struct buffer_head *bh;
        struct msdos_dir_entry *raw_entry;
-       struct inode *linked;
-
-       linked = MSDOS_I(inode)->i_linked;
-       if (linked) {
-               if (MSDOS_I(linked)->i_oldlink != inode) {
-                       printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n",
-                              linked, inode, MSDOS_I(linked)->i_oldlink);
-                       fat_fs_panic(sb,"...");
-                       return;
-               }
-               linked->i_version = ++event;
-               linked->i_mode = inode->i_mode;
-               linked->i_uid = inode->i_uid;
-               linked->i_gid = inode->i_gid;
-               linked->i_size = inode->i_size;
-               linked->i_atime = inode->i_atime;
-               linked->i_mtime = inode->i_mtime;
-               linked->i_ctime = inode->i_ctime;
-               linked->i_blocks = inode->i_blocks;
-               linked->i_atime = inode->i_atime;
-               MSDOS_I(linked)->i_attrs = MSDOS_I(inode)->i_attrs;
-               mark_inode_dirty(linked);
-       }
 
        if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
        if (!(bh = fat_bread(sb, inode->i_ino >> MSDOS_DPB_BITS))) {
@@ -823,6 +736,7 @@ void fat_write_inode(struct inode *inode)
        raw_entry->date = CT_LE_W(raw_entry->date);
        if (MSDOS_SB(sb)->options.isvfat) {
                fat_date_unix2dos(inode->i_ctime,&raw_entry->ctime,&raw_entry->cdate);
+               raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms;
                raw_entry->ctime = CT_LE_W(raw_entry->ctime);
                raw_entry->cdate = CT_LE_W(raw_entry->cdate);
        }
index dc3a2545ce8a32a7857e367562e9d4d115d306ab..b398a0bbd1e8ac92866caaabb92cc4642d4c9f0f 100644 (file)
@@ -221,9 +221,9 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1));
 #endif
        sector = MSDOS_SB(sb)->data_start+(nr-2)*cluster_size;
        last_sector = sector + cluster_size;
-       if(MSDOS_SB(sb)->cvf_format&&
-         MSDOS_SB(sb)->cvf_format->zero_out_cluster)
-           MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr);
+       if (MSDOS_SB(sb)->cvf_format &&
+           MSDOS_SB(sb)->cvf_format->zero_out_cluster)
+               MSDOS_SB(sb)->cvf_format->zero_out_cluster(inode,nr);
        else
        for ( ; sector < last_sector; sector++) {
                #ifdef DEBUG
index a95db457f75da989fbe851fffab1f97c34ae082a..641c414a7ede029041e20a728186e8d3afcb0b6f 100644 (file)
@@ -97,9 +97,9 @@ struct vm_operations_struct fat_file_mmap = {
 int fat_mmap(struct file * file, struct vm_area_struct * vma)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       if(MSDOS_SB(inode->i_sb)->cvf_format)
-         if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap)
-           return MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap(file,vma);
+       if (MSDOS_SB(inode->i_sb)->cvf_format &&
+           MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap)
+               return MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap(file,vma);
 
        if (vma->vm_flags & VM_SHARED)  /* only PAGE_COW or read-only supported now */
                return -EINVAL;
@@ -121,10 +121,9 @@ int fat_mmap(struct file * file, struct vm_area_struct * vma)
 int fat_readpage(struct dentry * dentry, struct page * page)
 {
        struct inode * inode = dentry->d_inode;
-       if(MSDOS_SB(inode->i_sb)->cvf_format)
-               if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage)
-                       return MSDOS_SB(inode->i_sb)->cvf_format
-                               ->cvf_readpage(inode,page);
+       if (MSDOS_SB(inode->i_sb)->cvf_format &&
+           MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage)
+               return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page);
            
        printk("fat_readpage called with no handler (shouldn't happen)\n");
        return -1;
index 38f131d84e9ca986706f5725e50926673b7a812f..87c62e4c9cd356ec0797f62b48bdf24ea9f99ed4 100644 (file)
@@ -21,8 +21,7 @@
 
 #include "../fat/msbuffer.h"
 
-#define MSDOS_PARANOIA 1       
-/* #define MSDOS_DEBUG 1 */    
+#define MSDOS_DEBUG 0
 #define PRINTK(x)
 
 /* MS-DOS "device special files" */
@@ -257,7 +256,7 @@ int msdos_lookup(struct inode *dir,struct dentry *dentry)
        int ino,res;
        struct msdos_dir_entry *de;
        struct buffer_head *bh;
-       struct inode *next, *inode;
+       struct inode *inode;
        
        PRINTK (("msdos_lookup\n"));
 
@@ -294,20 +293,8 @@ int msdos_lookup(struct inode *dir,struct dentry *dentry)
                return 0;
        }
        PRINTK (("msdos_lookup 6\n"));
-       while (MSDOS_I(inode)->i_old) {
-               next = MSDOS_I(inode)->i_old;
-#ifdef MSDOS_PARANOIA
-printk("msdos_lookup: ino %ld, old ino=%ld\n", inode->i_ino, next->i_ino);
-if (MSDOS_I(next)->i_depend != inode)
-printk("msdos_lookup: depend=%p, inode=%p??\n", MSDOS_I(next)->i_depend, inode);
-#endif
-               next->i_count++;
-               iput(inode);
-               inode = next;
-       }
-       PRINTK (("msdos_lookup 7\n"));
        d_add(dentry, inode);
-       PRINTK (("msdos_lookup 8\n"));
+       PRINTK (("msdos_lookup 7\n"));
        return 0;
 }
 
@@ -428,6 +415,9 @@ static int msdos_empty(struct inode *dir)
                pos = 0;
                bh = NULL;
                while (fat_get_entry(dir,&pos,&bh,&de) > -1) {
+                       /* Ignore vfat longname entries */
+                       if (de->attr == ATTR_EXT)
+                               continue;
                        if (!IS_FREE(de->name) && 
                            strncmp(de->name,MSDOS_DOT   , MSDOS_NAME) &&
                            strncmp(de->name,MSDOS_DOTDOT, MSDOS_NAME)) {
@@ -471,7 +461,7 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry)
        res = -EBUSY;
        if (dentry->d_count > 1) {
 #ifdef MSDOS_DEBUG
-printk("rename_diff_dir: %s/%s busy, d_count=%d\n",
+printk("msdos_rmdir: %s/%s busy, d_count=%d\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
 #endif
                goto rmdir_done;
@@ -744,53 +734,31 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,
                mark_inode_dirty(new_dir);
        }
        msdos_read_inode(free_inode);
-       /*
-        * Check whether there's already a linked inode ...
-        */
-       if (MSDOS_I(old_inode)->i_linked) {
-               struct inode *linked = MSDOS_I(old_inode)->i_linked;
-#ifdef MSDOS_PARANOIA
-printk("rename_diff_dir: inode %ld already has link %ld, freeing it\n",
-old_inode->i_ino, linked->i_ino);
-#endif
-               MSDOS_I(old_inode)->i_linked = NULL;
-               MSDOS_I(linked)->i_oldlink = NULL;
-               iput(linked);
-       }
-       MSDOS_I(old_inode)->i_busy = 1;
-       MSDOS_I(old_inode)->i_linked = free_inode;
-       MSDOS_I(free_inode)->i_oldlink = old_inode;
-#ifdef MSDOS_DEBUG
-printk("rename_diff_dir: inode %ld added as link of %ld\n",
-free_inode->i_ino, old_inode->i_ino);
-#endif
+
+       free_inode->i_mode   = old_inode->i_mode;
+       free_inode->i_size   = old_inode->i_size;
+       free_inode->i_blocks = old_inode->i_blocks;
+       free_inode->i_mtime  = old_inode->i_mtime;
+       free_inode->i_atime  = old_inode->i_atime;
+       free_inode->i_ctime  = old_inode->i_ctime;
+       MSDOS_I(free_inode)->i_ctime_ms = MSDOS_I(old_inode)->i_ctime_ms;
+
+       MSDOS_I(free_inode)->i_start = MSDOS_I(old_inode)->i_start;
+       MSDOS_I(free_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart;
+       MSDOS_I(free_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs;
+
+       /* Detach d_alias from old inode and attach to new inode */
+       list_del(&old_dentry->d_alias);
+       d_instantiate(old_dentry, free_inode);
+       iput(old_inode);
+
        fat_cache_inval_inode(old_inode);
        mark_inode_dirty(old_inode);
        old_de->name[0] = DELETED_FLAG;
        fat_mark_buffer_dirty(sb, old_bh, 1);
        fat_mark_buffer_dirty(sb, free_bh, 1);
+
        if (exists) {
-               /*
-                * Check whether there's already a depend inode ...
-                */
-               if (MSDOS_I(new_inode)->i_depend) {
-                       struct inode *depend = MSDOS_I(new_inode)->i_depend;
-#ifdef MSDOS_PARANOIA
-printk("rename_diff_dir: inode %ld already has depend %ld, freeing it\n",
-new_inode->i_ino, depend->i_ino);
-#endif
-                       MSDOS_I(new_inode)->i_depend = NULL;
-                       MSDOS_I(depend)->i_old = NULL;
-                       iput(depend);
-               }
-               MSDOS_I(new_inode)->i_depend = free_inode;
-               MSDOS_I(free_inode)->i_old = new_inode;
-               /* Two references now exist to free_inode so increase count */
-               free_inode->i_count++;
-#ifdef MSDOS_DEBUG
-printk("rename_diff_dir: inode %ld added as depend of %ld\n",
-free_inode->i_ino, new_inode->i_ino);
-#endif
                /* free_inode is put after putting new_inode and old_inode */
                fat_brelse(sb, new_bh);
        }
@@ -815,6 +783,7 @@ free_inode->i_ino, new_inode->i_ino);
                iput(dotdot_inode);
                fat_brelse(sb, dotdot_bh);
        }
+
        /* Update the dcache */
        d_move(old_dentry, new_dentry);
        error = 0;
index 4ea31ed3337f5643a23a7bcfd30c27260b2af604..836c1b4d6f538e03c925f5c41f4e6888721c7e61 100644 (file)
@@ -433,19 +433,37 @@ exp_readlock(void)
 int
 exp_writelock(void)
 {
+       /* fast track */
+       if (!hash_count && !hash_lock) {
+       lock_it:
+               hash_lock = 1;
+               return 0;
+       }
+
+       current->sigpending = 0;
        want_lock++;
-       while (hash_count || hash_lock)
+       while (hash_count || hash_lock) {
                interruptible_sleep_on(&hash_wait);
+               if (signal_pending(current))
+                       break;
+       }
        want_lock--;
-       if (signal_pending(current))
-               return -EINTR;
-       hash_lock = 1;
-       return 0;
+
+       /* restore the task's signals */
+       spin_lock_irq(&current->sigmask_lock);
+       recalc_sigpending(current);
+       spin_unlock_irq(&current->sigmask_lock);
+
+       if (!hash_count && !hash_lock)
+               goto lock_it;
+       return -EINTR;
 }
 
 void
 exp_unlock(void)
 {
+       if (!hash_count && !hash_lock)
+               printk(KERN_WARNING "exp_unlock: not locked!\n");
        if (hash_count)
                hash_count--;
        else
index 7bd2b5ebe578d688ad22e4f660f148513e2814cc..2cd24e78ffb7c6b10a490c238758d60bcddc9d14 100644 (file)
@@ -999,21 +999,19 @@ out:
 u32
 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 {
+       struct knfs_fh  *fh = &fhp->fh_handle;
        struct svc_export *exp;
        struct dentry   *dentry;
        struct inode    *inode;
-       struct knfs_fh  *fh = &fhp->fh_handle;
        u32             error = 0;
 
-       if(fhp->fh_dverified)
-               goto out;
-
-       dprintk("nfsd: fh_lookup(exp %x/%ld fh %p)\n",
-                       fh->fh_xdev, fh->fh_xino, fh->fh_dcookie);
+       dprintk("nfsd: fh_verify(exp %x/%ld cookie %p)\n",
+               fh->fh_xdev, fh->fh_xino, fh->fh_dcookie);
 
+       if(fhp->fh_dverified)
+               goto check_type;
        /*
         * Look up the export entry.
-        * N.B. We need to lock this while in use ...
         */
        error = nfserr_stale;
        exp = exp_get(rqstp->rq_client, fh->fh_xdev, fh->fh_xino);
@@ -1057,6 +1055,8 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
         * spec says this is incorrect (implementation notes for the
         * write call).
         */
+check_type:
+       dentry = fhp->fh_dentry;
        inode = dentry->d_inode;
        if (type > 0 && (inode->i_mode & S_IFMT) != type) {
                error = (type == S_IFDIR)? nfserr_notdir : nfserr_isdir;
@@ -1069,9 +1069,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 
        /* Finally, check access permissions. */
        error = nfsd_permission(fhp->fh_export, dentry, access);
+#ifdef NFSD_PARANOIA
 if (error)
 printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, access, error);
+#endif
 
 out:
        return error;
index 3d392eea68a1b38f99609582d671a16325eb1867..cba32eea781c186ef9208c5705351b4448bee5e5 100644 (file)
@@ -42,6 +42,7 @@
 extern struct svc_program      nfsd_program;
 static void                    nfsd(struct svc_rqst *rqstp);
 struct timeval                 nfssvc_boot = { 0, 0 };
+static int                     nfsd_active = 0;
 
 int
 nfsd_svc(unsigned short port, int nrservs)
@@ -97,6 +98,7 @@ nfsd(struct svc_rqst *rqstp)
        oldumask = current->fs->umask;          /* Set umask to 0.  */
        current->fs->umask = 0;
        nfssvc_boot = xtime;                    /* record boot time */
+       nfsd_active++;
        lockd_up();                             /* start lockd */
 
        /*
@@ -160,6 +162,11 @@ nfsd(struct svc_rqst *rqstp)
 
        /* Release lockd */
        lockd_down();
+       if (!--nfsd_active) {
+               printk("nfsd: last server exiting\n");
+               /* revoke all exports */
+               nfsd_export_shutdown();
+       }
 
        /* Destroy the thread */
        svc_exit_thread(rqstp);
index 18704ea5992f6ed3d31b5a79de0170a5207de947..ac4f5892b1671beaa68fd32b9c9a04ed825d5bb2 100644 (file)
@@ -881,8 +881,8 @@ ntfs_read_super_unl:
 ntfs_read_super_vol:
        #ifndef NTFS_IN_LINUX_KERNEL
        ntfs_free(vol);
-       #endif
 ntfs_read_super_dec:
+       #endif
        ntfs_debug(DEBUG_OTHER, "read_super: done\n");
        MOD_DEC_USE_COUNT;
        return NULL;
index a2e512d88a03e96d0fd10606844e8032b9d18365..e417119a95c0d67c97749443f08d06d763d9b661 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -545,6 +545,23 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
        struct dentry * dentry;
        int error;
 
+       lock_kernel();
+       dentry = namei(filename);
+
+       error = PTR_ERR(dentry);
+       if (!IS_ERR(dentry)) {
+               error = chown_common(dentry, user, group);
+               dput(dentry);
+       }
+       unlock_kernel();
+       return error;
+}
+
+asmlinkage int sys_lchown(const char * filename, uid_t user, gid_t group)
+{
+       struct dentry * dentry;
+       int error;
+
        lock_kernel();
        dentry = lnamei(filename);
 
index 4bd075df68a0092a4d93129716398ae6fab15b7b..ae9ccce2e6bd88df3a0bd1f233ae5a33eddb070c 100644 (file)
@@ -342,11 +342,6 @@ int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
                if (dp->ops == NULL)
                        dp->ops = &proc_file_inode_operations;
        }
-       /*
-        * kludge until we fixup the md device driver
-        */
-       if (dp->low_ino == PROC_MD)
-               dp->ops = &proc_array_inode_operations;
        return 0;
 }
 
index fb302376554c6161dbe2606d57638cba5ca4d782..97d2d2f629a9720c67e7035ab357c5f26a7e076f 100644 (file)
 
 #include "../fat/msbuffer.h"
 
-#if 0
-# define PRINTK(x) printk x
+#define DEBUG_LEVEL 0
+#if (DEBUG_LEVEL >= 1)
+#  define PRINTK1(x) printk x
+#else
+#  define PRINTK1(x)
+#endif
+#if (DEBUG_LEVEL >= 2)
+#  define PRINTK2(x) printk x
 #else
-# define PRINTK(x)
+#  define PRINTK2(x)
+#endif
+#if (DEBUG_LEVEL >= 3)
+#  define PRINTK3(x) printk x
+#else
+#  define PRINTK3(x)
 #endif
 
 #ifndef DEBUG
@@ -114,6 +125,7 @@ void vfat_put_super(struct super_block *sb)
 
 static int vfat_revalidate(struct dentry *dentry)
 {
+       PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
        if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
                return 1;
        }
@@ -309,6 +321,9 @@ struct super_block *vfat_read_super(struct super_block *sb,void *data,
                MOD_DEC_USE_COUNT;
        } else {
                MSDOS_SB(sb)->options.dotsOK = 0;
+               if (MSDOS_SB(sb)->options.posixfs) {
+                       MSDOS_SB(sb)->options.name_check = 's';
+               }
                if (MSDOS_SB(sb)->options.name_check != 's') {
                        sb->s_root->d_op = &vfat_dentry_ops[0];
                } else {
@@ -600,7 +615,7 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
        const char *name_start;
        struct qstr qname;
 
-       PRINTK(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));
+       PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));
        sz = 0;                 /* Make compiler happy */
        if (len && name[len-1]==' ') return -EINVAL;
        if (len <= 12) {
@@ -625,17 +640,17 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
                        res = vfat_format_name(msdos_name, len, name_res, 1, utf8);
                }
                if (res > -1) {
-                       PRINTK(("vfat_create_shortname 1\n"));
+                       PRINTK3(("vfat_create_shortname 1\n"));
                        qname.name=msdos_name;
                        qname.len=len;
                        res = vfat_find(dir, &qname, 0, 0, 0, &sinfo);
-                       PRINTK(("vfat_create_shortname 2\n"));
+                       PRINTK3(("vfat_create_shortname 2\n"));
                        if (res > -1) return -EEXIST;
                        return 0;
                }
        }
 
-       PRINTK(("vfat_create_shortname 3\n"));
+       PRINTK3(("vfat_create_shortname 3\n"));
        /* Now, we need to create a shortname from the long name */
        ext_start = end = &name[len];
        while (--ext_start >= name) {
@@ -793,7 +808,7 @@ static loff_t vfat_find_free_slots(struct inode *dir,int slots)
        int res;
        int added;
 
-       PRINTK(("vfat_find_free_slots: find %d free slots\n", slots));
+       PRINTK2(("vfat_find_free_slots: find %d free slots\n", slots));
        offset = curr = 0;
        bh = NULL;
        row = 0;
@@ -807,7 +822,7 @@ static loff_t vfat_find_free_slots(struct inode *dir,int slots)
                                if (inode) {
                                        /* Directory slots of busy deleted files aren't available yet. */
                                        done = !MSDOS_I(inode)->i_busy;
-                                       /* PRINTK(("inode %d still busy\n", ino)); */
+                                       /* PRINTK3(("inode %d still busy\n", ino)); */
                                        iput(inode);
                                }
                        }
@@ -934,18 +949,18 @@ vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
        for (cksum = i = 0; i < 11; i++) {
                cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
        }
-       PRINTK(("vfat_fill_long_slots 3: slots=%d\n",*slots));
+       PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots));
 
        for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
                int end, j;
 
-               PRINTK(("vfat_fill_long_slots 4\n"));
+               PRINTK3(("vfat_fill_long_slots 4\n"));
                ps->id = slot;
                ps->attr = ATTR_EXT;
                ps->reserved = 0;
                ps->alias_checksum = cksum;
                ps->start = 0;
-               PRINTK(("vfat_fill_long_slots 5: uniname=%s\n",uniname));
+               PRINTK3(("vfat_fill_long_slots 5: uniname=%s\n",uniname));
                offset = (slot - 1) * 26;
                ip = &uniname[offset];
                j = offset;
@@ -954,22 +969,22 @@ vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
                        ps->name0_4[i] = *ip++;
                        ps->name0_4[i+1] = *ip++;
                }
-               PRINTK(("vfat_fill_long_slots 6\n"));
+               PRINTK3(("vfat_fill_long_slots 6\n"));
                for (i = 0; i < 12; i += 2) {
                        ps->name5_10[i] = *ip++;
                        ps->name5_10[i+1] = *ip++;
                }
-               PRINTK(("vfat_fill_long_slots 7\n"));
+               PRINTK3(("vfat_fill_long_slots 7\n"));
                for (i = 0; i < 4; i += 2) {
                        ps->name11_12[i] = *ip++;
                        ps->name11_12[i+1] = *ip++;
                }
        }
-       PRINTK(("vfat_fill_long_slots 8\n"));
+       PRINTK3(("vfat_fill_long_slots 8\n"));
        ds[0].id |= 0x40;
 
        de = (struct msdos_dir_entry *) ps;
-       PRINTK(("vfat_fill_long_slots 9\n"));
+       PRINTK3(("vfat_fill_long_slots 9\n"));
        strncpy(de->name, msdos_name, MSDOS_NAME);
 
        free_page(page);
@@ -984,7 +999,7 @@ static int vfat_build_slots(struct inode *dir,const char *name,int len,
        int res, xlate, utf8;
        struct nls_table *nls;
 
-       PRINTK(("Entering vfat_build_slots: name=%s, len=%d\n", name, len));
+       PRINTK2(("Entering vfat_build_slots: name=%s, len=%d\n", name, len));
        de = (struct msdos_dir_entry *) ds;
        xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
        utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
@@ -997,12 +1012,12 @@ static int vfat_build_slots(struct inode *dir,const char *name,int len,
        } else if (len == 2 && name[0] == '.' && name[1] == '.') {
                strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
        } else {
-               PRINTK(("vfat_build_slots 4\n"));
+               PRINTK3(("vfat_build_slots 4\n"));
                res = vfat_valid_shortname(name, len, 1, utf8);
                if (res > -1) {
-                       PRINTK(("vfat_build_slots 5a\n"));
+                       PRINTK3(("vfat_build_slots 5a\n"));
                        res = vfat_format_name(name, len, de->name, 1, utf8);
-                       PRINTK(("vfat_build_slots 5b\n"));
+                       PRINTK3(("vfat_build_slots 5b\n"));
                } else {
                        res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
                        if (res < 0) {
@@ -1082,7 +1097,7 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
        int slots, slot;
        int res;
 
-       PRINTK(("Entering vfat_find\n"));
+       PRINTK2(("Entering vfat_find\n"));
 
        ds = (struct msdos_dir_slot *)
            kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
@@ -1096,7 +1111,7 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
        vf.posix = MSDOS_SB(sb)->options.posixfs;
        vf.anycase = (MSDOS_SB(sb)->options.name_check != 's');
        res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,find_long,0);
-       PRINTK(("vfat_find: Debug 1\n"));
+       PRINTK3(("vfat_find: Debug 1\n"));
        if (res < 0) goto cleanup;
        if (vf.found) {
                if (new_filename) {
@@ -1110,12 +1125,12 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
                sinfo_out->total_slots = vf.long_slots + 1;
                sinfo_out->ino = vf.ino;
 
-               PRINTK(("vfat_find: Debug 2\n"));
+               PRINTK3(("vfat_find: Debug 2\n"));
                res = 0;
                goto cleanup;
        }
 
-       PRINTK(("vfat_find: Debug 3\n"));
+       PRINTK3(("vfat_find: Debug 3\n"));
        if (!vf.found && !new_filename) {
                res = -ENOENT;
                goto cleanup;
@@ -1129,7 +1144,7 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
 
        bh = NULL;
        if (new_filename) {
-               PRINTK(("vfat_find: create file 1\n"));
+               PRINTK3(("vfat_find: create file 1\n"));
                if (is_long) slots++;
                offset = vfat_find_free_slots(dir, slots);
                if (offset < 0) {
@@ -1137,14 +1152,14 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
                        goto cleanup;
                }
 
-               PRINTK(("vfat_find: create file 2\n"));
+               PRINTK3(("vfat_find: create file 2\n"));
                /* Now create the new entry */
                bh = NULL;
                for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
-                       PRINTK(("vfat_find: create file 3, slot=%d\n",slot));
+                       PRINTK3(("vfat_find: create file 3, slot=%d\n",slot));
                        sinfo_out->ino = fat_get_entry(dir,&offset,&bh,&de);
                        if (sinfo_out->ino < 0) {
-                               PRINTK(("vfat_find: problem\n"));
+                               PRINTK3(("vfat_find: problem\n"));
                                res = sinfo_out->ino;
                                goto cleanup;
                        }
@@ -1152,11 +1167,11 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
                        fat_mark_buffer_dirty(sb, bh, 1);
                }
 
-               PRINTK(("vfat_find: create file 4\n"));
+               PRINTK3(("vfat_find: create file 4\n"));
                dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
                mark_inode_dirty(dir);
 
-               PRINTK(("vfat_find: create file 5\n"));
+               PRINTK3(("vfat_find: create file 5\n"));
 
                fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
                de->ctime_ms = 0;
@@ -1198,7 +1213,7 @@ int vfat_lookup(struct inode *dir,struct dentry *dentry)
        struct inode *result;
        int table;
        
-       PRINTK (("vfat_lookup: name=%s, len=%d\n", 
+       PRINTK2(("vfat_lookup: name=%s, len=%d\n", 
                 dentry->d_name.name, dentry->d_name.len));
 
        table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
@@ -1210,17 +1225,17 @@ int vfat_lookup(struct inode *dir,struct dentry *dentry)
                table++;
                goto error;
        }
-       PRINTK (("vfat_lookup 4.5\n"));
+       PRINTK3(("vfat_lookup 4.5\n"));
        if (!(result = iget(dir->i_sb,sinfo.ino)))
                return -EACCES;
-       PRINTK (("vfat_lookup 5\n"));
+       PRINTK3(("vfat_lookup 5\n"));
        if (MSDOS_I(result)->i_busy) { /* mkdir in progress */
                iput(result);
                result = NULL;
                table++;
                goto error;
        }
-       PRINTK (("vfat_lookup 6\n"));
+       PRINTK3(("vfat_lookup 6\n"));
 error:
        dentry->d_op = &vfat_dentry_ops[table];
        dentry->d_time = dentry->d_parent->d_inode->i_version;
@@ -1240,7 +1255,7 @@ static int vfat_create_entry(struct inode *dir,struct qstr* qname,
        struct vfat_slot_info sinfo;
 
        *result=0;
-       PRINTK(("vfat_create_entry 1\n"));
+       PRINTK1(("vfat_create_entry: Entering\n"));
        res = vfat_find(dir, qname, 1, 1, is_dir, &sinfo);
        if (res < 0) {
                return res;
@@ -1248,16 +1263,16 @@ static int vfat_create_entry(struct inode *dir,struct qstr* qname,
 
        offset = sinfo.shortname_offset;
 
-       PRINTK(("vfat_create_entry 2\n"));
+       PRINTK3(("vfat_create_entry 2\n"));
        bh = NULL;
        ino = fat_get_entry(dir, &offset, &bh, &de);
        if (ino < 0) {
-               PRINTK(("vfat_mkdir problem\n"));
+               PRINTK3(("vfat_mkdir problem\n"));
                if (bh)
                        fat_brelse(sb, bh);
                return ino;
        }
-       PRINTK(("vfat_create_entry 3\n"));
+       PRINTK3(("vfat_create_entry 3\n"));
 
        if ((*result = iget(dir->i_sb,ino)) != NULL)
                vfat_read_inode(*result);
@@ -1283,7 +1298,7 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
        res = vfat_create_entry(dir,&dentry->d_name,0,&result);
        fat_unlock_creation();
        if (res < 0) {
-               PRINTK(("vfat_create: unable to get new entry\n"));
+               PRINTK3(("vfat_create: unable to get new entry\n"));
        } else {
                dentry->d_time = dentry->d_parent->d_inode->i_version;
                d_instantiate(dentry,result);
@@ -1298,7 +1313,7 @@ static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,
        struct super_block *sb = dir->i_sb;
        struct inode *dot;
 
-       PRINTK(("vfat_create_a_dotdir 1\n"));
+       PRINTK2(("vfat_create_a_dotdir: Entering\n"));
 
        /*
         * XXX all times should be set by caller upon successful completion.
@@ -1336,7 +1351,7 @@ static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,
 
        iput(dot);
 
-       PRINTK(("vfat_create_a_dotdir 2\n"));
+       PRINTK3(("vfat_create_a_dotdir 2\n"));
        return 0;
 }
 
@@ -1348,31 +1363,31 @@ static int vfat_create_dotdirs(struct inode *dir, struct inode *parent)
        struct msdos_dir_entry *de;
        loff_t offset;
 
-       PRINTK(("vfat_create_dotdirs 1\n"));
+       PRINTK2(("vfat_create_dotdirs: Entering\n"));
        if ((res = fat_add_cluster(dir)) < 0) return res;
 
-       PRINTK(("vfat_create_dotdirs 2\n"));
+       PRINTK3(("vfat_create_dotdirs 2\n"));
        offset = 0;
        bh = NULL;
        if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) return res;
        
-       PRINTK(("vfat_create_dotdirs 3\n"));
+       PRINTK3(("vfat_create_dotdirs 3\n"));
        res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOT, 1);
-       PRINTK(("vfat_create_dotdirs 4\n"));
+       PRINTK3(("vfat_create_dotdirs 4\n"));
        if (res < 0) {
                fat_brelse(sb, bh);
                return res;
        }
-       PRINTK(("vfat_create_dotdirs 5\n"));
+       PRINTK3(("vfat_create_dotdirs 5\n"));
 
        if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) {
                fat_brelse(sb, bh);
                return res;
        }
-       PRINTK(("vfat_create_dotdirs 6\n"));
+       PRINTK3(("vfat_create_dotdirs 6\n"));
 
        res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOTDOT, 0);
-       PRINTK(("vfat_create_dotdirs 7\n"));
+       PRINTK3(("vfat_create_dotdirs 7\n"));
        fat_brelse(sb, bh);
 
        return res;
@@ -1386,12 +1401,6 @@ static int vfat_empty(struct inode *dir)
        struct buffer_head *bh;
        struct msdos_dir_entry *de;
 
-       /*
-        * Prune any child dentries, then verify that
-        * the directory is empty and not in use.
-        */
-       shrink_dcache_sb(sb); /* should be child prune */
-
        if (dir->i_count > 1) {
                return -EBUSY;
        }
@@ -1427,6 +1436,7 @@ static int vfat_rmdir_free_ino(struct inode *dir,struct buffer_head *bh,
        if (dir->i_dev != dentry->d_inode->i_dev || dir == dentry->d_inode) {
                return -EBUSY;
        }
+
        res = vfat_empty(dentry->d_inode);
        if (res) {
                return res;
@@ -1498,11 +1508,13 @@ static int vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
        return 0;
 }
 
-static void vfat_delete_dentries(struct dentry *dentry)
+/* Replace inodes in alias dentries and drop all but the initial dentry */
+static void drop_replace_inodes(struct dentry *dentry, struct inode *inode)
 {
        struct list_head *head, *next, *tmp;
        struct dentry *alias;
 
+       PRINTK1(("drop_replace_inodes: dentry=%p, inode=%p\n", dentry, inode));
        head = &dentry->d_inode->i_dentry;
        if (dentry->d_inode) {
                next = dentry->d_inode->i_dentry.next;
@@ -1510,10 +1522,19 @@ static void vfat_delete_dentries(struct dentry *dentry)
                        tmp = next;
                        next = tmp->next;
                        alias = list_entry(tmp, struct dentry, d_alias);
-                       d_delete(alias);
+                       if (inode) {
+                               list_del(&alias->d_alias);
+                               iput(alias->d_inode);
+                               d_instantiate(alias, inode);
+                               /* dentry is already accounted for */
+                               if (alias != dentry) {
+                                       inode->i_count++;
+                               }
+                       }
+                       if (alias != dentry) {
+                               d_drop(alias);
+                       }
                }
-       } else {
-               d_delete(dentry);
        }
 }
 
@@ -1524,6 +1545,7 @@ static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
        struct buffer_head *bh;
        struct vfat_slot_info sinfo;
 
+       PRINTK1(("vfat_rmdirx: dentry=%p\n", dentry));
        res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
 
        if (res >= 0 && sinfo.total_slots > 0) {
@@ -1542,9 +1564,11 @@ static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
 {
        int res;
+       PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
        res = vfat_rmdirx(dir, dentry);
        if (res >= 0) {
-               vfat_delete_dentries(dentry);
+               drop_replace_inodes(dentry, NULL);
+               d_delete(dentry);
        }
        return res;
 }
@@ -1559,6 +1583,7 @@ static int vfat_unlinkx(
        struct buffer_head *bh;
        struct vfat_slot_info sinfo;
 
+       PRINTK1(("vfat_unlinkx: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
        bh = NULL;
        res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo);
 
@@ -1579,6 +1604,7 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
        struct inode *inode;
        int res;
 
+       PRINTK1(("vfat_mkdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
        fat_lock_creation();
        if ((res = vfat_create_entry(dir,&dentry->d_name,1,&inode)) < 0) {
                fat_unlock_creation();
@@ -1606,9 +1632,11 @@ int vfat_unlink(struct inode *dir,struct dentry* dentry)
 {
        int res;
 
+       PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
        res = vfat_unlinkx (dir,dentry,1);
        if (res >= 0) {
-               vfat_delete_dentries(dentry);
+               drop_replace_inodes(dentry, NULL);
+               d_delete(dentry);
        }
        return res;
 }
@@ -1636,8 +1664,12 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
        int res, is_dir, i;
        int locked = 0;
        struct vfat_slot_info sinfo;
+       int put_new_inode = 0;
 
-       PRINTK(("vfat_rename 1\n"));
+       PRINTK1(("vfat_rename: Entering: old_dentry=%p, old_inode=%p, old ino=%ld, new_dentry=%p, new_inode=%p, new ino=%ld\n",
+                old_dentry, old_dentry->d_inode, old_dentry->d_inode->i_ino,
+                new_dentry, new_dentry->d_inode,
+                new_dentry->d_inode ? new_dentry->d_inode->i_ino : 0));
        if (old_dir == new_dir && 
            old_dentry->d_name.len == new_dentry->d_name.len &&
            strncmp(old_dentry->d_name.name, new_dentry->d_name.name, 
@@ -1647,7 +1679,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
        old_bh = new_bh = NULL;
        old_inode = new_inode = NULL;
        res = vfat_find(old_dir,&old_dentry->d_name,1,0,0,&sinfo);
-       PRINTK(("vfat_rename 2\n"));
+       PRINTK3(("vfat_rename 2\n"));
        if (res < 0) goto rename_done;
 
        old_slots = sinfo.total_slots;
@@ -1655,7 +1687,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
        old_offset = sinfo.shortname_offset;
        old_ino = sinfo.ino;
        res = fat_get_entry(old_dir, &old_offset, &old_bh, &old_de);
-       PRINTK(("vfat_rename 3\n"));
+       PRINTK3(("vfat_rename 3\n"));
        if (res < 0) goto rename_done;
 
        res = -ENOENT;
@@ -1678,15 +1710,15 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
 
        res = vfat_find(new_dir,&new_dentry->d_name,1,0,is_dir,&sinfo);
 
-       PRINTK(("vfat_rename 4\n"));
+       PRINTK3(("vfat_rename 4\n"));
        if (res > -1) {
                int new_is_dir;
 
-               PRINTK(("vfat_rename 5\n"));
+               PRINTK3(("vfat_rename 5\n"));
                /* Filename currently exists.  Need to delete it */
                new_offset = sinfo.shortname_offset;
                res = fat_get_entry(new_dir, &new_offset, &new_bh, &new_de);
-               PRINTK(("vfat_rename 6\n"));
+               PRINTK3(("vfat_rename 6\n"));
                if (res < 0) goto rename_done;
 
                if (!(new_inode = iget(new_dir->i_sb,res)))
@@ -1694,82 +1726,67 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
                new_is_dir = S_ISDIR(new_inode->i_mode);
                iput(new_inode);
                if (new_is_dir) {
-                       PRINTK(("vfat_rename 7\n"));
+                       PRINTK3(("vfat_rename 7\n"));
                        res = vfat_rmdirx(new_dir,new_dentry);
-                       PRINTK(("vfat_rename 8\n"));
+                       PRINTK3(("vfat_rename 8\n"));
                        if (res < 0) goto rename_done;
                } else {
                        /* Is this the same file, different case? */
                        if (new_inode != old_inode) {
-                               PRINTK(("vfat_rename 9\n"));
+                               PRINTK3(("vfat_rename 9\n"));
                                res = vfat_unlink(new_dir,new_dentry);
-                               PRINTK(("vfat_rename 10\n"));
+                               PRINTK3(("vfat_rename 10\n"));
                                if (res < 0) goto rename_done;
                        }
                }
        }
 
-       PRINTK(("vfat_rename 11\n"));
+       PRINTK3(("vfat_rename 11\n"));
        fat_lock_creation(); locked = 1;
        res = vfat_find(new_dir,&new_dentry->d_name,1,1,is_dir,&sinfo);
 
-       PRINTK(("vfat_rename 12\n"));
+       PRINTK3(("vfat_rename 12\n"));
        if (res < 0) goto rename_done;
 
        new_offset = sinfo.shortname_offset;
        new_ino = sinfo.ino;
-       res = fat_get_entry(new_dir, &new_offset, &new_bh, &new_de);
-       PRINTK(("vfat_rename 13\n"));
-       if (res < 0) goto rename_done;
-
-       new_de->attr = old_de->attr;
-       new_de->time = old_de->time;
-       new_de->date = old_de->date;
-       new_de->ctime_ms = old_de->ctime_ms;
-       new_de->cdate = old_de->cdate;
-       new_de->adate = old_de->adate;
-       new_de->start = old_de->start;
-       new_de->starthi = old_de->starthi;
-       new_de->size = old_de->size;
+       PRINTK3(("vfat_rename 13: new_ino=%d\n", new_ino));
 
        if (!(new_inode = iget(new_dir->i_sb,new_ino))) goto rename_done;
-       PRINTK(("vfat_rename 14\n"));
+       put_new_inode = 1;
 
-       /* At this point, we have the inodes of the old file and the
-        * new file.  We need to transfer all information from the old
-        * inode to the new inode and then delete the slots of the old
-        * entry
-        */
+       new_inode->i_mode   = old_inode->i_mode;
+       new_inode->i_size   = old_inode->i_size;
+       new_inode->i_blocks = old_inode->i_blocks;
+       new_inode->i_mtime  = old_inode->i_mtime;
+       new_inode->i_atime  = old_inode->i_atime;
+       new_inode->i_ctime  = old_inode->i_ctime;
+       MSDOS_I(new_inode)->i_ctime_ms = MSDOS_I(old_inode)->i_ctime_ms;
+
+       MSDOS_I(new_inode)->i_start = MSDOS_I(old_inode)->i_start;
+       MSDOS_I(new_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart;
+       MSDOS_I(new_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs;
+
+       mark_inode_dirty(new_inode);
 
-       vfat_read_inode(new_inode);
-       MSDOS_I(old_inode)->i_busy = 1;
-       MSDOS_I(old_inode)->i_linked = new_inode;
-       MSDOS_I(new_inode)->i_oldlink = old_inode;
-       fat_cache_inval_inode(old_inode);
-       PRINTK(("vfat_rename 15: old_slots=%d\n",old_slots));
-       mark_inode_dirty(old_inode);
        old_dir->i_version = ++event;
+       new_dir->i_version = ++event;
+
+       PRINTK3(("vfat_rename 14: old_slots=%d\n",old_slots));
 
        /* remove the old entry */
        for (i = old_slots; i > 0; --i) {
                res = fat_get_entry(old_dir, &old_longname_offset, &old_bh, &old_de);
                if (res < 0) {
-                       printk("vfat_unlinkx: problem 1\n");
+                       printk("vfat_rename: problem 1\n");
                        continue;
                }
                old_de->name[0] = DELETED_FLAG;
                old_de->attr = 0;
                fat_mark_buffer_dirty(sb, old_bh, 1);
        }
-       PRINTK(("vfat_rename 15b\n"));
+       PRINTK3(("vfat_rename 15b\n"));
 
-       fat_mark_buffer_dirty(sb, new_bh, 1);
-
-       /* XXX: There is some code in the original MSDOS rename that
-        * is not duplicated here and it might cause a problem in
-        * certain circumstances.
-        */
-       
        if (S_ISDIR(old_inode->i_mode)) {
                if ((res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
                    &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
@@ -1793,8 +1810,11 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
        }
 
        if (res > 0) res = 0;
+
        if (res == 0) {
+               drop_replace_inodes(old_dentry, new_inode);
                d_move(old_dentry, new_dentry);
+               put_new_inode = 0;
        }
 
 rename_done:
@@ -1804,6 +1824,8 @@ rename_done:
                fat_brelse(sb, old_bh);
        if (new_bh)
                fat_brelse(sb, new_bh);
+       if (put_new_inode)
+               iput(new_inode);
        return res;
 }
 
index 39a8206ef4454c39f7ed426d4008c731de74669d..1d45fded1e8ae7154a611418dcdbd4d0b4dd19fe 100644 (file)
@@ -15,7 +15,6 @@ extern unsigned int local_irq_count[NR_CPUS];
 #define hardirq_exit(cpu)      (local_irq_count[cpu]--)
 
 #define synchronize_irq()      do { } while (0)
-#define synchronize_one_irq(x) do { } while (0)
 
 #else
 
@@ -30,7 +29,7 @@ static inline void release_irqlock(int cpu)
        /* if we didn't own the irq lock, just ignore.. */
        if (global_irq_holder == (unsigned char) cpu) {
                global_irq_holder = NO_PROC_ID;
-               global_irq_lock = 0;
+               clear_bit(0,&global_irq_lock);
        }
 }
 
@@ -70,7 +69,6 @@ static inline void hardirq_endlock(int cpu)
 }
 
 extern void synchronize_irq(void);
-extern void synchronize_one_irq(unsigned int irq);
 
 #endif /* __SMP__ */
 
index 8946d577e6a480bce0721b99105d72c9c83e0c1e..a28f6bae8d720cca4639154fe14e98746917a173 100644 (file)
@@ -4,6 +4,9 @@
 #include <asm/atomic.h>
 #include <asm/hardirq.h>
 
+extern unsigned int local_bh_count[NR_CPUS];
+#define in_bh()        (local_bh_count[smp_processor_id()] != 0)
+
 #define get_active_bhs()       (bh_mask & bh_active)
 #define clear_active_bhs(x)    atomic_clear_mask((x),&bh_active)
 
@@ -25,23 +28,6 @@ extern inline void mark_bh(int nr)
        set_bit(nr, &bh_active);
 }
 
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void disable_bh(int nr)
-{
-       bh_mask &= ~(1 << nr);
-       bh_mask_count[nr]++;
-       synchronize_irq();
-}
-
-extern inline void enable_bh(int nr)
-{
-       if (!--bh_mask_count[nr])
-               bh_mask |= 1 << nr;
-}
-
 #ifdef __SMP__
 
 /*
@@ -49,52 +35,83 @@ extern inline void enable_bh(int nr)
  * is entirely private to an implementation, it should not be
  * referenced at all outside of this file.
  */
-extern atomic_t __intel_bh_counter;
+extern atomic_t global_bh_lock;
+extern atomic_t global_bh_count;
 
-extern inline void start_bh_atomic(void)
+extern void synchronize_bh(void);
+
+static inline void start_bh_atomic(void)
 {
-       atomic_inc(&__intel_bh_counter);
-       synchronize_irq();
+       atomic_inc(&global_bh_lock);
+       synchronize_bh();
 }
 
-extern inline void end_bh_atomic(void)
+static inline void end_bh_atomic(void)
 {
-       atomic_dec(&__intel_bh_counter);
+       atomic_dec(&global_bh_lock);
 }
 
 /* These are for the irq's testing the lock */
-static inline int softirq_trylock(void)
+static inline int softirq_trylock(int cpu)
 {
-       atomic_inc(&__intel_bh_counter);
-       if (atomic_read(&__intel_bh_counter) != 1) {
-               atomic_dec(&__intel_bh_counter);
+       unsigned long flags;
+
+       __save_flags(flags);
+       __cli();
+       atomic_inc(&global_bh_count);
+       if (atomic_read(&global_bh_count) != 1 || atomic_read(&global_bh_lock) != 0) {
+               atomic_dec(&global_bh_count);
+               __restore_flags(flags);
                return 0;
        }
+       ++local_bh_count[cpu];
        return 1;
 }
 
-#define softirq_endlock()      atomic_dec(&__intel_bh_counter)
+static inline void softirq_endlock(int cpu)
+{
+       __cli();
+       atomic_dec(&global_bh_count);
+       local_bh_count[cpu]--;
+       __sti();
+}
 
 #else
 
-extern int __intel_bh_counter;
-
 extern inline void start_bh_atomic(void)
 {
-       __intel_bh_counter++;
+       local_bh_count[smp_processor_id()]++;
        barrier();
 }
 
 extern inline void end_bh_atomic(void)
 {
        barrier();
-       __intel_bh_counter--;
+       local_bh_count[smp_processor_id()]--;
 }
 
 /* These are for the irq's testing the lock */
-#define softirq_trylock()      (__intel_bh_counter ? 0 : (__intel_bh_counter=1))
-#define softirq_endlock()      (__intel_bh_counter = 0)
+#define softirq_trylock()      (in_bh ? 0 : (local_bh_count[smp_processor_id()]=1))
+#define softirq_endlock()      (local_bh_count[smp_processor_id()] = 0)
+#define synchronize_bh()       do { } while (0)
 
 #endif /* SMP */
 
+/*
+ * These use a mask count to correctly handle
+ * nested disable/enable calls
+ */
+extern inline void disable_bh(int nr)
+{
+       bh_mask &= ~(1 << nr);
+       bh_mask_count[nr]++;
+       synchronize_bh();
+}
+
+extern inline void enable_bh(int nr)
+{
+       if (!--bh_mask_count[nr])
+               bh_mask |= 1 << nr;
+}
+
 #endif /* __ASM_SOFTIRQ_H */
index 349329515ceb6c9f9b2fa9b9afd7c3b806017888..ef08ac5101838d40f3f16ef1962c370c06cba989 100644 (file)
@@ -263,7 +263,7 @@ do {                                                                        \
                "       .long 0b,3b\n"                                  \
                "       .long 1b,2b\n"                                  \
                ".previous"                                             \
-               : "=c"(size)                                            \
+               : "=&c"(size)                                           \
                : "r"(size & 3), "0"(size / 4), "D"(to), "S"(from)      \
                : "di", "si", "memory")
 
index 1a45b75c39b6c6e39f15e99a2039d6522a8d8f7e..2dc02df02ad368466fc0e040df50592e8cbc3dba 100644 (file)
 #define __NR_rt_sigsuspend     179
 #define __NR_pread             180
 #define __NR_pwrite            181
+#define __NR_lchown            182
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
index 5648eae7f9a57bd3fbac2f1da4c16d679d291beb..d04de37f11f0102a31fe63e6cbb6fe158c36a80e 100644 (file)
@@ -98,6 +98,7 @@
 #define TIOCTTYGSTRUCT 0x5487  /* For debugging only */
 #define TIOCSBRK       0x5427  /* BSD compatibility */
 #define TIOCCBRK       0x5428  /* BSD compatibility */
+#define TIOCGSID       0x5429  /* Return the session ID of FD */
 
 #define TIOCSERCONFIG  0x5488
 #define TIOCSERGWILD   0x5489
index 8893b170a88d4b2e5182b9209bce064a804b6a7b..f5d58f4bb99115fe4c78a0bcd5587ef0c7c91784 100644 (file)
@@ -39,6 +39,9 @@
 #ifdef CONFIG_CDROM
 extern int cdrom_init(void);
 #endif CONFIG_CDROM 
+#ifdef CONFIG_ISP16_CDI
+extern int isp16_init(void);
+#endif CONFIG_ISP16_CDI
 #ifdef CONFIG_CDU31A
 extern int cdu31a_init(void);
 #endif CONFIG_CDU31A
index 530930e539d16e8d7e289bd75770e929eac17a8f..674999c58e72d2f5ea48ff0b91f784174c4ad8e8 100644 (file)
@@ -28,16 +28,9 @@ struct msdos_inode_info {
        int i_start;    /* first cluster or 0 */
        int i_logstart; /* logical first cluster */
        int i_attrs;    /* unused attribute bits */
+       int i_ctime_ms; /* unused change time in milliseconds */
        int i_busy;     /* file is either deleted but still open, or
                           inconsistent (mkdir) */
-       struct inode *i_depend; /* pointer to inode that depends on the
-                                  current inode */
-       struct inode *i_old;    /* pointer to the old inode this inode
-                                  depends on */
-       struct inode *i_linked; /* pointer to inode linked to the current one,
-                                  happens when an open file is moved */
-       struct inode *i_oldlink;/* pointer to open inode that references
-                                  the same file */
        int i_binary;   /* file contains non-text data */
 };
 
index 10be0abc61d5e95599349a166f3d390ebdada643..3e341077639a67d79e7a9ba6e0ff184265000dc7 100644 (file)
@@ -116,12 +116,16 @@ fh_lock(struct svc_fh *fhp)
        dfprintk(FILEOP, "nfsd: fh_lock(%x/%ld) locked = %d\n",
                        SVCFH_DEV(fhp), SVCFH_INO(fhp), fhp->fh_locked);
         */
-       if (!fhp->fh_locked) {
-               down(&inode->i_sem);
-               if (!fhp->fh_pre_mtime)
-                       fhp->fh_pre_mtime = inode->i_mtime;
-               fhp->fh_locked = 1;
+       if (fhp->fh_locked) {
+               printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
+                       fhp->fh_dentry->d_parent->d_name.name,
+                       fhp->fh_dentry->d_name.name);
+               return;
        }
+       down(&inode->i_sem);
+       if (!fhp->fh_pre_mtime)
+               fhp->fh_pre_mtime = inode->i_mtime;
+       fhp->fh_locked = 1;
 }
 
 /*
@@ -130,9 +134,8 @@ fh_lock(struct svc_fh *fhp)
 static inline void
 fh_unlock(struct svc_fh *fhp)
 {
-       struct inode    *inode = fhp->fh_dentry->d_inode;
-
        if (fhp->fh_locked) {
+               struct inode *inode = fhp->fh_dentry->d_inode;
                if (!fhp->fh_post_version)
                        fhp->fh_post_version = inode->i_version;
                fhp->fh_locked = 0;
index 0dd75b8863387a88d17b4d0fec5a25441e688de6..ff193cd24f79595660b2cfeb743769f54ce306b2 100644 (file)
@@ -174,6 +174,11 @@ extern inline void sigdelsetmask(sigset_t *set, unsigned long mask)
        set->sig[0] &= ~mask;
 }
 
+extern inline int sigtestsetmask(sigset_t *set, unsigned long mask)
+{
+       return (set->sig[0] & mask) != 0;
+}
+
 extern inline void siginitset(sigset_t *set, unsigned long mask)
 {
        set->sig[0] = mask;
index a9e697da79267c0147300d342d62696bf9aeceef..7f3c97b3664917835504ac99f6a9b5be9aec4356 100644 (file)
@@ -303,6 +303,7 @@ extern int tty_init(void);
 extern int pcxe_init(void);
 extern int pc_init(void);
 extern int vcs_init(void);
+extern int rp_init(void);
 extern int cy_init(void);
 extern int stl_init(void);
 extern int stli_init(void);
@@ -352,10 +353,6 @@ extern long serial_console_init(long kmem_start, long kmem_end);
 
 extern int pcxe_open(struct tty_struct *tty, struct file *filp);
 
-/* epca.c */
-
-extern int pc_open(struct tty_struct *tty, struct file *filp);
-
 /* console.c */
 
 extern void update_screen(int new_console);
index f6e398b832312f3ed2940cee800cdf13f386a48a..064ee9d064fd1bbc5fcf5bc9de31f8045b602030 100644 (file)
@@ -173,4 +173,14 @@ struct video_key
 #define VID_HARDWARE_PMS       3
 #define VID_HARDWARE_QCAM_C    4
 
+/*
+ *     Initialiser list
+ */
+struct video_init
+{
+       char *name;
+       int (*init)(struct video_init *);
+};
+
 #endif
index 27f99ff925b7e0456590b55cfdd97b5ed8f67513..801f3c002bf0d8fbc7bf794fb3b032afa36e6932 100644 (file)
@@ -268,8 +268,8 @@ int acct_process(long exitcode)
 
 
        /*
-        * Fill the accounting struct with the needed info as recorded by the different
-        * kernel functions.
+        * Fill the accounting struct with the needed info as recorded
+        * by the different kernel functions.
         */
        memset((caddr_t)&ac, 0, sizeof(struct acct));
 
@@ -304,7 +304,7 @@ int acct_process(long exitcode)
        }
        vsize = vsize / 1024;
        ac.ac_mem = encode_comp_t(vsize);
-       ac.ac_io = encode_comp_t(current->io_usage);
+       ac.ac_io = encode_comp_t(current->io_usage);    /* %% */
        ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
        ac.ac_minflt = encode_comp_t(current->min_flt);
        ac.ac_majflt = encode_comp_t(current->maj_flt);
index 8c16a6c763b85a2e1e0bfcde749545921197a86f..de7daeb3af6ee755ff226a3298d56b595b70dcc8 100644 (file)
@@ -229,9 +229,7 @@ asmlinkage int printk(const char *fmt, ...)
        static signed char msg_level = -1;
        long flags;
 
-       __save_flags(flags);
-       __cli();
-       spin_lock(&console_lock);
+       spin_lock_irqsave(&console_lock, flags);
        va_start(args, fmt);
        i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
        buf_end = buf + 3 + i;
@@ -279,9 +277,8 @@ asmlinkage int printk(const char *fmt, ...)
                if (line_feed)
                        msg_level = -1;
        }
-       spin_unlock(&console_lock);
-       __restore_flags(flags);
-/*     wake_up_interruptible(&log_wait);*/
+       spin_unlock_irqrestore(&console_lock, flags);
+       wake_up_interruptible(&log_wait);
        return i;
 }
 
index de398bcff1dba6abee110d37e7639a6448792f70..4bc5ee4b6f5533546506c4738565b377f4d29759 100644 (file)
@@ -62,14 +62,14 @@ static inline void run_bottom_halves(void)
 
 asmlinkage void do_bottom_half(void)
 {
-       if (softirq_trylock()) {
-               int cpu = smp_processor_id();
+       int cpu = smp_processor_id();
 
+       if (softirq_trylock(cpu)) {
                if (hardirq_trylock(cpu)) {
                        __sti();
                        run_bottom_halves();
                        hardirq_endlock(cpu);
                }
-               softirq_endlock();
+               softirq_endlock(cpu);
        }
 }
index 657bb04892fbb4eb5e7725afccf14f685916d51c..4dd37ab52a61398835f16befc9036bbfdcaedee0 100644 (file)
@@ -40,6 +40,9 @@
 #
 # 221297 Michael Chastain (mec@shout.net) - make define_bool actually
 # define its arguments so that later tests on them work right.
+#
+# 160198 Michael Chastain (mec@shout.net) - fix bug with 'c' command
+# (complement existing value) when used on virgin uninitialized variables.
 #----------------------------------------------------------------------------
 
 
@@ -349,6 +352,7 @@ function l_bool () {
                        case $x in
                        y) eval $1=n ;;
                        n) eval $1=y ;;
+                       *) eval $1=y ;;
                        esac ;;
                *)      eval $1=n ;;
                esac
@@ -392,6 +396,7 @@ As a result, this feature will be built as a module." 4 70
                        case $x in
                        m) eval $1=n ;;
                        n) eval $1=m ;;
+                       *) eval $1=m ;;
                        esac ;;
                *)      eval $1=n ;;
                esac
@@ -416,6 +421,7 @@ function l_tristate () {
                   y) eval $1=n ;;
                   n) eval $1=m ;;
                   m) eval $1=y ;;
+                  *) eval $1=y ;;
                   esac ;;
                *) eval $1=n ;;
                esac